@hology/core 0.0.53 → 0.0.54

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,4 @@
1
- import{__decorate as t}from"tslib";import{ActorComponent as i,Component as e}from"../../../component.js";import{RootMotionClip as s}from"../../../../animation/root-motion.js";import{inject as r}from"../../../../inject.js";import{ViewController as o}from"../../../../services/render.js";import{AnimationMixer as n,Bone as p,LoopOnce as l}from"three";let h=class extends i{constructor(){super(...arguments),this.viewController=r(o),this.stateMachines=[],this.upperStateMachines=[],this.fadeTime=.2,this.movementSpeed=null,this.upperBodyTimer=0,this.upperBodyOverride=!1,this.fullBodyTimer=0,this.currentFullBodyPriority=-1,this.currentUpperBodyPriority=-1,this.getFullBodyClip=a((t=>t.uuid),(t=>u(this.fullBodyMask,t))),this.getUpperBodyClip=a((t=>t.uuid),(t=>u(this.upperBodyMask,t)))}onInit(){this.viewController.onUpdate(this.actor).subscribe((t=>this.updateInternal(t)))}getRootMotionAction(){if(this.fullBodyAction.getClip()instanceof s)return this.fullBodyAction}setup(t,i,e){null!=i&&(this.upperBodyMask=c(i),this.fullBodyMask=function(t,i){const e=new Set(c(i).map((t=>t.uuid))),s=[];return t.traverse((t=>{(t instanceof p||t.isBone)&&!e.has(t.uuid)&&s.push(t)})),s}(function(t){let i;return t.traverse((t=>{(t instanceof p||t.isBone)&&null==i&&(i=t)})),i}(t),i)),null!=this.mixer&&this.mixer.stopAllAction(),this.mixer=new n(t)}updateStateMachines(t){this.stateMachines.forEach((i=>{i.step(t);const e=i.current.clip;null!=e&&this.play(e,{priority:0})})),this.upperStateMachines.forEach((i=>{i.step(t);const e=i.current.clip;null!=e?this.playUpper(e,{priority:0}):this.play(this.fullBodyClip)}))}updateInternal(t){null!=this.mixer&&(this.upperBodyTimer+=t,this.fullBodyTimer+=t,this.upperBodyAction&&this.upperBodyOverride&&this.upperBodyAction.getClip().duration-2*this.fadeTime<this.upperBodyTimer&&(this.upperBodyOverride=!1,null!=this.fullBodyClip&&this.transition(this.upperBodyAction,this.getUpperBodyClip(this.fullBodyClip))),this.fullBodyAction&&this.fullBodyAction.loop===l&&this.fullBodyAction.getClip().duration-2*this.fadeTime<this.fullBodyTimer&&(this.currentFullBodyPriority=-1),this.updateStateMachines(t),this.syncMovementSpeed(this.fullBodyAction),this.upperBodyOverride||this.syncMovementSpeed(this.upperBodyAction),this.mixer.update(t))}syncMovementSpeed(t){if(null!=t){const i=t.getClip();i instanceof s&&i.fixedInPlace&&null!=this.movementSpeed&&(t.timeScale=i.duration/i.displacement*this.movementSpeed)}}playStateMachine(t){this.stateMachines.push(t)}playUpperStateMachine(t){this.upperStateMachines.push(t)}removeStateMachine(t){this.stateMachines.splice(this.stateMachines.indexOf(t))}removeUpperStateMachine(t){this.upperStateMachines.splice(this.upperStateMachines.indexOf(t))}playUpper(t,i={}){const e=i?.priority??1;e<this.currentUpperBodyPriority||(this.currentUpperBodyPriority=e,this.upperBodyAction=this.transition(this.upperBodyAction,this.getUpperBodyClip(t),i),this.upperBodyTimer=0,this.upperBodyOverride=!0)}play(t,i={}){!function(t,i){if(!1===t||"function"==typeof t&&!1===t())throw new Error(i)}(null!=this.mixer,"Can't play animation before setup is called");const e=i.priority??1;e<this.currentFullBodyPriority||(this.currentFullBodyPriority=e,this.fullBodyTimer=0,this.upperBodyOverride||(this.upperBodyAction=this.transition(this.upperBodyAction,this.getUpperBodyClip(t),i)),this.fullBodyClip=t,this.fullBodyAction=this.transition(this.fullBodyAction,this.getFullBodyClip(t),i),this.fullBodyAction.getClip().uuid==this.upperBodyAction.getClip().uuid&&this.upperBodyAction.syncWith(this.fullBodyAction))}onActionDone(t){return new Promise((i=>{const e=s=>{s.action===t&&(i(s.action),this.mixer.removeEventListener("finished",e))};this.mixer.addEventListener("finished",e)}))}transition(t,i,e={}){if(null!=t&&t.getClip().uuid===i.uuid)return t;if(t){const e=t,s=t=this.mixer.clipAction(i);s.play(),s.enabled=!0,s.setEffectiveTimeScale(1),s.setEffectiveWeight(1),s.time=0,e.crossFadeTo(s,this.fadeTime,!0)}else t=this.mixer.clipAction(i),t?.fadeIn(.3),t?.play();return!1===e.loop&&(t.setLoop(l,1),t.clampWhenFinished=!0,t.reset()),t}};h=t([e()],h);export{h as CharacterAnimationComponent};function u(t,i){if(null==t)return i;const e=i.clone(),s=new Set(t.map((t=>t.name)));return e.tracks=e.tracks.filter((t=>s.has(t.name.split(".")[0]))),e}function c(t){return t.flatMap((t=>function(t){const i=[];return t.traverse((t=>{i.push(t)})),i}(t))).filter((t=>t instanceof p))}function a(t,i){const e=new Map;return(s,...r)=>{const o=t(s);return e.has(o)||e.set(o,i(s,...r)),e.get(o)}}
1
+ import{__decorate as t}from"tslib";import{ActorComponent as i,Component as e}from"../../../component.js";import{RootMotionClip as s}from"../../../../animation/root-motion.js";import{inject as r}from"../../../../inject.js";import{ViewController as o}from"../../../../services/render.js";import{AnimationMixer as n,Bone as p,LoopOnce as l}from"three";let h=class extends i{constructor(){super(...arguments),this.viewController=r(o),this.stateMachines=[],this.upperStateMachines=[],this.fadeTime=.2,this.movementSpeed=null,this.upperBodyTimer=0,this.upperBodyOverride=!1,this.fullBodyTimer=0,this.currentFullBodyPriority=-1,this.currentUpperBodyPriority=-1,this.getFullBodyClip=a((t=>t.uuid),(t=>u(this.fullBodyMask,t))),this.getUpperBodyClip=a((t=>t.uuid),(t=>u(this.upperBodyMask,t)))}onInit(){this.viewController.onUpdate(this.actor).subscribe((t=>this.updateInternal(t)))}getRootMotionAction(){if(this.fullBodyAction.getClip()instanceof s)return this.fullBodyAction}setup(t,i,e){null!=i&&(this.upperBodyMask=c(i),this.fullBodyMask=function(t,i){const e=new Set(c(i).map((t=>t.uuid))),s=[];return t.traverse((t=>{(t instanceof p||t.isBone)&&!e.has(t.uuid)&&s.push(t)})),s}(function(t){let i;return t.traverse((t=>{(t instanceof p||t.isBone)&&null==i&&(i=t)})),i}(t),i)),null!=this.mixer&&this.mixer.stopAllAction(),this.mixer=new n(t)}updateStateMachines(t){this.stateMachines.forEach((i=>{i.step(t);const e=i.current.clip;null!=e&&this.play(e,{priority:0})})),this.upperStateMachines.forEach((i=>{i.step(t);const e=i.current.clip;null!=e?this.playUpper(e,{priority:0}):this.play(this.fullBodyClip)}))}updateInternal(t){null!=this.mixer&&(this.upperBodyTimer+=t,this.fullBodyTimer+=t,this.upperBodyAction&&this.upperBodyOverride&&this.upperBodyAction.getClip().duration-2*this.fadeTime<this.upperBodyTimer&&(this.upperBodyOverride=!1,null!=this.fullBodyClip&&this.transition(this.upperBodyAction,this.getUpperBodyClip(this.fullBodyClip))),this.fullBodyAction&&this.fullBodyAction.loop===l&&this.fullBodyAction.getClip().duration-2*this.fadeTime<this.fullBodyTimer&&(this.currentFullBodyPriority=-1),this.updateStateMachines(t),this.syncMovementSpeed(this.fullBodyAction),this.upperBodyOverride||this.syncMovementSpeed(this.upperBodyAction),this.mixer.update(t))}syncMovementSpeed(t){if(null!=t){const i=t.getClip();i instanceof s&&i.fixedInPlace&&null!=this.movementSpeed&&(t.timeScale=i.duration/i.displacement*this.movementSpeed)}}playStateMachine(t){this.stateMachines.push(t)}playUpperStateMachine(t){this.upperStateMachines.push(t)}removeStateMachine(t){const i=this.stateMachines.indexOf(t);i>=0&&this.stateMachines.splice(i,1)}removeUpperStateMachine(t){const i=this.upperStateMachines.indexOf(t);i>=0&&this.upperStateMachines.splice(i,1)}playUpper(t,i={}){const e=i?.priority??1;e<this.currentUpperBodyPriority||(this.currentUpperBodyPriority=e,this.upperBodyAction=this.transition(this.upperBodyAction,this.getUpperBodyClip(t),i),this.upperBodyTimer=0,this.upperBodyOverride=!0)}play(t,i={}){!function(t,i){if(!1===t||"function"==typeof t&&!1===t())throw new Error(i)}(null!=this.mixer,"Can't play animation before setup is called");const e=i.priority??1;e<this.currentFullBodyPriority||(this.currentFullBodyPriority=e,this.fullBodyTimer=0,this.upperBodyOverride||(this.upperBodyAction=this.transition(this.upperBodyAction,this.getUpperBodyClip(t),i)),this.fullBodyClip=t,this.fullBodyAction=this.transition(this.fullBodyAction,this.getFullBodyClip(t),i),this.fullBodyAction.getClip().uuid==this.upperBodyAction.getClip().uuid&&this.upperBodyAction.syncWith(this.fullBodyAction))}onActionDone(t){return new Promise((i=>{const e=s=>{s.action===t&&(i(s.action),this.mixer.removeEventListener("finished",e))};this.mixer.addEventListener("finished",e)}))}transition(t,i,e={}){if(null!=t&&t.getClip().uuid===i.uuid)return t;if(t){const e=t,s=t=this.mixer.clipAction(i);s.play(),s.enabled=!0,s.setEffectiveTimeScale(1),s.setEffectiveWeight(1),s.time=0,e.crossFadeTo(s,this.fadeTime,!0)}else t=this.mixer.clipAction(i),t?.fadeIn(.3),t?.play();return!1===e.loop&&(t.setLoop(l,1),t.clampWhenFinished=!0,t.reset()),t}};h=t([e()],h);export{h as CharacterAnimationComponent};function u(t,i){if(null==t)return i;const e=i.clone(),s=new Set(t.map((t=>t.name)));return e.tracks=e.tracks.filter((t=>s.has(t.name.split(".")[0]))),e}function c(t){return t.flatMap((t=>function(t){const i=[];return t.traverse((t=>{i.push(t)})),i}(t))).filter((t=>t instanceof p))}function a(t,i){const e=new Map;return(s,...r)=>{const o=t(s);return e.has(o)||e.set(o,i(s,...r)),e.get(o)}}
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -1,4 +1,4 @@
1
- import{init as t}from"recast-navigation";import{buildTile as e}from"./build-tile.js";let s=!1;const a=[];self.onmessage=t=>{s?o(t.data):a.push(t.data)};const o=t=>{const s=e(t);if(!s.success||!s.data)return;const a=s.data.toTypedArray();s.data.destroy(),self.postMessage({tileX:t.tileX,tileY:t.tileY,navMeshData:a},[a.buffer])};t().then((()=>{s=!0;for(const t of a)o(t)}));
1
+ import{init as t}from"recast-navigation";import{buildTile as s}from"./build-tile.js";let a=!1;const e=[];self.onmessage=t=>{a?o(t.data):e.push(t.data)};const o=t=>{const a=s(t);if(!a.success||!a.data)return;const e=a.data.toTypedArray();a.data.destroy(),self.postMessage({tileX:t.tileX,tileY:t.tileY,navMeshData:e},[e.buffer])};t().then((()=>{a=!0;for(const t of e)o(t)}));
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 i}from"tslib";import{Service as e}from"typedi";import{ActorFactory as s}from"../actors/factory.js";import{Vector3 as o}from"three";import{ActorComponent as r}from"../../gameplay/actors/component.js";import{Subject as n}from"rxjs";import{RenderingView as c}from"../../rendering.js";const a=new o;class h{constructor(t){this.view=t}get direction(){return this.view.csm.lightDirection}set intensity(t){this.view.csm.lightIntensity=t,this.view.csm.lights.forEach((t=>t.intensity=this.view.csm.lightIntensity))}get intensity(){return this.view.csm.lightIntensity}get position(){return 0==this.view.csm.lights.length?a:this.view.csm.lights[0].position}}let m=class{constructor(t,i){this.actorFactory=t,this.view=i,this.actors=[],this.actorAdded=new n,this.actorRemoved=new n,this.directionalLight=new h(this.view)}async spawnActor(t,i,e){const s=await this.actorFactory.create(t,i,e);return this.addActor(s,i,e),s}addActor(t,i,e){i&&t.object.position.copy(i),e&&t.object.rotation.copy(e),this.scene.add(t.object),this.actors.push(t),d(t,(t=>t.onBeginPlay())),this.actorAdded.next(t)}removeActor(t){d(t,(t=>t.onEndPlay())),this.actors.splice(this.actors.indexOf(t),1),this.scene.remove(t.object),t.disposed.next(!0),this.actorRemoved.next(t)}findActorByType(t,i){return this.actors.find((e=>e instanceof t&&(null==i||e.object.name==i)))}findActorsByType(t,i){return this.actors.filter((e=>e instanceof t&&(null==i||e.object.name==i)))}};m=t([e(),i("design:paramtypes",[s,c])],m);export{m as World};function d(t,i){return i(t),Object.entries(t).filter((([t,i])=>i instanceof r)).forEach((([t,e])=>{d(e,i)}))}
1
+ import{__decorate as t,__metadata as i}from"tslib";import{Service as e}from"typedi";import{ActorFactory as s}from"../actors/factory.js";import{Vector3 as o}from"three";import{ActorComponent as r}from"../../gameplay/actors/component.js";import{Subject as n}from"rxjs";import{RenderingView as c}from"../../rendering.js";const a=new o;class h{constructor(t){this.view=t}get direction(){return this.view.csm.lightDirection}set intensity(t){this.view.csm.lightIntensity=t,this.view.csm.lights.forEach((t=>t.intensity=this.view.csm.lightIntensity))}get intensity(){return this.view.csm.lightIntensity}get position(){return 0==this.view.csm.lights.length?a:this.view.csm.lights[0].position}}let m=class{constructor(t,i){this.actorFactory=t,this.view=i,this.actors=[],this.actorAdded=new n,this.actorRemoved=new n,this.directionalLight=new h(this.view)}async spawnActor(t,i,e){const s=await this.actorFactory.create(t,i,e);return this.addActor(s,i,e),s}addActor(t,i,e){i&&t.object.position.copy(i),e&&t.object.rotation.copy(e),this.scene.add(t.object),this.actors.push(t),d(t,(t=>t.onBeginPlay())),this.actorAdded.next(t)}removeActor(t){d(t,(t=>t.onEndPlay()));const i=this.actors.indexOf(t);i>=0&&this.actors.splice(i,1),this.scene.remove(t.object),t.disposed.next(!0),this.actorRemoved.next(t)}findActorByType(t,i){return this.actors.find((e=>e instanceof t&&(null==i||e.object.name==i)))}findActorsByType(t,i){return this.actors.filter((e=>e instanceof t&&(null==i||e.object.name==i)))}};m=t([e(),i("design:paramtypes",[s,c])],m);export{m as World};function d(t,i){return i(t),Object.entries(t).filter((([t,i])=>i instanceof r)).forEach((([t,e])=>{d(e,i)}))}
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
package/dist/rendering.js CHANGED
@@ -1,4 +1,4 @@
1
- var e;import{__decorate as t,__metadata as i}from"tslib";import*as s from"three";import{Mesh as r,Matrix4 as n,ShaderMaterial as a,Color as o,PerspectiveCamera as h,ShaderChunk as l}from"three";import{EffectComposer as d,UnrealBloomPass as c,VRButton as m}from"three-stdlib";import{RenderPass as p}from"three-stdlib";import{ShaderPass as u}from"three-stdlib";import{FXAAShader as g}from"three-stdlib";import{CSMShader as f,CSMUtil as v}from"./csm.js";import{GammaCorrectionShader as w}from"three-stdlib";import{Reflector as x}from"three-stdlib";import{depthUniformName as b,resolutionUniformName as C,supportsDepthTextureExtension as P,nearUniformName as S,farUniformName as R}from"./shader-nodes/depth.js";import{elapsedTimeUniformName as M}from"./shader-nodes/time.js";import{OutlinePass as y}from"./utils/three/outline-pass.js";import T from"./utils/three/stats.js";import{findFirstVisibleObject as W}from"./utils/three/traverse.js";import{DepthPass as L}from"./utils/three/depth-pass.js";import{Service as E}from"typedi";import{CSM as H}from"three/examples/jsm/csm/CSM.js";import{GPUStatsPanel as B}from"three/examples/jsm/utils/GPUStatsPanel.js";(new s.Layers).set(9);const D=new s.MeshBasicMaterial({color:"black"}),F=new s.MeshDepthMaterial;F.depthPacking=s.RGBADepthPacking,F.blending=s.NoBlending,l.lights_pars_begin=f.lights_pars_begin(5);const j=/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);let z=e=class{setPaused(e){this.paused=e}resizeRender(){this.previousClientWith===this.container.clientWidth&&this.previousClientHeight===this.container.clientHeight||(this.previousClientWith=this.container.clientWidth,this.previousClientHeight=this.container.clientHeight,this.camera instanceof h&&(this.camera.aspect=this.container.clientWidth/this.container.clientHeight,this.camera.updateProjectionMatrix()),this.renderer.setPixelRatio(Math.min(this.maxPixelRatio,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))}constructor(t,i={}){this.container=t,this.options=i,this.windowVisible=!0,this.running=!0,this.paused=!1,this.fpsCap=null,this.resolutionScale=j?.5:1,this.maxPixelRatio=j?1:window.devicePixelRatio,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 o,this.hadBloom=!1,this.bloomStoredMaterials={},null!=i.maxPixelRatio&&(this.maxPixelRatio=i.maxPixelRatio),window.renderer=this.renderer=new s.WebGLRenderer({antialias:!0,powerPreference:"high-performance"}),this.scene=new s.Scene,this.renderer.setPixelRatio(Math.min(this.maxPixelRatio,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(m.createButton(this.renderer)),this.composer=new d(this.renderer);var r=t.clientWidth/t.clientHeight;const n=new s.PerspectiveCamera(45,r,.5,800);n.layers.enable(19),this.setCamera(n),this.renderer.shadowMap.enabled=!0,this.renderer.shadowMap.type=s.PCFSoftShadowMap,this.renderer.shadowMap.autoUpdate=!1,this.renderer.outputColorSpace=s.SRGBColorSpace,this.renderer.toneMapping=s.NoToneMapping,this.renderer.toneMappingExposure=1,this.renderer.gammaFactor=1.4,v.renderingView=this,v.patchThreeAdd(),this.isDepthTextureExtensionSupported=P(this.renderer),t.replaceChildren(this.renderer.domElement),this.setupEventListeners(),this.depthRenderTarget=e.createDepthRenderTarget(this.renderer,this.container);const a=new p(this.scene,this.camera);this.composer.addPass(a);const h=new c(new s.Vector2(t.clientWidth,t.clientHeight),1.5,.4,.85);h.threshold=0,h.strength=.9,h.radius=1,this.renderer.info.autoReset=!1;const l=new d(this.renderer);l.renderToScreen=!1,l.addPass(a),l.addPass(h),this.bloomComposer=l;const f=new u(new s.ShaderMaterial({uniforms:{baseTexture:{value:null},bloomTexture:{value:l.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 y(new s.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 u(g);e.uniforms.resolution.value.set(1/t.clientWidth,1/t.clientHeight),this.composer.addPass(e)}var x=new u(w);x.clear=!1,this.composer.addPass(x)}setCamera(e){this.camera=e,this.composer.passes.forEach((t=>{t instanceof p?t.camera=e:t instanceof y?t.renderCamera=e:t instanceof L&&(t.camera=e)})),null==this.csm?this.csm=new H({maxFar:250,lightFar:250,lightMargin:20,cascades:4,shadowMapSize:2048,lightDirection:new s.Vector3(.5,-1,-.6).normalize(),lightIntensity:.5*Math.PI,camera:this.camera,parent:this.scene,mode:"logarithmic"}):(this.csm.camera=this.camera,this.camera instanceof h&&(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(e,t){var i=!!e.extensions.get("WEBGL_depth_texture");const r=new s.WebGLRenderTarget(t.clientWidth*e.getPixelRatio(),t.clientHeight*e.getPixelRatio());return r.texture.minFilter=s.NearestFilter,r.texture.magFilter=s.NearestFilter,r.texture.generateMipmaps=!1,r.stencilBuffer=!1,!0===i&&(r.depthTexture=new s.DepthTexture(128,128),r.depthTexture.type=s.UnsignedShortType,r.depthTexture.minFilter=s.NearestFilter,r.depthTexture.magFilter=s.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(e,t=!1){const i=this.stats,a=i.addPanel(new T.Panel("Calls","#83f","#002"));let o;navigator.userAgent.includes("Chrome")&&navigator.userAgent.includes("HologyEngine")&&(o=new B(this.renderer.getContext()),i.addPanel(o)),i.showPanel(0),this.showStats=t;let h=10;const l=()=>{const e=this.renderer.info.render.calls;e>h&&(h=e,setTimeout((()=>h=10),5e3)),a.update(e,h)};performance.now();s.Ray.prototype.intersectTriangle;let d=0;const c=new n,m=new n,p=t=>{const s=this.renderer.getContext();if(this.paused&&this.running&&s.drawingBufferHeight>1)return void setTimeout((()=>p(t)),500);this.renderer.autoClear=!1,this.renderer.clear(),this.renderer.setViewport(0,0,this.container.clientWidth,this.container.clientHeight),this.camera,i.begin();let n=(t*=.001)-d;if(d=t,c.copy(this.camera.matrixWorld),n>1){let t=n;for(;t>.05;)e(O),t-=O;e(t)}else e(n);this.onLoopCallbacks.forEach((e=>e(n))),this.camera?.updateMatrixWorld(),m.copy(this.camera.matrixWorld),m.equals(c)||(this.renderer.shadowMap.needsUpdate=!0),this.resizeRender();const a=[],h=[];if(this.scene.traverse((e=>{e instanceof r&&e.visible&&(e.material?.userData?.water||e.material?.uniforms&&null!=e.material?.uniforms[b])?(e.visible=!1,a.push(e),this.initDepthUniform(e.material),e.renderOrder=100):e instanceof x&&(e.visible=!1,h.push(e)),e instanceof r&&e.material?.uniforms&&null!=e.material?.uniforms[M]&&(e.material.uniforms[M].value=t)})),a.length>0){if(this.scene.overrideMaterial=F,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}a.forEach((e=>e.visible=!0)),h.forEach((e=>e.visible=!0));try{!this.paused&&this.running&&(o?.startQuery(),this.render(n),o?.endQuery(),this.showStats&&l(),this.renderer.info.reset(),this.renderOverlay())}catch(e){console.warn(e)}i.end(),this.csm?.update(),this.running&&!0!==this.options.enableXR&&(this.fpsCap?setTimeout((()=>{requestAnimationFrame(p)}),1e3/this.fpsCap):requestAnimationFrame(p))};!0===this.options.enableXR?this.renderer.setAnimationLoop(p):requestAnimationFrame(p)}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){const t=this.hasBloom();if(t||this.hadBloom){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.hadBloom=t,this.composer.render(e)}hasBloom(){return null!=W(this.scene,(e=>e instanceof r&&!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=D: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 a&&(e.uniforms[b].value=this.isDepthTextureExtensionSupported?this.depthRenderTarget.depthTexture:this.depthRenderTarget.texture,null!=e.uniforms[C]&&e.uniforms[C].value.set(this.container.clientWidth*this.renderer.getPixelRatio(),this.container.clientHeight*this.renderer.getPixelRatio()),this.camera instanceof h&&(e.uniforms[S].value=this.camera.near,e.uniforms[R].value=this.camera.far))}};z=e=t([E(),i("design:paramtypes",[HTMLElement,Object])],z);export{z as RenderingView};export function setRenderingPaused(e){null!=window.editor?.viewer?.renderingView&&(window.editor.viewer.renderingView.paused=e)}const O=.05;
1
+ var e;import{__decorate as t,__metadata as i}from"tslib";import*as s from"three";import{Mesh as r,Matrix4 as n,Material as a,ShaderMaterial as o,Color as h,PerspectiveCamera as l,ShaderChunk as d}from"three";import{EffectComposer as c,UnrealBloomPass as m,VRButton as p}from"three-stdlib";import{RenderPass as u}from"three-stdlib";import{ShaderPass as g}from"three-stdlib";import{FXAAShader as f}from"three-stdlib";import{CSMShader as v,CSMUtil as w}from"./csm.js";import{GammaCorrectionShader as x}from"three-stdlib";import{Reflector as b}from"three-stdlib";import{depthUniformName as C,resolutionUniformName as P,supportsDepthTextureExtension as S,nearUniformName as R,farUniformName as M}from"./shader-nodes/depth.js";import{elapsedTimeUniformName as y}from"./shader-nodes/time.js";import{OutlinePass as T}from"./utils/three/outline-pass.js";import W from"./utils/three/stats.js";import{findFirstVisibleObject as L}from"./utils/three/traverse.js";import{DepthPass as E}from"./utils/three/depth-pass.js";import{Service as H}from"typedi";import{CSM as B}from"three/examples/jsm/csm/CSM.js";import{GPUStatsPanel as D}from"three/examples/jsm/utils/GPUStatsPanel.js";(new s.Layers).set(9);const F=new s.MeshBasicMaterial({color:"black"}),j=new s.MeshDepthMaterial;j.depthPacking=s.RGBADepthPacking,j.blending=s.NoBlending,d.lights_pars_begin=v.lights_pars_begin(5);const V=/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);let z=e=class{setPaused(e){this.paused=e}resizeRender(){this.previousClientWith===this.container.clientWidth&&this.previousClientHeight===this.container.clientHeight||(this.previousClientWith=this.container.clientWidth,this.previousClientHeight=this.container.clientHeight,this.camera instanceof l&&(this.camera.aspect=this.container.clientWidth/this.container.clientHeight,this.camera.updateProjectionMatrix()),this.renderer.setPixelRatio(Math.min(this.maxPixelRatio,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))}constructor(t,i={}){this.container=t,this.options=i,this.windowVisible=!0,this.running=!0,this.paused=!1,this.fpsCap=null,this.resolutionScale=V?.5:1,this.maxPixelRatio=V?1:window.devicePixelRatio,this.onResize=()=>{this.resizeRender(),this.paused||this.render()},this.onVisiblityChane=()=>{this.windowVisible=!document.hidden},this.isDepthTextureExtensionSupported=!1,this.onLoopCallbacks=[],this.stats=W(),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 h,this.hadBloom=!1,this.bloomStoredMaterials={},null!=i.maxPixelRatio&&(this.maxPixelRatio=i.maxPixelRatio),window.renderer=this.renderer=new s.WebGLRenderer({antialias:!0,powerPreference:"high-performance"}),this.scene=new s.Scene,this.renderer.setPixelRatio(Math.min(this.maxPixelRatio,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(p.createButton(this.renderer)),this.composer=new c(this.renderer);var r=t.clientWidth/t.clientHeight;const n=new s.PerspectiveCamera(45,r,.5,800);n.layers.enable(19),this.setCamera(n),this.renderer.shadowMap.enabled=!0,this.renderer.shadowMap.type=s.PCFSoftShadowMap,this.renderer.shadowMap.autoUpdate=!1,this.renderer.outputColorSpace=s.SRGBColorSpace,this.renderer.toneMapping=s.NoToneMapping,this.renderer.toneMappingExposure=1,this.renderer.gammaFactor=1.4,w.renderingView=this,w.patchThreeAdd(),this.isDepthTextureExtensionSupported=S(this.renderer),t.replaceChildren(this.renderer.domElement),this.setupEventListeners(),this.depthRenderTarget=e.createDepthRenderTarget(this.renderer,this.container);const a=new u(this.scene,this.camera);this.composer.addPass(a);const o=new m(new s.Vector2(t.clientWidth,t.clientHeight),1.5,.4,.85);o.threshold=0,o.strength=.9,o.radius=1,this.renderer.info.autoReset=!1;const l=new c(this.renderer);l.renderToScreen=!1,l.addPass(a),l.addPass(o),this.bloomComposer=l;const d=new g(new s.ShaderMaterial({uniforms:{baseTexture:{value:null},bloomTexture:{value:l.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(d.needsSwap=!0,this.composer.addPass(d),this.outlinePass=new T(new s.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 g(f);e.uniforms.resolution.value.set(1/t.clientWidth,1/t.clientHeight),this.composer.addPass(e)}var v=new g(x);v.clear=!1,this.composer.addPass(v)}setCamera(e){this.camera=e,this.composer.passes.forEach((t=>{t instanceof u?t.camera=e:t instanceof T?t.renderCamera=e:t instanceof E&&(t.camera=e)})),null==this.csm?this.csm=new B({maxFar:250,lightFar:250,lightMargin:20,cascades:4,shadowMapSize:2048,lightDirection:new s.Vector3(.5,-1,-.6).normalize(),lightIntensity:.5*Math.PI,camera:this.camera,parent:this.scene,mode:"logarithmic"}):(this.csm.camera=this.camera,this.camera instanceof l&&(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(e,t){var i=!!e.extensions.get("WEBGL_depth_texture");const r=new s.WebGLRenderTarget(t.clientWidth*e.getPixelRatio(),t.clientHeight*e.getPixelRatio());return r.texture.minFilter=s.NearestFilter,r.texture.magFilter=s.NearestFilter,r.texture.generateMipmaps=!1,r.stencilBuffer=!1,!0===i&&(r.depthTexture=new s.DepthTexture(128,128),r.depthTexture.type=s.UnsignedShortType,r.depthTexture.minFilter=s.NearestFilter,r.depthTexture.magFilter=s.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);t>=0&&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(e,t=!1){const i=this.stats,o=i.addPanel(new W.Panel("Calls","#83f","#002"));let h;navigator.userAgent.includes("Chrome")&&navigator.userAgent.includes("HologyEngine")&&(h=new D(this.renderer.getContext()),i.addPanel(h)),i.showPanel(0),this.showStats=t;let l=10;const d=()=>{const e=this.renderer.info.render.calls;e>l&&(l=e,setTimeout((()=>l=10),5e3)),o.update(e,l)};performance.now();s.Ray.prototype.intersectTriangle;const c=[],m=[];let p=0;const u=new n,g=new n,f=t=>{const s=this.renderer.getContext();if(this.paused&&this.running&&s.drawingBufferHeight>1)return void setTimeout((()=>f(t)),500);this.renderer.autoClear=!1,this.renderer.clear(),this.renderer.setViewport(0,0,this.container.clientWidth,this.container.clientHeight),this.camera,i.begin();let n=(t*=.001)-p;if(p=t,u.copy(this.camera.matrixWorld),n>1){let t=n;for(;t>.05;)e(O),t-=O;e(t)}else e(n);if(this.onLoopCallbacks.forEach((e=>e(n))),this.camera?.updateMatrixWorld(),g.copy(this.camera.matrixWorld),g.equals(u)||(this.renderer.shadowMap.needsUpdate=!0),this.resizeRender(),c.length=0,m.length=0,this.scene.traverseVisible((e=>{e instanceof r&&e.visible&&(e.material?.userData?.water||e.material?.uniforms&&null!=e.material?.uniforms[C])?(e.visible=!1,c.push(e),this.initDepthUniform(e.material),e.renderOrder=100):(e instanceof b||e instanceof r&&function(e){if(e.material instanceof a)return e.material.transparent||e.material.alphaTest>0;if(Array.isArray(e.material))for(const t of e.material)if(t.transparent||t.alphaTest>0)return!0}(e))&&(e.visible=!1,m.push(e)),e instanceof r&&e.material?.uniforms&&null!=e.material?.uniforms[y]&&(e.material.uniforms[y].value=t)})),c.length>0){if(this.scene.overrideMaterial=j,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}c.forEach((e=>e.visible=!0)),m.forEach((e=>e.visible=!0));try{!this.paused&&this.running&&(h?.startQuery(),this.render(n),h?.endQuery(),this.showStats&&d(),this.renderer.info.reset(),this.renderOverlay())}catch(e){console.warn(e)}i.end(),this.csm?.update(),this.running&&!0!==this.options.enableXR&&(this.fpsCap?setTimeout((()=>{requestAnimationFrame(f)}),1e3/this.fpsCap):requestAnimationFrame(f))};!0===this.options.enableXR?this.renderer.setAnimationLoop(f):requestAnimationFrame(f)}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){const t=this.hasBloom();if(t||this.hadBloom){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.hadBloom=t,this.composer.render(e)}hasBloom(){return null!=L(this.scene,(e=>e instanceof r&&!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=F: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 o&&(e.uniforms[C].value=this.isDepthTextureExtensionSupported?this.depthRenderTarget.depthTexture:this.depthRenderTarget.texture,null!=e.uniforms[P]&&e.uniforms[P].value.set(this.container.clientWidth*this.renderer.getPixelRatio(),this.container.clientHeight*this.renderer.getPixelRatio()),this.camera instanceof l&&(e.uniforms[R].value=this.camera.near,e.uniforms[M].value=this.camera.far))}};z=e=t([H(),i("design:paramtypes",[HTMLElement,Object])],z);export{z as RenderingView};export function setRenderingPaused(e){null!=window.editor?.viewer?.renderingView&&(window.editor.viewer.renderingView.paused=e)}const O=.05;
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -12,6 +12,7 @@ export declare class AssetResourceLoader {
12
12
  private fbxLoader;
13
13
  private objLoader;
14
14
  private textureLoader;
15
+ private _textureLoader;
15
16
  private audioLoader;
16
17
  protected onError(error: unknown): void;
17
18
  private makeReady;
@@ -1,4 +1,4 @@
1
- import{AudioLoader as e,Group as t,LoadingManager as a,Mesh as s,Object3D as i,TextureLoader as r}from"three";import{GLTFLoader as n,MTLLoader as o,OBJLoader as h}from"three-stdlib";import{FBXLoader as c}from"three-stdlib";import{cloneMesh as l}from"../utils/mesh.js";import{pathJoin as d}from"../utils/files.js";import{Subject as p,firstValueFrom as m}from"rxjs";import{importCollisionShapes as f}from"./collision/collision-shape-import.js";import*as u from"three";import{iterateMaterials as g}from"../utils/materials.js";const w=["glb","gltf","fbx","obj"];export class AssetResourceLoader{onError(e){console.error(e)}constructor(){this.cache=new Map,this.textureCache=new Map,this.loadingManager=new a,this.glbLoader=new n(this.loadingManager),this.fbxLoader=new c(this.loadingManager),this.objLoader=new h(this.loadingManager),this.textureLoader=new r(this.loadingManager),this.audioLoader=new e(this.loadingManager),this.makeReady=new p,this.ready=m(this.makeReady),this.collisionShapeCache=new Map}setDataDir(e){this.basePath=d(e,"asset-resources"),this.makeReady.next(!0)}getUri(e){return d(this.basePath,e)+`?windowId=${getElectronArg("windowId")}`}async getTexture(e){return null==e?null:(await this.ready,this.cache.has(e.id)||await this.textureLoader.loadAsync(this.getUri(e.fileKey)).then((t=>(t.wrapS=L(e.texture?.wrapS),t.wrapT=L(e.texture?.wrapT),t.flipY=e.texture?.flipY??!0,this.textureCache.set(e.id,t),t))),this.textureCache.get(e.id))}async getMesh(e){if(await this.ready,!w.includes(e.fileFormat?.toLowerCase()))return console.error("Unsupported mesh file format "+e.fileFormat,e),{scene:new t,animations:[]};if(!this.cache.has(e.fileKey))try{this.cache.set(e.fileKey,await this.loadMesh(e))}catch(e){return this.onError(e),{scene:new t,animations:[]}}const a=l(this.cache.get(e.fileKey).scene),i=this.cache.get(e.fileKey).animations;a.traverse((e=>{e instanceof s&&e.material instanceof Array&&(e.material=e.material.slice())}));const r=this.computeCollisionShapes(e,a),n=new AssetMeshInstance;n.add(a),n.collisionShapes=r,n.animations=i;const o=!!e.receiveShadow??!0,h=!!e.castShadow??!1;return a.traverse((e=>{e.castShadow=h,e.receiveShadow=o})),{scene:n,animations:i}}async getAudio(e){return await this.ready,this.audioLoader.loadAsync(this.getUri(e.fileKey))}computeCollisionShapes(e,t){const a=e.id+e.mesh?.collisions?.shapeType;return this.collisionShapeCache.has(a)||this.collisionShapeCache.set(a,f(t,e)),this.collisionShapeCache.get(a)}async loadMesh(e){return await this.ready,await this.loadByAsset(e).then((e=>(e.scene=function(e,t){let a=!1;if(t.traverseVisible((e=>{b.test(e.name)&&(a=!0)})),!a)return t;const s=new u.LOD,i=[t];for(;i.length>0;){const e=i.shift(),t=e.name.match(b);if(null!=t){const a=parseInt(t[1]);0===a?s.addLevel(e,0):console.warn(`Skipping LOD level ${a} for now as LOD is not fully supported`)}else i.push(...e.children)}return s}(0,e.scene),e)))}async loadByAsset(e){const t=this.getUri(e.fileKey);switch(e.fileFormat){case"glb":case"gltf":return this.glbLoader.loadAsync(t).then((e=>({scene:e.scene,animations:e.animations})));case"fbx":return this.fbxLoader.loadAsync(t).then((e=>({scene:e,animations:e.animations})));case"obj":if(null!=e.materialLib){const t=new o;t.materialOptions={normalizeRGB:!1};const a=await t.loadAsync(this.getUri(e.materialLib));this.objLoader.setMaterials(a)}return this.objLoader.loadAsync(t).then((e=>(y(e),e))).then((e=>({scene:e,animations:e.animations})))}}}function y(e){if(e instanceof s)for(const t of g(e.material))t instanceof u.MeshPhongMaterial&&!t.color.isLinear&&(t.color.isLinear=!0);e.children?.forEach(y)}export class AssetMeshInstance extends i{}export function getElectronArg(e){const t=`--${e}=`,a=window.process?.argv.find((e=>e.startsWith(t)));return a?.substring(t.length)}function L(e){switch(e){case"clamp":return u.ClampToEdgeWrapping;case"repeat":return u.RepeatWrapping;case"mirror":return u.MirroredRepeatWrapping}return u.RepeatWrapping}const b=/_LOD(\d+)$/;
1
+ import{AudioLoader as e,Group as t,LoadingManager as a,Mesh as s,Object3D as i,TextureLoader as r}from"three";import{GLTFLoader as n,MTLLoader as o,OBJLoader as h}from"three-stdlib";import{FBXLoader as c}from"three-stdlib";import{cloneMesh as l}from"../utils/mesh.js";import{pathJoin as d}from"../utils/files.js";import{Subject as m,firstValueFrom as p}from"rxjs";import{importCollisionShapes as u}from"./collision/collision-shape-import.js";import*as f from"three";import{iterateMaterials as g}from"../utils/materials.js";const w=["glb","gltf","fbx","obj"];export class AssetResourceLoader{onError(e){console.error(e)}constructor(){this.cache=new Map,this.textureCache=new Map,this.loadingManager=new a,this.glbLoader=new n(this.loadingManager),this.fbxLoader=new c(this.loadingManager),this.objLoader=new h(this.loadingManager),this.textureLoader=new r(this.loadingManager),this._textureLoader=new f.ImageBitmapLoader(this.loadingManager),this.audioLoader=new e(this.loadingManager),this.makeReady=new m,this.ready=p(this.makeReady),this.collisionShapeCache=new Map}setDataDir(e){this.basePath=d(e,"asset-resources"),this.makeReady.next(!0)}getUri(e){return d(this.basePath,e)+`?windowId=${getElectronArg("windowId")}`}async getTexture(e){return null==e?null:(await this.ready,this.textureCache.has(e.id)||await this.textureLoader.loadAsync(this.getUri(e.fileKey)).then((t=>(t.wrapS=L(e.texture?.wrapS),t.wrapT=L(e.texture?.wrapT),t.flipY=e.texture?.flipY??!0,this.textureCache.set(e.id,t),t))),this.textureCache.get(e.id))}async getMesh(e){if(await this.ready,!w.includes(e.fileFormat?.toLowerCase()))return console.error("Unsupported mesh file format "+e.fileFormat,e),{scene:new t,animations:[]};if(!this.cache.has(e.fileKey))try{this.cache.set(e.fileKey,await this.loadMesh(e))}catch(e){return this.onError(e),{scene:new t,animations:[]}}const a=l(this.cache.get(e.fileKey).scene),i=this.cache.get(e.fileKey).animations;a.traverse((e=>{e instanceof s&&e.material instanceof Array&&(e.material=e.material.slice())}));const r=this.computeCollisionShapes(e,a),n=new AssetMeshInstance;n.add(a),n.collisionShapes=r,n.animations=i;const o=!!e.receiveShadow??!0,h=!!e.castShadow??!1;return a.traverse((e=>{e.castShadow=h,e.receiveShadow=o})),{scene:n,animations:i}}async getAudio(e){return await this.ready,this.audioLoader.loadAsync(this.getUri(e.fileKey))}computeCollisionShapes(e,t){const a=e.id+e.mesh?.collisions?.shapeType;return this.collisionShapeCache.has(a)||this.collisionShapeCache.set(a,u(t,e)),this.collisionShapeCache.get(a)}async loadMesh(e){return await this.ready,await this.loadByAsset(e).then((e=>(e.scene=function(e,t){let a=!1;if(t.traverseVisible((e=>{b.test(e.name)&&(a=!0)})),!a)return t;const s=new f.LOD,i=[t];for(;i.length>0;){const e=i.shift(),t=e.name.match(b);if(null!=t){const a=parseInt(t[1]);0===a?s.addLevel(e,0):console.warn(`Skipping LOD level ${a} for now as LOD is not fully supported`)}else i.push(...e.children)}return s}(0,e.scene),e)))}async loadByAsset(e){const t=this.getUri(e.fileKey);switch(e.fileFormat){case"glb":case"gltf":return this.glbLoader.loadAsync(t).then((e=>({scene:e.scene,animations:e.animations})));case"fbx":return this.fbxLoader.loadAsync(t).then((e=>({scene:e,animations:e.animations})));case"obj":if(null!=e.materialLib){const t=new o;t.materialOptions={normalizeRGB:!1};const a=await t.loadAsync(this.getUri(e.materialLib));this.objLoader.setMaterials(a)}return this.objLoader.loadAsync(t).then((e=>(y(e),e))).then((e=>({scene:e,animations:e.animations})))}}}function y(e){if(e instanceof s)for(const t of g(e.material))t instanceof f.MeshPhongMaterial&&!t.color.isLinear&&(t.color.isLinear=!0);e.children?.forEach(y)}export class AssetMeshInstance extends i{}export function getElectronArg(e){const t=`--${e}=`,a=window.process?.argv.find((e=>e.startsWith(t)));return a?.substring(t.length)}function L(e){switch(e){case"clamp":return f.ClampToEdgeWrapping;case"repeat":return f.RepeatWrapping;case"mirror":return f.MirroredRepeatWrapping}return f.RepeatWrapping}const b=/_LOD(\d+)$/;
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -20,6 +20,7 @@ export declare class LandscapeManager {
20
20
  private loadedScatterSquares;
21
21
  private refreshRequests;
22
22
  private defaultLandscapeMaterial;
23
+ private scatterMeshPool;
23
24
  private onLoopHandler;
24
25
  constructor(source: SceneObject, view: RenderingView, landscape: LandscapeGroup, assetManagerService: AssetResourceLoader, assetService: AssetsProvider, shaders: ShaderImpl[], applyMaterial: (object: Mesh) => void);
25
26
  updateShaders(shaders: ShaderImpl[]): void;
@@ -1,4 +1,4 @@
1
- import{materialFromAsset as e}from"../../scene/materializer.js";import{Mesh as t,PlaneGeometry as s,Vector3 as n,InstancedMesh as a,Matrix4 as o,Vector2 as i,Triangle as r,Box3 as c,MathUtils as l,MeshStandardMaterial as h,ShaderMaterial as u,PerspectiveCamera as f}from"three";import{indexBy as d}from"../../utils/collections.js";import{smoothNormalsCrossMeshes as p}from"./utils.js";import{defaultLandscapeMaterial as m,LandscapeMesh as w}from"./landscape.js";import{meanVectors3withWeight as y,clamp as M}from"../../utils/math.js";import{whenIdle as g}from"../../utils/async.js";import{Subject as x,debounceTime as b}from"rxjs";new n,new n;const S=new n,v=new n,A=new n;export class LandscapeManager{constructor(e,t,s,a,i,r,c){this.source=e,this.view=t,this.landscape=s,this.assetManagerService=a,this.assetService=i,this.shaders=r,this.applyMaterial=c,this.scatterMeshes=new Map,this.loadedScatterSquares=new Set,this.refreshRequests=new x,this.defaultLandscapeMaterial=m.clone(),this.onLoopHandler=()=>this.update(),this.sectionCache=new Map,this._matrix=new o,this.scatterGeometryCache=new Map,this._lastUpdatePosition=new n,this._cameraPosition=new n,this.view.onLoop(this.onLoopHandler),this.defaultLandscapeMaterial.name=m.name,this.defaultLandscapeMaterial.color=m.color,this.refreshRequests.pipe(b(500)).subscribe((e=>this.refreshScatter(e.origin,e.force,e.predicate)))}updateShaders(e){this.shaders=e}async loadGrass(){const e=await this.assetService.getAsset("6ij937n72g");await this.assetManagerService.getMesh(e);this.grassGeometry=new s(2,2,3,3);const t=this.grassGeometry.getAttribute("normal");for(let e=0;e<t.count;e++)t.setXYZ(e,0,1,0);t.needsUpdate=!0,this.grassMaterial=new h({color:3765785})}refreshGeometry(){const e=this.source.landscape.options,t=(new n,new n);this.view.camera.getWorldPosition(t);const s=[];A.fromArray(this.source.position);const a=this.view.camera instanceof f?Math.min(this.view.camera.far,1e3):1e3,o=1.1*a,i=e.sections.y*e.sectionSize/-2,r=e.sections.x*e.sectionSize/-2;for(let n=0;n<e.sections.x;n++)if(S.x=r+n*e.sectionSize,!(Math.abs(t.x-S.x)>o))for(let c=0;c<e.sections.y;c++){S.z=i+c*e.sectionSize,v.copy(A).add(S);const l=v.distanceTo(t),h=`${n},${c}`,u=this.landscape.sections.find((e=>e.x===n&&e.y===c));if(l<=a){if(null==u){this.sectionCache.has(h)||this.sectionCache.set(h,this.createLandscapeMesh(this.source,e,r,i,n,c));const t=this.sectionCache.get(h);this.applyMaterial(t),this.landscape.add(t),s.push(t)}}else l>o&&this.landscape.remove(u)}p(s)}applyHeightMap(e,t,s,n=1){const a=Math.pow(s+1,2),o=e.getAttribute("position");if(1===n)for(const e of t.points)o.setY(e.i,e.y);else{const e=d(t.points??[],(e=>e.i));for(let t=0;t<o.count;t++){const s=z(t,o.count,a);let n=0;n=s%1==0?e.get(s)?.y??0:Math.floor(e.get(s)?.y),o.setY(t,n)}}o.needsUpdate=!0,e.computeVertexNormals()}deleteOldScatterMeshes(){const e=new Set;for(const[t,s]of this.source.grass?.layers.entries()??[])for(const[n,a]of s.meshes.entries()){const s=`${t}-${n}`;e.add(s)}for(const t of this.scatterMeshes.keys())if(!e.has(t)){this.scatterMeshes.get(t).forEach((e=>{e.parent?.remove(e),e.dispose()})),this.scatterMeshes.delete(t)}}queueRefreshScatter(e,t=!1,s=(()=>!0)){this.refreshRequests.next({origin:e,force:t,predicate:s})}async refreshScatter(s,o=!1,i=(()=>!0)){o&&this.scatterGeometryCache.clear(),this.deleteOldScatterMeshes();for(const[c,h]of this.source.grass?.layers.entries()??[])for(const[u,f]of h.meshes.entries()){const h=`${c}-${u}`;this.scatterMeshes.has(h)||this.scatterMeshes.set(h,new Map);const p=this.scatterMeshes.get(h),m=await this.assetService.getAsset(f.assetId),w=await this.assetManagerService.getMesh(m),x=[];if(w.scene.traverse((e=>{e instanceof t&&x.push(e)})),1!==x.length){console.log(w),console.warn("Dynamic grass only works for meshes with a single geometry.");continue}if(!(x[0]instanceof t)){console.warn("Only meshes can be used for dynamic grass. Found:",w.scene);continue}const b=x[0];let S=b.geometry;this.scatterGeometryCache.has(b.geometry.uuid)?S=this.scatterGeometryCache.get(b.geometry.uuid):(S=b.geometry.clone(),!0===f.normalsUp&&D(S),null==S.userData.updatedMatrix&&(w.scene.updateMatrixWorld(),S.applyMatrix4(b.matrixWorld),S.userData.updatedMatrix=!0));const v=S.getIndex().count/3;if(v>400){console.warn(`The triangle count of ${m.name} is too big ${v}. Keep it below 400`);continue}const A=null!=m.materialAssignments&&m.materialAssignments.length>0?m.materialAssignments[0].materialId:null,z=null!=A&&"null"!==A?await e(await this.assetService.getAsset(A),null,this.assetService,this.assetManagerService,this.shaders,!1):null;let P=null!=z?z:b.material;const G=l.degToRad(f.maxSlope??90),C=Math.cos(G),R=this.landscape.sections,T=R.filter(j(s,f.viewDistance)).filter((e=>!p.has(e.uuid)||o)).filter((e=>i(e)));R.filter(L(s,2*f.viewDistance)).forEach((e=>{const t=p.get(e.uuid);null!=t&&(t.visible=!1)}));performance.now();const W=this.source.landscape.options,I=W.sectionSize,O=f.density??1??1,H=W.density,Y=I/H,E=O,X=Y/Math.sqrt(E),F=Math.pow(H,2),N=X/Y,Z=Math.floor(F*E),K=[0,0,0];for(const e of T)await g((async()=>{e.updateWorldMatrix(!0,!1);const t=this._matrix,s=new n,i=e.geometry.getAttribute("position"),l=e.geometry.getAttribute("normal"),h=(this.source.vertexMaterials??[]).filter((t=>t.m===e.name)),u=d(h,(e=>e.i));let m=p.get(e.uuid);null==m||m.count==Z&&!o||(m.parent?.remove(m),p.delete(e.uuid),m=null),null==m&&(m=new a(S,P,Z),m.raycast=()=>{},m.receiveShadow=!0),m.visible=!0;const w=new r(new n,new n,new n);let[g,x,b,v]=[new n,new n,new n,new n],[A,z,L]=[[],[],[]],[j,G,R]=[new n,new n,new n,new n];const T=new n,W=new n,D=new n,I=new n,O=new r(new n,new n,new n),Y=new r(new n,new n,new n),X=new r(new n,new n,new n),V=new r(new n,new n,new n);let J=0;e:for(let n=0;n<F;n++){const a=Math.floor(n/H);g.fromBufferAttribute(i,n+a),I.copy(g).applyMatrix4(e.matrixWorld),O.a.copy(g),O.b.fromBufferAttribute(i,n+1+a),O.c.fromBufferAttribute(i,n+H+1+a),Y.a.copy(O.b),Y.b.copy(O.c),Y.c.fromBufferAttribute(i,n+H+2+a),X.a.fromBufferAttribute(l,n+a),X.b.fromBufferAttribute(l,n+1+a),X.c.fromBufferAttribute(l,n+H+1+a),V.a.copy(X.b),V.b.copy(X.c),V.c.fromBufferAttribute(l,n+H+2+a);const o=[];o[0]=u.get(n+a)?.w,o[1]=u.get(n+1+a)?.w,o[2]=u.get(n+H+1+a)?.w,o[3]=u.get(n+H+2+a)?.w;let r=0;for(let n=0;n<=1+N;n+=N)for(let a=0;a<=1+N;a+=N){if(J>Z)break e;if(r++,r>E)continue e;1-n>a?(x=O.a,b=O.b,v=O.c,j=X.a,G=X.b,R=X.c,A=o[0],z=o[1],L=o[2]):(x=Y.a,b=Y.b,v=Y.c,j=V.a,G=V.b,R=V.c,A=o[1],z=o[2],L=o[3]),w.a.copy(x),w.b.copy(b),w.c.copy(v),B(w),T.set(g.x,0,g.z),T.x=_(w.a.x,w.b.x),T.z=_(w.a.z,w.c.z),w.getBarycoord(T,s).toArray(K);if($([A,z,L],K,.2)!==c-1)continue;const i=[x,b,v];y(i,K,W),y([j,G,R],K,D);const l=i.map((e=>e.y)),h=Math.max(...l),u=Math.min(...l);if(W.y=M(W.y,u,h),null!=f.maxSlope&&f.maxSlope<90&&D.y<C)continue;const d=W.applyMatrix4(e.matrixWorld);d.y+=_(f.offsetMin,f.offsetMax);const p=_(f.scaleMin,f.scaleMax);t.makeScale(1,1,1),t.setPosition(d),t.scale(q(p)),f.alignToNormal&&U(t,d,m.matrixWorld,D),!1!==f.randomRotation&&k(t),m.setMatrixAt(J,t),J++}}m.count=J,m.instanceMatrix.needsUpdate=!0;m.material;p.has(e.uuid)||this.landscape?.add(m),p.set(e.uuid,m)}));performance.now()}}stop(){this.view.removeOnLoop(this.onLoopHandler)}update(){this.view.camera&&(this.view.camera.getWorldPosition(this._cameraPosition),this._cameraPosition.distanceTo(this._lastUpdatePosition)>10&&(this._lastUpdatePosition.copy(this._cameraPosition),this.refreshGeometry(),this.refreshScatter(this._cameraPosition)))}clear(){this.scatterMeshes.forEach((e=>e.forEach((e=>e.parent?.remove(e)))))}createLandscapeMesh(e,t,n,a,o,i){const r=new s(t.sectionSize,t.sectionSize,t.density,t.density);r.rotateX(Math.PI/-2);const c=this.defaultLandscapeMaterial,l=new w(r,c);l.position.x=n+o*t.sectionSize,l.position.z=a+i*t.sectionSize,l.receiveShadow=!0,l.castShadow=!1,l.userData.landscape={x:o,y:i},l.x=o,l.y=i,l.name=`${o},${i}`;const h=e.landscape.heightMaps.find((e=>e.x===o&&e.y===i));return null!=h&&this.applyHeightMap(r,h,t.density,1),r.computeBoundsTree(),l}}function z(e,t,s){const n=Math.sqrt(t),a=Math.floor(e/n)/(n-1),o=e%n/(n-1),i=Math.sqrt(s);return(s-1)*a-(i-1)*a+(i-1)*o}new Map,new i(0,0),new i(1,0),new i(0,1),new i(1,0),new i(0,1),new i(1,1),new n;const P=new c;function L(e,t){return function(s){return P.setFromObject(s).distanceToPoint(e)>t}}function j(e,t){return function(s){return P.setFromObject(s).distanceToPoint(e)<t}}function B(e){e.a.y=0,e.b.y=0,e.c.y=0}function $(e,t,s=.5){let n=-1,a=0;for(let o=0;o<e.length;o++)if(null!=e[o])for(let i=0;i<e[o].length;i++){const r=e[o][i]*t[o];r>s&&r>a&&(a=r,n=i)}return n}function _(e,t){let s=t-e,n=Math.random();return n*=s,n+=e,n}const G=new n;function q(e){return G.set(e,e,e)}new n;const C=new n,R=new n(0,1,0),T=(new o).makeRotationX(Math.PI/-2);function U(e,t,s,n){e.lookAt(C,n,R).multiply(T)}const W=new o;function k(e){e.multiply(W.makeRotationY(Math.random()*Math.PI/2))}function D(e){const t=e.getAttribute("normal");for(let e=0;e<t.count;e++)t.setXYZ(e,0,1,0);t.normalized=!0,t.needsUpdate=!0}
1
+ import{materialFromAsset as e}from"../../scene/materializer.js";import{Mesh as t,PlaneGeometry as s,Vector3 as n,InstancedMesh as o,Matrix4 as a,Vector2 as i,Triangle as r,Box3 as c,MathUtils as l,MeshStandardMaterial as h,ShaderMaterial as u,PerspectiveCamera as f}from"three";import{indexBy as d}from"../../utils/collections.js";import{smoothNormalsCrossMeshes as p}from"./utils.js";import{defaultLandscapeMaterial as m,LandscapeMesh as w}from"./landscape.js";import{meanVectors3withWeight as g}from"../../utils/math.js";import{Subject as y,debounceTime as M}from"rxjs";new n,new n;const x=new n,b=new n,S=new n;export class LandscapeManager{constructor(e,t,s,o,i,r,c){this.source=e,this.view=t,this.landscape=s,this.assetManagerService=o,this.assetService=i,this.shaders=r,this.applyMaterial=c,this.scatterMeshes=new Map,this.loadedScatterSquares=new Set,this.refreshRequests=new y,this.defaultLandscapeMaterial=m.clone(),this.scatterMeshPool=[],this.onLoopHandler=()=>this.update(),this.sectionCache=new Map,this._matrix=new a,this.scatterGeometryCache=new Map,this._lastUpdatePosition=new n,this._cameraPosition=new n,this.view.onLoop(this.onLoopHandler),this.defaultLandscapeMaterial.name=m.name,this.defaultLandscapeMaterial.color=m.color,this.refreshRequests.pipe(M(500)).subscribe((e=>this.refreshScatter(e.origin,e.force,e.predicate)))}updateShaders(e){this.shaders=e}async loadGrass(){const e=await this.assetService.getAsset("6ij937n72g");await this.assetManagerService.getMesh(e);this.grassGeometry=new s(2,2,3,3);const t=this.grassGeometry.getAttribute("normal");for(let e=0;e<t.count;e++)t.setXYZ(e,0,1,0);t.needsUpdate=!0,this.grassMaterial=new h({color:3765785})}refreshGeometry(){const e=this.source.landscape.options,t=(new n,new n);this.view.camera.getWorldPosition(t);const s=[];S.fromArray(this.source.position);const o=this.view.camera instanceof f?Math.min(this.view.camera.far,1e3):1e3,a=1.1*o,i=e.sections.y*e.sectionSize/-2,r=e.sections.x*e.sectionSize/-2;for(let n=0;n<e.sections.x;n++)if(x.x=r+n*e.sectionSize,!(Math.abs(t.x-x.x)>a))for(let c=0;c<e.sections.y;c++){x.z=i+c*e.sectionSize,b.copy(S).add(x);const l=b.distanceTo(t),h=`${n},${c}`,u=this.landscape.sections.find((e=>e.x===n&&e.y===c));if(l<=o){if(null==u){this.sectionCache.has(h)||this.sectionCache.set(h,this.createLandscapeMesh(this.source,e,r,i,n,c));const t=this.sectionCache.get(h);this.applyMaterial(t),this.landscape.add(t),s.push(t)}}else l>a&&this.landscape.remove(u)}p(s)}applyHeightMap(e,t,s,n=1){const o=Math.pow(s+1,2),a=e.getAttribute("position");if(1===n)for(const e of t.points)a.setY(e.i,e.y);else{const e=d(t.points??[],(e=>e.i));for(let t=0;t<a.count;t++){const s=v(t,a.count,o);let n=0;n=s%1==0?e.get(s)?.y??0:Math.floor(e.get(s)?.y),a.setY(t,n)}}a.needsUpdate=!0,e.computeVertexNormals()}deleteOldScatterMeshes(){const e=new Set;for(const[t,s]of this.source.grass?.layers.entries()??[])for(const[n,o]of s.meshes.entries()){const s=`${t}-${n}`;e.add(s)}for(const t of this.scatterMeshes.keys())if(!e.has(t)){this.scatterMeshes.get(t).forEach((e=>{e.parent?.remove(e),e.dispose()})),this.scatterMeshes.delete(t)}}queueRefreshScatter(e,t=!1,s=(()=>!0)){this.refreshRequests.next({origin:e,force:t,predicate:s})}async refreshScatter(s,a=!1,i=(()=>!0)){a&&this.scatterGeometryCache.clear(),this.deleteOldScatterMeshes();for(const[c,h]of this.source.grass?.layers.entries()??[])for(const[u,f]of h.meshes.entries()){const h=`${c}-${u}`;this.scatterMeshes.has(h)||this.scatterMeshes.set(h,new Map);const p=this.scatterMeshes.get(h),m=await this.assetService.getAsset(f.assetId),w=await this.assetManagerService.getMesh(m),y=[];if(w.scene.traverse((e=>{e instanceof t&&y.push(e)})),1!==y.length){console.log(w),console.warn("Dynamic grass only works for meshes with a single geometry.");continue}if(!(y[0]instanceof t)){console.warn("Only meshes can be used for dynamic grass. Found:",w.scene);continue}const M=y[0];let x=M.geometry;this.scatterGeometryCache.has(M.geometry.uuid)?x=this.scatterGeometryCache.get(M.geometry.uuid):(x=M.geometry.clone(),!0===f.normalsUp&&O(x),null==x.userData.updatedMatrix&&(w.scene.updateMatrixWorld(),x.applyMatrix4(M.matrixWorld),x.userData.updatedMatrix=!0));const b=x.getIndex().count/3;if(b>400){console.warn(`The triangle count of ${m.name} is too big ${b}. Keep it below 400`);continue}const S=null!=m.materialAssignments&&m.materialAssignments.length>0?m.materialAssignments[0].materialId:null,v=null!=S&&"null"!==S?await e(await this.assetService.getAsset(S),null,this.assetService,this.assetManagerService,this.shaders,!1):null;let A=null!=v?v:M.material;const j=l.degToRad(f.maxSlope??90),C=Math.cos(j),G=this.landscape.sections,R=G.filter(P(s,f.viewDistance)),k=R.filter((e=>!p.has(e.uuid)||a)).filter((e=>i(e)));G.filter(z(s,2*f.viewDistance)).forEach((e=>{const t=p.get(e.uuid);null!=t&&(t.visible=!1)}));for(const e of R){const t=p.get(e.uuid);null!=t&&(t.visible=!0)}performance.now();const T=this.source.landscape.options,U=T.sectionSize,W=f.density??1??1,H=T.density,X=U/H,Y=W,E=X/Math.sqrt(Y),F=Math.pow(H,2),N=E/X,Z=Math.floor(F*Y),K=[0,0,0];for(const e of k){e.updateWorldMatrix(!0,!1);const t=this._matrix,s=new n,i=e.geometry.getAttribute("position"),l=e.geometry.getAttribute("normal"),h=(this.source.vertexMaterials??[]).filter((t=>t.m===e.name)),u=d(h,(e=>e.i));let m=p.get(e.uuid);if(null==m||m.count==Z&&!a||(m.parent?.remove(m),this.scatterMeshPool.push(m),p.delete(e.uuid),m=null),null==m){const e=this.scatterMeshPool.findIndex((e=>e.count>=Z));e>-1?(m=this.scatterMeshPool[e],m.geometry=x,m.material=A,this.scatterMeshPool.splice(e,1)):m=new o(x,A,Z),m.raycast=()=>{},m.receiveShadow=!0}m.visible=!0;const w=new r(new n,new n,new n);let[y,M,b,S]=[new n,new n,new n,new n],[v,z,P]=[[],[],[]],[j,G,R]=[new n,new n,new n,new n];const k=new n,T=new n,U=new n,W=new n,O=new r(new n,new n,new n),X=new r(new n,new n,new n),E=new r(new n,new n,new n),V=new r(new n,new n,new n);let J=0;e:for(let n=0;n<F;n++){const o=Math.floor(n/H);y.fromBufferAttribute(i,n+o),W.copy(y).applyMatrix4(e.matrixWorld),O.a.copy(y),O.b.fromBufferAttribute(i,n+1+o),O.c.fromBufferAttribute(i,n+H+1+o),X.a.copy(O.b),X.b.copy(O.c),X.c.fromBufferAttribute(i,n+H+2+o),E.a.fromBufferAttribute(l,n+o),E.b.fromBufferAttribute(l,n+1+o),E.c.fromBufferAttribute(l,n+H+1+o),V.a.copy(E.b),V.b.copy(E.c),V.c.fromBufferAttribute(l,n+H+2+o);const a=[];a[0]=u.get(n+o)?.w,a[1]=u.get(n+1+o)?.w,a[2]=u.get(n+H+1+o)?.w,a[3]=u.get(n+H+2+o)?.w;let r=0;for(let n=0;n<=1+N;n+=N)for(let o=0;o<=1+N;o+=N){if(J>Z)break e;if(r++,r>Y)continue e;1-n>o?(M=O.a,b=O.b,S=O.c,j=E.a,G=E.b,R=E.c,v=a[0],z=a[1],P=a[2]):(M=X.a,b=X.b,S=X.c,j=V.a,G=V.b,R=V.c,v=a[1],z=a[2],P=a[3]),w.a.copy(M),w.b.copy(b),w.c.copy(S),L(w),k.set(y.x,0,y.z),q(w,k),w.getBarycoord(k,s).toArray(K),B[0]=v,B[1]=z,B[2]=P;if($(B,K,.2)!==c-1)continue;if(g([M,b,S],K,T),g([j,G,R],K,U),null!=f.maxSlope&&f.maxSlope<90&&U.y<C)continue;const i=T.applyMatrix4(e.matrixWorld);i.y+=_(f.offsetMin,f.offsetMax);const l=_(f.scaleMin,f.scaleMax);t.makeScale(l,l,l);const h=t.elements;h[12]=i.x,h[13]=i.y,h[14]=i.z,f.alignToNormal&&D(t,i,m.matrixWorld,U),!1!==f.randomRotation&&I(t);const u=m.instanceMatrix.array,d=16*J;u[d]=h[0],u[d+1]=h[1],u[d+2]=h[2],u[d+3]=h[3],u[d+4]=h[4],u[d+5]=h[5],u[d+6]=h[6],u[d+7]=h[7],u[d+8]=h[8],u[d+9]=h[9],u[d+10]=h[10],u[d+11]=h[11],u[d+12]=h[12],u[d+13]=h[13],u[d+14]=h[14],u[d+15]=h[15],J++}}m.count=J,m.instanceMatrix.needsUpdate=!0,p.has(e.uuid)||this.landscape?.add(m),p.set(e.uuid,m),m.userData.meshConfig=f}performance.now()}}stop(){this.view.removeOnLoop(this.onLoopHandler)}update(){this.view.camera&&(this.view.camera.getWorldPosition(this._cameraPosition),this._cameraPosition.distanceTo(this._lastUpdatePosition)>10&&(this._lastUpdatePosition.copy(this._cameraPosition),this.refreshGeometry(),this.refreshScatter(this._cameraPosition)))}clear(){this.scatterMeshes.forEach((e=>e.forEach((e=>e.parent?.remove(e)))))}createLandscapeMesh(e,t,n,o,a,i){const r=new s(t.sectionSize,t.sectionSize,t.density,t.density);r.rotateX(Math.PI/-2);const c=this.defaultLandscapeMaterial,l=new w(r,c);l.position.x=n+a*t.sectionSize,l.position.z=o+i*t.sectionSize,l.receiveShadow=!0,l.castShadow=!1,l.userData.landscape={x:a,y:i},l.x=a,l.y=i,l.name=`${a},${i}`;const h=e.landscape.heightMaps.find((e=>e.x===a&&e.y===i));return null!=h&&this.applyHeightMap(r,h,t.density,1),r.computeBoundsTree(),l}}function v(e,t,s){const n=Math.sqrt(t),o=Math.floor(e/n)/(n-1),a=e%n/(n-1),i=Math.sqrt(s);return(s-1)*o-(i-1)*o+(i-1)*a}new Map,new i(0,0),new i(1,0),new i(0,1),new i(1,0),new i(0,1),new i(1,1),new n;const A=new c;function z(e,t){return function(s){return A.setFromObject(s).distanceToPoint(e)>t}}function P(e,t){return function(s){return A.setFromObject(s).distanceToPoint(e)<t}}function L(e){e.a.y=0,e.b.y=0,e.c.y=0}const B=[];function $(e,t,s=.5){const n=B;let o=-1,a=0;for(let e=0;e<n.length;e++)if(null!=n[e])for(let i=0;i<n[e].length;i++){const r=n[e][i]*t[e];r>s&&r>a&&(a=r,o=i)}return o}function _(e,t){let s=t-e,n=G();return n*=s,n+=e,n}const j=[];let C=1e3;for(;C--;)j.push(Math.random());function G(){return++C>=j.length?j[C=0]:j[C]}const R=[];let k=20;for(;k--;)R.push((new a).makeRotationY(G()*Math.PI/2));function q(e,t){let s=G(),n=G();s+n>1&&(s=1-s,n=1-n);const o=e.a,a=e.b,i=e.c;t.x=o.x+s*(a.x-o.x)+n*(i.x-o.x),t.z=o.z+s*(a.z-o.z)+n*(i.z-o.z)}new n;new n;const T=new n,U=new n(0,1,0),W=(new a).makeRotationX(Math.PI/-2);function D(e,t,s,n){e.lookAt(T,n,U).multiply(W)}new a;function I(e){e.makeRotationX;const t=(++k>=R.length?R[k=0]:R[k]).elements,s=e.elements;s[0]=t[0],s[4]=t[4],s[8]=t[8],s[1]=t[1],s[5]=t[5],s[9]=t[9],s[2]=t[2],s[6]=t[6],s[10]=t[10]}function O(e){const t=e.getAttribute("normal");for(let e=0;e<t.count;e++)t.setXYZ(e,0,1,0);t.normalized=!0,t.needsUpdate=!0}
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -185,6 +185,7 @@ export declare class SceneMaterializer {
185
185
  private objectMap;
186
186
  private sceneObjectMap;
187
187
  private updateSubscription;
188
+ private createAssetSubscription;
188
189
  readonly components: GameComponent[];
189
190
  private readonly landscapeManagers;
190
191
  materializedActors: Map<string, BaseActor>;
@@ -200,6 +201,7 @@ export declare class SceneMaterializer {
200
201
  error$: Subject<Error>;
201
202
  private editorActorParamSnapshot;
202
203
  private originalFog;
204
+ private assets;
203
205
  constructor(scene: Scene, dataProvider: SceneDataProvider, assetsService: AssetsProvider, assetManagerService: AssetResourceLoader, renderingView: RenderingView, shaders: ShaderImpl[], actorTypes: ActorImpl[], actorProvider: ActorProvider);
204
206
  private refreshMaterial;
205
207
  get actorInstances(): BaseActor[];
@@ -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 p,Object3D as d,PointLight as f,Quaternion as u,SphereGeometry as y,Texture as g,Vector2 as w,Vector3 as S,Vector4 as A}from"three";import v,{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 N,Texture2dLookupNode as E,textureSampler2d as V,vec2 as F,Vec2Node as C,vec3 as k,Vec3Node as z,vec4 as O}from"three-shader-graph";import B 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 J,PhysicalShapeMesh as H}from"./collision/collision-shape.js";import{isCollisionMesh as W}from"./collision/collision-shape-import.js";import{initLandscape as q}from"./landscape/landscape.js";import{LandscapeManager as X}from"./landscape/landscape-manager.js";import{SectionGrid as G,smoothNormalsCrossMeshes as Y}from"./landscape/utils.js";import{createGrassMaterial as Z}from"./materials/grass.js";import{createGrassFoliageMaterial as Q}from"./materials/grass-foliage.js";import{getMaterialAttribute as K}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{PhysicsBodyType as pe,withInjectionContext as de}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 ye}from"../effects/vfx/vfx-param.js";import{findFirstVisibleObject as ge}from"../utils/three/traverse.js";const we={};export const shapeDefaultColor="#aaaaaa";export class SceneMaterializerLoader{constructor(e,t,a){this.dataProvider=e,this.assetsService=t,this.assetManagerService=a}get(e,t){return new SceneMaterializer(e,this.dataProvider,this.assetsService,this.assetManagerService,t,[],[],{create:()=>null,initActor:async()=>{}})}}export class SceneMaterializer{constructor(a,s,r,i,n,o,c,l){this.scene=a,this.dataProvider=s,this.assetsService=r,this.assetManagerService=i,this.renderingView=n,this.shaders=o,this.actorTypes=c,this.actorProvider=l,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.geometryCache=new Map,this.collisionShapeCache=new Map,this.originalFog=null,s.onUpdate((e=>this.update(e))),s.onRemove((e=>this.remove(e))),this.updateSubscription=r.onUpdate.subscribe((async e=>{"material"==e.type?a.traverse((a=>{if(a instanceof t.Mesh)if(Array.isArray(a.material))for(let t=0;t<a.material.length;t++)this.refreshMaterial(a,a.material[t],e,t);else this.refreshMaterial(a,a.material,e)})):"mesh"==e.type?(this.findByAssetId(e.id).forEach((t=>{De(t.userData.src.materialAssignments,e.materialAssignments).forEach((e=>{this.applyMaterial(t,e)}))})),this.landscapeManagers.forEach((t=>{t.source.grass.layers.some((t=>t.meshes.some((t=>t.assetId===e.id))))&&t.queueRefreshScatter(this.renderingView?.camera.position??new S,!0)}))):"prefab"===e.type&&this.findByAssetId(e.id).forEach((e=>{const t=e.userData.src;this.remove(t),this.materializeAndInitActor(t)}))}))}async refreshMaterial(e,t,a,s){if(t?.userData?.assetId!==a.id)return;const r=await materialFromAsset(a,this.renderingView,this.assetsService,this.assetManagerService,this.shaders,!0);r.userData=t.userData,s?e.material[s]=r:e.material=r}get actorInstances(){return Array.from(this.materializedActors.values())}async prefetchAssets(){const e=Array.from(new Set(this.dataProvider.getObjects().filter((e=>null!=e.assetId&&"asset_mesh"==e.type)).filter((e=>e.assetId))));await Promise.all(e.map((e=>this.assetsService.getAsset(e.assetId).then((e=>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??{}};for(const a of t.actor.innerParams??[])await this.applyActorComponentParams(e,a.path.slice(),a.params);const r=await Me(s,e.constructor,this.assetsService,this.assetManagerService,this.materializedActors,this.renderingView,this.shaders,this.actorProvider);Object.assign(e,r);try{return await this.actorProvider.initActor(e)}catch(e){console.error(`Failed to initiate actor (name="${t.name}", id=${t.id})`,e)}}));return Promise.all(t)}addVfxChildActors(e,t=e){}async applyActorComponentParams(e,t,a){const s=t.length,r=t.shift();if(0==s){const t=await Me(a,null,this.assetsService,this.assetManagerService,this.materializedActors,this.renderingView,this.shaders);for(const[a,s]of Object.entries(t))null!=s&&(e[a]=s)}else null!=e[r]&&await this.applyActorComponentParams(e[r],t,a)}canObjectBeInstanced(e){return e.physics?.type!==pe.dynamic&&"sky"!==e.type&&"global_fog"!==e.type}async canAssetBeInstanced(e){if(!this._canBeInstancedCache.has(e.assetId)){const t=await this.createFromAsset(e);if(null==t)return!1;const a=[];t.traverse((e=>{!W(e)&&e.isMesh&&a.push(e)}));const s=1==a.length&&0==a[0].children.length,r=a[0]instanceof l&&null!=a[0].geometry.morphAttributes&&Object.keys(a[0].geometry.morphAttributes).length>0,i=!0;this._canBeInstancedCache.set(e.assetId,s&&i&&!r)}return this._canBeInstancedCache.get(e.assetId)}preInit(){this.renderingView?.onLoop((()=>{null!=this.sky&&this.renderingView.camera.getWorldPosition(this.sky.position)}))}async initWithInstancing(){this.preInit(),await this.prefetchAssets();const e=[],a=new $,s=new $;for(const t of this.dataProvider.getObjects())await Pe(t,(async(t,r,i)=>{const n="asset_mesh"==t.type&&this.canObjectBeInstanced(t)&&await this.canAssetBeInstanced(t),o="shape_mesh"===t.type&&"landscape"!==t.shape&&t.physics?.type!==pe.dynamic;if(n||o)if(r&&r.children?.length>0&&r.children.splice(r.children.findIndex((e=>e.id===t.id)),1),o){const e=t.shape+JSON.stringify(t.materialAssignments??[])+JSON.stringify(t.shapeParams??{})+t.castShadow+t.receiveShadow;s.push(e,{...t,parentTransform:i})}else{const e=t.assetId+JSON.stringify(t.materialAssignments??[]);a.push(e,{...t,parentTransform:i})}else null==r&&e.push({...t,parentTransform:i})}));for(const e of a.values()){if(0==e.length)continue;const t=await this.createFromAsset(e[0]);if(null==t)continue;const a=await this.createInstancedMesh(e,t),s=new U;s.add(a),s.userData.src=e[0],t instanceof U&&(s.collisionShapes=t.collisionShapes),s.castShadow=!1,s.receiveShadow=!1,this.scene.add(s)}for(const e of s.values()){if(0==e.length)continue;const a=await this.createFromShape(e[0]),s=ge(a,(e=>!W(e)&&null!=e.geometry)),i=s.geometry,n=new t.InstancedMesh(i,s.material.clone(),e.length);for(let i=0;i<e.length;i++){const o=(new t.Matrix4).compose((new S).fromArray(e[i].position),(new u).setFromEuler((new r).fromArray(e[i].rotation)),(new S).fromArray(e[i].scale)),c=(new ae).copy(e[i].parentTransform).multiply(o);n.setMatrixAt(i,c),n.castShadow=a.castShadow??!0,n.receiveShadow=s.receiveShadow??!0;const l=new U;l.add(n),l.userData.src=e[0],a instanceof H&&(l.collisionShapes=[a.collisionShape]),l.castShadow=!1,l.receiveShadow=!1,this.scene.add(l)}}await Promise.all(e.map((e=>this.materialize(e)))),await this.initActorsPostInit()}async createInstancedMesh(e,a){const s=ge(a,(e=>!W(e)&&null!=e.geometry)),i=await this.assetsService.getAsset(e[0].assetId);await this.applyMaterials(a,De(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 S).fromArray(e[a].position),(new u).setFromEuler((new r).fromArray(e[a].rotation)),(new S).fromArray(e[a].scale)),i=(new ae).copy(e[a].parentTransform).multiply(s);o.setMatrixAt(a,i)}return o.castShadow=e[0].castShadow??i.castShadow??!0,o.receiveShadow=e[0].receiveShadow??i.receiveShadow??!0,o}remove(e){if(console.log("Remove scene object",e),"global_fog"==e.type)return void(this.scene.fog=this.originalFog);if("actor"==e.type){const t=this.materializedActors.get(e.id);null!=t?(t.disposed.next(!0),t.onEndPlay()):console.warn("Failed to remove actor",e)}const t=this.sceneObjectMap.get(e.id);t?.parent.remove(t),this.sceneObjectMap.delete(e.id),this.components.filter((t=>t.object.userData.src?.id===e.id)).forEach((e=>this.components.splice(this.components.indexOf(e,1)))),this.landscapeManagers.filter((t=>t.source.id===e.id)).forEach((e=>{e.clear(),e.stop(),this.landscapeManagers.splice(this.landscapeManagers.indexOf(e,1))})),this.removed$.next({object:t,source:e})}deleteSceneObject(e){const t=this.sceneObjectMap.get(e.id);if(this.scene.remove(t),"landscape"==e.type){const t=this.landscapeManagers.findIndex((t=>t.source.id===e.id));if(t>-1){const e=this.landscapeManagers.splice(t,1)[0];e.clear(),e.stop()}}}findByAssetId(e){return 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){applyMaterial(e,t,(async e=>{const t=await this.assetsService.getAsset(e);if(null!=t)return materialFromAsset(t,this.renderingView,this.assetsService,this.assetManagerService,this.shaders)}),this._originalMaterials)}unapplyMaterials(e){e.traverse((async e=>{if(e instanceof 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(B));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((async e=>{if(e instanceof l)if(Array.isArray(e.material))for(let t=0;t<e.material.length;t++){const a=e.material[t].userData?.customShaderName;if(null!=a){const a=await this.assetsService.getAsset(e.material[t].userData.assetId);this.refreshMaterial(e,e.material[t],a,t)}}else{const t=e.material.userData?.customShaderName;if(null!=t){const t=await this.assetsService.getAsset(e.material.userData.assetId);this.refreshMaterial(e,e.material,t)}}}))}))}async update(e){if("sky"===e.type&&null!=this.sky&&null!=this.sky.parent)return void this.updateSky(e);const t=this.sceneObjectMap.get(e.id);if(t){let r=!1;if(t.traverseAncestors((e=>{"_hology_transform_group"===e.name&&(r=!0)})),!r){const a=this.findParent(e);null!=a&&a.uuid!=t.uuid?a.attach(t):console.error("Parent is wrong")}if("prefab"!==e.type&&"group"!==e.type){this.unapplyMaterials(t);this.inEditor&&e.hidden&&!1?t.traverse((e=>{e instanceof 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);De(e.materialAssignments,a.materialAssignments).forEach((e=>this.applyMaterial(t,e)))}else"shape_mesh"===e.type&&this.applyMaterials(t,e.materialAssignments);if(r||(null!=e.position&&t.position.fromArray(e.position),null!=e.scale&&t.scale.fromArray(e.scale),null!=e.rotation&&t.rotation.fromArray(e.rotation)),this.applyVertexMaterials(e,t),"light"==e.type)if("point"==e.light.type){const a=t;a.color=new s(e.light.point.color),a.intensity=e.light.point.intensity,a.decay=e.light.point.decay,a.castShadow=e.light.point.castShadow,a.distance=Math.max(e.light.point.distance,0)}else"directional"===e.light.type?this.applyDirectionalLight(e.light.directional):"ambient"===e.light.type&&this.applyDirectionalAmbientLight(t,e.light.ambient);else if("landscape"===e.shape)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=je(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"),r||(this.remove(e),await this.materializeAndInitActor(e)))}}else if("shape_mesh"===e.type){const a=await this.createMeshByShape(e.shape,t.material,e.shapeParams);t instanceof H&&(t.geometry=a.geometry,t.collisionShape=a.collisionShape)}("asset_mesh"===e.type||"shape_mesh"===e.type&&"landscape"!==e.shape)&&Se(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 Pe(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))}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=K(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=K(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=je(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),null!=e.position&&r.position.fromArray(e.position),null!=e.scale&&r.scale.fromArray(e.scale),null!=e.rotation&&r.rotation.fromArray(e.rotation),s||(r.userData.src=e),this.inEditor,this.inEditor){let e=null;r instanceof H&&(e=function(e){if(e instanceof J)return new l(new a(...e.offset.toArray()),Ie);return null}(r.collisionShape)),null!=e&&(e.layers.disable(0),e.layers.enable(18),e.scale.multiplyScalar(1.1),r.add(e))}return this.objectMap.set(r.uuid,e),this.sceneObjectMap.set(e.id,r),e.physics?.type!==pe.dynamic||null==t||this.inEditor?null==t?this.scene.add(r):t?.add(r):(t.add(r),r.getWorldPosition(r.position),r.getWorldQuaternion(r.quaternion),r.getWorldScale(r.scale),this.scene?.attach(r)),null!=e.children&&await Promise.all(e.children?.map((e=>this.materialize(e,r,s)))),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 we[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??B[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 S).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 S).fromArray(e.position),(new r).fromArray(e.rotation),!1);return await a.fromAsset(t),a.play(),this.materializedActors.set(e.id,a),a?.object}cleanup(){this.materializedActors.clear()}async createFromShape(e){const t=this.inEditor&&e.hidden;let a;if("landscape"==e.shape)a=this.createLandscape(e),a.traverse((e=>{e instanceof l&&this._originalMaterials.set(e.id,e.material)}));else{let r=new p({name:"Default",color:new s("#aaaaaa"),visible:this.inEditor||!e.hidden,wireframe:!!t});const i=await this.createMeshByShape(e.shape,r,e.shapeParams);i.castShadow=e.castShadow??!0,i.receiveShadow=e.castShadow??!1,e.collisionDetection||(i.collisionShape=null),i.physics=e.physics,a=i,this._originalMaterials.set(a.id,i.material),a.traverse((e=>{}))}return t||((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=q(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 G(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((()=>Y(r)),50)}async createMeshByShape(e,t,a={}){if("landscape"!==e&&ce.includes(e)){const s=await prepareShapeParameters(a??{}),r=e+JSON.stringify(a);return this.geometryCache.has(r)||this.geometryCache.set(r,oe[e].geometry(s)),this.collisionShapeCache.has(r)||this.collisionShapeCache.set(r,oe[e].collision(s)),new H(this.geometryCache.get(r),t,this.collisionShapeCache.get(r))}if(this.inEditor)throw new Error(`Unsupported shape '${e}'`);console.warn(`Failed to create shape. Unsupported shape '${e}'. This might be because the hology/core library is not compatible with the editor version.`)}async createFromAsset(e){const t=await this.assetsService.getAsset(e.assetId);if(null==t)return void console.warn(`Can not find asset with id ${e.assetId} and name ${e.name}`);let{scene:a}=await this.assetManagerService.getMesh(t);De(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,Se(a,r,s),e.collisionDetection||(a.collisionShapes=[]),null!=e.physics&&!0!==this.inEditor&&(a.physics=e.physics),this.applyVertexMaterials(e,a),a.traverse((e=>{e instanceof 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 d;return await v.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 y(.3,10,10),a=new p({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 Se(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}),be=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),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 p;switch(e.material.type){case"phong":p=new m({...l,...h});break;case"water":p=ee(l,a);break;case"grassFoliage":p=Q({color:l.color,map:l.map},a);break;case"grass":p=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 Me(e.material?.shaderParams??{},t,r,i,null,a,n);Object.assign(s,o);try{p=s.build()}catch(t){console.log("Shader runtime error: "+t),be.has(e.material.shader)||be.set(e.material.shader,ve.clone()),p=be.get(e.material.shader)}p.userData.customShaderName=e.material.shader}else console.warn("Missing shader implementation with name "+e.material.shader),p=ve;break;default:throw new Error("Unsupported material type"+e.material.type)}return a?.csm.setupMaterial(p),o&&Ae.set(c,p),p.side=e.material.side??p.side??t.FrontSide,p.transparent=(e.material.transparent??l.transparent??!1)||p.transparent,e.material.bloom&&(p.userData.hasBloom=!0),p.userData.assetId=e.id,p}async function Me(e,t,a,s,r,i,n,o){const c={};for(const[t,l]of Object.entries(e)){const e=await xe(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 xe(s,null,null,null);null!=e&&(t[a]=e)}return t}async function xe(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 V(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 S).fromArray(l):new S(l.x,l.y,l.z);return e.type===te.Vec3Node?k(t):t}return null;case te.Color:case te.RgbNode:const m=new s(l);return e.type===te.RgbNode?D(m):m;case te.String:return l;case te.BaseActor:const p=l;return null==i&&console.warn("Class parameters can not be prepared as actors are not passed in"),i?.get(p);case te.Euler:const d=l;return(new r).fromArray(d);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 ye(c,f);console.error("Using a non-vfx asset for visual effect parameter")}return null}function je(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 Ie=new p({color:4229780});async function Pe(e,a,s,i){null==i&&(i=(new ae).identity()),await a(e,s,i);const n=i.clone().multiply(function(e,t){if(null==e.position||null==e.rotation||null==e.scale)return t.identity();return t.compose((new S).fromArray(e.position),(new u).setFromEuler((new r).fromArray(e.rotation)),(new S).fromArray(e.scale))}(e,new t.Matrix4));return Promise.all((e.children??[]).map((t=>Pe(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 g||e===g||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 N||"function"==typeof e.prototype.isRgb?te.RgbNode:t instanceof w||e==w?te.Vector2:t instanceof C||"function"==typeof e.prototype.isVec2?te.Vec2Node:t instanceof S||e==S?te.Vector3:t instanceof z||"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 d||e==d?te.Object3D:t instanceof c||e==c?te.Material:t instanceof AudioBuffer||e==AudioBuffer?te.AudioBuffer:t instanceof ye||e==ye?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?de(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 S:return t instanceof S?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 De(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=>Ne(e.materialId))),(t??[]).filter((e=>Ne(e.materialId))),(e=>e.color+e.name))}function Ne(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"]]]);export function applyMaterial(e,a,r,i){const n=[];return e.traverse((async e=>{if(e instanceof l||e.isMesh||e instanceof t.SkinnedMesh||e.isSkinnedMesh)for(const t of fe(e.material))t.hasOwnProperty("color")&&n.push(e)})),Promise.all(n.map((async e=>{if(e.material instanceof Array)for(let t=0;t<e.material.length;t++){const n=e.material[t];if(null==n.color||!(n.color instanceof s))continue;const o="#"+n.color.getHexString(),c=n.name;if(o===a.color&&(n.name===a.name||null==a.name)||e.userData["originalColor_"+t]===a.color&&e.userData["originalMaterialName_"+t]===a.name){const s=await r(a.materialId),n=e.material[t];null!=s&&(e.material[t]=s,e.userData["originalColor_"+t]=e.userData["originalColor_"+t]??o,e.userData["originalMaterialName_"+t]=e.userData["originalMaterialName_"+t]??c,null!=i&&i.set(e.id+"#"+t,n))}}else if("color"in e.material){const t="#"+e.material.color.getHexString(),s=e.material.name;if(t===a.color&&(e.material.name===a.name||null==a.name)||e.userData.originalColor===a.color&&e.userData.originalName===a.name){const n=await r(a.materialId),o=e.material;null!=n&&(e.material=n,e.userData.originalColor=e.userData.originalColor??t,e.userData.originalMaterialName=e.userData.originalMaterialName??s,null!=i&&(i.has(e.id)||i.set(e.id,o)))}}})))}
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 p,Object3D as d,PointLight as u,Quaternion as f,SphereGeometry as y,Texture as g,Vector2 as w,Vector3 as S,Vector4 as v}from"three";import A,{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 N,Texture2dLookupNode as E,textureSampler2d as V,vec2 as C,Vec2Node as F,vec3 as k,Vec3Node as z,vec4 as O}from"three-shader-graph";import B 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 J,PhysicalShapeMesh as H}from"./collision/collision-shape.js";import{isCollisionMesh as W}from"./collision/collision-shape-import.js";import{initLandscape as q}from"./landscape/landscape.js";import{LandscapeManager as X}from"./landscape/landscape-manager.js";import{SectionGrid as G,smoothNormalsCrossMeshes as Y}from"./landscape/utils.js";import{createGrassMaterial as Z}from"./materials/grass.js";import{createGrassFoliageMaterial as Q}from"./materials/grass-foliage.js";import{getMaterialAttribute as K}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{PhysicsBodyType as pe,withInjectionContext as de}from"../gameplay/index.js";import{iterateMaterials as ue}from"../utils/materials.js";import{VfxActor as fe}from"../effects/vfx/vfx-actor.js";import{VisualEffect as ye}from"../effects/vfx/vfx-param.js";import{findFirstVisibleObject as ge}from"../utils/three/traverse.js";const we={};export const shapeDefaultColor="#aaaaaa";export class SceneMaterializerLoader{constructor(e,t,a){this.dataProvider=e,this.assetsService=t,this.assetManagerService=a}get(e,t){return new SceneMaterializer(e,this.dataProvider,this.assetsService,this.assetManagerService,t,[],[],{create:()=>null,initActor:async()=>{}})}}export class SceneMaterializer{constructor(a,s,r,i,n,o,c,l){this.scene=a,this.dataProvider=s,this.assetsService=r,this.assetManagerService=i,this.renderingView=n,this.shaders=o,this.actorTypes=c,this.actorProvider=l,this.objectMap=new Map,this.sceneObjectMap=new Map,this.components=[],this.landscapeManagers=[],this.materializedActors=new Map,this.inEditor=!0,this.updated$=new e,this.removed$=new e,this.error$=new e,this.editorActorParamSnapshot=new Map,this.assets=new Map,this._canBeInstancedCache=new Map,this._originalMaterials=new Map,this.geometryCache=new Map,this.collisionShapeCache=new Map,this.originalFog=null,s.onUpdate((e=>this.update(e))),s.onRemove((e=>this.remove(e))),this.createAssetSubscription=r.onCreate.subscribe((e=>{this.assets.set(e.id,e)})),this.updateSubscription=r.onUpdate.subscribe((async e=>{this.assets.set(e.id,e),"material"==e.type?a.traverse((a=>{if(a instanceof t.Mesh)if(Array.isArray(a.material))for(let t=0;t<a.material.length;t++)this.refreshMaterial(a,a.material[t],e,t);else this.refreshMaterial(a,a.material,e)})):"mesh"==e.type?(this.findByAssetId(e.id).forEach((t=>{De(t.userData.src.materialAssignments,e.materialAssignments).forEach((e=>{this.applyMaterial(t,e)}))})),this.landscapeManagers.forEach((t=>{t.source.grass.layers.some((t=>t.meshes.some((t=>t.assetId===e.id))))&&t.queueRefreshScatter(this.renderingView?.camera.position??new S,!0)}))):"prefab"===e.type&&this.findByAssetId(e.id).forEach((e=>{const t=e.userData.src;this.remove(t),this.materializeAndInitActor(t)}))}))}async refreshMaterial(e,t,a,s){if(t?.userData?.assetId!==a.id)return;const r=await materialFromAsset(a,this.renderingView,this.assetsService,this.assetManagerService,this.shaders,!0);r.userData=t.userData,null!=s?Ee(e.material[s],r)||(e.material[s]=r):Ee(e.material,r)||(e.material=r)}get actorInstances(){return Array.from(this.materializedActors.values())}async prefetchAssets(){const e=Array.from(new Set(this.dataProvider.getObjects().filter((e=>null!=e.assetId&&"asset_mesh"==e.type)).filter((e=>e.assetId))));await Promise.all(e.map((e=>this.assetsService.getAsset(e.assetId).then((e=>{if(null!=e)return this.assetManagerService.getMesh(e)})))))}async init(){await this.preInit(),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 Me(s,e.constructor,this.assetsService,this.assetManagerService,this.materializedActors,this.renderingView,this.shaders,this.actorProvider);Object.assign(e,r);try{return await this.actorProvider.initActor(e)}catch(e){console.error(`Failed to initiate actor (name="${t.name}", id=${t.id})`,e)}}));return Promise.all(t)}addVfxChildActors(e,t=e){}async applyActorComponentParams(e,t,a){const s=t.length,r=t.shift();if(0==s){const t=await Me(a,null,this.assetsService,this.assetManagerService,this.materializedActors,this.renderingView,this.shaders);for(const[a,s]of Object.entries(t))null!=s&&(e[a]=s)}else null!=e[r]&&await this.applyActorComponentParams(e[r],t,a)}canObjectBeInstanced(e){return e.physics?.type!==pe.dynamic&&"sky"!==e.type&&"global_fog"!==e.type}async canAssetBeInstanced(e){if(!this._canBeInstancedCache.has(e.assetId)){const t=await this.createFromAsset(e);if(null==t)return!1;const a=[];t.traverse((e=>{!W(e)&&e.isMesh&&a.push(e)}));const s=1==a.length&&0==a[0].children.length,r=a[0]instanceof l&&null!=a[0].geometry.morphAttributes&&Object.keys(a[0].geometry.morphAttributes).length>0,i=!0;this._canBeInstancedCache.set(e.assetId,s&&i&&!r)}return this._canBeInstancedCache.get(e.assetId)}async preInit(){this.renderingView?.onLoop((()=>{null!=this.sky&&this.renderingView.camera.getWorldPosition(this.sky.position)})),this.assetsService.getAssets().then((e=>{for(const t of e)this.assets.set(t.id,t)}))}async initWithInstancing(){await this.preInit(),await this.prefetchAssets();const e=[],a=new $,s=new $;for(const t of this.dataProvider.getObjects())await Pe(t,(async(t,r,i)=>{const n="asset_mesh"==t.type&&this.canObjectBeInstanced(t)&&await this.canAssetBeInstanced(t),o="shape_mesh"===t.type&&"landscape"!==t.shape&&t.physics?.type!==pe.dynamic;if(n||o)if(r&&r.children?.length>0&&r.children.splice(r.children.findIndex((e=>e.id===t.id)),1),o){const e=t.shape+JSON.stringify(t.materialAssignments??[])+JSON.stringify(t.shapeParams??{})+t.castShadow+t.receiveShadow;s.push(e,{...t,parentTransform:i})}else{const e=t.assetId+JSON.stringify(t.materialAssignments??[]);a.push(e,{...t,parentTransform:i})}else null==r&&e.push({...t,parentTransform:i})}));for(const e of a.values()){if(0==e.length)continue;const t=await this.createFromAsset(e[0]);if(null==t)continue;const a=await this.createInstancedMesh(e,t),s=new U;s.add(a),s.userData.src=e[0],t instanceof U&&(s.collisionShapes=t.collisionShapes),s.castShadow=!1,s.receiveShadow=!1,this.scene.add(s)}for(const e of s.values()){if(0==e.length)continue;const a=await this.createFromShape(e[0]),s=ge(a,(e=>!W(e)&&null!=e.geometry)),i=s.geometry,n=new t.InstancedMesh(i,s.material.clone(),e.length);for(let i=0;i<e.length;i++){const o=(new t.Matrix4).compose((new S).fromArray(e[i].position),(new f).setFromEuler((new r).fromArray(e[i].rotation)),(new S).fromArray(e[i].scale)),c=(new ae).copy(e[i].parentTransform).multiply(o);n.setMatrixAt(i,c),n.castShadow=a.castShadow??!0,n.receiveShadow=s.receiveShadow??!0;const l=new U;l.add(n),l.userData.src=e[0],a instanceof H&&(l.collisionShapes=[a.collisionShape]),l.castShadow=!1,l.receiveShadow=!1,this.scene.add(l)}}await Promise.all(e.map((e=>this.materialize(e)))),await this.initActorsPostInit()}async createInstancedMesh(e,a){const s=ge(a,(e=>!W(e)&&null!=e.geometry)),i=await this.assetsService.getAsset(e[0].assetId);await this.applyMaterials(a,De(e[0].materialAssignments,i.materialAssignments)),s.updateMatrix();const n=s.geometry.clone().applyMatrix4(s.matrix),o=new t.InstancedMesh(n,s.material,e.length);s.material instanceof c&&(o.material.side=t.FrontSide);for(let a=0;a<e.length;a++){const s=(new t.Matrix4).compose((new S).fromArray(e[a].position),(new f).setFromEuler((new r).fromArray(e[a].rotation)),(new S).fromArray(e[a].scale)),i=(new ae).copy(e[a].parentTransform).multiply(s);o.setMatrixAt(a,i)}return o.castShadow=e[0].castShadow??i.castShadow??!0,o.receiveShadow=e[0].receiveShadow??i.receiveShadow??!0,o}remove(e){if(console.log("Remove scene object",e),"global_fog"==e.type)return void(this.scene.fog=this.originalFog);if("actor"==e.type){const t=this.materializedActors.get(e.id);null!=t?(t.disposed.next(!0),t.onEndPlay()):console.warn("Failed to remove actor",e)}const t=this.sceneObjectMap.get(e.id);t?.parent.remove(t),this.sceneObjectMap.delete(e.id),this.components.filter((t=>t.object.userData.src?.id===e.id)).forEach((e=>this.components.splice(this.components.indexOf(e,1)))),this.landscapeManagers.filter((t=>t.source.id===e.id)).forEach((e=>{e.clear(),e.stop(),this.landscapeManagers.splice(this.landscapeManagers.indexOf(e,1))})),this.removed$.next({object:t,source:e})}deleteSceneObject(e){const t=this.sceneObjectMap.get(e.id);if(this.scene.remove(t),"landscape"==e.type){const t=this.landscapeManagers.findIndex((t=>t.source.id===e.id));if(t>-1){const e=this.landscapeManagers.splice(t,1)[0];e.clear(),e.stop()}}}findByAssetId(e){return 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))))}async applyMaterial(e,t){await applyMaterial(e,t,(e=>{const t=this.assets.get(e);if(null!=t)return materialFromAsset(t,this.renderingView,this.assetsService,this.assetManagerService,this.shaders)}),this._originalMaterials)}unapplyMaterials(e){e.traverse((async e=>{if(e instanceof 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(B));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((async e=>{if(e instanceof l)if(Array.isArray(e.material))for(let t=0;t<e.material.length;t++){const a=e.material[t].userData?.customShaderName;if(null!=a){const a=this.assets.get(e.material[t].userData.assetId);this.refreshMaterial(e,e.material[t],a,t)}}else{const t=e.material.userData?.customShaderName;if(null!=t){const t=this.assets.get(e.material.userData.assetId);this.refreshMaterial(e,e.material,t)}}}))}))}async update(e){if("sky"===e.type&&null!=this.sky&&null!=this.sky.parent)return void this.updateSky(e);const t=this.sceneObjectMap.get(e.id);if(t){let r=!1;if(t.traverseAncestors((e=>{"_hology_transform_group"===e.name&&(r=!0)})),!r){const a=this.findParent(e);null!=a&&a.uuid!=t.uuid?a.attach(t):console.error("Parent is wrong")}if("prefab"!==e.type&&"group"!==e.type){this.unapplyMaterials(t);this.inEditor&&e.hidden&&!1?t.traverse((e=>{e instanceof l&&(e.material.wireframe=!0)})):t.traverse((e=>{e instanceof l&&(e.material.wireframe=!1)}))}if("asset_mesh"===e.type){const a=this.assets.get(e.assetId);De(e.materialAssignments,a.materialAssignments).forEach((e=>this.applyMaterial(t,e)))}else"shape_mesh"===e.type&&this.applyMaterials(t,e.materialAssignments);if(r||(null!=e.position&&t.position.fromArray(e.position),null!=e.scale&&t.scale.fromArray(e.scale),null!=e.rotation&&t.rotation.fromArray(e.rotation)),this.applyVertexMaterials(e,t),"light"==e.type)if("point"==e.light.type){const a=t;a.color=new s(e.light.point.color),a.intensity=e.light.point.intensity,a.decay=e.light.point.decay,a.castShadow=e.light.point.castShadow,a.distance=Math.max(e.light.point.distance,0)}else"directional"===e.light.type?this.applyDirectionalLight(e.light.directional):"ambient"===e.light.type&&this.applyDirectionalAmbientLight(t,e.light.ambient);else if("landscape"===e.shape)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=je(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"),r||(this.remove(e),await this.materializeAndInitActor(e)))}}else if("shape_mesh"===e.type){const a=await this.createMeshByShape(e.shape,t.material,e.shapeParams);t instanceof H&&(t.geometry=a.geometry,t.collisionShape=a.collisionShape)}("asset_mesh"===e.type||"shape_mesh"===e.type&&"landscape"!==e.shape)&&Se(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 Pe(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))}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=K(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=K(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=je(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),null!=e.position&&r.position.fromArray(e.position),null!=e.scale&&r.scale.fromArray(e.scale),null!=e.rotation&&r.rotation.fromArray(e.rotation),s||(r.userData.src=e),this.inEditor,this.inEditor){let e=null;r instanceof H&&(e=function(e){if(e instanceof J)return new l(new a(...e.offset.toArray()),Ie);return null}(r.collisionShape)),null!=e&&(e.layers.disable(0),e.layers.enable(18),e.scale.multiplyScalar(1.1),r.add(e))}return this.objectMap.set(r.uuid,e),this.sceneObjectMap.set(e.id,r),e.physics?.type!==pe.dynamic||null==t||this.inEditor?null==t?this.scene.add(r):t?.add(r):(t.add(r),r.getWorldPosition(r.position),r.getWorldQuaternion(r.quaternion),r.getWorldScale(r.scale),this.scene?.attach(r)),null!=e.children&&await Promise.all(e.children?.map((e=>this.materialize(e,r,s)))),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 we[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??B[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 S).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(fe,(new S).fromArray(e.position),(new r).fromArray(e.rotation),!1);return await a.fromAsset(t),a.play(),this.materializedActors.set(e.id,a),a?.object}cleanup(){this.materializedActors.clear()}async createFromShape(e){const t=this.inEditor&&e.hidden;let a;if("landscape"==e.shape)a=this.createLandscape(e),a.traverse((e=>{e instanceof l&&this._originalMaterials.set(e.id,e.material)}));else{let r=new p({name:"Default",color:new s("#aaaaaa"),visible:this.inEditor||!e.hidden,wireframe:!!t});const i=await this.createMeshByShape(e.shape,r,e.shapeParams);i.castShadow=e.castShadow??!0,i.receiveShadow=e.castShadow??!1,e.collisionDetection||(i.collisionShape=null),i.physics=e.physics,a=i,this._originalMaterials.set(a.id,i.material),a.traverse((e=>{}))}return t||((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=q(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 G(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((()=>Y(r)),50)}async createMeshByShape(e,t,a={}){if("landscape"!==e&&ce.includes(e)){const s=await prepareShapeParameters(a??{}),r=e+JSON.stringify(a);return this.geometryCache.has(r)||this.geometryCache.set(r,oe[e].geometry(s)),this.collisionShapeCache.has(r)||this.collisionShapeCache.set(r,oe[e].collision(s)),new H(this.geometryCache.get(r),t,this.collisionShapeCache.get(r))}if(this.inEditor)throw new Error(`Unsupported shape '${e}'`);console.warn(`Failed to create shape. Unsupported shape '${e}'. This might be because the hology/core library is not compatible with the editor version.`)}async createFromAsset(e){const t=await this.assetsService.getAsset(e.assetId);if(null==t)return void console.warn(`Can not find asset with id ${e.assetId} and name ${e.name}`);let{scene:a}=await this.assetManagerService.getMesh(t);De(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,Se(a,r,s),e.collisionDetection||(a.collisionShapes=[]),null!=e.physics&&!0!==this.inEditor&&(a.physics=e.physics),this.applyVertexMaterials(e,a),a.traverse((e=>{e instanceof 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 d;return await A.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 u(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 y(.3,10,10),a=new p({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.createAssetSubscription.unsubscribe(),this.materializedActors.forEach((e=>e.disposed.next(!0)))}}function Se(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}),be=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),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 p;switch(e.material.type){case"phong":p=new m({...l,...h});break;case"water":p=ee(l,a);break;case"grassFoliage":p=Q({color:l.color,map:l.map},a);break;case"grass":p=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 Me(e.material?.shaderParams??{},t,r,i,null,a,n);Object.assign(s,o);try{p=s.build()}catch(t){console.log("Shader runtime error: "+t),be.has(e.material.shader)||be.set(e.material.shader,Ae.clone()),p=be.get(e.material.shader)}p.userData.customShaderName=e.material.shader}else console.warn("Missing shader implementation with name "+e.material.shader),p=Ae;break;default:throw new Error("Unsupported material type"+e.material.type)}return a?.csm.setupMaterial(p),o&&ve.set(c,p),p.side=e.material.side??p.side??t.FrontSide,p.transparent=(e.material.transparent??l.transparent??!1)||p.transparent,e.material.bloom&&(p.userData.hasBloom=!0),p.userData.assetId=e.id,p}async function Me(e,t,a,s,r,i,n,o){const c={};for(const[t,l]of Object.entries(e)){const e=await xe(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 xe(s,null,null,null);null!=e&&(t[a]=e)}return t}async function xe(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 V(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 S).fromArray(l):new S(l.x,l.y,l.z);return e.type===te.Vec3Node?k(t):t}return null;case te.Color:case te.RgbNode:const m=new s(l);return e.type===te.RgbNode?D(m):m;case te.String:return l;case te.BaseActor:const p=l;return null==i&&console.warn("Class parameters can not be prepared as actors are not passed in"),i?.get(p);case te.Euler:const d=l;return(new r).fromArray(d);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 u=await t.getAsset(l);if(null==c){console.error("Can not create instance of visual effect because missing actor provider");break}if("vfx"in u)return new ye(c,u);console.error("Using a non-vfx asset for visual effect parameter")}return null}function je(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 Ie=new p({color:4229780});async function Pe(e,a,s,i){null==i&&(i=(new ae).identity()),await a(e,s,i);const n=i.clone().multiply(function(e,t){if(null==e.position||null==e.rotation||null==e.scale)return t.identity();return t.compose((new S).fromArray(e.position),(new f).setFromEuler((new r).fromArray(e.rotation)),(new S).fromArray(e.scale))}(e,new t.Matrix4));return Promise.all((e.children??[]).map((t=>Pe(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 g||e===g||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 N||"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 S||e==S?te.Vector3:t instanceof z||"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 d||e==d?te.Object3D:t instanceof c||e==c?te.Material:t instanceof AudioBuffer||e==AudioBuffer?te.AudioBuffer:t instanceof ye||e==ye?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?de(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 S:return t instanceof S?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 De(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=>Ne(e.materialId))),(t??[]).filter((e=>Ne(e.materialId))),(e=>e.color+e.name))}function Ne(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"]]]);export function applyMaterial(e,a,r,i){const n=[];return e.traverse((async e=>{if(e instanceof l||e.isMesh||e instanceof t.SkinnedMesh||e.isSkinnedMesh)for(const t of ue(e.material))t.hasOwnProperty("color")&&n.push(e)})),Promise.all(n.map((async e=>{if(e.material instanceof Array)for(let t=0;t<e.material.length;t++){const n=e.material[t];if(null==n.color||!(n.color instanceof s))continue;const o="#"+n.color.getHexString(),c=n.name;if(o===a.color&&(n.name===a.name||null==a.name)||e.userData["originalColor_"+t]===a.color&&e.userData["originalMaterialName_"+t]===a.name){const s=await r(a.materialId),n=e.material[t];null!=s&&(e.material[t]=s,e.userData["originalColor_"+t]=e.userData["originalColor_"+t]??o,e.userData["originalMaterialName_"+t]=e.userData["originalMaterialName_"+t]??c,null!=i&&i.set(e.id+"#"+t,n))}}else if("color"in e.material){const t="#"+e.material.color.getHexString(),s=e.material.name;if(t===a.color&&(e.material.name===a.name||null==a.name)||e.userData.originalColor===a.color&&e.userData.originalName===a.name){const n=await r(a.materialId),o=e.material;null!=n&&(e.material=n,e.userData.originalColor=e.userData.originalColor??t,e.userData.originalMaterialName=e.userData.originalMaterialName??s,null!=i&&(i.has(e.id)||i.set(e.id,o)))}}})))}function Ee(e,a){if(e instanceof t.ShaderMaterial&&a instanceof t.ShaderMaterial){return e.fragmentShader+e.vertexShader==a.fragmentShader+a.vertexShader&&function(e,a){if(e instanceof t.ShaderMaterial&&a instanceof t.ShaderMaterial){for(const t in e.uniforms){if(null==a.uniforms[t])return!1;if(a.uniforms[t].value!==e.uniforms[t].value)return console.log("Different values",a.uniforms[t].value,e.uniforms[t].value),!1}return!0}return!1}(e,a)}return!1}
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -44,6 +44,7 @@ export type TextureSettings = {
44
44
  export interface Asset {
45
45
  id: string;
46
46
  name: string;
47
+ filename?: string;
47
48
  path?: string;
48
49
  type: AssetType;
49
50
  sourceFile?: string;
@@ -22,9 +22,38 @@ export declare class ObjectStorage<T extends Entity> {
22
22
  constructor(name: string, filePathFn?: (o: ObjectIndexEntry) => string);
23
23
  setBasePath(path: string): void;
24
24
  private determineIfMetaFileShouldBeCreated;
25
- watch(): Observable<T>;
25
+ createFolder(name: string, relativePath?: string): Promise<void>;
26
+ /**
27
+ * Deletes a folder and all it contains permanently.
28
+ */
29
+ deleteFolderForceDangerous(relativePath: string): Promise<void>;
30
+ /**
31
+ *
32
+ * @param from Relative path
33
+ * @param to Relative path that the given folder should be put into
34
+ */
35
+ moveFolder(from: string, to: string): Promise<void>;
36
+ renameFolder(folderPath: string, name: string): Promise<void>;
37
+ /**
38
+ *
39
+ * @param from Relative path
40
+ * @param to Relative path that the given folder should be put into
41
+ */
42
+ moveToFolder(object: T, to: string): Promise<void>;
43
+ getAbsolutePath(relativePath?: string): string;
44
+ /**
45
+ * @returns An array of folders
46
+ */
47
+ watchFolders(): Observable<string[]>;
48
+ watch(): Observable<{
49
+ event: "add" | "addDir" | "change" | "unlink" | "unlinkDir";
50
+ object: T;
51
+ path: string;
52
+ filename: string;
53
+ }>;
54
+ private reloadSubdirectory;
26
55
  private readFileIfExists;
27
- getAll(): Promise<T[]>;
56
+ getAll(relativePath?: string): Promise<T[]>;
28
57
  get(id: string): Promise<T>;
29
58
  save(obj: T): Promise<T>;
30
59
  rename(obj: T, name: string): Promise<T>;
@@ -41,6 +70,8 @@ export declare class ObjectStorage<T extends Entity> {
41
70
  replaceFile(asset: T, replacementFile: string): Promise<void>;
42
71
  deleteFile(fileKey: string): Promise<void>;
43
72
  private privateObjectPath;
73
+ private watchers;
74
+ private watchDir;
44
75
  }
45
76
  export declare function tokenizeName(name: string): string;
46
77
  export {};
@@ -1,4 +1,4 @@
1
- import{randomUUID as t}from"../../utils/uuid.js";import{pathJoin as e}from"../../utils/files.js";import{filter as i,firstValueFrom as a,from as s,map as n,mergeMap as r,Observable as h,Subject as o,switchMap as c,tap as l}from"rxjs";import{sleepDelay as d}from"../../utils/async.js";const u={},p={},w={};null==u.read&&window.require&&(Object.assign(u,window.require("fs")),Object.assign(p,u.promises),Object.assign(w,window.require("path")));const f=null!=u.existsSync;function m(){if(f){const t="--path=",e=window.process.argv.find((e=>e.startsWith(t)));return e?e.substring(t.length):""}return""}const y=/^[A-Z]:/;function g(...t){return 0===t.length?"":y.test(t[0])?w.join(...t):e(...t)}export class ObjectStorage{constructor(t,e){this.name=t,this.filePathFn=e,this.basePathUpdates=new o,this.basePath=this.basePathUpdates.pipe(n((t=>g(m(),t))),l((t=>{this.path=g(t,this.name),x(this.path),this.determineIfMetaFileShouldBeCreated()}))),this.loaded=a(this.basePath),this.shouldCreateIndex=!0}setBasePath(t){this.basePathUpdates.next(t)}async determineIfMetaFileShouldBeCreated(){try{(await p.readFile(g(m(),"vite.config.ts"))).toString().includes("hologyBuild")&&(this.shouldCreateIndex=!1)}catch(t){console.warn("Failed to read vite config to determine if meta files should be created")}}watch(){return P(),s(this.loaded).pipe(c((()=>function(t){return new h((e=>{const i=new AbortController,{signal:a}=i,s=p.watch(t,{recursive:!0,signal:a});return(async()=>{for await(const t of s)console.log(t),e.next(t)})(),()=>{i.abort()}}))}(this.path))),r((t=>s(this.readFileIfExists(t.filename)))),i((t=>null!=t)))}async readFileIfExists(t){const e=g(this.path,t);try{const i=await p.readFile(e);return{...JSON.parse(i.toString()),path:w.basename(t)}}catch{return console.warn("Could not find file at "+e),null}}async getAll(){if(f){await this.loaded,await x(this.path);const t=(await p.readdir(this.path,{recursive:!0,withFileTypes:!0})).filter((t=>t.isFile()&&t.name.endsWith(".json")&&!/^[\._]/.test(t.name)));return await Promise.all(t.map((t=>p.readFile(g(t.path,t.name)).then((e=>({...JSON.parse(e.toString()),path:t}))))))}const t=await this.loadIndex();return Promise.all(Object.keys(t).map((t=>this.get(t))))}async get(t){const e=await this.loadIndex(),i=e[t]??Object.values(e).find((e=>e.name===t));if(null==i)return;const a=this.privateObjectPath(i);if(!f)return(await fetch(a)).json();return await F(a)?JSON.parse((await p.readFile(a)).toString()):null}async save(t){return P(),await this.loaded,await p.writeFile(this.privateObjectPath(t),this.serialize(t)),await this.updateIndex(),t}async rename(t,e){const i={...t,name:e},a=this.privateObjectPath(t),s=this.privateObjectPath(i);try{await p.rename(a,s)}catch(t){console.error(t),console.warn("Rename failed, retrying",{currentPath:a,newPath:s}),await d(400),await p.rename(a,s)}return await this.save(i),await this.updateIndex(),i}async delete(t){await p.unlink(this.privateObjectPath(t)),this.updateIndex()}async create(e){return P(),await this.loaded,e.id=t(),await p.writeFile(this.privateObjectPath(e),this.serialize(e)),await this.updateIndex(),e}serialize(t){const e={...t};return delete e.path,JSON.stringify(e,null,2)}async updateIndex(){P();const t=await this.getAll(),e={};for(const i of t)e[i.id]={id:i.id,name:i.name??i.id,path:i.path};if(this.cachedIndex=e,f){if(!this.shouldCreateIndex)return;await p.writeFile(this.indexFilePath,JSON.stringify(e,null,2))}}get indexFilePath(){return g(this.path,"_meta.json")}async loadIndex(){return null==this.cachedIndex&&(f?await this.updateIndex():this.cachedIndex=await(await fetch(this.indexFilePath)).json()),this.cachedIndex}async ensureResourceDir(){await x(g(this.path+"-resources"))}async saveFile(t,e){return P(),await x(g(this.path+"-resources")),p.copyFile(e.path,g(this.path+"-resources",t.fileKey))}async saveExtraFile(t,e){return P(),await x(g(this.path+"-resources")),p.copyFile(t,g(this.path+"-resources",e))}getAssetPath(t){return window&&"function"==typeof window.require?window.require("path").join(this.path+"-resources",t.fileKey):g(this.path+"-resources",t.fileKey)}async replaceFile(t,e){if(await F(e))return p.copyFile(e,g(this.path+"-resources",t.fileKey));console.error("Failed to replace file using path "+e)}async deleteFile(t){if(null==t)return;P();const e=g(this.path+"-resources",t);return await F(e)?p.unlink(e):void 0}privateObjectPath(t){return this.filePathFn?g(this.path,this.filePathFn(t)):g(this.path,tokenizeName(t.name??t.id)+".json")}}export function tokenizeName(t){return t.trim().replace(/\s/g,"_").replace(/[^a-z0-9_\-\.]/gi,"")}async function x(t){f&&(await F(t)||await p.mkdir(t,{recursive:!0}))}function F(t){return!!f&&new Promise((function(e,i){u.exists(t,(function(t){e(t)}))}))}function P(){if(!f)throw new Error("Must have direct access to filesystem")}
1
+ import{randomUUID as e}from"../../utils/uuid.js";import{pathJoin as t}from"../../utils/files.js";import{combineLatest as a,EMPTY as i,filter as r,firstValueFrom as s,from as n,map as h,mergeAll as o,mergeMap as l,Observable as c,of as d,startWith as u,Subject as p,switchMap as w,tap as f}from"rxjs";import{sleepDelay as m}from"../../utils/async.js";const y={},v={},j={},F={};null==y.read&&window.require&&(Object.assign(y,window.require("fs")),Object.assign(v,y.promises),Object.assign(j,window.require("path")),Object.assign(F,window.require("chokidar")));const b=null!=y.existsSync;function g(){if(b){const e="--path=",t=window.process.argv.find((t=>t.startsWith(e)));return t?t.substring(e.length):""}return""}const x=/^[A-Z]:/;function P(...e){return 0===e.length?"":x.test(e[0])||b?j.join(...e):t(...e)}export class ObjectStorage{constructor(e,t){this.name=e,this.filePathFn=t,this.basePathUpdates=new p,this.basePath=this.basePathUpdates.pipe(h((e=>P(g(),e))),f((e=>{this.path=P(e,this.name),O(this.path),this.determineIfMetaFileShouldBeCreated()}))),this.loaded=s(this.basePath),this.shouldCreateIndex=!0,this.watchers=[]}setBasePath(e){this.basePathUpdates.next(e)}async determineIfMetaFileShouldBeCreated(){try{(await v.readFile(P(g(),"vite.config.ts"))).toString().includes("hologyBuild")&&(this.shouldCreateIndex=!1)}catch(e){console.warn("Failed to read vite config to determine if meta files should be created")}}async createFolder(e,t=""){S(),await v.mkdir(j.join(this.path,t,e),{recursive:!0})}async deleteFolderForceDangerous(e){await v.rm(j.join(this.path,e),{recursive:!0,force:!0})}async moveFolder(e,t){if(S(),""==e)return void console.warn("Can not move a folder in root");const a=j.resolve(j.join(this.path,t),j.basename(e));if(await async function(e){try{await v.access(e,v.constants.F_OK)}catch(e){return!1}return!0}(a)){if(a!==j.resolve(this.path,e))throw new Error("Can not move to directory as a file already exists with the same name")}else{if(function(e,t){const a=j.resolve(e),i=j.resolve(t),r=j.normalize(a)+j.sep;return(j.normalize(i)+j.sep).startsWith(r)}(j.join(this.path,e),j.join(this.path,t)))throw new Error("Can not move a folder into a folder it contains");await v.rename(j.join(this.path,e),a)}}async renameFolder(e,t){await v.rename(j.join(this.path,e),j.resolve(j.dirname(j.join(this.path,e)),t))}async moveToFolder(e,t){if(S(),e.path===t)return;const a=this.privateObjectPath({...e,path:t});await v.rename(this.privateObjectPath(e),a)}getAbsolutePath(e=""){return j.join(this.path,e)}watchFolders(){const e=v.readdir(this.path,{recursive:!0,withFileTypes:!0});return a([n(e),this.watchDir(this.path).pipe(r((e=>!e.filename.endsWith(".json"))),u(null))]).pipe(w((([e,t])=>null!=t?n(v.readdir(this.path,{recursive:!0,withFileTypes:!0})):d(e))),h((e=>Array.from(new Set(e.filter((e=>e.isDirectory())).map((e=>j.relative(this.path,j.join(e.path,e.name)).replace(/^\.$/,""))).values())))))}watch(){return S(),n(this.loaded).pipe(w((()=>this.watchDir(this.path))),l((e=>{const t={event:e.event,path:j.dirname(e.filename).replace(/^\.$/,""),filename:j.basename(e.filename)};return e.filename.endsWith(".json")?"unlink"!==e.event?n(this.readFileIfExists(e.filename)).pipe(h((e=>({object:e,...t})))):d({object:null,...t}):"change"===e.event?n(this.reloadSubdirectory(e.filename)).pipe(o(),h((e=>({object:e,...t})))):i})))}async reloadSubdirectory(e){return(await this.getAll(e)).filter((t=>t.path.startsWith(e)))}async readFileIfExists(e){console.log("read file if exists");const t=P(this.path,e);try{const a=await v.readFile(t);return{...JSON.parse(a.toString()),path:j.dirname(e).replace(/^\.$/,""),filename:j.basename(e)}}catch{return console.error("Could not find file at "+t),null}}async getAll(e){if(b){await this.loaded,await O(this.path);const t=(await v.readdir(j.join(this.path,e??""),{recursive:!0,withFileTypes:!0})).filter((e=>e.isFile()&&e.name.endsWith(".json")&&!/^[\._]/.test(e.name)));return await Promise.all(t.map((e=>v.readFile(P(e.path,e.name)).then((t=>({...JSON.parse(t.toString()),path:j.relative(this.path,e.path).replace(/^\.$/,""),filename:j.basename(e.path)}))))))}const t=await this.loadIndex();return Promise.all(Object.keys(t).map((e=>this.get(e))))}async get(e){const t=await this.loadIndex(),a=t[e]??Object.values(t).find((t=>t.name===e));if(null==a)return;const i=this.privateObjectPath(a);if(!b)return(await fetch(i)).json();return await I(i)?JSON.parse((await v.readFile(i)).toString()):null}async save(e){return S(),await this.loaded,await v.writeFile(this.privateObjectPath(e),this.serialize(e)),await this.updateIndex(),e}async rename(e,t){const a={...e,name:t},i=this.privateObjectPath(e),r=this.privateObjectPath(a);try{await v.rename(i,r)}catch(e){console.error(e),console.warn("Rename failed, retrying",{currentPath:i,newPath:r}),await m(400),await v.rename(i,r)}return await this.save(a),await this.updateIndex(),a}async delete(e){await v.unlink(this.privateObjectPath(e)),this.updateIndex()}async create(t){return S(),await this.loaded,t.id=e(),await v.writeFile(this.privateObjectPath(t),this.serialize(t)),await this.updateIndex(),t}serialize(e){const t={...e};return delete t.path,delete t.filename,JSON.stringify(t,null,2)}async updateIndex(){S();const e=await this.getAll(),t={};for(const a of e)t[a.id]={id:a.id,name:a.name??a.id,path:a.path};if(this.cachedIndex=t,b){if(!this.shouldCreateIndex)return;await v.writeFile(this.indexFilePath,JSON.stringify(t,null,2))}}get indexFilePath(){return P(this.path,"_meta.json")}async loadIndex(){return null==this.cachedIndex&&(b?await this.updateIndex():this.cachedIndex=await(await fetch(this.indexFilePath)).json()),this.cachedIndex}async ensureResourceDir(){await O(P(this.path+"-resources"))}async saveFile(e,t){return S(),await O(P(this.path+"-resources")),v.copyFile(t.path,P(this.path+"-resources",e.fileKey))}async saveExtraFile(e,t){return S(),await O(P(this.path+"-resources")),v.copyFile(e,P(this.path+"-resources",t))}getAssetPath(e){return window&&"function"==typeof window.require?window.require("path").join(this.path+"-resources",e.fileKey):P(this.path+"-resources",e.fileKey)}async replaceFile(e,t){if(await I(t))return v.copyFile(t,P(this.path+"-resources",e.fileKey));console.error("Failed to replace file using path "+t)}async deleteFile(e){if(null==e)return;S();const t=P(this.path+"-resources",e);return await I(t)?v.unlink(t):void 0}privateObjectPath(e){return this.filePathFn?P(this.path,e.path??"",this.filePathFn(e)):P(this.path,e.path??"",tokenizeName(e.name??e.id)+".json")}watchDir(e){return new c((t=>{const a=F.watch(e,{cwd:e});return a.on("all",((e,a,i)=>{t.next({event:e,filename:a})})),a.on("unlinkDir",(e=>{})),a.on("error",(()=>{})),this.watchers.push(a),()=>{a.close()}}))}}export function tokenizeName(e){return e.trim().replace(/\s/g,"_").replace(/[^a-z0-9_\-\.]/gi,"")}async function O(e){b&&(await I(e)||await v.mkdir(e,{recursive:!0}))}function I(e){return!!b&&new Promise((function(t,a){y.exists(e,(function(e){t(e)}))}))}function S(){if(!b)throw new Error("Must have direct access to filesystem")}
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -1,7 +1,7 @@
1
1
  import { Color, Material, Texture } from 'three';
2
2
  import { Shader } from '../shader.js';
3
3
  export declare class LambertShader extends Shader {
4
- color?: Color;
4
+ color: Color;
5
5
  emissive?: Color;
6
6
  emissiveIntensity?: number;
7
7
  emissiveMap?: Texture;
@@ -1,4 +1,4 @@
1
- import{__decorate as e,__metadata as t}from"tslib";import{Color as i,Texture as a,MeshLambertMaterial as r}from"three";import{Shader as p}from"../shader.js";import{Parameter as o}from"../parameter.js";export class LambertShader extends p{build(){return new r({color:this.color,emissive:this.emissive,emissiveIntensity:this.emissiveIntensity,emissiveMap:this.emissiveMap,map:this.map,lightMap:this.lightMap,lightMapIntensity:this.lightMapIntensity,aoMap:this.aoMap,aoMapIntensity:this.aoMapIntensity,specularMap:this.specularMap,alphaMap:this.alphaMap,envMap:this.envMap,reflectivity:this.reflectivity,refractionRatio:this.refractionRatio})}}e([o(),t("design:type",i)],LambertShader.prototype,"color",void 0),e([o(),t("design:type",i)],LambertShader.prototype,"emissive",void 0),e([o({range:[0,1]}),t("design:type",Number)],LambertShader.prototype,"emissiveIntensity",void 0),e([o(),t("design:type",a)],LambertShader.prototype,"emissiveMap",void 0),e([o(),t("design:type",a)],LambertShader.prototype,"map",void 0),e([o(),t("design:type",a)],LambertShader.prototype,"lightMap",void 0),e([o(),t("design:type",Number)],LambertShader.prototype,"lightMapIntensity",void 0),e([o(),t("design:type",a)],LambertShader.prototype,"aoMap",void 0),e([o(),t("design:type",Number)],LambertShader.prototype,"aoMapIntensity",void 0),e([o(),t("design:type",a)],LambertShader.prototype,"specularMap",void 0),e([o(),t("design:type",a)],LambertShader.prototype,"alphaMap",void 0),e([o(),t("design:type",a)],LambertShader.prototype,"envMap",void 0),e([o({range:[0,1]}),t("design:type",Number)],LambertShader.prototype,"reflectivity",void 0),e([o({range:[0,1]}),t("design:type",Number)],LambertShader.prototype,"refractionRatio",void 0);
1
+ import{__decorate as e,__metadata as t}from"tslib";import{Color as i,Texture as r,MeshLambertMaterial as a}from"three";import{Shader as p}from"../shader.js";import{Parameter as o}from"../parameter.js";import{removeObjectUndefined as s}from"../../utils/collections.js";export class LambertShader extends p{constructor(){super(...arguments),this.color=new i("#FFFFFF")}build(){return new a(s({color:this.color,emissive:this.emissive,emissiveIntensity:this.emissiveIntensity,emissiveMap:this.emissiveMap,map:this.map,lightMap:this.lightMap,lightMapIntensity:this.lightMapIntensity,aoMap:this.aoMap,aoMapIntensity:this.aoMapIntensity,specularMap:this.specularMap,alphaMap:this.alphaMap,envMap:this.envMap,reflectivity:this.reflectivity,refractionRatio:this.refractionRatio}))}}e([o(),t("design:type",i)],LambertShader.prototype,"color",void 0),e([o(),t("design:type",i)],LambertShader.prototype,"emissive",void 0),e([o({range:[0,1]}),t("design:type",Number)],LambertShader.prototype,"emissiveIntensity",void 0),e([o(),t("design:type",r)],LambertShader.prototype,"emissiveMap",void 0),e([o(),t("design:type",r)],LambertShader.prototype,"map",void 0),e([o(),t("design:type",r)],LambertShader.prototype,"lightMap",void 0),e([o(),t("design:type",Number)],LambertShader.prototype,"lightMapIntensity",void 0),e([o(),t("design:type",r)],LambertShader.prototype,"aoMap",void 0),e([o(),t("design:type",Number)],LambertShader.prototype,"aoMapIntensity",void 0),e([o(),t("design:type",r)],LambertShader.prototype,"specularMap",void 0),e([o(),t("design:type",r)],LambertShader.prototype,"alphaMap",void 0),e([o(),t("design:type",r)],LambertShader.prototype,"envMap",void 0),e([o({range:[0,1]}),t("design:type",Number)],LambertShader.prototype,"reflectivity",void 0),e([o({range:[0,1]}),t("design:type",Number)],LambertShader.prototype,"refractionRatio",void 0);
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -1,4 +1,4 @@
1
- import{__decorate as e,__metadata as t}from"tslib";import{Color as a,MeshStandardMaterial as p,Texture as d,Vector2 as i}from"three";import{Shader as r}from"../shader.js";import{Parameter as s}from"../parameter.js";import{removeObjectUndefined as n}from"../../utils/collections.js";export class StandardShader extends r{build(){return new p(n({color:this.color,roughness:this.roughness,metalness:this.metalness,map:this.map,lightMap:this.lightMap,lightMapIntensity:this.lightMapIntensity,aoMap:this.aoMap,aoMapIntensity:this.aoMapIntensity,emissive:this.emissive,emissiveIntensity:this.emissiveIntensity,emissiveMap:this.emissiveMap,bumpMap:this.bumpMap,bumpScale:this.bumpScale,normalMap:this.normalMap,normalScale:this.normalScale,displacementMap:this.displacementMap,displacementScale:this.displacementScale,displacementBias:this.displacementBias,roughnessMap:this.roughnessMap,metalnessMap:this.metalnessMap,alphaMap:this.alphaMap,envMap:this.envMap,envMapIntensity:this.envMapIntensity,refractionRatio:this.refractionRatio}))}}e([s(),t("design:type",a)],StandardShader.prototype,"color",void 0),e([s({range:[0,1]}),t("design:type",Number)],StandardShader.prototype,"roughness",void 0),e([s({range:[0,1]}),t("design:type",Number)],StandardShader.prototype,"metalness",void 0),e([s(),t("design:type",d)],StandardShader.prototype,"map",void 0),e([s(),t("design:type",d)],StandardShader.prototype,"lightMap",void 0),e([s(),t("design:type",Number)],StandardShader.prototype,"lightMapIntensity",void 0),e([s(),t("design:type",d)],StandardShader.prototype,"aoMap",void 0),e([s(),t("design:type",Number)],StandardShader.prototype,"aoMapIntensity",void 0),e([s(),t("design:type",a)],StandardShader.prototype,"emissive",void 0),e([s({range:[0,1]}),t("design:type",Number)],StandardShader.prototype,"emissiveIntensity",void 0),e([s(),t("design:type",d)],StandardShader.prototype,"emissiveMap",void 0),e([s(),t("design:type",d)],StandardShader.prototype,"bumpMap",void 0),e([s(),t("design:type",Number)],StandardShader.prototype,"bumpScale",void 0),e([s(),t("design:type",d)],StandardShader.prototype,"normalMap",void 0),e([s(),t("design:type",i)],StandardShader.prototype,"normalScale",void 0),e([s(),t("design:type",d)],StandardShader.prototype,"displacementMap",void 0),e([s(),t("design:type",Number)],StandardShader.prototype,"displacementScale",void 0),e([s(),t("design:type",Number)],StandardShader.prototype,"displacementBias",void 0),e([s(),t("design:type",d)],StandardShader.prototype,"roughnessMap",void 0),e([s(),t("design:type",d)],StandardShader.prototype,"metalnessMap",void 0),e([s(),t("design:type",d)],StandardShader.prototype,"alphaMap",void 0),e([s(),t("design:type",d)],StandardShader.prototype,"envMap",void 0),e([s({range:[0,1]}),t("design:type",Number)],StandardShader.prototype,"envMapIntensity",void 0),e([s({range:[0,1]}),t("design:type",Number)],StandardShader.prototype,"refractionRatio",void 0);
1
+ import{__decorate as e,__metadata as t}from"tslib";import{Color as a,MeshStandardMaterial as p,Texture as i,Vector2 as d}from"three";import{Shader as r}from"../shader.js";import{Parameter as s}from"../parameter.js";import{removeObjectUndefined as n}from"../../utils/collections.js";export class StandardShader extends r{constructor(){super(...arguments),this.color=new a("#FFFFFF")}build(){return new p(n({color:this.color,roughness:this.roughness,metalness:this.metalness,map:this.map,lightMap:this.lightMap,lightMapIntensity:this.lightMapIntensity,aoMap:this.aoMap,aoMapIntensity:this.aoMapIntensity,emissive:this.emissive,emissiveIntensity:this.emissiveIntensity,emissiveMap:this.emissiveMap,bumpMap:this.bumpMap,bumpScale:this.bumpScale,normalMap:this.normalMap,normalScale:this.normalScale,displacementMap:this.displacementMap,displacementScale:this.displacementScale,displacementBias:this.displacementBias,roughnessMap:this.roughnessMap,metalnessMap:this.metalnessMap,alphaMap:this.alphaMap,envMap:this.envMap,envMapIntensity:this.envMapIntensity,refractionRatio:this.refractionRatio}))}}e([s(),t("design:type",a)],StandardShader.prototype,"color",void 0),e([s({range:[0,1]}),t("design:type",Number)],StandardShader.prototype,"roughness",void 0),e([s({range:[0,1]}),t("design:type",Number)],StandardShader.prototype,"metalness",void 0),e([s(),t("design:type",i)],StandardShader.prototype,"map",void 0),e([s(),t("design:type",i)],StandardShader.prototype,"lightMap",void 0),e([s(),t("design:type",Number)],StandardShader.prototype,"lightMapIntensity",void 0),e([s(),t("design:type",i)],StandardShader.prototype,"aoMap",void 0),e([s(),t("design:type",Number)],StandardShader.prototype,"aoMapIntensity",void 0),e([s(),t("design:type",a)],StandardShader.prototype,"emissive",void 0),e([s({range:[0,1]}),t("design:type",Number)],StandardShader.prototype,"emissiveIntensity",void 0),e([s(),t("design:type",i)],StandardShader.prototype,"emissiveMap",void 0),e([s(),t("design:type",i)],StandardShader.prototype,"bumpMap",void 0),e([s(),t("design:type",Number)],StandardShader.prototype,"bumpScale",void 0),e([s(),t("design:type",i)],StandardShader.prototype,"normalMap",void 0),e([s(),t("design:type",d)],StandardShader.prototype,"normalScale",void 0),e([s(),t("design:type",i)],StandardShader.prototype,"displacementMap",void 0),e([s(),t("design:type",Number)],StandardShader.prototype,"displacementScale",void 0),e([s(),t("design:type",Number)],StandardShader.prototype,"displacementBias",void 0),e([s(),t("design:type",i)],StandardShader.prototype,"roughnessMap",void 0),e([s(),t("design:type",i)],StandardShader.prototype,"metalnessMap",void 0),e([s(),t("design:type",i)],StandardShader.prototype,"alphaMap",void 0),e([s(),t("design:type",i)],StandardShader.prototype,"envMap",void 0),e([s({range:[0,1]}),t("design:type",Number)],StandardShader.prototype,"envMapIntensity",void 0),e([s({range:[0,1]}),t("design:type",Number)],StandardShader.prototype,"refractionRatio",void 0);
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -1,4 +1,4 @@
1
- import*as t from"three";import{Vector3 as e}from"three";export function clamp(t,e,n){return Math.max(Math.min(n,t),e)}export function byChance(t,e){Math.random()<t&&e()}export function mean(t){let e=0,n=t.length;for(;--n>=0;)e+=t[n];return t.length>0?e/t.length:0}export function meanVectors3(t){const e=n.set(0,0,0);for(const n of t)e.add(n);return e.divideScalar(t.length),e}export function meanBottomVectors3(t){const e=n.set(0,0,0);let o=null;for(const n of t)e.add(n),(null==o||n.y<o)&&(o=n.y);return e.divideScalar(t.length),e.y=o,e}export function meanVectors3Mapped(t,n){const o=new e,r=new e;for(const e of t)r.add(n(e,o));return r.divideScalar(t.length),r}const n=new e;export function meanVectors3withWeight(t,e,o){let r=0;for(const t of e)r+=t;n.set(0,0,0);let a=0;for(const o of t){const t=e[a]/r;n.x+=o.x*t,n.y+=o.y*t,n.z+=o.z*t,a++}return o.copy(n),o}export function randomString(t=9){return Math.random().toString(36).substr(2,t)}export function toDegrees(t){return t*(180/Math.PI)}var o=new t.Sphere;export function boundingRadius(...e){o.makeEmpty();for(var n=0;n<e.length;n++)e[n].traverse((e=>{e instanceof t.Mesh&&(e.geometry.computeBoundingSphere(),o.union(e.geometry.boundingSphere))}));return o.radius}
1
+ import*as t from"three";import{Vector3 as e}from"three";export function clamp(t,e,n){return Math.max(Math.min(n,t),e)}export function byChance(t,e){Math.random()<t&&e()}export function mean(t){let e=0,n=t.length;for(;--n>=0;)e+=t[n];return t.length>0?e/t.length:0}export function meanVectors3(t){const e=n.set(0,0,0);for(const n of t)e.add(n);return e.divideScalar(t.length),e}export function meanBottomVectors3(t){const e=n.set(0,0,0);let o=null;for(const n of t)e.add(n),(null==o||n.y<o)&&(o=n.y);return e.divideScalar(t.length),e.y=o,e}export function meanVectors3Mapped(t,n){const o=new e,r=new e;for(const e of t)r.add(n(e,o));return r.divideScalar(t.length),r}const n=new e;export function meanVectors3withWeight(t,e,o){let r=0;for(const t of e)r+=t;n.set(0,0,0);let a=0;for(const o of t){const t=e[a]/r;n.x+=o.x*t,n.y+=o.y*t,n.z+=o.z*t,a++}return o.copy(n),o}export function randomString(t=9){return Math.random().toString(36).substr(2,t)}export function toDegrees(t){return t*(180/Math.PI)}var o=new t.Sphere,r=new t.Sphere;export function boundingRadius(...e){o.makeEmpty(),r.makeEmpty();for(var n=0;n<e.length;n++)e[n].traverse((e=>{if(e instanceof t.Mesh){const t=e.geometry;t.computeBoundingSphere(),r.copy(t.boundingSphere),r.applyMatrix4(e.matrixWorld),o.makeEmpty().union(r)}}));return o.radius}
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.