@hology/core 0.0.33 → 0.0.34

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,4 @@
1
- import{__decorate as t,__metadata as e}from"tslib";import{Raycaster as i,Vector2 as o}from"three";import{Service as n}from"typedi";import{ViewController as s}from"./render";import{World as r}from"./world";import{inject as c}from"../../gameplay";import{Subject as h,tap as p,map as a,filter as d,takeUntil as l,withLatestFrom as b,mergeMap as P,merge as u,from as j}from"rxjs";let w=class{constructor(){this.view=c(s),this.world=c(r),this.enabled=!1,this.stopped=new h,this.monitoredObjects=new Map,this.useCache=!1,this.cachePointerPosition=new o,this.pointerPosition=new o,this.adjustedPosition=new o,this.raycastIntersectionResult=[],this.raycaster=new i,this.onClick=new h,this.onDoubleClick=new h,this.onPointerMove=new h,this.onPointerDown=new h,this.onPointerUp=new h,this.onPointerEnterObject3D=t=>{let e=!1;return this.onPointerMove.pipe(this.tapUsingPointerMove(),this.tapMonitorObject(t),a((()=>this.findIntersection(t))),p((t=>{null==t&&(e=!1)})),d((t=>null!=t&&!e)),p((()=>{e=!0})),a((e=>({intersection:e,object:t}))))},this.onPointerEnterActor=t=>this.onPointerEnterObject3D(t.object).pipe(l(t.disposed),a((({intersection:e})=>({intersection:e,actor:t})))),this.onPointerEnterActorType=t=>u(j(this.world.actors),this.world.actorAdded).pipe(d((e=>e instanceof t)),P((t=>this.onPointerEnterActor(t)))),this.onPointerLeaveObject3D=t=>{let e=!1;return this.onPointerMove.pipe(this.tapUsingPointerMove(),this.tapMonitorObject(t),a((()=>this.findIntersection(t))),p((t=>{null!=t&&(e=!1)})),d((t=>null==t&&!e)),p((()=>{e=!0})),a((e=>({intersection:e,object:t}))))},this.onPointerLeaveActor=t=>this.onPointerLeaveObject3D(t.object).pipe(l(t.disposed),a((({intersection:e})=>({intersection:e,actor:t})))),this.onPointerLeaveActorType=t=>u(j(this.world.actors),this.world.actorAdded).pipe(d((e=>e instanceof t)),P((t=>this.onPointerLeaveActor(t)))),this.onClickObject3D=t=>{const e=this.onPointerDown.pipe(a((()=>this.findIntersection(t))));return this.onPointerUp.pipe(a((()=>this.findIntersection(t)))).pipe(this.tapMonitorObject(t),b(e),d((([t,e])=>null!=t&&null!=e)),a((([e])=>({intersection:e,object:t}))))},this.onClickActor=t=>this.onClickObject3D(t.object).pipe(l(t.disposed),a((({intersection:e})=>({intersection:e,actor:t})))),this.onClickActorType=t=>u(j(this.world.actors),this.world.actorAdded).pipe(d((e=>e instanceof t)),P((t=>this.onClickActor(t)))),this.onPointerDownActor=t=>this.onPointerDownObject3D(t.object).pipe(l(t.disposed),a((({intersection:e})=>({intersection:e,actor:t})))),this.onPointerDownActorType=t=>u(j(this.world.actors),this.world.actorAdded).pipe(d((e=>e instanceof t)),P((t=>this.onPointerDownActor(t)))),this.onPointerDownObject3D=t=>this.onPointerDown.pipe(this.tapMonitorObject(t),a((()=>this.findIntersection(t))),d((t=>null!=t)),a((e=>({intersection:e,object:t})))),this.onPointerUpActor=t=>this.onPointerUpObject3D(t.object).pipe(l(t.disposed),a((({intersection:e})=>({intersection:e,actor:t})))),this.onPointerUpActorType=t=>u(j(this.world.actors),this.world.actorAdded).pipe(d((e=>e instanceof t)),P((t=>this.onPointerUpActor(t)))),this.onPointerUpObject3D=t=>this.onPointerUp.pipe(this.tapMonitorObject(t),a((()=>this.findIntersection(t))),d((t=>null!=t)),a((e=>({intersection:e,object:t})))),this.onPointerMoveActor=t=>this.onPointerMoveObject3D(t.object).pipe(l(t.disposed),a((({intersection:e})=>({intersection:e,actor:t})))),this.onPointerMoveActorType=t=>u(j(this.world.actors),this.world.actorAdded).pipe(d((e=>e instanceof t)),P((t=>this.onPointerMoveActor(t)))),this.onPointerMoveObject3D=t=>this.onPointerMove.pipe(this.tapUsingPointerMove(),this.tapMonitorObject(t),a((()=>this.findIntersection(t))),d((t=>null!=t)),a((e=>({intersection:e,object:t})))),this.usingPointerMoveEvents=!1,this.handlers={click:t=>{this.onClick.next(t)},dblclick:t=>{this.onDoubleClick.next(t)},pointermove:t=>{this.onPointerMove.next(t)},pointerup:t=>{this.onPointerUp.next(t)},pointerdown:t=>{this.onPointerDown.next(t)}},this.raycaster.firstHitOnly=!0}start(){this.enabled||(this.enabled=!0,Object.entries(this.handlers).forEach((([t,e])=>{this.view.htmlElement.addEventListener(t,(i=>{("pointermove"!==t||this.usingPointerMoveEvents)&&(this.updateRaycast(i),e(i))}))})),this.view.onLateUpdate().pipe(l(this.stopped)).subscribe((()=>this.useCache=!1)))}stop(){this.enabled=!1,Object.entries(this.handlers).forEach((([t,e])=>{document.removeEventListener(t,e)})),this.stopped.next(!0)}addMonitoredObject(t){const e=this.monitoredObjects.get(t)??0;this.monitoredObjects.set(t,e+1)}removeMonitoriedObject(t){const e=this.monitoredObjects.get(t);null!=e&&(e>1?this.monitoredObjects.set(t,e-1):this.monitoredObjects.delete(t))}updateRaycast(t){this.pointerPosition.set(t.x,t.y),this.useCache&&this.cachePointerPosition.equals(this.pointerPosition)||(this.cachePointerPosition.copy(this.pointerPosition),this.useCache=!0,this.adjustedPosition.x=t.offsetX/this.view.htmlElement.offsetWidth*2-1,this.adjustedPosition.y=-t.offsetY/this.view.htmlElement.offsetHeight*2+1,this.raycaster.setFromCamera(this.adjustedPosition,this.view.getCamera()),this.raycastIntersectionResult.length=0,this.raycaster.intersectObject(this.world.scene,!0,this.raycastIntersectionResult))}tapUsingPointerMove(){return p({subscribe:()=>{this.usingPointerMoveEvents=!0},unsubscribe:()=>{}})}tapMonitorObject(t){return p({subscribe:()=>{this.addMonitoredObject(t)},unsubscribe:()=>{this.removeMonitoriedObject(t)}})}findIntersection(t){if(this.raycastIntersectionResult.length>0){let e=this.raycastIntersectionResult[0].object;for(;null!=e;){if(e.uuid===t.uuid)return this.raycastIntersectionResult[0];e=e.parent}}return null}};w=t([n(),e("design:paramtypes",[])],w);export{w as PointerEvents};
1
+ import{__decorate as t,__metadata as e}from"tslib";import{Raycaster as i,Vector2 as o}from"three";import{Service as n}from"typedi";import{ViewController as s}from"./render";import{World as r}from"./world";import{inject as c}from"../../gameplay";import{Subject as h,tap as p,map as a,filter as d,takeUntil as l,withLatestFrom as b,mergeMap as P,merge as u,from as j}from"rxjs";let w=class{constructor(){this.view=c(s),this.world=c(r),this.enabled=!1,this.stopped=new h,this.monitoredObjects=new Map,this.useCache=!1,this.cachePointerPosition=new o,this.pointerPosition=new o,this.adjustedPosition=new o,this.raycastIntersectionResult=[],this.raycaster=new i,this.onClick=new h,this.onDoubleClick=new h,this.onPointerMove=new h,this.onPointerDown=new h,this.onPointerUp=new h,this.onPointerEnterObject3D=t=>{let e=!1;return this.onPointerMove.pipe(this.tapUsingPointerMove(),this.tapMonitorObject(t),a((()=>this.findIntersection(t))),p((t=>{null==t&&(e=!1)})),d((t=>null!=t&&!e)),p((()=>{e=!0})),a((e=>({intersection:e,object:t}))))},this.onPointerEnterActor=t=>this.onPointerEnterObject3D(t.object).pipe(l(t.disposed),a((({intersection:e})=>({intersection:e,actor:t})))),this.onPointerEnterActorType=t=>u(j(this.world.actors),this.world.actorAdded).pipe(d((e=>e instanceof t)),P((t=>this.onPointerEnterActor(t)))),this.onPointerLeaveObject3D=t=>{let e=!1;return this.onPointerMove.pipe(this.tapUsingPointerMove(),this.tapMonitorObject(t),a((()=>this.findIntersection(t))),p((t=>{null!=t&&(e=!1)})),d((t=>null==t&&!e)),p((()=>{e=!0})),a((e=>({intersection:e,object:t}))))},this.onPointerLeaveActor=t=>this.onPointerLeaveObject3D(t.object).pipe(l(t.disposed),a((({intersection:e})=>({intersection:e,actor:t})))),this.onPointerLeaveActorType=t=>u(j(this.world.actors),this.world.actorAdded).pipe(d((e=>e instanceof t)),P((t=>this.onPointerLeaveActor(t)))),this.onClickObject3D=t=>{const e=this.onPointerDown.pipe(a((()=>this.findIntersection(t))));return this.onPointerUp.pipe(a((()=>this.findIntersection(t)))).pipe(this.tapMonitorObject(t),b(e),d((([t,e])=>null!=t&&null!=e)),a((([e])=>({intersection:e,object:t}))))},this.onClickActor=t=>this.onClickObject3D(t.object).pipe(l(t.disposed),a((({intersection:e})=>({intersection:e,actor:t})))),this.onClickActorType=t=>u(j(this.world.actors),this.world.actorAdded).pipe(d((e=>e instanceof t)),P((t=>this.onClickActor(t)))),this.onPointerDownActor=t=>this.onPointerDownObject3D(t.object).pipe(l(t.disposed),a((({intersection:e})=>({intersection:e,actor:t})))),this.onPointerDownActorType=t=>u(j(this.world.actors),this.world.actorAdded).pipe(d((e=>e instanceof t)),P((t=>this.onPointerDownActor(t)))),this.onPointerDownObject3D=t=>this.onPointerDown.pipe(this.tapMonitorObject(t),a((()=>this.findIntersection(t))),d((t=>null!=t)),a((e=>({intersection:e,object:t})))),this.onPointerUpActor=t=>this.onPointerUpObject3D(t.object).pipe(l(t.disposed),a((({intersection:e})=>({intersection:e,actor:t})))),this.onPointerUpActorType=t=>u(j(this.world.actors),this.world.actorAdded).pipe(d((e=>e instanceof t)),P((t=>this.onPointerUpActor(t)))),this.onPointerUpObject3D=t=>this.onPointerUp.pipe(this.tapMonitorObject(t),a((()=>this.findIntersection(t))),d((t=>null!=t)),a((e=>({intersection:e,object:t})))),this.onPointerMoveActor=t=>this.onPointerMoveObject3D(t.object).pipe(l(t.disposed),a((({intersection:e})=>({intersection:e,actor:t})))),this.onPointerMoveActorType=t=>u(j(this.world.actors),this.world.actorAdded).pipe(d((e=>e instanceof t)),P((t=>this.onPointerMoveActor(t)))),this.onPointerMoveObject3D=t=>this.onPointerMove.pipe(this.tapUsingPointerMove(),this.tapMonitorObject(t),a((()=>this.findIntersection(t))),d((t=>null!=t)),a((e=>({intersection:e,object:t})))),this.usingPointerMoveEvents=!1,this.handlers={click:t=>{this.onClick.next(t)},dblclick:t=>{this.onDoubleClick.next(t)},pointermove:t=>{this.onPointerMove.next(t)},pointerup:t=>{this.onPointerUp.next(t)},pointerdown:t=>{this.onPointerDown.next(t)}},this.raycaster.firstHitOnly=!0}start(){this.enabled||(this.enabled=!0,Object.entries(this.handlers).forEach((([t,e])=>{this.view.htmlElement.addEventListener(t,(i=>{("pointermove"!==t||this.usingPointerMoveEvents)&&(this.updateRaycast(i),e(i))}))})),this.view.onLateUpdate().pipe(l(this.stopped)).subscribe((()=>this.useCache=!1)))}stop(){this.enabled=!1,Object.entries(this.handlers).forEach((([t,e])=>{document.removeEventListener(t,e)})),this.stopped.next(!0),this.onClick.complete(),this.onDoubleClick.complete(),this.onPointerMove.complete(),this.onPointerDown.complete(),this.onPointerUp.complete()}addMonitoredObject(t){const e=this.monitoredObjects.get(t)??0;this.monitoredObjects.set(t,e+1)}removeMonitoriedObject(t){const e=this.monitoredObjects.get(t);null!=e&&(e>1?this.monitoredObjects.set(t,e-1):this.monitoredObjects.delete(t))}updateRaycast(t){this.pointerPosition.set(t.x,t.y),this.useCache&&this.cachePointerPosition.equals(this.pointerPosition)||(this.cachePointerPosition.copy(this.pointerPosition),this.useCache=!0,this.adjustedPosition.x=t.offsetX/this.view.htmlElement.offsetWidth*2-1,this.adjustedPosition.y=-t.offsetY/this.view.htmlElement.offsetHeight*2+1,this.raycaster.setFromCamera(this.adjustedPosition,this.view.getCamera()),this.raycastIntersectionResult.length=0,this.raycaster.intersectObject(this.world.scene,!0,this.raycastIntersectionResult))}tapUsingPointerMove(){return p({subscribe:()=>{this.usingPointerMoveEvents=!0},unsubscribe:()=>{}})}tapMonitorObject(t){return p({subscribe:()=>{this.addMonitoredObject(t)},unsubscribe:()=>{this.removeMonitoriedObject(t)}})}findIntersection(t){if(this.raycastIntersectionResult.length>0){let e=this.raycastIntersectionResult[0].object;for(;null!=e;){if(e.uuid===t.uuid)return this.raycastIntersectionResult[0];e=e.parent}}return null}};w=t([n(),e("design:paramtypes",[])],w);export{w as PointerEvents};
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -1,6 +1,7 @@
1
1
  import { Object3D, Texture } from 'three';
