ecspresso 0.12.4 → 0.12.7

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.
Files changed (36) hide show
  1. package/dist/ecspresso-builder.d.ts +1 -3
  2. package/dist/index.js +2 -2
  3. package/dist/index.js.map +6 -6
  4. package/dist/plugins/audio.js +2 -2
  5. package/dist/plugins/audio.js.map +2 -2
  6. package/dist/plugins/bounds.js +2 -2
  7. package/dist/plugins/bounds.js.map +2 -2
  8. package/dist/plugins/camera.js +2 -2
  9. package/dist/plugins/camera.js.map +2 -2
  10. package/dist/plugins/collision.js +2 -2
  11. package/dist/plugins/collision.js.map +2 -2
  12. package/dist/plugins/coroutine.js +2 -2
  13. package/dist/plugins/coroutine.js.map +2 -2
  14. package/dist/plugins/diagnostics.js +3 -3
  15. package/dist/plugins/diagnostics.js.map +2 -2
  16. package/dist/plugins/input.js +2 -2
  17. package/dist/plugins/input.js.map +2 -2
  18. package/dist/plugins/particles.js +2 -2
  19. package/dist/plugins/particles.js.map +2 -2
  20. package/dist/plugins/physics2D.js +2 -2
  21. package/dist/plugins/physics2D.js.map +2 -2
  22. package/dist/plugins/renderers/renderer2D.js +2 -2
  23. package/dist/plugins/renderers/renderer2D.js.map +2 -2
  24. package/dist/plugins/spatial-index.js +2 -2
  25. package/dist/plugins/spatial-index.js.map +2 -2
  26. package/dist/plugins/sprite-animation.js +2 -2
  27. package/dist/plugins/sprite-animation.js.map +2 -2
  28. package/dist/plugins/state-machine.js +2 -2
  29. package/dist/plugins/state-machine.js.map +2 -2
  30. package/dist/plugins/timers.js +2 -2
  31. package/dist/plugins/timers.js.map +2 -2
  32. package/dist/plugins/transform.js +2 -2
  33. package/dist/plugins/transform.js.map +2 -2
  34. package/dist/plugins/tween.js +2 -2
  35. package/dist/plugins/tween.js.map +2 -2
  36. package/package.json +5 -4
@@ -1,4 +1,4 @@
1
- var{defineProperty:B,getOwnPropertyNames:A,getOwnPropertyDescriptor:D}=Object,R=Object.prototype.hasOwnProperty;function v(q){return this[q]}var y=(q)=>{var C=(L??=new WeakMap).get(q),Q;if(C)return C;if(C=B({},"__esModule",{value:!0}),q&&typeof q==="object"||typeof q==="function"){for(var V of A(q))if(!R.call(C,V))B(C,V,{get:v.bind(q,V),enumerable:!(Q=D(q,V))||Q.enumerable})}return L.set(q,C),C},L;var P=(q)=>q;function S(q,C){this[q]=P.bind(null,C)}var l=(q,C)=>{for(var Q in C)B(q,Q,{get:C[Q],enumerable:!0,configurable:!0,set:S.bind(C,Q)})};var h=(q,C)=>()=>(q&&(C=q(q=0)),C);var d=((q)=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(q,{get:(C,Q)=>(typeof require<"u"?require:C)[Q]}):q)(function(q){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+q+'" is not supported')});import{definePlugin as _}from"ecspresso";function i(q){return q}function b(){return{keysDown:new Set,keysPressed:[],keysReleased:[],buttonsDown:new Set,buttonsPressed:[],buttonsReleased:[],pointerX:0,pointerY:0,pointerDeltaX:0,pointerDeltaY:0,lastPointerX:0,lastPointerY:0,pointerMoved:!1}}var K=new Set,F=new Set;function k(){return{keysDown:K,keysPressed:K,keysReleased:K,buttonsDown:F,buttonsPressed:F,buttonsReleased:F,pointerX:0,pointerY:0,pointerDeltaX:0,pointerDeltaY:0,actionsActive:K,prevActionsActive:K}}function E(q,C,Q){let V=new Set;for(let[$,Z]of Object.entries(q)){let O=Z.keys?.some((W)=>C.has(W))??!1,J=Z.buttons?.some((W)=>Q.has(W))??!1;if(O||J)V.add($)}return V}function M(q,C,Q){let V=new Set(q.keysDown),$=new Set(q.keysPressed),Z=new Set(q.keysReleased),O=new Set(q.buttonsDown),J=new Set(q.buttonsPressed),W=new Set(q.buttonsReleased),f=q.pointerMoved?q.pointerX-q.lastPointerX:0,j=q.pointerMoved?q.pointerY-q.lastPointerY:0,x=E(Q,V,O),m={keysDown:V,keysPressed:$,keysReleased:Z,buttonsDown:O,buttonsPressed:J,buttonsReleased:W,pointerX:q.pointerX,pointerY:q.pointerY,pointerDeltaX:f,pointerDeltaY:j,actionsActive:x,prevActionsActive:C};return q.keysPressed=[],q.keysReleased=[],q.buttonsPressed=[],q.buttonsReleased=[],q.lastPointerX=q.pointerX,q.lastPointerY=q.pointerY,q.pointerMoved=!1,m}function w(q){let{systemGroup:C="input",priority:Q=100,phase:V="preUpdate",actions:$={},target:Z=globalThis}=q??{},O=b(),J=k(),W={...$},f=[],j={x:0,y:0},x={x:0,y:0},G={keyboard:{isDown:(z)=>J.keysDown.has(z),justPressed:(z)=>J.keysPressed.has(z),justReleased:(z)=>J.keysReleased.has(z)},pointer:{position:j,delta:x,isDown:(z)=>J.buttonsDown.has(z),justPressed:(z)=>J.buttonsPressed.has(z),justReleased:(z)=>J.buttonsReleased.has(z)},actions:{isActive:(z)=>J.actionsActive.has(z),justActivated:(z)=>J.actionsActive.has(z)&&!J.prevActionsActive.has(z),justDeactivated:(z)=>!J.actionsActive.has(z)&&J.prevActionsActive.has(z)},setActionMap(z){W={...z}},getActionMap(){return{...W}}};function I(z){let H=z;if(H.repeat)return;O.keysDown.add(H.key),O.keysPressed.push(H.key)}function U(z){let H=z;O.keysDown.delete(H.key),O.keysReleased.push(H.key)}function g(z){let H=z;O.buttonsDown.add(H.button),O.buttonsPressed.push(H.button)}function N(z){let H=z;O.pointerX=H.clientX,O.pointerY=H.clientY,O.pointerMoved=!0}function Y(z){let H=z;O.buttonsDown.delete(H.button),O.buttonsReleased.push(H.button)}function X(z,H){Z.addEventListener(z,H),f.push(()=>{Z.removeEventListener(z,H)})}return _({id:"input",install(z){z.addResource("inputState",G),z.addSystem("input-state").setPriority(Q).inPhase(V).inGroup(C).setOnInitialize(()=>{X("keydown",I),X("keyup",U),X("pointerdown",g),X("pointermove",N),X("pointerup",Y)}).setOnDetach(()=>{for(let H of f)H();f.length=0}).setProcess(()=>{let H=J.actionsActive;J=M(O,H,W),j.x=J.pointerX,j.y=J.pointerY,x.x=J.pointerDeltaX,x.y=J.pointerDeltaY})}})}export{w as createInputPlugin,i as createActionBinding};
1
+ var S=((z)=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(z,{get:(Q,V)=>(typeof require<"u"?require:Q)[V]}):z)(function(z){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+z+'" is not supported')});import{definePlugin as N}from"ecspresso";function k(z){return z}function Y(){return{keysDown:new Set,keysPressed:[],keysReleased:[],buttonsDown:new Set,buttonsPressed:[],buttonsReleased:[],pointerX:0,pointerY:0,pointerDeltaX:0,pointerDeltaY:0,lastPointerX:0,lastPointerY:0,pointerMoved:!1}}var K=new Set,B=new Set;function A(){return{keysDown:K,keysPressed:K,keysReleased:K,buttonsDown:B,buttonsPressed:B,buttonsReleased:B,pointerX:0,pointerY:0,pointerDeltaX:0,pointerDeltaY:0,actionsActive:K,prevActionsActive:K}}function D(z,Q,V){let W=new Set;for(let[$,Z]of Object.entries(z)){let J=Z.keys?.some((O)=>Q.has(O))??!1,H=Z.buttons?.some((O)=>V.has(O))??!1;if(J||H)W.add($)}return W}function R(z,Q,V){let W=new Set(z.keysDown),$=new Set(z.keysPressed),Z=new Set(z.keysReleased),J=new Set(z.buttonsDown),H=new Set(z.buttonsPressed),O=new Set(z.buttonsReleased),f=z.pointerMoved?z.pointerX-z.lastPointerX:0,j=z.pointerMoved?z.pointerY-z.lastPointerY:0,x=D(V,W,J),F={keysDown:W,keysPressed:$,keysReleased:Z,buttonsDown:J,buttonsPressed:H,buttonsReleased:O,pointerX:z.pointerX,pointerY:z.pointerY,pointerDeltaX:f,pointerDeltaY:j,actionsActive:x,prevActionsActive:Q};return z.keysPressed=[],z.keysReleased=[],z.buttonsPressed=[],z.buttonsReleased=[],z.lastPointerX=z.pointerX,z.lastPointerY=z.pointerY,z.pointerMoved=!1,F}function E(z){let{systemGroup:Q="input",priority:V=100,phase:W="preUpdate",actions:$={},target:Z=globalThis}=z??{},J=Y(),H=A(),O={...$},f=[],j={x:0,y:0},x={x:0,y:0},m={keyboard:{isDown:(q)=>H.keysDown.has(q),justPressed:(q)=>H.keysPressed.has(q),justReleased:(q)=>H.keysReleased.has(q)},pointer:{position:j,delta:x,isDown:(q)=>H.buttonsDown.has(q),justPressed:(q)=>H.buttonsPressed.has(q),justReleased:(q)=>H.buttonsReleased.has(q)},actions:{isActive:(q)=>H.actionsActive.has(q),justActivated:(q)=>H.actionsActive.has(q)&&!H.prevActionsActive.has(q),justDeactivated:(q)=>!H.actionsActive.has(q)&&H.prevActionsActive.has(q)},setActionMap(q){O={...q}},getActionMap(){return{...O}}};function L(q){let C=q;if(C.repeat)return;J.keysDown.add(C.key),J.keysPressed.push(C.key)}function G(q){let C=q;J.keysDown.delete(C.key),J.keysReleased.push(C.key)}function I(q){let C=q;J.buttonsDown.add(C.button),J.buttonsPressed.push(C.button)}function U(q){let C=q;J.pointerX=C.clientX,J.pointerY=C.clientY,J.pointerMoved=!0}function g(q){let C=q;J.buttonsDown.delete(C.button),J.buttonsReleased.push(C.button)}function X(q,C){Z.addEventListener(q,C),f.push(()=>{Z.removeEventListener(q,C)})}return N({id:"input",install(q){q.addResource("inputState",m),q.addSystem("input-state").setPriority(V).inPhase(W).inGroup(Q).setOnInitialize(()=>{X("keydown",L),X("keyup",G),X("pointerdown",I),X("pointermove",U),X("pointerup",g)}).setOnDetach(()=>{for(let C of f)C();f.length=0}).setProcess(()=>{let C=H.actionsActive;H=R(J,C,O),j.x=H.pointerX,j.y=H.pointerY,x.x=H.pointerDeltaX,x.y=H.pointerDeltaY})}})}export{E as createInputPlugin,k as createActionBinding};
2
2
 
3
- //# debugId=AA1CB6B40EFAD7D764756E2164756E21
3
+ //# debugId=513EE3E4CA561E4664756E2164756E21
4
4
  //# sourceMappingURL=input.js.map
