@combos-fun/engine 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- "use strict";var e=require("eventemitter3"),t=require("lodash-es"),s=require("tslib"),r=require("@combos-fun/inspector-decorator"),o=require("resource-loader");function n(e){return e&&e.__esModule?e:{default:e}}var a,i=n(e);class c extends i.default{constructor(e){super(),this.started=!1;const t=this.constructor;this.name=t.componentName,this.__componentDefaultParams=e}}exports.OBSERVER_TYPE=void 0,(a=exports.OBSERVER_TYPE||(exports.OBSERVER_TYPE={})).ADD="ADD",a.REMOVE="REMOVE",a.CHANGE="CHANGE";const h={},p={},m={},d={};function l(e,t){h[e.gameObject.id]||(h[e.gameObject.id]={});const s=h[e.gameObject.id],r=e.name+"_"+t.join(",");if(s[r])return s[r];const o=t.length-1;let n=e;for(let e=0;e<o;e++)n=n[t[e]];return s[r]={property:n,key:t[o]},s[r]}function u({systemName:e,componentName:t,component:s,prop:r,type:o}){p[e]?.componentObserver?.add({component:s,prop:r,type:o,componentName:t})}function y({obj:e,key:s,prop:r,component:o,componentName:n}){if(void 0!==e)if(s in e){if(Object.defineProperty(e,`_${s}`,{enumerable:!1,writable:!0,value:e[s]}),r.deep&&t.isObject(e[s]))for(const t of Object.keys(e[s]))y({obj:e[s],key:t,prop:r,component:o,componentName:n});Object.defineProperty(e,s,{enumerable:!0,set(a){e[`_${s}`]!==a&&(e[`_${s}`]=a,function({prop:e,component:s,componentName:r}){for(const o in m){const n=(m[o]||{})[r];n&&(n.findIndex(s=>t.isEqual(s,e))>-1&&u({systemName:o,componentName:r,component:s,prop:e,type:exports.OBSERVER_TYPE.CHANGE}))}}({prop:r,component:o,componentName:n}))},get:()=>e[`_${s}`]})}else console.error(`prop ${s} not in component: ${n}, Can not observer`)}function f(e,t=e.name){for(const s in m){(m[s]||{})[t]&&p[s]?.componentObserver?.add({component:e,type:exports.OBSERVER_TYPE.REMOVE,componentName:t})}!function(e){e.gameObject&&delete h[e.gameObject.id]}(e)}class g extends c{constructor(){super(...arguments),this.name="Transform",this._parent=null,this.inScene=!1,this.children=[],this.position={x:0,y:0},this.size={width:0,height:0},this.origin={x:0,y:0},this.anchor={x:0,y:0},this.scale={x:1,y:1},this.skew={x:0,y:0},this.rotation=0}static{this.componentName="Transform"}init(e={}){const t=["position","size","origin","anchor","scale","skew"];for(const s of t)Object.assign(this[s],e[s]);this.rotation=e.rotation||this.rotation}set parent(e){e?e.addChild(this):this.parent&&this.parent.removeChild(this)}get parent(){return this._parent}addChild(e){if(e.parent===this){const t=this.children.findIndex(t=>t===e);this.children.splice(t,1)}else e.parent&&e.parent.removeChild(e);e._parent=this,this.children.push(e)}removeChild(e){const t=this.children.findIndex(t=>t===e);t>-1&&(this.children.splice(t,1),e._parent=null)}clearChildren(){this.children.length=0}}s.__decorate([r.type("vector2"),r.step(1)],g.prototype,"position",void 0),s.__decorate([r.type("size"),r.step(1)],g.prototype,"size",void 0),s.__decorate([r.type("vector2"),r.step(.1)],g.prototype,"origin",void 0),s.__decorate([r.type("vector2"),r.step(.1)],g.prototype,"anchor",void 0),s.__decorate([r.type("vector2"),r.step(.1)],g.prototype,"scale",void 0),s.__decorate([r.type("vector2"),r.step(.1)],g.prototype,"skew",void 0),s.__decorate([r.type("number"),r.step(.1)],g.prototype,"rotation",void 0);let E=0;class _{constructor(e,t){this._componentCache={},this.components=[],this.destroyed=!1,this._name=e,this.id=++E,this.addComponent(g,t)}get transform(){return this.getComponent(g)}get parent(){return this.transform&&this.transform.parent&&this.transform.parent.gameObject}get name(){return this._name}set scene(e){if(this._scene===e)return;const t=this._scene;if(this._scene=e,this.transform&&this.transform.children)for(const t of this.transform.children)t.gameObject.scene=e;e?e.addGameObject(this):t&&t.removeGameObject(this)}get scene(){return this._scene}addChild(e){if(e&&e.transform&&e!==this){if(!(e instanceof _))throw new Error("addChild only receive GameObject");if(!this.transform)throw new Error(`gameObject '${this.name}' has been destroy`);e.transform.parent=this.transform,e.scene=this.scene}}removeChild(e){return e instanceof _&&e.parent&&e.parent===this?(e.transform.parent=null,e.scene=null,e):e}addComponent(e,t){if(this.destroyed)return;const s=function(e){return e instanceof c?e.name:e instanceof Function?e.componentName:void 0}(e);if(this._componentCache[s])return;let r;if(e instanceof Function)r=new e(t);else{if(!(e instanceof c))throw new Error("addComponent recieve Component and Component Constructor");r=e}if(r.gameObject)throw new Error(`component has been added on gameObject ${r.gameObject.name}`);return r.gameObject=this,r.init&&r.init(r.__componentDefaultParams),function(e,t=e.name){for(const s in m)(m[s]||{})[t]&&p[s]?.componentObserver?.add({component:e,type:exports.OBSERVER_TYPE.ADD,componentName:t})}(r,r.name),function(e,t=e.name){if(t&&d[t]){if(!(e&&(s=e,s&&s.constructor&&"componentName"in s.constructor)))throw new Error("component param must be an instance of Component");var s;if(!e.gameObject||!e.gameObject.id)throw new Error("component should be add to a gameObject");for(const s of d[t]){const{property:r,key:o}=l(e,s.prop);y({obj:r,key:o,prop:s,component:e,componentName:t})}}}(r,r.name),this.components.push(r),this._componentCache[s]=r,r.awake&&r.awake(),r}removeComponent(e){let t;if("string"==typeof e?t=e:e instanceof c?t=e.name:e.componentName&&(t=e.componentName),"Transform"===t)throw new Error("Transform can't be removed");return this._removeComponent(t)}_removeComponent(e){const t=this.components.findIndex(({name:t})=>t===e);if(-1===t)return;const s=this.components.splice(t,1)[0];return delete this._componentCache[e],delete s.__componentDefaultParams,s.onDestroy&&s.onDestroy(),f(s,e),s.gameObject=void 0,s}getComponent(e){let t;return"string"==typeof e?t=e:e instanceof c?t=e.name:e.componentName&&(t=e.componentName),void 0!==this._componentCache[t]?this._componentCache[t]:void 0}remove(){if(this.parent)return this.parent.removeChild(this)}destroy(){if(this.transform){Array.from(this.transform.children).forEach(({gameObject:e})=>{e.destroy()}),this.remove(),this.transform.clearChildren();for(const e in this._componentCache)this._removeComponent(e);this.components.length=0,this.destroyed=!0}else console.error("Cannot destroy gameObject that have already been destroyed.")}}class b{constructor(){this.events=[]}add({component:e,prop:s,type:r,componentName:o}){if(r===exports.OBSERVER_TYPE.REMOVE){if(this.events.find(t=>t.component===e&&t.type===exports.OBSERVER_TYPE.ADD))return void(this.events=this.events.filter(t=>t.component!==e));this.events=this.events.filter(t=>t.component!==e)}const n=this.events.findIndex(o=>o.component===e&&t.isEqual(o.prop,s)&&o.type===r);n>-1&&this.events.splice(n,1),this.events.push({gameObject:e.gameObject,component:e,prop:s,type:r,componentName:o})}getChanged(){return this.events}get changed(){return this.events}clear(){const e=this.events;return this.events=[],e}}class R{constructor(e){this.started=!1,this.componentObserver=new b,this.__systemDefaultParams=e;const t=this.constructor;this.name=t.systemName}destroy(){this.componentObserver=null,this.__systemDefaultParams=null,this.onDestroy?.()}}const T=function(){let e=null;return e=Date.now?Date.now:()=>(new Date).getTime(),e}(),O={originTime:0,playbackRate:1};class S{constructor(e,t){e instanceof S&&(t=e,e={}),e=Object.assign({},O,e),t&&(this._parent=t),this._createTime=T(),this._timeMark=[{globalTime:this.globalTime,localTime:-e.originTime,entropy:-e.originTime,playbackRate:e.playbackRate,globalEntropy:0}],this._parent&&(this._timeMark[0].globalEntropy=this._parent.entropy),this._playbackRate=e.playbackRate}get globalTime(){return this.parent?this.parent.currentTime:T()-this._createTime}get parent(){return this._parent}get lastTimeMark(){return this._timeMark[this._timeMark.length-1]}markTime({time:e=this.currentTime,entropy:t=this.entropy,playbackRate:s=this.playbackRate}={}){const r={globalTime:this.globalTime,localTime:e,entropy:t,playbackRate:s,globalEntropy:this.globalEntropy};this._timeMark.push(r)}get currentTime(){const{localTime:e,globalTime:t}=this.lastTimeMark;return e+(this.globalTime-t)*this.playbackRate}set currentTime(e){this.markTime({time:e})}get globalEntropy(){return this._parent?this._parent.entropy:this.globalTime}get entropy(){const{entropy:e,globalEntropy:t}=this.lastTimeMark;return e+Math.abs((this.globalEntropy-t)*this.playbackRate)}set entropy(e){if(this.entropy>e){const t=this.seekTimeMark(e);this._timeMark.length=t+1}this.markTime({entropy:e})}fork(e){return new S(e,this)}seekGlobalTime(e){const t=this.seekTimeMark(e),s=this._timeMark[t],{entropy:r,playbackRate:o,globalTime:n}=s;return n+(e-r)/Math.abs(o)}seekLocalTime(e){const t=this.seekTimeMark(e),s=this._timeMark[t],{localTime:r,entropy:o,playbackRate:n}=s;return n>0?r+(e-o):r-(e-o)}seekTimeMark(e){const t=this._timeMark;let s=0,r=t.length-1;if(e<=t[s].entropy)return s;if(e>=t[r].entropy)return r;let o=Math.floor((s+r)/2);for(;o>s&&o<r;){if(e===t[o].entropy)return o;e<t[o].entropy?r=o:e>t[o].entropy&&(s=o),o=Math.floor((s+r)/2)}return s}get playbackRate(){return this._playbackRate}set playbackRate(e){e!==this.playbackRate&&(this.markTime({playbackRate:e}),this._playbackRate=e)}get paused(){if(0===this.playbackRate)return!0;let e=this.parent;for(;e;){if(0===e.playbackRate)return!0;e=e.parent}return!1}}const k={autoStart:!0,frameRate:60};class v{constructor(e){e=Object.assign({},k,e),this._frameCount=0,this._frameDuration=1e3/e.frameRate,this.autoStart=e.autoStart,this.frameRate=e.frameRate,this.timeline=new S({originTime:0,playbackRate:1}),this._lastFrameTime=this.timeline.currentTime,this._tickers=new Set,this._requestId=null,this._ticker=()=>{this._started&&(this._requestId=requestAnimationFrame(this._ticker),this.update())},this.autoStart&&this.start()}update(){const e=this.timeline.currentTime,t=e-this._lastFrameTime;if(t>=this._frameDuration){const s=e-t%this._frameDuration,r=s-this._lastFrameTime;this._lastFrameTime=s;const o={deltaTime:r,time:s,currentTime:s,frameCount:++this._frameCount,fps:Math.round(1e3/r)};for(const e of this._tickers)"function"==typeof e&&e(o)}}add(e){this._tickers.add(e)}remove(e){this._tickers.delete(e)}start(){this._started||(this._started=!0,this.timeline.playbackRate=1,this._requestId=requestAnimationFrame(this._ticker))}pause(){this._started=!1,this.timeline.playbackRate=0}setPlaybackRate(e){this.timeline.playbackRate=e}}class x extends _{constructor(e,t){super(e,t),this.gameObjects=[],this.scene=this}addGameObject(e){this.gameObjects.push(e),e.transform&&(e.transform.inScene=!0)}removeGameObject(e){const t=this.gameObjects.indexOf(e);-1!==t&&(e.transform&&(e.transform.inScene=!1),this.gameObjects.splice(t,1))}destroy(){this.scene=null,super.destroy(),this.gameObjects=null,this.canvas=null}}function L(e){if("systemName"in e){const t=e.systemName;if("string"==typeof t)return t}return"UnknownSystem"}var C;exports.LOAD_SCENE_MODE=void 0,(C=exports.LOAD_SCENE_MODE||(exports.LOAD_SCENE_MODE={})).SINGLE="SINGLE",C.MULTI_CANVAS="MULTI_CANVAS";const M=e=>{if((e instanceof R||e instanceof c)&&!e.started){e.started=!0;try{e.start&&e.start()}catch(t){e instanceof c?console.error(`${function(e){if("componentName"in e){const t=e.componentName;if("string"==typeof t)return t}return"UnknownComponent"}(e.constructor)} start error`,t):console.error(`${L(e.constructor)} start error`,t)}}};class P extends i.default{constructor({systems:e,frameRate:t=60,autoStart:s=!0,needScene:r=!0,onSystemsBootstrapComplete:o}={}){if(super(),this.playing=!1,this.started=!1,this.multiScenes=[],this.systems=[],this.ticker=new v({autoStart:!1,frameRate:t}),this.initTicker(),e&&e.length){const t=[...e];this.bootstrapSystemsAndMaybeStart(t,r,s,o)}else o?.(this)}async bootstrapSystemsAndMaybeStart(e,t,s,r){let o;try{for(const t of e)await this.addSystem(t);t&&this.loadScene(new x("scene")),s&&this.start()}catch(e){o=e,console.error("Game bootstrap failed",e)}finally{r?.(this,o)}}get scene(){return this._scene}set scene(e){this._scene=e}get gameObjects(){return(e=>{const t=e?.scene?.gameObjects||[],s=e?.multiScenes.map(({gameObjects:e})=>e);let r=[];for(const e of s)r=[...r,...e];return[...t,...r]})(this)}async addSystem(e,s){let r;if(e instanceof Function)r=new e(s);else{if(!(e instanceof R))return void console.warn("can only add System");r=e}if(!this.systems.find(e=>e.constructor===r.constructor)){r.game=this,r.init&&await Promise.resolve(r.init(r.__systemDefaultParams)),function(e,t){m[t.systemName]=t.observerInfo,p[t.systemName]=e}(r,r.constructor),function(e){const s=[];e instanceof Array?s.push(...e):s.push(e);for(const e of s)for(const s in e.observerInfo){d[s]=d[s]||[];const r=d[s];for(const o of e.observerInfo[s])-1===r.findIndex(e=>t.isEqual(e,o))&&d[s].push(o)}}(r.constructor);try{r.awake&&r.awake()}catch(e){console.error(`${L(r.constructor)} awake error`,e)}return this.systems.push(r),r}console.warn(`${L(r.constructor)} System has been added`)}removeSystem(e){if(!e)return;let t=-1;"string"==typeof e?t=this.systems.findIndex(t=>t.name===e):e instanceof Function?t=this.systems.findIndex(t=>t.constructor===e):e instanceof R&&(t=this.systems.findIndex(t=>t===e)),t>-1&&(this.systems[t].destroy&&this.systems[t].destroy(),this.systems.splice(t,1))}getSystem(e){return this.systems.find(t=>"string"==typeof e?t.name===e:t instanceof e)}pause(){this.playing&&(this.playing=!1,this.ticker.pause(),this.triggerPause())}start(){this.playing||(this.playing=!0,this.started=!0,this.ticker.start())}resume(){this.playing||(this.playing=!0,this.ticker.start(),this.triggerResume())}initTicker(){this.ticker.add(e=>{this.scene&&((e,t=[])=>{for(const s of t)for(const t of s.components)try{M(t),t.update&&t.update(e)}catch(e){console.error(`gameObject: ${s.name} ${t.name} update error`,e)}for(const s of t)for(const t of s.components)try{t.lateUpdate&&t.lateUpdate(e)}catch(e){console.error(`gameObject: ${s.name} ${t.name} lateUpdate error`,e)}})(e,this.gameObjects);for(const t of this.systems)try{M(t),t.update&&t.update(e)}catch(e){console.error(`${L(t.constructor)} update error`,e)}for(const t of this.systems)try{t.lateUpdate&&t.lateUpdate(e)}catch(e){console.error(`${L(t.constructor)} lateUpdate error`,e)}})}triggerResume(){(e=>{for(const t of e)for(const e of t.components)try{e.onResume&&e.onResume()}catch(s){console.error(`gameObject: ${t.name}, ${e.name}, onResume error`,s)}})(this.gameObjects);for(const e of this.systems)try{e.onResume&&e.onResume()}catch(t){console.error(`${L(e.constructor)}, onResume error`,t)}}triggerPause(){(e=>{for(const t of e)for(const e of t.components)try{e.onPause&&e.onPause()}catch(s){console.error(`gameObject: ${t.name}, ${e.name}, onResume error`,s)}})(this.gameObjects);for(const e of this.systems)try{e.onPause&&e.onPause()}catch(t){console.error(`${L(e.constructor)}, onPause error`,t)}}destroySystems(){for(const e of[...this.systems])this.removeSystem(e);this.systems.length=0}destroy(){this.removeAllListeners(),this.pause(),this.scene.destroy(),this.destroySystems(),this.ticker=null,this.scene=null,this.canvas=null,this.multiScenes=null}loadScene({scene:e,mode:t=exports.LOAD_SCENE_MODE.SINGLE,params:s={}}){if(e){switch(t){case exports.LOAD_SCENE_MODE.SINGLE:this.scene=e;break;case exports.LOAD_SCENE_MODE.MULTI_CANVAS:this.multiScenes.push(e)}this.emit("sceneChanged",{scene:e,mode:t,params:s})}}}function w(e,t){e.constructor.IDEProps||(e.constructor.IDEProps=[]),e.constructor.IDEProps.push(t)}function A(e={}){return function(t){if(!t.observerInfo){for(const t in e)for(const s in e[t]){let r;"string"==typeof e[t][s]&&(e[t][s]=[e[t][s]]),Array.isArray(e[t][s])&&(r={prop:e[t][s],deep:!1},e[t][s]=r),r=e[t][s],"string"==typeof r.prop&&(r.prop=[r.prop])}t.observerInfo=e}}}var I;exports.LOAD_EVENT=void 0,(I=exports.LOAD_EVENT||(exports.LOAD_EVENT={})).START="start",I.PROGRESS="progress",I.LOADED="loaded",I.COMPLETE="complete",I.ERROR="error";class N extends i.default{constructor({resource:e,resourceTotal:t}){super(),this.progress=0,this.resourceTotal=0,this.resourceLoadedCount=0,this.resource=e,this.resourceTotal=t,0===t&&this.resource.emit(exports.LOAD_EVENT.COMPLETE,this)}onStart(){this.resource.emit(exports.LOAD_EVENT.START,this)}onProgress(e){this.resourceLoadedCount++,this.progress=Math.floor(this.resourceLoadedCount/this.resourceTotal*100)/100,e.success?this.resource.emit(exports.LOAD_EVENT.LOADED,this,e):this.resource.emit(exports.LOAD_EVENT.ERROR,this,e),this.resource.emit(exports.LOAD_EVENT.PROGRESS,this,e),this.resourceLoadedCount===this.resourceTotal&&this.resource.emit(exports.LOAD_EVENT.COMPLETE,this)}}const D={AbstractLoadStrategy:o.AbstractLoadStrategy,AudioLoadStrategy:o.AudioLoadStrategy,ImageLoadStrategy:o.ImageLoadStrategy,XhrResponseType:o.XhrResponseType,MediaElementLoadStrategy:o.MediaElementLoadStrategy,VideoLoadStrategy:o.VideoLoadStrategy,XhrLoadStrategy:o.XhrLoadStrategy,Loader:o.Loader,Resource:o.Resource,ResourceType:o.ResourceType,ResourceState:o.ResourceState};var j;exports.RESOURCE_TYPE=void 0,(j=exports.RESOURCE_TYPE||(exports.RESOURCE_TYPE={})).IMAGE="IMAGE",j.SPRITE="SPRITE",j.SPRITE_ANIMATION="SPRITE_ANIMATION",j.AUDIO="AUDIO",j.VIDEO="VIDEO",o.XhrLoadStrategy.setExtensionXhrType("json",o.XhrResponseType.Json),o.XhrLoadStrategy.setExtensionXhrType("tex",o.XhrResponseType.Json),o.XhrLoadStrategy.setExtensionXhrType("ske",o.XhrResponseType.Json),o.XhrLoadStrategy.setExtensionXhrType("mp3",o.XhrResponseType.Buffer),o.XhrLoadStrategy.setExtensionXhrType("wav",o.XhrResponseType.Buffer),o.XhrLoadStrategy.setExtensionXhrType("aac",o.XhrResponseType.Buffer),o.XhrLoadStrategy.setExtensionXhrType("ogg",o.XhrResponseType.Buffer);const V={png:o.ImageLoadStrategy,jpg:o.ImageLoadStrategy,jpeg:o.ImageLoadStrategy,webp:o.ImageLoadStrategy,json:o.XhrLoadStrategy,tex:o.XhrLoadStrategy,ske:o.XhrLoadStrategy,audio:o.XhrLoadStrategy,video:o.VideoLoadStrategy};class $ extends i.default{constructor(e){super(),this.timeout=6e3,this.preProcessResourceHandlers=[],this.resourcesMap={},this.makeInstanceFunctions={},this.destroyInstanceFunctions={},this.promiseMap={},this.loaders=[],e&&"number"==typeof e.timeout&&(this.timeout=e.timeout)}loadConfig(e){this.addResource(e),this.preload()}loadSingle(e){return this.addResource([e]),this.getResource(e.name)}addResource(e){if(!e||e.length<1)console.warn("no resources");else for(const t of e)this.resourcesMap[t.name]?console.warn(t.name+" was already added"):(this.resourcesMap[t.name]=t,this.resourcesMap[t.name].data={})}addPreProcessResourceHandler(e){this.preProcessResourceHandlers.push(e)}removePreProcessResourceHandler(e){this.preProcessResourceHandlers.splice(this.preProcessResourceHandlers.indexOf(e),1)}preload(){const e=[];for(const t in this.resourcesMap){const s=this.resourcesMap[t];!s.preload||s.complete||this.promiseMap[t]||e.push(s.name)}this.progress=new N({resource:this,resourceTotal:e.length}),this.loadResource({names:e,preload:!0})}async getResource(e){return this.loadResource({names:[e]}),this.promiseMap[e]||Promise.resolve({})}async instance(e){const t=this.resourcesMap[e];return this.makeInstanceFunctions[t.type]&&await this.makeInstanceFunctions[t.type](t)}async destroy(e){await this._destroy(e)}async _destroy(e,t=!1){const s=this.resourcesMap[e];if(s){if(!t)try{this.destroyInstanceFunctions[s.type]&&await this.destroyInstanceFunctions[s.type](s)}catch(e){console.warn(`destroy resource ${s.name} error with '${e.message}'`)}delete this.promiseMap[e],s.data={},s.complete=!1,s.instance=void 0}}registerResourceType(e,t=e){if(exports.RESOURCE_TYPE[e])throw new Error(`The type ${e} already exists in RESOURCE_TYPE`);exports.RESOURCE_TYPE[e]=t}registerInstance(e,t){this.makeInstanceFunctions[e]=t}registerDestroy(e,t){this.destroyInstanceFunctions[e]=t}loadResource({names:e=[],preload:t=!1}){const s=e.filter(e=>!this.promiseMap[e]&&this.resourcesMap[e]);if(!s.length)return;const r={},o=this.getLoader(t);s.forEach(e=>{this.promiseMap[e]=new Promise(t=>r[e]=t);const s=this.resourcesMap[e];for(const e of this.preProcessResourceHandlers)e(s);for(const n in s.src){const a=s.src[n].type;"data"===a?(s.data[n]=s.src[n].data,this.doComplete(e,r[e],t)):o.add({url:s.src[n].url,name:`${s.name}_${n}`,strategy:V[a],metadata:{key:n,name:s.name,resolves:r}})}}),o.load()}async doComplete(e,t,s=!1){const r=this.resourcesMap[e],o={name:e,resource:this.resourcesMap[e],success:!0};if(this.checkAllLoaded(e))try{r.instance=await this.instance(e),r.complete=!0,s&&this.progress.onProgress(o),t(r)}catch(e){console.error(e),r.complete=!1,s&&(o.errMsg=e.message,o.success=!1,this.progress.onProgress(o)),t({})}}checkAllLoaded(e){const t=this.resourcesMap[e];return Array.from(Object.keys(t.src)).every(e=>t.data[e])}getLoader(e=!1){let t=this.loaders.find(({loading:e})=>!e);return t||(t=new o.Loader,this.loaders.push(t)),e&&t.onStart.once(()=>{this.progress.onStart()}),t.onLoad.add((t,s)=>{this.onLoad({preload:e,resource:s})}),t.onError.add((t,s,r)=>{this.onError({errMsg:t,resource:r,preload:e})}),t.onComplete.once(()=>{t.onLoad.detachAll(),t.onError.detachAll(),t.reset()}),t}async onLoad({preload:e=!1,resource:t}){const{metadata:{key:s,name:r,resolves:o},data:n}=t;this.resourcesMap[r].data[s]=n,this.doComplete(r,o[r],e)}async onError({errMsg:e,preload:t=!1,resource:s}){const{metadata:{name:r,resolves:o}}=s;if(this._destroy(r,!0),o[r]({}),t){const t={name:r,resource:this.resourcesMap[r],success:!1,errMsg:e};this.progress.onProgress(t)}}}const X=new $,G={IDEProp:w,componentObserver:A},U="__VERSION__";console.log(`@combos-fun/engine version: ${U}`),exports.Component=c,exports.Game=P,exports.GameObject=_,exports.IDEProp=w,exports.RESOURCE_TYPE_STRATEGY=V,exports.Scene=x,exports.System=R,exports.Transform=g,exports.componentObserver=A,exports.decorators=G,exports.resource=X,exports.resourceLoader=D,exports.version=U;
1
+ "use strict";var e=require("eventemitter3"),t=require("lodash-es"),s=require("tslib"),r=require("@combos-fun/inspector-decorator"),o=require("resource-loader");function n(e){return e&&e.__esModule?e:{default:e}}var a,i=n(e);class c extends i.default{constructor(e){super(),this.started=!1;const t=this.constructor;this.name=t.componentName,this.__componentDefaultParams=e}}exports.OBSERVER_TYPE=void 0,(a=exports.OBSERVER_TYPE||(exports.OBSERVER_TYPE={})).ADD="ADD",a.REMOVE="REMOVE",a.CHANGE="CHANGE";const p={},h={},m={},d={};function u(e,t){p[e.gameObject.id]||(p[e.gameObject.id]={});const s=p[e.gameObject.id],r=e.name+"_"+t.join(",");if(s[r])return s[r];const o=t.length-1;let n=e;for(let e=0;e<o;e++)n=n[t[e]];return s[r]={property:n,key:t[o]},s[r]}function l({systemName:e,componentName:t,component:s,prop:r,type:o}){h[e]?.componentObserver?.add({component:s,prop:r,type:o,componentName:t})}function y({obj:e,key:s,prop:r,component:o,componentName:n}){if(void 0!==e)if(s in e){if(Object.defineProperty(e,`_${s}`,{enumerable:!1,writable:!0,value:e[s]}),r.deep&&t.isObject(e[s]))for(const t of Object.keys(e[s]))y({obj:e[s],key:t,prop:r,component:o,componentName:n});Object.defineProperty(e,s,{enumerable:!0,set(a){e[`_${s}`]!==a&&(e[`_${s}`]=a,function({prop:e,component:s,componentName:r}){for(const o in m){const n=(m[o]||{})[r];n&&(n.findIndex(s=>t.isEqual(s,e))>-1&&l({systemName:o,componentName:r,component:s,prop:e,type:exports.OBSERVER_TYPE.CHANGE}))}}({prop:r,component:o,componentName:n}))},get:()=>e[`_${s}`]})}else console.error(`prop ${s} not in component: ${n}, Can not observer`)}function f(e,t=e.name){for(const s in m){(m[s]||{})[t]&&h[s]?.componentObserver?.add({component:e,type:exports.OBSERVER_TYPE.REMOVE,componentName:t})}!function(e){e.gameObject&&delete p[e.gameObject.id]}(e)}class g extends c{constructor(){super(...arguments),this.name="Transform",this._parent=null,this.inScene=!1,this.children=[],this.position={x:0,y:0},this.size={width:0,height:0},this.origin={x:0,y:0},this.anchor={x:0,y:0},this.scale={x:1,y:1},this.skew={x:0,y:0},this.rotation=0}static{this.componentName="Transform"}init(e={}){const t=["position","size","origin","anchor","scale","skew"];for(const s of t)Object.assign(this[s],e[s]);this.rotation=e.rotation||this.rotation}set parent(e){e?e.addChild(this):this.parent&&this.parent.removeChild(this)}get parent(){return this._parent}addChild(e){if(e.parent===this){const t=this.children.findIndex(t=>t===e);this.children.splice(t,1)}else e.parent&&e.parent.removeChild(e);e._parent=this,this.children.push(e)}removeChild(e){const t=this.children.findIndex(t=>t===e);t>-1&&(this.children.splice(t,1),e._parent=null)}clearChildren(){this.children.length=0}}s.__decorate([r.type("vector2"),r.step(1)],g.prototype,"position",void 0),s.__decorate([r.type("size"),r.step(1)],g.prototype,"size",void 0),s.__decorate([r.type("vector2"),r.step(.1)],g.prototype,"origin",void 0),s.__decorate([r.type("vector2"),r.step(.1)],g.prototype,"anchor",void 0),s.__decorate([r.type("vector2"),r.step(.1)],g.prototype,"scale",void 0),s.__decorate([r.type("vector2"),r.step(.1)],g.prototype,"skew",void 0),s.__decorate([r.type("number"),r.step(.1)],g.prototype,"rotation",void 0);let E=0;class _{constructor(e,t){this._componentCache={},this.components=[],this.destroyed=!1,this._name=e,this.id=++E,this.addComponent(g,t)}get transform(){return this.getComponent(g)}get parent(){return this.transform&&this.transform.parent&&this.transform.parent.gameObject}get name(){return this._name}set scene(e){if(this._scene===e)return;const t=this._scene;if(this._scene=e,this.transform&&this.transform.children)for(const t of this.transform.children)t.gameObject.scene=e;e?e.addGameObject(this):t&&t.removeGameObject(this)}get scene(){return this._scene}addChild(e){if(e&&e.transform&&e!==this){if(!(e instanceof _))throw new Error("addChild only receive GameObject");if(!this.transform)throw new Error(`gameObject '${this.name}' has been destroy`);e.transform.parent=this.transform,e.scene=this.scene}}removeChild(e){return e instanceof _&&e.parent&&e.parent===this?(e.transform.parent=null,e.scene=null,e):e}addComponent(e,t){if(this.destroyed)return;const s=function(e){return e instanceof c?e.name:e instanceof Function?e.componentName:void 0}(e);if(this._componentCache[s])return;let r;if(e instanceof Function)r=new e(t);else{if(!(e instanceof c))throw new Error("addComponent recieve Component and Component Constructor");r=e}if(r.gameObject)throw new Error(`component has been added on gameObject ${r.gameObject.name}`);return r.gameObject=this,r.init&&r.init(r.__componentDefaultParams),function(e,t=e.name){for(const s in m)(m[s]||{})[t]&&h[s]?.componentObserver?.add({component:e,type:exports.OBSERVER_TYPE.ADD,componentName:t})}(r,r.name),function(e,t=e.name){if(t&&d[t]){if(!(e&&(s=e,s&&s.constructor&&"componentName"in s.constructor)))throw new Error("component param must be an instance of Component");var s;if(!e.gameObject||!e.gameObject.id)throw new Error("component should be add to a gameObject");for(const s of d[t]){const{property:r,key:o}=u(e,s.prop);y({obj:r,key:o,prop:s,component:e,componentName:t})}}}(r,r.name),this.components.push(r),this._componentCache[s]=r,r.awake&&r.awake(),r}removeComponent(e){let t;if("string"==typeof e?t=e:e instanceof c?t=e.name:e.componentName&&(t=e.componentName),"Transform"===t)throw new Error("Transform can't be removed");return this._removeComponent(t)}_removeComponent(e){const t=this.components.findIndex(({name:t})=>t===e);if(-1===t)return;const s=this.components.splice(t,1)[0];return delete this._componentCache[e],delete s.__componentDefaultParams,s.onDestroy&&s.onDestroy(),f(s,e),s.gameObject=void 0,s}getComponent(e){let t;return"string"==typeof e?t=e:e instanceof c?t=e.name:e.componentName&&(t=e.componentName),void 0!==this._componentCache[t]?this._componentCache[t]:void 0}remove(){if(this.parent)return this.parent.removeChild(this)}destroy(){if(this.transform){Array.from(this.transform.children).forEach(({gameObject:e})=>{e.destroy()}),this.remove(),this.transform.clearChildren();for(const e in this._componentCache)this._removeComponent(e);this.components.length=0,this.destroyed=!0}else console.error("Cannot destroy gameObject that have already been destroyed.")}}class b{constructor(){this.events=[]}add({component:e,prop:s,type:r,componentName:o}){if(r===exports.OBSERVER_TYPE.REMOVE){if(this.events.find(t=>t.component===e&&t.type===exports.OBSERVER_TYPE.ADD))return void(this.events=this.events.filter(t=>t.component!==e));this.events=this.events.filter(t=>t.component!==e)}const n=this.events.findIndex(o=>o.component===e&&t.isEqual(o.prop,s)&&o.type===r);n>-1&&this.events.splice(n,1),this.events.push({gameObject:e.gameObject,component:e,prop:s,type:r,componentName:o})}getChanged(){return this.events}get changed(){return this.events}clear(){const e=this.events;return this.events=[],e}}class T{constructor(e){this.started=!1,this.componentObserver=new b,this.__systemDefaultParams=e;const t=this.constructor;this.name=t.systemName}destroy(){this.componentObserver=null,this.__systemDefaultParams=null,this.onDestroy?.()}}const R=function(){let e=null;return e=Date.now?Date.now:()=>(new Date).getTime(),e}(),O={originTime:0,playbackRate:1};class S{constructor(e,t){e instanceof S&&(t=e,e={}),e=Object.assign({},O,e),t&&(this._parent=t),this._createTime=R(),this._timeMark=[{globalTime:this.globalTime,localTime:-e.originTime,entropy:-e.originTime,playbackRate:e.playbackRate,globalEntropy:0}],this._parent&&(this._timeMark[0].globalEntropy=this._parent.entropy),this._playbackRate=e.playbackRate}get globalTime(){return this.parent?this.parent.currentTime:R()-this._createTime}get parent(){return this._parent}get lastTimeMark(){return this._timeMark[this._timeMark.length-1]}markTime({time:e=this.currentTime,entropy:t=this.entropy,playbackRate:s=this.playbackRate}={}){const r={globalTime:this.globalTime,localTime:e,entropy:t,playbackRate:s,globalEntropy:this.globalEntropy};this._timeMark.push(r)}get currentTime(){const{localTime:e,globalTime:t}=this.lastTimeMark;return e+(this.globalTime-t)*this.playbackRate}set currentTime(e){this.markTime({time:e})}get globalEntropy(){return this._parent?this._parent.entropy:this.globalTime}get entropy(){const{entropy:e,globalEntropy:t}=this.lastTimeMark;return e+Math.abs((this.globalEntropy-t)*this.playbackRate)}set entropy(e){if(this.entropy>e){const t=this.seekTimeMark(e);this._timeMark.length=t+1}this.markTime({entropy:e})}fork(e){return new S(e,this)}seekGlobalTime(e){const t=this.seekTimeMark(e),s=this._timeMark[t],{entropy:r,playbackRate:o,globalTime:n}=s;return n+(e-r)/Math.abs(o)}seekLocalTime(e){const t=this.seekTimeMark(e),s=this._timeMark[t],{localTime:r,entropy:o,playbackRate:n}=s;return n>0?r+(e-o):r-(e-o)}seekTimeMark(e){const t=this._timeMark;let s=0,r=t.length-1;if(e<=t[s].entropy)return s;if(e>=t[r].entropy)return r;let o=Math.floor((s+r)/2);for(;o>s&&o<r;){if(e===t[o].entropy)return o;e<t[o].entropy?r=o:e>t[o].entropy&&(s=o),o=Math.floor((s+r)/2)}return s}get playbackRate(){return this._playbackRate}set playbackRate(e){e!==this.playbackRate&&(this.markTime({playbackRate:e}),this._playbackRate=e)}get paused(){if(0===this.playbackRate)return!0;let e=this.parent;for(;e;){if(0===e.playbackRate)return!0;e=e.parent}return!1}}const k={autoStart:!0,frameRate:60};class v{constructor(e){e=Object.assign({},k,e),this._frameCount=0,this._frameDuration=1e3/e.frameRate,this.autoStart=e.autoStart,this.frameRate=e.frameRate,this.timeline=new S({originTime:0,playbackRate:1}),this._lastFrameTime=this.timeline.currentTime,this._tickers=new Set,this._requestId=null,this._ticker=()=>{this._started&&(this._requestId=requestAnimationFrame(this._ticker),this.update())},this.autoStart&&this.start()}update(){const e=this.timeline.currentTime,t=e-this._lastFrameTime;if(t>=this._frameDuration){const s=e-t%this._frameDuration,r=s-this._lastFrameTime;this._lastFrameTime=s;const o={deltaTime:r,time:s,currentTime:s,frameCount:++this._frameCount,fps:Math.round(1e3/r)};for(const e of this._tickers)"function"==typeof e&&e(o)}}add(e){this._tickers.add(e)}remove(e){this._tickers.delete(e)}start(){this._started||(this._started=!0,this.timeline.playbackRate=1,this._requestId=requestAnimationFrame(this._ticker))}pause(){this._started=!1,this.timeline.playbackRate=0}setPlaybackRate(e){this.timeline.playbackRate=e}}class x extends _{constructor(e,t){super(e,t),this.gameObjects=[],this.scene=this}addGameObject(e){this.gameObjects.push(e),e.transform&&(e.transform.inScene=!0)}removeGameObject(e){const t=this.gameObjects.indexOf(e);-1!==t&&(e.transform&&(e.transform.inScene=!1),this.gameObjects.splice(t,1))}destroy(){this.scene=null,super.destroy(),this.gameObjects=null,this.canvas=null}}const C="combos-game:plugin-init-success";function M(e,t="*"){if("undefined"==typeof window)return;if(!window.parent||window.parent===window)return;const s={type:C,systemName:e};try{window.parent.postMessage(s,t)}catch{}}function L(e){if("systemName"in e){const t=e.systemName;if("string"==typeof t)return t}return"UnknownSystem"}var w;exports.LOAD_SCENE_MODE=void 0,(w=exports.LOAD_SCENE_MODE||(exports.LOAD_SCENE_MODE={})).SINGLE="SINGLE",w.MULTI_CANVAS="MULTI_CANVAS";const I=e=>{if((e instanceof T||e instanceof c)&&!e.started){e.started=!0;try{e.start&&e.start()}catch(t){e instanceof c?console.error(`${function(e){if("componentName"in e){const t=e.componentName;if("string"==typeof t)return t}return"UnknownComponent"}(e.constructor)} start error`,t):console.error(`${L(e.constructor)} start error`,t)}}};class N extends i.default{constructor({systems:e,frameRate:t=60,autoStart:s=!0,needScene:r=!0,onSystemsBootstrapComplete:o,pluginInitNotifyTargetOrigin:n="*"}={}){if(super(),this.playing=!1,this.started=!1,this.multiScenes=[],this.systems=[],this.pluginInitNotifyTargetOrigin="*",this.pluginInitNotifyTargetOrigin=n,this.ticker=new v({autoStart:!1,frameRate:t}),this.initTicker(),e&&e.length){const t=[...e];this.bootstrapSystemsAndMaybeStart(t,r,s,o)}else o?.(this)}async bootstrapSystemsAndMaybeStart(e,t,s,r){let o;try{for(const t of e)await this.addSystem(t);t&&this.loadScene(new x("scene")),s&&this.start()}catch(e){o=e,console.error("Game bootstrap failed",e)}finally{r?.(this,o)}}get scene(){return this._scene}set scene(e){this._scene=e}get gameObjects(){return(e=>{const t=e?.scene?.gameObjects||[],s=e?.multiScenes.map(({gameObjects:e})=>e);let r=[];for(const e of s)r=[...r,...e];return[...t,...r]})(this)}async addSystem(e,s){let r;if(e instanceof Function)r=new e(s);else{if(!(e instanceof T))return void console.warn("can only add System");r=e}if(!this.systems.find(e=>e.constructor===r.constructor)){r.game=this,r.init&&await Promise.resolve(r.init(r.__systemDefaultParams)),M(L(r.constructor),this.pluginInitNotifyTargetOrigin),function(e,t){m[t.systemName]=t.observerInfo,h[t.systemName]=e}(r,r.constructor),function(e){const s=[];e instanceof Array?s.push(...e):s.push(e);for(const e of s)for(const s in e.observerInfo){d[s]=d[s]||[];const r=d[s];for(const o of e.observerInfo[s])-1===r.findIndex(e=>t.isEqual(e,o))&&d[s].push(o)}}(r.constructor);try{r.awake&&r.awake()}catch(e){console.error(`${L(r.constructor)} awake error`,e)}return this.systems.push(r),r}console.warn(`${L(r.constructor)} System has been added`)}removeSystem(e){if(!e)return;let t=-1;"string"==typeof e?t=this.systems.findIndex(t=>t.name===e):e instanceof Function?t=this.systems.findIndex(t=>t.constructor===e):e instanceof T&&(t=this.systems.findIndex(t=>t===e)),t>-1&&(this.systems[t].destroy&&this.systems[t].destroy(),this.systems.splice(t,1))}getSystem(e){return this.systems.find(t=>"string"==typeof e?t.name===e:t instanceof e)}pause(){this.playing&&(this.playing=!1,this.ticker.pause(),this.triggerPause())}start(){this.playing||(this.playing=!0,this.started=!0,this.ticker.start())}resume(){this.playing||(this.playing=!0,this.ticker.start(),this.triggerResume())}initTicker(){this.ticker.add(e=>{this.scene&&((e,t=[])=>{for(const s of t)for(const t of s.components)try{I(t),t.update&&t.update(e)}catch(e){console.error(`gameObject: ${s.name} ${t.name} update error`,e)}for(const s of t)for(const t of s.components)try{t.lateUpdate&&t.lateUpdate(e)}catch(e){console.error(`gameObject: ${s.name} ${t.name} lateUpdate error`,e)}})(e,this.gameObjects);for(const t of this.systems)try{I(t),t.update&&t.update(e)}catch(e){console.error(`${L(t.constructor)} update error`,e)}for(const t of this.systems)try{t.lateUpdate&&t.lateUpdate(e)}catch(e){console.error(`${L(t.constructor)} lateUpdate error`,e)}})}triggerResume(){(e=>{for(const t of e)for(const e of t.components)try{e.onResume&&e.onResume()}catch(s){console.error(`gameObject: ${t.name}, ${e.name}, onResume error`,s)}})(this.gameObjects);for(const e of this.systems)try{e.onResume&&e.onResume()}catch(t){console.error(`${L(e.constructor)}, onResume error`,t)}}triggerPause(){(e=>{for(const t of e)for(const e of t.components)try{e.onPause&&e.onPause()}catch(s){console.error(`gameObject: ${t.name}, ${e.name}, onResume error`,s)}})(this.gameObjects);for(const e of this.systems)try{e.onPause&&e.onPause()}catch(t){console.error(`${L(e.constructor)}, onPause error`,t)}}destroySystems(){for(const e of[...this.systems])this.removeSystem(e);this.systems.length=0}destroy(){this.removeAllListeners(),this.pause(),this.scene.destroy(),this.destroySystems(),this.ticker=null,this.scene=null,this.canvas=null,this.multiScenes=null}loadScene({scene:e,mode:t=exports.LOAD_SCENE_MODE.SINGLE,params:s={}}){if(e){switch(t){case exports.LOAD_SCENE_MODE.SINGLE:this.scene=e;break;case exports.LOAD_SCENE_MODE.MULTI_CANVAS:this.multiScenes.push(e)}this.emit("sceneChanged",{scene:e,mode:t,params:s})}}}function P(e,t){e.constructor.IDEProps||(e.constructor.IDEProps=[]),e.constructor.IDEProps.push(t)}function A(e={}){return function(t){if(!t.observerInfo){for(const t in e)for(const s in e[t]){let r;"string"==typeof e[t][s]&&(e[t][s]=[e[t][s]]),Array.isArray(e[t][s])&&(r={prop:e[t][s],deep:!1},e[t][s]=r),r=e[t][s],"string"==typeof r.prop&&(r.prop=[r.prop])}t.observerInfo=e}}}var D;exports.LOAD_EVENT=void 0,(D=exports.LOAD_EVENT||(exports.LOAD_EVENT={})).START="start",D.PROGRESS="progress",D.LOADED="loaded",D.COMPLETE="complete",D.ERROR="error";class j extends i.default{constructor({resource:e,resourceTotal:t}){super(),this.progress=0,this.resourceTotal=0,this.resourceLoadedCount=0,this.resource=e,this.resourceTotal=t,0===t&&this.resource.emit(exports.LOAD_EVENT.COMPLETE,this)}onStart(){this.resource.emit(exports.LOAD_EVENT.START,this)}onProgress(e){this.resourceLoadedCount++,this.progress=Math.floor(this.resourceLoadedCount/this.resourceTotal*100)/100,e.success?this.resource.emit(exports.LOAD_EVENT.LOADED,this,e):this.resource.emit(exports.LOAD_EVENT.ERROR,this,e),this.resource.emit(exports.LOAD_EVENT.PROGRESS,this,e),this.resourceLoadedCount===this.resourceTotal&&this.resource.emit(exports.LOAD_EVENT.COMPLETE,this)}}const V={AbstractLoadStrategy:o.AbstractLoadStrategy,AudioLoadStrategy:o.AudioLoadStrategy,ImageLoadStrategy:o.ImageLoadStrategy,XhrResponseType:o.XhrResponseType,MediaElementLoadStrategy:o.MediaElementLoadStrategy,VideoLoadStrategy:o.VideoLoadStrategy,XhrLoadStrategy:o.XhrLoadStrategy,Loader:o.Loader,Resource:o.Resource,ResourceType:o.ResourceType,ResourceState:o.ResourceState};var $;exports.RESOURCE_TYPE=void 0,($=exports.RESOURCE_TYPE||(exports.RESOURCE_TYPE={})).IMAGE="IMAGE",$.SPRITE="SPRITE",$.SPRITE_ANIMATION="SPRITE_ANIMATION",$.AUDIO="AUDIO",$.VIDEO="VIDEO",o.XhrLoadStrategy.setExtensionXhrType("json",o.XhrResponseType.Json),o.XhrLoadStrategy.setExtensionXhrType("tex",o.XhrResponseType.Json),o.XhrLoadStrategy.setExtensionXhrType("ske",o.XhrResponseType.Json),o.XhrLoadStrategy.setExtensionXhrType("mp3",o.XhrResponseType.Buffer),o.XhrLoadStrategy.setExtensionXhrType("wav",o.XhrResponseType.Buffer),o.XhrLoadStrategy.setExtensionXhrType("aac",o.XhrResponseType.Buffer),o.XhrLoadStrategy.setExtensionXhrType("ogg",o.XhrResponseType.Buffer);const X={png:o.ImageLoadStrategy,jpg:o.ImageLoadStrategy,jpeg:o.ImageLoadStrategy,webp:o.ImageLoadStrategy,json:o.XhrLoadStrategy,tex:o.XhrLoadStrategy,ske:o.XhrLoadStrategy,audio:o.XhrLoadStrategy,video:o.VideoLoadStrategy};class G extends i.default{constructor(e){super(),this.timeout=6e3,this.preProcessResourceHandlers=[],this.resourcesMap={},this.makeInstanceFunctions={},this.destroyInstanceFunctions={},this.promiseMap={},this.loaders=[],e&&"number"==typeof e.timeout&&(this.timeout=e.timeout)}loadConfig(e){this.addResource(e),this.preload()}loadSingle(e){return this.addResource([e]),this.getResource(e.name)}addResource(e){if(!e||e.length<1)console.warn("no resources");else for(const t of e)this.resourcesMap[t.name]?console.warn(t.name+" was already added"):(this.resourcesMap[t.name]=t,this.resourcesMap[t.name].data={})}addPreProcessResourceHandler(e){this.preProcessResourceHandlers.push(e)}removePreProcessResourceHandler(e){this.preProcessResourceHandlers.splice(this.preProcessResourceHandlers.indexOf(e),1)}preload(){const e=[];for(const t in this.resourcesMap){const s=this.resourcesMap[t];!s.preload||s.complete||this.promiseMap[t]||e.push(s.name)}this.progress=new j({resource:this,resourceTotal:e.length}),this.loadResource({names:e,preload:!0})}async getResource(e){return this.loadResource({names:[e]}),this.promiseMap[e]||Promise.resolve({})}async instance(e){const t=this.resourcesMap[e];return this.makeInstanceFunctions[t.type]&&await this.makeInstanceFunctions[t.type](t)}async destroy(e){await this._destroy(e)}async _destroy(e,t=!1){const s=this.resourcesMap[e];if(s){if(!t)try{this.destroyInstanceFunctions[s.type]&&await this.destroyInstanceFunctions[s.type](s)}catch(e){console.warn(`destroy resource ${s.name} error with '${e.message}'`)}delete this.promiseMap[e],s.data={},s.complete=!1,s.instance=void 0}}registerResourceType(e,t=e){if(exports.RESOURCE_TYPE[e])throw new Error(`The type ${e} already exists in RESOURCE_TYPE`);exports.RESOURCE_TYPE[e]=t}registerInstance(e,t){this.makeInstanceFunctions[e]=t}registerDestroy(e,t){this.destroyInstanceFunctions[e]=t}loadResource({names:e=[],preload:t=!1}){const s=e.filter(e=>!this.promiseMap[e]&&this.resourcesMap[e]);if(!s.length)return;const r={},o=this.getLoader(t);s.forEach(e=>{this.promiseMap[e]=new Promise(t=>r[e]=t);const s=this.resourcesMap[e];for(const e of this.preProcessResourceHandlers)e(s);for(const n in s.src){const a=s.src[n].type;"data"===a?(s.data[n]=s.src[n].data,this.doComplete(e,r[e],t)):o.add({url:s.src[n].url,name:`${s.name}_${n}`,strategy:X[a],metadata:{key:n,name:s.name,resolves:r}})}}),o.load()}async doComplete(e,t,s=!1){const r=this.resourcesMap[e],o={name:e,resource:this.resourcesMap[e],success:!0};if(this.checkAllLoaded(e))try{r.instance=await this.instance(e),r.complete=!0,s&&this.progress.onProgress(o),t(r)}catch(e){console.error(e),r.complete=!1,s&&(o.errMsg=e.message,o.success=!1,this.progress.onProgress(o)),t({})}}checkAllLoaded(e){const t=this.resourcesMap[e];return Array.from(Object.keys(t.src)).every(e=>t.data[e])}getLoader(e=!1){let t=this.loaders.find(({loading:e})=>!e);return t||(t=new o.Loader,this.loaders.push(t)),e&&t.onStart.once(()=>{this.progress.onStart()}),t.onLoad.add((t,s)=>{this.onLoad({preload:e,resource:s})}),t.onError.add((t,s,r)=>{this.onError({errMsg:t,resource:r,preload:e})}),t.onComplete.once(()=>{t.onLoad.detachAll(),t.onError.detachAll(),t.reset()}),t}async onLoad({preload:e=!1,resource:t}){const{metadata:{key:s,name:r,resolves:o},data:n}=t;this.resourcesMap[r].data[s]=n,this.doComplete(r,o[r],e)}async onError({errMsg:e,preload:t=!1,resource:s}){const{metadata:{name:r,resolves:o}}=s;if(this._destroy(r,!0),o[r]({}),t){const t={name:r,resource:this.resourcesMap[r],success:!1,errMsg:e};this.progress.onProgress(t)}}}const U=new G,F={IDEProp:P,componentObserver:A},Y="__VERSION__";console.log(`@combos-fun/engine version: ${Y}`),exports.COMBOS_GAME_PLUGIN_INIT_SUCCESS=C,exports.Component=c,exports.Game=N,exports.GameObject=_,exports.IDEProp=P,exports.RESOURCE_TYPE_STRATEGY=X,exports.Scene=x,exports.System=T,exports.Transform=g,exports.componentObserver=A,exports.decorators=F,exports.postParentPluginInitSuccess=M,exports.resource=U,exports.resourceLoader=V,exports.version=Y;
package/dist/engine.d.ts CHANGED
@@ -397,6 +397,11 @@ interface GameParams {
397
397
  systems?: System[];
398
398
  /** whether or not need to create scene */
399
399
  needScene?: boolean;
400
+ /**
401
+ * `postMessage` targetOrigin when notifying parent after each system `init` (default `'*'`).
402
+ * Only used when `window.parent` exists and differs from `window`.
403
+ */
404
+ pluginInitNotifyTargetOrigin?: string;
400
405
  /**
401
406
  * Called after async system bootstrap finishes (constructor path with non-empty `systems`),
402
407
  * i.e. after all `addSystem`/`init` work and optional `loadScene` / `start`.
@@ -448,7 +453,11 @@ declare class Game extends EventEmitter {
448
453
  ticker: Ticker;
449
454
  /** Systems alled to this game */
450
455
  systems: System[];
451
- constructor({ systems, frameRate, autoStart, needScene, onSystemsBootstrapComplete, }?: GameParams);
456
+ /**
457
+ * Passed to `postMessage` when reporting `COMBOS_GAME_PLUGIN_INIT_SUCCESS` to `window.parent`.
458
+ */
459
+ pluginInitNotifyTargetOrigin: string;
460
+ constructor({ systems, frameRate, autoStart, needScene, onSystemsBootstrapComplete, pluginInitNotifyTargetOrigin, }?: GameParams);
452
461
  /** When `systems` is passed in the constructor, run async `init` for each before `loadScene` / `start`. */
453
462
  private bootstrapSystemsAndMaybeStart;
454
463
  /**
@@ -813,6 +822,21 @@ declare class Resource extends EventEmitter {
813
822
  /** Resource manager single instance */
814
823
  declare const resource: Resource;
815
824
 
825
+ /**
826
+ * Sent to `window.parent` after each `System.init` completes during `Game.addSystem`
827
+ * (when running inside an iframe and parent differs from self).
828
+ */
829
+ declare const COMBOS_GAME_PLUGIN_INIT_SUCCESS: "combos-game:plugin-init-success";
830
+ interface CombosGamePluginInitSuccessMessage {
831
+ type: typeof COMBOS_GAME_PLUGIN_INIT_SUCCESS;
832
+ /** Resolved from `System.systemName` on the constructor, or `"UnknownSystem"`. */
833
+ systemName: string;
834
+ }
835
+ /**
836
+ * Notifies the embedding page that a system (plugin) finished async/sync `init`.
837
+ */
838
+ declare function postParentPluginInitSuccess(systemName: string, targetOrigin?: string): void;
839
+
816
840
  /** Decorators util */
817
841
  declare const decorators: {
818
842
  IDEProp: typeof IDEProp;
@@ -821,5 +845,5 @@ declare const decorators: {
821
845
 
822
846
  declare const version = "__VERSION__";
823
847
 
824
- export { Component, Game, GameObject, IDEProp, LOAD_EVENT, LOAD_SCENE_MODE, ObserverType as OBSERVER_TYPE, RESOURCE_TYPE, RESOURCE_TYPE_STRATEGY, Scene, System, Transform, componentObserver, decorators, resource, resourceLoader, version };
825
- export type { ObserverEvent as ComponentChanged, ComponentParams, GameParams, ObserverInfo, PluginStruct, PureObserverInfo, ResourceBase, SystemConstructor, TransformParams, UpdateParams };
848
+ export { COMBOS_GAME_PLUGIN_INIT_SUCCESS, Component, Game, GameObject, IDEProp, LOAD_EVENT, LOAD_SCENE_MODE, ObserverType as OBSERVER_TYPE, RESOURCE_TYPE, RESOURCE_TYPE_STRATEGY, Scene, System, Transform, componentObserver, decorators, postParentPluginInitSuccess, resource, resourceLoader, version };
849
+ export type { CombosGamePluginInitSuccessMessage, ObserverEvent as ComponentChanged, ComponentParams, GameParams, ObserverInfo, PluginStruct, PureObserverInfo, ResourceBase, SystemConstructor, TransformParams, UpdateParams };
@@ -948,6 +948,31 @@ class Scene extends GameObject {
948
948
  }
949
949
  }
950
950
 
951
+ /**
952
+ * Sent to `window.parent` after each `System.init` completes during `Game.addSystem`
953
+ * (when running inside an iframe and parent differs from self).
954
+ */
955
+ const COMBOS_GAME_PLUGIN_INIT_SUCCESS = 'combos-game:plugin-init-success';
956
+ /**
957
+ * Notifies the embedding page that a system (plugin) finished async/sync `init`.
958
+ */
959
+ function postParentPluginInitSuccess(systemName, targetOrigin = '*') {
960
+ if (typeof window === 'undefined')
961
+ return;
962
+ if (!window.parent || window.parent === window)
963
+ return;
964
+ const payload = {
965
+ type: COMBOS_GAME_PLUGIN_INIT_SUCCESS,
966
+ systemName,
967
+ };
968
+ try {
969
+ window.parent.postMessage(payload, targetOrigin);
970
+ }
971
+ catch {
972
+ /* ignore cross-origin or detached frame */
973
+ }
974
+ }
975
+
951
976
  function systemClassName(ctor) {
952
977
  if ('systemName' in ctor) {
953
978
  const sn = ctor.systemName;
@@ -1044,7 +1069,7 @@ const gameObjectPause = gameObjects => {
1044
1069
  }
1045
1070
  };
1046
1071
  class Game extends EventEmitter {
1047
- constructor({ systems, frameRate = 60, autoStart = true, needScene = true, onSystemsBootstrapComplete, } = {}) {
1072
+ constructor({ systems, frameRate = 60, autoStart = true, needScene = true, onSystemsBootstrapComplete, pluginInitNotifyTargetOrigin = '*', } = {}) {
1048
1073
  super();
1049
1074
  /**
1050
1075
  * State of game
@@ -1055,6 +1080,11 @@ class Game extends EventEmitter {
1055
1080
  this.multiScenes = [];
1056
1081
  /** Systems alled to this game */
1057
1082
  this.systems = [];
1083
+ /**
1084
+ * Passed to `postMessage` when reporting `COMBOS_GAME_PLUGIN_INIT_SUCCESS` to `window.parent`.
1085
+ */
1086
+ this.pluginInitNotifyTargetOrigin = '*';
1087
+ this.pluginInitNotifyTargetOrigin = pluginInitNotifyTargetOrigin;
1058
1088
  this.ticker = new Ticker({ autoStart: false, frameRate });
1059
1089
  this.initTicker();
1060
1090
  if (systems && systems.length) {
@@ -1128,6 +1158,7 @@ class Game extends EventEmitter {
1128
1158
  if (system.init) {
1129
1159
  await Promise.resolve(system.init(system.__systemDefaultParams));
1130
1160
  }
1161
+ postParentPluginInitSuccess(systemClassName(system.constructor), this.pluginInitNotifyTargetOrigin);
1131
1162
  setSystemObserver(system, system.constructor);
1132
1163
  initObserver(system.constructor);
1133
1164
  try {
@@ -1660,5 +1691,5 @@ const decorators = {
1660
1691
  const version = '__VERSION__';
1661
1692
  console.log(`@combos-fun/engine version: ${version}`);
1662
1693
 
1663
- export { Component, Game, GameObject, IDEProp, LOAD_EVENT, LOAD_SCENE_MODE, ObserverType as OBSERVER_TYPE, RESOURCE_TYPE, RESOURCE_TYPE_STRATEGY, Scene, System, Transform, componentObserver, decorators, resource, resourceLoader, version };
1694
+ export { COMBOS_GAME_PLUGIN_INIT_SUCCESS, Component, Game, GameObject, IDEProp, LOAD_EVENT, LOAD_SCENE_MODE, ObserverType as OBSERVER_TYPE, RESOURCE_TYPE, RESOURCE_TYPE_STRATEGY, Scene, System, Transform, componentObserver, decorators, postParentPluginInitSuccess, resource, resourceLoader, version };
1664
1695
  //# sourceMappingURL=engine.esm.js.map