@skewedaspect/sage 0.5.0 → 0.5.1
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.
- package/dist/classes/bindings/toggle.d.ts +4 -4
- package/dist/classes/bindings/trigger.d.ts +4 -4
- package/dist/classes/bindings/value.d.ts +4 -4
- package/dist/classes/entity.d.ts +2 -2
- package/dist/classes/eventBus.d.ts +1 -1
- package/dist/classes/gameEngine.d.ts +8 -8
- package/dist/classes/input/gamepad.d.ts +1 -1
- package/dist/classes/input/keyboard.d.ts +1 -1
- package/dist/classes/input/mouse.d.ts +1 -1
- package/dist/classes/input/readers/gamepad.d.ts +1 -1
- package/dist/classes/input/readers/keyboard.d.ts +1 -1
- package/dist/classes/input/readers/mouse.d.ts +1 -1
- package/dist/classes/loggers/consoleBackend.d.ts +1 -1
- package/dist/classes/loggers/nullBackend.d.ts +1 -1
- package/dist/engines/scene.d.ts +2 -2
- package/dist/interfaces/binding.d.ts +4 -11
- package/dist/interfaces/entity.d.ts +5 -5
- package/dist/interfaces/game.d.ts +2 -2
- package/dist/managers/binding.d.ts +5 -5
- package/dist/managers/entity.d.ts +7 -7
- package/dist/managers/game.d.ts +5 -5
- package/dist/managers/input.d.ts +3 -3
- package/dist/managers/level.d.ts +1 -2
- package/dist/sage.d.ts +16 -14
- package/dist/sage.es.js +129 -71
- package/dist/sage.es.js.map +1 -1
- package/dist/sage.umd.js +1 -1
- package/dist/sage.umd.js.map +1 -1
- package/dist/utils/graphics.d.ts +1 -1
- package/dist/utils/logger.d.ts +3 -3
- package/package.json +11 -7
- package/src/classes/bindings/toggle.ts +0 -261
- package/src/classes/bindings/trigger.ts +0 -211
- package/src/classes/bindings/value.ts +0 -227
- package/src/classes/entity.ts +0 -256
- package/src/classes/eventBus.ts +0 -259
- package/src/classes/gameEngine.ts +0 -125
- package/src/classes/input/gamepad.ts +0 -388
- package/src/classes/input/keyboard.ts +0 -189
- package/src/classes/input/mouse.ts +0 -276
- package/src/classes/input/readers/gamepad.ts +0 -179
- package/src/classes/input/readers/keyboard.ts +0 -123
- package/src/classes/input/readers/mouse.ts +0 -133
- package/src/classes/loggers/consoleBackend.ts +0 -135
- package/src/classes/loggers/nullBackend.ts +0 -51
- package/src/engines/scene.ts +0 -112
- package/src/images/sage_logo.svg +0 -172
- package/src/images/sage_logo_shape.svg +0 -146
- package/src/interfaces/action.ts +0 -30
- package/src/interfaces/binding.ts +0 -191
- package/src/interfaces/entity.ts +0 -21
- package/src/interfaces/game.ts +0 -44
- package/src/interfaces/input.ts +0 -221
- package/src/interfaces/logger.ts +0 -118
- package/src/managers/binding.ts +0 -729
- package/src/managers/entity.ts +0 -252
- package/src/managers/game.ts +0 -111
- package/src/managers/input.ts +0 -233
- package/src/managers/level.ts +0 -261
- package/src/sage.ts +0 -122
- package/src/types/global.d.ts +0 -11
- package/src/utils/capabilities.ts +0 -16
- package/src/utils/graphics.ts +0 -148
- package/src/utils/logger.ts +0 -225
- package/src/utils/physics.ts +0 -16
- package/src/utils/version.ts +0 -11
package/dist/sage.umd.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
(function(u,h){typeof exports=="object"&&typeof module<"u"?h(exports,require("@babylonjs/core"),require("@babylonjs/havok")):typeof define=="function"&&define.amd?define(["exports","@babylonjs/core","@babylonjs/havok"],h):(u=typeof globalThis<"u"?globalThis:u||self,h(u.SAGameEngine={},u.BABYLON,u.HavokPhysics))})(this,function(u,h,f){"use strict";var ee=Object.defineProperty;var te=(u,h,f)=>h in u?ee(u,h,{enumerable:!0,configurable:!0,writable:!0,value:f}):u[h]=f;var n=(u,h,f)=>te(u,typeof h!="symbol"?h+"":h,f);const y="0.5.0";class C{constructor(e,t,s,i,o,a,c){n(this,"canvas");n(this,"renderEngine");n(this,"physics");n(this,"managers");n(this,"engines");n(this,"eventBus");n(this,"logger");n(this,"_log");this.canvas=e,this.renderEngine=t,this.physics=s,this.eventBus=i,this.logger=o,this.engines=a,this.managers=c,this._log=o.getLogger("GameEngine")}async start(){this._log.info(`Starting SkewedAspect Game Engine (Version: ${y})...`),await this.managers.gameManager.start(this.canvas),this._log.info("Game engine started successfully")}async stop(){this._log.info(`Stopping SkewedAspect Game Engine (Version: ${y})...`),await this.managers.gameManager.stop(),this._log.info("Game engine stopped successfully")}}class ${constructor(){n(this,"timers");this.timers=new Map}getStyleForLevel(e){const t={trace:"color: #999999",debug:"color: #00AAAA",info:"color: #00AA00",warn:"color: #AAAA00",error:"color: #AA0000",timer:"color: #AA00AA",none:"color: inherit"};return t[e]||t.none}formatMessage(e,t){const s=new Date,i=s.getHours()%12||12,o=s.getMinutes().toString().padStart(2,"0"),a=s.getSeconds().toString().padStart(2,"0"),c=s.getHours()>=12?"PM":"AM",d=`[${i}:${o}:${a} ${c}]`,l=t.toUpperCase();return[`${d} %c${l}%c (${e}): `,this.getStyleForLevel(t),"",""]}trace(e,t,...s){const[i,o,a,c]=this.formatMessage(e,"trace");console.debug(i,o,a,c,t,...s)}debug(e,t,...s){const[i,o,a,c]=this.formatMessage(e,"debug");console.debug(i,o,a,c,t,...s)}info(e,t,...s){const[i,o,a,c]=this.formatMessage(e,"info");console.info(i,o,a,c,t,...s)}warn(e,t,...s){const[i,o,a,c]=this.formatMessage(e,"warn");console.warn(i,o,a,c,t,...s)}error(e,t,...s){const[i,o,a,c]=this.formatMessage(e,"error");console.error(i,o,a,c,t,...s)}time(e,t){const s=`${e}:${t}`;this.timers.set(s,performance.now())}timeEnd(e,t){const s=`${e}:${t}`,i=this.timers.get(s);if(i!==void 0){const o=performance.now()-i;this.timers.delete(s);const[a,c,d,l]=this.formatMessage(e,"timer");console.info(`${a} Timer '${t}' completed in ${o.toFixed(2)}ms`,c,d,l)}else console.warn(`[${e}]: Timer '${t}' does not exist`)}}class M{trace(e,t,...s){}debug(e,t,...s){}info(e,t,...s){}warn(e,t,...s){}error(e,t,...s){}time(e,t){}timeEnd(e,t){}}class g{constructor(e,t="none",s=new M){n(this,"category");n(this,"backend");n(this,"minLevel");this.category=e,this.backend=s,this.minLevel=t}updateSettings(e,t){this.backend=e,this.minLevel=t}trace(e,...t){this.shouldLog("trace")&&this.backend.trace(this.category,e,...t)}debug(e,...t){this.shouldLog("debug")&&this.backend.debug(this.category,e,...t)}info(e,...t){this.shouldLog("info")&&this.backend.info(this.category,e,...t)}warn(e,...t){this.shouldLog("warn")&&this.backend.warn(this.category,e,...t)}error(e,...t){this.shouldLog("error")&&this.backend.error(this.category,e,...t)}time(e){this.minLevel!=="none"&&this.backend.time(this.category,e)}timeEnd(e){this.minLevel!=="none"&&this.backend.timeEnd(this.category,e)}shouldLog(e){if(this.minLevel==="none")return!1;switch(this.minLevel){case"trace":return!0;case"debug":return e!=="trace";case"info":return e==="info"||e==="warn"||e==="error";case"warn":return e==="warn"||e==="error";case"error":return e==="error";default:return!1}}}class A{constructor(e="debug",t=new $){n(this,"backend");n(this,"level");n(this,"loggers");this.backend=t,this.level=e,this.loggers=new Map}setBackend(e){this.backend=e,this.loggers.forEach(t=>{t instanceof g&&t.updateSettings(this.backend,this.level)})}setLevel(e){this.level=e,this.loggers.forEach(t=>{t instanceof g&&t.updateSettings(this.backend,this.level)})}getLevel(){return this.level}getLogger(e){this.loggers.has(e)||this.loggers.set(e,new g(e,this.level,this.backend));const t=this.loggers.get(e);if(t===void 0)throw new Error(`Failed to create logger for category: ${e}`);return t}}class I{constructor(e){n(this,"directMap",new Map);n(this,"patternSubs",new Set);n(this,"_log");this._log=(e==null?void 0:e.getLogger("EventBus"))||new g("EventBus")}subscribe(e,t){return this._log.trace(`Subscribe request for: ${e.toString()}`),e instanceof RegExp||typeof e=="string"&&e.includes("*")?this.subscribePattern(e,t):this.subscribeExact(e,t)}subscribeExact(e,t){this._log.debug(`Adding exact subscription for: ${e}`);let s=this.directMap.get(e);s||(s=new Set,this.directMap.set(e,s));const i={callback:o=>t(o)};return s.add(i),()=>{this._log.debug(`Removing exact subscription for: ${e}`),s.delete(i),s.size===0&&this.directMap.delete(e)}}subscribePattern(e,t){let s;if(typeof e=="string"){const o=e.replace(/[-/\\^$+?.()|[\]{}]/g,"\\$&").replace(/\*/g,".*");s=new RegExp(`^${o}$`),this._log.debug(`Adding pattern subscription for string: ${e}, regex: ${s.toString()}`)}else s=e,this._log.debug(`Adding pattern subscription for regex: ${s.toString()}`);const i={pattern:s,callback:o=>t(o)};return this.patternSubs.add(i),()=>{this._log.debug(`Removing pattern subscription: ${s.toString()}`),this.patternSubs.delete(i)}}publish(e){this._log.trace(`Publishing event: ${e.type}`,e);let t=0;const s=this.directMap.get(e.type);if(s){t+=s.size;for(const i of s)Promise.resolve().then(()=>i.callback(e))}for(const i of this.patternSubs)i.pattern&&i.pattern.test(e.type)&&(t++,Promise.resolve().then(()=>i.callback(e)));t===0?this._log.debug(`No subscribers found for event: ${e.type}`):this._log.trace(`Event ${e.type} dispatched to ${t} subscribers`)}}class K{constructor(e,t,s){n(this,"_engine");n(this,"_physics");n(this,"_log");this._engine=e,this._physics=t,this._log=(s==null?void 0:s.getLogger("SceneEngine"))||new g("SceneEngine")}async _buildDemoScene(e,t){this._log.debug("Building demo scene..."),this._log.trace("Creating camera...");const s=new h.FreeCamera("camera1",new h.Vector3(0,5,-10),e);s.setTarget(h.Vector3.Zero()),s.attachControl(t,!0),this._log.trace("Creating light...");const i=new h.HemisphericLight("light",new h.Vector3(0,1,0),e);i.intensity=.7,this._log.trace("Creating sphere...");const o=h.MeshBuilder.CreateSphere("sphere",{diameter:2,segments:32},e);o.position.y=4,this._log.trace("Creating ground...");const a=h.MeshBuilder.CreateGround("ground",{width:10,height:10},e);this._log.trace("Adding physics to sphere..."),new h.PhysicsAggregate(o,h.PhysicsShapeType.SPHERE,{mass:1,restitution:.75},e),this._log.trace("Adding physics to ground..."),new h.PhysicsAggregate(a,h.PhysicsShapeType.BOX,{mass:0},e),this._log.debug("Demo scene built successfully")}async loadScene(e){this._log.info("Loading scene..."),this._log.time("sceneLoad"),this._log.debug("Creating new scene...");const t=new h.Scene(this._engine);return this._log.debug("Enabling physics with gravity (0, -9.8, 0)..."),t.enablePhysics(new h.Vector3(0,-9.8,0),this._physics),await this._buildDemoScene(t,e),this._log.timeEnd("sceneLoad"),this._log.info("Scene loaded successfully"),t}}const k=["trigger","toggle","value"];class U{constructor(e,t,s,i={}){n(this,"type","trigger");n(this,"action");n(this,"context");n(this,"deviceID");n(this,"reader");n(this,"_edgeMode");n(this,"_threshold");n(this,"_lastDigitalState",!1);this.action=e,this.deviceID=t,this.reader=s,this.context=i.context,this._edgeMode=i.edgeMode??"rising",this._threshold=i.threshold??.5}get options(){return{edgeMode:this._edgeMode,threshold:this._threshold}}process(e,t){const s=this.reader.getValue(e)??!1,i=typeof s=="boolean"?s:s>=this._threshold;let o=!1;switch(this._edgeMode){case"rising":o=i&&!this._lastDigitalState;break;case"falling":o=!i&&this._lastDigitalState;break;case"both":o=i!==this._lastDigitalState;break}if(this._lastDigitalState=i,o){let a;if(this.action.type==="analog"){let d=typeof s=="number"?s:s?1:0;if(this.action.minValue!==void 0||this.action.maxValue!==void 0){const l=this.action.minValue??0,p=this.action.maxValue??1;d=l+d*(p-l)}a=d}else a=!0;const c={type:`action:${this.action.name}`,payload:{value:a,deviceId:this.deviceID,context:this.context}};t.publish(c)}}toJSON(){return{type:this.type,action:this.action.name,input:{deviceID:this.deviceID,...this.reader.toJSON()},context:this.context,options:this.options}}}class R{constructor(e,t,s,i={}){n(this,"type","toggle");n(this,"action");n(this,"context");n(this,"deviceID");n(this,"reader");n(this,"_invert");n(this,"_threshold");n(this,"_initialState");n(this,"_onValue");n(this,"_offValue");n(this,"_lastDigitalState",!1);n(this,"_toggleState");this.action=e,this.deviceID=t,this.reader=s,this.context=i.context,this._invert=i.invert??!1,this._threshold=i.threshold??.5,this._initialState=i.initialState??!1,this._toggleState=this._initialState,this._onValue=i.onValue??!0,this._offValue=i.offValue??!1}get state(){return this._toggleState}set state(e){this._toggleState=e}get onValue(){return this._onValue}get offValue(){return this._offValue}get value(){return this.action.type==="analog"?this._toggleState?this.action.maxValue??1:this.action.minValue??0:this._toggleState?this._onValue:this._offValue}get options(){return{invert:this._invert,threshold:this._threshold,initialState:this._initialState,onValue:this._onValue,offValue:this._offValue}}process(e,t){const s=this.reader.getValue(e)??!1,i=typeof s=="boolean"?s:s>=this._threshold,o=this._invert?!i&&this._lastDigitalState:i&&!this._lastDigitalState;this._lastDigitalState=i,o&&(this._toggleState=!this._toggleState,t.publish({type:`action:${this.action.name}`,payload:{value:this.value,deviceId:this.deviceID,context:this.context}}))}reset(){this._toggleState=this._initialState}toJSON(){return{type:this.type,action:this.action.name,input:{deviceID:this.deviceID,...this.reader.toJSON()},state:this._toggleState,context:this.context,options:this.options}}}class T{constructor(e,t,s,i={}){n(this,"type","value");n(this,"action");n(this,"context");n(this,"deviceID");n(this,"reader");n(this,"_scale");n(this,"_offset");n(this,"_invert");n(this,"_emitOnChange");n(this,"_deadzone");n(this,"_onValue");n(this,"_offValue");n(this,"_min");n(this,"_max");n(this,"_lastValue");this.action=e,this.deviceID=t,this.reader=s,this.context=i.context,this._scale=i.scale??1,this._offset=i.offset??0,this._invert=i.invert??!1,this._emitOnChange=i.emitOnChange??!0,this._deadzone=i.deadzone??0,this._onValue=i.onValue??!0,this._offValue=i.offValue??!1;const o=this.action.type==="analog"?this.action.minValue??Number.NEGATIVE_INFINITY:Number.NEGATIVE_INFINITY;this._min=i.min??o;const a=this.action.type==="analog"?this.action.maxValue??Number.POSITIVE_INFINITY:Number.POSITIVE_INFINITY;this._max=i.max??a}get options(){return{scale:this._scale,offset:this._offset,invert:this._invert,emitOnChange:this._emitOnChange,deadzone:this._deadzone,onValue:this._onValue,offValue:this._offValue,min:this._min,max:this._max}}process(e,t){const s=this.reader.getValue(e);if(s===void 0)return;const i=typeof s=="boolean"?s?1:0:s;if(i===void 0)return;let o=this._deadzone>0&&Math.abs(i)<this._deadzone?0:i;o=(this._invert?-o:o)*this._scale+this._offset,o=Math.max(this._min,Math.min(this._max,o)),!(this._emitOnChange&&this._lastValue===o)&&(this._lastValue=o,t.publish({type:`action:${this.action.name}`,payload:{value:o,deviceId:this.deviceID,context:this.context}}))}toJSON(){return{type:this.type,action:this.action.name,input:{deviceID:this.deviceID,...this.reader.toJSON()},context:this.context,options:this.options}}}class S{constructor(e,t={}){n(this,"sourceType","key");n(this,"sourceKey");n(this,"useDelta");this.sourceKey=e,this.useDelta=t.useDelta||!1}getValue(e){if(e.type!=="keyboard")return;const t=e;return this.useDelta?t.delta[this.sourceKey]:t.keys[this.sourceKey]}static fromString(e,t={}){return new S(e,t)}toJSON(){return{type:"keyboard",sourceType:this.sourceType,sourceKey:this.sourceKey,options:{useDelta:this.useDelta}}}}class x{constructor(e,t){n(this,"sourceType");n(this,"sourceKey");this.sourceType=e,this.sourceKey=t}getValue(e){if(e.type==="mouse")switch(this.sourceType){case"button":{const t=e.buttons[this.sourceKey];return t?t.pressed:void 0}case"position":{const[t,s]=this.sourceKey.split(":");return!t||!s||t!=="absolute"&&t!=="relative"||s!=="x"&&s!=="y"?void 0:e.position[t][s]}case"wheel":{const t=this.sourceKey==="deltaX"||this.sourceKey==="deltaY"||this.sourceKey==="deltaZ";return e.wheel&&t?e.wheel[this.sourceKey]:void 0}default:return}}static fromString(e){const[t,...s]=e.split(":"),i=s.join(":");if(!t||!i)throw new Error(`Invalid mouse source format: ${e}`);return new x(t,i)}toJSON(){return{type:"mouse",sourceType:this.sourceType,sourceKey:this.sourceKey}}}class E{constructor(e,t,s={}){n(this,"sourceType");n(this,"sourceKey");n(this,"useAnalogValue");n(this,"deadzone");n(this,"invert");this.sourceType=e,this.sourceKey=t,this.useAnalogValue=s.useAnalogValue||!1,this.deadzone=s.deadzone||.1,this.invert=s.invert||!1}getValue(e){if(e.type==="gamepad")switch(this.sourceType){case"button":{const t=e.buttons[this.sourceKey];return t?this.useAnalogValue?t.value:t.pressed:void 0}case"axis":{let t=e.axes[this.sourceKey];return t===void 0?void 0:(Math.abs(t)<this.deadzone&&(t=0),this.invert?-t:t)}default:return}}static fromString(e,t={}){const[s,i]=e.split(":");if(!s||!i)throw new Error(`Invalid gamepad source format: ${e}`);return new E(s,i,t)}toJSON(){return{type:"gamepad",sourceType:this.sourceType,sourceKey:this.sourceKey,options:{useAnalogValue:this.useAnalogValue,deadzone:this.deadzone,invert:this.invert}}}}class z{constructor(e,t){n(this,"_bindings",new Map);n(this,"_actions",new Map);n(this,"_contexts",new Map);n(this,"_activeContexts",new Set);n(this,"_eventBus");n(this,"_log");this._eventBus=e,this._eventBus.subscribe("input:changed",s=>{s.payload&&this.$handleInput(s.payload.device,s.payload.state)}),this._log=(t==null?void 0:t.getLogger("BindingManager"))||new g("BindingManager"),this._log.debug("BindingManager initialized")}_isBindingContextActive(e){return e.context?this._activeContexts.has(e.context):!0}_getOrCreateContext(e,t=!0){let s=this._contexts.get(e);return s||(s={name:e,exclusive:t},this._contexts.set(e,s),this._log.debug(`Auto-created context "${e}" (exclusive: ${t})`)),s}_deactivateExclusiveContexts(e){const t=[];for(const s of this._activeContexts){if(s===e)continue;const i=this._contexts.get(s);i!=null&&i.exclusive&&(this._activeContexts.delete(s),t.push(s))}return t}_createBindingFromDefinition(e){const t=this._actions.get(e.action);if(!t)return this._log.warn(`Cannot create binding: Action "${e.action}" not found.`),null;const{deviceID:s,...i}=e.input;switch(e.type){case"trigger":return new U(t,s,this._createInputSourceFromDefinition(i),{...e.options||{},context:e.context});case"toggle":return new R(t,s,this._createInputSourceFromDefinition(i),{...e.options||{},context:e.context});case"value":return new T(t,s,this._createInputSourceFromDefinition(i),{...e.options||{},context:e.context});default:return this._log.error(`Binding type not implemented: ${e.type}`),null}}_createInputSourceFromDefinition(e){switch(e.type){case"keyboard":return new S(e.sourceKey,e.options);case"mouse":{const t=e.sourceType;if(!(t==="button"||t==="position"||t==="wheel"))throw new Error(`Invalid mouse source type: ${t}`);return new x(t,e.sourceKey)}case"gamepad":{const t=e.sourceType;if(!(t==="button"||t==="axis"))throw new Error(`Invalid gamepad source type: ${t}`);return new E(t,e.sourceKey,e.options)}default:throw new Error(`Unsupported input source type: ${e.type}`)}}$handleInput(e,t){const s=this._bindings.get(e.id);if(!(!s||s.length===0)&&!(this._activeContexts.size===0&&s.some(i=>i.context)))for(const i of s)this._isBindingContextActive(i)&&i.process(t,this._eventBus)}registerAction(e){if(this._log.debug(`Registering action "${e.name}"`),this._actions.has(e.name)){const t=`Action "${e.name}" already registered.`;throw this._log.error(t),new Error(t)}this._actions.set(e.name,e),this._log.debug(`Action "${e.name}" registered successfully`)}getAction(e){this._log.trace(`Getting action "${e}"`);const t=this._actions.get(e)??null;return t||this._log.debug(`Action "${e}" not found`),t}registerContext(e,t=!0){const s=this._getOrCreateContext(e,t);return s.exclusive!==t&&(s.exclusive=t,this._log.info(`Updated context "${e}" exclusivity: ${t}`)),s}activateContext(e){const s=this._getOrCreateContext(e).exclusive;this._log.debug(`Activating context "${e}" (exclusive: ${s})`);const i=this._activeContexts.has(e);if(s){const o=this._deactivateExclusiveContexts(e);o.length>0&&this._log.info(`Deactivated exclusive contexts: ${o.join(", ")}`)}i||(this._activeContexts.add(e),this._log.info(`Context "${e}" activated${s?" as exclusive":""}`))}deactivateContext(e){this._log.debug(`Deactivating context "${e}"`),this._activeContexts.has(e)?(this._activeContexts.delete(e),this._log.info(`Context "${e}" deactivated`)):this._log.debug(`Context "${e}" was not active`)}getActiveContexts(){return[...this._activeContexts]}isContextActive(e){return this._activeContexts.has(e)}getContext(e){return this._contexts.get(e)||null}$registerBinding(e){var t;if(!k.includes(e.type))throw new Error(`Invalid binding type: ${e.type}`);e.context&&!this._contexts.has(e.context)&&this.registerContext(e.context),this._bindings.has(e.deviceID)||this._bindings.set(e.deviceID,[]),(t=this._bindings.get(e.deviceID))==null||t.push(e),this._log.debug(`Registered ${e.type} binding for "${e.action.name}" in context "${e.context||null}"`)}registerBinding(e){const t=this._createBindingFromDefinition(e);t?this.$registerBinding(t):this._log.error(`Failed to create binding for action "${e.action}" with type "${e.type}"`)}unregisterBindings(e,t=null){this._log.debug(`Unregistering all bindings for action "${e}" in context "${t}"`);let s=0;for(const[i,o]of this._bindings.entries()){const a=o.filter(c=>{const d=c.context||null,l=c.action.name!==e||d!==t;return l||s++,l});a.length!==o.length&&this._bindings.set(i,a)}this._log.info(`Removed ${s} bindings for action "${e}" in context "${t}"`)}getBindingsForAction(e,t){const s=[];for(const i of this._bindings.values())for(const o of i){const a=o.context||null;o.action.name===e&&(!t||a===t)&&s.push(o)}return s}exportConfiguration(){this._log.debug("Exporting binding configuration");const e=[...this._actions.values()].map(i=>i.type==="analog"?{name:i.name,type:i.type,minValue:i.minValue??0,maxValue:i.maxValue??1}:i),t=[];for(const i of this._bindings.values())for(const o of i)t.push(o.toJSON());const s=[...this._contexts.values()].map(i=>({name:i.name,exclusive:i.exclusive,active:this._activeContexts.has(i.name)}));return this._log.info(`Configuration exported: ${e.length} actions, ${t.length} bindings, ${s.length} contexts`),{actions:e,bindings:t,contexts:s}}importConfiguration(e){this._log.debug("Importing binding configuration"),this._bindings.clear(),this._actions.clear(),this._contexts.clear(),this._activeContexts.clear();for(const t of e.actions)this.registerAction(t);for(const t of e.contexts)this.registerContext(t.name,t.exclusive),t.active&&this.activateContext(t.name);for(const t of e.bindings)try{this.registerBinding(t)}catch(s){s instanceof Error&&this._log.error(`Failed to import binding for action "${t.action}": ${s.message}`)}this._log.info(`Configuration imported: ${e.actions.length} actions, ${e.bindings.length} bindings, ${e.contexts.length} contexts`)}}function G(){return typeof window<"u"&&typeof window.document<"u"}function V(){return G()&&!!window.navigator.gpu}class P{constructor(e,t,s,i,o){n(this,"_engine");n(this,"_entityManager");n(this,"_inputManager");n(this,"_sceneEngine");n(this,"_currentScene",null);n(this,"_log");n(this,"started",!1);this._engine=e,this._sceneEngine=t,this._entityManager=s,this._inputManager=i,this._log=(o==null?void 0:o.getLogger("GameManager"))||new g("GameManager"),G()&&window.addEventListener("resize",this._resizeHandler.bind(this))}_renderLoop(){const e=this._engine.getDeltaTime();this._entityManager.$frameUpdate(e),this._inputManager&&this._inputManager.pollGamepads(),this._currentScene&&this._currentScene.render()}_resizeHandler(){this.started&&this._engine.resize()}async start(e){this._currentScene=await this._sceneEngine.loadScene(e),this._engine.runRenderLoop(this._renderLoop.bind(this)),this.started=!0,this._log.info("SkewedAspect Game Engine started successfully")}async stop(){this.started=!1,this._engine.stopRenderLoop(),this._log.info("SkewedAspect Game Engine stopped successfully")}}class W{constructor(){n(this,"entity",null)}$emit(e){if(!this.entity)throw new Error("Entity is not set for this behavior.");e.senderID=this.entity.id,this.entity.eventBus.publish(e)}$setEntity(e){this.entity=e}}class L{constructor(e,t,s,i){n(this,"id");n(this,"type");n(this,"state");n(this,"behaviors",new Map);n(this,"eventBus");n(this,"subscriptions",new Map);this.id=crypto.randomUUID(),this.type=e,this.state=s,this.eventBus=t;for(const o of i)this.attachBehavior(new o)}async $processEvent(e){for(const t of this.behaviors.values())if(await t.processEvent(e,this.state))break}$update(e){var t;for(const s of this.behaviors.values())(t=s.update)==null||t.call(s,e,this.state)}async $destroy(){var e;for(const t of this.behaviors.values())(e=t.destroy)==null||e.call(t);for(const t of this.subscriptions.values())t.unsubscribe();this.behaviors.clear(),this.subscriptions.clear()}attachBehavior(e){if(this.behaviors.has(e.name))throw new Error(`Behavior ${e.name} is already attached to this entity.`);for(const t of e.eventSubscriptions){const s=this.subscriptions.get(t);if(s)s.count++;else{const i=this.eventBus.subscribe(t,this.$processEvent.bind(this));this.subscriptions.set(t,{count:1,unsubscribe:i})}}this.behaviors.set(e.name,e),e.$setEntity(this)}detachBehavior(e){const t=this.behaviors.get(e);if(t){for(const s of t.eventSubscriptions){const i=this.subscriptions.get(s);i&&(i.count--,i.count<=0&&(i.unsubscribe(),this.subscriptions.delete(s)))}this.behaviors.delete(t.name),t.$setEntity(null)}}}class O{constructor(e,t,s){n(this,"eventBus");n(this,"entities",new Map);n(this,"entityDefinitions",new Map);n(this,"bindingManager");n(this,"_log");this.eventBus=e,this.bindingManager=s,this._log=(t==null?void 0:t.getLogger("EntityManager"))||new g("EntityManager"),this._log.info("EntityManager initialized")}areActionsCompatible(e,t){return!(e.type!==t.type||e.type==="analog"&&t.type==="analog"&&(t.minValue!==void 0&&e.minValue!==t.minValue||t.maxValue!==void 0&&e.maxValue!==t.maxValue))}registerEntityActions(e){if(e.actions)for(const t of e.actions)try{const s=this.bindingManager.getAction(t.name);s?this.areActionsCompatible(s,t)?this._log.trace(`Action "${t.name}" already registered with compatible options, skipping registration`):this._log.warn(`Action "${t.name}" already registered with different options. Entity "${e.type}" requires: ${JSON.stringify(t)}, but found: ${JSON.stringify(s)}`):(this._log.debug(`Registering action "${t.name}" from entity type "${e.type}"`),this.bindingManager.registerAction(t))}catch(s){this._log.debug(`Failed to register action "${t.name}": ${s instanceof Error?s.message:String(s)}`)}}$frameUpdate(e){this._log.trace(`Updating ${this.entities.size} entities with dt=${e}`);for(const t of this.entities.values())t.$update(e)}registerEntityDefinition(e){this._log.debug(`Registering entity definition: ${e.type}`),this.registerEntityActions(e),this.entityDefinitions.set(e.type,e)}createEntity(e,t={}){var a;this._log.debug(`Creating entity of type: ${e}`);const s=this.entityDefinitions.get(e);if(!s){const c=`Entity type ${e} is not registered.`;throw this._log.error(c),new Error(c)}this._log.trace(`Using entity definition with ${((a=s.behaviors)==null?void 0:a.length)||0} behaviors`);const i={...s.defaultState,...t},o=new L(s.type,this.eventBus,i,s.behaviors);return this.entities.set(o.id,o),this._log.debug(`Entity created with ID: ${o.id}`),o}destroyEntity(e){this._log.debug(`Destroying entity: ${e}`);const t=this.entities.get(e);t?(t.$destroy(),this.entities.delete(e),this._log.debug(`Entity ${e} destroyed`)):this._log.warn(`Attempted to destroy non-existent entity: ${e}`)}getEntity(e){return this._log.trace(`Getting entity: ${e}`),this.entities.get(e)??null}addEntity(e){this._log.debug(`Adding existing entity: ${e.id} (type: ${e.type})`),this.entities.set(e.id,e)}removeEntity(e){this._log.debug(`Removing entity: ${e}`),this.entities.get(e)?(this.entities.delete(e),this._log.debug(`Entity ${e} removed`)):this._log.warn(`Attempted to remove non-existent entity: ${e}`)}}class F{constructor(){n(this,"_keyboardDevice");n(this,"_keysState",{});n(this,"_onDeviceConnected");n(this,"_onInputChanged");this._keyboardDevice={id:"keyboard-0",name:"Keyboard",type:"keyboard",connected:!0},this._setupKeyboardEvents(),setTimeout(()=>this._notifyDeviceConnected(),0)}onDeviceConnected(e){this._onDeviceConnected=e}onInputChanged(e){this._onInputChanged=e}getState(){return{type:"keyboard",keys:{...this._keysState},delta:{}}}getDevice(){return{...this._keyboardDevice}}destroy(){window.removeEventListener("keydown",this._handleKeyDown),window.removeEventListener("keyup",this._handleKeyUp)}_setupKeyboardEvents(){this._handleKeyDown=this._handleKeyDown.bind(this),this._handleKeyUp=this._handleKeyUp.bind(this),window.addEventListener("keydown",this._handleKeyDown),window.addEventListener("keyup",this._handleKeyUp)}_handleKeyDown(e){this._keysState[e.code]=!0;const t={};t[e.code]=!0;const s={type:"keyboard",keys:{...this._keysState},delta:t,event:e};this._notifyInputChanged(s)}_handleKeyUp(e){this._keysState[e.code]=!1;const t={};t[e.code]=!1;const s={type:"keyboard",keys:{...this._keysState},delta:t,event:e};this._notifyInputChanged(s)}_notifyDeviceConnected(){this._onDeviceConnected&&this._onDeviceConnected(this._keyboardDevice)}_notifyInputChanged(e){this._onInputChanged&&this._onInputChanged(this._keyboardDevice,e)}}class N{constructor(e=document.body){n(this,"_targetElement");n(this,"_mouseDevice");n(this,"_buttonState",{});n(this,"_axesState",{});n(this,"_position",{absolute:{x:0,y:0},relative:{x:0,y:0}});n(this,"_wheelState",{deltaX:0,deltaY:0,deltaZ:0,deltaMode:0});n(this,"_onDeviceConnected");n(this,"_onInputChanged");this._targetElement=e,this._mouseDevice={id:"mouse-0",name:"Mouse",type:"mouse",connected:!0},this._setupMouseEvents(),this._axesState["axis-x"]=0,this._axesState["axis-y"]=0,setTimeout(()=>this._notifyDeviceConnected(),0)}onDeviceConnected(e){this._onDeviceConnected=e}onInputChanged(e){this._onInputChanged=e}getState(){return{type:"mouse",buttons:{...this._buttonState},axes:{...this._axesState},position:{absolute:{...this._position.absolute},relative:{...this._position.relative}},wheel:{...this._wheelState}}}getDevice(){return{...this._mouseDevice}}destroy(){this._targetElement.removeEventListener("mousedown",this._handleMouseDown),this._targetElement.removeEventListener("mouseup",this._handleMouseUp),this._targetElement.removeEventListener("mousemove",this._handleMouseMove),this._targetElement.removeEventListener("wheel",this._handleMouseWheel)}_setupMouseEvents(){this._handleMouseDown=this._handleMouseDown.bind(this),this._handleMouseUp=this._handleMouseUp.bind(this),this._handleMouseMove=this._handleMouseMove.bind(this),this._handleMouseWheel=this._handleMouseWheel.bind(this),this._targetElement.addEventListener("mousedown",this._handleMouseDown),this._targetElement.addEventListener("mouseup",this._handleMouseUp),this._targetElement.addEventListener("mousemove",this._handleMouseMove),this._targetElement.addEventListener("wheel",this._handleMouseWheel)}_handleMouseDown(e){const t=`button-${e.button}`,s={pressed:!0};this._buttonState[t]=s,this._notifyInputChanged({type:"mouse",event:e,buttons:{...this._buttonState},axes:{...this._axesState},position:{...this._position}})}_handleMouseUp(e){const t=`button-${e.button}`,s={pressed:!1};this._buttonState[t]=s,this._notifyInputChanged({type:"mouse",event:e,buttons:{...this._buttonState},axes:{...this._axesState},position:{...this._position}})}_handleMouseMove(e){this._position={absolute:{x:e.clientX,y:e.clientY},relative:{x:e.movementX,y:e.movementY}},this._axesState["axis-x"]=e.clientX,this._axesState["axis-y"]=e.clientY,this._notifyInputChanged({type:"mouse",event:e,buttons:{...this._buttonState},axes:{...this._axesState},position:{...this._position}})}_handleMouseWheel(e){this._wheelState={deltaX:e.deltaX,deltaY:e.deltaY,deltaZ:e.deltaZ,deltaMode:e.deltaMode},this._notifyInputChanged({type:"mouse",event:e,buttons:{...this._buttonState},axes:{...this._axesState},position:{...this._position},wheel:{...this._wheelState}})}_notifyDeviceConnected(){this._onDeviceConnected&&this._onDeviceConnected(this._mouseDevice)}_notifyInputChanged(e){this._onInputChanged&&this._onInputChanged(this._mouseDevice,e)}}class j{constructor(){n(this,"_gamepadDevices",{});n(this,"_buttonStates",{});n(this,"_axesStates",{});n(this,"_onDeviceConnected");n(this,"_onDeviceDisconnected");n(this,"_onInputChanged");this._setupGamepadEvents()}onDeviceConnected(e){this._onDeviceConnected=e}onDeviceDisconnected(e){this._onDeviceDisconnected=e}onInputChanged(e){this._onInputChanged=e}getDevices(){return Object.values(this._gamepadDevices).map(e=>({...e}))}getStates(){const e={};return Object.keys(this._buttonStates).forEach(t=>{const s=Number(t),i=this._buttonStates[s]||{},o=this._axesStates[s]||{};e[s]={type:"gamepad",buttons:{...i},axes:{...o}}}),e}getDevice(e){const t=this._gamepadDevices[e];return t?{...t}:null}getState(e){const t=this._buttonStates[e],s=this._axesStates[e];return!t&&!s?null:{type:"gamepad",buttons:t?{...t}:{},axes:s?{...s}:{}}}pollGamepads(){if(!navigator.getGamepads)return;const e=navigator.getGamepads();for(const t of e){if(!t)continue;const s=t.index;if(!this._gamepadDevices[s]){this._handleGamepadConnected(t);continue}const i=this._gamepadDevices[s];if(!i)continue;const o=this._buttonStates[s]||{},a=this._axesStates[s]||{},c={};let d=!1;t.buttons.forEach((_,b)=>{const m=`button-${b}`,v={pressed:_.pressed,touched:_.touched,value:_.value};c[m]=v;const w=o[m];(!w||w.pressed!==v.pressed||w.touched!==v.touched||w.value!==v.value)&&(d=!0)});const l={};let p=!1;if(t.axes.forEach((_,b)=>{const m=`axis-${b}`;l[m]=_,a[m]!==_&&(p=!0)}),this._buttonStates[s]=c,this._axesStates[s]=l,d||p){const _={type:"gamepad",buttons:{...c},axes:{...l}};this._notifyInputChanged(i,_)}}}destroy(){window.removeEventListener("gamepadconnected",this._handleGamepadConnected),window.removeEventListener("gamepaddisconnected",this._handleGamepadDisconnected)}_setupGamepadEvents(){if(this._handleGamepadConnected=this._handleGamepadConnected.bind(this),this._handleGamepadDisconnected=this._handleGamepadDisconnected.bind(this),window.addEventListener("gamepadconnected",this._handleGamepadConnected),window.addEventListener("gamepaddisconnected",this._handleGamepadDisconnected),navigator.getGamepads){const e=navigator.getGamepads();for(const t of e)t&&this._handleGamepadConnected(t)}}_handleGamepadConnected(e){const t=e instanceof GamepadEvent?e.gamepad:e,s=t.index,i={id:`gamepad-${s}`,name:t.id,type:"gamepad",connected:!0,index:s,mapping:t.mapping,axes:Array.from(t.axes),buttons:Array.from(t.buttons)};this._gamepadDevices[s]=i;const o={};Array.from(t.buttons).forEach((c,d)=>{o[`button-${d}`]={pressed:c.pressed,touched:c.touched,value:c.value}}),this._buttonStates[s]=o;const a={};Array.from(t.axes).forEach((c,d)=>{a[`axis-${d}`]=c}),this._axesStates[s]=a,this._notifyDeviceConnected(i),this._notifyInputChanged(i,{type:"gamepad",buttons:{...o},axes:{...a},event:e instanceof GamepadEvent?e:void 0})}_handleGamepadDisconnected(e){const s=e.gamepad.index,i=this._gamepadDevices[s];i&&(i.connected=!1,this._notifyDeviceDisconnected(i),this._gamepadDevices[s]=void 0,this._buttonStates[s]=void 0,this._axesStates[s]=void 0)}_notifyDeviceConnected(e){this._onDeviceConnected&&this._onDeviceConnected(e)}_notifyDeviceDisconnected(e){this._onDeviceDisconnected&&this._onDeviceDisconnected(e)}_notifyInputChanged(e,t){this._onInputChanged&&this._onInputChanged(e,t)}}class J{constructor(e,t,s){n(this,"_eventBus");n(this,"_keyboardRA");n(this,"_mouseRA");n(this,"_gamepadRA");n(this,"_log");this._eventBus=e,this._log=(s==null?void 0:s.getLogger("UserInputManager"))||new g("UserInputManager"),this._log.info("Initializing UserInputManager"),this._log.debug("Initializing input resource access classes"),this._keyboardRA=new F,this._mouseRA=new N(t),this._gamepadRA=new j,this._log.debug("Registering input event callbacks"),this._keyboardRA.onDeviceConnected(this._publishDeviceConnected.bind(this)),this._keyboardRA.onInputChanged(this._publishInputChanged.bind(this)),this._mouseRA.onDeviceConnected(this._publishDeviceConnected.bind(this)),this._mouseRA.onInputChanged(this._publishInputChanged.bind(this)),this._gamepadRA.onDeviceConnected(this._publishDeviceConnected.bind(this)),this._gamepadRA.onDeviceDisconnected(this._publishDeviceDisconnected.bind(this)),this._gamepadRA.onInputChanged(this._publishInputChanged.bind(this)),this._log.info("UserInputManager initialized successfully")}_publishDeviceConnected(e){this._log.debug(`Device connected: ${e.id} (${e.name})`);const t={type:"input:device:connected",payload:{device:e}};this._eventBus.publish(t)}_publishDeviceDisconnected(e){this._log.debug(`Device disconnected: ${e.id} (${e.name})`);const t={type:"input:device:disconnected",payload:{device:e}};this._eventBus.publish(t)}_publishInputChanged(e,t){this._log.trace(`Input changed: ${e.id}`,t);const s={type:"input:changed",payload:{deviceId:e.id,device:e,state:t}};this._eventBus.publish(s)}$destroy(){this._log.info("Destroying UserInputManager"),this._log.debug("Cleaning up input resource access instances"),this._keyboardRA.destroy(),this._mouseRA.destroy(),this._gamepadRA.destroy(),this._log.info("UserInputManager destroyed")}listDevices(){this._log.debug("Getting all connected input devices");const e=[];return e.push(this._keyboardRA.getDevice()),e.push(this._mouseRA.getDevice()),e.push(...this._gamepadRA.getDevices()),this._log.debug(`Found ${e.length} connected devices`),e}getDevice(e){if(this._log.debug(`Getting device: ${e}`),e.startsWith("keyboard-"))return this._keyboardRA.getDevice();if(e.startsWith("mouse-"))return this._mouseRA.getDevice();if(e.startsWith("gamepad-")){const t=parseInt(e.split("-")[1],10);return this._gamepadRA.getDevice(t)}else{const t=this.listDevices();for(const s of t)if(s.id===e)return s}return this._log.warn(`Device not found: ${e}`),null}pollGamepads(){this._gamepadRA.pollGamepads()}}async function B(r,e){const t=new h.WebGPUEngine(r,e);return await t.initAsync(),t}function D(r,e){return new h.Engine(r,e.antialias,e.options,e.adaptToDeviceRatio)}function Y(r){return new h.NullEngine(r)}async function H(r,e){if(r===null)return console.debug("Using Null Engine"),Y(e);const t=e.engine||"auto";if(t==="webgpu")if(V())try{return console.debug("Using forced WebGPU engine"),await B(r,e)}catch(s){throw console.error("Forced WebGPU initialization failed:",s),new Error("Forced WebGPU failed to initialize. If WebGPU is required, check browser compatibility.")}else throw new Error("WebGPU was forced but is not available in this browser.");if(t==="webgl")return console.debug("Using forced WebGL engine"),D(r,e);if(V())try{return console.debug("Using WebGPU"),B(r,e).catch(s=>(console.warn("WebGPU initialization failed, falling back to WebGL:",s),D(r,e)))}catch(s){console.warn("WebGPU initialization failed, falling back to WebGL:",s)}else console.warn("WebGPU not supported, falling back to WebGL.");return console.debug("Using WebGL"),D(r,e)}async function X(){const r=await f();return new h.HavokPlugin(!0,r)}const q=["keyboard","mouse","gamepad"],Z=["trace","debug","info","warn","error","none"];async function Q(r,e={}){const t=new A(e.logLevel||"debug"),s=t.getLogger("SAGE");s.info(`Initializing SAGE Game Engine v${y}...`),s.debug("Creating rendering engine...");const i=await H(r,e.renderOptions||{});s.debug("Creating physics engine...");const o=await X();s.debug("Creating event bus...");const a=new I(t);s.debug("Creating scene engine...");const c=new K(i,o,t);s.debug("Creating managers...");const d=new J(a,r,t),l=new z(a,t),p=new O(a,t,l),_=new P(i,c,p,d,t);if(s.info(`SAGE Game Engine v${y} initialized successfully.`),s.debug("Registering default input bindings..."),e.bindings)for(const b of e.bindings)l.registerBinding(b);return new C(r,i,o,a,t,{sceneEngine:c},{bindingManager:l,entityManager:p,gameManager:_,inputManager:d})}u.ConsoleBackend=$,u.GameEntity=L,u.GameEntityBehavior=W,u.GameEventBus=I,u.LogLevels=Z,u.LoggingUtility=A,u.NullBackend=M,u.SAGELogger=g,u.SkewedAspectGameEngine=C,u.VERSION=y,u.bindingTypes=k,u.createGameEngine=Q,u.validDeviceTypes=q,Object.defineProperty(u,Symbol.toStringTag,{value:"Module"})});
|
|
1
|
+
(function(u,h){typeof exports=="object"&&typeof module<"u"?h(exports,require("@babylonjs/core"),require("@babylonjs/havok")):typeof define=="function"&&define.amd?define(["exports","@babylonjs/core","@babylonjs/havok"],h):(u=typeof globalThis<"u"?globalThis:u||self,h(u.SAGameEngine={},u.BABYLON,u.HavokPhysics))})(this,function(u,h,y){"use strict";var ee=Object.defineProperty;var te=(u,h,y)=>h in u?ee(u,h,{enumerable:!0,configurable:!0,writable:!0,value:y}):u[h]=y;var n=(u,h,y)=>te(u,typeof h!="symbol"?h+"":h,y);const b="0.5.1";class C{constructor(e,t,i,s,o,a,r){n(this,"canvas");n(this,"renderEngine");n(this,"physics");n(this,"managers");n(this,"engines");n(this,"eventBus");n(this,"logger");n(this,"_log");this.canvas=e,this.renderEngine=t,this.physics=i,this.eventBus=s,this.logger=o,this.engines=a,this.managers=r,this._log=o.getLogger("GameEngine")}async start(){this._log.info(`Starting SkewedAspect Game Engine (Version: ${b})...`),await this.managers.gameManager.start(this.canvas),this._log.info("Game engine started successfully")}async stop(){this._log.info(`Stopping SkewedAspect Game Engine (Version: ${b})...`),await this.managers.gameManager.stop(),this._log.info("Game engine stopped successfully")}}class ${constructor(){n(this,"timers");this.timers=new Map}getStyleForLevel(e){const t={trace:"color: #999999",debug:"color: #00AAAA",info:"color: #00AA00",warn:"color: #AAAA00",error:"color: #AA0000",timer:"color: #AA00AA",none:"color: inherit"};return t[e]||t.none}formatMessage(e,t){const i=new Date,s=i.getHours()%12||12,o=i.getMinutes().toString().padStart(2,"0"),a=i.getSeconds().toString().padStart(2,"0"),r=i.getHours()>=12?"PM":"AM",d=`[${s}:${o}:${a} ${r}]`,l=t.toUpperCase();return[`${d} %c${l}%c (${e}): `,this.getStyleForLevel(t),"",""]}trace(e,t,...i){const[s,o,a,r]=this.formatMessage(e,"trace");console.debug(s,o,a,r,t,...i)}debug(e,t,...i){const[s,o,a,r]=this.formatMessage(e,"debug");console.debug(s,o,a,r,t,...i)}info(e,t,...i){const[s,o,a,r]=this.formatMessage(e,"info");console.info(s,o,a,r,t,...i)}warn(e,t,...i){const[s,o,a,r]=this.formatMessage(e,"warn");console.warn(s,o,a,r,t,...i)}error(e,t,...i){const[s,o,a,r]=this.formatMessage(e,"error");console.error(s,o,a,r,t,...i)}time(e,t){const i=`${e}:${t}`;this.timers.set(i,performance.now())}timeEnd(e,t){const i=`${e}:${t}`,s=this.timers.get(i);if(s!==void 0){const o=performance.now()-s;this.timers.delete(i);const[a,r,d,l]=this.formatMessage(e,"timer");console.info(`${a} Timer '${t}' completed in ${o.toFixed(2)}ms`,r,d,l)}else console.warn(`[${e}]: Timer '${t}' does not exist`)}}class M{trace(e,t,...i){}debug(e,t,...i){}info(e,t,...i){}warn(e,t,...i){}error(e,t,...i){}time(e,t){}timeEnd(e,t){}}class _{constructor(e,t="none",i=new M){n(this,"category");n(this,"backend");n(this,"minLevel");this.category=e,this.backend=i,this.minLevel=t}updateSettings(e,t){this.backend=e,this.minLevel=t}trace(e,...t){this.shouldLog("trace")&&this.backend.trace(this.category,e,...t)}debug(e,...t){this.shouldLog("debug")&&this.backend.debug(this.category,e,...t)}info(e,...t){this.shouldLog("info")&&this.backend.info(this.category,e,...t)}warn(e,...t){this.shouldLog("warn")&&this.backend.warn(this.category,e,...t)}error(e,...t){this.shouldLog("error")&&this.backend.error(this.category,e,...t)}time(e){this.minLevel!=="none"&&this.backend.time(this.category,e)}timeEnd(e){this.minLevel!=="none"&&this.backend.timeEnd(this.category,e)}shouldLog(e){if(this.minLevel==="none")return!1;switch(this.minLevel){case"trace":return!0;case"debug":return e!=="trace";case"info":return e==="info"||e==="warn"||e==="error";case"warn":return e==="warn"||e==="error";case"error":return e==="error";default:return!1}}}class A{constructor(e="debug",t=new $){n(this,"backend");n(this,"level");n(this,"loggers");this.backend=t,this.level=e,this.loggers=new Map}setBackend(e){this.backend=e,this.loggers.forEach(t=>{t instanceof _&&t.updateSettings(this.backend,this.level)})}setLevel(e){this.level=e,this.loggers.forEach(t=>{t instanceof _&&t.updateSettings(this.backend,this.level)})}getLevel(){return this.level}getLogger(e){this.loggers.has(e)||this.loggers.set(e,new _(e,this.level,this.backend));const t=this.loggers.get(e);if(t===void 0)throw new Error(`Failed to create logger for category: ${e}`);return t}}class I{constructor(e){n(this,"directMap",new Map);n(this,"patternSubs",new Set);n(this,"_log");this._log=(e==null?void 0:e.getLogger("EventBus"))||new _("EventBus")}subscribe(e,t){return this._log.trace(`Subscribe request for: ${e.toString()}`),e instanceof RegExp||typeof e=="string"&&e.includes("*")?this.subscribePattern(e,t):this.subscribeExact(e,t)}subscribeExact(e,t){this._log.debug(`Adding exact subscription for: ${e}`);let i=this.directMap.get(e);i||(i=new Set,this.directMap.set(e,i));const s={callback:o=>t(o)};return i.add(s),()=>{this._log.debug(`Removing exact subscription for: ${e}`),i.delete(s),i.size===0&&this.directMap.delete(e)}}subscribePattern(e,t){let i;if(typeof e=="string"){const o=e.replace(/[-/\\^$+?.()|[\]{}]/g,"\\$&").replace(/\*/g,".*");i=new RegExp(`^${o}$`),this._log.debug(`Adding pattern subscription for string: ${e}, regex: ${i.toString()}`)}else i=e,this._log.debug(`Adding pattern subscription for regex: ${i.toString()}`);const s={pattern:i,callback:o=>t(o)};return this.patternSubs.add(s),()=>{this._log.debug(`Removing pattern subscription: ${i.toString()}`),this.patternSubs.delete(s)}}publish(e){this._log.trace(`Publishing event: ${e.type}`,e);let t=0;const i=this.directMap.get(e.type);if(i){t+=i.size;for(const s of i)Promise.resolve().then(()=>s.callback(e))}for(const s of this.patternSubs)s.pattern&&s.pattern.test(e.type)&&(t++,Promise.resolve().then(()=>s.callback(e)));t===0?this._log.debug(`No subscribers found for event: ${e.type}`):this._log.trace(`Event ${e.type} dispatched to ${t} subscribers`)}}class K{constructor(e,t,i){n(this,"_engine");n(this,"_physics");n(this,"_log");this._engine=e,this._physics=t,this._log=(i==null?void 0:i.getLogger("SceneEngine"))||new _("SceneEngine")}async _buildDemoScene(e,t){this._log.debug("Building demo scene..."),this._log.trace("Creating camera...");const i=new h.FreeCamera("camera1",new h.Vector3(0,5,-10),e);i.setTarget(h.Vector3.Zero()),i.attachControl(t,!0),this._log.trace("Creating light...");const s=new h.HemisphericLight("light",new h.Vector3(0,1,0),e);s.intensity=.7,this._log.trace("Creating sphere...");const o=h.MeshBuilder.CreateSphere("sphere",{diameter:2,segments:32},e);o.position.y=4,this._log.trace("Creating ground...");const a=h.MeshBuilder.CreateGround("ground",{width:10,height:10},e);this._log.trace("Adding physics to sphere..."),new h.PhysicsAggregate(o,h.PhysicsShapeType.SPHERE,{mass:1,restitution:.75},e),this._log.trace("Adding physics to ground..."),new h.PhysicsAggregate(a,h.PhysicsShapeType.BOX,{mass:0},e),this._log.debug("Demo scene built successfully")}async loadScene(e){this._log.info("Loading scene..."),this._log.time("sceneLoad"),this._log.debug("Creating new scene...");const t=new h.Scene(this._engine);return this._log.debug("Enabling physics with gravity (0, -9.8, 0)..."),t.enablePhysics(new h.Vector3(0,-9.8,0),this._physics),await this._buildDemoScene(t,e),this._log.timeEnd("sceneLoad"),this._log.info("Scene loaded successfully"),t}}const k=["trigger","toggle","value"];class U{constructor(e,t,i,s={}){n(this,"type","trigger");n(this,"action");n(this,"context");n(this,"deviceID");n(this,"reader");n(this,"_edgeMode");n(this,"_threshold");n(this,"_lastDigitalState",!1);this.action=e,this.deviceID=t,this.reader=i,this.context=s.context,this._edgeMode=s.edgeMode??"rising",this._threshold=s.threshold??.5}get options(){return{edgeMode:this._edgeMode,threshold:this._threshold}}process(e,t){const i=this.reader.getValue(e)??!1,s=typeof i=="boolean"?i:i>=this._threshold;let o=!1;switch(this._edgeMode){case"rising":o=s&&!this._lastDigitalState;break;case"falling":o=!s&&this._lastDigitalState;break;case"both":o=s!==this._lastDigitalState;break}if(this._lastDigitalState=s,o){let a;if(this.action.type==="analog"){let d=typeof i=="number"?i:i?1:0;if(this.action.minValue!==void 0||this.action.maxValue!==void 0){const l=this.action.minValue??0,f=this.action.maxValue??1;d=l+d*(f-l)}a=d}else a=!0;const r={type:`action:${this.action.name}`,payload:{value:a,deviceId:this.deviceID,context:this.context}};t.publish(r)}}toJSON(){return{type:this.type,action:this.action.name,input:{deviceID:this.deviceID,...this.reader.toJSON()},context:this.context,options:this.options}}}class R{constructor(e,t,i,s={}){n(this,"type","toggle");n(this,"action");n(this,"context");n(this,"deviceID");n(this,"reader");n(this,"_invert");n(this,"_threshold");n(this,"_initialState");n(this,"_onValue");n(this,"_offValue");n(this,"_lastDigitalState",!1);n(this,"_toggleState");this.action=e,this.deviceID=t,this.reader=i,this.context=s.context,this._invert=s.invert??!1,this._threshold=s.threshold??.5,this._initialState=s.initialState??!1,this._toggleState=this._initialState,this._onValue=s.onValue??!0,this._offValue=s.offValue??!1}get state(){return this._toggleState}set state(e){this._toggleState=e}get onValue(){return this._onValue}get offValue(){return this._offValue}get value(){return this.action.type==="analog"?this._toggleState?this.action.maxValue??1:this.action.minValue??0:this._toggleState?this._onValue:this._offValue}get options(){return{invert:this._invert,threshold:this._threshold,initialState:this._initialState,onValue:this._onValue,offValue:this._offValue}}process(e,t){const i=this.reader.getValue(e)??!1,s=typeof i=="boolean"?i:i>=this._threshold,o=this._invert?!s&&this._lastDigitalState:s&&!this._lastDigitalState;this._lastDigitalState=s,o&&(this._toggleState=!this._toggleState,t.publish({type:`action:${this.action.name}`,payload:{value:this.value,deviceId:this.deviceID,context:this.context}}))}reset(){this._toggleState=this._initialState}toJSON(){return{type:this.type,action:this.action.name,input:{deviceID:this.deviceID,...this.reader.toJSON()},state:this._toggleState,context:this.context,options:this.options}}}class T{constructor(e,t,i,s={}){n(this,"type","value");n(this,"action");n(this,"context");n(this,"deviceID");n(this,"reader");n(this,"_scale");n(this,"_offset");n(this,"_invert");n(this,"_emitOnChange");n(this,"_deadzone");n(this,"_onValue");n(this,"_offValue");n(this,"_min");n(this,"_max");n(this,"_lastValue");this.action=e,this.deviceID=t,this.reader=i,this.context=s.context,this._scale=s.scale??1,this._offset=s.offset??0,this._invert=s.invert??!1,this._emitOnChange=s.emitOnChange??!0,this._deadzone=s.deadzone??0,this._onValue=s.onValue??!0,this._offValue=s.offValue??!1;const o=this.action.type==="analog"?this.action.minValue??Number.NEGATIVE_INFINITY:Number.NEGATIVE_INFINITY;this._min=s.min??o;const a=this.action.type==="analog"?this.action.maxValue??Number.POSITIVE_INFINITY:Number.POSITIVE_INFINITY;this._max=s.max??a}get options(){return{scale:this._scale,offset:this._offset,invert:this._invert,emitOnChange:this._emitOnChange,deadzone:this._deadzone,onValue:this._onValue,offValue:this._offValue,min:this._min,max:this._max}}process(e,t){const i=this.reader.getValue(e);if(i===void 0)return;const s=typeof i=="boolean"?i?1:0:i;if(s===void 0)return;let o=this._deadzone>0&&Math.abs(s)<this._deadzone?0:s;o=(this._invert?-o:o)*this._scale+this._offset,o=Math.max(this._min,Math.min(this._max,o)),!(this._emitOnChange&&this._lastValue===o)&&(this._lastValue=o,t.publish({type:`action:${this.action.name}`,payload:{value:o,deviceId:this.deviceID,context:this.context}}))}toJSON(){return{type:this.type,action:this.action.name,input:{deviceID:this.deviceID,...this.reader.toJSON()},context:this.context,options:this.options}}}class S{constructor(e,t={}){n(this,"sourceType","key");n(this,"sourceKey");n(this,"useDelta");this.sourceKey=e,this.useDelta=t.useDelta||!1}getValue(e){if(e.type!=="keyboard")return;const t=e;return this.useDelta?t.delta[this.sourceKey]:t.keys[this.sourceKey]}static fromString(e,t={}){return new S(e,t)}toJSON(){return{type:"keyboard",sourceType:this.sourceType,sourceKey:this.sourceKey,options:{useDelta:this.useDelta}}}}class x{constructor(e,t){n(this,"sourceType");n(this,"sourceKey");this.sourceType=e,this.sourceKey=t}getValue(e){if(e.type==="mouse")switch(this.sourceType){case"button":{const t=e.buttons[this.sourceKey];return t?t.pressed:void 0}case"position":{const[t,i]=this.sourceKey.split(":");return!t||!i||t!=="absolute"&&t!=="relative"||i!=="x"&&i!=="y"?void 0:e.position[t][i]}case"wheel":{const t=this.sourceKey==="deltaX"||this.sourceKey==="deltaY"||this.sourceKey==="deltaZ";return e.wheel&&t?e.wheel[this.sourceKey]:void 0}default:return}}static fromString(e){const[t,...i]=e.split(":"),s=i.join(":");if(!t||!s)throw new Error(`Invalid mouse source format: ${e}`);return new x(t,s)}toJSON(){return{type:"mouse",sourceType:this.sourceType,sourceKey:this.sourceKey}}}class E{constructor(e,t,i={}){n(this,"sourceType");n(this,"sourceKey");n(this,"useAnalogValue");n(this,"deadzone");n(this,"invert");this.sourceType=e,this.sourceKey=t,this.useAnalogValue=i.useAnalogValue||!1,this.deadzone=i.deadzone||.1,this.invert=i.invert||!1}getValue(e){if(e.type==="gamepad")switch(this.sourceType){case"button":{const t=e.buttons[this.sourceKey];return t?this.useAnalogValue?t.value:t.pressed:void 0}case"axis":{let t=e.axes[this.sourceKey];return t===void 0?void 0:(Math.abs(t)<this.deadzone&&(t=0),this.invert?-t:t)}default:return}}static fromString(e,t={}){const[i,s]=e.split(":");if(!i||!s)throw new Error(`Invalid gamepad source format: ${e}`);return new E(i,s,t)}toJSON(){return{type:"gamepad",sourceType:this.sourceType,sourceKey:this.sourceKey,options:{useAnalogValue:this.useAnalogValue,deadzone:this.deadzone,invert:this.invert}}}}class z{constructor(e,t){n(this,"_bindings",new Map);n(this,"_actions",new Map);n(this,"_contexts",new Map);n(this,"_activeContexts",new Set);n(this,"_eventBus");n(this,"_log");this._eventBus=e,this._eventBus.subscribe("input:changed",i=>{i.payload&&this.$handleInput(i.payload.device,i.payload.state)}),this._log=(t==null?void 0:t.getLogger("BindingManager"))||new _("BindingManager"),this._log.debug("BindingManager initialized")}_isBindingContextActive(e){return e.context?this._activeContexts.has(e.context):!0}_getOrCreateContext(e,t=!0){let i=this._contexts.get(e);return i||(i={name:e,exclusive:t},this._contexts.set(e,i),this._log.debug(`Auto-created context "${e}" (exclusive: ${t})`)),i}_deactivateExclusiveContexts(e){const t=[];for(const i of this._activeContexts){if(i===e)continue;const s=this._contexts.get(i);s!=null&&s.exclusive&&(this._activeContexts.delete(i),t.push(i))}return t}_createBindingFromDefinition(e){const t=this._actions.get(e.action);if(!t)return this._log.warn(`Cannot create binding: Action "${e.action}" not found.`),null;const{deviceID:i,...s}=e.input;switch(e.type){case"trigger":return new U(t,i,this._createInputSourceFromDefinition(s),{...e.options||{},context:e.context});case"toggle":return new R(t,i,this._createInputSourceFromDefinition(s),{...e.options||{},context:e.context});case"value":return new T(t,i,this._createInputSourceFromDefinition(s),{...e.options||{},context:e.context});default:return this._log.error(`Binding type not implemented: ${e.type}`),null}}_createInputSourceFromDefinition(e){switch(e.type){case"keyboard":return new S(e.sourceKey,e.options);case"mouse":{const t=e.sourceType;if(!(t==="button"||t==="position"||t==="wheel"))throw new Error(`Invalid mouse source type: ${t}`);return new x(t,e.sourceKey)}case"gamepad":{const t=e.sourceType;if(!(t==="button"||t==="axis"))throw new Error(`Invalid gamepad source type: ${t}`);return new E(t,e.sourceKey,e.options)}default:throw new Error(`Unsupported input source type: ${e.type}`)}}$handleInput(e,t){const i=this._bindings.get(e.id);if(!(!i||i.length===0)&&!(this._activeContexts.size===0&&i.some(s=>s.context)))for(const s of i)this._isBindingContextActive(s)&&s.process(t,this._eventBus)}registerAction(e){if(this._log.debug(`Registering action "${e.name}"`),this._actions.has(e.name)){const t=`Action "${e.name}" already registered.`;throw this._log.error(t),new Error(t)}this._actions.set(e.name,e),this._log.debug(`Action "${e.name}" registered successfully`)}getAction(e){this._log.trace(`Getting action "${e}"`);const t=this._actions.get(e)??null;return t||this._log.debug(`Action "${e}" not found`),t}registerContext(e,t=!0){const i=this._getOrCreateContext(e,t);return i.exclusive!==t&&(i.exclusive=t,this._log.info(`Updated context "${e}" exclusivity: ${t}`)),i}activateContext(e){const i=this._getOrCreateContext(e).exclusive;this._log.debug(`Activating context "${e}" (exclusive: ${i})`);const s=this._activeContexts.has(e);if(i){const o=this._deactivateExclusiveContexts(e);o.length>0&&this._log.info(`Deactivated exclusive contexts: ${o.join(", ")}`)}s||(this._activeContexts.add(e),this._log.info(`Context "${e}" activated${i?" as exclusive":""}`))}deactivateContext(e){this._log.debug(`Deactivating context "${e}"`),this._activeContexts.has(e)?(this._activeContexts.delete(e),this._log.info(`Context "${e}" deactivated`)):this._log.debug(`Context "${e}" was not active`)}getActiveContexts(){return[...this._activeContexts]}isContextActive(e){return this._activeContexts.has(e)}getContext(e){return this._contexts.get(e)||null}$registerBinding(e){var t;if(!k.includes(e.type))throw new Error(`Invalid binding type: ${e.type}`);e.context&&!this._contexts.has(e.context)&&this.registerContext(e.context),this._bindings.has(e.deviceID)||this._bindings.set(e.deviceID,[]),(t=this._bindings.get(e.deviceID))==null||t.push(e),this._log.debug(`Registered ${e.type} binding for "${e.action.name}" in context "${e.context||null}"`)}registerBinding(e){const t=this._createBindingFromDefinition(e);t?this.$registerBinding(t):this._log.error(`Failed to create binding for action "${e.action}" with type "${e.type}"`)}unregisterBindings(e,t=null){this._log.debug(`Unregistering all bindings for action "${e}" in context "${t}"`);let i=0;for(const[s,o]of this._bindings.entries()){const a=o.filter(r=>{const d=r.context||null,l=r.action.name!==e||d!==t;return l||i++,l});a.length!==o.length&&this._bindings.set(s,a)}this._log.info(`Removed ${i} bindings for action "${e}" in context "${t}"`)}getBindingsForAction(e,t){const i=[];for(const s of this._bindings.values())for(const o of s){const a=o.context||null;o.action.name===e&&(!t||a===t)&&i.push(o)}return i}exportConfiguration(){this._log.debug("Exporting binding configuration");const e=[...this._actions.values()].map(s=>s.type==="analog"?{name:s.name,type:s.type,minValue:s.minValue??0,maxValue:s.maxValue??1}:s),t=[];for(const s of this._bindings.values())for(const o of s)t.push(o.toJSON());const i=[...this._contexts.values()].map(s=>({name:s.name,exclusive:s.exclusive,active:this._activeContexts.has(s.name)}));return this._log.info(`Configuration exported: ${e.length} actions, ${t.length} bindings, ${i.length} contexts`),{actions:e,bindings:t,contexts:i}}importConfiguration(e){this._log.debug("Importing binding configuration"),this._bindings.clear(),this._actions.clear(),this._contexts.clear(),this._activeContexts.clear();for(const t of e.actions)this.registerAction(t);for(const t of e.contexts)this.registerContext(t.name,t.exclusive),t.active&&this.activateContext(t.name);for(const t of e.bindings)try{this.registerBinding(t)}catch(i){i instanceof Error&&this._log.error(`Failed to import binding for action "${t.action}": ${i.message}`)}this._log.info(`Configuration imported: ${e.actions.length} actions, ${e.bindings.length} bindings, ${e.contexts.length} contexts`)}}function G(){return typeof window<"u"&&typeof window.document<"u"}function V(){return G()&&!!window.navigator.gpu}class P{constructor(e,t,i,s,o){n(this,"_engine");n(this,"_entityManager");n(this,"_inputManager");n(this,"_sceneEngine");n(this,"_currentScene",null);n(this,"_log");n(this,"started",!1);this._engine=e,this._sceneEngine=t,this._entityManager=i,this._inputManager=s,this._log=(o==null?void 0:o.getLogger("GameManager"))||new _("GameManager"),G()&&window.addEventListener("resize",this._resizeHandler.bind(this))}_renderLoop(){const e=this._engine.getDeltaTime();this._entityManager.$frameUpdate(e),this._inputManager&&this._inputManager.pollGamepads(),this._currentScene&&this._currentScene.render()}_resizeHandler(){this.started&&this._engine.resize()}async start(e){this._currentScene=await this._sceneEngine.loadScene(e),this._engine.runRenderLoop(this._renderLoop.bind(this)),this.started=!0,this._log.info("SkewedAspect Game Engine started successfully")}async stop(){this.started=!1,this._engine.stopRenderLoop(),this._log.info("SkewedAspect Game Engine stopped successfully")}}class W{constructor(){n(this,"entity",null)}$emit(e){if(!this.entity)throw new Error("Entity is not set for this behavior.");e.senderID=this.entity.id,this.entity.eventBus.publish(e)}$setEntity(e){this.entity=e}}class L{constructor(e,t,i,s){n(this,"id");n(this,"type");n(this,"state");n(this,"behaviors",new Map);n(this,"eventBus");n(this,"subscriptions",new Map);this.id=crypto.randomUUID(),this.type=e,this.state=i,this.eventBus=t;for(const o of s)this.attachBehavior(new o)}async $processEvent(e){for(const t of this.behaviors.values())if(await t.processEvent(e,this.state))break}$update(e){var t;for(const i of this.behaviors.values())(t=i.update)==null||t.call(i,e,this.state)}async $destroy(){var e;for(const t of this.behaviors.values())(e=t.destroy)==null||e.call(t);for(const t of this.subscriptions.values())t.unsubscribe();this.behaviors.clear(),this.subscriptions.clear()}attachBehavior(e){if(this.behaviors.has(e.name))throw new Error(`Behavior ${e.name} is already attached to this entity.`);for(const t of e.eventSubscriptions){const i=this.subscriptions.get(t);if(i)i.count++;else{const s=this.eventBus.subscribe(t,this.$processEvent.bind(this));this.subscriptions.set(t,{count:1,unsubscribe:s})}}this.behaviors.set(e.name,e),e.$setEntity(this)}detachBehavior(e){const t=this.behaviors.get(e);if(t){for(const i of t.eventSubscriptions){const s=this.subscriptions.get(i);s&&(s.count--,s.count<=0&&(s.unsubscribe(),this.subscriptions.delete(i)))}this.behaviors.delete(t.name),t.$setEntity(null)}}}class O{constructor(e,t,i){n(this,"eventBus");n(this,"entities",new Map);n(this,"entityDefinitions",new Map);n(this,"bindingManager");n(this,"_log");this.eventBus=e,this.bindingManager=i,this._log=(t==null?void 0:t.getLogger("EntityManager"))||new _("EntityManager"),this._log.info("EntityManager initialized")}_areActionsCompatible(e,t){return!(e.type!==t.type||e.type==="analog"&&t.type==="analog"&&(t.minValue!==void 0&&e.minValue!==t.minValue||t.maxValue!==void 0&&e.maxValue!==t.maxValue))}_registerEntityActions(e){if(e.actions)for(const t of e.actions)try{const i=this.bindingManager.getAction(t.name);i?this._areActionsCompatible(i,t)?this._log.trace(`Action "${t.name}" already registered with compatible options, skipping registration`):this._log.warn(`Action "${t.name}" already registered with different options. Entity "${e.type}" requires: ${JSON.stringify(t)}, but found: ${JSON.stringify(i)}`):(this._log.debug(`Registering action "${t.name}" from entity type "${e.type}"`),this.bindingManager.registerAction(t))}catch(i){this._log.debug(`Failed to register action "${t.name}": ${i instanceof Error?i.message:String(i)}`)}}$frameUpdate(e){this._log.trace(`Updating ${this.entities.size} entities with dt=${e}`);for(const t of this.entities.values())t.$update(e)}registerEntityDefinition(e){this._log.debug(`Registering entity definition: ${e.type}`),this._registerEntityActions(e),this.entityDefinitions.set(e.type,e)}createEntity(e,t={}){var a;this._log.debug(`Creating entity of type: ${e}`);const i=this.entityDefinitions.get(e);if(!i){const r=`Entity type ${e} is not registered.`;throw this._log.error(r),new Error(r)}this._log.trace(`Using entity definition with ${((a=i.behaviors)==null?void 0:a.length)||0} behaviors`);const s={...i.defaultState,...t},o=new L(i.type,this.eventBus,s,i.behaviors);return this.entities.set(o.id,o),this._log.debug(`Entity created with ID: ${o.id}`),o}destroyEntity(e){this._log.debug(`Destroying entity: ${e}`);const t=this.entities.get(e);t?(t.$destroy(),this.entities.delete(e),this._log.debug(`Entity ${e} destroyed`)):this._log.warn(`Attempted to destroy non-existent entity: ${e}`)}getEntity(e){return this._log.trace(`Getting entity: ${e}`),this.entities.get(e)??null}addEntity(e){this._log.debug(`Adding existing entity: ${e.id} (type: ${e.type})`),this.entities.set(e.id,e)}removeEntity(e){this._log.debug(`Removing entity: ${e}`),this.entities.get(e)?(this.entities.delete(e),this._log.debug(`Entity ${e} removed`)):this._log.warn(`Attempted to remove non-existent entity: ${e}`)}}class F{constructor(){n(this,"_keyboardDevice");n(this,"_keysState",{});n(this,"_onDeviceConnected");n(this,"_onInputChanged");this._keyboardDevice={id:"keyboard-0",name:"Keyboard",type:"keyboard",connected:!0},this._setupKeyboardEvents(),setTimeout(()=>this._notifyDeviceConnected(),0)}onDeviceConnected(e){this._onDeviceConnected=e}onInputChanged(e){this._onInputChanged=e}getState(){return{type:"keyboard",keys:{...this._keysState},delta:{}}}getDevice(){return{...this._keyboardDevice}}destroy(){window.removeEventListener("keydown",this._handleKeyDown),window.removeEventListener("keyup",this._handleKeyUp)}_setupKeyboardEvents(){this._handleKeyDown=this._handleKeyDown.bind(this),this._handleKeyUp=this._handleKeyUp.bind(this),window.addEventListener("keydown",this._handleKeyDown),window.addEventListener("keyup",this._handleKeyUp)}_handleKeyDown(e){this._keysState[e.code]=!0;const t={};t[e.code]=!0;const i={type:"keyboard",keys:{...this._keysState},delta:t,event:e};this._notifyInputChanged(i)}_handleKeyUp(e){this._keysState[e.code]=!1;const t={};t[e.code]=!1;const i={type:"keyboard",keys:{...this._keysState},delta:t,event:e};this._notifyInputChanged(i)}_notifyDeviceConnected(){this._onDeviceConnected&&this._onDeviceConnected(this._keyboardDevice)}_notifyInputChanged(e){this._onInputChanged&&this._onInputChanged(this._keyboardDevice,e)}}class N{constructor(e=document.body){n(this,"_targetElement");n(this,"_mouseDevice");n(this,"_buttonState",{});n(this,"_axesState",{});n(this,"_position",{absolute:{x:0,y:0},relative:{x:0,y:0}});n(this,"_wheelState",{deltaX:0,deltaY:0,deltaZ:0,deltaMode:0});n(this,"_onDeviceConnected");n(this,"_onInputChanged");this._targetElement=e,this._mouseDevice={id:"mouse-0",name:"Mouse",type:"mouse",connected:!0},this._setupMouseEvents(),this._axesState["axis-x"]=0,this._axesState["axis-y"]=0,setTimeout(()=>this._notifyDeviceConnected(),0)}onDeviceConnected(e){this._onDeviceConnected=e}onInputChanged(e){this._onInputChanged=e}getState(){return{type:"mouse",buttons:{...this._buttonState},axes:{...this._axesState},position:{absolute:{...this._position.absolute},relative:{...this._position.relative}},wheel:{...this._wheelState}}}getDevice(){return{...this._mouseDevice}}destroy(){this._targetElement.removeEventListener("mousedown",this._handleMouseDown),this._targetElement.removeEventListener("mouseup",this._handleMouseUp),this._targetElement.removeEventListener("mousemove",this._handleMouseMove),this._targetElement.removeEventListener("wheel",this._handleMouseWheel)}_setupMouseEvents(){this._handleMouseDown=this._handleMouseDown.bind(this),this._handleMouseUp=this._handleMouseUp.bind(this),this._handleMouseMove=this._handleMouseMove.bind(this),this._handleMouseWheel=this._handleMouseWheel.bind(this),this._targetElement.addEventListener("mousedown",this._handleMouseDown),this._targetElement.addEventListener("mouseup",this._handleMouseUp),this._targetElement.addEventListener("mousemove",this._handleMouseMove),this._targetElement.addEventListener("wheel",this._handleMouseWheel)}_handleMouseDown(e){const t=`button-${e.button}`,i={pressed:!0};this._buttonState[t]=i,this._notifyInputChanged({type:"mouse",event:e,buttons:{...this._buttonState},axes:{...this._axesState},position:{...this._position}})}_handleMouseUp(e){const t=`button-${e.button}`,i={pressed:!1};this._buttonState[t]=i,this._notifyInputChanged({type:"mouse",event:e,buttons:{...this._buttonState},axes:{...this._axesState},position:{...this._position}})}_handleMouseMove(e){this._position={absolute:{x:e.clientX,y:e.clientY},relative:{x:e.movementX,y:e.movementY}},this._axesState["axis-x"]=e.clientX,this._axesState["axis-y"]=e.clientY,this._notifyInputChanged({type:"mouse",event:e,buttons:{...this._buttonState},axes:{...this._axesState},position:{...this._position}})}_handleMouseWheel(e){this._wheelState={deltaX:e.deltaX,deltaY:e.deltaY,deltaZ:e.deltaZ,deltaMode:e.deltaMode},this._notifyInputChanged({type:"mouse",event:e,buttons:{...this._buttonState},axes:{...this._axesState},position:{...this._position},wheel:{...this._wheelState}})}_notifyDeviceConnected(){this._onDeviceConnected&&this._onDeviceConnected(this._mouseDevice)}_notifyInputChanged(e){this._onInputChanged&&this._onInputChanged(this._mouseDevice,e)}}class j{constructor(){n(this,"_gamepadDevices",{});n(this,"_buttonStates",{});n(this,"_axesStates",{});n(this,"_onDeviceConnected");n(this,"_onDeviceDisconnected");n(this,"_onInputChanged");this._setupGamepadEvents()}onDeviceConnected(e){this._onDeviceConnected=e}onDeviceDisconnected(e){this._onDeviceDisconnected=e}onInputChanged(e){this._onInputChanged=e}getDevices(){return Object.values(this._gamepadDevices).map(e=>({...e}))}getStates(){const e={};return Object.keys(this._buttonStates).forEach(t=>{const i=Number(t),s=this._buttonStates[i]||{},o=this._axesStates[i]||{};e[i]={type:"gamepad",buttons:{...s},axes:{...o}}}),e}getDevice(e){const t=this._gamepadDevices[e];return t?{...t}:null}getState(e){const t=this._buttonStates[e],i=this._axesStates[e];return!t&&!i?null:{type:"gamepad",buttons:t?{...t}:{},axes:i?{...i}:{}}}pollGamepads(){if(!navigator.getGamepads)return;const e=navigator.getGamepads();for(const t of e){if(!t)continue;const i=t.index;if(!this._gamepadDevices[i]){this._handleGamepadConnected(t);continue}const s=this._gamepadDevices[i];if(!s)continue;const o=this._buttonStates[i]||{},a=this._axesStates[i]||{},r={};let d=!1;t.buttons.forEach((g,m)=>{const p=`button-${m}`,v={pressed:g.pressed,touched:g.touched,value:g.value};r[p]=v;const w=o[p];(!w||w.pressed!==v.pressed||w.touched!==v.touched||w.value!==v.value)&&(d=!0)});const l={};let f=!1;if(t.axes.forEach((g,m)=>{const p=`axis-${m}`;l[p]=g,a[p]!==g&&(f=!0)}),this._buttonStates[i]=r,this._axesStates[i]=l,d||f){const g={type:"gamepad",buttons:{...r},axes:{...l}};this._notifyInputChanged(s,g)}}}destroy(){window.removeEventListener("gamepadconnected",this._handleGamepadConnected),window.removeEventListener("gamepaddisconnected",this._handleGamepadDisconnected)}_setupGamepadEvents(){if(this._handleGamepadConnected=this._handleGamepadConnected.bind(this),this._handleGamepadDisconnected=this._handleGamepadDisconnected.bind(this),window.addEventListener("gamepadconnected",this._handleGamepadConnected),window.addEventListener("gamepaddisconnected",this._handleGamepadDisconnected),navigator.getGamepads){const e=navigator.getGamepads();for(const t of e)t&&this._handleGamepadConnected(t)}}_handleGamepadConnected(e){const t=e instanceof GamepadEvent?e.gamepad:e,i=t.index,s={id:`gamepad-${i}`,name:t.id,type:"gamepad",connected:!0,index:i,mapping:t.mapping,axes:Array.from(t.axes),buttons:Array.from(t.buttons)};this._gamepadDevices[i]=s;const o={};Array.from(t.buttons).forEach((r,d)=>{o[`button-${d}`]={pressed:r.pressed,touched:r.touched,value:r.value}}),this._buttonStates[i]=o;const a={};Array.from(t.axes).forEach((r,d)=>{a[`axis-${d}`]=r}),this._axesStates[i]=a,this._notifyDeviceConnected(s),this._notifyInputChanged(s,{type:"gamepad",buttons:{...o},axes:{...a},event:e instanceof GamepadEvent?e:void 0})}_handleGamepadDisconnected(e){const i=e.gamepad.index,s=this._gamepadDevices[i];s&&(s.connected=!1,this._notifyDeviceDisconnected(s),this._gamepadDevices[i]=void 0,this._buttonStates[i]=void 0,this._axesStates[i]=void 0)}_notifyDeviceConnected(e){this._onDeviceConnected&&this._onDeviceConnected(e)}_notifyDeviceDisconnected(e){this._onDeviceDisconnected&&this._onDeviceDisconnected(e)}_notifyInputChanged(e,t){this._onInputChanged&&this._onInputChanged(e,t)}}class J{constructor(e,t,i){n(this,"_eventBus");n(this,"_keyboardRA");n(this,"_mouseRA");n(this,"_gamepadRA");n(this,"_log");this._eventBus=e,this._log=(i==null?void 0:i.getLogger("UserInputManager"))||new _("UserInputManager"),this._log.info("Initializing UserInputManager"),this._log.debug("Initializing input resource access classes"),this._keyboardRA=new F,this._mouseRA=new N(t),this._gamepadRA=new j,this._log.debug("Registering input event callbacks"),this._keyboardRA.onDeviceConnected(this._publishDeviceConnected.bind(this)),this._keyboardRA.onInputChanged(this._publishInputChanged.bind(this)),this._mouseRA.onDeviceConnected(this._publishDeviceConnected.bind(this)),this._mouseRA.onInputChanged(this._publishInputChanged.bind(this)),this._gamepadRA.onDeviceConnected(this._publishDeviceConnected.bind(this)),this._gamepadRA.onDeviceDisconnected(this._publishDeviceDisconnected.bind(this)),this._gamepadRA.onInputChanged(this._publishInputChanged.bind(this)),this._log.info("UserInputManager initialized successfully")}_publishDeviceConnected(e){this._log.debug(`Device connected: ${e.id} (${e.name})`);const t={type:"input:device:connected",payload:{device:e}};this._eventBus.publish(t)}_publishDeviceDisconnected(e){this._log.debug(`Device disconnected: ${e.id} (${e.name})`);const t={type:"input:device:disconnected",payload:{device:e}};this._eventBus.publish(t)}_publishInputChanged(e,t){this._log.trace(`Input changed: ${e.id}`,t);const i={type:"input:changed",payload:{deviceId:e.id,device:e,state:t}};this._eventBus.publish(i)}$destroy(){this._log.info("Destroying UserInputManager"),this._log.debug("Cleaning up input resource access instances"),this._keyboardRA.destroy(),this._mouseRA.destroy(),this._gamepadRA.destroy(),this._log.info("UserInputManager destroyed")}listDevices(){this._log.debug("Getting all connected input devices");const e=[];return e.push(this._keyboardRA.getDevice()),e.push(this._mouseRA.getDevice()),e.push(...this._gamepadRA.getDevices()),this._log.debug(`Found ${e.length} connected devices`),e}getDevice(e){if(this._log.debug(`Getting device: ${e}`),e.startsWith("keyboard-"))return this._keyboardRA.getDevice();if(e.startsWith("mouse-"))return this._mouseRA.getDevice();if(e.startsWith("gamepad-")){const t=parseInt(e.split("-")[1],10);return this._gamepadRA.getDevice(t)}else{const t=this.listDevices();for(const i of t)if(i.id===e)return i}return this._log.warn(`Device not found: ${e}`),null}pollGamepads(){this._gamepadRA.pollGamepads()}}async function B(c,e){const t=new h.WebGPUEngine(c,e);return await t.initAsync(),t}function D(c,e){return new h.Engine(c,e.antialias,e.options,e.adaptToDeviceRatio)}function Y(c){return new h.NullEngine(c)}async function H(c,e){if(c===null)return console.debug("Using Null Engine"),Y(e);const t=e.engine||"auto";if(t==="webgpu")if(V())try{return console.debug("Using forced WebGPU engine"),await B(c,e)}catch(i){throw console.error("Forced WebGPU initialization failed:",i),new Error("Forced WebGPU failed to initialize. If WebGPU is required, check browser compatibility.")}else throw new Error("WebGPU was forced but is not available in this browser.");if(t==="webgl")return console.debug("Using forced WebGL engine"),D(c,e);if(V())try{return console.debug("Using WebGPU"),B(c,e).catch(i=>(console.warn("WebGPU initialization failed, falling back to WebGL:",i),D(c,e)))}catch(i){console.warn("WebGPU initialization failed, falling back to WebGL:",i)}else console.warn("WebGPU not supported, falling back to WebGL.");return console.debug("Using WebGL"),D(c,e)}async function X(){const c=await y();return new h.HavokPlugin(!0,c)}const q=["keyboard","mouse","gamepad"],Z=["trace","debug","info","warn","error","none"];async function Q(c,e,t={}){const i=new A(t.logLevel||"debug"),s=i.getLogger("SAGE");s.info(`Initializing SAGE Game Engine v${b}...`),s.debug("Creating rendering engine...");const o=await H(c,t.renderOptions||{});s.debug("Creating physics engine...");const a=await X();s.debug("Creating event bus...");const r=new I(i);s.debug("Creating scene engine...");const d=new K(o,a,i);s.debug("Creating managers...");const l=new J(r,c,i),f=new z(r,i),g=new O(r,i,f),m=new P(o,d,g,l,i);s.info(`SAGE Game Engine v${b} initialized successfully.`),s.debug("Loading entities...");for(const p of e)g.registerEntityDefinition(p);if(s.debug("Registering default input bindings..."),t.bindings)for(const p of t.bindings)f.registerBinding(p);return new C(c,o,a,r,i,{sceneEngine:d},{bindingManager:f,entityManager:g,gameManager:m,inputManager:l})}u.ConsoleBackend=$,u.GameEntity=L,u.GameEntityBehavior=W,u.GameEventBus=I,u.LogLevels=Z,u.LoggingUtility=A,u.NullBackend=M,u.SAGELogger=_,u.SkewedAspectGameEngine=C,u.VERSION=b,u.bindingTypes=k,u.createGameEngine=Q,u.validDeviceTypes=q,Object.defineProperty(u,Symbol.toStringTag,{value:"Module"})});
|
|
2
2
|
//# sourceMappingURL=sage.umd.js.map
|