@@ -4,7 +4,7 @@
4
4
  "sourcesContent": [
5
5
  "/**\n * Input Plugin for ECSpresso\n *\n * Provides frame-accurate keyboard, pointer (mouse + touch via PointerEvent),\n * and action mapping input. Resource-only plugin — input is polled via the\n * `inputState` resource. No ECS components or events.\n *\n * DOM events are accumulated between frames and snapshotted once per frame\n * in the system's process step, so all systems see consistent state.\n */\n\nimport { definePlugin, type Plugin, type BasePluginOptions } from 'ecspresso';\nimport type { WorldConfigFrom, EmptyConfig } from '../type-utils';\n\n// ==================== Public Types ====================\n\nexport interface Vec2 {\n\tx: number;\n\ty: number;\n}\n\n// Key codes per the UI Events spec (KeyboardEvent.key values)\n// https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values\n\ntype LowercaseLetter =\n\t| 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' | 'k' | 'l' | 'm'\n\t| 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z';\n\ntype Digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9';\n\ntype Punctuation =\n\t| '`' | '~' | '!' | '@' | '#' | '$' | '%' | '^' | '&' | '*' | '(' | ')'\n\t| '-' | '_' | '=' | '+' | '[' | '{' | ']' | '}' | '\\\\' | '|'\n\t| ';' | ':' | \"'\" | '\"' | ',' | '<' | '.' | '>' | '/' | '?';\n\ntype ModifierKey =\n\t| 'Alt' | 'AltGraph' | 'CapsLock' | 'Control' | 'Fn' | 'FnLock'\n\t| 'Hyper' | 'Meta' | 'NumLock' | 'ScrollLock' | 'Shift'\n\t| 'Super' | 'Symbol' | 'SymbolLock';\n\ntype WhitespaceKey = 'Enter' | 'Tab' | ' ';\n\ntype NavigationKey =\n\t| `Arrow${'Down' | 'Left' | 'Right' | 'Up'}`\n\t| 'End' | 'Home' | 'PageDown' | 'PageUp';\n\ntype EditingKey =\n\t| 'Backspace' | 'Clear' | 'Copy' | 'CrSel' | 'Cut' | 'Delete'\n\t| 'EraseEof' | 'ExSel' | 'Insert' | 'Paste' | 'Redo' | 'Undo';\n\ntype UIKey =\n\t| 'Accept' | 'Again' | 'Attn' | 'Cancel' | 'ContextMenu' | 'Escape'\n\t| 'Execute' | 'Find' | 'Finish' | 'Help' | 'Pause' | 'Play'\n\t| 'Props' | 'Select' | 'ZoomIn' | 'ZoomOut';\n\ntype DeviceKey =\n\t| 'BrightnessDown' | 'BrightnessUp' | 'Eject' | 'Hibernate'\n\t| 'LogOff' | 'Power' | 'PowerOff' | 'PrintScreen' | 'Standby' | 'WakeUp';\n\ntype IMEKey =\n\t| 'AllCandidates' | 'Alphanumeric' | 'CodeInput' | 'Compose' | 'Convert'\n\t| 'FinalMode' | 'GroupFirst' | 'GroupLast' | 'GroupNext' | 'GroupPrevious'\n\t| 'ModeChange' | 'NextCandidate' | 'NonConvert' | 'PreviousCandidate'\n\t| 'Process' | 'SingleCandidate'\n\t| 'HangulMode' | 'HanjaMode' | 'JunjaMode'\n\t| 'Eisu' | 'Hankaku' | 'Hiragana' | 'HiraganaKatakana' | 'KanaMode'\n\t| 'KanjiMode' | 'Katakana' | 'Romaji' | 'Zenkaku' | 'ZenkakuHankaku';\n\ntype FunctionKey =\n\t| `F${1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24}`\n\t| 'Soft1' | 'Soft2' | 'Soft3' | 'Soft4';\n\ntype PhoneKey =\n\t| 'AppSwitch' | 'Call' | 'Camera' | 'CameraFocus' | 'EndCall'\n\t| 'GoBack' | 'GoHome' | 'HeadsetHook' | 'LastNumberRedial'\n\t| 'Notification' | 'MannerMode' | 'VoiceDial';\n\ntype MultimediaKey =\n\t| 'ChannelDown' | 'ChannelUp'\n\t| `Media${\n\t\t'FastForward' | 'Pause' | 'Play' | 'PlayPause'\n\t\t| 'Record' | 'Rewind' | 'Stop' | 'TrackNext' | 'TrackPrevious'\n\t}`;\n\ntype AudioKey =\n\t| `Audio${\n\t\t'BalanceLeft' | 'BalanceRight' | 'BassDown' | 'BassBoostDown'\n\t\t| 'BassBoostToggle' | 'BassBoostUp' | 'BassUp' | 'FaderFront' | 'FaderRear'\n\t\t| 'SurroundModeNext' | 'TrebleDown' | 'TrebleUp'\n\t\t| 'VolumeDown' | 'VolumeMute' | 'VolumeUp'\n\t}`\n\t| `Microphone${'Toggle' | 'VolumeDown' | 'VolumeMute' | 'VolumeUp'}`;\n\ntype TVKey =\n\t| 'TV'\n\t| `TV${\n\t\t'3DMode' | 'AntennaCable' | 'AudioDescription' | 'AudioDescriptionMixDown'\n\t\t| 'AudioDescriptionMixUp' | 'ContentsMenu' | 'DataService' | 'Input'\n\t\t| 'InputComponent1' | 'InputComponent2' | 'InputComposite1' | 'InputComposite2'\n\t\t| 'InputHDMI1' | 'InputHDMI2' | 'InputHDMI3' | 'InputHDMI4' | 'InputVGA1'\n\t\t| 'MediaContext' | 'Network' | 'NumberEntry' | 'Power' | 'RadioService'\n\t\t| 'Satellite' | 'SatelliteBS' | 'SatelliteCS' | 'SatelliteToggle'\n\t\t| 'TerrestrialAnalog' | 'TerrestrialDigital' | 'Timer'\n\t}`;\n\ntype MediaControllerKey =\n\t| 'AVRInput' | 'AVRPower'\n\t| `Color${'F0Red' | 'F1Green' | 'F2Yellow' | 'F3Blue' | 'F4Grey' | 'F5Brown'}`\n\t| 'ClosedCaptionToggle' | 'Dimmer' | 'DisplaySwap' | 'DVR' | 'Exit'\n\t| `Favorite${'Clear' | 'Recall' | 'Store'}${0 | 1 | 2 | 3}`\n\t| 'Guide' | 'GuideNextDay' | 'GuidePreviousDay' | 'Info' | 'InstantReplay'\n\t| 'Link' | 'ListProgram' | 'LiveContent' | 'Lock'\n\t| `Media${\n\t\t'Apps' | 'AudioTrack' | 'Last' | 'SkipBackward'\n\t\t| 'SkipForward' | 'StepBackward' | 'StepForward' | 'TopMenu'\n\t}`\n\t| `Navigate${'In' | 'Next' | 'Out' | 'Previous'}`\n\t| 'NextFavoriteChannel' | 'NextUserProfile' | 'OnDemand' | 'Pairing'\n\t| `PinP${'Down' | 'Move' | 'Toggle' | 'Up'}`\n\t| `PlaySpeed${'Down' | 'Reset' | 'Up'}`\n\t| 'RandomToggle' | 'RcLowBattery' | 'RecordSpeedNext' | 'RfBypass'\n\t| 'ScanChannelsToggle' | 'ScreenModeNext' | 'Settings' | 'SplitScreenToggle'\n\t| 'STBInput' | 'STBPower' | 'Subtitle' | 'Teletext'\n\t| 'VideoModeNext' | 'Wink' | 'ZoomToggle';\n\ntype SpeechKey = 'SpeechCorrectionList' | 'SpeechInputToggle';\n\ntype DocumentKey =\n\t| 'Close' | 'New' | 'Open' | 'Print' | 'Save' | 'SpellCheck'\n\t| 'MailForward' | 'MailReply' | 'MailSend';\n\ntype LaunchKey = `Launch${\n\t| 'Calculator' | 'Calendar' | 'Contacts' | 'Mail' | 'MediaPlayer'\n\t| 'MusicPlayer' | 'MyComputer' | 'Phone' | 'ScreenSaver' | 'Spreadsheet'\n\t| 'WebBrowser' | 'WebCam' | 'WordProcessor'\n\t| `Application${1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16}`\n}`;\n\ntype BrowserKey = `Browser${'Back' | 'Favorites' | 'Forward' | 'Home' | 'Refresh' | 'Search' | 'Stop'}`;\n\ntype NumpadKey = 'Decimal' | 'Key11' | 'Key12' | 'Multiply' | 'Add' | 'Divide' | 'Subtract' | 'Separator';\n\nexport type KeyCode =\n\t| LowercaseLetter | Uppercase<LowercaseLetter> | Digit | Punctuation\n\t| ModifierKey | WhitespaceKey | NavigationKey | EditingKey | UIKey | DeviceKey\n\t| IMEKey | FunctionKey | PhoneKey | MultimediaKey | AudioKey | TVKey\n\t| MediaControllerKey | SpeechKey | DocumentKey | LaunchKey | BrowserKey | NumpadKey\n\t| 'Unidentified' | 'Dead';\n\nexport interface KeyboardState {\n\tisDown(key: KeyCode): boolean;\n\tjustPressed(key: KeyCode): boolean;\n\tjustReleased(key: KeyCode): boolean;\n}\n\nexport interface PointerState {\n\treadonly position: Readonly<Vec2>;\n\treadonly delta: Readonly<Vec2>;\n\tisDown(button: number): boolean;\n\tjustPressed(button: number): boolean;\n\tjustReleased(button: number): boolean;\n}\n\nexport interface ActionState<A extends string = string> {\n\tisActive(action: A): boolean;\n\tjustActivated(action: A): boolean;\n\tjustDeactivated(action: A): boolean;\n}\n\nexport interface InputState<A extends string = string> {\n\treadonly keyboard: KeyboardState;\n\treadonly pointer: PointerState;\n\treadonly actions: ActionState<A>;\n\tsetActionMap(actions: ActionMap<A>): void;\n\tgetActionMap(): Readonly<ActionMap<A>>;\n}\n\nexport interface ActionBinding {\n\tkeys?: KeyCode[];\n\tbuttons?: number[];\n}\n\nexport type ActionMap<A extends string = string> = Record<A, ActionBinding>;\n\nexport interface InputResourceTypes<A extends string = string> {\n\tinputState: InputState<A>;\n}\n\nexport interface InputPluginOptions<A extends string = string, G extends string = 'input'> extends BasePluginOptions<G> {\n\t/** Initial action mappings */\n\tactions?: ActionMap<A>;\n\t/** EventTarget to attach listeners to (default: globalThis). Pass a custom target for testability. */\n\ttarget?: EventTarget;\n}\n\n// ==================== Helper Functions ====================\n\n/**\n * Create a single action binding.\n *\n * @param binding The binding configuration\n * @returns The same binding object\n */\nexport function createActionBinding(binding: ActionBinding): ActionBinding {\n\treturn binding;\n}\n\n// ==================== Internal Types ====================\n\ninterface RawInputState {\n\tkeysDown: Set<string>;\n\tkeysPressed: string[];\n\tkeysReleased: string[];\n\tbuttonsDown: Set<number>;\n\tbuttonsPressed: number[];\n\tbuttonsReleased: number[];\n\tpointerX: number;\n\tpointerY: number;\n\tpointerDeltaX: number;\n\tpointerDeltaY: number;\n\tlastPointerX: number;\n\tlastPointerY: number;\n\tpointerMoved: boolean;\n}\n\ninterface FrameSnapshot {\n\tkeysDown: ReadonlySet<string>;\n\tkeysPressed: ReadonlySet<string>;\n\tkeysReleased: ReadonlySet<string>;\n\tbuttonsDown: ReadonlySet<number>;\n\tbuttonsPressed: ReadonlySet<number>;\n\tbuttonsReleased: ReadonlySet<number>;\n\tpointerX: number;\n\tpointerY: number;\n\tpointerDeltaX: number;\n\tpointerDeltaY: number;\n\tactionsActive: ReadonlySet<string>;\n\tprevActionsActive: ReadonlySet<string>;\n}\n\n// ==================== Plugin Factory ====================\n\nfunction createRawInputState(): RawInputState {\n\treturn {\n\t\tkeysDown: new Set(),\n\t\tkeysPressed: [],\n\t\tkeysReleased: [],\n\t\tbuttonsDown: new Set(),\n\t\tbuttonsPressed: [],\n\t\tbuttonsReleased: [],\n\t\tpointerX: 0,\n\t\tpointerY: 0,\n\t\tpointerDeltaX: 0,\n\t\tpointerDeltaY: 0,\n\t\tlastPointerX: 0,\n\t\tlastPointerY: 0,\n\t\tpointerMoved: false,\n\t};\n}\n\nconst EMPTY_SET_STRING: ReadonlySet<string> = new Set<string>();\nconst EMPTY_SET_NUMBER: ReadonlySet<number> = new Set<number>();\n\nfunction createEmptySnapshot(): FrameSnapshot {\n\treturn {\n\t\tkeysDown: EMPTY_SET_STRING,\n\t\tkeysPressed: EMPTY_SET_STRING,\n\t\tkeysReleased: EMPTY_SET_STRING,\n\t\tbuttonsDown: EMPTY_SET_NUMBER,\n\t\tbuttonsPressed: EMPTY_SET_NUMBER,\n\t\tbuttonsReleased: EMPTY_SET_NUMBER,\n\t\tpointerX: 0,\n\t\tpointerY: 0,\n\t\tpointerDeltaX: 0,\n\t\tpointerDeltaY: 0,\n\t\tactionsActive: EMPTY_SET_STRING,\n\t\tprevActionsActive: EMPTY_SET_STRING,\n\t};\n}\n\nfunction computeActiveActions(\n\tactionMap: ActionMap,\n\tkeysDown: ReadonlySet<string>,\n\tbuttonsDown: ReadonlySet<number>,\n): Set<string> {\n\tconst active = new Set<string>();\n\tfor (const [name, binding] of Object.entries(actionMap)) {\n\t\tconst keyActive = binding.keys?.some((k) => keysDown.has(k)) ?? false;\n\t\tconst buttonActive = binding.buttons?.some((b) => buttonsDown.has(b)) ?? false;\n\t\tif (keyActive || buttonActive) {\n\t\t\tactive.add(name);\n\t\t}\n\t}\n\treturn active;\n}\n\nfunction snapshotRaw(raw: RawInputState, prevActionsActive: ReadonlySet<string>, actionMap: ActionMap): FrameSnapshot {\n\tconst keysDown = new Set(raw.keysDown);\n\tconst keysPressed = new Set(raw.keysPressed);\n\tconst keysReleased = new Set(raw.keysReleased);\n\tconst buttonsDown = new Set(raw.buttonsDown);\n\tconst buttonsPressed = new Set(raw.buttonsPressed);\n\tconst buttonsReleased = new Set(raw.buttonsReleased);\n\n\tconst pointerDeltaX = raw.pointerMoved ? raw.pointerX - raw.lastPointerX : 0;\n\tconst pointerDeltaY = raw.pointerMoved ? raw.pointerY - raw.lastPointerY : 0;\n\n\tconst actionsActive = computeActiveActions(actionMap, keysDown, buttonsDown);\n\n\tconst snapshot: FrameSnapshot = {\n\t\tkeysDown,\n\t\tkeysPressed,\n\t\tkeysReleased,\n\t\tbuttonsDown,\n\t\tbuttonsPressed,\n\t\tbuttonsReleased,\n\t\tpointerX: raw.pointerX,\n\t\tpointerY: raw.pointerY,\n\t\tpointerDeltaX,\n\t\tpointerDeltaY,\n\t\tactionsActive,\n\t\tprevActionsActive,\n\t};\n\n\t// Clear accumulation buffers\n\traw.keysPressed = [];\n\traw.keysReleased = [];\n\traw.buttonsPressed = [];\n\traw.buttonsReleased = [];\n\traw.lastPointerX = raw.pointerX;\n\traw.lastPointerY = raw.pointerY;\n\traw.pointerMoved = false;\n\n\treturn snapshot;\n}\n\n/**\n * Create an input plugin for ECSpresso.\n *\n * This plugin provides:\n * - Frame-accurate keyboard state (isDown, justPressed, justReleased)\n * - Pointer position/delta and button state (mouse + touch via PointerEvent)\n * - Named action mapping with runtime remapping\n * - Automatic listener cleanup on detach\n *\n * @example\n * ```typescript\n * const ecs = ECSpresso.create()\n * .withPlugin(createInputPlugin({\n * actions: {\n * jump: { keys: [' ', 'ArrowUp'] },\n * shoot: { keys: ['z'], buttons: [0] },\n * },\n * }))\n * .build();\n *\n * // In a system:\n * const input = ecs.getResource('inputState');\n * if (input.actions.justActivated('jump')) { ... }\n * if (input.keyboard.isDown('ArrowRight')) { ... }\n * ```\n */\nexport function createInputPlugin<A extends string = string, G extends string = 'input'>(\n\toptions?: InputPluginOptions<A, G>\n): Plugin<WorldConfigFrom<{}, {}, InputResourceTypes<A>>, EmptyConfig, 'input-state', G> {\n\tconst {\n\t\tsystemGroup = 'input',\n\t\tpriority = 100,\n\t\tphase = 'preUpdate',\n\t\tactions: initialActions = {},\n\t\ttarget = globalThis,\n\t} = options ?? {};\n\n\t// Closure state\n\tconst raw = createRawInputState();\n\tlet snapshot = createEmptySnapshot();\n\tlet actionMap: ActionMap = { ...initialActions };\n\tconst cleanupFns: Array<() => void> = [];\n\n\t// The position/delta objects exposed via the resource.\n\t// Updated in-place each frame to avoid allocations.\n\tconst position: Vec2 = { x: 0, y: 0 };\n\tconst delta: Vec2 = { x: 0, y: 0 };\n\n\t// Build the InputState resource that closes over snapshot\n\tconst keyboard: KeyboardState = {\n\t\tisDown: (key) => snapshot.keysDown.has(key),\n\t\tjustPressed: (key) => snapshot.keysPressed.has(key),\n\t\tjustReleased: (key) => snapshot.keysReleased.has(key),\n\t};\n\n\tconst pointer: PointerState = {\n\t\tposition,\n\t\tdelta,\n\t\tisDown: (button) => snapshot.buttonsDown.has(button),\n\t\tjustPressed: (button) => snapshot.buttonsPressed.has(button),\n\t\tjustReleased: (button) => snapshot.buttonsReleased.has(button),\n\t};\n\n\tconst actionState: ActionState<A> = {\n\t\tisActive: (action) => snapshot.actionsActive.has(action),\n\t\tjustActivated: (action) =>\n\t\t\tsnapshot.actionsActive.has(action) && !snapshot.prevActionsActive.has(action),\n\t\tjustDeactivated: (action) =>\n\t\t\t!snapshot.actionsActive.has(action) && snapshot.prevActionsActive.has(action),\n\t};\n\n\tconst inputState: InputState<A> = {\n\t\tkeyboard,\n\t\tpointer,\n\t\tactions: actionState,\n\t\tsetActionMap(newMap) {\n\t\t\tactionMap = { ...newMap };\n\t\t},\n\t\tgetActionMap() {\n\t\t\treturn { ...actionMap } as ActionMap<A>;\n\t\t},\n\t};\n\n\t// DOM event handlers\n\tfunction onKeyDown(e: Event) {\n\t\tconst ke = e as KeyboardEvent;\n\t\tif (ke.repeat) return;\n\t\traw.keysDown.add(ke.key);\n\t\traw.keysPressed.push(ke.key);\n\t}\n\n\tfunction onKeyUp(e: Event) {\n\t\tconst ke = e as KeyboardEvent;\n\t\traw.keysDown.delete(ke.key);\n\t\traw.keysReleased.push(ke.key);\n\t}\n\n\tfunction onPointerDown(e: Event) {\n\t\tconst pe = e as PointerEvent;\n\t\traw.buttonsDown.add(pe.button);\n\t\traw.buttonsPressed.push(pe.button);\n\t}\n\n\tfunction onPointerMove(e: Event) {\n\t\tconst pe = e as PointerEvent;\n\t\traw.pointerX = pe.clientX;\n\t\traw.pointerY = pe.clientY;\n\t\traw.pointerMoved = true;\n\t}\n\n\tfunction onPointerUp(e: Event) {\n\t\tconst pe = e as PointerEvent;\n\t\traw.buttonsDown.delete(pe.button);\n\t\traw.buttonsReleased.push(pe.button);\n\t}\n\n\tfunction addListener(type: string, handler: (e: Event) => void) {\n\t\ttarget.addEventListener(type, handler);\n\t\tcleanupFns.push(() => { target.removeEventListener(type, handler); });\n\t}\n\n\treturn definePlugin<WorldConfigFrom<{}, {}, InputResourceTypes<A>>, EmptyConfig, 'input-state', G>({\n\t\tid: 'input',\n\t\tinstall(world) {\n\t\t\tworld.addResource('inputState', inputState);\n\n\t\t\tworld\n\t\t\t\t.addSystem('input-state')\n\t\t\t\t.setPriority(priority)\n\t\t\t\t.inPhase(phase)\n\t\t\t\t.inGroup(systemGroup)\n\t\t\t\t.setOnInitialize(() => {\n\t\t\t\t\taddListener('keydown', onKeyDown);\n\t\t\t\t\taddListener('keyup', onKeyUp);\n\t\t\t\t\taddListener('pointerdown', onPointerDown);\n\t\t\t\t\taddListener('pointermove', onPointerMove);\n\t\t\t\t\taddListener('pointerup', onPointerUp);\n\t\t\t\t})\n\t\t\t\t.setOnDetach(() => {\n\t\t\t\t\tfor (const cleanup of cleanupFns) {\n\t\t\t\t\t\tcleanup();\n\t\t\t\t\t}\n\t\t\t\t\tcleanupFns.length = 0;\n\t\t\t\t})\n\t\t\t\t.setProcess(() => {\n\t\t\t\t\tconst prevActionsActive = snapshot.actionsActive;\n\t\t\t\t\tsnapshot = snapshotRaw(raw, prevActionsActive, actionMap);\n\n\t\t\t\t\t// Update the exposed position/delta objects in-place\n\t\t\t\t\tposition.x = snapshot.pointerX;\n\t\t\t\t\tposition.y = snapshot.pointerY;\n\t\t\t\t\tdelta.x = snapshot.pointerDeltaX;\n\t\t\t\t\tdelta.y = snapshot.pointerDeltaY;\n\t\t\t\t});\n\t\t},\n\t});\n}\n"
6
6
  ],
7
- "mappings": "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",
8
- "debugId": "AA1CB6B40EFAD7D764756E2164756E21",
7
+ "mappings": "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",
8
+ "debugId": "513EE3E4CA561E4664756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -1,4 +1,4 @@
1
- var{defineProperty:W,getOwnPropertyNames:D,getOwnPropertyDescriptor:X}=Object,Y=Object.prototype.hasOwnProperty;function T(k){return this[k]}var x=(k)=>{var A=(_??=new WeakMap).get(k),B;if(A)return A;if(A=W({},"__esModule",{value:!0}),k&&typeof k==="object"||typeof k==="function"){for(var Z of D(k))if(!Y.call(A,Z))W(A,Z,{get:T.bind(k,Z),enumerable:!(B=X(k,Z))||B.enumerable})}return _.set(k,A),A},_;var C=(k)=>k;function R(k,A){this[k]=C.bind(null,A)}var y=(k,A)=>{for(var B in A)W(k,B,{get:A[B],enumerable:!0,configurable:!0,set:R.bind(A,B)})};var g=(k,A)=>()=>(k&&(A=k(k=0)),A);var w=((k)=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(k,{get:(A,B)=>(typeof require<"u"?require:A)[B]}):k)(function(k){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+k+'" is not supported')});import{definePlugin as v}from"ecspresso";function M(k){if(typeof k==="number")return k;let[A,B]=k;return A+Math.random()*(B-A)}function I(k,A,B){if(k===A)return k;let Z=k>>16&255,L=k>>8&255,q=k&255,H=A>>16&255,j=A>>8&255,$=A&255,Q=Z+(H-Z)*B|0,V=L+(j-L)*B|0,J=q+($-q)*B|0;return Q<<16|V<<8|J}var O=Math.PI*2;function G(k){let A=k.startSize??1,B=k.startTint??16777215;return Object.freeze({maxParticles:k.maxParticles,texture:k.texture,spawnRate:k.spawnRate??10,burstCount:k.burstCount??0,duration:k.duration??-1,lifetime:k.lifetime??1,speed:k.speed??100,angle:k.angle??[0,O],emissionShape:k.emissionShape??"point",emissionRadius:k.emissionRadius??0,gravity:Object.freeze(k.gravity??{x:0,y:0}),startSize:A,endSize:k.endSize??A,startAlpha:k.startAlpha??1,endAlpha:k.endAlpha??0,startTint:B,endTint:k.endTint??B,startRotation:k.startRotation??0,rotationSpeed:k.rotationSpeed??0,blendMode:k.blendMode??"normal",worldSpace:k.worldSpace??!0})}function l(k,A){return{particleEmitter:{config:k,activeCount:0,spawnAccumulator:0,elapsed:0,playing:A?.playing??!0,pendingBurst:0,finished:!1,onComplete:A?.onComplete}}}function d(k,A,B){let Z=k.getComponent(A,"particleEmitter");if(!Z)return!1;return Z.pendingBurst+=B??Z.config.burstCount,k.markChanged(A,"particleEmitter"),!0}function s(k,A){let B=k.getComponent(A,"particleEmitter");if(!B)return!1;return B.playing=!1,!0}function m(k,A){let B=k.getComponent(A,"particleEmitter");if(!B)return!1;return B.playing=!0,!0}function b(k,A,B,Z,L){k.active=!0;let q=M(A.lifetime);if(k.life=q,k.maxLife=q,A.emissionShape==="circle"&&A.emissionRadius>0){let $=Math.random()*O,Q=Math.random()*A.emissionRadius;k.x=B+Math.cos($)*Q,k.y=Z+Math.sin($)*Q}else k.x=B,k.y=Z;let H=M(A.speed),j=M(A.angle)+L;k.vx=Math.cos(j)*H,k.vy=Math.sin(j)*H,k.startSize=M(A.startSize),k.endSize=M(A.endSize),k.size=k.startSize,k.startAlpha=M(A.startAlpha),k.endAlpha=M(A.endAlpha),k.alpha=k.startAlpha,k.tint=A.startTint,k.rotation=M(A.startRotation),k.rotationSpeed=M(A.rotationSpeed)}function P(k,A,B,Z,L,q){let H=k.config;k.elapsed+=B;let j=H.duration>=0&&k.elapsed>=H.duration;if(k.playing&&!j&&H.spawnRate>0){k.spawnAccumulator+=H.spawnRate*B;let F=Math.floor(k.spawnAccumulator);k.spawnAccumulator-=F;for(let U=0;U<F;U++){if(k.activeCount>=H.maxParticles)break;let z=A.particles[k.activeCount];if(!z)break;b(z,H,Z,L,q),k.activeCount++}}if(k.pendingBurst>0){let F=Math.min(k.pendingBurst,H.maxParticles-k.activeCount);for(let U=0;U<F;U++){let z=A.particles[k.activeCount];if(!z)break;b(z,H,Z,L,q),k.activeCount++}k.pendingBurst-=F}let Q=H.gravity.x,V=H.gravity.y,J=Q!==0||V!==0,N=H.startTint!==H.endTint,K=0;while(K<k.activeCount){let F=A.particles[K];if(!F)break;if(F.life-=B,F.life<=0){if(k.activeCount--,K<k.activeCount){let z=A.particles[k.activeCount];if(z){A.particles[K]=z,A.particles[k.activeCount]=F;let h=A.pixiParticles[K];A.pixiParticles[K]=A.pixiParticles[k.activeCount],A.pixiParticles[k.activeCount]=h}}F.active=!1;continue}if(J)F.vx+=Q*B,F.vy+=V*B;F.x+=F.vx*B,F.y+=F.vy*B;let U=1-F.life/F.maxLife;if(F.size=F.startSize+(F.endSize-F.startSize)*U,F.alpha=F.startAlpha+(F.endAlpha-F.startAlpha)*U,N)F.tint=I(H.startTint,H.endTint,U);F.rotation+=F.rotationSpeed*B,K++}}function E(k){let A=Array(k);for(let B=0;B<k;B++)A[B]={active:!1,x:0,y:0,vx:0,vy:0,life:0,maxLife:0,size:0,startSize:0,endSize:0,alpha:0,startAlpha:0,endAlpha:0,tint:16777215,rotation:0,rotationSpeed:0};return A}var o={explosion(k,A){return G({maxParticles:50,texture:k,spawnRate:0,burstCount:30,duration:1,lifetime:[0.3,0.8],speed:[100,300],angle:[0,O],startSize:[0.5,1.5],endSize:[0.1,0.3],startAlpha:1,endAlpha:0,...A})},smoke(k,A){return G({maxParticles:60,texture:k,spawnRate:15,duration:-1,lifetime:[1,3],speed:[20,60],angle:[-Math.PI/2-0.3,-Math.PI/2+0.3],startSize:[0.3,0.6],endSize:[1,2],startAlpha:0.4,endAlpha:0,...A})},fire(k,A){return G({maxParticles:80,texture:k,spawnRate:30,duration:-1,lifetime:[0.3,1],speed:[40,120],angle:[-Math.PI/2-0.5,-Math.PI/2+0.5],startSize:[0.5,1],endSize:[0.1,0.3],startAlpha:1,endAlpha:0,startTint:16746496,endTint:16720384,blendMode:"add",...A})},sparkle(k,A){return G({maxParticles:30,texture:k,spawnRate:10,duration:-1,lifetime:[0.5,1.5],speed:[10,40],angle:[0,O],startSize:[0.2,0.8],endSize:[0.1,0.4],startAlpha:[0.5,1],endAlpha:0,...A})},trail(k,A){return G({maxParticles:40,texture:k,spawnRate:20,duration:-1,lifetime:[0.3,0.8],speed:0,startSize:[0.5,1],endSize:[0.05,0.2],startAlpha:0.8,endAlpha:0,...A})}};function c(k){let{systemGroup:A="particles",priority:B=0,phase:Z="update"}=k??{},L=new Map;return v({id:"particles",install(q){q.registerRequired("particleEmitter","localTransform",()=>({x:0,y:0,rotation:0,scaleX:1,scaleY:1})),q.registerDispose("particleEmitter",({entityId:H})=>{let j=L.get(H);if(j){let $=j.pixiContainer;if($)$.removeFromParent?.(),$.destroy?.();L.delete(H)}}),q.addSystem("particle-update").setPriority(B).inPhase(Z).inGroup(A).addQuery("emitters",{with:["particleEmitter"]}).setProcess(({queries:H,dt:j,ecs:$})=>{for(let Q of H.emitters){let V=Q.components.particleEmitter,J=L.get(Q.id);if(!J)J={particles:E(V.config.maxParticles),pixiContainer:null,pixiParticles:[]},L.set(Q.id,J);let N=$.getComponent(Q.id,"worldTransform"),K=N?.x??0,F=N?.y??0,U=N?.rotation??0;P(V,J,j,K,F,U);let z=V.config;if(z.duration>=0&&V.elapsed>=z.duration&&V.activeCount===0&&!V.finished){if(V.finished=!0,V.onComplete)V.onComplete({entityId:Q.id});$.commands.removeComponent(Q.id,"particleEmitter")}}}),q.addSystem("particle-render-sync").setPriority(400).inPhase("render").inGroup(A).setOnInitialize(async(H)=>{let j=await import("pixi.js"),$=j.ParticleContainer,Q=j.Particle,V=H.tryGetResource("rootContainer");H.addReactiveQuery("particle-emitters",{with:["particleEmitter"],onEnter:(J)=>{let K=J.components.particleEmitter.config,F=new $({dynamicProperties:{position:!0,rotation:!0,color:!0,vertex:!0}});F.blendMode=K.blendMode;let U=[];for(let h=0;h<K.maxParticles;h++){let S=new Q({texture:K.texture});S.alpha=0,U.push(S),F.addParticle(S)}let z=E(K.maxParticles);if(V)if(H.getComponent(J.id,"renderLayer"))V.addChild(F);else V.addChild(F);L.set(J.id,{particles:z,pixiContainer:F,pixiParticles:U})},onExit:(J)=>{let N=L.get(J);if(N){let K=N.pixiContainer;if(K)K.removeFromParent?.(),K.destroy?.();L.delete(J)}}})}).setProcess(({ecs:H})=>{for(let[j,$]of L){let Q=H.getComponent(j,"particleEmitter");if(!Q)continue;let V=Q.config;if(!V.worldSpace){let J=H.getComponent(j,"worldTransform");if(J){let N=$.pixiContainer;N.position.set(J.x,J.y),N.rotation=J.rotation,N.scale.set(J.scaleX,J.scaleY)}}for(let J=0;J<Q.activeCount;J++){let N=$.particles[J],K=$.pixiParticles[J];if(!N||!K)continue;K.x=N.x,K.y=N.y,K.scaleX=N.size,K.scaleY=N.size,K.rotation=N.rotation,K.tint=N.tint,K.alpha=N.alpha}for(let J=Q.activeCount;J<V.maxParticles;J++){let N=$.pixiParticles[J];if(N)N.alpha=0}}})}})}function p(k,A){return k.get(A)}export{s as stopEmitter,M as sampleRange,m as resumeEmitter,o as particlePresets,I as lerpTint,p as getEmitterData,G as defineParticleEffect,c as createParticlePlugin,l as createParticleEmitter,d as burstParticles};
1
+ var b=((k)=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(k,{get:(A,F)=>(typeof require<"u"?require:A)[F]}):k)(function(k){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+k+'" is not supported')});import{definePlugin as E}from"ecspresso";function M(k){if(typeof k==="number")return k;let[A,F]=k;return A+Math.random()*(F-A)}function D(k,A,F){if(k===A)return k;let L=k>>16&255,j=k>>8&255,q=k&255,H=A>>16&255,$=A>>8&255,Z=A&255,Q=L+(H-L)*F|0,V=j+($-j)*F|0,J=q+(Z-q)*F|0;return Q<<16|V<<8|J}var O=Math.PI*2;function G(k){let A=k.startSize??1,F=k.startTint??16777215;return Object.freeze({maxParticles:k.maxParticles,texture:k.texture,spawnRate:k.spawnRate??10,burstCount:k.burstCount??0,duration:k.duration??-1,lifetime:k.lifetime??1,speed:k.speed??100,angle:k.angle??[0,O],emissionShape:k.emissionShape??"point",emissionRadius:k.emissionRadius??0,gravity:Object.freeze(k.gravity??{x:0,y:0}),startSize:A,endSize:k.endSize??A,startAlpha:k.startAlpha??1,endAlpha:k.endAlpha??0,startTint:F,endTint:k.endTint??F,startRotation:k.startRotation??0,rotationSpeed:k.rotationSpeed??0,blendMode:k.blendMode??"normal",worldSpace:k.worldSpace??!0})}function C(k,A){return{particleEmitter:{config:k,activeCount:0,spawnAccumulator:0,elapsed:0,playing:A?.playing??!0,pendingBurst:0,finished:!1,onComplete:A?.onComplete}}}function R(k,A,F){let L=k.getComponent(A,"particleEmitter");if(!L)return!1;return L.pendingBurst+=F??L.config.burstCount,k.markChanged(A,"particleEmitter"),!0}function w(k,A){let F=k.getComponent(A,"particleEmitter");if(!F)return!1;return F.playing=!1,!0}function v(k,A){let F=k.getComponent(A,"particleEmitter");if(!F)return!1;return F.playing=!0,!0}function W(k,A,F,L,j){k.active=!0;let q=M(A.lifetime);if(k.life=q,k.maxLife=q,A.emissionShape==="circle"&&A.emissionRadius>0){let Z=Math.random()*O,Q=Math.random()*A.emissionRadius;k.x=F+Math.cos(Z)*Q,k.y=L+Math.sin(Z)*Q}else k.x=F,k.y=L;let H=M(A.speed),$=M(A.angle)+j;k.vx=Math.cos($)*H,k.vy=Math.sin($)*H,k.startSize=M(A.startSize),k.endSize=M(A.endSize),k.size=k.startSize,k.startAlpha=M(A.startAlpha),k.endAlpha=M(A.endAlpha),k.alpha=k.startAlpha,k.tint=A.startTint,k.rotation=M(A.startRotation),k.rotationSpeed=M(A.rotationSpeed)}function X(k,A,F,L,j,q){let H=k.config;k.elapsed+=F;let $=H.duration>=0&&k.elapsed>=H.duration;if(k.playing&&!$&&H.spawnRate>0){k.spawnAccumulator+=H.spawnRate*F;let B=Math.floor(k.spawnAccumulator);k.spawnAccumulator-=B;for(let U=0;U<B;U++){if(k.activeCount>=H.maxParticles)break;let z=A.particles[k.activeCount];if(!z)break;W(z,H,L,j,q),k.activeCount++}}if(k.pendingBurst>0){let B=Math.min(k.pendingBurst,H.maxParticles-k.activeCount);for(let U=0;U<B;U++){let z=A.particles[k.activeCount];if(!z)break;W(z,H,L,j,q),k.activeCount++}k.pendingBurst-=B}let Q=H.gravity.x,V=H.gravity.y,J=Q!==0||V!==0,N=H.startTint!==H.endTint,K=0;while(K<k.activeCount){let B=A.particles[K];if(!B)break;if(B.life-=F,B.life<=0){if(k.activeCount--,K<k.activeCount){let z=A.particles[k.activeCount];if(z){A.particles[K]=z,A.particles[k.activeCount]=B;let h=A.pixiParticles[K];A.pixiParticles[K]=A.pixiParticles[k.activeCount],A.pixiParticles[k.activeCount]=h}}B.active=!1;continue}if(J)B.vx+=Q*F,B.vy+=V*F;B.x+=B.vx*F,B.y+=B.vy*F;let U=1-B.life/B.maxLife;if(B.size=B.startSize+(B.endSize-B.startSize)*U,B.alpha=B.startAlpha+(B.endAlpha-B.startAlpha)*U,N)B.tint=D(H.startTint,H.endTint,U);B.rotation+=B.rotationSpeed*F,K++}}function _(k){let A=Array(k);for(let F=0;F<k;F++)A[F]={active:!1,x:0,y:0,vx:0,vy:0,life:0,maxLife:0,size:0,startSize:0,endSize:0,alpha:0,startAlpha:0,endAlpha:0,tint:16777215,rotation:0,rotationSpeed:0};return A}var I={explosion(k,A){return G({maxParticles:50,texture:k,spawnRate:0,burstCount:30,duration:1,lifetime:[0.3,0.8],speed:[100,300],angle:[0,O],startSize:[0.5,1.5],endSize:[0.1,0.3],startAlpha:1,endAlpha:0,...A})},smoke(k,A){return G({maxParticles:60,texture:k,spawnRate:15,duration:-1,lifetime:[1,3],speed:[20,60],angle:[-Math.PI/2-0.3,-Math.PI/2+0.3],startSize:[0.3,0.6],endSize:[1,2],startAlpha:0.4,endAlpha:0,...A})},fire(k,A){return G({maxParticles:80,texture:k,spawnRate:30,duration:-1,lifetime:[0.3,1],speed:[40,120],angle:[-Math.PI/2-0.5,-Math.PI/2+0.5],startSize:[0.5,1],endSize:[0.1,0.3],startAlpha:1,endAlpha:0,startTint:16746496,endTint:16720384,blendMode:"add",...A})},sparkle(k,A){return G({maxParticles:30,texture:k,spawnRate:10,duration:-1,lifetime:[0.5,1.5],speed:[10,40],angle:[0,O],startSize:[0.2,0.8],endSize:[0.1,0.4],startAlpha:[0.5,1],endAlpha:0,...A})},trail(k,A){return G({maxParticles:40,texture:k,spawnRate:20,duration:-1,lifetime:[0.3,0.8],speed:0,startSize:[0.5,1],endSize:[0.05,0.2],startAlpha:0.8,endAlpha:0,...A})}};function P(k){let{systemGroup:A="particles",priority:F=0,phase:L="update"}=k??{},j=new Map;return E({id:"particles",install(q){q.registerRequired("particleEmitter","localTransform",()=>({x:0,y:0,rotation:0,scaleX:1,scaleY:1})),q.registerDispose("particleEmitter",({entityId:H})=>{let $=j.get(H);if($){let Z=$.pixiContainer;if(Z)Z.removeFromParent?.(),Z.destroy?.();j.delete(H)}}),q.addSystem("particle-update").setPriority(F).inPhase(L).inGroup(A).addQuery("emitters",{with:["particleEmitter"]}).setProcess(({queries:H,dt:$,ecs:Z})=>{for(let Q of H.emitters){let V=Q.components.particleEmitter,J=j.get(Q.id);if(!J)J={particles:_(V.config.maxParticles),pixiContainer:null,pixiParticles:[]},j.set(Q.id,J);let N=Z.getComponent(Q.id,"worldTransform"),K=N?.x??0,B=N?.y??0,U=N?.rotation??0;X(V,J,$,K,B,U);let z=V.config;if(z.duration>=0&&V.elapsed>=z.duration&&V.activeCount===0&&!V.finished){if(V.finished=!0,V.onComplete)V.onComplete({entityId:Q.id});Z.commands.removeComponent(Q.id,"particleEmitter")}}}),q.addSystem("particle-render-sync").setPriority(400).inPhase("render").inGroup(A).setOnInitialize(async(H)=>{let $=await import("pixi.js"),Z=$.ParticleContainer,Q=$.Particle,V=H.tryGetResource("rootContainer");H.addReactiveQuery("particle-emitters",{with:["particleEmitter"],onEnter:(J)=>{let K=J.components.particleEmitter.config,B=new Z({dynamicProperties:{position:!0,rotation:!0,color:!0,vertex:!0}});B.blendMode=K.blendMode;let U=[];for(let h=0;h<K.maxParticles;h++){let S=new Q({texture:K.texture});S.alpha=0,U.push(S),B.addParticle(S)}let z=_(K.maxParticles);if(V)if(H.getComponent(J.id,"renderLayer"))V.addChild(B);else V.addChild(B);j.set(J.id,{particles:z,pixiContainer:B,pixiParticles:U})},onExit:(J)=>{let N=j.get(J);if(N){let K=N.pixiContainer;if(K)K.removeFromParent?.(),K.destroy?.();j.delete(J)}}})}).setProcess(({ecs:H})=>{for(let[$,Z]of j){let Q=H.getComponent($,"particleEmitter");if(!Q)continue;let V=Q.config;if(!V.worldSpace){let J=H.getComponent($,"worldTransform");if(J){let N=Z.pixiContainer;N.position.set(J.x,J.y),N.rotation=J.rotation,N.scale.set(J.scaleX,J.scaleY)}}for(let J=0;J<Q.activeCount;J++){let N=Z.particles[J],K=Z.pixiParticles[J];if(!N||!K)continue;K.x=N.x,K.y=N.y,K.scaleX=N.size,K.scaleY=N.size,K.rotation=N.rotation,K.tint=N.tint,K.alpha=N.alpha}for(let J=Q.activeCount;J<V.maxParticles;J++){let N=Z.pixiParticles[J];if(N)N.alpha=0}}})}})}function x(k,A){return k.get(A)}export{w as stopEmitter,M as sampleRange,v as resumeEmitter,I as particlePresets,D as lerpTint,x as getEmitterData,G as defineParticleEffect,P as createParticlePlugin,C as createParticleEmitter,R as burstParticles};
2
2
 
3
- //# debugId=4CA5165A66C2506A64756E2164756E21
3
+ //# debugId=84EAAF5C730AFBAB64756E2164756E21
4
4
  //# sourceMappingURL=particles.js.map
