@hology/core 0.0.55 → 0.0.57
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/config/project-config.d.ts +5 -0
- package/dist/csm.d.ts +2 -3
- package/dist/csm.js +1 -1
- package/dist/effects/vfx/trail-renderer.js +1 -1
- package/dist/effects/vfx/vfx-materializer.js +1 -1
- package/dist/gameplay/actors/builtin/camera-actor.d.ts +0 -6
- package/dist/gameplay/actors/builtin/camera-actor.js +1 -1
- package/dist/gameplay/actors/camera/camera-component.d.ts +7 -2
- package/dist/gameplay/actors/camera/camera-component.js +1 -1
- package/dist/gameplay/initiate.d.ts +4 -0
- package/dist/gameplay/initiate.js +1 -1
- package/dist/gameplay/services/asset-loader.d.ts +1 -0
- package/dist/gameplay/services/asset-loader.js +1 -1
- package/dist/gameplay/services/physics/physics-system.js +1 -1
- package/dist/rendering.d.ts +5 -1
- package/dist/rendering.js +1 -1
- package/dist/scene/asset-resource-loader.d.ts +3 -0
- package/dist/scene/asset-resource-loader.js +1 -1
- package/dist/scene/landscape/landscape.js +1 -1
- package/dist/scene/materializer.d.ts +6 -7
- package/dist/scene/materializer.js +1 -1
- package/dist/scene/materials/grass-foliage.js +1 -1
- package/dist/scene/sky.js +1 -1
- package/dist/shader-nodes/effects.d.ts +2 -2
- package/dist/shader-nodes/effects.js +1 -1
- package/dist/shader-nodes/landscape.js +1 -1
- package/dist/shader-nodes/layers.js +1 -1
- package/dist/shader-nodes/shapes.js +1 -1
- package/dist/shader-nodes/voronoi.js +1 -1
- package/dist/utils/three/gpu-stats-panel.d.ts +10 -0
- package/dist/utils/three/gpu-stats-panel.js +5 -0
- package/dist/utils/three/outline-pass.d.ts +0 -1
- package/package.json +6 -5
- package/tsconfig.tsbuildinfo +1 -1
@@ -1,19 +1,18 @@
|
|
1
1
|
import { Subject } from "rxjs";
|
2
2
|
import * as THREE from "three";
|
3
3
|
import { Euler, Material, Object3D, Scene, Vector3 } from "three";
|
4
|
+
import { ContainerInstance } from "typedi";
|
4
5
|
import { GameComponent } from '../game-component/game-component.js';
|
6
|
+
import { BaseActor } from '../gameplay/actors/actor.js';
|
7
|
+
import { PhysicsBodyType } from '../gameplay/index.js';
|
5
8
|
import { RenderingView } from '../rendering.js';
|
6
9
|
import { ParameterType, PropertyParameter } from '../shader/parameter.js';
|
7
|
-
import {
|
10
|
+
import { ActorImpl, ShaderImpl } from '../shader/shader.js';
|
8
11
|
import { Type } from '../utils/type.js';
|
9
12
|
import { AssetResourceLoader } from './asset-resource-loader.js';
|
10
13
|
import { AssetsProvider } from './assets-provider.js';
|
11
14
|
import { LandscapeInitOptions } from './landscape/landscape.js';
|
12
|
-
import { Asset, CustomParamValue, MaterialAssignment, SerializedParamType, ShapeType } from './model.js';
|
13
|
-
import { BaseActor } from '../gameplay/actors/actor.js';
|
14
|
-
import { ContainerInstance } from "typedi";
|
15
|
-
import { PhysicsBodyType } from '../gameplay/index.js';
|
16
|
-
import { AssetId } from './model.js';
|
15
|
+
import { Asset, AssetId, CustomParamValue, MaterialAssignment, SerializedParamType, ShapeType } from './model.js';
|
17
16
|
export type SceneObjectId = string;
|
18
17
|
export type SceneObjectType = "asset_mesh" | "light" | "shape_mesh" | "spline" | "landscape" | "particles" | "global_fog" | "global_light" | "actor" | "group" | "prefab" | "vfx" | "sky";
|
19
18
|
export type LightType = "point" | "directional" | "ambient";
|
@@ -53,7 +52,7 @@ export type SceneObject = {
|
|
53
52
|
};
|
54
53
|
position?: number[];
|
55
54
|
scale?: number[];
|
56
|
-
rotation?: [number, number, number, THREE.EulerOrder
|
55
|
+
rotation?: [number, number, number, THREE.EulerOrder?];
|
57
56
|
collisionDetection?: boolean;
|
58
57
|
components?: AttachedComponent[];
|
59
58
|
hidden?: boolean;
|
@@ -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 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&&null==e.geometry.boundsTree&&e.geometry.computeBoundsTree()})),a}async createFromPrefabAsset(e){const t=await this.assetsService.getAsset(e.assetId);if(null==t)return void console.warn(`Can not find asset with id ${e.assetId} and name ${e.name}`);const a=new o;return t.prefab.objects.filter((e=>"global_fog"!==e.type)).forEach((e=>this.materialize(e,a,!0))),a}async createParticleSystem(e){const a=await this.assetsService.getAsset(e.assetId),s=new 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}
|
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,Matrix4 as l,Mesh as h,MeshLambertMaterial as m,MeshPhongMaterial as p,MeshStandardMaterial as d,Object3D as u,PointLight as f,Quaternion as y,SphereGeometry as g,Texture as w,Vector2 as S,Vector3 as v,Vector4 as A}from"three";import b,{SpriteRenderer as M}from"three-nebula";import{bool as x,BooleanNode as j,float as I,FloatNode as P,NodeShaderMaterial as D,rgb as N,RgbNode as E,Texture2dLookupNode as V,textureSampler2d as C,vec2 as F,Vec2Node as k,vec3 as z,Vec3Node as O,vec4 as _}from"three-shader-graph";import{VfxActor as B}from"../effects/vfx/vfx-actor.js";import{VisualEffect as T}from"../effects/vfx/vfx-param.js";import{BaseActor as $}from"../gameplay/actors/actor.js";import L from"../gameplay/actors/builtin/index.js";import{PhysicsBodyType as U,withInjectionContext as R}from"../gameplay/index.js";import{Sampler2DNode as W}from"../shader-nodes/index.js";import{LambertShader as J}from"../shader/builtin/lambert-shader.js";import{StandardShader as H}from"../shader/builtin/standard-shader.js";import{extractShaderParameters as q}from"../shader/parameter.js";import{ArrayMap as X,groupBy as G}from"../utils/collections.js";import{iterateMaterials as Y}from"../utils/materials.js";import{filterChildrenShallow as Z,filterSceneShallow as Q,findFirstVisibleObject as K}from"../utils/three/traverse.js";import{AssetMeshInstance as ee}from"./asset-resource-loader.js";import{isCollisionMesh as te}from"./collision/collision-shape-import.js";import{BoxCollisionShape as ae,PhysicalShapeMesh as se}from"./collision/collision-shape.js";import{LandscapeManager as re}from"./landscape/landscape-manager.js";import{initLandscape as ie}from"./landscape/landscape.js";import{SectionGrid as ne,smoothNormalsCrossMeshes as oe}from"./landscape/utils.js";import{createGrassFoliageMaterial as ce}from"./materials/grass-foliage.js";import{createGrassMaterial as le}from"./materials/grass.js";import{getMaterialAttribute as he}from"./materials/utils/material-painting.js";import{createWaterMaterial as me}from"./materials/water.js";import{SerializedParamType as pe}from"./model.js";import{ShapeLibrary as de,ShapeLibraryKeys as ue}from"./objects/shapes.js";import{ambientLightName as fe,createSky as ye,defaultSkyMaterial as ge}from"./sky.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=>{Ne(t.userData.src.materialAssignments,e.materialAssignments).forEach((e=>{this.applyMaterial(t,e)}))})),this.landscapeManagers.forEach((t=>{t.source.grass.layers.some((t=>t.meshes.some((t=>t.assetId===e.id))))&&t.queueRefreshScatter(this.renderingView?.camera.position??new v,!0)}))):"prefab"===e.type&&this.findByAssetId(e.id).forEach((e=>{const t=e.userData.src;this.remove(t),this.materializeAndInitActor(t)}))}))}async refreshMaterial(e,t,a,s){if(t?.userData?.assetId!==a.id)return;const r=await materialFromAsset(a,this.renderingView,this.assetsService,this.assetManagerService,this.shaders,!0);r.userData=t.userData,null!=s?Ve(e.material[s],r)||(e.material[s]=r):Ve(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!==U.dynamic&&"sky"!==e.type&&"global_fog"!==e.type}async canAssetBeInstanced(e){if(!this._canBeInstancedCache.has(e.assetId)){const t=await this.createFromAsset(e);if(null==t)return!1;const a=[];t.traverse((e=>{!te(e)&&e.isMesh&&a.push(e)}));const s=1==a.length&&0==a[0].children.length,r=a[0]instanceof h&&null!=a[0].geometry.morphAttributes&&Object.keys(a[0].geometry.morphAttributes).length>0,i=!0;this._canBeInstancedCache.set(e.assetId,s&&i&&!r)}return this._canBeInstancedCache.get(e.assetId)}async preInit(){this.renderingView?.onLoop((()=>{null!=this.sky&&this.renderingView.camera.getWorldPosition(this.sky.position)})),this.assetsService.getAssets().then((e=>{for(const t of e)this.assets.set(t.id,t)}))}async initWithInstancing(){await this.preInit(),await this.prefetchAssets();const e=[],a=new X,s=new X;for(const t of this.dataProvider.getObjects())await De(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!==U.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 ee;s.add(a),s.userData.src=e[0],t instanceof ee&&(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=K(a,(e=>!te(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 v).fromArray(e[i].position),(new y).setFromEuler((new r).fromArray(e[i].rotation)),(new v).fromArray(e[i].scale)),c=(new l).copy(e[i].parentTransform).multiply(o);n.setMatrixAt(i,c),n.castShadow=a.castShadow??!0,n.receiveShadow=s.receiveShadow??!0;const h=new ee;h.add(n),h.userData.src=e[0],a instanceof se&&(h.collisionShapes=[a.collisionShape]),h.castShadow=!1,h.receiveShadow=!1,this.scene.add(h)}}await Promise.all(e.map((e=>this.materialize(e)))),await this.initActorsPostInit()}async createInstancedMesh(e,a){const s=K(a,(e=>!te(e)&&null!=e.geometry)),i=await this.assetsService.getAsset(e[0].assetId);await this.applyMaterials(a,Ne(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 v).fromArray(e[a].position),(new y).setFromEuler((new r).fromArray(e[a].rotation)),(new v).fromArray(e[a].scale)),i=(new l).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 Q(this.scene,(t=>t.userData.src?.assetId==e),(e=>null!=e.userData.src))}applyMaterials(e,t){return null==t?Promise.resolve([]):Promise.all(t.filter((e=>"null"!==e.materialId)).map((t=>this.applyMaterial(e,t))))}async applyMaterial(e,t){await applyMaterial(e,t,(e=>{const t=this.assets.get(e);if(null!=t)return materialFromAsset(t,this.renderingView,this.assetsService,this.assetManagerService,this.shaders)}),this._originalMaterials)}unapplyMaterials(e){e.traverse((async e=>{if(e instanceof h)if(e.material instanceof Array)for(let t=0;t<e.material.length;t++)e.material[t]=this._originalMaterials.get(e.id+"#"+t)??e.material[t];else e.material=this._originalMaterials.get(e.id)??e.material}))}updateActors(e){console.log("update actors"),this.actorTypes=e;const t=new Set(Object.values(L));Q(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))),Q(this.scene,(e=>!0)).forEach((e=>{e.traverse((async e=>{if(e instanceof h)if(Array.isArray(e.material))for(let t=0;t<e.material.length;t++){const a=e.material[t].userData?.customShaderName;if(null!=a){const a=this.assets.get(e.material[t].userData.assetId);this.refreshMaterial(e,e.material[t],a,t)}}else{const t=e.material.userData?.customShaderName;if(null!=t){const t=this.assets.get(e.material.userData.assetId);this.refreshMaterial(e,e.material,t)}}}))}))}async update(e){if("sky"===e.type&&null!=this.sky&&null!=this.sky.parent)return void this.updateSky(e);const t=this.sceneObjectMap.get(e.id);if(t){let r=!1;if(t.traverseAncestors((e=>{"_hology_transform_group"===e.name&&(r=!0)})),!r){const a=this.findParent(e);null!=a&&a.uuid!=t.uuid?a.attach(t):console.error("Parent is wrong")}if("prefab"!==e.type&&"group"!==e.type){this.unapplyMaterials(t);this.inEditor&&e.hidden&&!1?t.traverse((e=>{e instanceof h&&(e.material.wireframe=!0)})):t.traverse((e=>{e instanceof h&&(e.material.wireframe=!1)}))}if("asset_mesh"===e.type){const a=this.assets.get(e.assetId);Ne(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=Ie(e.fog),t&&(a=this.scene).traverse((e=>{if(e instanceof h){const t=e.material;t instanceof D&&(a.fog instanceof i?(t.uniforms.fogFar.value=a.fog.far,t.uniforms.fogNear.value=a.fog.near):a.fog instanceof n&&(t.uniforms.density={value:a.fog.density}),t.needsUpdate=!0,t.uniformsNeedUpdate=!0)}})),this.fixFogColor()}else if("actor"===e.type){if(this.materializedActors.has(e.id)){const t=this.editorActorParamSnapshot.get(e.id);null!=t&&t===JSON.stringify(e.actor)||(console.log("Rematerializing actor because parameters changed"),r||(this.remove(e),await this.materializeAndInitActor(e)))}}else if("shape_mesh"===e.type){const a=await this.createMeshByShape(e.shape,t.material,e.shapeParams);t instanceof se&&(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 De(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:Z(t,(t=>t.children?.some((t=>t.id===e.id))),(()=>!0))))[0];return null==t?this.scene:null!=t?Q(this.scene,(e=>e.userData?.src?.id===t.id),(e=>null!=e.userData?.src))[0]:void 0}fixFogColor(){!0===this.renderingView.options.enableOutlines&&(this.scene.fog.color=new s(this.scene.fog.color))}findMeshWithGeometry(e){let t;return e.traverse((e=>{e instanceof h&&e.geometry&&(t=e)})),t}applyVertexMaterials(e,t){if(null==e.vertexMaterials||0===e.vertexMaterials.length)return;const a=G(e.vertexMaterials,(e=>e.m));t.traverse((e=>{if(e instanceof h){const t=he(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=he(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=Ie(e.fog),this.fixFogColor(),r=new o;break;case"sky":this.sky=ye(),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 se&&(e=function(e){if(e instanceof ae)return new h(new a(...e.offset.toArray()),Pe);return null}(r.collisionShape)),null!=e&&(e.layers.disable(0),e.layers.enable(18),e.scale.multiplyScalar(1.1),r.add(e))}return this.objectMap.set(r.uuid,e),this.sceneObjectMap.set(e.id,r),e.physics?.type!==U.dynamic||null==t||this.inEditor?null==t?this.scene.add(r):t?.add(r):(t.add(r),r.getWorldPosition(r.position),r.getWorldQuaternion(r.quaternion),r.getWorldScale(r.scale),this.scene?.attach(r)),null!=e.children&&await Promise.all(e.children?.map((e=>this.materialize(e,r,s)))),this.inEditor||"asset_mesh"!=e.type&&"shape_mesh"!==e.type||null!=e.physics?.type&&e.physics.type==U.dynamic||je(r),r}}async updateSky(e){if(null==e?.sky?.materialId)return void(this.sky.material=ge);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??L[e.actor?.type];if(null==t)return null;this.inEditor&&this.editorActorParamSnapshot.set(e.id,JSON.stringify(e.actor));const a=await this.actorProvider.create(t,(new v).fromArray(e.position),(new r).fromArray(e.rotation),!0);return this.materializedActors.set(e.id,a),a?.object}async createFromVfx(e){const t=await this.assetsService.getAsset(e.assetId);null==t&&console.error("Could not find asset",e);const a=await this.actorProvider.create(B,(new v).fromArray(e.position),(new r).fromArray(e.rotation),!1);return await a.fromAsset(t),a.play(),this.materializedActors.set(e.id,a),a?.object}cleanup(){this.materializedActors.clear()}async createFromShape(e){const t=this.inEditor&&e.hidden;let a;if("landscape"==e.shape)a=this.createLandscape(e),a.traverse((e=>{e instanceof h&&this._originalMaterials.set(e.id,e.material)}));else{let r=new d({name:"Default",color:new s("#aaaaaa"),visible:this.inEditor||!e.hidden,wireframe:!!t});const i=await this.createMeshByShape(e.shape,r,e.shapeParams);i.castShadow=e.castShadow??!0,i.receiveShadow=e.castShadow??!1,e.collisionDetection||(i.collisionShape=null),i.physics=e.physics,a=i,this._originalMaterials.set(a.id,i.material),a.traverse((e=>{}))}return t||(await Promise.all((e.materialAssignments??[]).filter((e=>null!=e.materialId)).map((e=>this.applyMaterial(a,e)))),this.applyVertexMaterials(e,a)),a}createLandscape(e){const t=e.landscape?.options;if(null==t)return console.error(`No landscape options exist on scene object ${e.id} ${e.name}`),new o;const a=ie(e.landscape.options);this.applyHeightMaps(a,e.landscape.heightMaps,!0);const s=new re(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 ne(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((()=>oe(r)),50)}async createMeshByShape(e,t,a={}){if("landscape"!==e&&ue.includes(e)){const s=await prepareShapeParameters(a??{}),r=e+JSON.stringify(a);return this.geometryCache.has(r)||this.geometryCache.set(r,de[e].geometry(s)),this.collisionShapeCache.has(r)||this.collisionShapeCache.set(r,de[e].collision(s)),new se(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);Ne(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 h&&"computeBoundsTree"in e.geometry&&null==e.geometry.boundsTree&&e.geometry.computeBoundsTree()})),a}async createFromPrefabAsset(e){const t=await this.assetsService.getAsset(e.assetId);if(null==t)return void console.warn(`Can not find asset with id ${e.assetId} and name ${e.name}`);const a=new o;return t.prefab.objects.filter((e=>"global_fog"!==e.type)).forEach((e=>this.materialize(e,a,!0))),a}async createParticleSystem(e){const a=await this.assetsService.getAsset(e.assetId),s=new u;return await b.fromJSONAsync(a.particleSystem,t).then((e=>{const a=new M(s,t);e.addRenderer(a),this.renderingView.onLoop((t=>e.update()))})),s}async createLight(e){if("point"===e.light.type){const t=new f(e.light.point.color,e.light.point.intensity,e.light.point.distance,e.light.point.decay);if(t.castShadow=e.light.point.castShadow??!0,this.inEditor){const e=new g(.3,10,10),a=new d({color:new s(16771709)}),r=new h(e,a);t.add(r)}return t}return"directional"===e.light.type?(this.applyDirectionalLight(e.light.directional),new o):"ambient"===e.light.type?(this.applyDirectionalAmbientLight(null,e.light.ambient),new o):void 0}applyDirectionalAmbientLight(e,t){const a=this.scene.children.find((e=>e.name===fe));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 m({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 m;switch(e.material.type){case"phong":m=new p({...l,...h});break;case"water":m=me(l,a);break;case"grassFoliage":m=ce({color:l.color,map:l.map},a);break;case"grass":m=le({...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:H,lambert:J}[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{m=s.build()}catch(t){console.log("Shader runtime error: "+t),be.has(e.material.shader)||be.set(e.material.shader,Ae.clone()),m=be.get(e.material.shader)}m.userData.customShaderName=e.material.shader}else console.warn("Missing shader implementation with name "+e.material.shader),m=Ae;break;default:throw new Error("Unsupported material type"+e.material.type)}return a?.csm.setupMaterial(m),o&&ve.set(c,m),m.side=e.material.side??m.side??t.FrontSide,m.transparent=(e.material.transparent??l.transparent??!1)||m.transparent,e.material.bloom&&(m.userData.hasBloom=!0),m.userData.assetId=e.id,m}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(pe.String,null==e||null==e.value||""==e.value)return null;const l=e.value;switch(e.type){case pe.Number:case pe.FloatNode:let h="string"==typeof l?parseFloat(l):l;return e.type===pe.FloatNode?I(h):h;case pe.Texture:return await a.getTexture(await t.getAsset(l));case pe.Sampler2DNode:return C(await a.getTexture(await t.getAsset(l)));case pe.Boolean:return l;case pe.BooleanNode:return x(l);case pe.Vector2:case pe.Vec2Node:if("object"==typeof l){const t=l instanceof Array?(new S).fromArray(l):new S(l.x,l.y);return e.type===pe.Vec2Node?F(t):t}return null;case pe.Vector3:case pe.Vec3Node:if("object"==typeof l){const t=l instanceof Array?(new v).fromArray(l):new v(l.x,l.y,l.z);return e.type===pe.Vec3Node?z(t):t}return null;case pe.Color:case pe.RgbNode:const m=new s(l);return e.type===pe.RgbNode?N(m):m;case pe.String:return l;case pe.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 pe.Euler:const d=l;return(new r).fromArray(d);case pe.Object3D:return(await a.getMesh(await t.getAsset(l))).scene;case pe.Material:return await materialFromAsset(await t.getAsset(l),n,t,a,o);case pe.AudioBuffer:return await a.getAudio(await t.getAsset(l));case pe.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 T(c,u);console.error("Using a non-vfx asset for visual effect parameter")}return null}function je(e){e.updateWorldMatrix(!1,!0),e.traverse((e=>{e.matrixAutoUpdate=!1,e.matrixWorldNeedsUpdate=!1}));const t=e.updateMatrixWorld;e.updateMatrixWorld=function(){t.apply(e),e.updateMatrixWorld=function(){}}}function Ie(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 Pe=new d({color:4229780});async function De(e,a,s,i){null==i&&(i=(new l).identity()),await a(e,s,i);const n=i.clone().multiply(function(e,t){if(null==e.position||null==e.rotation||null==e.scale)return t.identity();return t.compose((new v).fromArray(e.position),(new y).setFromEuler((new r).fromArray(e.rotation)),(new v).fromArray(e.scale))}(e,new t.Matrix4));return Promise.all((e.children??[]).map((t=>De(t,a,e,n))))}export function toSerializedParamType(e){const t=e.constructor.prototype;return t instanceof Number||e===Number?pe.Number:t instanceof P||"function"==typeof e.prototype.isFloat?pe.FloatNode:t instanceof w||e===w||e.isTexture?pe.Texture:t instanceof W||e===V?pe.Sampler2DNode:t instanceof Boolean||e===Boolean?pe.Boolean:t instanceof j?pe.BooleanNode:t instanceof s||e==s?pe.Color:t instanceof E||"function"==typeof e.prototype.isRgb?pe.RgbNode:t instanceof S||e==S?pe.Vector2:t instanceof k||"function"==typeof e.prototype.isVec2?pe.Vec2Node:t instanceof v||e==v?pe.Vector3:t instanceof O||"function"==typeof e.prototype.isVec3?pe.Vec3Node:t instanceof String||e===String?pe.String:t instanceof $||e==$||e.prototype instanceof $||e.prototype==$?pe.BaseActor:t instanceof r||e==r?pe.Euler:t instanceof u||e==u?pe.Object3D:t instanceof c||e==c?pe.Material:t instanceof AudioBuffer||e==AudioBuffer?pe.AudioBuffer:t instanceof T||e==T?pe.VisualEffect:void console.warn("Failed to map parameter type to serialized version",{type:e})}export function prepareCustomParams(e,t,a={}){return Object.fromEntries(e.map((e=>[e.name,{type:toSerializedParamType(e.type),value:t[e.name]?.value??a[e.name]??customParameterDefaultValueByType.get(toSerializedParamType(e.type))}])))}export function prepareCustomParamsFromType(e,t,a=null){const s=q(e);if(0===s.length)return{};let r;null!=a?R(a,(()=>{r=a.get(e)})):r=new e;const i={};for(const e of s){const t=r[e.name];if(null!=t){const a=serializeCustomParameter(e.type,t);null!=a&&(i[e.name]=a)}}return prepareCustomParams(s,t,i)}export function serializeCustomParameter(e,t){function a(){console.error("Failed to serialize value",{type:e,value:t})}switch(e){case Number:case Boolean:return t;case S:return t instanceof S?t.toArray():void a();case v:return t instanceof v?t.toArray():void a();case A:return t instanceof A?t.toArray():void a();case s:return t instanceof s?"#"+t.getHexString():"string"==typeof t?t:"number"==typeof t?"#"+new s(t).getHexString():void a();case String:return t;case r:return t instanceof r?t.toArray():void a()}}function Ne(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=>Ee(e.materialId))),(t??[]).filter((e=>Ee(e.materialId))),(e=>e.color+e.name))}function Ee(e){return"null"!=e&&null!=e}export const customParameterDefaultValueByType=new Map([[pe.RgbNode,"#000000"],[pe.Color,"#000000"],[pe.Vector4,[0,0,0,0]],[pe.Vec4Node,[0,0,0,0]],[pe.Vector3,[0,0,0]],[pe.Vec3Node,[0,0,0]],[pe.Vector2,[0,0]],[pe.Vec2Node,[0,0]],[pe.Euler,[0,0,0,"XYZ"]]]);export function applyMaterial(e,a,r,i){const n=[];return e.traverse((async e=>{if(e instanceof h||e.isMesh||e instanceof t.SkinnedMesh||e.isSkinnedMesh)for(const t of Y(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 Ve(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.
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import{attributes as m,float as o,lambertMaterial as l,NodeShaderMaterial as e,rgb as r,rgba as i,select as t,sin as a,smoothstep as p,transformed as n,translateAxis as u,uniformFloat as s,uniformSampler2d as f,varyingFloat as y,varyingVec2 as c}from"../../shader-nodes/index.js";import{Vector3 as v}from"three";import{CSMUtil as d}from"../../csm.js";export function createGrassFoliageMaterial(g,w){const x=n.mvPosition.z
|
1
|
+
import{attributes as m,float as o,lambertMaterial as l,NodeShaderMaterial as e,rgb as r,rgba as i,select as t,sin as a,smoothstep as p,transformed as n,translateAxis as u,uniformFloat as s,uniformSampler2d as f,varyingFloat as y,varyingVec2 as c}from"../../shader-nodes/index.js";import{Vector3 as v}from"three";import{CSMUtil as d}from"../../csm.js";export function createGrassFoliageMaterial(g,w){const x=n.mvPosition.z.multiply(o(-1)),h=y(p(o(100),o(60),x)),j=m.uv.y,z=r(11977268),B=o(.2),C=l(r(g.color)).rgb.multiplyScalar(o(.9)).add(z.multiplyScalar(y(j).multiply(B))),S=c(m.uv),b=f("map").sample(S,o(0)),F=i(C,b.x.multiply(h)),G=s("time"),L=o(.5).multiply(t(j.gt(o(0)),j.multiply(j),o(0))).multiply(a(G.multiply(o(.001)))),M=u(new v(1,0,0).normalize(),L),P=new e({color:F,transform:M,uniforms:{map:{value:g.map},time:{value:0}},transparent:!0});return P.onBeforeCompile=m=>{d.onBeforeCompile(P,m)},P.uniforms.map.value=g.map,w.onLoop((()=>{P.uniforms.time.value=performance.now()})),P}
|
2
2
|
/*
|
3
3
|
* Copyright (©) 2023. All rights reserved.
|
4
4
|
* See the LICENSE.md file for details.
|
package/dist/scene/sky.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import*as e from"three";import{AmbientLight as a,FogExp2 as t}from"three";import{attributes as r,NodeShaderMaterial as o,uniforms as i,vec4 as n,varyingVec3 as s,float as h,normalize as d,rgb as c,mix as m,max as w,pow as p}from"three-shader-graph";export function basicSceneSetup(r){!function(t){new a(16777215,.5);var r=new e.HemisphereLight(16777215,273,.5*Math.PI);r.name=ambientLightName,r.position.set(0,100,0),t.add(r);new e.HemisphereLightHelper(r,10);var o=new e.DirectionalLight(16777215,.7);o.position.set(-30,50,30),o.castShadow=!0,o.shadow.mapSize.width=2048,o.shadow.mapSize.height=2048;var i=250;o.shadow.normalBias=.3,o.shadow.camera.left=-i,o.shadow.camera.right=i,o.shadow.camera.top=i,o.shadow.camera.bottom=-i,o.shadow.camera.far=500,o.shadow.bias=-5e-4;new e.DirectionalLightHelper(o,10);var n=new e.PointLight(16777215,1,50);n.castShadow=!0,n.position.set(0,40,0),n.shadow.camera.near=1,n.shadow.camera.far=60,n.shadow.bias=-.005}(r),function(e){e.fog=new t(l,f)}(r)}export const ambientLightName="default_ambient";const l=157554,f=.005;export const defaultSkyMaterial=function(){const a=h(5),t=h(.6),l=new e.Color(16777215),f=new e.Color(13431551),g=s(i.modelMatrix.multiplyVec(n(r.position,1)).xyz
|
1
|
+
import*as e from"three";import{AmbientLight as a,FogExp2 as t}from"three";import{attributes as r,NodeShaderMaterial as o,uniforms as i,vec4 as n,varyingVec3 as s,float as h,normalize as d,rgb as c,mix as m,max as w,pow as p}from"three-shader-graph";export function basicSceneSetup(r){!function(t){new a(16777215,.5);var r=new e.HemisphereLight(16777215,273,.5*Math.PI);r.name=ambientLightName,r.position.set(0,100,0),t.add(r);new e.HemisphereLightHelper(r,10);var o=new e.DirectionalLight(16777215,.7);o.position.set(-30,50,30),o.castShadow=!0,o.shadow.mapSize.width=2048,o.shadow.mapSize.height=2048;var i=250;o.shadow.normalBias=.3,o.shadow.camera.left=-i,o.shadow.camera.right=i,o.shadow.camera.top=i,o.shadow.camera.bottom=-i,o.shadow.camera.far=500,o.shadow.bias=-5e-4;new e.DirectionalLightHelper(o,10);var n=new e.PointLight(16777215,1,50);n.castShadow=!0,n.position.set(0,40,0),n.shadow.camera.near=1,n.shadow.camera.far=60,n.shadow.bias=-.005}(r),function(e){e.fog=new t(l,f)}(r)}export const ambientLightName="default_ambient";const l=157554,f=.005;export const defaultSkyMaterial=function(){const a=h(5),t=h(.6),l=new e.Color(16777215),f=new e.Color(13431551),g=s(i.modelMatrix.multiplyVec(n(r.position,1)).xyz),u=d(g.addScalar(a)).y,S=w(p(w(u,h(0)),h(t)),h(0)),b=n(m(c(f),c(l),S),h(1)),y=new o({color:b.rgba});return y.side=e.BackSide,y.depthTest=!1,y}();export function createSky(){var a=new e.SphereGeometry(300,10,15),t=new e.Mesh(a,defaultSkyMaterial);return t.renderOrder=-999,t.raycast=()=>{},t}
|
2
2
|
/*
|
3
3
|
* Copyright (©) 2023. All rights reserved.
|
4
4
|
* See the LICENSE.md file for details.
|
@@ -1,5 +1,5 @@
|
|
1
|
-
import { FloatNode } from "three-shader-graph";
|
2
|
-
export declare function fresnelEffect(power?: number | FloatNode): FloatNode;
|
1
|
+
import { FloatNode, Vec3Node } from "three-shader-graph";
|
2
|
+
export declare function fresnelEffect(power?: number | FloatNode, normal?: Vec3Node): FloatNode;
|
3
3
|
/**
|
4
4
|
* Gives a factor for how shallow the depth is where 1 is the most shallow.
|
5
5
|
* This can be useful to for example create a highlight where an object intersects
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import{Vec3ExpressionNode as t,attributes as
|
1
|
+
import{Vec3ExpressionNode as t,attributes as e,dot as r,float as o,normalize as c,pow as i,saturate as n,uniforms as s,varyingAttributes as a,varyingVec3 as m,vec4 as p}from"three-shader-graph";import{fragmentLinearEyeDepth as u,linearEyeDepth as f}from"./depth.js";const l=s.modelMatrix.multiplyVec(p(e.position,1)),d=s.modelMatrix.multiplyVec(p(e.normal,0)).xyz;export function fresnelEffect(e=1,s=d){const a=new t("cameraPosition"),m=c(a.subtract(l.xyz)),p=o(1);return i(n(p.subtract(r(s,m))),o(e))}const x=o(1).subtract(f.subtract(u).divide(f));export function edgeDepthEffect(t=1){return i(x,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{attributes as r,float as t,uniforms as o,vec4 as e,varyingVec2 as a}from"three-shader-graph";const i=o.modelMatrix.multiplyVec(e(r.position,1));export function getLandscapeCoords(r){return a(i.xz
|
1
|
+
import{attributes as r,float as t,uniforms as o,vec4 as e,varyingVec2 as a}from"three-shader-graph";const i=o.modelMatrix.multiplyVec(e(r.position,1));export function getLandscapeCoords(r){return a(i.xz.multiplyScalar(t(r)))}
|
2
2
|
/*
|
3
3
|
* Copyright (©) 2023. All rights reserved.
|
4
4
|
* See the LICENSE.md file for details.
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import{float as e,uniforms as o,vec4 as r,attributes as t,varyingVec2 as a,AttributeVec3Node as i,varyingVec3 as l,SimplexNoiseNode as d,select as n,mix as s,smoothstep as y}from"three-shader-graph";export var LayerMixMode;!function(e){e[e.hard=0]="hard",e[e.soft=1]="soft"}(LayerMixMode||(LayerMixMode={}));const c={enableNoise:!0,noiseScale:e(.1),noiseAmount:e(.5),decay:.3,mode:LayerMixMode.soft},u=a(o.modelMatrix.multiplyVec(r(t.position,1)).xz
|
1
|
+
import{float as e,uniforms as o,vec4 as r,attributes as t,varyingVec2 as a,AttributeVec3Node as i,varyingVec3 as l,SimplexNoiseNode as d,select as n,mix as s,smoothstep as y}from"three-shader-graph";export var LayerMixMode;!function(e){e[e.hard=0]="hard",e[e.soft=1]="soft"}(LayerMixMode||(LayerMixMode={}));const c={enableNoise:!0,noiseScale:e(.1),noiseAmount:e(.5),decay:.3,mode:LayerMixMode.soft},u=a(o.modelMatrix.multiplyVec(r(t.position,1)).xz),m=l(new i("material")),p=[e(0),m.x,m.y,m.z];export function mixColorsByLayer(o){const r={...c,...o},t=e(r.noiseAmount).multiply(e(.1)),a=e(r.noiseScale),i=new d(u.multiplyScalar(a)).multiply(e(2)).subtract(e(1)).multiply(t),l=e(.5),m=r.enableNoise?l.add(i.multiply(e(.1))):l;if(r.mode==LayerMixMode.hard)return r.layerColors.reduce(((e,o,r)=>n(p[r].gt(m),o,e)));{const o=e(r.decay),t=e(.5),a=o.divide(e(2)),l=t.subtract(a),d=t.add(a);return r.layerColors.slice(0,p.length).reduce(((e,o,r)=>s(e,o,y(l,d,p[r].add(i)))))}}
|
2
2
|
/*
|
3
3
|
* Copyright (©) 2023. All rights reserved.
|
4
4
|
* See the LICENSE.md file for details.
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import{float as t,length as a,min as r,max as e,saturate as c,dFdx as d,dFdy as l,abs as u,ComponentsVec2Node as n,vec2 as i}from"three-shader-graph";export function rectangleFloat(t,a,e){const o=u(t.multiplyScalar(2).subtractScalar(1)).subtract(new n(a,e)),s=i(1,1).subtract(o.divide(u(d(p=o)).add(u(l(p)))));var p;return c(r(s.x
|
1
|
+
import{float as t,length as a,min as r,max as e,saturate as c,dFdx as d,dFdy as l,abs as u,ComponentsVec2Node as n,vec2 as i}from"three-shader-graph";export function rectangleFloat(t,a,e){const o=u(t.multiplyScalar(2).subtractScalar(1)).subtract(new n(a,e)),s=i(1,1).subtract(o.divide(u(d(p=o)).add(u(l(p)))));var p;return c(r(s.x,s.y))}export function roundedRectangleFloat(o,s,p,b){const m=e(r(r(u(b.multiply(2)),u(s)),u(p)),t(1e-5)),v=u(o.multiplyScalar(2).subtractScalar(1)).subtract(new n(s,p)).addScalar(m),S=a(e(i(0,0),v)).divide(m);return c(t(1).subtract(S).divide(u(d(y=S)).add(u(l(y)))));var y}
|
2
2
|
/*
|
3
3
|
* Copyright (©) 2023. All rights reserved.
|
4
4
|
* See the LICENSE.md file for details.
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import{select as t,length as a,ComponentsVec2Node as r,ConstantMat2Node as l,fract as d,sin as n,cos as e,vec2 as o,vec3 as u,floor as c}from"three-shader-graph";export function voronoi(i,p,m){const y=i.multiplyScalar(m),s=c(y),x=d(y),f=[-1,0,1],h=f.flatMap((t=>f.map((a=>[t,a])))).reduce(((c,[i,m])=>{const y=o(i,m),f=function(t,a){const o=new l(15.27,47.63,99.41,89.98);return t=d(n(t.multiplyMat(o)).multiplyScalar(46839.32)),new r(n(t.y
|
1
|
+
import{select as t,length as a,ComponentsVec2Node as r,ConstantMat2Node as l,fract as d,sin as n,cos as e,vec2 as o,vec3 as u,floor as c}from"three-shader-graph";export function voronoi(i,p,m){const y=i.multiplyScalar(m),s=c(y),x=d(y),f=[-1,0,1],h=f.flatMap((t=>f.map((a=>[t,a])))).reduce(((c,[i,m])=>{const y=o(i,m),f=function(t,a){const o=new l(15.27,47.63,99.41,89.98);return t=d(n(t.multiplyMat(o)).multiplyScalar(46839.32)),new r(n(t.y.add(a)).multiply(.5).add(.5),e(t.x.add(a)).multiply(.5).add(.5))}(y.add(s),p),h=a(y.add(f).subtract(x));return t(h.lt(c.x),u(h,f.x,f.y),c)}),u(8,0,0));return{noise:h.x,cells:h.y}}
|
2
2
|
/*
|
3
3
|
* Copyright (©) 2023. All rights reserved.
|
4
4
|
* See the LICENSE.md file for details.
|
@@ -0,0 +1,10 @@
|
|
1
|
+
export class GPUStatsPanel extends Stats.Panel {
|
2
|
+
constructor(context: any, name?: string);
|
3
|
+
context: any;
|
4
|
+
extension: any;
|
5
|
+
maxTime: number;
|
6
|
+
activeQueries: number;
|
7
|
+
startQuery: () => void;
|
8
|
+
endQuery: () => void;
|
9
|
+
}
|
10
|
+
import * as Stats from 'stats.js';
|
@@ -0,0 +1,5 @@
|
|
1
|
+
import*as e from"stats.js";class t extends e.Panel{constructor(e,t="GPU MS"){super(t,"#f90","#210");let i=!0,n=e.getExtension("EXT_disjoint_timer_query_webgl2");null===n&&(i=!1,n=e.getExtension("EXT_disjoint_timer_query"),null===n&&console.warn("GPUStatsPanel: disjoint_time_query extension not available.")),this.context=e,this.extension=n,this.maxTime=30,this.activeQueries=0,this.startQuery=function(){const e=this.context,t=this.extension;if(null===t)return;let n;i?(n=e.createQuery(),e.beginQuery(t.TIME_ELAPSED_EXT,n)):(n=t.createQueryEXT(),t.beginQueryEXT(t.TIME_ELAPSED_EXT,n)),this.activeQueries++;const r=()=>{let s,E,a;i?(s=e.getQueryParameter(n,e.QUERY_RESULT_AVAILABLE),E=e.getParameter(t.GPU_DISJOINT_EXT),a=e.getQueryParameter(n,e.QUERY_RESULT)):(s=t.getQueryObjectEXT(n,t.QUERY_RESULT_AVAILABLE_EXT),E=e.getParameter(t.GPU_DISJOINT_EXT),a=t.getQueryObjectEXT(n,t.QUERY_RESULT_EXT));const u=1e-6*a;s?(E||this.update(u,this.maxTime),this.activeQueries--):requestAnimationFrame(r)};requestAnimationFrame(r)},this.endQuery=function(){const e=this.extension,t=this.context;null!==e&&(i?t.endQuery(e.TIME_ELAPSED_EXT):e.endQueryEXT(e.TIME_ELAPSED_EXT))}}}export{t as GPUStatsPanel};
|
2
|
+
/*
|
3
|
+
* Copyright (©) 2023. All rights reserved.
|
4
|
+
* See the LICENSE.md file for details.
|
5
|
+
*/
|
@@ -35,7 +35,6 @@ export class OutlinePass extends Pass {
|
|
35
35
|
tempPulseColor1: Color;
|
36
36
|
tempPulseColor2: Color;
|
37
37
|
textureMatrix: Matrix4;
|
38
|
-
dispose(): void;
|
39
38
|
setSize(width: any, height: any): void;
|
40
39
|
changeVisibilityOfSelectedObjects(bVisible: any): void;
|
41
40
|
changeVisibilityOfNonSelectedObjects(bVisible: any): void;
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@hology/core",
|
3
|
-
"version": "0.0.
|
3
|
+
"version": "0.0.57",
|
4
4
|
"description": "",
|
5
5
|
"main": "dist/index.js",
|
6
6
|
"type": "module",
|
@@ -89,13 +89,14 @@
|
|
89
89
|
"@types/three-nebula": "^10.0.3",
|
90
90
|
"recast-navigation": "^0.30.0",
|
91
91
|
"rxjs": "7.8.1",
|
92
|
+
"stats-gl": "^3.0.1",
|
92
93
|
"stats.js": "^0.17.0",
|
93
|
-
"three": "^0.
|
94
|
+
"three": "^0.169.0",
|
94
95
|
"three-csm": "^4.2.1",
|
95
96
|
"three-mesh-bvh": "^0.7.5",
|
96
97
|
"three-nebula": "^10.0.3",
|
97
|
-
"three-shader-graph": "^0.
|
98
|
-
"three-stdlib": "2.
|
98
|
+
"three-shader-graph": "^0.2.3",
|
99
|
+
"three-stdlib": "2.34.0",
|
99
100
|
"ts-key-enum": "^2.0.12",
|
100
101
|
"typedi": "^0.10.0"
|
101
102
|
},
|
@@ -103,7 +104,7 @@
|
|
103
104
|
"@types/chokidar": "^2.1.3",
|
104
105
|
"@types/node": "^20.3.1",
|
105
106
|
"@types/offscreencanvas": "^2019.7.0",
|
106
|
-
"@types/three": "0.
|
107
|
+
"@types/three": "0.169.0",
|
107
108
|
"foreach-cli": "^1.8.1",
|
108
109
|
"jsdom": "^22.1.0",
|
109
110
|
"mkdirp": "^3.0.1",
|