@hology/core 0.0.35 → 0.0.38
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/effects/vfx/vfx-param.d.ts +8 -10
- package/dist/effects/vfx/vfx-param.js +1 -1
- package/dist/gameplay/actors/camera/third-party-camera-component.js +1 -1
- package/dist/gameplay/index.d.ts +1 -0
- package/dist/gameplay/index.js +1 -1
- package/dist/gameplay/initiate.d.ts +3 -0
- package/dist/gameplay/initiate.js +1 -1
- package/dist/gameplay/services/asset-loader.d.ts +1 -1
- package/dist/gameplay/services/asset-loader.js +1 -1
- package/dist/gameplay/services/physics/physics-system.d.ts +1 -3
- package/dist/rendering.js +1 -1
- package/dist/scene/bootstrap.js +1 -1
- package/dist/scene/materializer.js +1 -1
- package/dist/scene/scene-data-service.d.ts +4 -1
- package/dist/scene/scene-data-service.js +1 -1
- package/package.json +1 -1
- package/tsconfig.tsbuildinfo +1 -1
@@ -1,13 +1,11 @@
|
|
1
|
-
import { Object3D } from "three";
|
2
1
|
import { VfxActor } from './vfx-actor.js';
|
2
|
+
import { ActorProvider } from "../../scene/materializer.js";
|
3
|
+
import { VfxAsset } from "../../scene/model.js";
|
4
|
+
import { Object3D } from 'three';
|
5
|
+
import { BaseActor } from 'gameplay/index.js';
|
3
6
|
export declare class VisualEffect {
|
4
|
-
private
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
pause(): void;
|
9
|
-
restart(): void;
|
10
|
-
set timescale(value: number);
|
11
|
-
get timescale(): number;
|
12
|
-
get object(): Object3D;
|
7
|
+
private actorProvider;
|
8
|
+
private asset;
|
9
|
+
constructor(actorProvider: ActorProvider, asset: VfxAsset);
|
10
|
+
spawn(parent: Object3D | BaseActor): Promise<VfxActor>;
|
13
11
|
}
|
@@ -1,4 +1,4 @@
|
|
1
|
-
export class VisualEffect{constructor(t){this.
|
1
|
+
import{VfxActor as t}from"./vfx-actor.js";import{BaseActor as s}from"gameplay/index.js";export class VisualEffect{constructor(t,s){this.actorProvider=t,this.asset=s}async spawn(a){const o=await this.actorProvider.create(t);return a instanceof s?a.object.add(o.object):a.add(o.object),await o.fromAsset(this.asset),o}}
|
2
2
|
/*
|
3
3
|
* Copyright (©) 2023. All rights reserved.
|
4
4
|
* See the LICENSE.md file for details.
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import{__decorate as t,__metadata as
|
1
|
+
import{__decorate as t,__metadata as s}from"tslib";import{ActorComponent as e,Component as i,attach as o}from"../component.js";import{CameraComponent as n}from"./camera-component.js";import{Vector3 as a,MathUtils as h}from"three";import{ViewController as c}from"../../services/render.js";import{DecimalInput as r,RestrictedRotationInput as m}from"../../input/index.js";import{PhysicsSystem as d,RayTestResult as l}from"../../services/physics/physics-system.js";let u=class extends e{constructor(t,s){super(),this.viewController=t,this.physicsSystem=s,this.camera=o(n),this.distance=9,this.minDistance=1.5,this.maxDistance=this.distance,this.height=3,this.offsetX=-1,this.offsetZ=1.5,this.autoActivate=!0,this.bounceBackSpeed=5,this.collisionCheckRadius=.5,this.restrictedDistance=Math.max(this.distance,this.maxDistance),this.rotationInput=new m(-Math.PI/4,Math.PI/2-.7),this.zoomInput=new r(1,0,1),this.offset=new a,this.lookAtOffset=new a(this.offsetX,0,this.offsetZ),this.isMouseLocked=!1,this.canvas=null,this.pointerLockInactivatedAt=null,this.onMouseDown=t=>{this.isMouseLocked||this.hideCursor()},this.onKeyDown=t=>{"Escape"===t.key&&this.showCursor()},this.onPointerLockChange=()=>{null!=document.pointerLockElement||null!=document.mozPointerLockElement||this.showCursor()}}async onInit(){this.restrictedDistance=Math.max(this.distance,this.maxDistance),this.lookAtOffset.set(this.offsetX,0,this.offsetZ),this.autoActivate&&this.viewController.setCamera(this.camera.instance);const t=this.element;null!=document.body.requestPointerLock&&(t.addEventListener("mousedown",this.onMouseDown),t.addEventListener("keydown",this.onKeyDown),document.addEventListener("pointerlockchange",this.onPointerLockChange,!1),this.disposed.subscribe((()=>{t.removeEventListener("mousedown",this.onMouseDown),t.removeEventListener("keydown",this.onKeyDown),document.removeEventListener("pointerlockchange",this.onPointerLockChange,!1)})))}onLateUpdate(t){this.setFromRotation(t)}get element(){return this.viewController.htmlElement}hideCursor(){"ontouchstart"in window||navigator.maxTouchPoints>0||navigator.msMaxTouchPoints>0||null!=this.pointerLockInactivatedAt&&performance.now()-this.pointerLockInactivatedAt<1600||(this.element.style.cursor="none",null==this.canvas&&(this.canvas=this.element.getElementsByTagName("canvas")[0]),this.canvas&&(this.canvas.requestPointerLock(),this.isMouseLocked=!0))}showCursor(){this.pointerLockInactivatedAt=performance.now(),this.element.style.cursor="default",window.document.exitPointerLock(),this.isMouseLocked=!1}setFromRotation(t){this.checkForCollision(t);const s=h.clamp(Math.min(this.restrictedDistance,this.distance),Math.min(this.minDistance,this.restrictedDistance),Math.max(this.distance*this.zoomInput.value,this.minDistance)),e=Math.cos(this.rotationInput.rotation.x)*s;this.offset.x=Math.sin(this.rotationInput.rotation.y)*e,this.offset.y=Math.sin(this.rotationInput.rotation.x)*s+2,this.offset.z=Math.cos(this.rotationInput.rotation.y)*-e,this.offset.add(this.lookAtOffset),this.updateCameraPosition()}checkForCollision(t){const s=this.getLookAtPosition(),e=f;let i=!1,o=this.distance;const n=new l,a=this.camera.instance.getWorldPosition(w);for(let t=-1;t<=1;t++){const h=k.subVectors(a,s);e.copy(a).add(h.multiplyScalar(1.2)),e.x+=t*this.collisionCheckRadius,this.physicsSystem.rayTest(s,e,n,{debugLifetime:0,excludeActor:this.actor}),n.hasHit&&n.distance<this.distance&&(o=Math.min(n.distance,o),i||=n.hasHit)}i||(this.restrictedDistance=h.lerp(this.restrictedDistance,this.distance,h.clamp(this.bounceBackSpeed*t,0,1)))}getLookAtPosition(){const t=p;return t.set(0,0,0),t.y=this.height,t.add(this.lookAtOffset),t.applyMatrix4(this.actor.object.matrixWorld),t}updateCameraPosition(){this.camera.instance.position.copy(this.offset);const t=this.getLookAtPosition();this.camera.instance.lookAt(t)}};u=t([i(),s("design:paramtypes",[c,d])],u);export{u as ThirdPartyCameraComponent};const p=new a,f=new a,k=(new a,new a),w=new a;
|
2
2
|
/*
|
3
3
|
* Copyright (©) 2023. All rights reserved.
|
4
4
|
* See the LICENSE.md file for details.
|
package/dist/gameplay/index.d.ts
CHANGED
package/dist/gameplay/index.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import"reflect-metadata";export{Container as DIContainer}from"typedi";export*from"./initiate.js";export*from"./inject.js";export{Service,Inject}from"typedi";export{ActorFactory}from"./actors/factory.js";export{Actor,BaseActor}from"./actors/actor.js";export{Component,ActorComponent,attach,Attach}from"./actors/component.js";export*from"./services/world.js";export*from"./services/render.js";export*from"./services/physics/physics-system.js";export*from"./animation/anim-sm.js";export*from"./animation/root-motion.js";export*from"./services/asset-loader.js";export*from"./services/pointer-events.js";export{VisualEffect}from"../effects/vfx/vfx-param.js";
|
1
|
+
import"reflect-metadata";export{Container as DIContainer}from"typedi";export*from"./initiate.js";export*from"./inject.js";export{Service,Inject}from"typedi";export{ActorFactory}from"./actors/factory.js";export{Actor,BaseActor}from"./actors/actor.js";export{Component,ActorComponent,attach,Attach}from"./actors/component.js";export*from"./services/world.js";export*from"./services/render.js";export*from"./services/physics/physics-system.js";export*from"./animation/anim-sm.js";export*from"./animation/root-motion.js";export*from"./services/asset-loader.js";export*from"./services/pointer-events.js";export{VisualEffect}from"../effects/vfx/vfx-param.js";export*from"../shader/parameter.js";
|
2
2
|
/*
|
3
3
|
* Copyright (©) 2023. All rights reserved.
|
4
4
|
* See the LICENSE.md file for details.
|
@@ -16,6 +16,9 @@ export type InitiateGameConfig = {
|
|
16
16
|
xr?: {
|
17
17
|
enabled: boolean;
|
18
18
|
};
|
19
|
+
rendering?: Partial<{
|
20
|
+
resolutionScale: number;
|
21
|
+
}>;
|
19
22
|
};
|
20
23
|
export declare function initiateGame<T_Game>(gameClass: GameClass<T_Game>, config: InitiateGameConfig): HologyRuntime<T_Game>;
|
21
24
|
export declare abstract class GameInstance {
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import
|
1
|
+
import e from"typedi";import{loadScene as t}from"../scene/bootstrap.js";import{ActorFactory as n}from"./actors/factory.js";import{World as s}from"./services/world.js";import{ViewController as o}from"./services/render.js";import{RenderingView as r}from"../rendering.js";import{PhysicsSystem as i}from"./services/physics/physics-system.js";import{MeshComponent as a}from"./actors/builtin/components/mesh-component.js";import{activeContainerInstance as c}from"./actors/internal/container-map.js";import{InputService as m}from"./input/index.js";import{RuntimeBackendService as l}from"../scene/runtime-backend-service.js";import{RuntimeAssetsService as p}from"../scene/runtime-asset-service.js";import{AssetResourceLoader as d}from"../scene/asset-resource-loader.js";import{AssetLoader as h}from"./services/asset-loader.js";import{polyfillClient as u}from"./polyfill.js";import{Subject as f}from"rxjs";import{PointerEvents as g}from"./services/pointer-events.js";export function initiateGame(m,f){if(u(),0!=f.element.childNodes.length)return console.error("Can not initialize the game with a non-empty html element"),null;e.has(o);const w=e.of("default"),j=new HologyRuntime(w),v=new n(w,{inEditor:!1});var S;e.set(n,v),S=f.element,Object.assign(S.style,{position:"absolute",top:"0",left:"0",width:"100%",height:"100%"});const y=new r(f.element,{enableXR:!0===f.xr?.enabled});y.renderer.shadowMap.autoUpdate=!0,null!=f?.rendering?.resolutionScale&&(y.resolutionScale=f.rendering.resolutionScale),e.set(r,y);const I=new o(y);e.set(o,I);const b=new s(e.get(n));e.set(s,b);const x=new l(f.dataDir),D=new p(x),G=new d;G.setDataDir(f.dataDir);const H=Object.entries(f.shaders).map((([e,t])=>({name:e,type:t}))),R=new h(G,D,H);return e.set(h,R),(async()=>{const n=e.get(i);if(await n.start(),j.isShutdown)return;const{scene:s,actors:o}=await t(y,f.sceneName,f.dataDir,f.shaders,f.actors,v,x,D,G);if(b.scene=s,j.isShutdown)return void y.stop();e.import([a]);for(const e of o)b.addActor(e);n.addFromScene(s),y.loop((e=>{})),j.status=5,c.value=w,w.remove(m),w.set({id:m,type:m});const r=w.get(m);c.value=null,j.gameInstance=r,w.get(g).start(),r instanceof GameInstance&&r.onStart(),j._resolver(!0)})(),j}export class GameInstance{onStart(){}onShutdown(){}}export function createHologyScene(){}export class HologyRuntime{constructor(e){this.containerInstance=e,this.status=0,this.isShutdown=!1,this.shutdownStarted=new f,this.ready=new Promise((e=>{this._resolver=e}))}getWorld(){return this.containerInstance.get(s)}getService(e){return this.containerInstance.get(e)}shutdown(){this.isShutdown=!0,this.shutdownStarted.next(),this.gameInstance instanceof GameInstance&&this.gameInstance.onShutdown(),this.containerInstance.get(m).stop();const e=this.containerInstance.get(r);e?.stop();for(const e of this.getWorld().actors)this.getWorld().removeActor(e);this.containerInstance.get(i).stop(),this.containerInstance.get(g).stop(),this.containerInstance.reset()}}
|
2
2
|
/*
|
3
3
|
* Copyright (©) 2023. All rights reserved.
|
4
4
|
* See the LICENSE.md file for details.
|
@@ -35,7 +35,7 @@ export declare class AssetLoader {
|
|
35
35
|
/**
|
36
36
|
* @param filePath A path relative to your website's base url. Always use backslash for directory separetors, even in Windows.
|
37
37
|
*/
|
38
|
-
|
38
|
+
getGltfAtPath(filePath: string): Promise<GLTF>;
|
39
39
|
getModelByAssetName(name: string): Promise<LoadedMesh>;
|
40
40
|
getModelByAssetId(id: AssetId): Promise<LoadedMesh>;
|
41
41
|
getTextureByAssetId(id: AssetId): Promise<THREE.Texture>;
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import{__decorate as e,__metadata as t}from"tslib";import{AssetResourceLoader as s}from"../../scene/asset-resource-loader.js";import{FBXLoader as r,GLTFLoader as a,MTLLoader as o,OBJLoader as i,TGALoader as n}from"three-stdlib";import{AudioLoader as d,LoadingManager as h,TextureLoader as l}from"three";import{pathJoin as u}from"../../utils/files.js";import{Service as c}from"typedi";import{materialFromAsset as g}from"../../scene/materializer.js";let w=class{constructor(e,t,s){this.assetResourceLoader=e,this.assetService=t,this.shaders=s,this.baseUrl="",this.urlSuffix="",this.loadingManager=new h,this.glbLoader=new a(this.loadingManager),this.fbxLoader=new r(this.loadingManager),this.objLoader=new i(this.loadingManager),this.mtlLoader=new o(this.loadingManager),this.tgaLoader=new n(this.loadingManager),this.textureLoader=new l(this.loadingManager),this.audioLoader=new d(this.loadingManager)}resolvePath(e){return u(this.baseUrl,e)+this.urlSuffix}getAudioAtPath(e){const t=this.resolvePath(e);return this.audioLoader.loadAsync(t)}async getAudioByAssetId(e){const t=await this.assetService.getAsset(e);if(null==t)throw new Error(`No
|
1
|
+
import{__decorate as e,__metadata as t}from"tslib";import{AssetResourceLoader as s}from"../../scene/asset-resource-loader.js";import{FBXLoader as r,GLTFLoader as a,MTLLoader as o,OBJLoader as i,TGALoader as n}from"three-stdlib";import{AudioLoader as d,LoadingManager as h,TextureLoader as l}from"three";import{pathJoin as u}from"../../utils/files.js";import{Service as c}from"typedi";import{materialFromAsset as g}from"../../scene/materializer.js";let w=class{constructor(e,t,s){this.assetResourceLoader=e,this.assetService=t,this.shaders=s,this.baseUrl="",this.urlSuffix="",this.loadingManager=new h,this.glbLoader=new a(this.loadingManager),this.fbxLoader=new r(this.loadingManager),this.objLoader=new i(this.loadingManager),this.mtlLoader=new o(this.loadingManager),this.tgaLoader=new n(this.loadingManager),this.textureLoader=new l(this.loadingManager),this.audioLoader=new d(this.loadingManager)}resolvePath(e){return u(this.baseUrl,e)+this.urlSuffix}getAudioAtPath(e){const t=this.resolvePath(e);return this.audioLoader.loadAsync(t)}async getAudioByAssetId(e){const t=await this.assetService.getAsset(e);if(null==t)throw new Error(`No audio could be found with asset id ${e}`);return this.assetResourceLoader.getAudio(t)}async getAudioByAssetName(e){const t=await this.assetService.getAsset(e);if(null==t)throw new Error(`No audio could be found with asset name ${e}`);return this.assetResourceLoader.getAudio(t)}async getModelAtPath(e){const t=this.resolvePath(e);switch(e.split(".").pop().toLowerCase()){case"glb":case"gltf":return(await this.glbLoader.loadAsync(t)).scene;case"fbx":return this.fbxLoader.loadAsync(t);case"obj":return this.objLoader.loadAsync(t);default:throw new Error(`File suffix is not supperted in file ${e}`)}}async getGltfAtPath(e){const t=this.resolvePath(e);return this.glbLoader.loadAsync(t)}async getModelByAssetName(e){const t=(await this.assetService.getAssets()).find((t=>t.name===e));if(null==t)throw new Error(`No model could be found with asset name ${e}`);return this.assetResourceLoader.getMesh(t)}async getModelByAssetId(e){const t=await this.assetService.getAsset(e);if(null==t)throw new Error(`No model could be found with asset id ${e}`);return this.assetResourceLoader.getMesh(t)}async getTextureByAssetId(e){const t=await this.assetService.getAsset(e);if(null==t)throw new Error(`No texture could be found with asset id ${e}`);return this.assetResourceLoader.getTexture(t)}async getMaterialByAssetId(e){const t=await this.assetService.getAsset(e);if(null==t)throw new Error(`No material could be found with asset id ${e}`);return g(t,null,this.assetService,this.assetResourceLoader,this.shaders,!1)}async getAsset(e){return this.assetService.getAsset(e)}};w=e([c(),t("design:paramtypes",[s,Object,Array])],w);export{w as AssetLoader};
|
2
2
|
/*
|
3
3
|
* Copyright (©) 2023. All rights reserved.
|
4
4
|
* See the LICENSE.md file for details.
|
@@ -1,5 +1,4 @@
|
|
1
1
|
import * as RAPIER from "@dimforge/rapier3d-compat";
|
2
|
-
import { RayColliderIntersection } from "@dimforge/rapier3d-compat";
|
3
2
|
import { Observable, Subject } from "rxjs";
|
4
3
|
import * as THREE from "three";
|
5
4
|
import { ColorRepresentation, Object3D, Vector3 } from "three";
|
@@ -9,8 +8,7 @@ import { BaseActor } from '../../actors/actor.js';
|
|
9
8
|
import { ViewController } from '../render.js';
|
10
9
|
import { World } from '../world.js';
|
11
10
|
export declare class RayTestResult {
|
12
|
-
|
13
|
-
actor: BaseActor;
|
11
|
+
actor?: BaseActor;
|
14
12
|
hasHit: boolean;
|
15
13
|
distance: number;
|
16
14
|
hitPoint: Vector3;
|
package/dist/rendering.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import*as e from"three";import{Mesh as t,Matrix4 as i,ShaderMaterial as s,Color as r,PerspectiveCamera as n,ShaderChunk as a}from"three";import{EffectComposer as o,UnrealBloomPass as h,VRButton as l}from"three-stdlib";import{RenderPass as d}from"three-stdlib";import{ShaderPass as c}from"three-stdlib";import{FXAAShader as m}from"three-stdlib";import{CSM as u}from"three-stdlib";import{CSMUtil as p}from"./csm.js";import{GammaCorrectionShader as g}from"three-stdlib";import{Reflector as v}from"three-stdlib";import{depthUniformName as f,resolutionUniformName as w,supportsDepthTextureExtension as b,nearUniformName as x,farUniformName as C}from"./shader-nodes/depth.js";import{elapsedTimeUniformName as R}from"./shader-nodes/time.js";import{OutlinePass as S}from"./utils/three/outline-pass.js";import T from"./utils/three/stats.js";import{findFirstVisibleObject as y}from"./utils/three/traverse.js";import{lambertVertexShaderOverride as P}from"./rendering/shader-override.js";import{DepthPass as M}from"./utils/three/depth-pass.js";(new e.Layers).set(9);const W=new e.MeshBasicMaterial({color:"black"}),L=new e.MeshDepthMaterial;L.depthPacking=e.RGBADepthPacking,L.blending=e.NoBlending;a.lights_pars_begin;a.lights_lambert_vertex=P;export class RenderingView{setPaused(e){this.paused=e}resizeRender(){this.previousClientWith===this.container.clientWidth&&this.previousClientHeight===this.container.clientHeight||(this.camera instanceof n&&(this.camera.aspect=this.container.clientWidth/this.container.clientHeight,this.camera.updateProjectionMatrix()),this.renderer.setPixelRatio(window.devicePixelRatio*this.resolutionScale),this.renderer.setSize(this.container.clientWidth,this.container.clientHeight),this.composer.setSize(this.container.clientWidth*this.resolutionScale,this.container.clientHeight*this.resolutionScale),this.previousClientWith=this.container.clientWidth,this.previousClientHeight=this.container.clientHeight)}constructor(t,i={}){this.container=t,this.options=i,this.windowVisible=!0,this.running=!0,this.paused=!1,this.fpsCap=null,this.resolutionScale=1,this.onResize=()=>{this.resizeRender(),this.paused||this.render()},this.onVisiblityChane=()=>{this.windowVisible=!document.hidden},this.isDepthTextureExtensionSupported=!1,this.onLoopCallbacks=[],this.stats=T(),this._showStats=!1,this.insetHeight=200,this.insetWidth=this.insetHeight*(16/9),this.insetOffsetY=250,this.insetMargin=10,this.maxInsetCameras=4,this.overlayCameras=new Set,this.prevClearColor=new r,this.bloomStoredMaterials={},window.renderer=this.renderer=new e.WebGLRenderer({antialias:!0,powerPreference:"high-performance"}),this.scene=new e.Scene,this.renderer.setPixelRatio(window.devicePixelRatio*this.resolutionScale),this.renderer.setSize(t.clientWidth,t.clientHeight),this.renderer.xr.enabled=this.options.enableXR??!1,!0===this.options.enableXR&&document.body.appendChild(l.createButton(this.renderer)),this.composer=new o(this.renderer);var s=t.clientWidth/t.clientHeight;const n=new e.PerspectiveCamera(45,s,.5,500);n.layers.enable(19),this.setCamera(n),this.renderer.shadowMap.enabled=!0,this.renderer.shadowMap.type=e.PCFSoftShadowMap,this.renderer.shadowMap.autoUpdate=!1,this.renderer.outputEncoding=e.sRGBEncoding,this.renderer.physicallyCorrectLights=!1,this.renderer.gammaFactor=1.4,p.renderingView=this,p.patchThreeAdd(),this.isDepthTextureExtensionSupported=b(this.renderer),t.replaceChildren(this.renderer.domElement),this.setupEventListeners(),this.depthRenderTarget=RenderingView.createDepthRenderTarget(this.renderer,this.container);const a=new d(this.scene,this.camera);this.composer.addPass(a);const u=new h(new e.Vector2(t.clientWidth,t.clientHeight),1.5,.4,.85);u.threshold=0,u.strength=.9,u.radius=1;const v=new o(this.renderer);v.renderToScreen=!1,v.addPass(a),v.addPass(u),this.bloomComposer=v;const f=new c(new e.ShaderMaterial({uniforms:{baseTexture:{value:null},bloomTexture:{value:v.renderTarget2.texture}},vertexShader:"\n varying vec2 vUv;\n void main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n }",fragmentShader:"\n uniform sampler2D baseTexture;\n uniform sampler2D bloomTexture;\n varying vec2 vUv;\n void main() {\n gl_FragColor = ( texture2D( baseTexture, vUv ) + vec4( 1.0 ) * texture2D( bloomTexture, vUv ) );\n }",defines:{}}),"baseTexture");if(f.needsSwap=!0,this.composer.addPass(f),this.outlinePass=new S(new e.Vector2(t.clientWidth,t.clientHeight),this.scene,this.camera),!0===i.enableOutlines){this.outlinePass.edgeThickness=0,this.outlinePass.edgeGlow=0,this.outlinePass.edgeThickness=1.5,this.outlinePass.edgeStrength=5,this.outlinePass.clear=!1,this.composer.addPass(this.outlinePass);const e=new c(m);e.uniforms.resolution.value.set(1/t.clientWidth,1/t.clientHeight),this.composer.addPass(e)}var w=new c(g);w.clear=!1,this.composer.addPass(w)}setCamera(t){this.camera=t,this.composer.passes.forEach((e=>{e instanceof d?e.camera=t:e instanceof S?e.renderCamera=t:e instanceof M&&(e.camera=t)})),null==this.csm?this.csm=new u({maxFar:200,lightFar:300,cascades:5,shadowMapSize:2048,lightDirection:new e.Vector3(.5,-1,-.6).normalize(),lightIntensity:.5,camera:this.camera,parent:this.scene}):(this.csm.camera=this.camera,this.camera instanceof n&&(this.csm.maxFar=this.camera.far)),this.csm.updateFrustums()}setSelectedObjects(e){const t=new Map;for(const i of e)t.set(i.uuid,i);for(const i of e)i.traverse((e=>{e.uuid!==i.uuid&&t.has(e.uuid)&&t.delete(e.uuid)}));this.outlinePass.selectedObjects=Array.from(t.values())}static createDepthRenderTarget(t,i){var s=!!t.extensions.get("WEBGL_depth_texture");const r=new e.WebGLRenderTarget(i.clientWidth*t.getPixelRatio(),i.clientHeight*t.getPixelRatio());return r.texture.minFilter=e.NearestFilter,r.texture.magFilter=e.NearestFilter,r.texture.generateMipmaps=!1,r.stencilBuffer=!1,!0===s&&(r.depthTexture=new e.DepthTexture(128,128),r.depthTexture.type=e.UnsignedShortType,r.depthTexture.minFilter=e.NearestFilter,r.depthTexture.magFilter=e.NearestFilter),r}setupEventListeners(){window.addEventListener("resize",this.onResize),window.addEventListener("orientationchange",this.onResize),document.addEventListener("visibilitychange",this.onVisiblityChane)}stop(){this.running=!1,window.removeEventListener("resize",this.onResize),window.removeEventListener("orientationchange",this.onResize),document.removeEventListener("visibilitychange",this.onVisiblityChane),this.onLoopCallbacks=[],this.renderer.dispose(),this.depthRenderTarget.dispose(),this.csm.dispose(),this.container.replaceChildren()}onLoop(e){this.onLoopCallbacks.push(e)}removeOnLoop(e){const t=this.onLoopCallbacks.find(e);this.onLoopCallbacks.splice(t,1)}set showStats(e){this._showStats=e,this._showStats&&!this.container.contains(this.stats.dom)?this.container.appendChild(this.stats.dom):!this._showStats&&this.container.contains(this.stats.dom)&&this.container.removeChild(this.stats.dom)}get showStats(){return this._showStats}loop(s,r=!1){const n=this.stats;n.showPanel(0),this.showStats=r;performance.now();e.Ray.prototype.intersectTriangle;let a=0;const o=new i,h=new i,l=e=>{const i=this.renderer.getContext();if(this.paused&&this.running&&i.drawingBufferHeight>1)return void setTimeout((()=>l(e)),500);this.renderer.autoClear=!1,this.renderer.clear(),this.renderer.setViewport(0,0,this.container.clientWidth,this.container.clientHeight),this.camera,n.begin();let r=(e*=.001)-a;if(a=e,o.copy(this.camera.matrixWorld),r>1){let e=r;for(;e>.05;)s(D),e-=D;s(e)}else s(r);this.onLoopCallbacks.forEach((e=>e(r))),this.camera?.updateMatrixWorld(),h.copy(this.camera.matrixWorld),h.equals(o)||(this.renderer.shadowMap.needsUpdate=!0),this.resizeRender();const d=[],c=[];if(this.scene.traverse((i=>{i instanceof t&&i.visible&&(i.material?.userData?.water||i.material?.uniforms&&null!=i.material?.uniforms[f])?(i.visible=!1,d.push(i),this.initDepthUniform(i.material),i.renderOrder=100):i instanceof v&&(i.visible=!1,c.push(i)),i instanceof t&&i.material?.uniforms&&null!=i.material?.uniforms[R]&&(i.material.uniforms[R].value=e)})),d.length>0){if(this.scene.overrideMaterial=L,this.renderer.setRenderTarget(this.depthRenderTarget),!this.paused&&null!=this.camera)try{this.renderer.clear(),this.renderer.render(this.scene,this.camera)}catch(e){console.warn(e)}this.renderer.setRenderTarget(null),this.scene.overrideMaterial=null}d.forEach((e=>e.visible=!0)),c.forEach((e=>e.visible=!0));try{!this.paused&&this.running&&(this.render(r),this.renderOverlay())}catch(e){console.warn(e)}n.end(),this.csm?.update(),this.running&&!0!==this.options.enableXR&&(this.fpsCap?setTimeout((()=>{requestAnimationFrame(l)}),1e3/this.fpsCap):requestAnimationFrame(l))};!0===this.options.enableXR?this.renderer.setAnimationLoop(l):requestAnimationFrame(l)}renderOverlay(){const e=Array.from(this.overlayCameras.values()).slice(0,this.maxInsetCameras),t=this.container.clientWidth/2,i=e.length*this.insetWidth+(e.length-1)*this.insetMargin;for(let s=0;s<e.length;s++)this.renderer.clearDepth(),this.renderer.setViewport(t-i/2+this.insetWidth*s+this.insetMargin*s,this.insetOffsetY,this.insetWidth,this.insetHeight),this.renderer.render(this.scene,e[s])}addOverlayCamera(e){this.overlayCameras.add(e)}clearOverlayCameras(){this.overlayCameras.clear()}removeOverlayCamera(e){this.overlayCameras.delete(e)}render(e){if(this.hasBloom()){const e=this.scene.fog;this.scene.fog=null;const t=this.renderer.getClearColor(this.prevClearColor);this.renderer.setClearColor(0),this.scene.traverseVisible((e=>this.darkenNonBloomed(e))),this.bloomComposer.render(),this.scene.traverse((e=>this.restoreMaterial(e))),this.renderer.setClearColor(t),this.scene.fog=e}this.composer.render(e)}hasBloom(){return null!=y(this.scene,(e=>e instanceof t&&!0===e.material?.userData?.hasBloom))}darkenNonBloomed(e){e.isMesh&&e.visible&&!0!==e.material.userData.hasBloom&&(this.bloomStoredMaterials[e.uuid]=e.material,!0!==e.material.transparent?e.material=W:e.visible=!1)}restoreMaterial(e){this.bloomStoredMaterials[e.uuid]&&(e.material=this.bloomStoredMaterials[e.uuid],delete this.bloomStoredMaterials[e.uuid],e.visible=!0)}initDepthUniform(e){e instanceof s&&(e.uniforms[f].value=this.isDepthTextureExtensionSupported?this.depthRenderTarget.depthTexture:this.depthRenderTarget.texture,null!=e.uniforms[w]&&e.uniforms[w].value.set(this.container.clientWidth*this.renderer.getPixelRatio(),this.container.clientHeight*this.renderer.getPixelRatio()),this.camera instanceof n&&(e.uniforms[x].value=this.camera.near,e.uniforms[C].value=this.camera.far))}}export function setRenderingPaused(e){null!=window.editor?.viewer?.renderingView&&(window.editor.viewer.renderingView.paused=e)}const D=.05;
|
1
|
+
import*as e from"three";import{Mesh as t,Matrix4 as i,ShaderMaterial as s,Color as r,PerspectiveCamera as n,ShaderChunk as a}from"three";import{EffectComposer as o,UnrealBloomPass as h,VRButton as l}from"three-stdlib";import{RenderPass as d}from"three-stdlib";import{ShaderPass as c}from"three-stdlib";import{FXAAShader as m}from"three-stdlib";import{CSM as u}from"three-stdlib";import{CSMUtil as p}from"./csm.js";import{GammaCorrectionShader as g}from"three-stdlib";import{Reflector as v}from"three-stdlib";import{depthUniformName as f,resolutionUniformName as w,supportsDepthTextureExtension as b,nearUniformName as x,farUniformName as C}from"./shader-nodes/depth.js";import{elapsedTimeUniformName as S}from"./shader-nodes/time.js";import{OutlinePass as R}from"./utils/three/outline-pass.js";import P from"./utils/three/stats.js";import{findFirstVisibleObject as y}from"./utils/three/traverse.js";import{lambertVertexShaderOverride as T}from"./rendering/shader-override.js";import{DepthPass as M}from"./utils/three/depth-pass.js";(new e.Layers).set(9);const W=new e.MeshBasicMaterial({color:"black"}),L=new e.MeshDepthMaterial;L.depthPacking=e.RGBADepthPacking,L.blending=e.NoBlending;a.lights_pars_begin;a.lights_lambert_vertex=T;const E=/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);export class RenderingView{setPaused(e){this.paused=e}resizeRender(){this.previousClientWith===this.container.clientWidth&&this.previousClientHeight===this.container.clientHeight||(this.camera instanceof n&&(this.camera.aspect=this.container.clientWidth/this.container.clientHeight,this.camera.updateProjectionMatrix()),this.renderer.setPixelRatio(window.devicePixelRatio*this.resolutionScale),this.renderer.setSize(this.container.clientWidth,this.container.clientHeight),this.composer.setSize(this.container.clientWidth*this.resolutionScale,this.container.clientHeight*this.resolutionScale),this.previousClientWith=this.container.clientWidth,this.previousClientHeight=this.container.clientHeight)}constructor(t,i={}){this.container=t,this.options=i,this.windowVisible=!0,this.running=!0,this.paused=!1,this.fpsCap=null,this.resolutionScale=E?.5:1,this.onResize=()=>{this.resizeRender(),this.paused||this.render()},this.onVisiblityChane=()=>{this.windowVisible=!document.hidden},this.isDepthTextureExtensionSupported=!1,this.onLoopCallbacks=[],this.stats=P(),this._showStats=!1,this.insetHeight=200,this.insetWidth=this.insetHeight*(16/9),this.insetOffsetY=250,this.insetMargin=10,this.maxInsetCameras=4,this.overlayCameras=new Set,this.prevClearColor=new r,this.bloomStoredMaterials={},window.renderer=this.renderer=new e.WebGLRenderer({antialias:!0,powerPreference:"high-performance"}),this.scene=new e.Scene,this.renderer.setPixelRatio(window.devicePixelRatio*this.resolutionScale),this.renderer.setSize(t.clientWidth,t.clientHeight),this.renderer.xr.enabled=this.options.enableXR??!1,!0===this.options.enableXR&&document.body.appendChild(l.createButton(this.renderer)),this.composer=new o(this.renderer);var s=t.clientWidth/t.clientHeight;const n=new e.PerspectiveCamera(45,s,.5,800);n.layers.enable(19),this.setCamera(n),this.renderer.shadowMap.enabled=!0,this.renderer.shadowMap.type=e.PCFSoftShadowMap,this.renderer.shadowMap.autoUpdate=!1,this.renderer.outputEncoding=e.sRGBEncoding,this.renderer.physicallyCorrectLights=!1,this.renderer.gammaFactor=1.4,p.renderingView=this,p.patchThreeAdd(),this.isDepthTextureExtensionSupported=b(this.renderer),t.replaceChildren(this.renderer.domElement),this.setupEventListeners(),this.depthRenderTarget=RenderingView.createDepthRenderTarget(this.renderer,this.container);const a=new d(this.scene,this.camera);this.composer.addPass(a);const u=new h(new e.Vector2(t.clientWidth,t.clientHeight),1.5,.4,.85);u.threshold=0,u.strength=.9,u.radius=1;const v=new o(this.renderer);v.renderToScreen=!1,v.addPass(a),v.addPass(u),this.bloomComposer=v;const f=new c(new e.ShaderMaterial({uniforms:{baseTexture:{value:null},bloomTexture:{value:v.renderTarget2.texture}},vertexShader:"\n varying vec2 vUv;\n void main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n }",fragmentShader:"\n uniform sampler2D baseTexture;\n uniform sampler2D bloomTexture;\n varying vec2 vUv;\n void main() {\n gl_FragColor = ( texture2D( baseTexture, vUv ) + vec4( 1.0 ) * texture2D( bloomTexture, vUv ) );\n }",defines:{}}),"baseTexture");if(f.needsSwap=!0,this.composer.addPass(f),this.outlinePass=new R(new e.Vector2(t.clientWidth,t.clientHeight),this.scene,this.camera),!0===i.enableOutlines){this.outlinePass.edgeThickness=0,this.outlinePass.edgeGlow=0,this.outlinePass.edgeThickness=1.5,this.outlinePass.edgeStrength=5,this.outlinePass.clear=!1,this.composer.addPass(this.outlinePass);const e=new c(m);e.uniforms.resolution.value.set(1/t.clientWidth,1/t.clientHeight),this.composer.addPass(e)}var w=new c(g);w.clear=!1,this.composer.addPass(w)}setCamera(t){this.camera=t,this.composer.passes.forEach((e=>{e instanceof d?e.camera=t:e instanceof R?e.renderCamera=t:e instanceof M&&(e.camera=t)})),null==this.csm?this.csm=new u({maxFar:200,lightFar:300,cascades:5,shadowMapSize:2048,lightDirection:new e.Vector3(.5,-1,-.6).normalize(),lightIntensity:.5,camera:this.camera,parent:this.scene}):(this.csm.camera=this.camera,this.camera instanceof n&&(this.csm.maxFar=this.camera.far)),this.csm.updateFrustums()}setSelectedObjects(e){const t=new Map;for(const i of e)t.set(i.uuid,i);for(const i of e)i.traverse((e=>{e.uuid!==i.uuid&&t.has(e.uuid)&&t.delete(e.uuid)}));this.outlinePass.selectedObjects=Array.from(t.values())}static createDepthRenderTarget(t,i){var s=!!t.extensions.get("WEBGL_depth_texture");const r=new e.WebGLRenderTarget(i.clientWidth*t.getPixelRatio(),i.clientHeight*t.getPixelRatio());return r.texture.minFilter=e.NearestFilter,r.texture.magFilter=e.NearestFilter,r.texture.generateMipmaps=!1,r.stencilBuffer=!1,!0===s&&(r.depthTexture=new e.DepthTexture(128,128),r.depthTexture.type=e.UnsignedShortType,r.depthTexture.minFilter=e.NearestFilter,r.depthTexture.magFilter=e.NearestFilter),r}setupEventListeners(){window.addEventListener("resize",this.onResize),window.addEventListener("orientationchange",this.onResize),document.addEventListener("visibilitychange",this.onVisiblityChane)}stop(){this.running=!1,window.removeEventListener("resize",this.onResize),window.removeEventListener("orientationchange",this.onResize),document.removeEventListener("visibilitychange",this.onVisiblityChane),this.onLoopCallbacks=[],this.renderer.dispose(),this.depthRenderTarget.dispose(),this.csm.dispose(),this.container.replaceChildren()}onLoop(e){this.onLoopCallbacks.push(e)}removeOnLoop(e){const t=this.onLoopCallbacks.find(e);this.onLoopCallbacks.splice(t,1)}set showStats(e){this._showStats=e,this._showStats&&!this.container.contains(this.stats.dom)?this.container.appendChild(this.stats.dom):!this._showStats&&this.container.contains(this.stats.dom)&&this.container.removeChild(this.stats.dom)}get showStats(){return this._showStats}loop(s,r=!1){const n=this.stats;n.showPanel(0),this.showStats=r;performance.now();e.Ray.prototype.intersectTriangle;let a=0;const o=new i,h=new i,l=e=>{const i=this.renderer.getContext();if(this.paused&&this.running&&i.drawingBufferHeight>1)return void setTimeout((()=>l(e)),500);this.renderer.autoClear=!1,this.renderer.clear(),this.renderer.setViewport(0,0,this.container.clientWidth,this.container.clientHeight),this.camera,n.begin();let r=(e*=.001)-a;if(a=e,o.copy(this.camera.matrixWorld),r>1){let e=r;for(;e>.05;)s(D),e-=D;s(e)}else s(r);this.onLoopCallbacks.forEach((e=>e(r))),this.camera?.updateMatrixWorld(),h.copy(this.camera.matrixWorld),h.equals(o)||(this.renderer.shadowMap.needsUpdate=!0),this.resizeRender();const d=[],c=[];if(this.scene.traverse((i=>{i instanceof t&&i.visible&&(i.material?.userData?.water||i.material?.uniforms&&null!=i.material?.uniforms[f])?(i.visible=!1,d.push(i),this.initDepthUniform(i.material),i.renderOrder=100):i instanceof v&&(i.visible=!1,c.push(i)),i instanceof t&&i.material?.uniforms&&null!=i.material?.uniforms[S]&&(i.material.uniforms[S].value=e)})),d.length>0){if(this.scene.overrideMaterial=L,this.renderer.setRenderTarget(this.depthRenderTarget),!this.paused&&null!=this.camera)try{this.renderer.clear(),this.renderer.render(this.scene,this.camera)}catch(e){console.warn(e)}this.renderer.setRenderTarget(null),this.scene.overrideMaterial=null}d.forEach((e=>e.visible=!0)),c.forEach((e=>e.visible=!0));try{!this.paused&&this.running&&(this.render(r),this.renderOverlay())}catch(e){console.warn(e)}n.end(),this.csm?.update(),this.running&&!0!==this.options.enableXR&&(this.fpsCap?setTimeout((()=>{requestAnimationFrame(l)}),1e3/this.fpsCap):requestAnimationFrame(l))};!0===this.options.enableXR?this.renderer.setAnimationLoop(l):requestAnimationFrame(l)}renderOverlay(){const e=Array.from(this.overlayCameras.values()).slice(0,this.maxInsetCameras),t=this.container.clientWidth/2,i=e.length*this.insetWidth+(e.length-1)*this.insetMargin;for(let s=0;s<e.length;s++)this.renderer.clearDepth(),this.renderer.setViewport(t-i/2+this.insetWidth*s+this.insetMargin*s,this.insetOffsetY,this.insetWidth,this.insetHeight),this.renderer.render(this.scene,e[s])}addOverlayCamera(e){this.overlayCameras.add(e)}clearOverlayCameras(){this.overlayCameras.clear()}removeOverlayCamera(e){this.overlayCameras.delete(e)}render(e){if(this.hasBloom()){const e=this.scene.fog;this.scene.fog=null;const t=this.renderer.getClearColor(this.prevClearColor);this.renderer.setClearColor(0),this.scene.traverseVisible((e=>this.darkenNonBloomed(e))),this.bloomComposer.render(),this.scene.traverse((e=>this.restoreMaterial(e))),this.renderer.setClearColor(t),this.scene.fog=e}this.composer.render(e)}hasBloom(){return null!=y(this.scene,(e=>e instanceof t&&!0===e.material?.userData?.hasBloom))}darkenNonBloomed(e){e.isMesh&&e.visible&&!0!==e.material.userData.hasBloom&&(this.bloomStoredMaterials[e.uuid]=e.material,!0!==e.material.transparent?e.material=W:e.visible=!1)}restoreMaterial(e){this.bloomStoredMaterials[e.uuid]&&(e.material=this.bloomStoredMaterials[e.uuid],delete this.bloomStoredMaterials[e.uuid],e.visible=!0)}initDepthUniform(e){e instanceof s&&(e.uniforms[f].value=this.isDepthTextureExtensionSupported?this.depthRenderTarget.depthTexture:this.depthRenderTarget.texture,null!=e.uniforms[w]&&e.uniforms[w].value.set(this.container.clientWidth*this.renderer.getPixelRatio(),this.container.clientHeight*this.renderer.getPixelRatio()),this.camera instanceof n&&(e.uniforms[x].value=this.camera.near,e.uniforms[C].value=this.camera.far))}}export function setRenderingPaused(e){null!=window.editor?.viewer?.renderingView&&(window.editor.viewer.renderingView.paused=e)}const D=.05;
|
2
2
|
/*
|
3
3
|
* Copyright (©) 2023. All rights reserved.
|
4
4
|
* See the LICENSE.md file for details.
|
package/dist/scene/bootstrap.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import{polyfill as e}from"../utils/polyfill.js";import{SceneDataService as t}from"./scene-data-service.js";import{SceneMaterializer as n}from"./materializer.js";import{basicSceneSetup as a}from"./sky.js";export async function loadScene(r,i,s,o,c,m,l,p,f){e();const{scene:w,renderer:d,camera:j}=r;a(w);const u=await l.getScene(i);if(null==u)throw Error(`Could not find scene with name ${i}`);const y=await l.getSceneData(u.id),S=new t;S.initiate(y
|
1
|
+
import{polyfill as e}from"../utils/polyfill.js";import{SceneDataService as t}from"./scene-data-service.js";import{SceneMaterializer as n}from"./materializer.js";import{basicSceneSetup as a}from"./sky.js";export async function loadScene(r,i,s,o,c,m,l,p,f){e();const{scene:w,renderer:d,camera:j}=r;a(w);const u=await l.getScene(i);if(null==u)throw Error(`Could not find scene with name ${i}`);const y=await l.getSceneData(u.id),S=new t;S.initiate(y);const g=Object.entries(o).map((([e,t])=>({name:e,type:t}))),h=Object.entries(c).map((([e,t])=>({name:e,type:t}))),v=new n(w,S,p,f,r,g,h,m);return await v.initWithInstancing(),{scene:w,view:r,materializer:v,assetResourceLoader:f,assetsService:p,actors:v.actorInstances}}
|
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 c,Mesh as l,MeshLambertMaterial as h,MeshPhongMaterial as m,MeshStandardMaterial as d,Object3D as p,PointLight as f,Quaternion as u,SphereGeometry as g,Texture as y,Vector2 as w,Vector3 as A,Vector4 as v}from"three";import S,{SpriteRenderer as b}from"three-nebula";import{bool as M,BooleanNode as x,float as j,FloatNode as I,NodeShaderMaterial as P,rgb as D,RgbNode as V,Texture2dLookupNode as E,textureSampler2d as N,vec2 as C,Vec2Node as F,vec3 as z,Vec3Node as k,vec4 as B}from"three-shader-graph";import O from"../gameplay/actors/builtin/index.js";import{extractShaderParameters as _}from"../shader/parameter.js";import{groupBy as T,ArrayMap as $}from"../utils/collections.js";import{filterChildrenShallow as L,filterSceneShallow as R}from"../utils/three/traverse.js";import{AssetMeshInstance as U}from"./asset-resource-loader.js";import{BoxCollisionShape as H,PhysicalShapeMesh as W}from"./collision/collision-shape.js";import{isCollisionMesh as G}from"./collision/collision-shape-import.js";import{initLandscape as J}from"./landscape/landscape.js";import{LandscapeManager as X}from"./landscape/landscape-manager.js";import{SectionGrid as Y,smoothNormalsCrossMeshes as q}from"./landscape/utils.js";import{createGrassMaterial as Z}from"./materials/grass.js";import{createGrassFoliageMaterial as K}from"./materials/grass-foliage.js";import{getMaterialAttribute as Q}from"./materials/utils/material-painting.js";import{createWaterMaterial as ee}from"./materials/water.js";import{SerializedParamType as te}from"./model.js";import{Matrix4 as ae}from"three";import{BaseActor as se}from"../gameplay/actors/actor.js";import{Sampler2DNode as re}from"../shader-nodes/index.js";import{StandardShader as ie}from"../shader/builtin/standard-shader.js";import{LambertShader as ne}from"../shader/builtin/lambert-shader.js";import{ShapeLibrary as oe,ShapeLibraryKeys as ce}from"./objects/shapes.js";import{ambientLightName as le,createSky as he,defaultSkyMaterial as me}from"./sky.js";import{ActorComponent as de,withInjectionContext as pe}from"../gameplay/index.js";import{iterateMaterials as fe}from"../utils/materials.js";import{VfxActor as ue}from"../effects/vfx/vfx-actor.js";import{VisualEffect as ge}from"../effects/vfx/vfx-param.js";const ye={};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(t,a,s,r,i,n,o,c){this.scene=t,this.dataProvider=a,this.assetsService=s,this.assetManagerService=r,this.renderingView=i,this.shaders=n,this.actorTypes=o,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._canBeInstancedCache=new Map,this._originalMaterials=new Map,this.originalFog=null,a.onUpdate((e=>this.update(e))),a.onRemove((e=>this.remove(e))),this.updateSubscription=s.onUpdate.subscribe((async e=>{"material"==e.type?((await this.assetsService.getAssets()).filter((t=>(t.materialAssignments??[]).some((t=>t.materialId===e.id)))).forEach((e=>{const t=this.findByAssetId(e.id);e.materialAssignments.forEach((e=>{t.forEach((t=>{const a=t.userData.src.materialAssignments;null!=a&&a.some((t=>t.color===e.color))||this.applyMaterial(t,e)}))}))})),R(this.scene,(t=>null!=t.userData.src&&(t.userData.src.materialAssignments??[]).some((t=>t.materialId===e.id))),(e=>null!=e.userData.src)).forEach((async e=>{this.deleteSceneObject(e.userData.src),this.materialize(e.userData.src)}))):"mesh"==e.type?this.findByAssetId(e.id).forEach((t=>{Pe(t.userData.src.materialAssignments,e.materialAssignments).forEach((e=>{this.applyMaterial(t,e)}))})):"prefab"===e.type&&this.findByAssetId(e.id).forEach((e=>{const t=e.userData.src;this.remove(t),this.materializeAndInitActor(t)}))}))}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=>e&&this.assetManagerService.getMesh(e))))))}async init(){this.preInit(),Ae.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??{}};this.removeVfxChildActors(e);for(const a of t.actor.innerParams??[])await this.applyActorComponentParams(e,a.path.slice(),a.params);const r=await be(s,e.constructor,this.assetsService,this.assetManagerService,this.materializedActors,this.renderingView,this.shaders,this.actorProvider);Object.assign(e,r),this.addVfxChildActors(e);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){for(const a of Object.keys(t))t[a]instanceof ge?null!=t[a].actor&&(console.log("add actor to world",t[a].actor),e.object.add(t[a].actor.object)):t[a]instanceof de&&this.addVfxChildActors(e,t[a])}removeVfxChildActors(e,t=e){for(const a of Object.keys(t))if(t[a]instanceof ge){if(null!=t[a].actor){t[a].actor.onEndPlay(),console.log("remve actor from world",t[a].actor),e.object.remove(t[a].actor.object)}}else t[a]instanceof de&&this.removeVfxChildActors(e,t[a])}async applyActorComponentParams(e,t,a){const s=t.length,r=t.shift();if(0==s){const t=await be(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)}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=>{!G(e)&&e.isMesh&&a.push(e)}));const s=1==a.length&&0==a[0].children.length,r=!0;this._canBeInstancedCache.set(e.assetId,s&&r)}return this._canBeInstancedCache.get(e.assetId)}preInit(){this.renderingView?.onLoop((()=>this.sky?.position.copy(this.renderingView.camera.position)))}async initWithInstancing(){this.preInit();const e=new $;for(const t of this.dataProvider.getObjects())await Ie(t,(async(t,a,s)=>{const r="asset_mesh"==t.type&&await this.canAssetBeInstanced(t)?t.assetId+JSON.stringify(t.materialAssignments??[]):"other";"other"!==r&&a&&a.children?.length>0&&a.children.splice(a.children.findIndex((e=>e.id===t.id)),1),"other"===r&&a||e.push(r,{...t,parentTransform:s})}));for(const[t,a]of e.entries())if("other"!==t&&a.length>0){const e=await this.createFromAsset(a[0]);if(null==e)continue;const t=await this.createInstancedMesh(a,e),s=new U;s.add(t),s.userData.src=a[0],e instanceof U&&(s.collisionShapes=e.collisionShapes),s.castShadow=!1,s.receiveShadow=!1,this.scene.add(s)}else await Promise.all(a.map((e=>this.materialize(e))));await this.initActorsPostInit()}async createInstancedMesh(e,a){const s=a.children.filter((e=>!G(e)))[0],i=await this.assetsService.getAsset(e[0].assetId);await this.applyMaterials(a,Pe(e[0].materialAssignments,i.materialAssignments)),s.updateMatrix();const n=s.geometry.clone().applyMatrix4(s.matrix),o=new t.InstancedMesh(n,s.material.clone(),e.length);o.material.side=t.FrontSide;for(let a=0;a<e.length;a++){const s=(new t.Matrix4).compose((new A).fromArray(e[a].position),(new u).setFromEuler((new r).fromArray(e[a].rotation)),(new A).fromArray(e[a].scale)),i=(new ae).copy(e[a].parentTransform).multiply(s);o.setMatrixAt(a,i)}return o.castShadow=i.castShadow??!0,o.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(),this.removeVfxChildActors(t)):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 R(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))))}applyMaterial(e,t){const a=[];return e.traverse((async e=>{if(e instanceof l||e.isMesh)for(const t of fe(e.material))t.hasOwnProperty("color")&&a.push(e)})),Promise.all(a.map((async e=>{if(e.material instanceof Array)for(let a=0;a<e.material.length;a++){const r=e.material[a];if(null==r.color||!(r.color instanceof s))continue;const i="#"+r.color.getHexString(),n=r.name;if(i===t.color&&(r.name===t.name||null==t.name)||e.userData["originalColor_"+a]===t.color&&e.userData["originalMaterialName_"+a]===t.name){const s=await this.assetsService.getAsset(t.materialId),r=e.material[a];s&&(e.material[a]=await materialFromAsset(s,this.renderingView,this.assetsService,this.assetManagerService,this.shaders),e.userData["originalColor_"+a]=e.userData["originalColor_"+a]??i,e.userData["originalMaterialName_"+a]=e.userData["originalMaterialName_"+a]??n,this.inEditor&&this._originalMaterials.set(e.id+"#"+a,r))}}else{const a="#"+e.material.color.getHexString(),s=e.material.name;if(a===t.color&&(e.material.name===t.name||null==t.name)||e.userData.originalColor===t.color&&e.userData.originalName===t.name){const r=await this.assetsService.getAsset(t.materialId),i=e.material;r&&(e.material=await materialFromAsset(r,this.renderingView,this.assetsService,this.assetManagerService,this.shaders),e.userData.originalColor=e.userData.originalColor??a,e.userData.originalMaterialName=e.userData.originalMaterialName??s,this.inEditor&&this._originalMaterials.set(e.id,i))}}})))}unapplyMaterials(e){e.traverse((async e=>{if(e instanceof l)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(O));R(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 Ae.entries())t.userData.customShaderName&&Ae.delete(e);this.landscapeManagers.forEach((t=>t.updateShaders(e))),R(this.scene,(e=>!0)).forEach((e=>{e.traverse((e=>{if(e instanceof l){const t=e.material.userData?.customShaderName;if(null!=t){const t=function(e,t){if(t(e))return e;let a;return e.traverseAncestors((e=>{null==a&&t(e)&&(a=e)})),a}(e,(e=>null!=e.userData.src?.id))?.userData.src;null!=t&&this.update(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){const r=this.findParent(e);if(null!=r&&r.uuid!=t.uuid?r.attach(t):console.error("Parent is wrong"),"prefab"!==e.type){this.unapplyMaterials(t);this.inEditor&&e.hidden&&!1?t.traverse((e=>{e instanceof l&&(e.material.wireframe=!0)})):t.traverse((e=>{e instanceof l&&(e.material.wireframe=!1)}))}if("asset_mesh"===e.type){const a=await this.assetsService.getAsset(e.assetId);Pe(e.materialAssignments,a.materialAssignments).forEach((e=>this.applyMaterial(t,e)))}else"shape_mesh"===e.type&&this.applyMaterials(t,e.materialAssignments);let o=!1;if(t.traverseAncestors((e=>{"_hology_transform_group"===e.name&&(o=!0)})),o||(t.position.fromArray(e.position),t.scale.fromArray(e.scale),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)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=xe(e.fog),t&&(a=this.scene).traverse((e=>{if(e instanceof l){const t=e.material;t instanceof P&&(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"),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 W&&(t.geometry=a.geometry,t.collisionShape=a.collisionShape)}("asset_mesh"===e.type||"shape_mesh"===e.type&&"landscape"!==e.shape)&&we(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 Ie(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:L(t,(t=>t.children?.some((t=>t.id===e.id))),(()=>!0))))[0];return null==t?this.scene:null!=t?R(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).convertSRGBToLinear())}findMeshWithGeometry(e){let t;return e.traverse((e=>{e instanceof l&&e.geometry&&(t=e)})),t}applyVertexMaterials(e,t){if(null==e.vertexMaterials||0===e.vertexMaterials.length)return;const a=T(e.vertexMaterials,(e=>e.m));t.traverse((e=>{if(e instanceof l){const t=Q(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=Q(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=xe(e.fog),this.fixFogColor(),r=new o;break;case"sky":this.sky=he(),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),r.position.fromArray(e.position),r.scale.fromArray(e.scale),r.rotation.fromArray(e.rotation),s||(r.userData.src=e),!this.inEditor){const t=e.components??[],a=null!=e.assetId?(await this.assetsService.getAsset(e.assetId))?.components??[]:[];t.push(...a),t.length>0?r.userData.componentRefs=await Promise.all(t.map(((t,a)=>this.createComponent(r,e,t,a)))):"asset_mesh"==e.type&&function(e){e.traverse((e=>{e.matrixAutoUpdate=!1,e.matrixWorldNeedsUpdate=!1}));const t=e.updateMatrixWorld;e.updateMatrixWorld=function(){t.apply(e),e.updateMatrixWorld=function(){}}}(r)}if(this.inEditor){let e=null;r instanceof W&&(e=function(e){if(e instanceof H)return new l(new a(...e.offset.toArray()),je);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),null==t?this.scene.add(r):t?.add(r),null!=e.children&&await Promise.all(e.children?.map((e=>this.materialize(e,r,s)))),r}}async updateSky(e){if(null==e?.sky?.materialId)return void(this.sky.material=me);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 ye[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??O[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 A).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(ue,(new A).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);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),a=i,this._originalMaterials.set(a.id,i.material),a.traverse((e=>{}))}return t||((e.materialAssignments??[]).filter((e=>null!=e.materialId)).forEach((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=J(e.landscape.options);this.applyHeightMaps(a,e.landscape.heightMaps,!0);const s=new X(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 Y(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((()=>q(r)),50)}async createMeshByShape(e,t,a={}){if("landscape"!==e&&ce.includes(e)){const s=await prepareShapeParameters(a??{});return"cylinder"==e&&s.openEnded,new W(oe[e].geometry(s),t,oe[e].collision(s))}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);Pe(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,we(a,r,s),e.collisionDetection||(a.collisionShapes=[]),this.applyVertexMaterials(e,a),a.traverse((e=>{e instanceof l&&"computeBoundsTree"in e.geometry&&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 p;return await S.fromJSONAsync(a.particleSystem,t).then((e=>{const a=new b(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 l(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===le));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.materializedActors.forEach((e=>e.disposed.next(!0)))}}function we(e,t,a){e.castShadow=t,e.receiveShadow=a,e.traverse((e=>{e.castShadow=t,e.receiveShadow=a}))}const Ae=new Map,ve=new h({color:16711935}),Se=new Map;export async function materialFromAsset(e,a,r,i,n,o=!0){const c=JSON.stringify(e.material);if(o&&Ae.has(c))return Ae.get(c);const l={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).convertSRGBToLinear(),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&&(l.map=await i.getTexture(a))}let d;switch(e.material.type){case"phong":d=new m({...l,...h});break;case"water":d=ee(l,a);break;case"grassFoliage":d=K({color:l.color,map:l.map},a);break;case"grass":d=Z({...l,colorTwo:new s(e.material.params.colorTwo),colorThree:new s(e.material.params.colorThree)},a);break;case"standard":case"lambert":case"shader":const t={standard:ie,lambert:ne}[e.material.type]??n.find((t=>t.name==e.material.shader))?.type;if(t){const s=new t,o=await be(e.material?.shaderParams??{},t,r,i,null,a,n);Object.assign(s,o);try{d=s.build()}catch(t){console.log("Shader runtime error: "+t),Se.has(e.material.shader)||Se.set(e.material.shader,ve.clone()),d=Se.get(e.material.shader)}d.userData.customShaderName=e.material.shader}else console.warn("Missing shader implementation with name "+e.material.shader),d=ve;break;default:throw new Error("Unsupported material type"+e.material.type)}return a?.csm.setupMaterial(d),o&&Ae.set(c,d),d.side=e.material.side??d.side??t.FrontSide,d.transparent=(e.material.transparent??l.transparent??!1)||d.transparent,e.material.bloom&&(d.userData.hasBloom=!0),d}async function be(e,t,a,s,r,i,n,o){const c={};for(const[t,l]of Object.entries(e)){const e=await Me(l,a,s,r,i,n,o);null!=e&&(c[t]=e)}return c}export async function prepareShapeParameters(e){const t={};for(const[a,s]of Object.entries(e)){const e=await Me(s,null,null,null);null!=e&&(t[a]=e)}return t}async function Me(e,t,a,i,n,o,c){if(te.String,null==e||null==e.value||""==e.value)return null;const l=e.value;switch(e.type){case te.Number:case te.FloatNode:let h="string"==typeof l?parseFloat(l):l;return e.type===te.FloatNode?j(h):h;case te.Texture:return await a.getTexture(await t.getAsset(l));case te.Sampler2DNode:return N(await a.getTexture(await t.getAsset(l)));case te.Boolean:return l;case te.BooleanNode:return M(l);case te.Vector2:case te.Vec2Node:if("object"==typeof l){const t=l instanceof Array?(new w).fromArray(l):new w(l.x,l.y);return e.type===te.Vec2Node?C(t):t}return null;case te.Vector3:case te.Vec3Node:if("object"==typeof l){const t=l instanceof Array?(new A).fromArray(l):new A(l.x,l.y,l.z);return e.type===te.Vec3Node?z(t):t}return null;case te.Color:case te.RgbNode:const m=new s(l).convertSRGBToLinear();return e.type===te.RgbNode?D(m):m;case te.String:return l;case te.BaseActor:const d=l;return null==i&&console.warn("Class parameters can not be prepared as actors are not passed in"),i?.get(d);case te.Euler:const p=l;return(new r).fromArray(p);case te.Object3D:return(await a.getMesh(await t.getAsset(l))).scene;case te.Material:return await materialFromAsset(await t.getAsset(l),n,t,a,o);case te.AudioBuffer:return await a.getAudio(await t.getAsset(l));case te.VisualEffect:const f=await t.getAsset(l);if(null==c){console.error("Can not create instance of visual effect because missing actor provider");break}if("vfx"in f){const e=await c.create(ue);return await e.fromAsset(f),new ge(e)}console.error("Using a non-vfx asset for visual effect parameter")}return null}function xe(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 je=new d({color:4229780});async function Ie(e,a,s,i){null==i&&(i=(new ae).identity()),await a(e,s,i);const n=i.clone().multiply(function(e,t){return t.compose((new A).fromArray(e.position),(new u).setFromEuler((new r).fromArray(e.rotation)),(new A).fromArray(e.scale))}(e,new t.Matrix4));return Promise.all((e.children??[]).map((t=>Ie(t,a,e,n))))}export function toSerializedParamType(e){const t=e.constructor.prototype;return t instanceof Number||e===Number?te.Number:t instanceof I||"function"==typeof e.prototype.isFloat?te.FloatNode:t instanceof y||e===y||e.isTexture?te.Texture:t instanceof re||e===E?te.Sampler2DNode:t instanceof Boolean||e===Boolean?te.Boolean:t instanceof x?te.BooleanNode:t instanceof s||e==s?te.Color:t instanceof V||"function"==typeof e.prototype.isRgb?te.RgbNode:t instanceof w||e==w?te.Vector2:t instanceof F||"function"==typeof e.prototype.isVec2?te.Vec2Node:t instanceof A||e==A?te.Vector3:t instanceof k||"function"==typeof e.prototype.isVec3?te.Vec3Node:t instanceof String||e===String?te.String:t instanceof se||e==se||e.prototype instanceof se||e.prototype==se?te.BaseActor:t instanceof r||e==r?te.Euler:t instanceof p||e==p?te.Object3D:t instanceof c||e==c?te.Material:t instanceof AudioBuffer||e==AudioBuffer?te.AudioBuffer:t instanceof ge||e==ge?te.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=_(e);if(0===s.length)return{};let r;null!=a?pe(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 w:return t instanceof w?t.toArray():void a();case A:return t instanceof A?t.toArray():void a();case v:return t instanceof v?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 Pe(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=>De(e.materialId))),(t??[]).filter((e=>De(e.materialId))),(e=>e.color+e.name))}function De(e){return"null"!=e&&null!=e}export const customParameterDefaultValueByType=new Map([[te.RgbNode,"#000000"],[te.Color,"#000000"],[te.Vector4,[0,0,0,0]],[te.Vec4Node,[0,0,0,0]],[te.Vector3,[0,0,0]],[te.Vec3Node,[0,0,0]],[te.Vector2,[0,0]],[te.Vec2Node,[0,0]],[te.Euler,[0,0,0,"XYZ"]]]);
|
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 c,Mesh as l,MeshLambertMaterial as h,MeshPhongMaterial as m,MeshStandardMaterial as d,Object3D as p,PointLight as f,Quaternion as u,SphereGeometry as g,Texture as y,Vector2 as w,Vector3 as v,Vector4 as A}from"three";import S,{SpriteRenderer as b}from"three-nebula";import{bool as M,BooleanNode as x,float as j,FloatNode as I,NodeShaderMaterial as P,rgb as D,RgbNode as E,Texture2dLookupNode as V,textureSampler2d as N,vec2 as F,Vec2Node as z,vec3 as C,Vec3Node as k,vec4 as B}from"three-shader-graph";import O from"../gameplay/actors/builtin/index.js";import{extractShaderParameters as _}from"../shader/parameter.js";import{groupBy as T,ArrayMap as $}from"../utils/collections.js";import{filterChildrenShallow as L,filterSceneShallow as R}from"../utils/three/traverse.js";import{AssetMeshInstance as U}from"./asset-resource-loader.js";import{BoxCollisionShape as H,PhysicalShapeMesh as W}from"./collision/collision-shape.js";import{isCollisionMesh as G}from"./collision/collision-shape-import.js";import{initLandscape as J}from"./landscape/landscape.js";import{LandscapeManager as X}from"./landscape/landscape-manager.js";import{SectionGrid as Y,smoothNormalsCrossMeshes as q}from"./landscape/utils.js";import{createGrassMaterial as Z}from"./materials/grass.js";import{createGrassFoliageMaterial as K}from"./materials/grass-foliage.js";import{getMaterialAttribute as Q}from"./materials/utils/material-painting.js";import{createWaterMaterial as ee}from"./materials/water.js";import{SerializedParamType as te}from"./model.js";import{Matrix4 as ae}from"three";import{BaseActor as se}from"../gameplay/actors/actor.js";import{Sampler2DNode as re}from"../shader-nodes/index.js";import{StandardShader as ie}from"../shader/builtin/standard-shader.js";import{LambertShader as ne}from"../shader/builtin/lambert-shader.js";import{ShapeLibrary as oe,ShapeLibraryKeys as ce}from"./objects/shapes.js";import{ambientLightName as le,createSky as he,defaultSkyMaterial as me}from"./sky.js";import{ActorComponent as de,withInjectionContext as pe}from"../gameplay/index.js";import{iterateMaterials as fe}from"../utils/materials.js";import{VfxActor as ue}from"../effects/vfx/vfx-actor.js";import{VisualEffect as ge}from"../effects/vfx/vfx-param.js";const ye={};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(t,a,s,r,i,n,o,c){this.scene=t,this.dataProvider=a,this.assetsService=s,this.assetManagerService=r,this.renderingView=i,this.shaders=n,this.actorTypes=o,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._canBeInstancedCache=new Map,this._originalMaterials=new Map,this.originalFog=null,a.onUpdate((e=>this.update(e))),a.onRemove((e=>this.remove(e))),this.updateSubscription=s.onUpdate.subscribe((async e=>{"material"==e.type?((await this.assetsService.getAssets()).filter((t=>(t.materialAssignments??[]).some((t=>t.materialId===e.id)))).forEach((e=>{const t=this.findByAssetId(e.id);e.materialAssignments.forEach((e=>{t.forEach((t=>{const a=t.userData.src.materialAssignments;null!=a&&a.some((t=>t.color===e.color))||this.applyMaterial(t,e)}))}))})),R(this.scene,(t=>null!=t.userData.src&&(t.userData.src.materialAssignments??[]).some((t=>t.materialId===e.id))),(e=>null!=e.userData.src)).forEach((async e=>{this.deleteSceneObject(e.userData.src),this.materialize(e.userData.src)}))):"mesh"==e.type?this.findByAssetId(e.id).forEach((t=>{Pe(t.userData.src.materialAssignments,e.materialAssignments).forEach((e=>{this.applyMaterial(t,e)}))})):"prefab"===e.type&&this.findByAssetId(e.id).forEach((e=>{const t=e.userData.src;this.remove(t),this.materializeAndInitActor(t)}))}))}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=>e&&this.assetManagerService.getMesh(e))))))}async init(){this.preInit(),ve.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 be(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){for(const a of Object.keys(t))t[a]instanceof ge?null!=t[a].actor&&(console.log("add actor to world",t[a].actor),e.object.add(t[a].actor.object)):t[a]instanceof de&&this.addVfxChildActors(e,t[a])}removeVfxChildActors(e,t=e){for(const a of Object.keys(t))if(t[a]instanceof ge){if(null!=t[a].actor){t[a].actor.onEndPlay(),console.log("remve actor from world",t[a].actor),e.object.remove(t[a].actor.object)}}else t[a]instanceof de&&this.removeVfxChildActors(e,t[a])}async applyActorComponentParams(e,t,a){const s=t.length,r=t.shift();if(0==s){const t=await be(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)}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=>{!G(e)&&e.isMesh&&a.push(e)}));const s=1==a.length&&0==a[0].children.length,r=!0;this._canBeInstancedCache.set(e.assetId,s&&r)}return this._canBeInstancedCache.get(e.assetId)}preInit(){this.renderingView?.onLoop((()=>this.sky?.position.copy(this.renderingView.camera.position)))}async initWithInstancing(){this.preInit();const e=new $;for(const t of this.dataProvider.getObjects())await Ie(t,(async(t,a,s)=>{const r="asset_mesh"==t.type&&await this.canAssetBeInstanced(t)?t.assetId+JSON.stringify(t.materialAssignments??[]):"other";"other"!==r&&a&&a.children?.length>0&&a.children.splice(a.children.findIndex((e=>e.id===t.id)),1),"other"===r&&a||e.push(r,{...t,parentTransform:s})}));for(const[t,a]of e.entries())if("other"!==t&&a.length>0){const e=await this.createFromAsset(a[0]);if(null==e)continue;const t=await this.createInstancedMesh(a,e),s=new U;s.add(t),s.userData.src=a[0],e instanceof U&&(s.collisionShapes=e.collisionShapes),s.castShadow=!1,s.receiveShadow=!1,this.scene.add(s)}else await Promise.all(a.map((e=>this.materialize(e))));await this.initActorsPostInit()}async createInstancedMesh(e,a){const s=a.children.filter((e=>!G(e)))[0],i=await this.assetsService.getAsset(e[0].assetId);await this.applyMaterials(a,Pe(e[0].materialAssignments,i.materialAssignments)),s.updateMatrix();const n=s.geometry.clone().applyMatrix4(s.matrix),o=new t.InstancedMesh(n,s.material.clone(),e.length);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 u).setFromEuler((new r).fromArray(e[a].rotation)),(new v).fromArray(e[a].scale)),i=(new ae).copy(e[a].parentTransform).multiply(s);o.setMatrixAt(a,i)}return o.castShadow=i.castShadow??!0,o.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(),this.removeVfxChildActors(t)):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 R(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))))}applyMaterial(e,t){const a=[];return e.traverse((async e=>{if(e instanceof l||e.isMesh)for(const t of fe(e.material))t.hasOwnProperty("color")&&a.push(e)})),Promise.all(a.map((async e=>{if(e.material instanceof Array)for(let a=0;a<e.material.length;a++){const r=e.material[a];if(null==r.color||!(r.color instanceof s))continue;const i="#"+r.color.getHexString(),n=r.name;if(i===t.color&&(r.name===t.name||null==t.name)||e.userData["originalColor_"+a]===t.color&&e.userData["originalMaterialName_"+a]===t.name){const s=await this.assetsService.getAsset(t.materialId),r=e.material[a];s&&(e.material[a]=await materialFromAsset(s,this.renderingView,this.assetsService,this.assetManagerService,this.shaders),e.userData["originalColor_"+a]=e.userData["originalColor_"+a]??i,e.userData["originalMaterialName_"+a]=e.userData["originalMaterialName_"+a]??n,this.inEditor&&this._originalMaterials.set(e.id+"#"+a,r))}}else{const a="#"+e.material.color.getHexString(),s=e.material.name;if(a===t.color&&(e.material.name===t.name||null==t.name)||e.userData.originalColor===t.color&&e.userData.originalName===t.name){const r=await this.assetsService.getAsset(t.materialId),i=e.material;r&&(e.material=await materialFromAsset(r,this.renderingView,this.assetsService,this.assetManagerService,this.shaders),e.userData.originalColor=e.userData.originalColor??a,e.userData.originalMaterialName=e.userData.originalMaterialName??s,this.inEditor&&this._originalMaterials.set(e.id,i))}}})))}unapplyMaterials(e){e.traverse((async e=>{if(e instanceof l)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(O));R(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 ve.entries())t.userData.customShaderName&&ve.delete(e);this.landscapeManagers.forEach((t=>t.updateShaders(e))),R(this.scene,(e=>!0)).forEach((e=>{e.traverse((e=>{if(e instanceof l){const t=e.material.userData?.customShaderName;if(null!=t){const t=function(e,t){if(t(e))return e;let a;return e.traverseAncestors((e=>{null==a&&t(e)&&(a=e)})),a}(e,(e=>null!=e.userData.src?.id))?.userData.src;null!=t&&this.update(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){const r=this.findParent(e);if(null!=r&&r.uuid!=t.uuid?r.attach(t):console.error("Parent is wrong"),"prefab"!==e.type){this.unapplyMaterials(t);this.inEditor&&e.hidden&&!1?t.traverse((e=>{e instanceof l&&(e.material.wireframe=!0)})):t.traverse((e=>{e instanceof l&&(e.material.wireframe=!1)}))}if("asset_mesh"===e.type){const a=await this.assetsService.getAsset(e.assetId);Pe(e.materialAssignments,a.materialAssignments).forEach((e=>this.applyMaterial(t,e)))}else"shape_mesh"===e.type&&this.applyMaterials(t,e.materialAssignments);let o=!1;if(t.traverseAncestors((e=>{"_hology_transform_group"===e.name&&(o=!0)})),o||(t.position.fromArray(e.position),t.scale.fromArray(e.scale),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)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=xe(e.fog),t&&(a=this.scene).traverse((e=>{if(e instanceof l){const t=e.material;t instanceof P&&(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"),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 W&&(t.geometry=a.geometry,t.collisionShape=a.collisionShape)}("asset_mesh"===e.type||"shape_mesh"===e.type&&"landscape"!==e.shape)&&we(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 Ie(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:L(t,(t=>t.children?.some((t=>t.id===e.id))),(()=>!0))))[0];return null==t?this.scene:null!=t?R(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).convertSRGBToLinear())}findMeshWithGeometry(e){let t;return e.traverse((e=>{e instanceof l&&e.geometry&&(t=e)})),t}applyVertexMaterials(e,t){if(null==e.vertexMaterials||0===e.vertexMaterials.length)return;const a=T(e.vertexMaterials,(e=>e.m));t.traverse((e=>{if(e instanceof l){const t=Q(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=Q(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=xe(e.fog),this.fixFogColor(),r=new o;break;case"sky":this.sky=he(),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),r.position.fromArray(e.position),r.scale.fromArray(e.scale),r.rotation.fromArray(e.rotation),s||(r.userData.src=e),!this.inEditor){const t=e.components??[],a=null!=e.assetId?(await this.assetsService.getAsset(e.assetId))?.components??[]:[];t.push(...a),t.length>0?r.userData.componentRefs=await Promise.all(t.map(((t,a)=>this.createComponent(r,e,t,a)))):"asset_mesh"==e.type&&function(e){e.traverse((e=>{e.matrixAutoUpdate=!1,e.matrixWorldNeedsUpdate=!1}));const t=e.updateMatrixWorld;e.updateMatrixWorld=function(){t.apply(e),e.updateMatrixWorld=function(){}}}(r)}if(this.inEditor){let e=null;r instanceof W&&(e=function(e){if(e instanceof H)return new l(new a(...e.offset.toArray()),je);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),null==t?this.scene.add(r):t?.add(r),null!=e.children&&await Promise.all(e.children?.map((e=>this.materialize(e,r,s)))),r}}async updateSky(e){if(null==e?.sky?.materialId)return void(this.sky.material=me);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 ye[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??O[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(ue,(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);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),a=i,this._originalMaterials.set(a.id,i.material),a.traverse((e=>{}))}return t||((e.materialAssignments??[]).filter((e=>null!=e.materialId)).forEach((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=J(e.landscape.options);this.applyHeightMaps(a,e.landscape.heightMaps,!0);const s=new X(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 Y(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((()=>q(r)),50)}async createMeshByShape(e,t,a={}){if("landscape"!==e&&ce.includes(e)){const s=await prepareShapeParameters(a??{});return"cylinder"==e&&s.openEnded,new W(oe[e].geometry(s),t,oe[e].collision(s))}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);Pe(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,we(a,r,s),e.collisionDetection||(a.collisionShapes=[]),this.applyVertexMaterials(e,a),a.traverse((e=>{e instanceof l&&"computeBoundsTree"in e.geometry&&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 p;return await S.fromJSONAsync(a.particleSystem,t).then((e=>{const a=new b(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 l(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===le));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.materializedActors.forEach((e=>e.disposed.next(!0)))}}function we(e,t,a){e.castShadow=t,e.receiveShadow=a,e.traverse((e=>{e.castShadow=t,e.receiveShadow=a}))}const ve=new Map,Ae=new h({color:16711935}),Se=new Map;export async function materialFromAsset(e,a,r,i,n,o=!0){const c=JSON.stringify(e.material);if(o&&ve.has(c))return ve.get(c);const l={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).convertSRGBToLinear(),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&&(l.map=await i.getTexture(a))}let d;switch(e.material.type){case"phong":d=new m({...l,...h});break;case"water":d=ee(l,a);break;case"grassFoliage":d=K({color:l.color,map:l.map},a);break;case"grass":d=Z({...l,colorTwo:new s(e.material.params.colorTwo),colorThree:new s(e.material.params.colorThree)},a);break;case"standard":case"lambert":case"shader":const t={standard:ie,lambert:ne}[e.material.type]??n.find((t=>t.name==e.material.shader))?.type;if(t){const s=new t,o=await be(e.material?.shaderParams??{},t,r,i,null,a,n);Object.assign(s,o);try{d=s.build()}catch(t){console.log("Shader runtime error: "+t),Se.has(e.material.shader)||Se.set(e.material.shader,Ae.clone()),d=Se.get(e.material.shader)}d.userData.customShaderName=e.material.shader}else console.warn("Missing shader implementation with name "+e.material.shader),d=Ae;break;default:throw new Error("Unsupported material type"+e.material.type)}return a?.csm.setupMaterial(d),o&&ve.set(c,d),d.side=e.material.side??d.side??t.FrontSide,d.transparent=(e.material.transparent??l.transparent??!1)||d.transparent,e.material.bloom&&(d.userData.hasBloom=!0),d}async function be(e,t,a,s,r,i,n,o){const c={};for(const[t,l]of Object.entries(e)){const e=await Me(l,a,s,r,i,n,o);null!=e&&(c[t]=e)}return c}export async function prepareShapeParameters(e){const t={};for(const[a,s]of Object.entries(e)){const e=await Me(s,null,null,null);null!=e&&(t[a]=e)}return t}async function Me(e,t,a,i,n,o,c){if(te.String,null==e||null==e.value||""==e.value)return null;const l=e.value;switch(e.type){case te.Number:case te.FloatNode:let h="string"==typeof l?parseFloat(l):l;return e.type===te.FloatNode?j(h):h;case te.Texture:return await a.getTexture(await t.getAsset(l));case te.Sampler2DNode:return N(await a.getTexture(await t.getAsset(l)));case te.Boolean:return l;case te.BooleanNode:return M(l);case te.Vector2:case te.Vec2Node:if("object"==typeof l){const t=l instanceof Array?(new w).fromArray(l):new w(l.x,l.y);return e.type===te.Vec2Node?F(t):t}return null;case te.Vector3:case te.Vec3Node:if("object"==typeof l){const t=l instanceof Array?(new v).fromArray(l):new v(l.x,l.y,l.z);return e.type===te.Vec3Node?C(t):t}return null;case te.Color:case te.RgbNode:const m=new s(l).convertSRGBToLinear();return e.type===te.RgbNode?D(m):m;case te.String:return l;case te.BaseActor:const d=l;return null==i&&console.warn("Class parameters can not be prepared as actors are not passed in"),i?.get(d);case te.Euler:const p=l;return(new r).fromArray(p);case te.Object3D:return(await a.getMesh(await t.getAsset(l))).scene;case te.Material:return await materialFromAsset(await t.getAsset(l),n,t,a,o);case te.AudioBuffer:return await a.getAudio(await t.getAsset(l));case te.VisualEffect:const f=await t.getAsset(l);if(null==c){console.error("Can not create instance of visual effect because missing actor provider");break}if("vfx"in f)return new ge(c,f);console.error("Using a non-vfx asset for visual effect parameter")}return null}function xe(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 je=new d({color:4229780});async function Ie(e,a,s,i){null==i&&(i=(new ae).identity()),await a(e,s,i);const n=i.clone().multiply(function(e,t){return t.compose((new v).fromArray(e.position),(new u).setFromEuler((new r).fromArray(e.rotation)),(new v).fromArray(e.scale))}(e,new t.Matrix4));return Promise.all((e.children??[]).map((t=>Ie(t,a,e,n))))}export function toSerializedParamType(e){const t=e.constructor.prototype;return t instanceof Number||e===Number?te.Number:t instanceof I||"function"==typeof e.prototype.isFloat?te.FloatNode:t instanceof y||e===y||e.isTexture?te.Texture:t instanceof re||e===V?te.Sampler2DNode:t instanceof Boolean||e===Boolean?te.Boolean:t instanceof x?te.BooleanNode:t instanceof s||e==s?te.Color:t instanceof E||"function"==typeof e.prototype.isRgb?te.RgbNode:t instanceof w||e==w?te.Vector2:t instanceof z||"function"==typeof e.prototype.isVec2?te.Vec2Node:t instanceof v||e==v?te.Vector3:t instanceof k||"function"==typeof e.prototype.isVec3?te.Vec3Node:t instanceof String||e===String?te.String:t instanceof se||e==se||e.prototype instanceof se||e.prototype==se?te.BaseActor:t instanceof r||e==r?te.Euler:t instanceof p||e==p?te.Object3D:t instanceof c||e==c?te.Material:t instanceof AudioBuffer||e==AudioBuffer?te.AudioBuffer:t instanceof ge||e==ge?te.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=_(e);if(0===s.length)return{};let r;null!=a?pe(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 w:return t instanceof w?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 Pe(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=>De(e.materialId))),(t??[]).filter((e=>De(e.materialId))),(e=>e.color+e.name))}function De(e){return"null"!=e&&null!=e}export const customParameterDefaultValueByType=new Map([[te.RgbNode,"#000000"],[te.Color,"#000000"],[te.Vector4,[0,0,0,0]],[te.Vec4Node,[0,0,0,0]],[te.Vector3,[0,0,0]],[te.Vec3Node,[0,0,0]],[te.Vector2,[0,0]],[te.Vec2Node,[0,0]],[te.Euler,[0,0,0,"XYZ"]]]);
|
2
2
|
/*
|
3
3
|
* Copyright (©) 2023. All rights reserved.
|
4
4
|
* See the LICENSE.md file for details.
|
@@ -7,7 +7,8 @@ export declare class SceneDataService implements SceneDataProvider {
|
|
7
7
|
private removeCallbacks;
|
8
8
|
objectChange: BehaviorSubject<SceneObject[]>;
|
9
9
|
constructor();
|
10
|
-
initiate(data: string
|
10
|
+
initiate(data: string): void;
|
11
|
+
private createDefaultObjects;
|
11
12
|
removeOnUpdateCallback(callback: (sceneObject: SceneObject) => void): void;
|
12
13
|
onUpdate(callback: (sceneObject: SceneObject) => void): void;
|
13
14
|
onRemove(callback: (sceneObject: SceneObject) => void): void;
|
@@ -31,3 +32,5 @@ export declare class SceneDataService implements SceneDataProvider {
|
|
31
32
|
save(): void;
|
32
33
|
serialize(): string;
|
33
34
|
}
|
35
|
+
export declare function createInitialFog(): SceneObject;
|
36
|
+
export declare function createInitialSky(): SceneObject;
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import{BehaviorSubject as t}from"rxjs";import{Matrix4 as e,Vector3 as s,Quaternion as i,Euler as o}from"three";export class SceneDataService{constructor(){this.objects=[],this.callbacks=[],this.removeCallbacks=[],this.objectChange=new t([])}initiate(t
|
1
|
+
import{BehaviorSubject as t}from"rxjs";import{Matrix4 as e,Vector3 as s,Quaternion as i,Euler as o}from"three";export class SceneDataService{constructor(){this.objects=[],this.callbacks=[],this.removeCallbacks=[],this.objectChange=new t([])}initiate(t){this.objects=t?JSON.parse(t)??[]:[],this.objectChange.next(this.objects)}createDefaultObjects(){this.objects.some((t=>"global_fog"===t.type))||this.objects.unshift(createInitialFog());this.objects.some((t=>"sky"===t.type))||this.objects.unshift(createInitialSky())}removeOnUpdateCallback(t){this.callbacks.splice(this.callbacks.indexOf(t),1)}onUpdate(t){this.callbacks.push(t)}onRemove(t){this.removeCallbacks.push(t)}getObjects(){return this.objects}addObject(t){this.objects.push(t),this.callbacks.forEach((e=>e(t))),this.objectChange.next(this.objects)}updateObject(t){const e=this.findObjectById(t.id);e?(Object.assign(e,t),this.callbacks.forEach((e=>e(t)))):this.addObject(t),this.objectChange.next(this.objects)}findObjectById(t){const e=[...this.objects];for(;e.length>0;){const s=e.pop();if(s.id===t)return s;s.children&&e.push(...s.children)}}findAncestorsById(t){const e=this.findParentById(t);return null==e?[]:[e,...this.findAncestorsById(e.id)]}findParentById(t){return this._findParentById(t,this.objects)}_findParentById(t,e,s=null){return e.some((e=>e.id===t))?s:e.filter((t=>null!=t.children)).map((e=>this._findParentById(t,e.children,e))).find((t=>null!=t))}updateParent(t,n){const r=this.findParentById(t.id);{const c=null!=n?this.getMatrixWorld(n).invert():(new e).identity();null!=r&&c.multiply(this.getMatrixWorld(r));const a=this.getLocalMatrix(t),l=c.multiply(a),h=new s,d=new i,b=new s;l.decompose(h,d,b),t.position=h.toArray(),t.rotation=(new o).setFromQuaternion(d).toArray(),t.scale=b.toArray()}this.removeRecursive(t.id,r?.children??this.objects),null!=n?(n.children??=[],n.children.push(t)):this.objects.push(t),this.objectChange.next(this.objects),this.callbacks.forEach((e=>e(t)))}getMatrixWorld(t){const e=this.findAncestorsById(t.id).reverse();e.push(t);const s=this.getLocalMatrix(e.shift());for(const t of e){const e=this.getLocalMatrix(t);s.multiply(e)}return s}getLocalMatrix(t){const n=new e,r=(new s).fromArray(t.position),c=(new i).setFromEuler((new o).fromArray(t.rotation)),a=(new s).fromArray(t.scale);return n.compose(r,c,a),n}removeObject(t){this.removeRecursive(t.id,this.objects),this.removeCallbacks.forEach((e=>e(t))),this.objectChange.next([...this.objects])}removeRecursive(t,e){const s=e.findIndex((e=>e.id===t));if(s>-1)e.splice(s,1);else for(const s of e)this.removeRecursive(t,s.children??[])}save(){}serialize(){return JSON.stringify(this.objects)}}export function createInitialFog(){return{id:"auto-global-fog",name:"Global fog",type:"global_fog",position:[0,0,0],scale:[1,1,1],rotation:[0,0,0],collisionDetection:!1,fog:{type:"density",color:"#b8f8ff",density:.005,near:100,far:1e3}}}export function createInitialSky(){return{id:"auto-sky",name:"Sky",type:"sky",position:[0,0,0],scale:[1,1,1],rotation:[0,0,0],collisionDetection:!1,sky:{materialId:null}}}
|
2
2
|
/*
|
3
3
|
* Copyright (©) 2023. All rights reserved.
|
4
4
|
* See the LICENSE.md file for details.
|