@@ -4,7 +4,7 @@
4
4
  "sourcesContent": [
5
5
  "/**\n * Particle System Plugin for ECSpresso\n *\n * High-performance particle system where particles live outside the ECS in\n * pre-allocated pools. Renders via PixiJS v8's ParticleContainer + Particle API.\n * Renderer2D is a required dependency.\n *\n * Follows the established plugin pattern: immutable shared config\n * (ParticleEffectConfig) + mutable per-entity state (ParticleEmitter) component,\n * side-storage Map for PixiJS objects, kit pattern for typed helpers.\n */\n\nimport { definePlugin, type Plugin, type BasePluginOptions } from 'ecspresso';\nimport type { BaseWorld } from 'ecspresso';\nimport type { WorldConfigFrom } from '../type-utils';\nimport type { TransformComponentTypes, LocalTransform } from 'ecspresso/plugins/transform';\n\n/** BaseWorld narrowed to particle components for typed access in helpers. */\ntype ParticleWorld = BaseWorld<ParticleComponentTypes>;\n\n// ==================== Value Types ====================\n\n/** Fixed value or random range [min, max] */\nexport type ParticleValue = number | readonly [number, number];\n\n/** Emission geometry */\nexport type EmissionShape = 'point' | 'circle';\n\n/** Blend modes for particle rendering */\nexport type ParticleBlendMode = 'normal' | 'add' | 'multiply' | 'screen';\n\n// ==================== Config Types ====================\n\n/**\n * User-facing config input for defining a particle effect.\n * All properties optional except maxParticles and texture.\n */\nexport interface ParticleEffectInput {\n\t/** Pool size — maximum simultaneous particles */\n\tmaxParticles: number;\n\t/** PixiJS Texture for particles */\n\ttexture: unknown;\n\t/** Particles per second (0 = burst-only, default: 10) */\n\tspawnRate?: number;\n\t/** Particles per burst (default: 0) */\n\tburstCount?: number;\n\t/** Emitter lifetime in seconds (-1 = infinite, default: -1) */\n\tduration?: number;\n\t/** Per-particle lifetime in seconds (default: 1) */\n\tlifetime?: ParticleValue;\n\t/** Initial speed in pixels/second (default: 100) */\n\tspeed?: ParticleValue;\n\t/** Emission direction in radians (default: [0, 2*PI]) */\n\tangle?: ParticleValue;\n\t/** Spawn geometry (default: 'point') */\n\temissionShape?: EmissionShape;\n\t/** Radius for 'circle' shape (default: 0) */\n\temissionRadius?: number;\n\t/** Acceleration in pixels/second^2 (default: {x: 0, y: 0}) */\n\tgravity?: { readonly x: number; readonly y: number };\n\t/** Initial scale (default: 1) */\n\tstartSize?: ParticleValue;\n\t/** Final scale (default: same as startSize) */\n\tendSize?: ParticleValue;\n\t/** Initial opacity (default: 1) */\n\tstartAlpha?: ParticleValue;\n\t/** Final opacity (default: 0) */\n\tendAlpha?: ParticleValue;\n\t/** Initial hex color (default: 0xffffff) */\n\tstartTint?: number;\n\t/** Final hex color (default: same as startTint) */\n\tendTint?: number;\n\t/** Initial rotation in radians (default: 0) */\n\tstartRotation?: ParticleValue;\n\t/** Rotation velocity in rad/s (default: 0) */\n\trotationSpeed?: ParticleValue;\n\t/** Blend mode (default: 'normal') */\n\tblendMode?: ParticleBlendMode;\n\t/** Particles in world coordinates (default: true) */\n\tworldSpace?: boolean;\n}\n\n/**\n * Frozen, fully-resolved particle effect config.\n * Output of defineParticleEffect.\n */\nexport interface ParticleEffectConfig {\n\treadonly maxParticles: number;\n\treadonly texture: unknown;\n\treadonly spawnRate: number;\n\treadonly burstCount: number;\n\treadonly duration: number;\n\treadonly lifetime: ParticleValue;\n\treadonly speed: ParticleValue;\n\treadonly angle: ParticleValue;\n\treadonly emissionShape: EmissionShape;\n\treadonly emissionRadius: number;\n\treadonly gravity: { readonly x: number; readonly y: number };\n\treadonly startSize: ParticleValue;\n\treadonly endSize: ParticleValue;\n\treadonly startAlpha: ParticleValue;\n\treadonly endAlpha: ParticleValue;\n\treadonly startTint: number;\n\treadonly endTint: number;\n\treadonly startRotation: ParticleValue;\n\treadonly rotationSpeed: ParticleValue;\n\treadonly blendMode: ParticleBlendMode;\n\treadonly worldSpace: boolean;\n}\n\n// ==================== Per-Particle Pool Element ====================\n\n/**\n * Mutable per-particle state. Pre-allocated, never GC'd.\n */\nexport interface ParticleState {\n\tactive: boolean;\n\tx: number;\n\ty: number;\n\tvx: number;\n\tvy: number;\n\tlife: number;\n\tmaxLife: number;\n\tsize: number;\n\tstartSize: number;\n\tendSize: number;\n\talpha: number;\n\tstartAlpha: number;\n\tendAlpha: number;\n\ttint: number;\n\trotation: number;\n\trotationSpeed: number;\n}\n\n// ==================== ECS Component ====================\n\n/**\n * Per-entity emitter state stored as an ECS component.\n */\nexport interface ParticleEmitter {\n\treadonly config: ParticleEffectConfig;\n\tactiveCount: number;\n\tspawnAccumulator: number;\n\telapsed: number;\n\tplaying: boolean;\n\tpendingBurst: number;\n\tfinished: boolean;\n\tonComplete?: (data: ParticleEmitterEventData) => void;\n}\n\n/**\n * Component types provided by the particle plugin.\n */\nexport interface ParticleComponentTypes {\n\tparticleEmitter: ParticleEmitter;\n}\n\n// ==================== Event Types ====================\n\n/**\n * Data published when an emitter completes.\n */\nexport interface ParticleEmitterEventData {\n\tentityId: number;\n}\n\n// ==================== Plugin Options ====================\n\nexport interface ParticlePluginOptions<G extends string = 'particles'> extends BasePluginOptions<G> {}\n\n// ==================== Pure Functions (Simulation Engine) ====================\n\n/**\n * Sample a ParticleValue: returns fixed value or random within [min, max].\n */\nexport function sampleRange(value: ParticleValue): number {\n\tif (typeof value === 'number') return value;\n\tconst [min, max] = value;\n\treturn min + Math.random() * (max - min);\n}\n\n/**\n * Linear interpolation between two hex colors (RGB channels).\n */\nexport function lerpTint(start: number, end: number, t: number): number {\n\tif (start === end) return start;\n\tconst sr = (start >> 16) & 0xff;\n\tconst sg = (start >> 8) & 0xff;\n\tconst sb = start & 0xff;\n\tconst er = (end >> 16) & 0xff;\n\tconst eg = (end >> 8) & 0xff;\n\tconst eb = end & 0xff;\n\tconst r = (sr + (er - sr) * t) | 0;\n\tconst g = (sg + (eg - sg) * t) | 0;\n\tconst b = (sb + (eb - sb) * t) | 0;\n\treturn (r << 16) | (g << 8) | b;\n}\n\n// ==================== Config Builder ====================\n\nconst TWO_PI = Math.PI * 2;\n\n/**\n * Define a particle effect config with defaults applied and frozen.\n */\nexport function defineParticleEffect(input: ParticleEffectInput): ParticleEffectConfig {\n\tconst startSize = input.startSize ?? 1;\n\tconst startTint = input.startTint ?? 0xffffff;\n\treturn Object.freeze({\n\t\tmaxParticles: input.maxParticles,\n\t\ttexture: input.texture,\n\t\tspawnRate: input.spawnRate ?? 10,\n\t\tburstCount: input.burstCount ?? 0,\n\t\tduration: input.duration ?? -1,\n\t\tlifetime: input.lifetime ?? 1,\n\t\tspeed: input.speed ?? 100,\n\t\tangle: input.angle ?? [0, TWO_PI] as const,\n\t\temissionShape: input.emissionShape ?? 'point',\n\t\temissionRadius: input.emissionRadius ?? 0,\n\t\tgravity: Object.freeze(input.gravity ?? { x: 0, y: 0 }),\n\t\tstartSize,\n\t\tendSize: input.endSize ?? startSize,\n\t\tstartAlpha: input.startAlpha ?? 1,\n\t\tendAlpha: input.endAlpha ?? 0,\n\t\tstartTint,\n\t\tendTint: input.endTint ?? startTint,\n\t\tstartRotation: input.startRotation ?? 0,\n\t\trotationSpeed: input.rotationSpeed ?? 0,\n\t\tblendMode: input.blendMode ?? 'normal',\n\t\tworldSpace: input.worldSpace ?? true,\n\t});\n}\n\n// ==================== Component Factory ====================\n\n/**\n * Create a particleEmitter component suitable for spreading into spawn().\n */\nexport function createParticleEmitter(\n\tconfig: ParticleEffectConfig,\n\toptions?: {\n\t\tplaying?: boolean;\n\t\tonComplete?: (data: ParticleEmitterEventData) => void;\n\t},\n): Pick<ParticleComponentTypes, 'particleEmitter'> {\n\treturn {\n\t\tparticleEmitter: {\n\t\t\tconfig,\n\t\t\tactiveCount: 0,\n\t\t\tspawnAccumulator: 0,\n\t\t\telapsed: 0,\n\t\t\tplaying: options?.playing ?? true,\n\t\t\tpendingBurst: 0,\n\t\t\tfinished: false,\n\t\t\tonComplete: options?.onComplete,\n\t\t},\n\t};\n}\n\n// ==================== Helper Functions ====================\n\n/**\n * Queue a burst of particles on an emitter.\n * Returns false if entity has no particleEmitter component.\n */\nexport function burstParticles(\n\tecs: ParticleWorld,\n\tentityId: number,\n\tcount?: number,\n): boolean {\n\tconst emitter = ecs.getComponent(entityId, 'particleEmitter');\n\tif (!emitter) return false;\n\temitter.pendingBurst += count ?? emitter.config.burstCount;\n\tecs.markChanged(entityId, 'particleEmitter');\n\treturn true;\n}\n\n/**\n * Stop an emitter from spawning new particles.\n * Existing particles continue their lifecycle.\n */\nexport function stopEmitter(\n\tecs: ParticleWorld,\n\tentityId: number,\n): boolean {\n\tconst emitter = ecs.getComponent(entityId, 'particleEmitter');\n\tif (!emitter) return false;\n\temitter.playing = false;\n\treturn true;\n}\n\n/**\n * Resume a stopped emitter.\n */\nexport function resumeEmitter(\n\tecs: ParticleWorld,\n\tentityId: number,\n): boolean {\n\tconst emitter = ecs.getComponent(entityId, 'particleEmitter');\n\tif (!emitter) return false;\n\temitter.playing = true;\n\treturn true;\n}\n\n// ==================== Side Storage ====================\n\n/**\n * Runtime data stored outside the ECS, keyed by entity ID.\n */\nexport interface EmitterRuntimeData {\n\tparticles: ParticleState[];\n\tpixiContainer: unknown;\n\tpixiParticles: unknown[];\n}\n\n// ==================== Spawn Logic ====================\n\nfunction spawnParticle(\n\tparticle: ParticleState,\n\tconfig: ParticleEffectConfig,\n\temitterX: number,\n\temitterY: number,\n\temitterRotation: number,\n): void {\n\tparticle.active = true;\n\tconst life = sampleRange(config.lifetime);\n\tparticle.life = life;\n\tparticle.maxLife = life;\n\n\t// Position from emission shape\n\tif (config.emissionShape === 'circle' && config.emissionRadius > 0) {\n\t\tconst angle = Math.random() * TWO_PI;\n\t\tconst radius = Math.random() * config.emissionRadius;\n\t\tparticle.x = emitterX + Math.cos(angle) * radius;\n\t\tparticle.y = emitterY + Math.sin(angle) * radius;\n\t} else {\n\t\tparticle.x = emitterX;\n\t\tparticle.y = emitterY;\n\t}\n\n\t// Velocity from speed + angle + emitter rotation\n\tconst speed = sampleRange(config.speed);\n\tconst angle = sampleRange(config.angle) + emitterRotation;\n\tparticle.vx = Math.cos(angle) * speed;\n\tparticle.vy = Math.sin(angle) * speed;\n\n\t// Visual properties\n\tparticle.startSize = sampleRange(config.startSize);\n\tparticle.endSize = sampleRange(config.endSize);\n\tparticle.size = particle.startSize;\n\tparticle.startAlpha = sampleRange(config.startAlpha);\n\tparticle.endAlpha = sampleRange(config.endAlpha);\n\tparticle.alpha = particle.startAlpha;\n\tparticle.tint = config.startTint;\n\tparticle.rotation = sampleRange(config.startRotation);\n\tparticle.rotationSpeed = sampleRange(config.rotationSpeed);\n}\n\n// ==================== Update Logic ====================\n\nfunction updateParticles(\n\temitter: ParticleEmitter,\n\tdata: EmitterRuntimeData,\n\tdt: number,\n\temitterX: number,\n\temitterY: number,\n\temitterRotation: number,\n): void {\n\tconst config = emitter.config;\n\n\t// Update emitter elapsed time\n\temitter.elapsed += dt;\n\n\t// Determine if spawning is allowed\n\tconst durationExpired = config.duration >= 0 && emitter.elapsed >= config.duration;\n\tconst canSpawn = emitter.playing && !durationExpired;\n\n\t// Continuous spawning\n\tif (canSpawn && config.spawnRate > 0) {\n\t\temitter.spawnAccumulator += config.spawnRate * dt;\n\t\tconst toSpawn = Math.floor(emitter.spawnAccumulator);\n\t\temitter.spawnAccumulator -= toSpawn;\n\n\t\tfor (let i = 0; i < toSpawn; i++) {\n\t\t\tif (emitter.activeCount >= config.maxParticles) break;\n\t\t\tconst particle = data.particles[emitter.activeCount];\n\t\t\tif (!particle) break;\n\t\t\tspawnParticle(particle, config, emitterX, emitterY, emitterRotation);\n\t\t\temitter.activeCount++;\n\t\t}\n\t}\n\n\t// Burst spawning\n\tif (emitter.pendingBurst > 0) {\n\t\tconst burstCount = Math.min(\n\t\t\temitter.pendingBurst,\n\t\t\tconfig.maxParticles - emitter.activeCount,\n\t\t);\n\t\tfor (let i = 0; i < burstCount; i++) {\n\t\t\tconst particle = data.particles[emitter.activeCount];\n\t\t\tif (!particle) break;\n\t\t\tspawnParticle(particle, config, emitterX, emitterY, emitterRotation);\n\t\t\temitter.activeCount++;\n\t\t}\n\t\temitter.pendingBurst -= burstCount;\n\t}\n\n\t// Update active particles\n\tconst gravityX = config.gravity.x;\n\tconst gravityY = config.gravity.y;\n\tconst hasGravity = gravityX !== 0 || gravityY !== 0;\n\tconst hasTintLerp = config.startTint !== config.endTint;\n\n\tlet i = 0;\n\twhile (i < emitter.activeCount) {\n\t\tconst p = data.particles[i];\n\t\tif (!p) break;\n\n\t\tp.life -= dt;\n\n\t\tif (p.life <= 0) {\n\t\t\t// Swap-and-pop: move last active particle to this slot\n\t\t\temitter.activeCount--;\n\t\t\tif (i < emitter.activeCount) {\n\t\t\t\tconst last = data.particles[emitter.activeCount];\n\t\t\t\tif (last) {\n\t\t\t\t\t// Copy last particle data to current slot\n\t\t\t\t\tdata.particles[i] = last;\n\t\t\t\t\tdata.particles[emitter.activeCount] = p;\n\t\t\t\t\t// Also swap PixiJS particle refs\n\t\t\t\t\tconst tmpPixi = data.pixiParticles[i];\n\t\t\t\t\tdata.pixiParticles[i] = data.pixiParticles[emitter.activeCount];\n\t\t\t\t\tdata.pixiParticles[emitter.activeCount] = tmpPixi;\n\t\t\t\t}\n\t\t\t}\n\t\t\tp.active = false;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Physics\n\t\tif (hasGravity) {\n\t\t\tp.vx += gravityX * dt;\n\t\t\tp.vy += gravityY * dt;\n\t\t}\n\t\tp.x += p.vx * dt;\n\t\tp.y += p.vy * dt;\n\n\t\t// Interpolation\n\t\tconst t = 1 - p.life / p.maxLife;\n\t\tp.size = p.startSize + (p.endSize - p.startSize) * t;\n\t\tp.alpha = p.startAlpha + (p.endAlpha - p.startAlpha) * t;\n\n\t\tif (hasTintLerp) {\n\t\t\tp.tint = lerpTint(config.startTint, config.endTint, t);\n\t\t}\n\n\t\t// Rotation\n\t\tp.rotation += p.rotationSpeed * dt;\n\n\t\ti++;\n\t}\n}\n\n// ==================== Pool Allocation ====================\n\nfunction createParticlePool(maxParticles: number): ParticleState[] {\n\tconst pool: ParticleState[] = new Array(maxParticles);\n\tfor (let i = 0; i < maxParticles; i++) {\n\t\tpool[i] = {\n\t\t\tactive: false,\n\t\t\tx: 0, y: 0,\n\t\t\tvx: 0, vy: 0,\n\t\t\tlife: 0, maxLife: 0,\n\t\t\tsize: 0,\n\t\t\tstartSize: 0, endSize: 0,\n\t\t\talpha: 0,\n\t\t\tstartAlpha: 0, endAlpha: 0,\n\t\t\ttint: 0xffffff,\n\t\t\trotation: 0,\n\t\t\trotationSpeed: 0,\n\t\t};\n\t}\n\treturn pool;\n}\n\n// ==================== Presets ====================\n\nexport const particlePresets = {\n\texplosion(texture: unknown, overrides?: Partial<ParticleEffectInput>): ParticleEffectConfig {\n\t\treturn defineParticleEffect({\n\t\t\tmaxParticles: 50,\n\t\t\ttexture,\n\t\t\tspawnRate: 0,\n\t\t\tburstCount: 30,\n\t\t\tduration: 1,\n\t\t\tlifetime: [0.3, 0.8],\n\t\t\tspeed: [100, 300],\n\t\t\tangle: [0, TWO_PI],\n\t\t\tstartSize: [0.5, 1.5],\n\t\t\tendSize: [0.1, 0.3],\n\t\t\tstartAlpha: 1,\n\t\t\tendAlpha: 0,\n\t\t\t...overrides,\n\t\t});\n\t},\n\n\tsmoke(texture: unknown, overrides?: Partial<ParticleEffectInput>): ParticleEffectConfig {\n\t\treturn defineParticleEffect({\n\t\t\tmaxParticles: 60,\n\t\t\ttexture,\n\t\t\tspawnRate: 15,\n\t\t\tduration: -1,\n\t\t\tlifetime: [1, 3],\n\t\t\tspeed: [20, 60],\n\t\t\tangle: [-Math.PI / 2 - 0.3, -Math.PI / 2 + 0.3],\n\t\t\tstartSize: [0.3, 0.6],\n\t\t\tendSize: [1, 2],\n\t\t\tstartAlpha: 0.4,\n\t\t\tendAlpha: 0,\n\t\t\t...overrides,\n\t\t});\n\t},\n\n\tfire(texture: unknown, overrides?: Partial<ParticleEffectInput>): ParticleEffectConfig {\n\t\treturn defineParticleEffect({\n\t\t\tmaxParticles: 80,\n\t\t\ttexture,\n\t\t\tspawnRate: 30,\n\t\t\tduration: -1,\n\t\t\tlifetime: [0.3, 1],\n\t\t\tspeed: [40, 120],\n\t\t\tangle: [-Math.PI / 2 - 0.5, -Math.PI / 2 + 0.5],\n\t\t\tstartSize: [0.5, 1],\n\t\t\tendSize: [0.1, 0.3],\n\t\t\tstartAlpha: 1,\n\t\t\tendAlpha: 0,\n\t\t\tstartTint: 0xff8800,\n\t\t\tendTint: 0xff2200,\n\t\t\tblendMode: 'add',\n\t\t\t...overrides,\n\t\t});\n\t},\n\n\tsparkle(texture: unknown, overrides?: Partial<ParticleEffectInput>): ParticleEffectConfig {\n\t\treturn defineParticleEffect({\n\t\t\tmaxParticles: 30,\n\t\t\ttexture,\n\t\t\tspawnRate: 10,\n\t\t\tduration: -1,\n\t\t\tlifetime: [0.5, 1.5],\n\t\t\tspeed: [10, 40],\n\t\t\tangle: [0, TWO_PI],\n\t\t\tstartSize: [0.2, 0.8],\n\t\t\tendSize: [0.1, 0.4],\n\t\t\tstartAlpha: [0.5, 1],\n\t\t\tendAlpha: 0,\n\t\t\t...overrides,\n\t\t});\n\t},\n\n\ttrail(texture: unknown, overrides?: Partial<ParticleEffectInput>): ParticleEffectConfig {\n\t\treturn defineParticleEffect({\n\t\t\tmaxParticles: 40,\n\t\t\ttexture,\n\t\t\tspawnRate: 20,\n\t\t\tduration: -1,\n\t\t\tlifetime: [0.3, 0.8],\n\t\t\tspeed: 0,\n\t\t\tstartSize: [0.5, 1],\n\t\t\tendSize: [0.05, 0.2],\n\t\t\tstartAlpha: 0.8,\n\t\t\tendAlpha: 0,\n\t\t\t...overrides,\n\t\t});\n\t},\n} as const;\n\n// ==================== Plugin Factory ====================\n\ntype ParticleLabels = 'particle-update' | 'particle-render-sync';\n\ntype ParticleRequires = WorldConfigFrom<TransformComponentTypes & { renderLayer: string }>;\n\n/**\n * Create a particle system plugin for ECSpresso.\n *\n * Provides:\n * - Pre-allocated particle pools outside the entity system\n * - Continuous and burst emission modes\n * - Velocity, gravity, lifetime, interpolation (size, alpha, tint, rotation)\n * - World-space and local-space particle emission\n * - PixiJS ParticleContainer rendering (via renderer2D dependency)\n * - Presets for common effects (explosion, smoke, fire, sparkle, trail)\n *\n * Renderer2D is a required dependency.\n */\nexport function createParticlePlugin<\n\tG extends string = 'particles',\n>(\n\toptions?: ParticlePluginOptions<G>,\n): Plugin<WorldConfigFrom<ParticleComponentTypes>, ParticleRequires, ParticleLabels, G, never, 'particle-emitters'> {\n\tconst {\n\t\tsystemGroup = 'particles',\n\t\tpriority = 0,\n\t\tphase = 'update',\n\t} = options ?? {};\n\n\t// Side storage for runtime particle data\n\tconst emitterData = new Map<number, EmitterRuntimeData>();\n\n\treturn definePlugin<WorldConfigFrom<ParticleComponentTypes>, ParticleRequires, ParticleLabels, G, never, 'particle-emitters'>({\n\t\tid: 'particles',\n\t\tinstall(world) {\n\t\t\t// Required component: particleEmitter needs localTransform\n\t\t\tworld.registerRequired('particleEmitter', 'localTransform', (): LocalTransform => ({\n\t\t\t\tx: 0, y: 0, rotation: 0, scaleX: 1, scaleY: 1,\n\t\t\t}));\n\n\t\t\t// Dispose: clean up side storage when particleEmitter removed\n\t\t\tworld.registerDispose('particleEmitter', ({ entityId }: { value: ParticleEmitter; entityId: number }) => {\n\t\t\t\tconst data = emitterData.get(entityId);\n\t\t\t\tif (data) {\n\t\t\t\t\t// Remove PixiJS container from scene graph\n\t\t\t\t\tconst container = data.pixiContainer as { removeFromParent?: () => void; destroy?: () => void } | null;\n\t\t\t\t\tif (container) {\n\t\t\t\t\t\tcontainer.removeFromParent?.();\n\t\t\t\t\t\tcontainer.destroy?.();\n\t\t\t\t\t}\n\t\t\t\t\temitterData.delete(entityId);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// ==================== Particle Update System ====================\n\t\t\tworld\n\t\t\t\t.addSystem('particle-update')\n\t\t\t\t.setPriority(priority)\n\t\t\t\t.inPhase(phase)\n\t\t\t\t.inGroup(systemGroup)\n\t\t\t\t.addQuery('emitters', {\n\t\t\t\t\twith: ['particleEmitter'],\n\t\t\t\t})\n\t\t\t\t.setProcess(({ queries, dt, ecs }) => {\n\t\t\t\t\tfor (const entity of queries.emitters) {\n\t\t\t\t\t\tconst emitter = entity.components.particleEmitter;\n\n\t\t\t\t\t\t// Lazily create particle pool on first encounter\n\t\t\t\t\t\tlet data = emitterData.get(entity.id);\n\t\t\t\t\t\tif (!data) {\n\t\t\t\t\t\t\tdata = {\n\t\t\t\t\t\t\t\tparticles: createParticlePool(emitter.config.maxParticles),\n\t\t\t\t\t\t\t\tpixiContainer: null,\n\t\t\t\t\t\t\t\tpixiParticles: [],\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\temitterData.set(entity.id, data);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst worldTransform = ecs.getComponent(entity.id, 'worldTransform');\n\t\t\t\t\t\tconst ex = worldTransform?.x ?? 0;\n\t\t\t\t\t\tconst ey = worldTransform?.y ?? 0;\n\t\t\t\t\t\tconst erot = worldTransform?.rotation ?? 0;\n\n\t\t\t\t\t\tupdateParticles(emitter, data, dt, ex, ey, erot);\n\n\t\t\t\t\t\t// Check completion\n\t\t\t\t\t\tconst config = emitter.config;\n\t\t\t\t\t\tconst durationExpired = config.duration >= 0 && emitter.elapsed >= config.duration;\n\t\t\t\t\t\tif (durationExpired && emitter.activeCount === 0 && !emitter.finished) {\n\t\t\t\t\t\t\temitter.finished = true;\n\n\t\t\t\t\t\t\tif (emitter.onComplete) {\n\t\t\t\t\t\t\t\temitter.onComplete({ entityId: entity.id });\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tecs.commands.removeComponent(entity.id, 'particleEmitter');\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t// ==================== Particle Render Sync System ====================\n\t\t\tworld\n\t\t\t\t.addSystem('particle-render-sync')\n\t\t\t\t.setPriority(400)\n\t\t\t\t.inPhase('render')\n\t\t\t\t.inGroup(systemGroup)\n\t\t\t\t.setOnInitialize(async (ecs) => {\n\t\t\t\t\t// Dynamic import PixiJS\n\t\t\t\t\tconst pixi = await import('pixi.js');\n\t\t\t\t\tconst ParticleContainerClass = pixi.ParticleContainer;\n\t\t\t\t\tconst ParticleClass = pixi.Particle;\n\n\t\t\t\t\t// Get root container\n\t\t\t\t\tconst rootContainer = ecs.tryGetResource<{ addChild(child: unknown): void }>('rootContainer');\n\n\t\t\t\t\t// Reactive query for particleEmitter component\n\t\t\t\t\tecs.addReactiveQuery('particle-emitters', {\n\t\t\t\t\t\twith: ['particleEmitter'],\n\t\t\t\t\t\tonEnter: (entity) => {\n\t\t\t\t\t\t\tconst emitter = entity.components.particleEmitter;\n\t\t\t\t\t\t\tconst config = emitter.config;\n\n\t\t\t\t\t\t\t// Create PixiJS ParticleContainer\n\t\t\t\t\t\t\tconst pixiContainer = new ParticleContainerClass({\n\t\t\t\t\t\t\t\tdynamicProperties: {\n\t\t\t\t\t\t\t\t\tposition: true,\n\t\t\t\t\t\t\t\t\trotation: true,\n\t\t\t\t\t\t\t\t\tcolor: true,\n\t\t\t\t\t\t\t\t\tvertex: true,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t// Set blend mode\n\t\t\t\t\t\t\tpixiContainer.blendMode = config.blendMode;\n\n\t\t\t\t\t\t\t// Pre-allocate Particle objects\n\t\t\t\t\t\t\tconst pixiParticles: InstanceType<typeof ParticleClass>[] = [];\n\t\t\t\t\t\t\tfor (let i = 0; i < config.maxParticles; i++) {\n\t\t\t\t\t\t\t\tconst p = new ParticleClass({\n\t\t\t\t\t\t\t\t\ttexture: config.texture,\n\t\t\t\t\t\t\t\t} as ConstructorParameters<typeof ParticleClass>[0]);\n\t\t\t\t\t\t\t\tp.alpha = 0;\n\t\t\t\t\t\t\t\tpixiParticles.push(p);\n\t\t\t\t\t\t\t\tpixiContainer.addParticle(p);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Create pre-allocated pool\n\t\t\t\t\t\t\tconst particles = createParticlePool(config.maxParticles);\n\n\t\t\t\t\t\t\t// Add to scene (cross-plugin structural access for renderLayer)\n\t\t\t\t\t\t\tif (rootContainer) {\n\t\t\t\t\t\t\t\tconst layerName = ecs.getComponent(entity.id, 'renderLayer');\n\t\t\t\t\t\t\t\tif (layerName) {\n\t\t\t\t\t\t\t\t\t(rootContainer as { addChild(child: unknown): void }).addChild(pixiContainer);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t(rootContainer as { addChild(child: unknown): void }).addChild(pixiContainer);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Store in side storage\n\t\t\t\t\t\t\temitterData.set(entity.id, {\n\t\t\t\t\t\t\t\tparticles,\n\t\t\t\t\t\t\t\tpixiContainer,\n\t\t\t\t\t\t\t\tpixiParticles,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t},\n\t\t\t\t\t\tonExit: (entityId) => {\n\t\t\t\t\t\t\tconst data = emitterData.get(entityId);\n\t\t\t\t\t\t\tif (data) {\n\t\t\t\t\t\t\t\tconst container = data.pixiContainer as { removeFromParent?: () => void; destroy?: () => void } | null;\n\t\t\t\t\t\t\t\tif (container) {\n\t\t\t\t\t\t\t\t\tcontainer.removeFromParent?.();\n\t\t\t\t\t\t\t\t\tcontainer.destroy?.();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\temitterData.delete(entityId);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t})\n\t\t\t\t.setProcess(({ ecs }) => {\n\t\t\t\t\t// Sync ParticleState -> PixiJS Particle properties\n\t\t\t\t\tfor (const [entityId, data] of emitterData) {\n\t\t\t\t\t\tconst emitter = ecs.getComponent(entityId, 'particleEmitter');\n\t\t\t\t\t\tif (!emitter) continue;\n\n\t\t\t\t\t\tconst config = emitter.config;\n\n\t\t\t\t\t\t// Local-space: sync container position to emitter's worldTransform\n\t\t\t\t\t\tif (!config.worldSpace) {\n\t\t\t\t\t\t\tconst wt = ecs.getComponent(entityId, 'worldTransform');\n\t\t\t\t\t\t\tif (wt) {\n\t\t\t\t\t\t\t\tconst container = data.pixiContainer as {\n\t\t\t\t\t\t\t\t\tposition: { set(x: number, y: number): void };\n\t\t\t\t\t\t\t\t\trotation: number;\n\t\t\t\t\t\t\t\t\tscale: { set(x: number, y: number): void };\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\tcontainer.position.set(wt.x, wt.y);\n\t\t\t\t\t\t\t\tcontainer.rotation = wt.rotation;\n\t\t\t\t\t\t\t\tcontainer.scale.set(wt.scaleX, wt.scaleY);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Sync active particles\n\t\t\t\t\t\tfor (let i = 0; i < emitter.activeCount; i++) {\n\t\t\t\t\t\t\tconst ps = data.particles[i];\n\t\t\t\t\t\t\tconst pp = data.pixiParticles[i] as {\n\t\t\t\t\t\t\t\tx: number;\n\t\t\t\t\t\t\t\ty: number;\n\t\t\t\t\t\t\t\tscaleX: number;\n\t\t\t\t\t\t\t\tscaleY: number;\n\t\t\t\t\t\t\t\trotation: number;\n\t\t\t\t\t\t\t\ttint: number;\n\t\t\t\t\t\t\t\talpha: number;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tif (!ps || !pp) continue;\n\t\t\t\t\t\t\tpp.x = ps.x;\n\t\t\t\t\t\t\tpp.y = ps.y;\n\t\t\t\t\t\t\tpp.scaleX = ps.size;\n\t\t\t\t\t\t\tpp.scaleY = ps.size;\n\t\t\t\t\t\t\tpp.rotation = ps.rotation;\n\t\t\t\t\t\t\tpp.tint = ps.tint;\n\t\t\t\t\t\t\tpp.alpha = ps.alpha;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Hide inactive particles\n\t\t\t\t\t\tfor (let i = emitter.activeCount; i < config.maxParticles; i++) {\n\t\t\t\t\t\t\tconst pp = data.pixiParticles[i] as { alpha: number } | undefined;\n\t\t\t\t\t\t\tif (pp) {\n\t\t\t\t\t\t\t\tpp.alpha = 0;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t},\n\t});\n}\n\n/**\n * Get the runtime data for an emitter entity.\n * Useful for tests and advanced usage.\n * @internal Exported for testing only.\n */\nexport function getEmitterData(\n\temitterDataMap: Map<number, EmitterRuntimeData>,\n\tentityId: number,\n): EmitterRuntimeData | undefined {\n\treturn emitterDataMap.get(entityId);\n}\n"
6
6
  ],
7
- "mappings": "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",
8
- "debugId": "4CA5165A66C2506A64756E2164756E21",
7
+ "mappings": "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",
8
+ "debugId": "84EAAF5C730AFBAB64756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -1,4 +1,4 @@
1
- var{defineProperty:N,getOwnPropertyNames:Y,getOwnPropertyDescriptor:w}=Object,I=Object.prototype.hasOwnProperty;function B(z){return this[z]}var b=(z)=>{var E=(q??=new WeakMap).get(z),J;if(E)return E;if(E=N({},"__esModule",{value:!0}),z&&typeof z==="object"||typeof z==="function"){for(var O of Y(z))if(!I.call(E,O))N(E,O,{get:B.bind(z,O),enumerable:!(J=w(z,O))||J.enumerable})}return q.set(z,E),E},q;var f=(z)=>z;function x(z,E){this[z]=f.bind(null,E)}var d=(z,E)=>{for(var J in E)N(z,J,{get:E[J],enumerable:!0,configurable:!0,set:x.bind(E,J)})};var r=(z,E)=>()=>(z&&(E=z(z=0)),E);var l=((z)=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(z,{get:(E,J)=>(typeof require<"u"?require:E)[J]}):z)(function(z){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+z+'" is not supported')});import{definePlugin as u}from"ecspresso";function M(z,E,J,O,Z,Q,K){if(!Q&&!K)return null;let k={entityId:z,x:E,y:J,layer:O,collidesWith:Z};if(Q)k.x+=Q.offsetX??0,k.y+=Q.offsetY??0,k.aabb={halfWidth:Q.width/2,halfHeight:Q.height/2};if(K)k.x+=K.offsetX??0,k.y+=K.offsetY??0,k.circle={radius:K.radius};return k}function S(z){return z("spatialIndex")}function m(z,E,J,O,Z,Q,K,k){let _=Z-z,j=Q-E,$=J+K-Math.abs(_),F=O+k-Math.abs(j);if($<=0||F<=0)return null;if($<F)return{normalX:_>=0?1:-1,normalY:0,depth:$};return{normalX:0,normalY:j>=0?1:-1,depth:F}}function g(z,E,J,O,Z,Q){let K=O-z,k=Z-E,_=K*K+k*k,j=J+Q;if(_>=j*j)return null;let $=Math.sqrt(_);if($===0)return{normalX:1,normalY:0,depth:j};return{normalX:K/$,normalY:k/$,depth:j-$}}function C(z,E,J,O,Z,Q,K){let k=Math.max(z-J,Math.min(Z,z+J)),_=Math.max(E-O,Math.min(Q,E+O)),j=Z-k,$=Q-_,F=j*j+$*$;if(F>=K*K)return null;if(F===0){let W=Z-(z-J),L=z+J-Z,R=Q-(E-O),V=E+O-Q,U=Math.min(W,L,R,V);if(U===L)return{normalX:1,normalY:0,depth:L+K};if(U===W)return{normalX:-1,normalY:0,depth:W+K};if(U===V)return{normalX:0,normalY:1,depth:V+K};return{normalX:0,normalY:-1,depth:R+K}}let T=Math.sqrt(F);return{normalX:j/T,normalY:$/T,depth:K-T}}function A(z,E){if(z.aabb&&E.aabb)return m(z.x,z.y,z.aabb.halfWidth,z.aabb.halfHeight,E.x,E.y,E.aabb.halfWidth,E.aabb.halfHeight);if(z.circle&&E.circle)return g(z.x,z.y,z.circle.radius,E.x,E.y,E.circle.radius);if(z.aabb&&E.circle)return C(z.x,z.y,z.aabb.halfWidth,z.aabb.halfHeight,E.x,E.y,E.circle.radius);if(z.circle&&E.aabb){let J=C(E.x,E.y,E.aabb.halfWidth,E.aabb.halfHeight,z.x,z.y,z.circle.radius);if(!J)return null;return{normalX:-J.normalX,normalY:-J.normalY,depth:J.depth}}return null}var P=new Set;function X(z,E,J,O){if(E)h(z,E,J,O);else v(z,J,O)}function v(z,E,J){for(let O=0;O<z.length;O++){let Z=z[O];if(!Z)continue;for(let Q=O+1;Q<z.length;Q++){let K=z[Q];if(!K)continue;if(!Z.collidesWith.includes(K.layer)&&!K.collidesWith.includes(Z.layer))continue;let k=A(Z,K);if(!k)continue;E(Z,K,k,J)}}}function h(z,E,J,O){let Z=new Map;for(let Q=0;Q<z.length;Q++){let K=z[Q];if(!K)continue;Z.set(K.entityId,K)}for(let Q=0;Q<z.length;Q++){let K=z[Q];if(!K)continue;let k=K.aabb?K.aabb.halfWidth:K.circle?K.circle.radius:0,_=K.aabb?K.aabb.halfHeight:K.circle?K.circle.radius:0;P.clear(),E.queryRectInto(K.x-k,K.y-_,K.x+k,K.y+_,P);for(let j of P){if(j<=K.entityId)continue;let $=Z.get(j);if(!$)continue;if(!K.collidesWith.includes($.layer)&&!$.collidesWith.includes(K.layer))continue;let F=A(K,$);if(!F)continue;J(K,$,F,O)}}}function e(z,E){return{rigidBody:{type:z,mass:z==="static"?1/0:E?.mass??1,drag:E?.drag??0,restitution:E?.restitution??0,friction:E?.friction??0,gravityScale:E?.gravityScale??1},force:{x:0,y:0}}}function c(z,E){return{force:{x:z,y:E}}}function t(z,E,J,O){let Z=z.getComponent(E,"force");if(!Z)return;Z.x+=J,Z.y+=O}function a(z,E,J,O){let Z=z.getComponent(E,"velocity"),Q=z.getComponent(E,"rigidBody");if(!Z||!Q)return;if(Q.mass===1/0||Q.mass===0)return;Z.x+=J/Q.mass,Z.y+=O/Q.mass}function zz(z,E,J,O){let Z=z.getComponent(E,"velocity");if(!Z)return;Z.x=J,Z.y=O}function p(z,E,J,O){let Z=z.rigidBody.type==="dynamic"&&z.rigidBody.mass>0&&z.rigidBody.mass!==1/0?1/z.rigidBody.mass:0,Q=E.rigidBody.type==="dynamic"&&E.rigidBody.mass>0&&E.rigidBody.mass!==1/0?1/E.rigidBody.mass:0,K=Z+Q;if(K>0){let k=J.depth/K;if(Z>0){let F=O.getComponent(z.entityId,"localTransform");if(!F)return;F.x-=k*Z*J.normalX,F.y-=k*Z*J.normalY,z.x=F.x,O.markChanged(z.entityId,"localTransform")}if(Q>0){let F=O.getComponent(E.entityId,"localTransform");if(!F)return;F.x+=k*Q*J.normalX,F.y+=k*Q*J.normalY,O.markChanged(E.entityId,"localTransform")}let _=E.velocity.x-z.velocity.x,j=E.velocity.y-z.velocity.y,$=_*J.normalX+j*J.normalY;if($<0){let T=-(1+Math.min(z.rigidBody.restitution,E.rigidBody.restitution))*$/K;z.velocity.x-=T*Z*J.normalX,z.velocity.y-=T*Z*J.normalY,E.velocity.x+=T*Q*J.normalX,E.velocity.y+=T*Q*J.normalY;let W=_-$*J.normalX,L=j-$*J.normalY,R=Math.sqrt(W*W+L*L);if(R>0.000001){let V=W/R,U=L/R,G=Math.sqrt(z.rigidBody.friction*E.rigidBody.friction)*Math.abs(T),H=Math.min(R/K,G);z.velocity.x+=H*Z*V,z.velocity.y+=H*Z*U,E.velocity.x-=H*Q*V,E.velocity.y-=H*Q*U}}O.markChanged(z.entityId,"velocity"),O.markChanged(E.entityId,"velocity")}O.eventBus.publish("physicsCollision",{entityA:z.entityId,entityB:E.entityId,normal:{x:J.normalX,y:J.normalY},depth:J.depth})}function y(z,E,J,O){p(z,E,J,O)}function Ez(z){let{gravity:E={x:0,y:0},systemGroup:J="physics2D",collisionSystemGroup:O,integrationPriority:Z=1000,collisionPriority:Q=900,phase:K="fixedUpdate"}=z??{};return u({id:"physics2D",install(k){k.registerRequired("rigidBody","velocity",()=>({x:0,y:0})),k.registerRequired("rigidBody","force",()=>({x:0,y:0})),k.addResource("physicsConfig",{gravity:{x:E.x,y:E.y}}),k.addSystem("physics2D-integration").setPriority(Z).inPhase(K).inGroup(J).addQuery("bodies",{with:["localTransform","velocity","rigidBody","force"]}).setProcess(({queries:j,dt:$,ecs:F})=>{let T=F.getResource("physicsConfig"),W=T.gravity.x,L=T.gravity.y;for(let R of j.bodies){let{localTransform:V,velocity:U,rigidBody:D,force:G}=R.components;if(D.type==="static")continue;if(D.type==="dynamic"){if(U.x+=W*D.gravityScale*$,U.y+=L*D.gravityScale*$,D.mass>0&&D.mass!==1/0)U.x+=G.x/D.mass*$,U.y+=G.y/D.mass*$;if(D.drag>0){let H=Math.max(0,1-D.drag*$);U.x*=H,U.y*=H}}V.x+=U.x*$,V.y+=U.y*$,G.x=0,G.y=0,F.markChanged(R.id,"localTransform")}});let _=k.addSystem("physics2D-collision").setPriority(Q).inPhase(K).inGroup(J);if(O)_.inGroup(O);_.addQuery("collidables",{with:["localTransform","rigidBody","velocity","collisionLayer"]}).setProcess(({queries:j,ecs:$})=>{let F=[];for(let W of j.collidables){let{localTransform:L,rigidBody:R,velocity:V,collisionLayer:U}=W.components,D=M(W.id,L.x,L.y,U.layer,U.collidesWith,$.getComponent(W.id,"aabbCollider"),$.getComponent(W.id,"circleCollider"));if(!D)continue;F.push(Object.assign(D,{rigidBody:R,velocity:V}))}let T=S($.tryGetResource.bind($));X(F,T,y,$)})}})}export{zz as setVelocity,e as createRigidBody,Ez as createPhysics2DPlugin,c as createForce,a as applyImpulse,t as applyForce};
1
+ var x=((z)=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(z,{get:(E,K)=>(typeof require<"u"?require:E)[K]}):z)(function(z){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+z+'" is not supported')});import{definePlugin as I}from"ecspresso";function q(z,E,K,Z,Q,O,J){if(!O&&!J)return null;let k={entityId:z,x:E,y:K,layer:Z,collidesWith:Q};if(O)k.x+=O.offsetX??0,k.y+=O.offsetY??0,k.aabb={halfWidth:O.width/2,halfHeight:O.height/2};if(J)k.x+=J.offsetX??0,k.y+=J.offsetY??0,k.circle={radius:J.radius};return k}function C(z){return z("spatialIndex")}function A(z,E,K,Z,Q,O,J,k){let _=Q-z,j=O-E,$=K+J-Math.abs(_),F=Z+k-Math.abs(j);if($<=0||F<=0)return null;if($<F)return{normalX:_>=0?1:-1,normalY:0,depth:$};return{normalX:0,normalY:j>=0?1:-1,depth:F}}function X(z,E,K,Z,Q,O){let J=Z-z,k=Q-E,_=J*J+k*k,j=K+O;if(_>=j*j)return null;let $=Math.sqrt(_);if($===0)return{normalX:1,normalY:0,depth:j};return{normalX:J/$,normalY:k/$,depth:j-$}}function P(z,E,K,Z,Q,O,J){let k=Math.max(z-K,Math.min(Q,z+K)),_=Math.max(E-Z,Math.min(O,E+Z)),j=Q-k,$=O-_,F=j*j+$*$;if(F>=J*J)return null;if(F===0){let W=Q-(z-K),L=z+K-Q,R=O-(E-Z),V=E+Z-O,U=Math.min(W,L,R,V);if(U===L)return{normalX:1,normalY:0,depth:L+J};if(U===W)return{normalX:-1,normalY:0,depth:W+J};if(U===V)return{normalX:0,normalY:1,depth:V+J};return{normalX:0,normalY:-1,depth:R+J}}let T=Math.sqrt(F);return{normalX:j/T,normalY:$/T,depth:J-T}}function M(z,E){if(z.aabb&&E.aabb)return A(z.x,z.y,z.aabb.halfWidth,z.aabb.halfHeight,E.x,E.y,E.aabb.halfWidth,E.aabb.halfHeight);if(z.circle&&E.circle)return X(z.x,z.y,z.circle.radius,E.x,E.y,E.circle.radius);if(z.aabb&&E.circle)return P(z.x,z.y,z.aabb.halfWidth,z.aabb.halfHeight,E.x,E.y,E.circle.radius);if(z.circle&&E.aabb){let K=P(E.x,E.y,E.aabb.halfWidth,E.aabb.halfHeight,z.x,z.y,z.circle.radius);if(!K)return null;return{normalX:-K.normalX,normalY:-K.normalY,depth:K.depth}}return null}var N=new Set;function S(z,E,K,Z){if(E)w(z,E,K,Z);else Y(z,K,Z)}function Y(z,E,K){for(let Z=0;Z<z.length;Z++){let Q=z[Z];if(!Q)continue;for(let O=Z+1;O<z.length;O++){let J=z[O];if(!J)continue;if(!Q.collidesWith.includes(J.layer)&&!J.collidesWith.includes(Q.layer))continue;let k=M(Q,J);if(!k)continue;E(Q,J,k,K)}}}function w(z,E,K,Z){let Q=new Map;for(let O=0;O<z.length;O++){let J=z[O];if(!J)continue;Q.set(J.entityId,J)}for(let O=0;O<z.length;O++){let J=z[O];if(!J)continue;let k=J.aabb?J.aabb.halfWidth:J.circle?J.circle.radius:0,_=J.aabb?J.aabb.halfHeight:J.circle?J.circle.radius:0;N.clear(),E.queryRectInto(J.x-k,J.y-_,J.x+k,J.y+_,N);for(let j of N){if(j<=J.entityId)continue;let $=Q.get(j);if(!$)continue;if(!J.collidesWith.includes($.layer)&&!$.collidesWith.includes(J.layer))continue;let F=M(J,$);if(!F)continue;K(J,$,F,Z)}}}function u(z,E){return{rigidBody:{type:z,mass:z==="static"?1/0:E?.mass??1,drag:E?.drag??0,restitution:E?.restitution??0,friction:E?.friction??0,gravityScale:E?.gravityScale??1},force:{x:0,y:0}}}function p(z,E){return{force:{x:z,y:E}}}function y(z,E,K,Z){let Q=z.getComponent(E,"force");if(!Q)return;Q.x+=K,Q.y+=Z}function b(z,E,K,Z){let Q=z.getComponent(E,"velocity"),O=z.getComponent(E,"rigidBody");if(!Q||!O)return;if(O.mass===1/0||O.mass===0)return;Q.x+=K/O.mass,Q.y+=Z/O.mass}function d(z,E,K,Z){let Q=z.getComponent(E,"velocity");if(!Q)return;Q.x=K,Q.y=Z}function B(z,E,K,Z){let Q=z.rigidBody.type==="dynamic"&&z.rigidBody.mass>0&&z.rigidBody.mass!==1/0?1/z.rigidBody.mass:0,O=E.rigidBody.type==="dynamic"&&E.rigidBody.mass>0&&E.rigidBody.mass!==1/0?1/E.rigidBody.mass:0,J=Q+O;if(J>0){let k=K.depth/J;if(Q>0){let F=Z.getComponent(z.entityId,"localTransform");if(!F)return;F.x-=k*Q*K.normalX,F.y-=k*Q*K.normalY,z.x=F.x,Z.markChanged(z.entityId,"localTransform")}if(O>0){let F=Z.getComponent(E.entityId,"localTransform");if(!F)return;F.x+=k*O*K.normalX,F.y+=k*O*K.normalY,Z.markChanged(E.entityId,"localTransform")}let _=E.velocity.x-z.velocity.x,j=E.velocity.y-z.velocity.y,$=_*K.normalX+j*K.normalY;if($<0){let T=-(1+Math.min(z.rigidBody.restitution,E.rigidBody.restitution))*$/J;z.velocity.x-=T*Q*K.normalX,z.velocity.y-=T*Q*K.normalY,E.velocity.x+=T*O*K.normalX,E.velocity.y+=T*O*K.normalY;let W=_-$*K.normalX,L=j-$*K.normalY,R=Math.sqrt(W*W+L*L);if(R>0.000001){let V=W/R,U=L/R,G=Math.sqrt(z.rigidBody.friction*E.rigidBody.friction)*Math.abs(T),H=Math.min(R/J,G);z.velocity.x+=H*Q*V,z.velocity.y+=H*Q*U,E.velocity.x-=H*O*V,E.velocity.y-=H*O*U}}Z.markChanged(z.entityId,"velocity"),Z.markChanged(E.entityId,"velocity")}Z.eventBus.publish("physicsCollision",{entityA:z.entityId,entityB:E.entityId,normal:{x:K.normalX,y:K.normalY},depth:K.depth})}function f(z,E,K,Z){B(z,E,K,Z)}function r(z){let{gravity:E={x:0,y:0},systemGroup:K="physics2D",collisionSystemGroup:Z,integrationPriority:Q=1000,collisionPriority:O=900,phase:J="fixedUpdate"}=z??{};return I({id:"physics2D",install(k){k.registerRequired("rigidBody","velocity",()=>({x:0,y:0})),k.registerRequired("rigidBody","force",()=>({x:0,y:0})),k.addResource("physicsConfig",{gravity:{x:E.x,y:E.y}}),k.addSystem("physics2D-integration").setPriority(Q).inPhase(J).inGroup(K).addQuery("bodies",{with:["localTransform","velocity","rigidBody","force"]}).setProcess(({queries:j,dt:$,ecs:F})=>{let T=F.getResource("physicsConfig"),W=T.gravity.x,L=T.gravity.y;for(let R of j.bodies){let{localTransform:V,velocity:U,rigidBody:D,force:G}=R.components;if(D.type==="static")continue;if(D.type==="dynamic"){if(U.x+=W*D.gravityScale*$,U.y+=L*D.gravityScale*$,D.mass>0&&D.mass!==1/0)U.x+=G.x/D.mass*$,U.y+=G.y/D.mass*$;if(D.drag>0){let H=Math.max(0,1-D.drag*$);U.x*=H,U.y*=H}}V.x+=U.x*$,V.y+=U.y*$,G.x=0,G.y=0,F.markChanged(R.id,"localTransform")}});let _=k.addSystem("physics2D-collision").setPriority(O).inPhase(J).inGroup(K);if(Z)_.inGroup(Z);_.addQuery("collidables",{with:["localTransform","rigidBody","velocity","collisionLayer"]}).setProcess(({queries:j,ecs:$})=>{let F=[];for(let W of j.collidables){let{localTransform:L,rigidBody:R,velocity:V,collisionLayer:U}=W.components,D=q(W.id,L.x,L.y,U.layer,U.collidesWith,$.getComponent(W.id,"aabbCollider"),$.getComponent(W.id,"circleCollider"));if(!D)continue;F.push(Object.assign(D,{rigidBody:R,velocity:V}))}let T=C($.tryGetResource.bind($));S(F,T,f,$)})}})}export{d as setVelocity,u as createRigidBody,r as createPhysics2DPlugin,p as createForce,b as applyImpulse,y as applyForce};
2
2
 
