@hology/core 0.0.26 → 0.0.27

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,4 @@
1
- import{__awaiter as e}from"tslib";import{Subject as t}from"rxjs";import*as i from"three";import{BoxGeometry as a,Color as r,Euler as s,Fog as n,FogExp2 as o,Group as l,Material as c,Mesh as d,MeshLambertMaterial as h,MeshPhongMaterial as u,MeshStandardMaterial as m,Object3D as p,PointLight as f,Quaternion as v,SphereGeometry as g,Texture as y,Vector2 as w,Vector3 as A,Vector4 as S}from"three";import b,{SpriteRenderer as M}from"three-nebula";import{bool as D,BooleanNode as I,float as x,FloatNode as P,NodeShaderMaterial as N,rgb as j,RgbNode as E,Texture2dLookupNode as O,textureSampler2d as F,vec2 as V,Vec2Node as B,vec3 as z,Vec3Node as C,vec4 as _}from"three-shader-graph";import T from"../gameplay/actors/builtin";import{extractShaderParameters as $}from"../shader/parameter";import{groupBy as k,ArrayMap as L}from"../utils/collections";import{filterChildrenShallow as R,filterSceneShallow as U}from"../utils/three/traverse";import{AssetMeshInstance as H}from"./asset-resource-loader";import{BoxCollisionShape as W,PhysicalShapeMesh as G}from"./collision/collision-shape";import{isCollisionMesh as J}from"./collision/collision-shape-import";import{initLandscape as X}from"./landscape/landscape";import{LandscapeManager as Y}from"./landscape/landscape-manager";import{SectionGrid as q,smoothNormalsCrossMeshes as Z}from"./landscape/utils";import{createGrassMaterial as K}from"./materials/grass";import{createGrassFoliageMaterial as Q}from"./materials/grass-foliage";import{getMaterialAttribute as ee}from"./materials/utils/material-painting";import{createWaterMaterial as te}from"./materials/water";import{SerializedParamType as ie}from"./model";import{Matrix4 as ae}from"three";import{BaseActor as re}from"../gameplay/actors/actor";import{Sampler2DNode as se}from"../shader-nodes";import{StandardShader as ne}from"../shader/builtin/standard-shader";import{LambertShader as oe}from"../shader/builtin/lambert-shader";import{ShapeLibrary as le,ShapeLibraryKeys as ce}from"./objects/shapes";import{ambientLightName as de}from"./sky";import{withInjectionContext as he}from"../gameplay";import{iterateMaterials as ue}from"../utils/materials";const me={};export const shapeDefaultColor="#aaaaaa";export class SceneMaterializerLoader{constructor(e,t,i){this.dataProvider=e,this.assetsService=t,this.assetManagerService=i}get(t,i){return new SceneMaterializer(t,this.dataProvider,this.assetsService,this.assetManagerService,i,[],[],{create:()=>null,initActor:()=>e(this,void 0,void 0,(function*(){}))})}}export class SceneMaterializer{constructor(i,a,r,s,n,o,l,c){this.scene=i,this.dataProvider=a,this.assetsService=r,this.assetManagerService=s,this.renderingView=n,this.shaders=o,this.actorTypes=l,this.actorProvider=c,this.objectMap=new Map,this.sceneObjectMap=new Map,this.components=[],this.landscapeManagers=[],this.materializedActors=new Map,this.inEditor=!0,this.updated$=new t,this.removed$=new t,this.error$=new t,this.editorActorParamSnapshot=new Map,this._canBeInstancedCache=new Map,this._originalMaterials=new Map,this.originalFog=null,a.onUpdate((e=>this.update(e))),a.onRemove((e=>this.remove(e))),this.updateSubscription=r.onUpdate.subscribe((t=>e(this,void 0,void 0,(function*(){"material"==t.type?((yield this.assetsService.getAssets()).filter((e=>{var i;return(null!==(i=e.materialAssignments)&&void 0!==i?i:[]).some((e=>e.materialId===t.id))})).forEach((e=>{const t=this.findByAssetId(e.id);e.materialAssignments.forEach((e=>{t.forEach((t=>{const i=t.userData.src.materialAssignments;null!=i&&i.some((t=>t.color===e.color))||this.applyMaterial(t,e)}))}))})),U(this.scene,(e=>{var i;return null!=e.userData.src&&(null!==(i=e.userData.src.materialAssignments)&&void 0!==i?i:[]).some((e=>e.materialId===t.id))}),(e=>null!=e.userData.src)).forEach((t=>e(this,void 0,void 0,(function*(){this.deleteSceneObject(t.userData.src),this.materialize(t.userData.src)}))))):"mesh"==t.type?this.findByAssetId(t.id).forEach((e=>{De(e.userData.src.materialAssignments,t.materialAssignments).forEach((t=>{this.applyMaterial(e,t)}))})):"prefab"===t.type&&this.findByAssetId(t.id).forEach((e=>{const t=e.userData.src;this.remove(t),this.materializeAndInitActor(t)}))}))))}get actorInstances(){return Array.from(this.materializedActors.values())}prefetchAssets(){return e(this,void 0,void 0,(function*(){const e=Array.from(new Set(this.dataProvider.getObjects().filter((e=>null!=e.assetId&&"asset_mesh"==e.type)).filter((e=>e.assetId))));yield Promise.all(e.map((e=>this.assetsService.getAsset(e.assetId).then((e=>e&&this.assetManagerService.getMesh(e))))))}))}init(){return e(this,void 0,void 0,(function*(){fe.clear(),yield this.prefetchAssets(),yield Promise.all(this.dataProvider.getObjects().map((e=>this.materialize(e)))),yield this.initActorsPostInit()}))}initActorsPostInit(t=this.actorInstances){const i=t.map((t=>e(this,void 0,void 0,(function*(){var e,i,a,r;const s=t.object.userData.src,n=yield this.assetsService.getAsset(s.assetId),o=Object.assign(Object.assign({},null!==(i=null===(e=null==n?void 0:n.actor)||void 0===e?void 0:e.params)&&void 0!==i?i:{}),null!==(a=s.actor.params)&&void 0!==a?a:{});for(const e of null!==(r=s.actor.innerParams)&&void 0!==r?r:[])yield this.applyActorComponentParams(t,e.path.slice(),e.params);const l=yield ye(o,t.constructor,this.assetsService,this.assetManagerService,this.materializedActors,this.renderingView,this.shaders);Object.assign(t,l);try{return yield this.actorProvider.initActor(t)}catch(e){console.error(`Failed to initiate actor (name="${s.name}", id=${s.id})`,e)}}))));return Promise.all(i)}applyActorComponentParams(t,i,a){return e(this,void 0,void 0,(function*(){const e=i.length,r=i.shift();if(0==e){const e=yield ye(a,null,this.assetsService,this.assetManagerService,this.materializedActors,this.renderingView,this.shaders);for(const[i,a]of Object.entries(e))null!=a&&(t[i]=a)}else null!=t[r]&&(yield this.applyActorComponentParams(t[r],i,a))}))}canAssetBeInstanced(t){return e(this,void 0,void 0,(function*(){if(!this._canBeInstancedCache.has(t.assetId)){const e=yield this.createFromAsset(t);if(null==e)return!1;const i=[];e.traverse((e=>{!J(e)&&e.isMesh&&i.push(e)}));const a=1==i.length&&0==i[0].children.length,r=!0;this._canBeInstancedCache.set(t.assetId,a&&r)}return this._canBeInstancedCache.get(t.assetId)}))}initWithInstancing(){return e(this,void 0,void 0,(function*(){const t=new L;for(const i of this.dataProvider.getObjects())yield be(i,((i,a,r)=>e(this,void 0,void 0,(function*(){var e,s;const n="asset_mesh"==i.type&&(yield this.canAssetBeInstanced(i))?i.assetId+JSON.stringify(null!==(e=i.materialAssignments)&&void 0!==e?e:[]):"other";"other"!==n&&a&&(null===(s=a.children)||void 0===s?void 0:s.length)>0&&a.children.splice(a.children.findIndex((e=>e.id===i.id)),1),"other"===n&&a||t.push(n,Object.assign(Object.assign({},i),{parentTransform:r}))}))));for(const[e,i]of t.entries())if("other"!==e&&i.length>0){const e=yield this.createFromAsset(i[0]);if(null==e)continue;const t=yield this.createInstancedMesh(i,e),a=new H;a.add(t),a.userData.src=i[0],e instanceof H&&(a.collisionShapes=e.collisionShapes),a.castShadow=!1,a.receiveShadow=!1,this.scene.add(a)}else yield Promise.all(i.map((e=>this.materialize(e))));yield this.initActorsPostInit()}))}createInstancedMesh(t,a){var r,n;return e(this,void 0,void 0,(function*(){const e=a.children.filter((e=>!J(e)))[0],o=yield this.assetsService.getAsset(t[0].assetId);yield this.applyMaterials(a,De(t[0].materialAssignments,o.materialAssignments)),e.updateMatrix();const l=e.geometry.clone().applyMatrix4(e.matrix),c=new i.InstancedMesh(l,e.material.clone(),t.length);c.material.side=i.FrontSide;for(let e=0;e<t.length;e++){const a=(new i.Matrix4).compose((new A).fromArray(t[e].position),(new v).setFromEuler((new s).fromArray(t[e].rotation)),(new A).fromArray(t[e].scale)),r=(new ae).copy(t[e].parentTransform).multiply(a);c.setMatrixAt(e,r)}return c.castShadow=null===(r=o.castShadow)||void 0===r||r,c.receiveShadow=null===(n=o.receiveShadow)||void 0===n||n,c}))}remove(e){if("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)}const t=this.sceneObjectMap.get(e.id);null==t||t.parent.remove(t),this.sceneObjectMap.delete(e.id),this.components.filter((t=>{var i;return(null===(i=t.object.userData.src)||void 0===i?void 0:i.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 U(this.scene,(t=>{var i;return(null===(i=t.userData.src)||void 0===i?void 0:i.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(t,i){const a=[];return t.traverse((t=>e(this,void 0,void 0,(function*(){if(t instanceof d||t.isMesh)for(const e of ue(t.material))e.hasOwnProperty("color")&&a.push(t)})))),Promise.all(a.map((t=>e(this,void 0,void 0,(function*(){var e,a,r,s;if(t.material instanceof Array)for(let r=0;r<t.material.length;r++){const s=t.material[r];if(null==s.color)continue;const n="#"+s.color.getHexString(),o=s.name;if(n===i.color&&(s.name===i.name||null==i.name)||t.userData["originalColor_"+r]===i.color&&t.userData["originalMaterialName_"+r]===i.name){const s=yield this.assetsService.getAsset(i.materialId),l=t.material[r];s&&(t.material[r]=yield materialFromAsset(s,this.renderingView,this.assetsService,this.assetManagerService,this.shaders),t.userData["originalColor_"+r]=null!==(e=t.userData["originalColor_"+r])&&void 0!==e?e:n,t.userData["originalMaterialName_"+r]=null!==(a=t.userData["originalMaterialName_"+r])&&void 0!==a?a:o,this.inEditor&&this._originalMaterials.set(t.id+"#"+r,l))}}else{const e="#"+t.material.color.getHexString(),a=t.material.name;if(e===i.color&&(t.material.name===i.name||null==i.name)||t.userData.originalColor===i.color&&t.userData.originalName===i.name){const n=yield this.assetsService.getAsset(i.materialId),o=t.material;n&&(t.material=yield materialFromAsset(n,this.renderingView,this.assetsService,this.assetManagerService,this.shaders),t.userData.originalColor=null!==(r=t.userData.originalColor)&&void 0!==r?r:e,t.userData.originalMaterialName=null!==(s=t.userData.originalMaterialName)&&void 0!==s?s:a,this.inEditor&&this._originalMaterials.set(t.id,o))}}})))))}unapplyMaterials(t){t.traverse((t=>e(this,void 0,void 0,(function*(){var e,i;if(t instanceof d)if(t.material instanceof Array)for(let i=0;i<t.material.length;i++)t.material[i]=null!==(e=this._originalMaterials.get(t.id+"#"+i))&&void 0!==e?e:t.material[i];else t.material=null!==(i=this._originalMaterials.get(t.id))&&void 0!==i?i:t.material}))))}updateActors(t){this.actorTypes=t;const i=new Set(Object.values(T));U(this.scene,(e=>{var t,a;return(null===(t=e.userData.src)||void 0===t?void 0:t.id)&&"actor"===e.userData.src.type&&this.materializedActors.has(null===(a=e.userData.src)||void 0===a?void 0:a.id)&&!i.has(e.userData.src.actor.type)})).forEach((t=>e(this,void 0,void 0,(function*(){this.remove(t.userData.src),yield this.materializeAndInitActor(t.userData.src)}))))}updateShaders(e){this.shaders=e;for(const[e,t]of fe.entries())t.userData.customShaderName&&fe.delete(e);this.landscapeManagers.forEach((t=>t.updateShaders(e))),U(this.scene,(e=>!0)).forEach((e=>{e.traverse((e=>{var t,i;if(e instanceof d){if(null!=(null===(t=e.material.userData)||void 0===t?void 0:t.customShaderName)){const t=null===(i=function(e,t){if(t(e))return e;let i;return e.traverseAncestors((e=>{null==i&&t(e)&&(i=e)})),i}(e,(e=>{var t;return null!=(null===(t=e.userData.src)||void 0===t?void 0:t.id)})))||void 0===i?void 0:i.userData.src;null!=t&&this.update(t)}}}))}))}update(t){return e(this,void 0,void 0,(function*(){const e=this.sceneObjectMap.get(t.id);if(e){const a=this.findParent(t);if(null!=a&&a.uuid!=e.uuid?a.attach(e):console.error("Parent is wrong"),"prefab"!==t.type){this.unapplyMaterials(e);this.inEditor&&t.hidden&&!1?e.traverse((e=>{e instanceof d&&(e.material.wireframe=!0)})):e.traverse((e=>{e instanceof d&&(e.material.wireframe=!1)}))}if("asset_mesh"===t.type){const i=yield this.assetsService.getAsset(t.assetId);De(t.materialAssignments,i.materialAssignments).forEach((t=>this.applyMaterial(e,t)))}else"shape_mesh"===t.type&&this.applyMaterials(e,t.materialAssignments);if(e.position.fromArray(t.position),e.scale.fromArray(t.scale),e.rotation.fromArray(t.rotation),this.applyVertexMaterials(t,e),"light"==t.type)if("point"==t.light.type){const i=e;i.color=new r(t.light.point.color),i.intensity=t.light.point.intensity,i.decay=t.light.point.decay,i.castShadow=t.light.point.castShadow,i.distance=Math.max(t.light.point.distance,0)}else"directional"===t.light.type?this.applyDirectionalLight(t.light.directional):"ambient"===t.light.type&&this.applyDirectionalAmbientLight(e,t.light.ambient);else if("landscape"===t.shape)this.applyHeightMaps(e,t.landscape.heightMaps),this.inEditor&&this.landscapeManagers.filter((e=>e.source.id===t.id)).forEach((e=>e.queueRefreshScatter(this.renderingView.camera.position,!0,(e=>!0))));else if("global_fog"===t.type){const e=(this.scene.fog instanceof o?"density":"linear")!==t.fog.type;this.scene.fog=Ae(t.fog),e&&(i=this.scene).traverse((e=>{if(e instanceof d){const t=e.material;t instanceof N&&(i.fog instanceof n?(t.uniforms.fogFar.value=i.fog.far,t.uniforms.fogNear.value=i.fog.near):i.fog instanceof o&&(t.uniforms.density={value:i.fog.density}),t.needsUpdate=!0,t.uniformsNeedUpdate=!0)}})),this.fixFogColor()}else if("actor"===t.type){if(this.materializedActors.has(t.id)){const e=this.editorActorParamSnapshot.get(t.id);null!=e&&e===JSON.stringify(t.actor)||(console.log("Rematerializing actor because parameters changed"),this.remove(t),yield this.materializeAndInitActor(t))}}else if("shape_mesh"===t.type){const i=yield this.createMeshByShape(t.shape,e.material,t.shapeParams);e instanceof G&&(e.geometry=i.geometry,e.collisionShape=i.collisionShape)}("asset_mesh"===t.type||"shape_mesh"===t.type&&"landscape"!==t.shape)&&pe(e,t.castShadow,t.receiveShadow),t.name&&t.name.length>0&&(e.name=t.name),this.updated$.next({object:e,source:t})}else{const e=yield this.materializeAndInitActor(t);this.updated$.next({object:e,source:t})}var i}))}materializeAndInitActor(t,i=this.findParent(t)){return e(this,void 0,void 0,(function*(){const e=yield this.materialize(t,i);if("actor"===t.type){const e=this.materializedActors.get(t.id);null!=e?yield this.initActorsPostInit([e]):console.error(`Something went wrong when creating actor ${t.id}`)}return e}))}findParent(e){const t=this.dataProvider.getObjects().flatMap((t=>t.id===e.id?null:R(t,(t=>{var i;return null===(i=t.children)||void 0===i?void 0:i.some((t=>t.id===e.id))}),(()=>!0))))[0];return null==t?this.scene:null!=t?U(this.scene,(e=>{var i,a;return(null===(a=null===(i=e.userData)||void 0===i?void 0:i.src)||void 0===a?void 0:a.id)===t.id}),(e=>{var t;return null!=(null===(t=e.userData)||void 0===t?void 0:t.src)}))[0]:void 0}fixFogColor(){!0===this.renderingView.options.enableOutlines&&(this.scene.fog.color=new r(this.scene.fog.color).convertSRGBToLinear())}findMeshWithGeometry(e){let t;return e.traverse((e=>{e instanceof d&&e.geometry&&(t=e)})),t}applyVertexMaterials(e,t){if(null==e.vertexMaterials||0===e.vertexMaterials.length)return;const i=k(e.vertexMaterials,(e=>e.m));t.traverse((e=>{if(e instanceof d){const t=ee(e,!1);if(null!=t){for(let e=0;e<t.array.length;e++)t.setX(e,0);t.needsUpdate=!0}}}));const a=new Set;for(const[e,r]of i.entries()){const i=null!=e?t.getObjectByName(e):this.findMeshWithGeometry(t);let s=!1;if(null==i)return void console.warn(`Failed to apply vertex materials on mesh with name "${e}"`);const n=ee(i,!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]),s=!0;s&&a.add(e)}this.inEditor&&this.landscapeManagers.filter((t=>t.source.id===e.id)).forEach((e=>e.queueRefreshScatter(this.renderingView.camera.position,!0,(e=>a.has(e.name)))))}materialize(t,i,r=!1){var s,n,o,c;return e(this,void 0,void 0,(function*(){let e;switch(t.type){case"asset_mesh":e=yield this.createFromAsset(t);break;case"shape_mesh":e=yield this.createFromShape(t);break;case"light":e=yield this.createLight(t);break;case"particles":e=yield this.createParticleSystem(t),t.collisionDetection=!1;break;case"global_fog":this.scene.fog=Ae(t.fog),this.fixFogColor(),e=new l;break;case"actor":e=yield this.createFromActor(t);break;case"group":e=new l;break;case"prefab":e=yield this.createFromPrefabAsset(t);break;default:throw console.log(t),new Error("unknown type "+t.type)}if(null!=e){if(t.name&&t.name.length>0&&(e.name=t.name),e.position.fromArray(t.position),e.scale.fromArray(t.scale),e.rotation.fromArray(t.rotation),r||(e.userData.src=t),!this.inEditor){const i=null!==(s=t.components)&&void 0!==s?s:[],a=null!=t.assetId&&null!==(o=null===(n=yield this.assetsService.getAsset(t.assetId))||void 0===n?void 0:n.components)&&void 0!==o?o:[];i.push(...a),i.length>0?e.userData.componentRefs=yield Promise.all(i.map(((i,a)=>this.createComponent(e,t,i,a)))):"asset_mesh"==t.type&&function(e){e.traverse((e=>{e.matrixAutoUpdate=!1,e.matrixWorldNeedsUpdate=!1}));const t=e.updateMatrixWorld;e.updateMatrixWorld=function(){t.apply(e),e.updateMatrixWorld=function(){}}}(e)}if(this.inEditor){let t=null;e instanceof G&&(t=function(e){if(e instanceof W)return new d(new a(...e.offset.toArray()),Se);return null}(e.collisionShape)),null!=t&&(t.layers.disable(0),t.layers.enable(18),t.scale.multiplyScalar(1.1),e.add(t))}return this.objectMap.set(e.uuid,t),this.sceneObjectMap.set(t.id,e),null==i?this.scene.add(e):null==i||i.add(e),null===(c=t.children)||void 0===c||c.forEach((t=>{this.materialize(t,e,r)})),e}}))}createComponent(t,i,a,r){return e(this,void 0,void 0,(function*(){const e=new me[a.path+"/"+a.className],s=i.id+r;e.id=s,e.object=t;for(const t of a.params)null!=t.value&&(e[t.name]=t.value);return this.components.push(e),s}))}createFromActor(t){var i,a,r;return e(this,void 0,void 0,(function*(){const e=null!==(a=null===(i=this.actorTypes.find((e=>{var i;return e.name===(null===(i=t.actor)||void 0===i?void 0:i.type)})))||void 0===i?void 0:i.type)&&void 0!==a?a:T[null===(r=t.actor)||void 0===r?void 0:r.type];if(null==e)return null;this.inEditor&&this.editorActorParamSnapshot.set(t.id,JSON.stringify(t.actor));const n=yield this.actorProvider.create(e,(new A).fromArray(t.position),(new s).fromArray(t.rotation),!0);return this.materializedActors.set(t.id,n),null==n?void 0:n.object}))}cleanup(){this.materializedActors.clear()}createFromShape(t){var i,a,s;return e(this,void 0,void 0,(function*(){const e=this.inEditor&&t.hidden;let n;if("landscape"==t.shape)n=this.createLandscape(t);else{const s=new m({name:"Default",color:new r("#aaaaaa"),visible:this.inEditor||!t.hidden,wireframe:e}),o=yield this.createMeshByShape(t.shape,s,t.shapeParams);o.castShadow=null===(i=t.castShadow)||void 0===i||i,o.receiveShadow=null!==(a=t.castShadow)&&void 0!==a&&a,t.collisionDetection||(o.collisionShape=null),n=o,this._originalMaterials.set(n.id,o.material),n.traverse((e=>{}))}return e||((null!==(s=t.materialAssignments)&&void 0!==s?s:[]).filter((e=>null!=e.materialId)).forEach((e=>this.applyMaterial(n,e))),this.applyVertexMaterials(t,n)),n}))}createLandscape(e){var t;if(null==(null===(t=e.landscape)||void 0===t?void 0:t.options))return console.error(`No landscape options exist on scene object ${e.id} ${e.name}`),new l;const i=X(e.landscape.options);this.applyHeightMaps(i,e.landscape.heightMaps,!0);const a=new Y(e,this.renderingView,i,this.assetManagerService,this.assetsService,this.shaders,(t=>{var i;(null!==(i=e.materialAssignments)&&void 0!==i?i:[]).filter((e=>null!=e.materialId)).forEach((e=>this.applyMaterial(t,e)))}));return this.landscapeManagers.push(a),a.refreshGeometry(),i}applyHeightMaps(e,t,i=!1){const a=new q(e.sections);for(const e of null!=t?t:[]){const t=a.find(e.x,e.y);if(!t)return;const i=t.geometry.getAttribute("position");for(const t of e.points)i.setY(t.i,t.y);i.needsUpdate=!0}const r=e.sections;r.forEach((e=>{e.geometry.computeBoundsTree(),e.geometry.computeVertexNormals()})),this.inEditor&&!i||setTimeout((()=>Z(r)),50)}createMeshByShape(t,i,a={}){return e(this,void 0,void 0,(function*(){if("landscape"!==t&&ce.includes(t)){const r=yield function(t){return e(this,void 0,void 0,(function*(){const e={};for(const[i,a]of Object.entries(t)){const t=yield we(a,null,null,null);null!=t&&(e[i]=t)}return e}))}(null!=a?a:{});return"cylinder"==t&&r.openEnded,new G(le[t].geometry(r),i,le[t].collision(r))}throw new Error(`Unsupported shape '${t}'`)}))}createFromAsset(t){var i,a,r,s;return e(this,void 0,void 0,(function*(){const e=yield this.assetsService.getAsset(t.assetId);if(null==e)return void console.warn(`Can not find asset with id ${t.assetId} and name ${t.name}`);let{scene:n}=yield this.assetManagerService.getMesh(e);De(t.materialAssignments,e.materialAssignments).forEach((e=>this.applyMaterial(n,e)));const o=null===(a=null!==(i=t.receiveShadow)&&void 0!==i?i:!!e.receiveShadow)||void 0===a||a,l=null!==(s=null!==(r=t.castShadow)&&void 0!==r?r:!!e.castShadow)&&void 0!==s&&s;return n.receiveShadow=o,pe(n,l,o),t.collisionDetection||(n.collisionShapes=[]),this.applyVertexMaterials(t,n),n.traverse((e=>{e instanceof d&&"computeBoundsTree"in e.geometry&&e.geometry.computeBoundsTree()})),n}))}createFromPrefabAsset(t){return e(this,void 0,void 0,(function*(){const e=yield this.assetsService.getAsset(t.assetId);if(null==e)return void console.warn(`Can not find asset with id ${t.assetId} and name ${t.name}`);const i=new l;return e.prefab.objects.filter((e=>"global_fog"!==e.type)).forEach((e=>this.materialize(e,i,!0))),i}))}createParticleSystem(t){return e(this,void 0,void 0,(function*(){const e=yield this.assetsService.getAsset(t.assetId),a=new p;return yield b.fromJSONAsync(e.particleSystem,i).then((e=>{const t=new M(a,i);e.addRenderer(t),this.renderingView.onLoop((t=>e.update()))})),a}))}createLight(t){var i;return e(this,void 0,void 0,(function*(){if("point"===t.light.type){const e=new f(t.light.point.color,t.light.point.intensity,t.light.point.distance,t.light.point.decay);if(e.castShadow=null===(i=t.light.point.castShadow)||void 0===i||i,this.inEditor){const t=new g(.3,10,10),i=new m({color:new r(16771709)}),a=new d(t,i);e.add(a)}return e}return"directional"===t.light.type?(this.applyDirectionalLight(t.light.directional),new l):"ambient"===t.light.type?(this.applyDirectionalAmbientLight(null,t.light.ambient),new l):void 0}))}applyDirectionalAmbientLight(e,t){const i=this.scene.children.find((e=>e.name===de));null!=i?(i.intensity=t.intensity,i.color.set(t.color),i.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()}}function pe(e,t,i){e.castShadow=t,e.receiveShadow=i,e.traverse((e=>{e.castShadow=t,e.receiveShadow=i}))}const fe=new Map,ve=new h({color:16711935}),ge=new Map;export function materialFromAsset(t,a,s,n,o,l=!0){var c,d,h,m,p,f,v,g,y,w,A;return e(this,void 0,void 0,(function*(){const e=JSON.stringify(t.material);if(l&&fe.has(e))return fe.get(e);const S={opacity:t.material.params.opacity,map:null,emissive:null!==(c=t.material.params.emissive)&&void 0!==c?c:null,metalness:null!==(d=t.material.params.metalness)&&void 0!==d?d:0,flatShading:null!==(h=t.material.params.flatShading)&&void 0!==h&&h,color:new r(t.material.params.color).convertSRGBToLinear(),transparent:null!=t.material.params.opacity&&t.material.params.opacity<1},b={};if(null!=t.material.params.map){const e=t.material.params.map,i=yield s.getAsset(e);null!=i&&(S.map=yield n.getTexture(i))}let M;switch(t.material.type){case"phong":M=new u(Object.assign(Object.assign({},S),b));break;case"water":M=te(S,a);break;case"grassFoliage":M=Q({color:S.color,map:S.map},a);break;case"grass":M=K(Object.assign(Object.assign({},S),{colorTwo:new r(t.material.params.colorTwo),colorThree:new r(t.material.params.colorThree)}),a);break;case"standard":case"lambert":case"shader":const e=null!==(m={standard:ne,lambert:oe}[t.material.type])&&void 0!==m?m:null===(p=o.find((e=>e.name==t.material.shader)))||void 0===p?void 0:p.type;if(e){const i=new e,r=yield ye(null!==(v=null===(f=t.material)||void 0===f?void 0:f.shaderParams)&&void 0!==v?v:{},e,s,n,null,a,o);Object.assign(i,r);try{M=i.build()}catch(e){console.log("Shader runtime error: "+e),ge.has(t.material.shader)||ge.set(t.material.shader,ve.clone()),M=ge.get(t.material.shader)}M.userData.customShaderName=t.material.shader}else console.warn("Missing shader implementation with name "+t.material.shader),M=ve;break;default:throw new Error("Unsupported material type"+t.material.type)}return null==a||a.csm.setupMaterial(M),l&&fe.set(e,M),M.side=null!==(y=null!==(g=t.material.side)&&void 0!==g?g:M.side)&&void 0!==y?y:i.FrontSide,M.transparent=null!==(A=null!==(w=t.material.transparent)&&void 0!==w?w:S.transparent)&&void 0!==A&&A||M.transparent,M}))}function ye(t,i,a,r,s,n,o){return e(this,void 0,void 0,(function*(){const e={};for(const[i,l]of Object.entries(t)){const t=yield we(l,a,r,s,n,o);null!=t&&(e[i]=t)}return e}))}function we(t,i,a,n,o,l){return e(this,void 0,void 0,(function*(){if(null==t||null==t.value||""==t.value)return null;const e=t.value;switch(t.type){case ie.Number:case ie.FloatNode:let c="string"==typeof e?parseFloat(e):e;return t.type===ie.FloatNode?x(c):c;case ie.Texture:return yield a.getTexture(yield i.getAsset(e));case ie.Sampler2DNode:return F(yield a.getTexture(yield i.getAsset(e)));case ie.Boolean:return e;case ie.BooleanNode:return D(e);case ie.Vector2:case ie.Vec2Node:if("object"==typeof e){const i=e instanceof Array?(new w).fromArray(e):new w(i.x,i.y);return t.type===ie.Vec2Node?V(i):i}return null;case ie.Vector3:case ie.Vec3Node:if("object"==typeof e){const i=e instanceof Array?(new A).fromArray(e):new A(i.x,i.y,i.z);return t.type===ie.Vec3Node?z(i):i}return null;case ie.Color:case ie.RgbNode:const d=new r(e).convertSRGBToLinear();return t.type===ie.RgbNode?j(d):d;case ie.String:return e;case ie.BaseActor:const h=e;return null==n&&console.warn("Class parameters can not be prepared as actors are not passed in"),null==n?void 0:n.get(h);case ie.Euler:const u=e;return(new s).fromArray(u);case ie.Object3D:return(yield a.getMesh(yield i.getAsset(e))).scene;case ie.Material:return yield materialFromAsset(yield i.getAsset(e),o,i,a,l);case ie.AudioBuffer:return yield a.getAudio(yield i.getAsset(e))}return null}))}function Ae(e){var t,i;return"linear"===e.type?new n(new r(e.color),null!==(t=e.near)&&void 0!==t?t:100,null!==(i=e.far)&&void 0!==i?i:1e3):"density"===e.type?new o(e.color,e.density):void console.warn("Invalid fog type",e)}const Se=new m({color:4229780});function be(t,a,r,n){var o;return e(this,void 0,void 0,(function*(){null==n&&(n=(new ae).identity()),yield a(t,r,n);const e=n.clone().multiply(function(e,t){return t.compose((new A).fromArray(e.position),(new v).setFromEuler((new s).fromArray(e.rotation)),(new A).fromArray(e.scale))}(t,new i.Matrix4));return Promise.all((null!==(o=t.children)&&void 0!==o?o:[]).map((i=>be(i,a,t,e))))}))}function Me(e){const t=e.constructor.prototype;return t instanceof Number||e===Number?ie.Number:t instanceof P||"function"==typeof e.prototype.isFloat?ie.FloatNode:t instanceof y||e===y||e.isTexture?ie.Texture:t instanceof se||e===O?ie.Sampler2DNode:t instanceof Boolean||e===Boolean?ie.Boolean:t instanceof I?ie.BooleanNode:t instanceof r||e==r?ie.Color:t instanceof E||"function"==typeof e.prototype.isRgb?ie.RgbNode:t instanceof w||e==w?ie.Vector2:t instanceof B||"function"==typeof e.prototype.isVec2?ie.Vec2Node:t instanceof A||e==A?ie.Vector3:t instanceof C||"function"==typeof e.prototype.isVec3?ie.Vec3Node:t instanceof String||e===String?ie.String:t instanceof re||e==re||e.prototype instanceof re||e.prototype==re?ie.BaseActor:t instanceof s||e==s?ie.Euler:t instanceof p||e==p?ie.Object3D:t instanceof c||e==c?ie.Material:t instanceof AudioBuffer||e==AudioBuffer?ie.AudioBuffer:void console.warn("Failed to map parameter type to serialized version",{type:e})}export function prepareCustomParams(e,t,i={}){return Object.fromEntries(e.map((e=>{var a,r,s;return[e.name,{type:Me(e.type),value:null!==(s=null!==(r=null===(a=t[e.name])||void 0===a?void 0:a.value)&&void 0!==r?r:i[e.name])&&void 0!==s?s:xe.get(Me(e.type))}]})))}export function prepareCustomParamsFromType(e,t,i=null){const a=$(e);if(0===a.length)return{};let r;null!=i?he(i,(()=>{r=i.get(e)})):r=new e;const s={};for(const e of a){const t=r[e.name];if(null!=t){const i=serializeCustomParameter(e.type,t);null!=i&&(s[e.name]=i)}}return prepareCustomParams(a,t,s)}export function serializeCustomParameter(e,t){function i(){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 i();case A:return t instanceof A?t.toArray():void i();case S:return t instanceof S?t.toArray():void i();case r:return t instanceof r?"#"+t.getHexString():"string"==typeof t?t:"number"==typeof t?"#"+new r(t).getHexString():void i();case String:return t;case s:return t instanceof s?t.toArray():void i()}}function De(e,t){return function(e,t,i){const a=[],r=new Set;for(const s of[...null!=e?e:[],...null!=t?t:[]]){const e=i(s);r.has(e)||(r.add(e),a.push(s))}return a}((null!=e?e:[]).filter((e=>Ie(e.materialId))),(null!=t?t:[]).filter((e=>Ie(e.materialId))),(e=>e.color+e.name))}function Ie(e){return"null"!=e&&null!=e}const xe=new Map([[ie.RgbNode,"#000000"],[ie.Color,"#000000"],[ie.Vector4,[0,0,0,0]],[ie.Vec4Node,[0,0,0,0]],[ie.Vector3,[0,0,0]],[ie.Vec3Node,[0,0,0]],[ie.Vector2,[0,0]],[ie.Vec2Node,[0,0]],[ie.Euler,[0,0,0,"XYZ"]]]);
1
+ import{__awaiter as e}from"tslib";import{Subject as t}from"rxjs";import*as i from"three";import{BoxGeometry as a,Color as r,Euler as s,Fog as n,FogExp2 as o,Group as l,Material as c,Mesh as d,MeshLambertMaterial as h,MeshPhongMaterial as u,MeshStandardMaterial as m,Object3D as p,PointLight as f,Quaternion as v,SphereGeometry as g,Texture as y,Vector2 as w,Vector3 as A,Vector4 as S}from"three";import b,{SpriteRenderer as M}from"three-nebula";import{bool as D,BooleanNode as I,float as x,FloatNode as P,NodeShaderMaterial as N,rgb as j,RgbNode as E,Texture2dLookupNode as O,textureSampler2d as F,vec2 as V,Vec2Node as B,vec3 as z,Vec3Node as C,vec4 as _}from"three-shader-graph";import T from"../gameplay/actors/builtin";import{extractShaderParameters as $}from"../shader/parameter";import{groupBy as k,ArrayMap as L}from"../utils/collections";import{filterChildrenShallow as R,filterSceneShallow as U}from"../utils/three/traverse";import{AssetMeshInstance as H}from"./asset-resource-loader";import{BoxCollisionShape as W,PhysicalShapeMesh as G}from"./collision/collision-shape";import{isCollisionMesh as J}from"./collision/collision-shape-import";import{initLandscape as X}from"./landscape/landscape";import{LandscapeManager as Y}from"./landscape/landscape-manager";import{SectionGrid as q,smoothNormalsCrossMeshes as Z}from"./landscape/utils";import{createGrassMaterial as K}from"./materials/grass";import{createGrassFoliageMaterial as Q}from"./materials/grass-foliage";import{getMaterialAttribute as ee}from"./materials/utils/material-painting";import{createWaterMaterial as te}from"./materials/water";import{SerializedParamType as ie}from"./model";import{Matrix4 as ae}from"three";import{BaseActor as re}from"../gameplay/actors/actor";import{Sampler2DNode as se}from"../shader-nodes";import{StandardShader as ne}from"../shader/builtin/standard-shader";import{LambertShader as oe}from"../shader/builtin/lambert-shader";import{ShapeLibrary as le,ShapeLibraryKeys as ce}from"./objects/shapes";import{ambientLightName as de}from"./sky";import{withInjectionContext as he}from"../gameplay";import{iterateMaterials as ue}from"../utils/materials";const me={};export const shapeDefaultColor="#aaaaaa";export class SceneMaterializerLoader{constructor(e,t,i){this.dataProvider=e,this.assetsService=t,this.assetManagerService=i}get(t,i){return new SceneMaterializer(t,this.dataProvider,this.assetsService,this.assetManagerService,i,[],[],{create:()=>null,initActor:()=>e(this,void 0,void 0,(function*(){}))})}}export class SceneMaterializer{constructor(i,a,r,s,n,o,l,c){this.scene=i,this.dataProvider=a,this.assetsService=r,this.assetManagerService=s,this.renderingView=n,this.shaders=o,this.actorTypes=l,this.actorProvider=c,this.objectMap=new Map,this.sceneObjectMap=new Map,this.components=[],this.landscapeManagers=[],this.materializedActors=new Map,this.inEditor=!0,this.updated$=new t,this.removed$=new t,this.error$=new t,this.editorActorParamSnapshot=new Map,this._canBeInstancedCache=new Map,this._originalMaterials=new Map,this.originalFog=null,a.onUpdate((e=>this.update(e))),a.onRemove((e=>this.remove(e))),this.updateSubscription=r.onUpdate.subscribe((t=>e(this,void 0,void 0,(function*(){"material"==t.type?((yield this.assetsService.getAssets()).filter((e=>{var i;return(null!==(i=e.materialAssignments)&&void 0!==i?i:[]).some((e=>e.materialId===t.id))})).forEach((e=>{const t=this.findByAssetId(e.id);e.materialAssignments.forEach((e=>{t.forEach((t=>{const i=t.userData.src.materialAssignments;null!=i&&i.some((t=>t.color===e.color))||this.applyMaterial(t,e)}))}))})),U(this.scene,(e=>{var i;return null!=e.userData.src&&(null!==(i=e.userData.src.materialAssignments)&&void 0!==i?i:[]).some((e=>e.materialId===t.id))}),(e=>null!=e.userData.src)).forEach((t=>e(this,void 0,void 0,(function*(){this.deleteSceneObject(t.userData.src),this.materialize(t.userData.src)}))))):"mesh"==t.type?this.findByAssetId(t.id).forEach((e=>{De(e.userData.src.materialAssignments,t.materialAssignments).forEach((t=>{this.applyMaterial(e,t)}))})):"prefab"===t.type&&this.findByAssetId(t.id).forEach((e=>{const t=e.userData.src;this.remove(t),this.materializeAndInitActor(t)}))}))))}get actorInstances(){return Array.from(this.materializedActors.values())}prefetchAssets(){return e(this,void 0,void 0,(function*(){const e=Array.from(new Set(this.dataProvider.getObjects().filter((e=>null!=e.assetId&&"asset_mesh"==e.type)).filter((e=>e.assetId))));yield Promise.all(e.map((e=>this.assetsService.getAsset(e.assetId).then((e=>e&&this.assetManagerService.getMesh(e))))))}))}init(){return e(this,void 0,void 0,(function*(){fe.clear(),yield this.prefetchAssets(),yield Promise.all(this.dataProvider.getObjects().map((e=>this.materialize(e)))),yield this.initActorsPostInit()}))}initActorsPostInit(t=this.actorInstances){const i=t.map((t=>e(this,void 0,void 0,(function*(){var e,i,a,r;const s=t.object.userData.src,n=yield this.assetsService.getAsset(s.assetId),o=Object.assign(Object.assign({},null!==(i=null===(e=null==n?void 0:n.actor)||void 0===e?void 0:e.params)&&void 0!==i?i:{}),null!==(a=s.actor.params)&&void 0!==a?a:{});for(const e of null!==(r=s.actor.innerParams)&&void 0!==r?r:[])yield this.applyActorComponentParams(t,e.path.slice(),e.params);const l=yield ye(o,t.constructor,this.assetsService,this.assetManagerService,this.materializedActors,this.renderingView,this.shaders);Object.assign(t,l);try{return yield this.actorProvider.initActor(t)}catch(e){console.error(`Failed to initiate actor (name="${s.name}", id=${s.id})`,e)}}))));return Promise.all(i)}applyActorComponentParams(t,i,a){return e(this,void 0,void 0,(function*(){const e=i.length,r=i.shift();if(0==e){const e=yield ye(a,null,this.assetsService,this.assetManagerService,this.materializedActors,this.renderingView,this.shaders);for(const[i,a]of Object.entries(e))null!=a&&(t[i]=a)}else null!=t[r]&&(yield this.applyActorComponentParams(t[r],i,a))}))}canAssetBeInstanced(t){return e(this,void 0,void 0,(function*(){if(!this._canBeInstancedCache.has(t.assetId)){const e=yield this.createFromAsset(t);if(null==e)return!1;const i=[];e.traverse((e=>{!J(e)&&e.isMesh&&i.push(e)}));const a=1==i.length&&0==i[0].children.length,r=!0;this._canBeInstancedCache.set(t.assetId,a&&r)}return this._canBeInstancedCache.get(t.assetId)}))}initWithInstancing(){return e(this,void 0,void 0,(function*(){const t=new L;for(const i of this.dataProvider.getObjects())yield be(i,((i,a,r)=>e(this,void 0,void 0,(function*(){var e,s;const n="asset_mesh"==i.type&&(yield this.canAssetBeInstanced(i))?i.assetId+JSON.stringify(null!==(e=i.materialAssignments)&&void 0!==e?e:[]):"other";"other"!==n&&a&&(null===(s=a.children)||void 0===s?void 0:s.length)>0&&a.children.splice(a.children.findIndex((e=>e.id===i.id)),1),"other"===n&&a||t.push(n,Object.assign(Object.assign({},i),{parentTransform:r}))}))));for(const[e,i]of t.entries())if("other"!==e&&i.length>0){const e=yield this.createFromAsset(i[0]);if(null==e)continue;const t=yield this.createInstancedMesh(i,e),a=new H;a.add(t),a.userData.src=i[0],e instanceof H&&(a.collisionShapes=e.collisionShapes),a.castShadow=!1,a.receiveShadow=!1,this.scene.add(a)}else yield Promise.all(i.map((e=>this.materialize(e))));yield this.initActorsPostInit()}))}createInstancedMesh(t,a){var r,n;return e(this,void 0,void 0,(function*(){const e=a.children.filter((e=>!J(e)))[0],o=yield this.assetsService.getAsset(t[0].assetId);yield this.applyMaterials(a,De(t[0].materialAssignments,o.materialAssignments)),e.updateMatrix();const l=e.geometry.clone().applyMatrix4(e.matrix),c=new i.InstancedMesh(l,e.material.clone(),t.length);c.material.side=i.FrontSide;for(let e=0;e<t.length;e++){const a=(new i.Matrix4).compose((new A).fromArray(t[e].position),(new v).setFromEuler((new s).fromArray(t[e].rotation)),(new A).fromArray(t[e].scale)),r=(new ae).copy(t[e].parentTransform).multiply(a);c.setMatrixAt(e,r)}return c.castShadow=null===(r=o.castShadow)||void 0===r||r,c.receiveShadow=null===(n=o.receiveShadow)||void 0===n||n,c}))}remove(e){if("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)}const t=this.sceneObjectMap.get(e.id);null==t||t.parent.remove(t),this.sceneObjectMap.delete(e.id),this.components.filter((t=>{var i;return(null===(i=t.object.userData.src)||void 0===i?void 0:i.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 U(this.scene,(t=>{var i;return(null===(i=t.userData.src)||void 0===i?void 0:i.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(t,i){const a=[];return t.traverse((t=>e(this,void 0,void 0,(function*(){if(t instanceof d||t.isMesh)for(const e of ue(t.material))e.hasOwnProperty("color")&&a.push(t)})))),Promise.all(a.map((t=>e(this,void 0,void 0,(function*(){var e,a,r,s;if(t.material instanceof Array)for(let r=0;r<t.material.length;r++){const s=t.material[r];if(null==s.color)continue;const n="#"+s.color.getHexString(),o=s.name;if(n===i.color&&(s.name===i.name||null==i.name)||t.userData["originalColor_"+r]===i.color&&t.userData["originalMaterialName_"+r]===i.name){const s=yield this.assetsService.getAsset(i.materialId),l=t.material[r];s&&(t.material[r]=yield materialFromAsset(s,this.renderingView,this.assetsService,this.assetManagerService,this.shaders),t.userData["originalColor_"+r]=null!==(e=t.userData["originalColor_"+r])&&void 0!==e?e:n,t.userData["originalMaterialName_"+r]=null!==(a=t.userData["originalMaterialName_"+r])&&void 0!==a?a:o,this.inEditor&&this._originalMaterials.set(t.id+"#"+r,l))}}else{const e="#"+t.material.color.getHexString(),a=t.material.name;if(e===i.color&&(t.material.name===i.name||null==i.name)||t.userData.originalColor===i.color&&t.userData.originalName===i.name){const n=yield this.assetsService.getAsset(i.materialId),o=t.material;n&&(t.material=yield materialFromAsset(n,this.renderingView,this.assetsService,this.assetManagerService,this.shaders),t.userData.originalColor=null!==(r=t.userData.originalColor)&&void 0!==r?r:e,t.userData.originalMaterialName=null!==(s=t.userData.originalMaterialName)&&void 0!==s?s:a,this.inEditor&&this._originalMaterials.set(t.id,o))}}})))))}unapplyMaterials(t){t.traverse((t=>e(this,void 0,void 0,(function*(){var e,i;if(t instanceof d)if(t.material instanceof Array)for(let i=0;i<t.material.length;i++)t.material[i]=null!==(e=this._originalMaterials.get(t.id+"#"+i))&&void 0!==e?e:t.material[i];else t.material=null!==(i=this._originalMaterials.get(t.id))&&void 0!==i?i:t.material}))))}updateActors(t){this.actorTypes=t;const i=new Set(Object.values(T));U(this.scene,(e=>{var t,a;return(null===(t=e.userData.src)||void 0===t?void 0:t.id)&&"actor"===e.userData.src.type&&this.materializedActors.has(null===(a=e.userData.src)||void 0===a?void 0:a.id)&&!i.has(e.userData.src.actor.type)})).forEach((t=>e(this,void 0,void 0,(function*(){this.remove(t.userData.src),yield this.materializeAndInitActor(t.userData.src)}))))}updateShaders(e){this.shaders=e;for(const[e,t]of fe.entries())t.userData.customShaderName&&fe.delete(e);this.landscapeManagers.forEach((t=>t.updateShaders(e))),U(this.scene,(e=>!0)).forEach((e=>{e.traverse((e=>{var t,i;if(e instanceof d){if(null!=(null===(t=e.material.userData)||void 0===t?void 0:t.customShaderName)){const t=null===(i=function(e,t){if(t(e))return e;let i;return e.traverseAncestors((e=>{null==i&&t(e)&&(i=e)})),i}(e,(e=>{var t;return null!=(null===(t=e.userData.src)||void 0===t?void 0:t.id)})))||void 0===i?void 0:i.userData.src;null!=t&&this.update(t)}}}))}))}update(t){return e(this,void 0,void 0,(function*(){const e=this.sceneObjectMap.get(t.id);if(e){const a=this.findParent(t);if(null!=a&&a.uuid!=e.uuid?a.attach(e):console.error("Parent is wrong"),"prefab"!==t.type){this.unapplyMaterials(e);this.inEditor&&t.hidden&&!1?e.traverse((e=>{e instanceof d&&(e.material.wireframe=!0)})):e.traverse((e=>{e instanceof d&&(e.material.wireframe=!1)}))}if("asset_mesh"===t.type){const i=yield this.assetsService.getAsset(t.assetId);De(t.materialAssignments,i.materialAssignments).forEach((t=>this.applyMaterial(e,t)))}else"shape_mesh"===t.type&&this.applyMaterials(e,t.materialAssignments);if(e.position.fromArray(t.position),e.scale.fromArray(t.scale),e.rotation.fromArray(t.rotation),this.applyVertexMaterials(t,e),"light"==t.type)if("point"==t.light.type){const i=e;i.color=new r(t.light.point.color),i.intensity=t.light.point.intensity,i.decay=t.light.point.decay,i.castShadow=t.light.point.castShadow,i.distance=Math.max(t.light.point.distance,0)}else"directional"===t.light.type?this.applyDirectionalLight(t.light.directional):"ambient"===t.light.type&&this.applyDirectionalAmbientLight(e,t.light.ambient);else if("landscape"===t.shape)this.applyHeightMaps(e,t.landscape.heightMaps),this.inEditor&&this.landscapeManagers.filter((e=>e.source.id===t.id)).forEach((e=>e.queueRefreshScatter(this.renderingView.camera.position,!0,(e=>!0))));else if("global_fog"===t.type){const e=(this.scene.fog instanceof o?"density":"linear")!==t.fog.type;this.scene.fog=Ae(t.fog),e&&(i=this.scene).traverse((e=>{if(e instanceof d){const t=e.material;t instanceof N&&(i.fog instanceof n?(t.uniforms.fogFar.value=i.fog.far,t.uniforms.fogNear.value=i.fog.near):i.fog instanceof o&&(t.uniforms.density={value:i.fog.density}),t.needsUpdate=!0,t.uniformsNeedUpdate=!0)}})),this.fixFogColor()}else if("actor"===t.type){if(this.materializedActors.has(t.id)){const e=this.editorActorParamSnapshot.get(t.id);null!=e&&e===JSON.stringify(t.actor)||(console.log("Rematerializing actor because parameters changed"),this.remove(t),yield this.materializeAndInitActor(t))}}else if("shape_mesh"===t.type){const i=yield this.createMeshByShape(t.shape,e.material,t.shapeParams);e instanceof G&&(e.geometry=i.geometry,e.collisionShape=i.collisionShape)}("asset_mesh"===t.type||"shape_mesh"===t.type&&"landscape"!==t.shape)&&pe(e,t.castShadow,t.receiveShadow),t.name&&t.name.length>0&&(e.name=t.name),this.updated$.next({object:e,source:t})}else{const e=yield this.materializeAndInitActor(t);this.updated$.next({object:e,source:t})}var i}))}materializeAndInitActor(t,i=this.findParent(t)){return e(this,void 0,void 0,(function*(){const e=yield this.materialize(t,i);if("actor"===t.type){const e=this.materializedActors.get(t.id);null!=e?yield this.initActorsPostInit([e]):console.error(`Something went wrong when creating actor ${t.id}`)}return e}))}findParent(e){const t=this.dataProvider.getObjects().flatMap((t=>t.id===e.id?null:R(t,(t=>{var i;return null===(i=t.children)||void 0===i?void 0:i.some((t=>t.id===e.id))}),(()=>!0))))[0];return null==t?this.scene:null!=t?U(this.scene,(e=>{var i,a;return(null===(a=null===(i=e.userData)||void 0===i?void 0:i.src)||void 0===a?void 0:a.id)===t.id}),(e=>{var t;return null!=(null===(t=e.userData)||void 0===t?void 0:t.src)}))[0]:void 0}fixFogColor(){!0===this.renderingView.options.enableOutlines&&(this.scene.fog.color=new r(this.scene.fog.color).convertSRGBToLinear())}findMeshWithGeometry(e){let t;return e.traverse((e=>{e instanceof d&&e.geometry&&(t=e)})),t}applyVertexMaterials(e,t){if(null==e.vertexMaterials||0===e.vertexMaterials.length)return;const i=k(e.vertexMaterials,(e=>e.m));t.traverse((e=>{if(e instanceof d){const t=ee(e,!1);if(null!=t){for(let e=0;e<t.array.length;e++)t.setX(e,0);t.needsUpdate=!0}}}));const a=new Set;for(const[e,r]of i.entries()){const i=null!=e?t.getObjectByName(e):this.findMeshWithGeometry(t);let s=!1;if(null==i)return void console.warn(`Failed to apply vertex materials on mesh with name "${e}"`);const n=ee(i,!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]),s=!0;s&&a.add(e)}this.inEditor&&this.landscapeManagers.filter((t=>t.source.id===e.id)).forEach((e=>e.queueRefreshScatter(this.renderingView.camera.position,!0,(e=>a.has(e.name)))))}materialize(t,i,r=!1){var s,n,o,c;return e(this,void 0,void 0,(function*(){let e;switch(t.type){case"asset_mesh":e=yield this.createFromAsset(t);break;case"shape_mesh":e=yield this.createFromShape(t);break;case"light":e=yield this.createLight(t);break;case"particles":e=yield this.createParticleSystem(t),t.collisionDetection=!1;break;case"global_fog":this.scene.fog=Ae(t.fog),this.fixFogColor(),e=new l;break;case"actor":e=yield this.createFromActor(t);break;case"group":e=new l;break;case"prefab":e=yield this.createFromPrefabAsset(t);break;default:throw console.log(t),new Error("unknown type "+t.type)}if(null!=e){if(t.name&&t.name.length>0&&(e.name=t.name),e.position.fromArray(t.position),e.scale.fromArray(t.scale),e.rotation.fromArray(t.rotation),r||(e.userData.src=t),!this.inEditor){const i=null!==(s=t.components)&&void 0!==s?s:[],a=null!=t.assetId&&null!==(o=null===(n=yield this.assetsService.getAsset(t.assetId))||void 0===n?void 0:n.components)&&void 0!==o?o:[];i.push(...a),i.length>0?e.userData.componentRefs=yield Promise.all(i.map(((i,a)=>this.createComponent(e,t,i,a)))):"asset_mesh"==t.type&&function(e){e.traverse((e=>{e.matrixAutoUpdate=!1,e.matrixWorldNeedsUpdate=!1}));const t=e.updateMatrixWorld;e.updateMatrixWorld=function(){t.apply(e),e.updateMatrixWorld=function(){}}}(e)}if(this.inEditor){let t=null;e instanceof G&&(t=function(e){if(e instanceof W)return new d(new a(...e.offset.toArray()),Se);return null}(e.collisionShape)),null!=t&&(t.layers.disable(0),t.layers.enable(18),t.scale.multiplyScalar(1.1),e.add(t))}return this.objectMap.set(e.uuid,t),this.sceneObjectMap.set(t.id,e),null==i?this.scene.add(e):null==i||i.add(e),null===(c=t.children)||void 0===c||c.forEach((t=>{this.materialize(t,e,r)})),e}}))}createComponent(t,i,a,r){return e(this,void 0,void 0,(function*(){const e=new me[a.path+"/"+a.className],s=i.id+r;e.id=s,e.object=t;for(const t of a.params)null!=t.value&&(e[t.name]=t.value);return this.components.push(e),s}))}createFromActor(t){var i,a,r;return e(this,void 0,void 0,(function*(){const e=null!==(a=null===(i=this.actorTypes.find((e=>{var i;return e.name===(null===(i=t.actor)||void 0===i?void 0:i.type)})))||void 0===i?void 0:i.type)&&void 0!==a?a:T[null===(r=t.actor)||void 0===r?void 0:r.type];if(null==e)return null;this.inEditor&&this.editorActorParamSnapshot.set(t.id,JSON.stringify(t.actor));const n=yield this.actorProvider.create(e,(new A).fromArray(t.position),(new s).fromArray(t.rotation),!0);return this.materializedActors.set(t.id,n),null==n?void 0:n.object}))}cleanup(){this.materializedActors.clear()}createFromShape(t){var i,a,s;return e(this,void 0,void 0,(function*(){const e=this.inEditor&&t.hidden;let n;if("landscape"==t.shape)n=this.createLandscape(t);else{let s=new m({name:"Default",color:new r("#aaaaaa"),visible:this.inEditor||!t.hidden,wireframe:e});const o=yield this.createMeshByShape(t.shape,s,t.shapeParams);o.castShadow=null===(i=t.castShadow)||void 0===i||i,o.receiveShadow=null!==(a=t.castShadow)&&void 0!==a&&a,t.collisionDetection||(o.collisionShape=null),n=o,this._originalMaterials.set(n.id,o.material),n.traverse((e=>{}))}return e||((null!==(s=t.materialAssignments)&&void 0!==s?s:[]).filter((e=>null!=e.materialId)).forEach((e=>this.applyMaterial(n,e))),this.applyVertexMaterials(t,n)),n}))}createLandscape(e){var t;if(null==(null===(t=e.landscape)||void 0===t?void 0:t.options))return console.error(`No landscape options exist on scene object ${e.id} ${e.name}`),new l;const i=X(e.landscape.options);this.applyHeightMaps(i,e.landscape.heightMaps,!0);const a=new Y(e,this.renderingView,i,this.assetManagerService,this.assetsService,this.shaders,(t=>{var i;(null!==(i=e.materialAssignments)&&void 0!==i?i:[]).filter((e=>null!=e.materialId)).forEach((e=>this.applyMaterial(t,e)))}));return this.landscapeManagers.push(a),a.refreshGeometry(),i}applyHeightMaps(e,t,i=!1){const a=new q(e.sections);for(const e of null!=t?t:[]){const t=a.find(e.x,e.y);if(!t)return;const i=t.geometry.getAttribute("position");for(const t of e.points)i.setY(t.i,t.y);i.needsUpdate=!0}const r=e.sections;r.forEach((e=>{e.geometry.computeBoundsTree(),e.geometry.computeVertexNormals()})),this.inEditor&&!i||setTimeout((()=>Z(r)),50)}createMeshByShape(t,i,a={}){return e(this,void 0,void 0,(function*(){if("landscape"!==t&&ce.includes(t)){const r=yield function(t){return e(this,void 0,void 0,(function*(){const e={};for(const[i,a]of Object.entries(t)){const t=yield we(a,null,null,null);null!=t&&(e[i]=t)}return e}))}(null!=a?a:{});return"cylinder"==t&&r.openEnded,new G(le[t].geometry(r),i,le[t].collision(r))}throw new Error(`Unsupported shape '${t}'`)}))}createFromAsset(t){var i,a,r,s;return e(this,void 0,void 0,(function*(){const e=yield this.assetsService.getAsset(t.assetId);if(null==e)return void console.warn(`Can not find asset with id ${t.assetId} and name ${t.name}`);let{scene:n}=yield this.assetManagerService.getMesh(e);De(t.materialAssignments,e.materialAssignments).forEach((e=>this.applyMaterial(n,e)));const o=null===(a=null!==(i=t.receiveShadow)&&void 0!==i?i:!!e.receiveShadow)||void 0===a||a,l=null!==(s=null!==(r=t.castShadow)&&void 0!==r?r:!!e.castShadow)&&void 0!==s&&s;return n.receiveShadow=o,pe(n,l,o),t.collisionDetection||(n.collisionShapes=[]),this.applyVertexMaterials(t,n),n.traverse((e=>{e instanceof d&&"computeBoundsTree"in e.geometry&&e.geometry.computeBoundsTree()})),n}))}createFromPrefabAsset(t){return e(this,void 0,void 0,(function*(){const e=yield this.assetsService.getAsset(t.assetId);if(null==e)return void console.warn(`Can not find asset with id ${t.assetId} and name ${t.name}`);const i=new l;return e.prefab.objects.filter((e=>"global_fog"!==e.type)).forEach((e=>this.materialize(e,i,!0))),i}))}createParticleSystem(t){return e(this,void 0,void 0,(function*(){const e=yield this.assetsService.getAsset(t.assetId),a=new p;return yield b.fromJSONAsync(e.particleSystem,i).then((e=>{const t=new M(a,i);e.addRenderer(t),this.renderingView.onLoop((t=>e.update()))})),a}))}createLight(t){var i;return e(this,void 0,void 0,(function*(){if("point"===t.light.type){const e=new f(t.light.point.color,t.light.point.intensity,t.light.point.distance,t.light.point.decay);if(e.castShadow=null===(i=t.light.point.castShadow)||void 0===i||i,this.inEditor){const t=new g(.3,10,10),i=new m({color:new r(16771709)}),a=new d(t,i);e.add(a)}return e}return"directional"===t.light.type?(this.applyDirectionalLight(t.light.directional),new l):"ambient"===t.light.type?(this.applyDirectionalAmbientLight(null,t.light.ambient),new l):void 0}))}applyDirectionalAmbientLight(e,t){const i=this.scene.children.find((e=>e.name===de));null!=i?(i.intensity=t.intensity,i.color.set(t.color),i.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()}}function pe(e,t,i){e.castShadow=t,e.receiveShadow=i,e.traverse((e=>{e.castShadow=t,e.receiveShadow=i}))}const fe=new Map,ve=new h({color:16711935}),ge=new Map;export function materialFromAsset(t,a,s,n,o,l=!0){var c,d,h,m,p,f,v,g,y,w,A;return e(this,void 0,void 0,(function*(){const e=JSON.stringify(t.material);if(l&&fe.has(e))return fe.get(e);const S={opacity:t.material.params.opacity,map:null,emissive:null!==(c=t.material.params.emissive)&&void 0!==c?c:null,metalness:null!==(d=t.material.params.metalness)&&void 0!==d?d:0,flatShading:null!==(h=t.material.params.flatShading)&&void 0!==h&&h,color:new r(t.material.params.color).convertSRGBToLinear(),transparent:null!=t.material.params.opacity&&t.material.params.opacity<1},b={};if(null!=t.material.params.map){const e=t.material.params.map,i=yield s.getAsset(e);null!=i&&(S.map=yield n.getTexture(i))}let M;switch(t.material.type){case"phong":M=new u(Object.assign(Object.assign({},S),b));break;case"water":M=te(S,a);break;case"grassFoliage":M=Q({color:S.color,map:S.map},a);break;case"grass":M=K(Object.assign(Object.assign({},S),{colorTwo:new r(t.material.params.colorTwo),colorThree:new r(t.material.params.colorThree)}),a);break;case"standard":case"lambert":case"shader":const e=null!==(m={standard:ne,lambert:oe}[t.material.type])&&void 0!==m?m:null===(p=o.find((e=>e.name==t.material.shader)))||void 0===p?void 0:p.type;if(e){const i=new e,r=yield ye(null!==(v=null===(f=t.material)||void 0===f?void 0:f.shaderParams)&&void 0!==v?v:{},e,s,n,null,a,o);Object.assign(i,r);try{M=i.build()}catch(e){console.log("Shader runtime error: "+e),ge.has(t.material.shader)||ge.set(t.material.shader,ve.clone()),M=ge.get(t.material.shader)}M.userData.customShaderName=t.material.shader}else console.warn("Missing shader implementation with name "+t.material.shader),M=ve;break;default:throw new Error("Unsupported material type"+t.material.type)}return null==a||a.csm.setupMaterial(M),l&&fe.set(e,M),M.side=null!==(y=null!==(g=t.material.side)&&void 0!==g?g:M.side)&&void 0!==y?y:i.FrontSide,M.transparent=null!==(A=null!==(w=t.material.transparent)&&void 0!==w?w:S.transparent)&&void 0!==A&&A||M.transparent,M}))}function ye(t,i,a,r,s,n,o){return e(this,void 0,void 0,(function*(){const e={};for(const[i,l]of Object.entries(t)){const t=yield we(l,a,r,s,n,o);null!=t&&(e[i]=t)}return e}))}function we(t,i,a,n,o,l){return e(this,void 0,void 0,(function*(){if(null==t||null==t.value||""==t.value)return null;const e=t.value;switch(t.type){case ie.Number:case ie.FloatNode:let c="string"==typeof e?parseFloat(e):e;return t.type===ie.FloatNode?x(c):c;case ie.Texture:return yield a.getTexture(yield i.getAsset(e));case ie.Sampler2DNode:return F(yield a.getTexture(yield i.getAsset(e)));case ie.Boolean:return e;case ie.BooleanNode:return D(e);case ie.Vector2:case ie.Vec2Node:if("object"==typeof e){const i=e instanceof Array?(new w).fromArray(e):new w(i.x,i.y);return t.type===ie.Vec2Node?V(i):i}return null;case ie.Vector3:case ie.Vec3Node:if("object"==typeof e){const i=e instanceof Array?(new A).fromArray(e):new A(i.x,i.y,i.z);return t.type===ie.Vec3Node?z(i):i}return null;case ie.Color:case ie.RgbNode:const d=new r(e).convertSRGBToLinear();return t.type===ie.RgbNode?j(d):d;case ie.String:return e;case ie.BaseActor:const h=e;return null==n&&console.warn("Class parameters can not be prepared as actors are not passed in"),null==n?void 0:n.get(h);case ie.Euler:const u=e;return(new s).fromArray(u);case ie.Object3D:return(yield a.getMesh(yield i.getAsset(e))).scene;case ie.Material:return yield materialFromAsset(yield i.getAsset(e),o,i,a,l);case ie.AudioBuffer:return yield a.getAudio(yield i.getAsset(e))}return null}))}function Ae(e){var t,i;return"linear"===e.type?new n(new r(e.color),null!==(t=e.near)&&void 0!==t?t:100,null!==(i=e.far)&&void 0!==i?i:1e3):"density"===e.type?new o(e.color,e.density):void console.warn("Invalid fog type",e)}const Se=new m({color:4229780});function be(t,a,r,n){var o;return e(this,void 0,void 0,(function*(){null==n&&(n=(new ae).identity()),yield a(t,r,n);const e=n.clone().multiply(function(e,t){return t.compose((new A).fromArray(e.position),(new v).setFromEuler((new s).fromArray(e.rotation)),(new A).fromArray(e.scale))}(t,new i.Matrix4));return Promise.all((null!==(o=t.children)&&void 0!==o?o:[]).map((i=>be(i,a,t,e))))}))}function Me(e){const t=e.constructor.prototype;return t instanceof Number||e===Number?ie.Number:t instanceof P||"function"==typeof e.prototype.isFloat?ie.FloatNode:t instanceof y||e===y||e.isTexture?ie.Texture:t instanceof se||e===O?ie.Sampler2DNode:t instanceof Boolean||e===Boolean?ie.Boolean:t instanceof I?ie.BooleanNode:t instanceof r||e==r?ie.Color:t instanceof E||"function"==typeof e.prototype.isRgb?ie.RgbNode:t instanceof w||e==w?ie.Vector2:t instanceof B||"function"==typeof e.prototype.isVec2?ie.Vec2Node:t instanceof A||e==A?ie.Vector3:t instanceof C||"function"==typeof e.prototype.isVec3?ie.Vec3Node:t instanceof String||e===String?ie.String:t instanceof re||e==re||e.prototype instanceof re||e.prototype==re?ie.BaseActor:t instanceof s||e==s?ie.Euler:t instanceof p||e==p?ie.Object3D:t instanceof c||e==c?ie.Material:t instanceof AudioBuffer||e==AudioBuffer?ie.AudioBuffer:void console.warn("Failed to map parameter type to serialized version",{type:e})}export function prepareCustomParams(e,t,i={}){return Object.fromEntries(e.map((e=>{var a,r,s;return[e.name,{type:Me(e.type),value:null!==(s=null!==(r=null===(a=t[e.name])||void 0===a?void 0:a.value)&&void 0!==r?r:i[e.name])&&void 0!==s?s:xe.get(Me(e.type))}]})))}export function prepareCustomParamsFromType(e,t,i=null){const a=$(e);if(0===a.length)return{};let r;null!=i?he(i,(()=>{r=i.get(e)})):r=new e;const s={};for(const e of a){const t=r[e.name];if(null!=t){const i=serializeCustomParameter(e.type,t);null!=i&&(s[e.name]=i)}}return prepareCustomParams(a,t,s)}export function serializeCustomParameter(e,t){function i(){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 i();case A:return t instanceof A?t.toArray():void i();case S:return t instanceof S?t.toArray():void i();case r:return t instanceof r?"#"+t.getHexString():"string"==typeof t?t:"number"==typeof t?"#"+new r(t).getHexString():void i();case String:return t;case s:return t instanceof s?t.toArray():void i()}}function De(e,t){return function(e,t,i){const a=[],r=new Set;for(const s of[...null!=e?e:[],...null!=t?t:[]]){const e=i(s);r.has(e)||(r.add(e),a.push(s))}return a}((null!=e?e:[]).filter((e=>Ie(e.materialId))),(null!=t?t:[]).filter((e=>Ie(e.materialId))),(e=>e.color+e.name))}function Ie(e){return"null"!=e&&null!=e}const xe=new Map([[ie.RgbNode,"#000000"],[ie.Color,"#000000"],[ie.Vector4,[0,0,0,0]],[ie.Vec4Node,[0,0,0,0]],[ie.Vector3,[0,0,0]],[ie.Vec3Node,[0,0,0]],[ie.Vector2,[0,0]],[ie.Vec2Node,[0,0]],[ie.Euler,[0,0,0,"XYZ"]]]);
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -96,6 +96,30 @@ declare class TextDefinition implements ShapeDefinition {
96
96
  geometry(params?: ParamsType<this>): TextGeometry;
97
97
  collision(params?: ParamsType<this>): ConvexPolyhedronCollisionShape;
98
98
  }
99
+ declare class StairsDefinition implements ShapeDefinition {
100
+ parameters: {
101
+ floating: ShapeParameterDef<boolean>;
102
+ width: ShapeParameterDef<number>;
103
+ height: ShapeParameterDef<number>;
104
+ depth: ShapeParameterDef<number>;
105
+ steps: ShapeParameterDef<number>;
106
+ };
107
+ geometry(params?: ParamsType<this>): BufferGeometry;
108
+ collision(params?: ParamsType<this>): TrimeshCollisionShape;
109
+ }
110
+ declare class StairsSpiralDefinition implements ShapeDefinition {
111
+ parameters: {
112
+ floating: ShapeParameterDef<boolean>;
113
+ width: ShapeParameterDef<number>;
114
+ height: ShapeParameterDef<number>;
115
+ steps: ShapeParameterDef<number>;
116
+ degrees: ShapeParameterDef<number>;
117
+ radius: ShapeParameterDef<number>;
118
+ flipped: ShapeParameterDef<boolean>;
119
+ };
120
+ geometry(params?: ParamsType<this>): BufferGeometry;
121
+ collision(params?: ParamsType<this>): TrimeshCollisionShape;
122
+ }
99
123
  declare const shapes: {
100
124
  box: {
101
125
  geometry(): BoxGeometry;
@@ -114,8 +138,10 @@ declare const shapes: {
114
138
  capsule: CapsuleDefinition;
115
139
  roundedBox: RoundedBoxDefinition;
116
140
  text: TextDefinition;
141
+ stairs: StairsDefinition;
142
+ stairsSpiral: StairsSpiralDefinition;
117
143
  };
118
144
  export type LibraryShapeType = keyof typeof shapes;
119
145
  export declare const ShapeLibrary: Record<LibraryShapeType, ShapeDefinition>;
120
- export declare const ShapeLibraryKeys: ("sphere" | "box" | "ramp" | "plane" | "cylinder" | "torus" | "cone" | "circle" | "capsule" | "roundedBox" | "text")[];
146
+ export declare const ShapeLibraryKeys: ("sphere" | "box" | "ramp" | "plane" | "cylinder" | "torus" | "cone" | "circle" | "capsule" | "roundedBox" | "text" | "stairs" | "stairsSpiral")[];
121
147
  export {};
@@ -1,4 +1,4 @@
1
- import{BoxCollisionShape as e,CapsuleCollisionShape as t,ConeCollisionShape as r,ConvexPolyhedronCollisionShape as s,CylinderCollisionShape as n,PlaneCollisionShape as o,SphereCollisionShape as a,TrimeshCollisionShape as i}from"../collision/collision-shape";import{BoxGeometry as m,PlaneGeometry as h,Vector3 as l,CylinderGeometry as c,SphereGeometry as g,Euler as u,TorusGeometry as p,ConeGeometry as d,CircleGeometry as w,CapsuleGeometry as S}from"three";import{rampGeometry as y}from"./ramp-geometry";import{RoundedBoxGeometry as f}from"three/examples/jsm/geometries/RoundedBoxGeometry";import{TextGeometry as x}from"three/examples/jsm/geometries/TextGeometry";import{Font as b}from"three/examples/jsm/loaders/FontLoader";import*as j from"three/examples/fonts/helvetiker_regular.typeface.json";function L(e){return{type:"number",default:e}}function z(e){return{type:"number",default:e,float:!0}}function E(e){return{type:"boolean",default:e}}function k(e,t){const r={};for(let s in t)null==e[s]?r[s]=t[s].default:r[s]=e[s];return r}const v={box:{geometry:()=>new m(1,1,1),collision:()=>new e(new l(1,1,1))},ramp:{geometry:()=>y(),collision:()=>new s(y())},plane:new class{constructor(){this.parameters={widthSegments:L(1),heightSegments:L(1)}}geometry(e={}){const t=k(e,this.parameters);return new h(1,1,t.widthSegments,t.heightSegments)}collision(e={}){return new o(1,1)}},cylinder:new class{constructor(){this.parameters={radialSegments:L(12),heightSegments:L(1),openEnded:E(!1)}}geometry(e={}){const t=k(e,this.parameters);return new c(.5,.5,1,t.radialSegments,t.heightSegments,t.openEnded)}collision(e={}){const t=k(e,this.parameters);return new n(.5,.5,1,t.radialSegments,new u(0,1,0))}},sphere:new class{constructor(){this.parameters={withSegments:L(12),heightSegments:L(12)}}geometry(e={}){const t=k(e,this.parameters);return new g(.5,t.withSegments,t.heightSegments)}collision(){return new a(.5)}},torus:new class{constructor(){this.parameters={radius:z(1),tube:z(.3),radialSegments:L(16),tubularSegments:L(50)}}geometry(e={}){const t=k(e,this.parameters);return new p(t.radius,t.tube,t.radialSegments,t.tubularSegments)}collision(e={}){return new i(this.geometry(e))}},cone:new class{constructor(){this.parameters={radialSegments:L(12),heightSegments:L(1),openEnded:E(!1)}}geometry(e={}){const t=k(e,this.parameters);return new d(.5,1,t.radialSegments,t.heightSegments)}collision(e={}){return new r(1,.5)}},circle:new class{constructor(){this.parameters={segments:L(32)}}geometry(e={}){const t=k(e,this.parameters);return new w(.5,t.segments)}collision(e={}){return new i(this.geometry(e))}},capsule:new class{constructor(){this.parameters={radius:z(.5),length:z(1),capSegments:L(8),radialSegments:L(32)}}geometry(e={}){const t=k(e,this.parameters);return new S(t.radius,t.length,t.capSegments,t.radialSegments)}collision(e={}){const r=k(e,this.parameters);return new t(r.length,r.radius)}},roundedBox:new class{constructor(){this.parameters={width:z(1),height:z(1),depth:z(1),segments:L(4),radius:z(.1)}}geometry(e={}){const t=k(e,this.parameters);return new f(t.width,t.height,t.depth,t.segments,t.radius)}collision(t={}){const r=k(t,this.parameters);return new e(new l(r.width,r.height,r.depth))}},text:new class{constructor(){var e;this.parameters={text:(e="Text",{type:"string",default:e}),size:z(1),depth:z(.2)}}geometry(e={}){const t=k(e,this.parameters);return new x(t.text,{font:new b(j),size:t.size,height:t.depth})}collision(e={}){return k(e,this.parameters).text.trim().length,null}}};export const ShapeLibrary=v;export const ShapeLibraryKeys=Object.keys(ShapeLibrary);
1
+ import{BoxCollisionShape as e,CapsuleCollisionShape as t,ConeCollisionShape as r,ConvexPolyhedronCollisionShape as s,CylinderCollisionShape as n,PlaneCollisionShape as i,SphereCollisionShape as o,TrimeshCollisionShape as a}from"../collision/collision-shape";import{BoxGeometry as m,PlaneGeometry as h,Vector3 as l,CylinderGeometry as c,SphereGeometry as g,Euler as p,TorusGeometry as u,ConeGeometry as d,CircleGeometry as w,CapsuleGeometry as y}from"three";import{rampGeometry as S}from"./ramp-geometry";import{RoundedBoxGeometry as f}from"three/examples/jsm/geometries/RoundedBoxGeometry";import{TextGeometry as x}from"three/examples/jsm/geometries/TextGeometry";import{Font as b}from"three/examples/jsm/loaders/FontLoader";import*as j from"three/examples/fonts/helvetiker_regular.typeface.json";import{createSpiralStairsGeometry as L,createStairsGeometry as z}from"./stairs-geometry";function E(e){return{type:"number",default:e}}function k(e){return{type:"number",default:e,float:!0}}function v(e){return{type:"boolean",default:e}}function B(e,t){const r={};for(let s in t)null==e[s]?r[s]=t[s].default:r[s]=e[s];return r}const G={box:{geometry:()=>new m(1,1,1),collision:()=>new e(new l(1,1,1))},ramp:{geometry:()=>S(),collision:()=>new s(S())},plane:new class{constructor(){this.parameters={widthSegments:E(1),heightSegments:E(1)}}geometry(e={}){const t=B(e,this.parameters);return new h(1,1,t.widthSegments,t.heightSegments)}collision(e={}){return new i(1,1)}},cylinder:new class{constructor(){this.parameters={radialSegments:E(12),heightSegments:E(1),openEnded:v(!1)}}geometry(e={}){const t=B(e,this.parameters);return new c(.5,.5,1,t.radialSegments,t.heightSegments,t.openEnded)}collision(e={}){const t=B(e,this.parameters);return new n(.5,.5,1,t.radialSegments,new p(0,1,0))}},sphere:new class{constructor(){this.parameters={withSegments:E(12),heightSegments:E(12)}}geometry(e={}){const t=B(e,this.parameters);return new g(.5,t.withSegments,t.heightSegments)}collision(){return new o(.5)}},torus:new class{constructor(){this.parameters={radius:k(1),tube:k(.3),radialSegments:E(16),tubularSegments:E(50)}}geometry(e={}){const t=B(e,this.parameters);return new u(t.radius,t.tube,t.radialSegments,t.tubularSegments)}collision(e={}){return new a(this.geometry(e))}},cone:new class{constructor(){this.parameters={radialSegments:E(12),heightSegments:E(1),openEnded:v(!1)}}geometry(e={}){const t=B(e,this.parameters);return new d(.5,1,t.radialSegments,t.heightSegments)}collision(e={}){return new r(1,.5)}},circle:new class{constructor(){this.parameters={segments:E(32)}}geometry(e={}){const t=B(e,this.parameters);return new w(.5,t.segments)}collision(e={}){return new a(this.geometry(e))}},capsule:new class{constructor(){this.parameters={radius:k(.5),length:k(1),capSegments:E(8),radialSegments:E(32)}}geometry(e={}){const t=B(e,this.parameters);return new y(t.radius,t.length,t.capSegments,t.radialSegments)}collision(e={}){const r=B(e,this.parameters);return new t(r.length,r.radius)}},roundedBox:new class{constructor(){this.parameters={width:k(1),height:k(1),depth:k(1),segments:E(4),radius:k(.1)}}geometry(e={}){const t=B(e,this.parameters);return new f(t.width,t.height,t.depth,t.segments,t.radius)}collision(t={}){const r=B(t,this.parameters);return new e(new l(r.width,r.height,r.depth))}},text:new class{constructor(){var e;this.parameters={text:(e="Text",{type:"string",default:e}),size:k(1),depth:k(.2)}}geometry(e={}){const t=B(e,this.parameters);return new x(t.text,{font:new b(j),size:t.size,height:t.depth})}collision(e={}){return B(e,this.parameters).text.trim().length,null}},stairs:new class{constructor(){this.parameters={floating:v(!1),width:k(1),height:k(.25),depth:k(.25),steps:E(4)}}geometry(e={}){const t=B(e,this.parameters);return z(t.floating,t.steps,t.depth,t.height,t.width)}collision(e={}){return new a(this.geometry(e))}},stairsSpiral:new class{constructor(){this.parameters={floating:v(!1),width:k(1),height:k(.25),steps:E(4),degrees:E(90),radius:k(.2),flipped:v(!1)}}geometry(e={}){const t=B(e,this.parameters);return L(t.floating,t.steps,t.height,t.width,t.degrees,t.radius,t.flipped)}collision(e={}){return new a(this.geometry(e))}}};export const ShapeLibrary=G;export const ShapeLibraryKeys=Object.keys(ShapeLibrary);
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -0,0 +1,3 @@
1
+ import * as THREE from "three";
2
+ export declare function createSpiralStairsGeometry(floating: boolean, numSteps: number, stepHeight: number, stepWidth: number, degrees: number, innerRadius: number, flipped: boolean): THREE.BufferGeometry;
3
+ export declare function createStairsGeometry(floating: boolean, numSteps: number, stepSize: number, stepHeight: number, stepWidth: number): THREE.BufferGeometry;
@@ -0,0 +1,5 @@
1
+ import*as t from"three";export function createSpiralStairsGeometry(e,o,r,s,n,a,l){const c=[];for(let i=0;i<o;i++){let f=i*r;const u=t.MathUtils.degToRad(Math.abs(n)),h=i/o,m=(i+1)/o,p=Math.cos(h*u)*a,M=Math.cos(h*u)*(a+s),b=Math.cos(m*u)*a,x=Math.cos(m*u)*(a+s),g=Math.sin(h*u)*a,w=Math.sin(h*u)*(a+s),y=Math.sin(m*u)*a,A=Math.sin(m*u)*(a+s);let B;if(e)B=[p,f,g,M,f,w,p,f+r,g,M,f+r,w,b,f,y,x,f,A,b,f+r,y,x,f+r,A];else{const t=0;B=[p,f,g,M,f,w,p,f+r,g,M,f+r,w,b,t,y,x,t,A,b,t+r*(i+1),y,x,t+r*(i+1),A,p,t,g,M,t,w]}const G=0,N=[G,G+2,G+1,G+1,G+2,G+3,G,G+4,G+2,G+2,G+4,G+6,G+5,G+1,G+3,G+5,G+3,G+7,...e||i===o-1?[G+6,G+4,G+5,G+6,G+5,G+7]:[],G+3,G+2,G+6,G+7,G+3,G+6,...!e&&i>0?[G,G+8,G+4,G+5,G+9,G+1]:[],...e?[G,G+1,G+4,G+1,G+5,G+4]:[G+8,G+9,G+4,G+9,G+5,G+4]];if(l)for(let t=0;t<N.length;t+=3){let e=N[t];N[t]=N[t+2],N[t+2]=e}for(let t=0;t<N.length;t++)c.push(B[3*N[t]],B[3*N[t]+1],B[3*N[t]+2])}const i=new t.BufferGeometry;return i.setAttribute("position",new t.Float32BufferAttribute(c,3)),i.computeVertexNormals(),l&&(i.scale(-1,1,1),i.computeVertexNormals()),i}export function createStairsGeometry(e,o,r,s,n){const a=[];for(let t=0;t<o;t++){let l=0,c=t*s;const i=t*r;let f;if(e)f=[l,c+0*s,i,l+n,c+0*s,i,l,c+s,i,l+n,c+s,i,l,c+0*s,i+r,l+n,c+0*s,i+r,l,c+s,i+r,l+n,c+s,i+r];else{const e=0;f=[l,c,i,l+n,c,i,l,c+s,i,l+n,c+s,i,l,e,i+r,l+n,e,i+r,l,e+s*(t+1),i+r,l+n,e+s*(t+1),i+r,l,e,i,l+n,e,i]}const u=0,h=[u,u+2,u+1,u+1,u+2,u+3,u,u+4,u+2,u+2,u+4,u+6,u+5,u+1,u+3,u+5,u+3,u+7,...e||t===o-1?[u+6,u+4,u+5,u+6,u+5,u+7]:[],...!e&&t>0?[u,u+8,u+4,u+5,u+9,u+1]:[],u+3,u+2,u+6,u+7,u+3,u+6,...e?[u,u+1,u+4,u+1,u+5,u+4]:[u+8,u+9,u+4,u+9,u+5,u+4]];for(let t=0;t<h.length;t++)a.push(f[3*h[t]],f[3*h[t]+1],f[3*h[t]+2])}const l=new t.BufferGeometry;return l.setAttribute("position",new t.Float32BufferAttribute(a,3)),l.computeVertexNormals(),l}
2
+ /*
3
+ * Copyright (©) 2023. All rights reserved.
4
+ * See the LICENSE.md file for details.
5
+ */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hology/core",
3
- "version": "0.0.26",
3
+ "version": "0.0.27",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {