@animech-public/playcanvas
Version:
PlayCanvas WebGL game engine
2 lines (1 loc) • 9.38 kB
JavaScript
import{SortedLoopArray as t}from"../../../core/sorted-loop-array.js";import{ScriptAttributes as e,assignAttributesToScript as i}from"../../script/script-attributes.js";import{SCRIPT_POST_INITIALIZE as s,SCRIPT_INITIALIZE as n,SCRIPT_UPDATE as r,SCRIPT_POST_UPDATE as o,SCRIPT_SWAP as p}from"../../script/constants.js";import{Component as a}from"../component.js";import{Entity as h}from"../../entity.js";import{ScriptType as c}from"../../script/script-type.js";import{getScriptName as _}from"../../script/script.js";class d extends a{constructor(e,i){super(e,i),this._attributeDataMap=new Map,this._scripts=[],this._updateList=new t({sortBy:"__executionOrder"}),this._postUpdateList=new t({sortBy:"__executionOrder"}),this._scriptsIndex={},this._destroyedScripts=[],this._destroyed=!1,this._scriptsData=null,this._oldState=!0,this._enabled=!0,this._beingEnabled=!1,this._isLoopingThroughScripts=!1,this._executionOrder=-1,this.on("set_enabled",this._onSetEnabled,this)}set scripts(t){this._scriptsData=t;for(const i in t){if(!t.hasOwnProperty(i))continue;const s=this._scriptsIndex[i];if(s){if("boolean"==typeof t[i].enabled&&(s.once("preInitialize",(()=>{this.initializeAttributes(s)})),s.enabled=!!t[i].enabled),"object"==typeof t[i].attributes)for(const n in t[i].attributes)if(!e.reservedNames.has(n)){if(!s.__attributes.hasOwnProperty(n)){const t=this.system.app.scripts.get(i);t&&t.attributes.add(n,{})}s[n]=t[i].attributes[n]}}else console.log(this.order)}}get scripts(){return this._scripts}set enabled(t){const e=this._enabled;this._enabled=t,this.fire("set","enabled",e,t)}get enabled(){return this._enabled}onEnable(){this._beingEnabled=!0,this._checkState(),this.entity._beingEnabled||this.onPostStateChange(),this._beingEnabled=!1}onDisable(){this._checkState()}onPostStateChange(){const t=this._beginLooping();for(let t=0,e=this.scripts.length;t<e;t++){const e=this.scripts[t];e._initialized&&!e._postInitialized&&e.enabled&&(e._postInitialized=!0,e.postInitialize&&this._scriptMethod(e,s))}this._endLooping(t)}_beginLooping(){const t=this._isLoopingThroughScripts;return this._isLoopingThroughScripts=!0,t}_endLooping(t){this._isLoopingThroughScripts=t,this._isLoopingThroughScripts||this._removeDestroyedScripts()}_onSetEnabled(t,e,i){this._beingEnabled=!0,this._checkState(),this._beingEnabled=!1}_checkState(){const t=this.enabled&&this.entity.enabled;if(t===this._oldState)return;this._oldState=t,this.fire(t?"enable":"disable"),this.fire("state",t),t?this.system._addComponentToEnabled(this):this.system._removeComponentFromEnabled(this);const e=this._beginLooping();for(let t=0,e=this.scripts.length;t<e;t++){const e=this.scripts[t];e.once("preInitialize",(()=>{this.initializeAttributes(e)})),e.enabled=e._enabled}this._endLooping(e)}_onBeforeRemove(){this.fire("remove");const t=this._beginLooping();for(let t=0;t<this.scripts.length;t++){const e=this.scripts[t];e&&this.destroy(e.__scriptType.__name)}this._endLooping(t)}_removeDestroyedScripts(){const t=this._destroyedScripts.length;if(t){for(let e=0;e<t;e++){const t=this._destroyedScripts[e];this._removeScriptInstance(t)}this._destroyedScripts.length=0,this._resetExecutionOrder(0,this._scripts.length)}}_onInitializeAttributes(){for(let t=0,e=this.scripts.length;t<e;t++){const e=this.scripts[t];this.initializeAttributes(e)}}initializeAttributes(t){if(t instanceof c)t.__initializeAttributes();else{var e;const s=t.__scriptType.__name,n=this._attributeDataMap.get(s);if(!n)return;const r=null==(e=this.system.app.scripts)?void 0:e.getSchema(s);i(this.system.app,r.attributes,n,t)}}_scriptMethod(t,e,i){t[e](i)}_onInitialize(){const t=this._scripts,e=this._beginLooping();for(let e=0,i=t.length;e<i;e++){const i=t[e];!i._initialized&&i.enabled&&(i._initialized=!0,i.initialize&&this._scriptMethod(i,n))}this._endLooping(e)}_onPostInitialize(){this.onPostStateChange()}_onUpdate(t){const e=this._updateList;if(!e.length)return;const i=this._beginLooping();for(e.loopIndex=0;e.loopIndex<e.length;e.loopIndex++){const i=e.items[e.loopIndex];i.enabled&&this._scriptMethod(i,r,t)}this._endLooping(i)}_onPostUpdate(t){const e=this._postUpdateList;if(!e.length)return;const i=this._beginLooping();for(e.loopIndex=0;e.loopIndex<e.length;e.loopIndex++){const i=e.items[e.loopIndex];i.enabled&&this._scriptMethod(i,o,t)}this._endLooping(i)}_insertScriptInstance(t,e,i){-1===e?(this._scripts.push(t),t.__executionOrder=i,t.update&&this._updateList.append(t),t.postUpdate&&this._postUpdateList.append(t)):(this._scripts.splice(e,0,t),t.__executionOrder=e,this._resetExecutionOrder(e+1,i+1),t.update&&this._updateList.insert(t),t.postUpdate&&this._postUpdateList.insert(t))}_removeScriptInstance(t){const e=this._scripts.indexOf(t);return-1===e||(this._scripts.splice(e,1),t.update&&this._updateList.remove(t),t.postUpdate&&this._postUpdateList.remove(t)),e}_resetExecutionOrder(t,e){for(let i=t;i<e;i++)this._scripts[i].__executionOrder=i}_resolveEntityScriptAttribute(t,e,i,s,n,r){if(t.array){const t=i.length;if(!t)return;const o=i.slice();for(let e=0;e<t;e++){const t=o[e]instanceof h?o[e].getGuid():o[e];r[t]&&(o[e]=s?r[t].getGuid():r[t])}n[e]=o}else{if(i instanceof h)i=i.getGuid();else if("string"!=typeof i)return;r[i]&&(n[e]=r[i])}}has(t){if("string"==typeof t)return!!this._scriptsIndex[t];if(!t)return!1;const e=t,i=e.__name,s=this._scriptsIndex[i];return(s&&s.instance)instanceof e}get(t){if("string"==typeof t){const e=this._scriptsIndex[t];return e?e.instance:null}if(!t)return null;const e=t,i=e.__name,s=this._scriptsIndex[i],n=s&&s.instance;return n instanceof e?n:null}create(t,e={}){const i=this;let r=t,o=t;if("string"==typeof r)r=this.system.app.scripts.get(r);else if(r){var p,a;o=null!=(a=(p=r).__name)?a:p.__name=(h=_(r))[0].toLowerCase()+h.substring(1)}var h;if(r){if(!this._scriptsIndex[o]||!this._scriptsIndex[o].instance){const t=new r({app:this.system.app,entity:this.entity,enabled:!e.hasOwnProperty("enabled")||e.enabled,attributes:e.attributes});t instanceof c||this._attributeDataMap.set(o,e.attributes);const p=this._scripts.length;let a=-1;return"number"==typeof e.ind&&-1!==e.ind&&p>e.ind&&(a=e.ind),this._insertScriptInstance(t,a,p),this._scriptsIndex[o]={instance:t,onSwap:function(){i.swap(o)}},this[o]=t,e.preloading||this.initializeAttributes(t),this.fire("create",o,t),this.fire(`create:${o}`,t),this.system.app.scripts.on(`swap:${o}`,this._scriptsIndex[o].onSwap),e.preloading||(t.enabled&&!t._initialized&&(t._initialized=!0,t.initialize&&this._scriptMethod(t,n)),t.enabled&&!t._postInitialized&&(t._postInitialized=!0,t.postInitialize&&this._scriptMethod(t,s))),t}}else this._scriptsIndex[o]={awaiting:!0,ind:this._scripts.length};return null}destroy(t){let e=t,i=t;"string"==typeof i?i=this.system.app.scripts.get(i):i&&(e=i.__name);const s=this._scriptsIndex[e];if(delete this._scriptsIndex[e],!s)return!1;this._attributeDataMap.delete(e);const n=s.instance;if(n&&!n._destroyed)if(n.enabled=!1,n._destroyed=!0,this._isLoopingThroughScripts)this._destroyedScripts.push(n);else{const t=this._removeScriptInstance(n);t>=0&&this._resetExecutionOrder(t,this._scripts.length)}return this.system.app.scripts.off(`swap:${e}`,s.onSwap),delete this[e],this.fire("destroy",e,n||null),this.fire(`destroy:${e}`,n||null),n&&n.fire("destroy"),!0}swap(t){let e=t,i=t;"string"==typeof i?i=this.system.app.scripts.get(i):i&&(e=i.__name);const s=this._scriptsIndex[e];if(!s||!s.instance)return!1;const n=s.instance,r=this._scripts.indexOf(n),o=new i({app:this.system.app,entity:this.entity,enabled:n.enabled,attributes:n.__attributes});return!!o.swap&&(this.initializeAttributes(o),this._scripts[r]=o,this._scriptsIndex[e].instance=o,this[e]=o,o.__executionOrder=r,n.update&&this._updateList.remove(n),n.postUpdate&&this._postUpdateList.remove(n),o.update&&this._updateList.insert(o),o.postUpdate&&this._postUpdateList.insert(o),this._scriptMethod(o,p,n),this.fire("swap",e,o),this.fire(`swap:${e}`,o),!0)}resolveDuplicatedEntityReferenceProperties(t,e){const i=this.entity.script;for(const s in t._scriptsIndex){const n=this.system.app.scripts.get(s);if(!n)continue;const r=t._scriptsIndex[s];if(!r||!r.instance)continue;const o=i[s].__attributesRaw,p=i[s].__attributes;if(!o&&!p)continue;const a=!!o,h=r.instance.__attributes;for(const t in h){if(!h[t])continue;const i=n.attributes.get(t);if(i)if("entity"===i.type)this._resolveEntityScriptAttribute(i,t,h[t],a,o||p,e);else if("json"===i.type&&Array.isArray(i.schema)){const s=h[t],n=o?o[t]:p[t];for(let t=0;t<i.schema.length;t++){const r=i.schema[t];if("entity"===r.type)if(i.array)for(let t=0;t<s.length;t++)this._resolveEntityScriptAttribute(r,r.name,s[t][r.name],a,n[t],e);else this._resolveEntityScriptAttribute(r,r.name,s[r.name],a,n,e)}}}}}move(t,e){const i=this._scripts.length;if(e>=i||e<0)return!1;let s=t,n=t;"string"!=typeof n?n=t.__name:s=null;const r=this._scriptsIndex[n];if(!r||!r.instance)return!1;const o=r.instance;if(s&&!(o instanceof s))return!1;const p=this._scripts.indexOf(o);return-1!==p&&p!==e&&(this._scripts.splice(e,0,this._scripts.splice(p,1)[0]),this._resetExecutionOrder(0,i),this._updateList.sort(),this._postUpdateList.sort(),this.fire("move",n,o,e,p),this.fire(`move:${n}`,o,e,p),!0)}}d.EVENT_CREATE="create",d.EVENT_DESTROY="destroy",d.EVENT_ENABLE="enable",d.EVENT_DISABLE="disable",d.EVENT_REMOVE="remove",d.EVENT_STATE="state",d.EVENT_MOVE="move",d.EVENT_ERROR="error";export{d as ScriptComponent};