3
- //# debugId=2F6003A2B3E0AA1D64756E2164756E21
3
+ //# debugId=F2CFD17EA992232B64756E2164756E21
4
4
  //# sourceMappingURL=physics2D.js.map
@@ -5,7 +5,7 @@
5
5
  "/**\n * Physics 2D Plugin for ECSpresso\n *\n * Provides ECS-native arcade physics: gravity, forces, drag, semi-implicit Euler\n * integration, and impulse-based collision response with friction.\n *\n * Reuses collider types from the collision plugin for shape definitions.\n * Has its own collision detection in fixedUpdate for physics response;\n * the existing collision plugin can still run in postUpdate for game logic events.\n */\n\nimport { definePlugin, type Plugin } from 'ecspresso';\nimport type { SystemPhase } from 'ecspresso';\nimport type { WorldConfigFrom } from '../type-utils';\nimport type { TransformComponentTypes, TransformWorldConfig } from './transform';\nimport type { CollisionComponentTypes, LayerFactories } from './collision';\nimport type { Vector2D } from 'ecspresso';\nimport { buildBaseColliderInfo, detectCollisions, tryGetSpatialIndex, type Contact, type BaseColliderInfo } from '../utils/narrowphase';\n\n// ==================== Component Types ====================\n\n/**\n * Rigid body types for physics simulation.\n * - 'dynamic': Fully simulated (gravity, forces, collisions)\n * - 'kinematic': Moves via velocity only (ignores gravity/forces, immovable in collisions)\n * - 'static': Immovable (ignores gravity, forces, and velocity)\n */\nexport type BodyType = 'dynamic' | 'kinematic' | 'static';\n\n/**\n * Rigid body component controlling physics behavior.\n */\nexport interface RigidBody {\n\ttype: BodyType;\n\t/** Mass in arbitrary units. Affects force→acceleration. Infinity = immovable. */\n\tmass: number;\n\t/** Linear velocity damping coefficient (units/sec, 0 = none) */\n\tdrag: number;\n\t/** Bounciness 0–1 (0 = no bounce, 1 = perfectly elastic) */\n\trestitution: number;\n\t/** Surface friction coefficient 0–1 */\n\tfriction: number;\n\t/** Per-entity gravity multiplier (0 = no gravity) */\n\tgravityScale: number;\n}\n\n/**\n * Component types directly provided by the physics plugin.\n */\nexport interface Physics2DOwnComponentTypes {\n\trigidBody: RigidBody;\n\tvelocity: Vector2D;\n\tforce: Vector2D;\n}\n\n/**\n * Full component types available when using the physics plugin\n * (own components + transform + collision dependencies).\n * Convenience alias for consumer code.\n */\nexport interface Physics2DComponentTypes<L extends string = never> extends TransformComponentTypes, CollisionComponentTypes<L>, Physics2DOwnComponentTypes {}\n\n// ==================== Resource Types ====================\n\n/**\n * Physics configuration resource.\n */\nexport interface Physics2DConfig {\n\tgravity: Vector2D;\n}\n\nexport interface Physics2DResourceTypes {\n\tphysicsConfig: Physics2DConfig;\n}\n\n// ==================== Event Types ====================\n\n/**\n * Event emitted for each physics collision pair.\n */\nexport interface Physics2DCollisionEvent {\n\tentityA: number;\n\tentityB: number;\n\t/** Unit normal pointing from A toward B */\n\tnormal: Vector2D;\n\t/** Penetration depth (positive) */\n\tdepth: number;\n}\n\nexport interface Physics2DEventTypes {\n\tphysicsCollision: Physics2DCollisionEvent;\n}\n\n// ==================== Plugin Options ====================\n\nexport interface Physics2DPluginOptions<G extends string = 'physics2D', CG extends string = never> {\n\t/** World gravity vector (default: {x: 0, y: 0}) */\n\tgravity?: Vector2D;\n\t/** System group name (default: 'physics2D') */\n\tsystemGroup?: G;\n\t/** Additional group for the collision system only (default: none).\n\t * When set, the collision system belongs to both `systemGroup` and this group,\n\t * allowing independent enable/disable of collision detection. */\n\tcollisionSystemGroup?: CG;\n\t/** Priority for integration system (default: 1000) */\n\tintegrationPriority?: number;\n\t/** Priority for collision system (default: 900) */\n\tcollisionPriority?: number;\n\t/** Execution phase (default: 'fixedUpdate') */\n\tphase?: SystemPhase;\n}\n\n// ==================== Helper Functions ====================\n\nexport interface RigidBodyOptions {\n\tmass?: number;\n\tdrag?: number;\n\trestitution?: number;\n\tfriction?: number;\n\tgravityScale?: number;\n}\n\n/**\n * Create a rigid body + force component pair.\n * Static bodies automatically get mass=Infinity.\n */\nexport function createRigidBody(\n\ttype: BodyType,\n\toptions?: RigidBodyOptions,\n): { rigidBody: RigidBody; force: Vector2D } {\n\treturn {\n\t\trigidBody: {\n\t\t\ttype,\n\t\t\tmass: type === 'static' ? Infinity : (options?.mass ?? 1),\n\t\t\tdrag: options?.drag ?? 0,\n\t\t\trestitution: options?.restitution ?? 0,\n\t\t\tfriction: options?.friction ?? 0,\n\t\t\tgravityScale: options?.gravityScale ?? 1,\n\t\t},\n\t\tforce: { x: 0, y: 0 },\n\t};\n}\n\n/**\n * Create a force component with initial values.\n */\nexport function createForce(x: number, y: number): { force: Vector2D } {\n\treturn { force: { x, y } };\n}\n\n/**\n * Accumulate a force onto an entity's force component.\n */\nexport function applyForce(\n\tecs: { getComponent(id: number, name: 'force'): Vector2D | undefined },\n\tentityId: number,\n\tfx: number,\n\tfy: number,\n): void {\n\tconst force = ecs.getComponent(entityId, 'force');\n\tif (!force) return;\n\tforce.x += fx;\n\tforce.y += fy;\n}\n\n/**\n * Apply an instantaneous impulse: velocity += impulse / mass.\n */\nexport function applyImpulse(\n\tecs: {\n\t\tgetComponent(id: number, name: 'velocity'): Vector2D | undefined;\n\t\tgetComponent(id: number, name: 'rigidBody'): RigidBody | undefined;\n\t},\n\tentityId: number,\n\tix: number,\n\tiy: number,\n): void {\n\tconst velocity = ecs.getComponent(entityId, 'velocity');\n\tconst rigidBody = ecs.getComponent(entityId, 'rigidBody');\n\tif (!velocity || !rigidBody) return;\n\tif (rigidBody.mass === Infinity || rigidBody.mass === 0) return;\n\tvelocity.x += ix / rigidBody.mass;\n\tvelocity.y += iy / rigidBody.mass;\n}\n\n/**\n * Directly set an entity's velocity.\n */\nexport function setVelocity(\n\tecs: { getComponent(id: number, name: 'velocity'): Vector2D | undefined },\n\tentityId: number,\n\tvx: number,\n\tvy: number,\n): void {\n\tconst velocity = ecs.getComponent(entityId, 'velocity');\n\tif (!velocity) return;\n\tvelocity.x = vx;\n\tvelocity.y = vy;\n}\n\n// ==================== Internal: Collider Info ====================\n\ninterface Physics2DColliderInfo<L extends string = string> extends BaseColliderInfo<L> {\n\trigidBody: RigidBody;\n\tvelocity: Vector2D;\n}\n\n// ==================== Collision Response ====================\n\ninterface PhysicsEcsLike {\n\tgetComponent(id: number, name: 'localTransform'): { x: number; y: number } | undefined;\n\teventBus: { publish(event: 'physicsCollision', data: Physics2DCollisionEvent): void };\n\tmarkChanged(entityId: number, componentName: 'localTransform' | 'velocity'): void;\n}\n\n/**\n * Resolve a physics collision pair: position correction, impulse response, event.\n */\nfunction resolvePhysicsContact(\n\ta: Physics2DColliderInfo,\n\tb: Physics2DColliderInfo,\n\tcontact: Contact,\n\tecs: PhysicsEcsLike,\n): void {\n\tconst invMassA = (a.rigidBody.type === 'dynamic' && a.rigidBody.mass > 0 && a.rigidBody.mass !== Infinity)\n\t\t? 1 / a.rigidBody.mass\n\t\t: 0;\n\tconst invMassB = (b.rigidBody.type === 'dynamic' && b.rigidBody.mass > 0 && b.rigidBody.mass !== Infinity)\n\t\t? 1 / b.rigidBody.mass\n\t\t: 0;\n\tconst totalInvMass = invMassA + invMassB;\n\n\t// Position correction\n\tif (totalInvMass > 0) {\n\t\tconst correctionScale = contact.depth / totalInvMass;\n\n\t\tif (invMassA > 0) {\n\t\t\tconst ltA = ecs.getComponent(a.entityId, 'localTransform');\n\t\t\tif (!ltA) return;\n\t\t\tltA.x -= correctionScale * invMassA * contact.normalX;\n\t\t\tltA.y -= correctionScale * invMassA * contact.normalY;\n\t\t\t// Update cached position for subsequent pairs (collider offset already baked in)\n\t\t\ta.x = ltA.x;\n\t\t\tecs.markChanged(a.entityId, 'localTransform');\n\t\t}\n\n\t\tif (invMassB > 0) {\n\t\t\tconst ltB = ecs.getComponent(b.entityId, 'localTransform');\n\t\t\tif (!ltB) return;\n\t\t\tltB.x += correctionScale * invMassB * contact.normalX;\n\t\t\tltB.y += correctionScale * invMassB * contact.normalY;\n\t\t\tecs.markChanged(b.entityId, 'localTransform');\n\t\t}\n\n\t\t// Velocity response (impulse-based)\n\t\tconst relVelX = b.velocity.x - a.velocity.x;\n\t\tconst relVelY = b.velocity.y - a.velocity.y;\n\t\tconst velAlongNormal = relVelX * contact.normalX + relVelY * contact.normalY;\n\n\t\tif (velAlongNormal < 0) {\n\t\t\tconst restitution = Math.min(a.rigidBody.restitution, b.rigidBody.restitution);\n\t\t\tconst normalImpulse = -(1 + restitution) * velAlongNormal / totalInvMass;\n\n\t\t\ta.velocity.x -= normalImpulse * invMassA * contact.normalX;\n\t\t\ta.velocity.y -= normalImpulse * invMassA * contact.normalY;\n\t\t\tb.velocity.x += normalImpulse * invMassB * contact.normalX;\n\t\t\tb.velocity.y += normalImpulse * invMassB * contact.normalY;\n\n\t\t\t// Friction (tangential impulse)\n\t\t\tconst tangentX = relVelX - velAlongNormal * contact.normalX;\n\t\t\tconst tangentY = relVelY - velAlongNormal * contact.normalY;\n\t\t\tconst tangentSpeed = Math.sqrt(tangentX * tangentX + tangentY * tangentY);\n\n\t\t\tif (tangentSpeed > 1e-6) {\n\t\t\t\tconst tangentNX = tangentX / tangentSpeed;\n\t\t\t\tconst tangentNY = tangentY / tangentSpeed;\n\t\t\t\tconst friction = Math.sqrt(a.rigidBody.friction * b.rigidBody.friction);\n\t\t\t\tconst maxFrictionImpulse = friction * Math.abs(normalImpulse);\n\t\t\t\tconst tangentImpulse = Math.min(tangentSpeed / totalInvMass, maxFrictionImpulse);\n\n\t\t\t\ta.velocity.x += tangentImpulse * invMassA * tangentNX;\n\t\t\t\ta.velocity.y += tangentImpulse * invMassA * tangentNY;\n\t\t\t\tb.velocity.x -= tangentImpulse * invMassB * tangentNX;\n\t\t\t\tb.velocity.y -= tangentImpulse * invMassB * tangentNY;\n\t\t\t}\n\t\t}\n\n\t\tecs.markChanged(a.entityId, 'velocity');\n\t\tecs.markChanged(b.entityId, 'velocity');\n\t}\n\n\tecs.eventBus.publish('physicsCollision', {\n\t\tentityA: a.entityId,\n\t\tentityB: b.entityId,\n\t\tnormal: { x: contact.normalX, y: contact.normalY },\n\t\tdepth: contact.depth,\n\t});\n}\n\n// ==================== Module-level Physics Callback ====================\n\nfunction onPhysicsContact(\n\ta: Physics2DColliderInfo,\n\tb: Physics2DColliderInfo,\n\tcontact: Contact,\n\tecs: PhysicsEcsLike,\n): void {\n\tresolvePhysicsContact(a, b, contact, ecs);\n}\n\n// ==================== Plugin Factory ====================\n\n/**\n * Create a 2D physics plugin for ECSpresso.\n *\n * Provides:\n * - Semi-implicit Euler integration (gravity, forces, drag → velocity → position)\n * - Impulse-based collision response with restitution and friction\n * - physicsCollision events with contact normal and depth\n *\n * @example\n * ```typescript\n * const ecs = ECSpresso.create()\n * .withPlugin(createTransformPlugin())\n * .withPlugin(createPhysics2DPlugin({ gravity: { x: 0, y: 980 } }))\n * .withFixedTimestep(1/60)\n * .build();\n *\n * ecs.spawn({\n * ...createTransform(100, 200),\n * ...createRigidBody('dynamic', { mass: 1, restitution: 0.5 }),\n * velocity: { x: 0, y: 0 },\n * ...createAABBCollider(32, 32),\n * ...createCollisionLayer('player', ['ground']),\n * });\n * ```\n */\n\ntype Physics2DProvides<L extends string = never> = Physics2DOwnComponentTypes & CollisionComponentTypes<L>;\n\nexport function createPhysics2DPlugin<L extends string = never, G extends string = 'physics2D', CG extends string = never>(\n\toptions?: Physics2DPluginOptions<G, CG> & { layers?: LayerFactories<Record<L, readonly string[]>> },\n): Plugin<WorldConfigFrom<Physics2DProvides<L>, Physics2DEventTypes, Physics2DResourceTypes>, TransformWorldConfig, 'physics2D-integration' | 'physics2D-collision', G | CG> {\n\tconst {\n\t\tgravity = { x: 0, y: 0 },\n\t\tsystemGroup = 'physics2D',\n\t\tcollisionSystemGroup,\n\t\tintegrationPriority = 1000,\n\t\tcollisionPriority = 900,\n\t\tphase = 'fixedUpdate',\n\t} = options ?? {};\n\n\treturn definePlugin<WorldConfigFrom<Physics2DProvides<L>, Physics2DEventTypes, Physics2DResourceTypes>, TransformWorldConfig, 'physics2D-integration' | 'physics2D-collision', G | CG>({\n\t\tid: 'physics2D',\n\t\tinstall(world) {\n\t\t\t// rigidBody requires velocity and force — auto-add with zero defaults\n\t\t\tworld.registerRequired('rigidBody', 'velocity', () => ({ x: 0, y: 0 }));\n\t\t\tworld.registerRequired('rigidBody', 'force', () => ({ x: 0, y: 0 }));\n\n\t\t\tworld.addResource('physicsConfig', { gravity: { x: gravity.x, y: gravity.y } });\n\n\t\t\t// ==================== Integration System ====================\n\n\t\t\tworld\n\t\t\t\t.addSystem('physics2D-integration')\n\t\t\t\t.setPriority(integrationPriority)\n\t\t\t\t.inPhase(phase)\n\t\t\t\t.inGroup(systemGroup)\n\t\t\t\t.addQuery('bodies', {\n\t\t\t\t\twith: ['localTransform', 'velocity', 'rigidBody', 'force'],\n\t\t\t\t})\n\t\t\t\t.setProcess(({ queries, dt, ecs }) => {\n\t\t\t\t\tconst config = ecs.getResource('physicsConfig');\n\t\t\t\t\tconst gx = config.gravity.x;\n\t\t\t\t\tconst gy = config.gravity.y;\n\n\t\t\t\t\tfor (const entity of queries.bodies) {\n\t\t\t\t\t\tconst { localTransform, velocity, rigidBody, force } = entity.components;\n\n\t\t\t\t\t\t// Static bodies: skip entirely\n\t\t\t\t\t\tif (rigidBody.type === 'static') continue;\n\n\t\t\t\t\t\t// Dynamic bodies: apply gravity, forces, drag\n\t\t\t\t\t\tif (rigidBody.type === 'dynamic') {\n\t\t\t\t\t\t\t// 1. Gravity\n\t\t\t\t\t\t\tvelocity.x += gx * rigidBody.gravityScale * dt;\n\t\t\t\t\t\t\tvelocity.y += gy * rigidBody.gravityScale * dt;\n\n\t\t\t\t\t\t\t// 2. Forces (F = ma → a = F/m)\n\t\t\t\t\t\t\tif (rigidBody.mass > 0 && rigidBody.mass !== Infinity) {\n\t\t\t\t\t\t\t\tvelocity.x += (force.x / rigidBody.mass) * dt;\n\t\t\t\t\t\t\t\tvelocity.y += (force.y / rigidBody.mass) * dt;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// 3. Drag\n\t\t\t\t\t\t\tif (rigidBody.drag > 0) {\n\t\t\t\t\t\t\t\tconst damping = Math.max(0, 1 - rigidBody.drag * dt);\n\t\t\t\t\t\t\t\tvelocity.x *= damping;\n\t\t\t\t\t\t\t\tvelocity.y *= damping;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Both dynamic and kinematic: integrate position\n\t\t\t\t\t\tlocalTransform.x += velocity.x * dt;\n\t\t\t\t\t\tlocalTransform.y += velocity.y * dt;\n\n\t\t\t\t\t\t// Clear accumulated forces\n\t\t\t\t\t\tforce.x = 0;\n\t\t\t\t\t\tforce.y = 0;\n\n\t\t\t\t\t\tecs.markChanged(entity.id, 'localTransform');\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t// ==================== Collision System ====================\n\n\t\t\tconst collisionSystem = world\n\t\t\t\t.addSystem('physics2D-collision')\n\t\t\t\t.setPriority(collisionPriority)\n\t\t\t\t.inPhase(phase)\n\t\t\t\t.inGroup(systemGroup);\n\n\t\t\tif (collisionSystemGroup) {\n\t\t\t\tcollisionSystem.inGroup(collisionSystemGroup);\n\t\t\t}\n\n\t\t\tcollisionSystem\n\t\t\t\t.addQuery('collidables', {\n\t\t\t\t\twith: ['localTransform', 'rigidBody', 'velocity', 'collisionLayer'],\n\t\t\t\t})\n\t\t\t\t.setProcess(({ queries, ecs }) => {\n\t\t\t\t\tconst colliders: Physics2DColliderInfo<L>[] = [];\n\n\t\t\t\t\tfor (const entity of queries.collidables) {\n\t\t\t\t\t\tconst { localTransform, rigidBody, velocity, collisionLayer } = entity.components;\n\t\t\t\t\t\tconst base = buildBaseColliderInfo(\n\t\t\t\t\t\t\tentity.id, localTransform.x, localTransform.y,\n\t\t\t\t\t\t\tcollisionLayer.layer, collisionLayer.collidesWith,\n\t\t\t\t\t\t\tecs.getComponent(entity.id, 'aabbCollider'),\n\t\t\t\t\t\t\tecs.getComponent(entity.id, 'circleCollider'),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (!base) continue;\n\t\t\t\t\t\tcolliders.push(Object.assign(base, { rigidBody, velocity }));\n\t\t\t\t\t}\n\n\t\t\t\t\tconst si = tryGetSpatialIndex(ecs.tryGetResource.bind(ecs));\n\t\t\t\t\tdetectCollisions(colliders, si, onPhysicsContact, ecs);\n\t\t\t\t});\n\t\t},\n\t});\n}\n",