2
2
  import { Asset } from './model.js';
3
3
  import { CollisionShape } from './collision/collision-shape.js';
4
+ import * as THREE from 'three';
4
5
  export declare class AssetResourceLoader {
5
6
  private basePath;
6
7
  private cache;
@@ -27,6 +28,7 @@ export declare class AssetResourceLoader {
27
28
  }
28
29
  export interface LoadedMesh {
29
30
  scene: AssetMeshInstance;
31
+ animations: THREE.AnimationClip[];
30
32
  }
31
33
  export declare class AssetMeshInstance extends Object3D {
32
34
  collisionShapes?: CollisionShape[];
@@ -1,4 +1,4 @@
1
- import{AudioLoader as e,Group as t,LoadingManager as s,Mesh as a,Object3D as i,TextureLoader as r}from"three";import{GLTFLoader as n,MTLLoader as o,OBJLoader as c}from"three-stdlib";import{FBXLoader as l}from"three-stdlib";import{cloneMesh as h}from"../utils/mesh.js";import{pathJoin as d}from"../utils/files.js";import{Subject as p,firstValueFrom as u}from"rxjs";import{importCollisionShapes as f}from"./collision/collision-shape-import.js";import*as m from"three";import{iterateMaterials as g}from"../utils/materials.js";const w=["glb","gltf","fbx","obj"];export class AssetResourceLoader{onError(e){console.error(e)}constructor(){this.cache=new Map,this.textureCache=new Map,this.loadingManager=new s,this.glbLoader=new n(this.loadingManager),this.fbxLoader=new l(this.loadingManager),this.objLoader=new c(this.loadingManager),this.textureLoader=new r(this.loadingManager),this.audioLoader=new e(this.loadingManager),this.makeReady=new p,this.ready=u(this.makeReady),this.collisionShapeCache=new Map}setDataDir(e){this.basePath=d(e,"asset-resources"),this.makeReady.next(!0)}getUri(e){return d(this.basePath,e)+`?windowId=${getElectronArg("windowId")}`}async getTexture(e){return null==e?null:(await this.ready,this.cache.has(e.id)||await this.textureLoader.loadAsync(this.getUri(e.fileKey)).then((t=>(t.wrapS=L(e.texture?.wrapS),t.wrapT=L(e.texture?.wrapT),t.flipY=e.texture?.flipY??!0,this.textureCache.set(e.id,t),t))),this.textureCache.get(e.id))}async getMesh(e){if(await this.ready,!w.includes(e.fileFormat?.toLowerCase()))return console.error("Unsupported mesh file format "+e.fileFormat,e),{scene:new t};if(!this.cache.has(e.fileKey))try{this.cache.set(e.fileKey,await this.loadMesh(e))}catch(e){return this.onError(e),{scene:new t}}const s=h(this.cache.get(e.fileKey).scene);s.traverse((e=>{e instanceof a&&e.material instanceof Array&&(e.material=e.material.slice())}));const i=this.computeCollisionShapes(e,s),r=(new AssetMeshInstance).copy(s);return r.collisionShapes=i,{scene:r}}async getAudio(e){return await this.ready,this.audioLoader.loadAsync(this.getUri(e.fileKey))}computeCollisionShapes(e,t){return this.collisionShapeCache.get(e.id)||this.collisionShapeCache.set(e.id,f(t)),this.collisionShapeCache.get(e.id)}async loadMesh(e){return await this.ready,await this.loadByAsset(e).then((e=>(e.scene.animations=[],e.scene=function(e,t){let s=!1;if(t.traverseVisible((e=>{b.test(e.name)&&(s=!0)})),!s)return t;const a=new m.LOD,i=[t];for(;i.length>0;){const e=i.shift(),t=e.name.match(b);if(null!=t){const s=parseInt(t[1]);0===s?a.addLevel(e,0):console.warn(`Skipping LOD level ${s} for now as LOD is not fully supported`)}else i.push(...e.children)}return a}(0,e.scene),e)))}async loadByAsset(e){const t=this.getUri(e.fileKey);switch(e.fileFormat){case"glb":case"gltf":return this.glbLoader.loadAsync(t).then((e=>({scene:e.scene})));case"fbx":return this.fbxLoader.loadAsync(t).then((e=>({scene:e})));case"obj":if(null!=e.materialLib){const t=new o;t.materialOptions={normalizeRGB:!1};const s=await t.loadAsync(this.getUri(e.materialLib));this.objLoader.setMaterials(s)}return this.objLoader.loadAsync(t).then((e=>(y(e),e))).then((e=>({scene:e})))}}}function y(e){if(e instanceof a)for(const t of g(e.material))t instanceof m.MeshPhongMaterial&&!t.color.isLinear&&(t.color.isLinear=!0,t.color.convertSRGBToLinear());e.children?.forEach(y)}export class AssetMeshInstance extends i{}export function getElectronArg(e){const t=`--${e}=`,s=window.process?.argv.find((e=>e.startsWith(t)));return s?.substring(t.length)}function L(e){switch(e){case"clamp":return m.ClampToEdgeWrapping;case"repeat":return m.RepeatWrapping;case"mirror":return m.MirroredRepeatWrapping}return m.RepeatWrapping}const b=/_LOD(\d+)$/;
1
+ import{AudioLoader as e,Group as t,LoadingManager as i,Mesh as a,Object3D as s,TextureLoader as r}from"three";import{GLTFLoader as n,MTLLoader as o,OBJLoader as c}from"three-stdlib";import{FBXLoader as h}from"three-stdlib";import{cloneMesh as l}from"../utils/mesh.js";import{pathJoin as d}from"../utils/files.js";import{Subject as p,firstValueFrom as m}from"rxjs";import{importCollisionShapes as f}from"./collision/collision-shape-import.js";import*as u from"three";import{iterateMaterials as g}from"../utils/materials.js";const w=["glb","gltf","fbx","obj"];export class AssetResourceLoader{onError(e){console.error(e)}constructor(){this.cache=new Map,this.textureCache=new Map,this.loadingManager=new i,this.glbLoader=new n(this.loadingManager),this.fbxLoader=new h(this.loadingManager),this.objLoader=new c(this.loadingManager),this.textureLoader=new r(this.loadingManager),this.audioLoader=new e(this.loadingManager),this.makeReady=new p,this.ready=m(this.makeReady),this.collisionShapeCache=new Map}setDataDir(e){this.basePath=d(e,"asset-resources"),this.makeReady.next(!0)}getUri(e){return d(this.basePath,e)+`?windowId=${getElectronArg("windowId")}`}async getTexture(e){return null==e?null:(await this.ready,this.cache.has(e.id)||await this.textureLoader.loadAsync(this.getUri(e.fileKey)).then((t=>(t.wrapS=L(e.texture?.wrapS),t.wrapT=L(e.texture?.wrapT),t.flipY=e.texture?.flipY??!0,this.textureCache.set(e.id,t),t))),this.textureCache.get(e.id))}async getMesh(e){if(await this.ready,!w.includes(e.fileFormat?.toLowerCase()))return console.error("Unsupported mesh file format "+e.fileFormat,e),{scene:new t,animations:[]};if(!this.cache.has(e.fileKey))try{this.cache.set(e.fileKey,await this.loadMesh(e))}catch(e){return this.onError(e),{scene:new t,animations:[]}}const i=l(this.cache.get(e.fileKey).scene),s=this.cache.get(e.fileKey).animations;i.traverse((e=>{e instanceof a&&e.material instanceof Array&&(e.material=e.material.slice())}));const r=this.computeCollisionShapes(e,i),n=(new AssetMeshInstance).copy(i);return n.collisionShapes=r,{scene:n,animations:s}}async getAudio(e){return await this.ready,this.audioLoader.loadAsync(this.getUri(e.fileKey))}computeCollisionShapes(e,t){return this.collisionShapeCache.get(e.id)||this.collisionShapeCache.set(e.id,f(t)),this.collisionShapeCache.get(e.id)}async loadMesh(e){return await this.ready,await this.loadByAsset(e).then((e=>(e.scene.animations=[],e.scene=function(e,t){let i=!1;if(t.traverseVisible((e=>{b.test(e.name)&&(i=!0)})),!i)return t;const a=new u.LOD,s=[t];for(;s.length>0;){const e=s.shift(),t=e.name.match(b);if(null!=t){const i=parseInt(t[1]);0===i?a.addLevel(e,0):console.warn(`Skipping LOD level ${i} for now as LOD is not fully supported`)}else s.push(...e.children)}return a}(0,e.scene),e)))}async loadByAsset(e){const t=this.getUri(e.fileKey);switch(e.fileFormat){case"glb":case"gltf":return this.glbLoader.loadAsync(t).then((e=>({scene:e.scene,animations:e.animations})));case"fbx":return this.fbxLoader.loadAsync(t).then((e=>({scene:e,animations:e.animations})));case"obj":if(null!=e.materialLib){const t=new o;t.materialOptions={normalizeRGB:!1};const i=await t.loadAsync(this.getUri(e.materialLib));this.objLoader.setMaterials(i)}return this.objLoader.loadAsync(t).then((e=>(y(e),e))).then((e=>({scene:e,animations:e.animations})))}}}function y(e){if(e instanceof a)for(const t of g(e.material))t instanceof u.MeshPhongMaterial&&!t.color.isLinear&&(t.color.isLinear=!0,t.color.convertSRGBToLinear());e.children?.forEach(y)}export class AssetMeshInstance extends s{}export function getElectronArg(e){const t=`--${e}=`,i=window.process?.argv.find((e=>e.startsWith(t)));return i?.substring(t.length)}function L(e){switch(e){case"clamp":return u.ClampToEdgeWrapping;case"repeat":return u.RepeatWrapping;case"mirror":return u.MirroredRepeatWrapping}return u.RepeatWrapping}const b=/_LOD(\d+)$/;
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -5,6 +5,7 @@ import { RuntimeBackendService } from './runtime-backend-service.js';
5
5
  export declare class RuntimeAssetsService implements AssetsProvider {
6
6
  private backend;
7
7
  private assets;
8
+ private loaded;
8
9
  onCreate: Subject<Asset>;
9
10
  onDelete: Subject<Asset>;
10
11
  onUpdate: Subject<Asset>;
@@ -1,4 +1,4 @@
1
- import{Subject as s}from"rxjs";export class RuntimeAssetsService{constructor(e){this.backend=e,this.assets=new Map,this.onCreate=new s,this.onDelete=new s,this.onUpdate=new s}async getAssets(){return Array.from(this.assets.values())}async getAsset(s){return this.assets.get(s)??async function(s,t){e.has(s)||e.set(s,t(s));return e.get(s)}(s,(()=>this.backend.getAsset(s)))}}const e=new Map;
1
+ import{Subject as s}from"rxjs";export class RuntimeAssetsService{constructor(t){this.backend=t,this.assets=new Map,this.loaded=!1,this.onCreate=new s,this.onDelete=new s,this.onUpdate=new s}async getAssets(){if(!this.loaded){const s=await this.backend.getAssets();for(const t of s)this.assets.set(t.id,t)}return Array.from(this.assets.values())}async getAsset(s){return this.assets.get(s)??async function(s,e){t.has(s)||t.set(s,e(s));return t.get(s)}(s,(()=>this.backend.getAsset(s)))}}const t=new Map;
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
@@ -1,4 +1,4 @@
1
- import{randomUUID as t}from"../../utils/uuid.js";import{pathJoin as e}from"../../utils/files.js";import{firstValueFrom as a,map as i,Subject as s,tap as n}from"rxjs";import{sleepDelay as r}from"../../utils/async.js";const h={},c={},o={};null==h.read&&window.require&&(Object.assign(h,window.require("fs")),Object.assign(c,h.promises),Object.assign(o,window.require("path")));const l=null!=h.existsSync;const u=/^[A-Z]:/;function d(...t){return 0===t.length?"":u.test(t[0])?o.join(...t):e(...t)}export class ObjectStorage{constructor(t,e){this.name=t,this.filePathFn=e,this.basePathUpdates=new s,this.basePath=this.basePathUpdates.pipe(i((t=>d(function(){if(l){const t="--path=",e=window.process.argv.find((e=>e.startsWith(t)));return e?e.substring(t.length):""}return""}(),t))),n((t=>{this.path=d(t,this.name),p(this.path)}))),this.loaded=a(this.basePath)}setBasePath(t){this.basePathUpdates.next(t)}async getAll(){f(),await this.loaded,await p(this.path);const t=(await c.readdir(this.path)).filter((t=>!/^[\._]/.test(t)));return(await Promise.all(t.map((t=>c.readFile(d(this.path,t)))))).map((t=>JSON.parse(t.toString())))}async get(t){const e=await this.loadIndex(),a=e[t]??Object.values(e).find((e=>e.name===t));if(null==a)return;const i=this.privateObjectPath(a);if(!l)return(await fetch(i)).json();return await w(i)?JSON.parse((await c.readFile(i)).toString()):null}async save(t){return f(),await this.loaded,await c.writeFile(this.privateObjectPath(t),JSON.stringify(t,null,2)),await this.updateIndex(),t}async rename(t,e){const a={...t,name:e},i=this.privateObjectPath(t),s=this.privateObjectPath(a);try{await c.rename(i,s)}catch(t){console.error(t),console.warn("Rename failed, retrying",{currentPath:i,newPath:s}),await r(400),await c.rename(i,s)}return await this.save(a),await this.updateIndex(),a}async delete(t){await c.unlink(this.privateObjectPath(t)),this.updateIndex()}async create(e){return f(),await this.loaded,e.id=t(),await c.writeFile(this.privateObjectPath(e),JSON.stringify(e,null,2)),await this.updateIndex(),e}async updateIndex(){f();const t=await this.getAll(),e={};for(const a of t)e[a.id]={id:a.id,name:a.name??a.id,path:a.path};this.cachedIndex=e,l&&await c.writeFile(this.indexFilePath,JSON.stringify(e,null,2))}get indexFilePath(){return d(this.path,"_meta.json")}async loadIndex(){return null==this.cachedIndex&&(l?await this.updateIndex():this.cachedIndex=await(await fetch(this.indexFilePath)).json()),this.cachedIndex}async ensureResourceDir(){await p(d(this.path+"-resources"))}async saveFile(t,e){return f(),await p(d(this.path+"-resources")),c.copyFile(e.path,d(this.path+"-resources",t.fileKey))}async saveExtraFile(t,e){return f(),await p(d(this.path+"-resources")),c.copyFile(t,d(this.path+"-resources",e))}getAssetPath(t){return window&&"function"==typeof window.require?window.require("path").join(this.path+"-resources",t.fileKey):d(this.path+"-resources",t.fileKey)}async replaceFile(t,e){if(await w(e))return c.copyFile(e,d(this.path+"-resources",t.fileKey));console.error("Failed to replace file using path "+e)}async deleteFile(t){if(null==t)return;f();const e=d(this.path+"-resources",t);return await w(e)?c.unlink(e):void 0}privateObjectPath(t){return this.filePathFn?d(this.path,this.filePathFn(t)):d(this.path,tokenizeName(t.name??t.id)+".json")}}export function tokenizeName(t){return t.trim().replace(/\s/g,"_").replace(/[^a-z0-9_\-\.]/gi,"")}async function p(t){l&&(await w(t)||await c.mkdir(t,{recursive:!0}))}function w(t){return!!l&&new Promise((function(e,a){h.exists(t,(function(t){e(t)}))}))}function f(){if(!l)throw new Error("Must have direct access to filesystem")}
1
+ import{randomUUID as t}from"../../utils/uuid.js";import{pathJoin as e}from"../../utils/files.js";import{firstValueFrom as a,map as i,Subject as s,tap as n}from"rxjs";import{sleepDelay as r}from"../../utils/async.js";const h={},c={},o={};null==h.read&&window.require&&(Object.assign(h,window.require("fs")),Object.assign(c,h.promises),Object.assign(o,window.require("path")));const l=null!=h.existsSync;const u=/^[A-Z]:/;function d(...t){return 0===t.length?"":u.test(t[0])?o.join(...t):e(...t)}export class ObjectStorage{constructor(t,e){this.name=t,this.filePathFn=e,this.basePathUpdates=new s,this.basePath=this.basePathUpdates.pipe(i((t=>d(function(){if(l){const t="--path=",e=window.process.argv.find((e=>e.startsWith(t)));return e?e.substring(t.length):""}return""}(),t))),n((t=>{this.path=d(t,this.name),p(this.path)}))),this.loaded=a(this.basePath)}setBasePath(t){this.basePathUpdates.next(t)}async getAll(){if(l){await this.loaded,await p(this.path);const t=(await c.readdir(this.path)).filter((t=>!/^[\._]/.test(t)));return(await Promise.all(t.map((t=>c.readFile(d(this.path,t)))))).map((t=>JSON.parse(t.toString())))}const t=await this.loadIndex();return Promise.all(Object.keys(t).map((t=>this.get(t))))}async get(t){const e=await this.loadIndex(),a=e[t]??Object.values(e).find((e=>e.name===t));if(null==a)return;const i=this.privateObjectPath(a);if(!l)return(await fetch(i)).json();return await w(i)?JSON.parse((await c.readFile(i)).toString()):null}async save(t){return f(),await this.loaded,await c.writeFile(this.privateObjectPath(t),JSON.stringify(t,null,2)),await this.updateIndex(),t}async rename(t,e){const a={...t,name:e},i=this.privateObjectPath(t),s=this.privateObjectPath(a);try{await c.rename(i,s)}catch(t){console.error(t),console.warn("Rename failed, retrying",{currentPath:i,newPath:s}),await r(400),await c.rename(i,s)}return await this.save(a),await this.updateIndex(),a}async delete(t){await c.unlink(this.privateObjectPath(t)),this.updateIndex()}async create(e){return f(),await this.loaded,e.id=t(),await c.writeFile(this.privateObjectPath(e),JSON.stringify(e,null,2)),await this.updateIndex(),e}async updateIndex(){f();const t=await this.getAll(),e={};for(const a of t)e[a.id]={id:a.id,name:a.name??a.id,path:a.path};this.cachedIndex=e,l&&await c.writeFile(this.indexFilePath,JSON.stringify(e,null,2))}get indexFilePath(){return d(this.path,"_meta.json")}async loadIndex(){return null==this.cachedIndex&&(l?await this.updateIndex():this.cachedIndex=await(await fetch(this.indexFilePath)).json()),this.cachedIndex}async ensureResourceDir(){await p(d(this.path+"-resources"))}async saveFile(t,e){return f(),await p(d(this.path+"-resources")),c.copyFile(e.path,d(this.path+"-resources",t.fileKey))}async saveExtraFile(t,e){return f(),await p(d(this.path+"-resources")),c.copyFile(t,d(this.path+"-resources",e))}getAssetPath(t){return window&&"function"==typeof window.require?window.require("path").join(this.path+"-resources",t.fileKey):d(this.path+"-resources",t.fileKey)}async replaceFile(t,e){if(await w(e))return c.copyFile(e,d(this.path+"-resources",t.fileKey));console.error("Failed to replace file using path "+e)}async deleteFile(t){if(null==t)return;f();const e=d(this.path+"-resources",t);return await w(e)?c.unlink(e):void 0}privateObjectPath(t){return this.filePathFn?d(this.path,this.filePathFn(t)):d(this.path,tokenizeName(t.name??t.id)+".json")}}export function tokenizeName(t){return t.trim().replace(/\s/g,"_").replace(/[^a-z0-9_\-\.]/gi,"")}async function p(t){l&&(await w(t)||await c.mkdir(t,{recursive:!0}))}function w(t){return!!l&&new Promise((function(e,a){h.exists(t,(function(t){e(t)}))}))}function f(){if(!l)throw new Error("Must have direct access to filesystem")}
2
2
  /*
3
3
  * Copyright (©) 2023. All rights reserved.
4
4
  * See the LICENSE.md file for details.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hology/core",
3
- "version": "0.0.33",
3
+ "version": "0.0.34",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",