6
6
  "/**\n * Shared Narrowphase Module\n *\n * Provides contact-computing narrowphase tests and a generic collision\n * iteration pipeline used by both the collision plugin (event-only) and\n * the physics2D plugin (impulse response).\n */\n\nimport type { SpatialIndex } from './spatial-hash';\n\n// ==================== Contact ====================\n\n/** Contact result from a narrowphase test. Normal points from A toward B. */\nexport interface Contact {\n\tnormalX: number;\n\tnormalY: number;\n\t/** Penetration depth (positive = overlapping) */\n\tdepth: number;\n}\n\n// ==================== BaseColliderInfo ====================\n\n/** Minimum collider data shared by collision and physics bundles. */\nexport interface BaseColliderInfo<L extends string = string> {\n\tentityId: number;\n\tx: number;\n\ty: number;\n\tlayer: L;\n\tcollidesWith: readonly L[];\n\taabb?: { halfWidth: number; halfHeight: number };\n\tcircle?: { radius: number };\n}\n\n// ==================== Collider Construction ====================\n\n/**\n * Build a BaseColliderInfo from raw entity/collider component data.\n * Returns null if the entity has neither an AABB nor circle collider.\n * Shared by collision plugin (event-only) and physics2D plugin (impulse response).\n */\nexport function buildBaseColliderInfo<L extends string>(\n\tentityId: number,\n\tx: number,\n\ty: number,\n\tlayer: L,\n\tcollidesWith: readonly L[],\n\taabb: { width: number; height: number; offsetX?: number; offsetY?: number } | undefined,\n\tcircle: { radius: number; offsetX?: number; offsetY?: number } | undefined,\n): BaseColliderInfo<L> | null {\n\tif (!aabb && !circle) return null;\n\n\tconst info: BaseColliderInfo<L> = { entityId, x, y, layer, collidesWith };\n\n\tif (aabb) {\n\t\tinfo.x += aabb.offsetX ?? 0;\n\t\tinfo.y += aabb.offsetY ?? 0;\n\t\tinfo.aabb = { halfWidth: aabb.width / 2, halfHeight: aabb.height / 2 };\n\t}\n\n\tif (circle) {\n\t\tinfo.x += circle.offsetX ?? 0;\n\t\tinfo.y += circle.offsetY ?? 0;\n\t\tinfo.circle = { radius: circle.radius };\n\t}\n\n\treturn info;\n}\n\n// ==================== Spatial Index Lookup ====================\n\n/**\n * Retrieve the optional spatialIndex resource, returning undefined when absent.\n * Centralizes the cross-plugin typed lookup so individual plugins don't each\n * need to import SpatialIndex or repeat the tryGetResource pattern.\n */\nexport function tryGetSpatialIndex(\n\ttryGetResource: <T>(key: string) => T | undefined,\n): SpatialIndex | undefined {\n\treturn tryGetResource<SpatialIndex>('spatialIndex');\n}\n\n// ==================== Narrowphase Tests ====================\n\nexport function computeAABBvsAABB(\n\tax: number, ay: number, ahw: number, ahh: number,\n\tbx: number, by: number, bhw: number, bhh: number,\n): Contact | null {\n\tconst dx = bx - ax;\n\tconst dy = by - ay;\n\tconst overlapX = (ahw + bhw) - Math.abs(dx);\n\tconst overlapY = (ahh + bhh) - Math.abs(dy);\n\n\tif (overlapX <= 0 || overlapY <= 0) return null;\n\n\tif (overlapX < overlapY) {\n\t\treturn {\n\t\t\tnormalX: dx >= 0 ? 1 : -1,\n\t\t\tnormalY: 0,\n\t\t\tdepth: overlapX,\n\t\t};\n\t}\n\treturn {\n\t\tnormalX: 0,\n\t\tnormalY: dy >= 0 ? 1 : -1,\n\t\tdepth: overlapY,\n\t};\n}\n\nexport function computeCircleVsCircle(\n\tax: number, ay: number, ar: number,\n\tbx: number, by: number, br: number,\n): Contact | null {\n\tconst dx = bx - ax;\n\tconst dy = by - ay;\n\tconst distSq = dx * dx + dy * dy;\n\tconst radiusSum = ar + br;\n\n\tif (distSq >= radiusSum * radiusSum) return null;\n\n\tconst dist = Math.sqrt(distSq);\n\tif (dist === 0) {\n\t\treturn { normalX: 1, normalY: 0, depth: radiusSum };\n\t}\n\treturn {\n\t\tnormalX: dx / dist,\n\t\tnormalY: dy / dist,\n\t\tdepth: radiusSum - dist,\n\t};\n}\n\nexport function computeAABBvsCircle(\n\taabbX: number, aabbY: number, ahw: number, ahh: number,\n\tcircleX: number, circleY: number, radius: number,\n): Contact | null {\n\tconst closestX = Math.max(aabbX - ahw, Math.min(circleX, aabbX + ahw));\n\tconst closestY = Math.max(aabbY - ahh, Math.min(circleY, aabbY + ahh));\n\n\tconst dx = circleX - closestX;\n\tconst dy = circleY - closestY;\n\tconst distSq = dx * dx + dy * dy;\n\n\tif (distSq >= radius * radius) return null;\n\n\t// Circle center inside AABB\n\tif (distSq === 0) {\n\t\tconst pushLeft = (circleX - (aabbX - ahw));\n\t\tconst pushRight = ((aabbX + ahw) - circleX);\n\t\tconst pushUp = (circleY - (aabbY - ahh));\n\t\tconst pushDown = ((aabbY + ahh) - circleY);\n\t\tconst minPush = Math.min(pushLeft, pushRight, pushUp, pushDown);\n\n\t\tif (minPush === pushRight) return { normalX: 1, normalY: 0, depth: pushRight + radius };\n\t\tif (minPush === pushLeft) return { normalX: -1, normalY: 0, depth: pushLeft + radius };\n\t\tif (minPush === pushDown) return { normalX: 0, normalY: 1, depth: pushDown + radius };\n\t\treturn { normalX: 0, normalY: -1, depth: pushUp + radius };\n\t}\n\n\tconst dist = Math.sqrt(distSq);\n\treturn {\n\t\tnormalX: dx / dist,\n\t\tnormalY: dy / dist,\n\t\tdepth: radius - dist,\n\t};\n}\n\n// ==================== Contact Dispatcher ====================\n\nexport function computeContact(a: BaseColliderInfo, b: BaseColliderInfo): Contact | null {\n\tif (a.aabb && b.aabb) {\n\t\treturn computeAABBvsAABB(\n\t\t\ta.x, a.y, a.aabb.halfWidth, a.aabb.halfHeight,\n\t\t\tb.x, b.y, b.aabb.halfWidth, b.aabb.halfHeight,\n\t\t);\n\t}\n\n\tif (a.circle && b.circle) {\n\t\treturn computeCircleVsCircle(\n\t\t\ta.x, a.y, a.circle.radius,\n\t\t\tb.x, b.y, b.circle.radius,\n\t\t);\n\t}\n\n\tif (a.aabb && b.circle) {\n\t\treturn computeAABBvsCircle(\n\t\t\ta.x, a.y, a.aabb.halfWidth, a.aabb.halfHeight,\n\t\t\tb.x, b.y, b.circle.radius,\n\t\t);\n\t}\n\n\tif (a.circle && b.aabb) {\n\t\tconst contact = computeAABBvsCircle(\n\t\t\tb.x, b.y, b.aabb.halfWidth, b.aabb.halfHeight,\n\t\t\ta.x, a.y, a.circle.radius,\n\t\t);\n\t\tif (!contact) return null;\n\t\treturn {\n\t\t\tnormalX: -contact.normalX,\n\t\t\tnormalY: -contact.normalY,\n\t\t\tdepth: contact.depth,\n\t\t};\n\t}\n\n\treturn null;\n}\n\n// ==================== Collision Iteration ====================\n\n/** Module-level reusable set for broadphase candidates. */\nconst _broadphaseCandidates = new Set<number>();\n\n/**\n * Generic collision detection pipeline: brute-force or broadphase,\n * with layer filtering and contact computation.\n *\n * Uses a context parameter forwarded to the callback to avoid\n * per-frame closure allocation.\n */\nexport function detectCollisions<I extends BaseColliderInfo, C>(\n\tcolliders: I[],\n\tspatialIndex: SpatialIndex | undefined,\n\tonContact: (a: I, b: I, contact: Contact, context: C) => void,\n\tcontext: C,\n): void {\n\tif (spatialIndex) {\n\t\tbroadphaseDetect(colliders, spatialIndex, onContact, context);\n\t} else {\n\t\tbruteForceDetect(colliders, onContact, context);\n\t}\n}\n\nfunction bruteForceDetect<I extends BaseColliderInfo, C>(\n\tcolliders: I[],\n\tonContact: (a: I, b: I, contact: Contact, context: C) => void,\n\tcontext: C,\n): void {\n\tfor (let i = 0; i < colliders.length; i++) {\n\t\tconst a = colliders[i];\n\t\tif (!a) continue;\n\n\t\tfor (let j = i + 1; j < colliders.length; j++) {\n\t\t\tconst b = colliders[j];\n\t\t\tif (!b) continue;\n\n\t\t\tif (!a.collidesWith.includes(b.layer) && !b.collidesWith.includes(a.layer)) continue;\n\n\t\t\tconst contact = computeContact(a, b);\n\t\t\tif (!contact) continue;\n\n\t\t\tonContact(a, b, contact, context);\n\t\t}\n\t}\n}\n\nfunction broadphaseDetect<I extends BaseColliderInfo, C>(\n\tcolliders: I[],\n\tspatialIndex: SpatialIndex,\n\tonContact: (a: I, b: I, contact: Contact, context: C) => void,\n\tcontext: C,\n): void {\n\tconst colliderMap = new Map<number, I>();\n\tfor (let i = 0; i < colliders.length; i++) {\n\t\tconst c = colliders[i];\n\t\tif (!c) continue;\n\t\tcolliderMap.set(c.entityId, c);\n\t}\n\n\tfor (let i = 0; i < colliders.length; i++) {\n\t\tconst a = colliders[i];\n\t\tif (!a) continue;\n\n\t\tconst aHalfW = a.aabb ? a.aabb.halfWidth : (a.circle ? a.circle.radius : 0);\n\t\tconst aHalfH = a.aabb ? a.aabb.halfHeight : (a.circle ? a.circle.radius : 0);\n\n\t\t_broadphaseCandidates.clear();\n\t\tspatialIndex.queryRectInto(\n\t\t\ta.x - aHalfW, a.y - aHalfH,\n\t\t\ta.x + aHalfW, a.y + aHalfH,\n\t\t\t_broadphaseCandidates,\n\t\t);\n\n\t\tfor (const bId of _broadphaseCandidates) {\n\t\t\tif (bId <= a.entityId) continue;\n\n\t\t\tconst b = colliderMap.get(bId);\n\t\t\tif (!b) continue;\n\n\t\t\tif (!a.collidesWith.includes(b.layer) && !b.collidesWith.includes(a.layer)) continue;\n\n\t\t\tconst contact = computeContact(a, b);\n\t\t\tif (!contact) continue;\n\n\t\t\tonContact(a, b, contact, context);\n\t\t}\n\t}\n}\n"
7
7
  ],
8
- "mappings": "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",
9
- "debugId": "2F6003A2B3E0AA1D64756E2164756E21",
8
+ "mappings": "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",
9
+ "debugId": "F2CFD17EA992232B64756E2164756E21",
10
10
  "names": []
11
11
  }
@@ -1,4 +1,4 @@
1
- var{defineProperty:T,getOwnPropertyNames:h,getOwnPropertyDescriptor:w}=Object,y=Object.prototype.hasOwnProperty;function d(z){return this[z]}var s=(z)=>{var K=(v??=new WeakMap).get(z),F;if(K)return K;if(K=T({},"__esModule",{value:!0}),z&&typeof z==="object"||typeof z==="function"){for(var E of h(z))if(!y.call(K,E))T(K,E,{get:d.bind(z,E),enumerable:!(F=w(z,E))||F.enumerable})}return v.set(z,K),K},v;var l=(z)=>z;function p(z,K){this[z]=l.bind(null,K)}var o=(z,K)=>{for(var F in K)T(z,F,{get:K[F],enumerable:!0,configurable:!0,set:p.bind(K,F)})};var i=(z,K)=>()=>(z&&(K=z(z=0)),K);var C=((z)=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(z,{get:(K,F)=>(typeof require<"u"?require:K)[F]}):z)(function(z){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+z+'" is not supported')});import{definePlugin as c}from"ecspresso";import{createTransformPlugin as a}from"ecspresso/plugins/transform";import{createBounds as H}from"ecspresso/plugins/bounds";import{createTransform as $z,createLocalTransform as kz,createWorldTransform as Ez,DEFAULT_LOCAL_TRANSFORM as Bz,DEFAULT_WORLD_TRANSFORM as Mz}from"ecspresso/plugins/transform";async function r(z){let{Application:K}=await import("pixi.js"),F=new K;return await F.init(z),F}function Y(z,K){let F=K?.scale,E=typeof F==="number"?F:F?.x??1,G=typeof F==="number"?F:F?.y??1;return{x:z?.x??0,y:z?.y??0,rotation:K?.rotation??0,scaleX:E,scaleY:G}}function S(z,K){let F=K?.scale,E=typeof F==="number"?F:F?.x??1,G=typeof F==="number"?F:F?.y??1;return{x:z?.x??0,y:z?.y??0,rotation:K?.rotation??0,scaleX:E,scaleY:G}}function P(z){return{visible:z?.visible??!0,alpha:z?.alpha}}function Fz(z,K,F){if(F?.anchor)z.anchor.set(F.anchor.x,F.anchor.y);return{sprite:z,localTransform:Y(K,F),worldTransform:S(K,F),visible:P(F)}}function Jz(z,K,F){return{graphics:z,localTransform:Y(K,F),worldTransform:S(K,F),visible:P(F)}}function Kz(z,K,F){return{container:z,localTransform:Y(K,F),worldTransform:S(K,F),visible:P(F)}}var n={fit:(z,K)=>{let F=Math.min(z,K);return{scaleX:F,scaleY:F}},cover:(z,K)=>{let F=Math.max(z,K);return{scaleX:F,scaleY:F}},stretch:(z,K)=>({scaleX:z,scaleY:K})};function b(z,K,F,E,G){let V=z/F,j=K/E,{scaleX:X,scaleY:N}=n[G](V,j);return{scaleX:X,scaleY:N,offsetX:(z-F*X)/2,offsetY:(K-E*N)/2,physicalWidth:z,physicalHeight:K,designWidth:F,designHeight:E}}function Qz(z,K,F){return{x:(z-F.offsetX)/F.scaleX,y:(K-F.offsetY)/F.scaleY}}function Uz(z){let{rootContainer:K,systemGroup:F="renderer2d",renderSyncPriority:E=500,transform:G,startLoop:V=!0,renderLayers:j=[],camera:X=!1,screenScale:N}=z,q=N!==void 0,A=N?.width??0,L=N?.height??0,W=N?.mode??"fit",R=new Map,I=new Map,f=()=>{throw Error("renderer2D: createLayerContainer called before initialization")};function g(Z,J){let Q=I.get(Z);if(Q)return Q;let U=f(`layer:${Z}`);return I.set(Z,U),J.addChild(U),U}function u(Z,J){let Q=J.getResource("rootContainer"),U=J.getComponent(Z,"renderLayer");if(U)return g(U,Q);return Q}function O(Z,J,Q){let U=u(Z,Q);if(J.parent!==U)U.addChild(J)}function x(Z,J){let Q=R.get(Z);if(!Q)return;let U=u(Z,J);if(Q.parent!==U)Q.removeFromParent(),U.addChild(Q)}let m="init"in z&&z.init!==void 0;return c({id:"renderer2d",install(Z){if(Z.installPlugin(a(G)),m){let{init:J,container:Q}=z;if(Z.addResource("pixiApp",async()=>{let U=await r(J);if(Q){let _=typeof Q==="string"?document.querySelector(Q):Q;if(_)_.appendChild(U.canvas);else if(typeof Q==="string")console.warn(`Renderer2D plugin: container selector "${Q}" not found`)}return U}),Z.addResource("rootContainer",{dependsOn:["pixiApp"],factory:(U)=>K??U.getResource("pixiApp").stage}),Z.addResource("bounds",{dependsOn:["pixiApp"],factory:(U)=>{if(q)return H(A,L);let _=U.getResource("pixiApp");return H(_.screen.width,_.screen.height)}}),q)Z.addResource("viewportScale",{dependsOn:["pixiApp"],factory:(U)=>{let _=U.getResource("pixiApp");return b(_.screen.width,_.screen.height,A,L,W)}})}else{let J=z.app;if(Z.addResource("pixiApp",J),Z.addResource("rootContainer",K??J.stage),Z.addResource("bounds",q?H(A,L):H(J.screen.width,J.screen.height)),q)Z.addResource("viewportScale",b(J.screen.width,J.screen.height,A,L,W))}if(Z.registerDispose("sprite",({value:J})=>{J.removeFromParent()}),Z.registerDispose("graphics",({value:J})=>{J.removeFromParent()}),Z.registerDispose("container",({value:J})=>{J.removeFromParent()}),Z.registerRequired("sprite","localTransform",()=>Y()),Z.registerRequired("sprite","visible",()=>P()),Z.registerRequired("graphics","localTransform",()=>Y()),Z.registerRequired("graphics","visible",()=>P()),Z.registerRequired("container","localTransform",()=>Y()),Z.registerRequired("container","visible",()=>P()),Z.addSystem("renderer2d-sync").setPriority(E).inPhase("render").inGroup(F).addQuery("sprites",{with:["sprite","worldTransform"],changed:["worldTransform"]}).addQuery("graphics",{with:["graphics","worldTransform"],changed:["worldTransform"]}).addQuery("containers",{with:["container","worldTransform"],changed:["worldTransform"]}).setProcess(({queries:J,ecs:Q})=>{for(let U of J.sprites){let{sprite:_,worldTransform:$}=U.components;_.position.set($.x,$.y),_.rotation=$.rotation,_.scale.set($.scaleX,$.scaleY);let D=Q.getComponent(U.id,"visible");if(D){if(_.visible=D.visible,D.alpha!==void 0)_.alpha=D.alpha}}for(let U of J.graphics){let{graphics:_,worldTransform:$}=U.components;_.position.set($.x,$.y),_.rotation=$.rotation,_.scale.set($.scaleX,$.scaleY);let D=Q.getComponent(U.id,"visible");if(D){if(_.visible=D.visible,D.alpha!==void 0)_.alpha=D.alpha}}for(let U of J.containers){let{container:_,worldTransform:$}=U.components;_.position.set($.x,$.y),_.rotation=$.rotation,_.scale.set($.scaleX,$.scaleY);let D=Q.getComponent(U.id,"visible");if(D){if(_.visible=D.visible,D.alpha!==void 0)_.alpha=D.alpha}}}),Z.addSystem("renderer2d-scene-graph").setPriority(9999).inGroup(F).setOnInitialize(async(J)=>{let Q=J.getResource("pixiApp"),U=J.getResource("rootContainer"),{Container:_}=await import("pixi.js");f=(D)=>{let k=new _;return k.label=D,k};let $;if(q){$=new _,$.label="viewportContainer";let D=J.tryGetResource("viewportScale");if(!D)throw Error("renderer2D: viewportScale resource not found");$.position.set(D.offsetX,D.offsetY),$.scale.set(D.scaleX,D.scaleY);let k=new _;k.label="rootContainer",Q.stage.addChild($),$.addChild(k),J.updateResource("rootContainer",()=>k),U=k}for(let D of j){let k=f(`layer:${D}`);I.set(D,k),U.addChild(k)}if(J.addReactiveQuery("renderer2d-sprites",{with:["sprite"],onEnter:(D)=>{let k=D.components.sprite;R.set(D.id,k),O(D.id,k,J)},onExit:(D)=>{R.delete(D)}}),J.addReactiveQuery("renderer2d-graphics",{with:["graphics"],onEnter:(D)=>{let k=D.components.graphics;R.set(D.id,k),O(D.id,k,J)},onExit:(D)=>{R.delete(D)}}),J.addReactiveQuery("renderer2d-containers",{with:["container"],onEnter:(D)=>{let k=D.components.container;R.set(D.id,k),O(D.id,k,J)},onExit:(D)=>{R.delete(D)}}),J.on("hierarchyChanged",({entityId:D})=>{x(D,J)}),J.onComponentAdded("renderLayer",({entity:D})=>{x(D.id,J)}),J.onComponentRemoved("renderLayer",({entity:D})=>{x(D.id,J)}),X){let D=J.tryGetResource("cameraState");if(!D)throw Error("renderer2D: cameraState resource not found");D.viewportWidth=q?A:Q.screen.width,D.viewportHeight=q?L:Q.screen.height}if(Q.renderer.on("resize",(D,k)=>{if(q){let B=b(D,k,A,L,W),M=J.tryGetResource("viewportScale");if(!M)throw Error("renderer2D: viewportScale resource not found");if(M.scaleX=B.scaleX,M.scaleY=B.scaleY,M.offsetX=B.offsetX,M.offsetY=B.offsetY,M.physicalWidth=D,M.physicalHeight=k,$)$.position.set(B.offsetX,B.offsetY),$.scale.set(B.scaleX,B.scaleY)}else{let B=J.getResource("bounds");if(B.width=D,B.height=k,X){let M=J.tryGetResource("cameraState");if(!M)throw Error("renderer2D: cameraState resource not found");M.viewportWidth=D,M.viewportHeight=k}}}),V)Q.ticker.add((D)=>{J.update(D.deltaMS/1000)})}),X)Z.addSystem("renderer2d-camera-sync").setPriority(900).inPhase("render").inGroup(F).setProcess(({ecs:J})=>{let Q=J.tryGetResource("cameraState");if(!Q)throw Error("renderer2D: cameraState resource not found");let U=J.getResource("rootContainer"),[_,$]=q?[A,L]:[J.getResource("pixiApp").screen.width,J.getResource("pixiApp").screen.height];U.position.set(_/2-(Q.x+Q.shakeOffsetX)*Q.zoom,$/2-(Q.y+Q.shakeOffsetY)*Q.zoom),U.scale.set(Q.zoom),U.rotation=-(Q.rotation+Q.shakeRotation)})}})}export{Qz as physicalToLogical,Ez as createWorldTransform,$z as createTransform,Fz as createSpriteComponents,Uz as createRenderer2DPlugin,kz as createLocalTransform,Jz as createGraphicsComponents,Kz as createContainerComponents,b as computeViewportScale,Mz as DEFAULT_WORLD_TRANSFORM,Bz as DEFAULT_LOCAL_TRANSFORM};
1
+ var u=((J)=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(J,{get:(U,F)=>(typeof require<"u"?require:U)[F]}):J)(function(J){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+J+'" is not supported')});import{definePlugin as g}from"ecspresso";import{createTransformPlugin as m}from"ecspresso/plugins/transform";import{createBounds as H}from"ecspresso/plugins/bounds";import{createTransform as t,createLocalTransform as e,createWorldTransform as zz,DEFAULT_LOCAL_TRANSFORM as Dz,DEFAULT_WORLD_TRANSFORM as Fz}from"ecspresso/plugins/transform";async function h(J){let{Application:U}=await import("pixi.js"),F=new U;return await F.init(J),F}function Y(J,U){let F=U?.scale,M=typeof F==="number"?F:F?.x??1,G=typeof F==="number"?F:F?.y??1;return{x:J?.x??0,y:J?.y??0,rotation:U?.rotation??0,scaleX:M,scaleY:G}}function b(J,U){let F=U?.scale,M=typeof F==="number"?F:F?.x??1,G=typeof F==="number"?F:F?.y??1;return{x:J?.x??0,y:J?.y??0,rotation:U?.rotation??0,scaleX:M,scaleY:G}}function P(J){return{visible:J?.visible??!0,alpha:J?.alpha}}function c(J,U,F){if(F?.anchor)J.anchor.set(F.anchor.x,F.anchor.y);return{sprite:J,localTransform:Y(U,F),worldTransform:b(U,F),visible:P(F)}}function a(J,U,F){return{graphics:J,localTransform:Y(U,F),worldTransform:b(U,F),visible:P(F)}}function r(J,U,F){return{container:J,localTransform:Y(U,F),worldTransform:b(U,F),visible:P(F)}}var w={fit:(J,U)=>{let F=Math.min(J,U);return{scaleX:F,scaleY:F}},cover:(J,U)=>{let F=Math.max(J,U);return{scaleX:F,scaleY:F}},stretch:(J,U)=>({scaleX:J,scaleY:U})};function T(J,U,F,M,G){let V=J/F,j=U/M,{scaleX:X,scaleY:N}=w[G](V,j);return{scaleX:X,scaleY:N,offsetX:(J-F*X)/2,offsetY:(U-M*N)/2,physicalWidth:J,physicalHeight:U,designWidth:F,designHeight:M}}function n(J,U,F){return{x:(J-F.offsetX)/F.scaleX,y:(U-F.offsetY)/F.scaleY}}function s(J){let{rootContainer:U,systemGroup:F="renderer2d",renderSyncPriority:M=500,transform:G,startLoop:V=!0,renderLayers:j=[],camera:X=!1,screenScale:N}=J,q=N!==void 0,A=N?.width??0,L=N?.height??0,W=N?.mode??"fit",R=new Map,I=new Map,f=()=>{throw Error("renderer2D: createLayerContainer called before initialization")};function v(Z,D){let K=I.get(Z);if(K)return K;let Q=f(`layer:${Z}`);return I.set(Z,Q),D.addChild(Q),Q}function S(Z,D){let K=D.getResource("rootContainer"),Q=D.getComponent(Z,"renderLayer");if(Q)return v(Q,K);return K}function O(Z,D,K){let Q=S(Z,K);if(D.parent!==Q)Q.addChild(D)}function x(Z,D){let K=R.get(Z);if(!K)return;let Q=S(Z,D);if(K.parent!==Q)K.removeFromParent(),Q.addChild(K)}let C="init"in J&&J.init!==void 0;return g({id:"renderer2d",install(Z){if(Z.installPlugin(m(G)),C){let{init:D,container:K}=J;if(Z.addResource("pixiApp",async()=>{let Q=await h(D);if(K){let _=typeof K==="string"?document.querySelector(K):K;if(_)_.appendChild(Q.canvas);else if(typeof K==="string")console.warn(`Renderer2D plugin: container selector "${K}" not found`)}return Q}),Z.addResource("rootContainer",{dependsOn:["pixiApp"],factory:(Q)=>U??Q.getResource("pixiApp").stage}),Z.addResource("bounds",{dependsOn:["pixiApp"],factory:(Q)=>{if(q)return H(A,L);let _=Q.getResource("pixiApp");return H(_.screen.width,_.screen.height)}}),q)Z.addResource("viewportScale",{dependsOn:["pixiApp"],factory:(Q)=>{let _=Q.getResource("pixiApp");return T(_.screen.width,_.screen.height,A,L,W)}})}else{let D=J.app;if(Z.addResource("pixiApp",D),Z.addResource("rootContainer",U??D.stage),Z.addResource("bounds",q?H(A,L):H(D.screen.width,D.screen.height)),q)Z.addResource("viewportScale",T(D.screen.width,D.screen.height,A,L,W))}if(Z.registerDispose("sprite",({value:D})=>{D.removeFromParent()}),Z.registerDispose("graphics",({value:D})=>{D.removeFromParent()}),Z.registerDispose("container",({value:D})=>{D.removeFromParent()}),Z.registerRequired("sprite","localTransform",()=>Y()),Z.registerRequired("sprite","visible",()=>P()),Z.registerRequired("graphics","localTransform",()=>Y()),Z.registerRequired("graphics","visible",()=>P()),Z.registerRequired("container","localTransform",()=>Y()),Z.registerRequired("container","visible",()=>P()),Z.addSystem("renderer2d-sync").setPriority(M).inPhase("render").inGroup(F).addQuery("sprites",{with:["sprite","worldTransform"],changed:["worldTransform"]}).addQuery("graphics",{with:["graphics","worldTransform"],changed:["worldTransform"]}).addQuery("containers",{with:["container","worldTransform"],changed:["worldTransform"]}).setProcess(({queries:D,ecs:K})=>{for(let Q of D.sprites){let{sprite:_,worldTransform:$}=Q.components;_.position.set($.x,$.y),_.rotation=$.rotation,_.scale.set($.scaleX,$.scaleY);let z=K.getComponent(Q.id,"visible");if(z){if(_.visible=z.visible,z.alpha!==void 0)_.alpha=z.alpha}}for(let Q of D.graphics){let{graphics:_,worldTransform:$}=Q.components;_.position.set($.x,$.y),_.rotation=$.rotation,_.scale.set($.scaleX,$.scaleY);let z=K.getComponent(Q.id,"visible");if(z){if(_.visible=z.visible,z.alpha!==void 0)_.alpha=z.alpha}}for(let Q of D.containers){let{container:_,worldTransform:$}=Q.components;_.position.set($.x,$.y),_.rotation=$.rotation,_.scale.set($.scaleX,$.scaleY);let z=K.getComponent(Q.id,"visible");if(z){if(_.visible=z.visible,z.alpha!==void 0)_.alpha=z.alpha}}}),Z.addSystem("renderer2d-scene-graph").setPriority(9999).inGroup(F).setOnInitialize(async(D)=>{let K=D.getResource("pixiApp"),Q=D.getResource("rootContainer"),{Container:_}=await import("pixi.js");f=(z)=>{let k=new _;return k.label=z,k};let $;if(q){$=new _,$.label="viewportContainer";let z=D.tryGetResource("viewportScale");if(!z)throw Error("renderer2D: viewportScale resource not found");$.position.set(z.offsetX,z.offsetY),$.scale.set(z.scaleX,z.scaleY);let k=new _;k.label="rootContainer",K.stage.addChild($),$.addChild(k),D.updateResource("rootContainer",()=>k),Q=k}for(let z of j){let k=f(`layer:${z}`);I.set(z,k),Q.addChild(k)}if(D.addReactiveQuery("renderer2d-sprites",{with:["sprite"],onEnter:(z)=>{let k=z.components.sprite;R.set(z.id,k),O(z.id,k,D)},onExit:(z)=>{R.delete(z)}}),D.addReactiveQuery("renderer2d-graphics",{with:["graphics"],onEnter:(z)=>{let k=z.components.graphics;R.set(z.id,k),O(z.id,k,D)},onExit:(z)=>{R.delete(z)}}),D.addReactiveQuery("renderer2d-containers",{with:["container"],onEnter:(z)=>{let k=z.components.container;R.set(z.id,k),O(z.id,k,D)},onExit:(z)=>{R.delete(z)}}),D.on("hierarchyChanged",({entityId:z})=>{x(z,D)}),D.onComponentAdded("renderLayer",({entity:z})=>{x(z.id,D)}),D.onComponentRemoved("renderLayer",({entity:z})=>{x(z.id,D)}),X){let z=D.tryGetResource("cameraState");if(!z)throw Error("renderer2D: cameraState resource not found");z.viewportWidth=q?A:K.screen.width,z.viewportHeight=q?L:K.screen.height}if(K.renderer.on("resize",(z,k)=>{if(q){let E=T(z,k,A,L,W),B=D.tryGetResource("viewportScale");if(!B)throw Error("renderer2D: viewportScale resource not found");if(B.scaleX=E.scaleX,B.scaleY=E.scaleY,B.offsetX=E.offsetX,B.offsetY=E.offsetY,B.physicalWidth=z,B.physicalHeight=k,$)$.position.set(E.offsetX,E.offsetY),$.scale.set(E.scaleX,E.scaleY)}else{let E=D.getResource("bounds");if(E.width=z,E.height=k,X){let B=D.tryGetResource("cameraState");if(!B)throw Error("renderer2D: cameraState resource not found");B.viewportWidth=z,B.viewportHeight=k}}}),V)K.ticker.add((z)=>{D.update(z.deltaMS/1000)})}),X)Z.addSystem("renderer2d-camera-sync").setPriority(900).inPhase("render").inGroup(F).setProcess(({ecs:D})=>{let K=D.tryGetResource("cameraState");if(!K)throw Error("renderer2D: cameraState resource not found");let Q=D.getResource("rootContainer"),[_,$]=q?[A,L]:[D.getResource("pixiApp").screen.width,D.getResource("pixiApp").screen.height];Q.position.set(_/2-(K.x+K.shakeOffsetX)*K.zoom,$/2-(K.y+K.shakeOffsetY)*K.zoom),Q.scale.set(K.zoom),Q.rotation=-(K.rotation+K.shakeRotation)})}})}export{n as physicalToLogical,zz as createWorldTransform,t as createTransform,c as createSpriteComponents,s as createRenderer2DPlugin,e as createLocalTransform,a as createGraphicsComponents,r as createContainerComponents,T as computeViewportScale,Fz as DEFAULT_WORLD_TRANSFORM,Dz as DEFAULT_LOCAL_TRANSFORM};
2
2
 
3
- //# debugId=94CD9C9F93830E4A64756E2164756E21
3
+ //# debugId=BFE63C0BDE8F323C64756E2164756E21
4
4
  //# sourceMappingURL=renderer2D.js.map