@utsp/input
Version:
Comprehensive input management system for UTSP - keyboard, mouse, gamepad, and touch support with unified routing
2 lines (1 loc) • 35.2 kB
JavaScript
var F=Object.defineProperty;var oe=(d,s,e)=>s in d?F(d,s,{enumerable:!0,configurable:!0,writable:!0,value:e}):d[s]=e;var p=(d,s)=>F(d,"name",{value:s,configurable:!0});var u=(d,s,e)=>(oe(d,typeof s!="symbol"?s+"":s,e),e);import{Vector2 as We,Vector3 as Ve}from"@utsp/types";import{InputDeviceType as ze,KeyboardInput as Ye,MouseInput as Xe,GamepadInput as Ne,TouchInput as Fe}from"@utsp/types";var O=(h=>(h.KeyDown="keydown",h.KeyUp="keyup",h.MouseDown="mousedown",h.MouseUp="mouseup",h.MouseMove="mousemove",h.MouseWheel="mousewheel",h.TouchStart="touchstart",h.TouchEnd="touchend",h.TouchMove="touchmove",h.GamepadConnected="gamepadconnected",h.GamepadDisconnected="gamepaddisconnected",h.GamepadButton="gamepadbutton",h.GamepadAxis="gamepadaxis",h))(O||{}),S=class S{constructor(s=window,e={}){u(this,"isActive",!1);u(this,"targetElement");u(this,"config");u(this,"callbacks",{});this.targetElement=s,this.config={enabled:!0,preventDefault:!1,stopPropagation:!1,debug:!1,...e}}isListening(){return this.isActive}destroy(){this.stop(),this.clearCallbacks()}setCallbacks(s){typeof s=="object"&&s!==null&&Object.assign(this.callbacks,s)}clearCallbacks(){this.callbacks={}}getTargetElement(){return this.targetElement}enable(){this.config.enabled=!0,this.isActive||this.start()}disable(){this.config.enabled=!1,this.isActive&&this.stop()}isEnabled(){return this.config.enabled??!0}emit(s,...e){this.callbacks[s]&&this.callbacks[s].forEach(t=>{try{t(...e)}catch(n){this.config.debug&&console.error(`Error in ${s} callback:`,n)}})}log(...s){this.config.debug&&console.warn("[InputSystem]",...s)}};p(S,"BaseInputs");var v=S;function ne(d){return typeof d=="object"&&d!==null&&"start"in d&&"stop"in d&&"reset"in d&&"isListening"in d&&"destroy"in d}p(ne,"isInputs");var j=class j extends v{constructor(e=window,t={}){super(e,t);u(this,"keys",{});u(this,"keyboardCallbacks",{});u(this,"textInputsThisFrame",[]);u(this,"boundHandlers");this.boundHandlers={keyDown:this.handleKeyDown.bind(this),keyUp:this.handleKeyUp.bind(this)}}start(){this.isActive||(this.targetElement.addEventListener("keydown",this.boundHandlers.keyDown),this.targetElement.addEventListener("keyup",this.boundHandlers.keyUp),this.isActive=!0)}stop(){this.isActive&&(this.targetElement.removeEventListener("keydown",this.boundHandlers.keyDown),this.targetElement.removeEventListener("keyup",this.boundHandlers.keyUp),this.isActive=!1)}reset(){this.keys={}}resetDelta(){}poll(){for(let e in this.keys)this.keys[e].justPressed=!1,this.keys[e].justReleased=!1;this.textInputsThisFrame=[]}getTextInputs(){return this.textInputsThisFrame}isKeyPressed(e){return this.keys[e]?.pressed||!1}isKeyJustPressed(e){return this.keys[e]?.justPressed||!1}isKeyJustReleased(e){return this.keys[e]?.justReleased||!1}getKeysPressed(){return Object.keys(this.keys).filter(e=>this.keys[e].pressed)}getKeysJustPressed(){return Object.keys(this.keys).filter(e=>this.keys[e].justPressed)}getKeysJustReleased(){return Object.keys(this.keys).filter(e=>this.keys[e].justReleased)}isAnyKeyPressed(){return Object.values(this.keys).some(e=>e.pressed)}setKeyboardCallbacks(e){this.keyboardCallbacks={...this.keyboardCallbacks,...e}}clearKeyboardCallbacks(){this.keyboardCallbacks={}}setCallbacks(e){this.isKeyboardCallbacks(e)&&this.setKeyboardCallbacks(e)}isKeyboardCallbacks(e){return typeof e=="object"&&e!==null&&("onKeyDown"in e||"onKeyUp"in e)}handleKeyDown(e){try{let t=e.code,n=/^F([1-9]|1[0-2])$/.test(t),o=(e.ctrlKey||e.metaKey)&&(t==="KeyT"||t==="KeyW"||t==="KeyR"||t==="KeyN"||t==="Tab");this.config.preventDefault&&!n&&!o&&e.preventDefault(),this.config.stopPropagation&&!n&&!o&&e.stopPropagation(),this.keys[t]||(this.keys[t]={pressed:!1,justPressed:!1,justReleased:!1}),this.keys[t].pressed||(this.keys[t].justPressed=!0,this.keyboardCallbacks.onKeyDown?.(t,e)),this.keys[t].pressed=!0,this.keys[t].justReleased=!1;let i=e.key;i.length===1&&!e.ctrlKey&&!e.metaKey&&this.textInputsThisFrame.push(i)}catch(t){console.error("Error in keyboard keydown handler:",t)}}handleKeyUp(e){try{let t=e.code,n=/^F([1-9]|1[0-2])$/.test(t),o=(e.ctrlKey||e.metaKey)&&(t==="KeyT"||t==="KeyW"||t==="KeyR"||t==="KeyN"||t==="Tab");this.config.preventDefault&&!n&&!o&&e.preventDefault(),this.config.stopPropagation&&!n&&!o&&e.stopPropagation(),this.keys[t]||(this.keys[t]={pressed:!1,justPressed:!1,justReleased:!1}),this.keys[t].pressed&&(this.keys[t].justReleased=!0,this.keyboardCallbacks.onKeyUp?.(t,e)),this.keys[t].pressed=!1,this.keys[t].justPressed=!1}catch(t){console.error("Error in keyboard keyup handler:",t)}}};p(j,"KeyboardInputs");var E=j;function ie(d,s){let e=new E(d);return s&&e.setCallbacks(s),e.start(),e}p(ie,"useKeyboardInputs");import{Vector2 as C}from"@utsp/types";var H=class H extends v{constructor(e=window,t={}){super(e,t);u(this,"mouseButtons",{left:{pressed:!1,justPressed:!1,justReleased:!1},middle:{pressed:!1,justPressed:!1,justReleased:!1},right:{pressed:!1,justPressed:!1,justReleased:!1}});u(this,"mousePosition",C.zero());u(this,"mouseDelta",C.zero());u(this,"wheelDelta",0);u(this,"mouseCallbacks",{});u(this,"boundHandlers");this.boundHandlers={mouseDown:this.handleMouseDown.bind(this),mouseUp:this.handleMouseUp.bind(this),mouseMove:this.handleMouseMove.bind(this),wheel:this.handleWheel.bind(this),mouseEnter:this.handleMouseEnter.bind(this),mouseLeave:this.handleMouseLeave.bind(this),contextMenu:this.handleContextMenu.bind(this)}}start(){this.isActive||(this.targetElement.addEventListener("mousedown",this.boundHandlers.mouseDown),this.targetElement.addEventListener("mouseup",this.boundHandlers.mouseUp),this.targetElement.addEventListener("mousemove",this.boundHandlers.mouseMove),this.targetElement.addEventListener("wheel",this.boundHandlers.wheel),this.targetElement.addEventListener("mouseenter",this.boundHandlers.mouseEnter),this.targetElement.addEventListener("mouseleave",this.boundHandlers.mouseLeave),this.targetElement.addEventListener("contextmenu",this.boundHandlers.contextMenu),this.isActive=!0)}stop(){this.isActive&&(this.targetElement.removeEventListener("mousedown",this.boundHandlers.mouseDown),this.targetElement.removeEventListener("mouseup",this.boundHandlers.mouseUp),this.targetElement.removeEventListener("mousemove",this.boundHandlers.mouseMove),this.targetElement.removeEventListener("wheel",this.boundHandlers.wheel),this.targetElement.removeEventListener("mouseenter",this.boundHandlers.mouseEnter),this.targetElement.removeEventListener("mouseleave",this.boundHandlers.mouseLeave),this.targetElement.removeEventListener("contextmenu",this.boundHandlers.contextMenu),this.isActive=!1)}reset(){this.mouseButtons={left:{pressed:!1,justPressed:!1,justReleased:!1},middle:{pressed:!1,justPressed:!1,justReleased:!1},right:{pressed:!1,justPressed:!1,justReleased:!1}},this.mousePosition=C.zero(),this.mouseDelta=C.zero(),this.wheelDelta=0}poll(){this.mouseButtons.left.justPressed=!1,this.mouseButtons.left.justReleased=!1,this.mouseButtons.middle.justPressed=!1,this.mouseButtons.middle.justReleased=!1,this.mouseButtons.right.justPressed=!1,this.mouseButtons.right.justReleased=!1,this.resetDelta()}resetDelta(){this.mouseDelta=C.zero(),this.wheelDelta=0}isLeftMousePressed(){return this.mouseButtons.left.pressed}isLeftMouseJustPressed(){return this.mouseButtons.left.justPressed}isLeftMouseJustReleased(){return this.mouseButtons.left.justReleased}isRightMousePressed(){return this.mouseButtons.right.pressed}isRightMouseJustPressed(){return this.mouseButtons.right.justPressed}isRightMouseJustReleased(){return this.mouseButtons.right.justReleased}isMiddleMousePressed(){return this.mouseButtons.middle.pressed}isMiddleMouseJustPressed(){return this.mouseButtons.middle.justPressed}isMiddleMouseJustReleased(){return this.mouseButtons.middle.justReleased}getMousePosition(){return this.mousePosition.clone()}getMouseDelta(){return this.mouseDelta.clone()}getWheelDelta(){return this.wheelDelta}setMouseCallbacks(e){this.mouseCallbacks={...this.mouseCallbacks,...e}}clearMouseCallbacks(){this.mouseCallbacks={}}setCallbacks(e){this.isMouseCallbacks(e)&&this.setMouseCallbacks(e)}isMouseCallbacks(e){return typeof e=="object"&&e!==null&&("onMouseDown"in e||"onMouseUp"in e||"onMouseMove"in e||"onMouseWheel"in e||"onMouseEnter"in e||"onMouseLeave"in e)}handleMouseDown(e){try{switch(this.config.preventDefault&&e.preventDefault(),this.config.stopPropagation&&e.stopPropagation(),e.button){case 0:this.mouseButtons.left.pressed||(this.mouseButtons.left.justPressed=!0),this.mouseButtons.left.pressed=!0,this.mouseButtons.left.justReleased=!1,this.mouseCallbacks.onMouseDown?.("left",this.mousePosition,e);break;case 1:this.mouseButtons.middle.pressed||(this.mouseButtons.middle.justPressed=!0),this.mouseButtons.middle.pressed=!0,this.mouseButtons.middle.justReleased=!1,this.mouseCallbacks.onMouseDown?.("middle",this.mousePosition,e);break;case 2:this.mouseButtons.right.pressed||(this.mouseButtons.right.justPressed=!0),this.mouseButtons.right.pressed=!0,this.mouseButtons.right.justReleased=!1,this.mouseCallbacks.onMouseDown?.("right",this.mousePosition,e);break}}catch(t){console.error("Error in mouse down handler:",t)}}handleMouseUp(e){try{switch(this.config.preventDefault&&e.preventDefault(),this.config.stopPropagation&&e.stopPropagation(),e.button){case 0:this.mouseButtons.left.pressed&&(this.mouseButtons.left.justReleased=!0),this.mouseButtons.left.pressed=!1,this.mouseButtons.left.justPressed=!1,this.mouseCallbacks.onMouseUp?.("left",this.mousePosition,e);break;case 1:this.mouseButtons.middle.pressed&&(this.mouseButtons.middle.justReleased=!0),this.mouseButtons.middle.pressed=!1,this.mouseButtons.middle.justPressed=!1,this.mouseCallbacks.onMouseUp?.("middle",this.mousePosition,e);break;case 2:this.mouseButtons.right.pressed&&(this.mouseButtons.right.justReleased=!0),this.mouseButtons.right.pressed=!1,this.mouseButtons.right.justPressed=!1,this.mouseCallbacks.onMouseUp?.("right",this.mousePosition,e);break}}catch(t){console.error("Error in mouse up handler:",t)}}handleMouseMove(e){try{this.config.preventDefault&&e.preventDefault(),this.config.stopPropagation&&e.stopPropagation();let t=new C(e.clientX,e.clientY);this.mouseDelta=t.subtract(this.mousePosition),this.mousePosition=t,this.mouseCallbacks.onMouseMove?.(this.mousePosition,this.mouseDelta,e)}catch(t){console.error("Error in mouse move handler:",t)}}handleWheel(e){try{this.config.preventDefault&&e.preventDefault(),this.config.stopPropagation&&e.stopPropagation(),this.wheelDelta=e.deltaY,this.mouseCallbacks.onMouseWheel?.(this.wheelDelta,e)}catch(t){console.error("Error in mouse wheel handler:",t)}}handleMouseEnter(e){try{this.mouseCallbacks.onMouseEnter?.(e)}catch(t){console.error("Error in mouse enter handler:",t)}}handleMouseLeave(e){try{this.mouseCallbacks.onMouseLeave?.(e)}catch(t){console.error("Error in mouse leave handler:",t)}}handleContextMenu(e){try{e.preventDefault(),this.config.stopPropagation&&e.stopPropagation()}catch(t){console.error("Error in context menu handler:",t)}}};p(H,"MouseInputs");var T=H;function ae(d,s){let e=new T(d);return s&&e.setCallbacks(s),e.start(),e}p(ae,"useMouseInputs");import{Vector2 as q}from"@utsp/types";var J=class J extends v{constructor(e=window,t={}){super(e,t);u(this,"touches",new Map);u(this,"nativeToInternal",new Map);u(this,"mobileCallbacks",{});u(this,"mobileConfig");u(this,"maxTouches",10);u(this,"lastLogTime",0);u(this,"boundHandlers");this.mobileConfig={targetElement:e,preventDefault:t.preventDefault??!0,passive:t.passive??!1,maxTouches:t.maxTouches??10,enabled:t.enabled??!0,debug:t.debug??!1,stopPropagation:t.stopPropagation??!1},this.maxTouches=this.mobileConfig.maxTouches,this.mobileConfig.preventDefault&&this.mobileConfig.passive&&(console.warn("[MobileInputs] passive=true prevents preventDefault() from working! Setting passive=false."),this.mobileConfig.passive=!1),this.boundHandlers={touchStart:this.handleTouchStart.bind(this),touchEnd:this.handleTouchEnd.bind(this),touchMove:this.handleTouchMove.bind(this),touchCancel:this.handleTouchCancel.bind(this),orientationChange:this.handleOrientationChange.bind(this)}}start(){if(this.isActive)return;let e={passive:!this.mobileConfig.preventDefault&&this.mobileConfig.passive};this.targetElement.addEventListener("touchstart",this.boundHandlers.touchStart,e),this.targetElement.addEventListener("touchend",this.boundHandlers.touchEnd,e),this.targetElement.addEventListener("touchmove",this.boundHandlers.touchMove,e),this.targetElement.addEventListener("touchcancel",this.boundHandlers.touchCancel,e),window.addEventListener("orientationchange",this.boundHandlers.orientationChange),this.isActive=!0}stop(){this.isActive&&(this.targetElement.removeEventListener("touchstart",this.boundHandlers.touchStart),this.targetElement.removeEventListener("touchend",this.boundHandlers.touchEnd),this.targetElement.removeEventListener("touchmove",this.boundHandlers.touchMove),this.targetElement.removeEventListener("touchcancel",this.boundHandlers.touchCancel),window.removeEventListener("orientationchange",this.boundHandlers.orientationChange),this.isActive=!1)}reset(){this.touches.clear(),this.nativeToInternal.clear()}resetDelta(){}poll(){for(let e of this.touches.values())e.justTouched=!1,e.justReleased=!1}isTouchActive(e){return e<0||e>=this.maxTouches?!1:this.touches.has(e)}getTouchPosition(e){if(e<0||e>=this.maxTouches)return null;let t=this.touches.get(e);return t?t.position.clone():null}getTouchStartPosition(e){if(e<0||e>=this.maxTouches)return null;let t=this.touches.get(e);return t?t.startPosition.clone():null}getTouchDelta(e){if(e<0||e>=this.maxTouches)return null;let t=this.touches.get(e);return t?t.position.subtract(t.startPosition):null}getTouchCount(){return this.touches.size}isTouchJustStarted(e){if(e<0||e>=this.maxTouches)return!1;let t=this.touches.get(e);return t?t.justTouched:!1}isTouchJustReleased(e){if(e<0||e>=this.maxTouches)return!1;let t=this.touches.get(e);return t?t.justReleased:!1}isAnyTouchJustStarted(){for(let e of this.touches.values())if(e.justTouched)return!0;return!1}getAllTouches(){return Array.from(this.touches.values())}setMobileCallbacks(e){this.mobileCallbacks={...this.mobileCallbacks,...e}}clearMobileCallbacks(){this.mobileCallbacks={}}setCallbacks(e){this.isMobileCallbacks(e)&&this.setMobileCallbacks(e)}isMobileCallbacks(e){return typeof e=="object"&&e!==null&&("onTouchStart"in e||"onTouchEnd"in e||"onTouchMove"in e||"onTouchCancel"in e||"onOrientationChange"in e)}handleTouchStart(e){try{this.mobileConfig.preventDefault&&e.preventDefault();let t=Array.from(e.changedTouches),n=[];for(let o of t){if(this.touches.size>=this.maxTouches)break;let i=-1;for(let c=0;c<this.maxTouches;c++)if(!this.touches.has(c)){i=c;break}if(i===-1)continue;let a=new q(o.clientX,o.clientY),r={id:i,nativeId:o.identifier,position:a.clone(),startPosition:a.clone(),active:!0,justTouched:!0,justReleased:!1};this.touches.set(i,r),this.nativeToInternal.set(o.identifier,i),n.push(r),console.warn(`\u{1F446} Touch START - ID: ${i}`)}this.mobileCallbacks.onTouchStart?.(n,e)}catch(t){console.error("Error in touch start handler:",t)}}handleTouchEnd(e){try{this.mobileConfig.preventDefault&&e.preventDefault();let t=Array.from(e.changedTouches),n=[];for(let o of t){let i=this.nativeToInternal.get(o.identifier);if(i!==void 0){let a=this.touches.get(i);a&&(a.justReleased=!0,a.justTouched=!1,n.push({...a}))}}for(let o of t){let i=this.nativeToInternal.get(o.identifier);i!==void 0&&(this.touches.delete(i),this.nativeToInternal.delete(o.identifier),console.warn(`\u{1F447} Touch END - ID: ${i}`))}this.mobileCallbacks.onTouchEnd?.(n,e)}catch(t){console.error("Error in touch end handler:",t)}}handleTouchMove(e){try{let t=Array.from(e.changedTouches);this.mobileConfig.debug&&(!this.lastLogTime||Date.now()-this.lastLogTime>200)&&(console.warn(`\u{1F504} TouchMove event - ${t.length} touches changed`),this.lastLogTime=Date.now());for(let n of t){let o=this.nativeToInternal.get(n.identifier);if(o!==void 0){let i=this.touches.get(o);if(i){let a=i.position.clone();i.position=new q(n.clientX,n.clientY),this.mobileConfig.debug&&(!this.lastLogTime||Date.now()-this.lastLogTime>200)&&console.warn(`\u{1F504} Updated touch ${i.id} (native ${n.identifier}) - ${a.x.toFixed(1)},${a.y.toFixed(1)} \u2192 ${n.clientX.toFixed(1)},${n.clientY.toFixed(1)}`)}}else this.mobileConfig.debug&&console.warn(`\u26A0\uFE0F Touch move for unknown native ID ${n.identifier}`)}this.mobileCallbacks.onTouchMove?.(this.getAllTouches(),e)}catch(t){console.error("Error in touch move handler:",t)}}handleTouchCancel(e){try{this.mobileConfig.preventDefault&&e.preventDefault();let t=[],n=Array.from(e.changedTouches);for(let o of n){let i=this.nativeToInternal.get(o.identifier);if(i!==void 0){let a=this.touches.get(i);a&&(a.justReleased=!0,a.justTouched=!1,t.push({...a}))}}for(let o of n){let i=this.nativeToInternal.get(o.identifier);i!==void 0&&(this.touches.delete(i),this.nativeToInternal.delete(o.identifier),this.mobileConfig.debug&&console.warn(`\u274C Touch CANCEL - ID: ${i}, nativeId: ${o.identifier}`))}this.mobileCallbacks.onTouchCancel?.(t,e)}catch(t){console.error("Error in touch cancel handler:",t)}}handleOrientationChange(e){try{let t=(window.screen.orientation&&window.screen.orientation.angle)??window.orientation??0;this.mobileCallbacks.onOrientationChange?.(t)}catch(t){console.error("Error in orientation change handler:",t)}}};p(J,"MobileInputs");var w=J;function re(d,s,e){console.warn("[MobileInputs] useMobileInputs() is deprecated and causes memory leaks. Use useMemo + useEffect instead.");let t=new w(d,e);return s&&t.setCallbacks(s),t.start(),t}p(re,"useMobileInputs");var $=class $ extends v{constructor(e={}){super(window,e);u(this,"gamepads",new Map);u(this,"previousGamepads",new Map);u(this,"gamepadCallbacks",{});u(this,"gamepadConfig");u(this,"pollingIntervalId",null);u(this,"rafId",null);u(this,"boundHandlers");this.gamepadConfig={targetElement:window,maxGamepads:e.maxGamepads??4,axisDeadzone:e.axisDeadzone??.1,pollingInterval:e.pollingInterval??16,autoPolling:e.autoPolling??!0,enabled:e.enabled??!0,debug:e.debug??!1,preventDefault:e.preventDefault??!1,stopPropagation:e.stopPropagation??!1},this.boundHandlers={connected:this.handleGamepadConnected.bind(this),disconnected:this.handleGamepadDisconnected.bind(this)}}start(){this.isActive||(window.addEventListener("gamepadconnected",this.boundHandlers.connected),window.addEventListener("gamepaddisconnected",this.boundHandlers.disconnected),this.gamepadConfig.autoPolling&&this.startPolling(),this.isActive=!0,this.log("GamepadInputs started"))}stop(){this.isActive&&(window.removeEventListener("gamepadconnected",this.boundHandlers.connected),window.removeEventListener("gamepaddisconnected",this.boundHandlers.disconnected),this.stopPolling(),this.isActive=!1,this.log("GamepadInputs stopped"))}reset(){this.gamepads.clear(),this.previousGamepads.clear()}resetDelta(){this.previousGamepads.clear(),this.gamepads.forEach((e,t)=>{this.previousGamepads.set(t,this.cloneGamepadState(e))})}startPolling(){if(this.pollingIntervalId!==null||this.rafId!==null)return;let e=p(()=>{this.poll(),this.rafId=requestAnimationFrame(e)},"poll");this.rafId=requestAnimationFrame(e),this.log("Polling started")}stopPolling(){this.rafId!==null&&(cancelAnimationFrame(this.rafId),this.rafId=null),this.pollingIntervalId!==null&&(clearInterval(this.pollingIntervalId),this.pollingIntervalId=null),this.log("Polling stopped")}poll(){let e=navigator.getGamepads?navigator.getGamepads():[];for(let t=0;t<e.length&&t<this.gamepadConfig.maxGamepads;t++){let n=e[t];n&&this.updateGamepadState(n)}}getConnectedGamepadCount(){return this.gamepads.size}isGamepadConnected(e){return this.gamepads.has(e)&&this.gamepads.get(e).connected}getGamepadState(e){return this.gamepads.get(e)||null}getAllGamepads(){return Array.from(this.gamepads.values()).filter(e=>e.connected)}isButtonPressed(e,t){if(!Number.isInteger(e)||e<0)throw new Error(`Invalid gamepadIndex: ${e}. Must be a non-negative integer.`);if(!Number.isInteger(t)||t<0)throw new Error(`Invalid buttonIndex: ${t}. Must be a non-negative integer.`);let n=this.gamepads.get(e);return!n||!n.connected||t>=n.buttons.length?!1:n.buttons[t].pressed}isButtonJustPressed(e,t){if(!Number.isInteger(e)||e<0)throw new Error(`Invalid gamepadIndex: ${e}. Must be a non-negative integer.`);if(!Number.isInteger(t)||t<0)throw new Error(`Invalid buttonIndex: ${t}. Must be a non-negative integer.`);let n=this.gamepads.get(e);return!n||!n.connected||t>=n.buttons.length?!1:n.buttons[t].justPressed}isButtonJustReleased(e,t){if(!Number.isInteger(e)||e<0)throw new Error(`Invalid gamepadIndex: ${e}. Must be a non-negative integer.`);if(!Number.isInteger(t)||t<0)throw new Error(`Invalid buttonIndex: ${t}. Must be a non-negative integer.`);let n=this.gamepads.get(e);return!n||!n.connected||t>=n.buttons.length?!1:n.buttons[t].justReleased}getButtonValue(e,t){if(!Number.isInteger(e)||e<0)throw new Error(`Invalid gamepadIndex: ${e}. Must be a non-negative integer.`);if(!Number.isInteger(t)||t<0)throw new Error(`Invalid buttonIndex: ${t}. Must be a non-negative integer.`);let n=this.gamepads.get(e);return!n||!n.connected||t>=n.buttons.length?0:n.buttons[t].value}getAxis(e,t){if(!Number.isInteger(e)||e<0)throw new Error(`Invalid gamepadIndex: ${e}. Must be a non-negative integer.`);if(!Number.isInteger(t)||t<0)throw new Error(`Invalid axisIndex: ${t}. Must be a non-negative integer.`);let n=this.gamepads.get(e);if(!n||!n.connected||t>=n.axes.length)return 0;let o=n.axes[t];return this.applyDeadzone(o)}getAxisRaw(e,t){if(!Number.isInteger(e)||e<0)throw new Error(`Invalid gamepadIndex: ${e}. Must be a non-negative integer.`);if(!Number.isInteger(t)||t<0)throw new Error(`Invalid axisIndex: ${t}. Must be a non-negative integer.`);let n=this.gamepads.get(e);return!n||!n.connected||t>=n.axes.length?0:n.axes[t]}getLeftStick(e){return{x:this.getAxis(e,0),y:this.getAxis(e,1)}}getRightStick(e){return{x:this.getAxis(e,2),y:this.getAxis(e,3)}}setGamepadCallbacks(e){this.gamepadCallbacks={...this.gamepadCallbacks,...e}}clearGamepadCallbacks(){this.gamepadCallbacks={}}setCallbacks(e){this.isGamepadCallbacks(e)&&this.setGamepadCallbacks(e)}isGamepadCallbacks(e){return typeof e=="object"&&e!==null&&("onGamepadConnected"in e||"onGamepadDisconnected"in e||"onButtonDown"in e||"onButtonUp"in e||"onAxisMove"in e)}updateGamepadState(e){let t=this.gamepads.get(e.index),n=Array.from(e.buttons).map((a,r)=>{let c=t?.buttons[r],k=a.pressed,m=c?.pressed??!1;return{pressed:k,justPressed:k&&!m,justReleased:!k&&m,value:a.value,touched:a.touched??!1}}),o=Array.from(e.axes),i={id:e.id,index:e.index,connected:e.connected,buttons:n,axes:o,timestamp:e.timestamp,mapping:e.mapping};this.gamepads.set(e.index,i),this.triggerCallbacks(i,t)}triggerCallbacks(e,t){try{e.buttons.forEach((n,o)=>{n.justPressed&&this.gamepadCallbacks.onButtonDown?.(e.index,o,n.value),n.justReleased&&this.gamepadCallbacks.onButtonUp?.(e.index,o)}),e.axes.forEach((n,o)=>{let i=t?.axes[o]??0,a=this.applyDeadzone(n),r=this.applyDeadzone(i);Math.abs(a-r)>.01&&this.gamepadCallbacks.onAxisMove?.(e.index,o,a)})}catch(n){this.log("Error in gamepad callbacks:",n)}}handleGamepadConnected(e){try{this.log(`Gamepad connected: ${e.gamepad.id} at index ${e.gamepad.index}`);let t={id:e.gamepad.id,index:e.gamepad.index,connected:!0,buttons:Array.from(e.gamepad.buttons).map(n=>({pressed:n.pressed,justPressed:!1,justReleased:!1,value:n.value,touched:n.touched??!1})),axes:Array.from(e.gamepad.axes),timestamp:e.gamepad.timestamp,mapping:e.gamepad.mapping};this.gamepads.set(e.gamepad.index,t),this.gamepadCallbacks.onGamepadConnected?.(t)}catch(t){this.log("Error handling gamepad connected:",t)}}handleGamepadDisconnected(e){try{this.log(`Gamepad disconnected at index ${e.gamepad.index}`),this.gamepads.delete(e.gamepad.index),this.previousGamepads.delete(e.gamepad.index),this.gamepadCallbacks.onGamepadDisconnected?.(e.gamepad.index)}catch(t){this.log("Error handling gamepad disconnected:",t)}}applyDeadzone(e){let t=this.gamepadConfig.axisDeadzone;return Math.abs(e)<t?0:(e>0?1:-1)*((Math.abs(e)-t)/(1-t))}cloneGamepadState(e){return{...e,buttons:e.buttons.map(t=>({...t})),axes:[...e.axes]}}};p($,"GamepadInputs");var I=$;function ue(d,s){let e=new I(s);return d&&e.setGamepadCallbacks(d),e.start(),e}p(ue,"useGamepadInputs");import{InputDeviceType as b,KeyboardInput as W,MouseInput as f,isButton as V,isAxis as le}from"@utsp/types";var z=class z{constructor(s={}){u(this,"keyboard",null);u(this,"mouse",null);u(this,"gamepad",null);u(this,"mobile",null);u(this,"config");this.config={enableKeyboardMouse:s.enableKeyboardMouse??!0,enableGamepad:s.enableGamepad??!0,enableMobile:s.enableMobile??!1,targetElement:s.targetElement??window,mobileTargetElement:s.mobileTargetElement??s.targetElement??window,debug:s.debug??!1,keyboardConfig:{preventDefault:!1,stopPropagation:!1,...s.keyboardConfig},mouseConfig:{preventDefault:!1,stopPropagation:!1,...s.mouseConfig},mobileConfig:{preventDefault:!0,passive:!1,maxTouches:10,...s.mobileConfig}},this.initialize()}initialize(){this.config.enableKeyboardMouse&&(this.keyboard=new E(this.config.targetElement,{preventDefault:this.config.keyboardConfig?.preventDefault??!1,stopPropagation:this.config.keyboardConfig?.stopPropagation??!1,debug:this.config.debug}),this.keyboard.start(),this.mouse=new T(this.config.targetElement,{preventDefault:this.config.mouseConfig?.preventDefault??!1,stopPropagation:this.config.mouseConfig?.stopPropagation??!1,debug:this.config.debug}),this.mouse.start(),this.log("Keyboard/Mouse initialized")),this.config.enableGamepad&&(this.gamepad=new I({debug:this.config.debug}),this.gamepad.start(),this.log("Gamepad initialized")),this.config.enableMobile&&(this.config.mobileTargetElement?(this.mobile=new w(this.config.mobileTargetElement,this.config.mobileConfig),this.mobile.start(),this.log("Mobile/Touch initialized")):this.warn("Mobile input enabled but no canvas provided - mobile input will be disabled until setMobileTarget() is called"))}getButton(s,e){if(!V({device:s,input:e}))return this.warn(`Input ${e} on device ${s} is not a button`),!1;switch(s){case b.Keyboard:return this.getKeyboardButton(e);case b.Mouse:return this.getMouseButton(e);case b.Gamepad:return this.getGamepadButton(e);case b.Touch:return this.getTouchButton(e);default:return this.warn(`Unknown device type: ${s}`),!1}}getButtonJustPressed(s,e){if(!V({device:s,input:e}))return this.warn(`Input ${e} on device ${s} is not a button`),!1;switch(s){case b.Keyboard:return this.getKeyboardButtonJustPressed(e);case b.Mouse:return this.getMouseButtonJustPressed(e);case b.Gamepad:return this.getGamepadButtonJustPressed(e);case b.Touch:return this.getTouchButtonJustPressed(e);default:return this.warn(`Unknown device type: ${s}`),!1}}getButtonJustReleased(s,e){if(!V({device:s,input:e}))return this.warn(`Input ${e} on device ${s} is not a button`),!1;switch(s){case b.Keyboard:return this.getKeyboardButtonJustReleased(e);case b.Mouse:return this.getMouseButtonJustReleased(e);case b.Gamepad:return this.getGamepadButtonJustReleased(e);case b.Touch:return this.getTouchButtonJustReleased(e);default:return this.warn(`Unknown device type: ${s}`),!1}}getAxis(s,e){if(!le({device:s,input:e}))return this.warn(`Input ${e} on device ${s} is not an axis`),0;switch(s){case b.Keyboard:return this.warn("Keyboard does not have axis inputs"),0;case b.Mouse:return this.getMouseAxis(e);case b.Gamepad:return this.getGamepadAxis(e);case b.Touch:return this.getTouchAxis(e);default:return this.warn(`Unknown device type: ${s}`),0}}getKeyboardButton(s){if(!this.keyboard)return!1;let e=W[s];return this.keyboard.isKeyPressed(e)}getKeyboardButtonJustPressed(s){if(!this.keyboard)return!1;let e=W[s];return this.keyboard.isKeyJustPressed(e)}getKeyboardButtonJustReleased(s){if(!this.keyboard)return!1;let e=W[s];return this.keyboard.isKeyJustReleased(e)}getMouseButton(s){if(!this.mouse)return!1;switch(s){case f.LeftButton:return this.mouse.isLeftMousePressed();case f.RightButton:return this.mouse.isRightMousePressed();case f.MiddleButton:return this.mouse.isMiddleMousePressed();default:return!1}}getMouseButtonJustPressed(s){if(!this.mouse)return!1;switch(s){case f.LeftButton:return this.mouse.isLeftMouseJustPressed();case f.RightButton:return this.mouse.isRightMouseJustPressed();case f.MiddleButton:return this.mouse.isMiddleMouseJustPressed();default:return!1}}getMouseButtonJustReleased(s){if(!this.mouse)return!1;switch(s){case f.LeftButton:return this.mouse.isLeftMouseJustReleased();case f.RightButton:return this.mouse.isRightMouseJustReleased();case f.MiddleButton:return this.mouse.isMiddleMouseJustReleased();default:return!1}}getGamepadButton(s){return!this.gamepad||s>=100?!1:this.gamepad.isButtonPressed(0,s)}getGamepadButtonJustPressed(s){return!this.gamepad||s>=100?!1:this.gamepad.isButtonJustPressed(0,s)}getGamepadButtonJustReleased(s){return!this.gamepad||s>=100?!1:this.gamepad.isButtonJustReleased(0,s)}getTouchButton(s){return this.mobile?s>=100?!1:this.mobile.isTouchActive?.(s)??!1:(console.warn("\u{1F6AB} MobileInputs not initialized!"),!1)}getTouchButtonJustPressed(s){return!this.mobile||s>=100?!1:this.mobile.isTouchJustStarted?.(s)??!1}getTouchButtonJustReleased(s){return!this.mobile||s>=100?!1:this.mobile.isTouchJustReleased?.(s)??!1}getMouseAxis(s){if(!this.mouse)return 0;switch(s){case f.PositionX:return this.mouse.getMousePosition().x;case f.PositionY:return this.mouse.getMousePosition().y;case f.DeltaX:return this.mouse.getMouseDelta().x;case f.DeltaY:return this.mouse.getMouseDelta().y;case f.WheelDeltaY:return this.mouse.getWheelDelta();default:return 0}}getGamepadAxis(s){if(!this.gamepad||s<100)return 0;let e=s-100;return this.gamepad.getAxis(0,e)}getTouchAxis(s){if(!this.mobile)return 0;if(s>=100&&s<200){let e=Math.floor((s-100)/2),t=(s-100)%2===0,n=this.mobile.getTouchPosition?.(e);return this.config.debug&&n&&console.warn(`\u{1F3AF} getTouchAxis(${s}) - touchIndex: ${e}, ${t?"X":"Y"}: ${t?n.x:n.y}`),n?t?n.x:n.y:0}return 0}getMousePosition(){if(!this.mouse)return null;let s=this.mouse.getMousePosition();return{x:s.x,y:s.y}}setMobileTarget(s){if(!s){this.warn("setMobileTarget() called with null/undefined canvas - mobile input will remain disabled");return}if(this.config.mobileTargetElement=s,!this.config.enableMobile){this.warn("setMobileTarget() called but mobile input is disabled in config");return}this.mobile&&this.mobile.stop(),this.mobile=new w(s,this.config.mobileConfig),this.mobile.start()}getTextInputs(){return this.keyboard?this.keyboard.getTextInputs():[]}start(){this.keyboard?.start(),this.mouse?.start(),this.log("Input router started")}stop(){this.keyboard?.stop(),this.mouse?.stop(),this.log("Input router stopped")}reset(){this.keyboard?.reset(),this.mouse?.reset(),this.log("Input router reset")}poll(){this.keyboard?.poll(),this.mouse?.poll(),this.gamepad?.poll(),this.mobile?.poll()}isListening(){return this.keyboard!==null&&this.config.enableKeyboardMouse||this.gamepad!==null&&this.config.enableGamepad||this.mobile!==null&&this.config.enableMobile}destroy(){this.keyboard?.destroy(),this.mouse?.destroy(),this.keyboard=null,this.mouse=null,this.gamepad=null,this.mobile=null,this.log("Input router destroyed")}log(s){this.config.debug&&console.warn(`[InputRouter] ${s}`)}warn(s){console.warn(`[InputRouter] ${s}`)}};p(z,"UnifiedInputRouter");var U=z;import{InputDeviceType as l,MouseInput as Q}from"@utsp/types";var X=class X{static collectAxisSources(s,e){let t=new Map;for(let n of s)for(let o of n.sources){if(t.has(o.sourceId))continue;let i=0,a=!1;if(o.type===l.Keyboard&&o.negativeKey!==void 0&&o.positiveKey!==void 0){let r=e.getButton(l.Keyboard,o.negativeKey);e.getButton(l.Keyboard,o.positiveKey)&&(i+=1),r&&(i-=1),a=!0}else if(o.type===l.Mouse&&o.mouseAxis!==void 0)i=e.getAxis(l.Mouse,o.mouseAxis),a=!0;else if(o.type===l.Gamepad&&o.axis!==void 0)i=e.getAxis(l.Gamepad,o.axis),a=!0;else if(o.type===l.Touch&&o.touchId!==void 0&&o.touchAxis!==void 0){let r=100+o.touchId*2,c=o.touchAxis==="x"?r:r+1;i=e.getAxis(l.Touch,c),a=!0}a&&t.set(o.sourceId,i)}return t}static collectButtonSources(s,e){let t=new Map;for(let n of s)for(let o of n.sources){if(t.has(o.sourceId))continue;let i=!1,a=!1;o.type===l.Keyboard&&o.key!==void 0?(i=e.getButton(l.Keyboard,o.key),a=!0):o.type===l.Mouse&&o.mouseButton!==void 0?(i=e.getButton(l.Mouse,o.mouseButton),a=!0):o.type===l.Gamepad&&o.button!==void 0?(i=e.getButton(l.Gamepad,o.button),a=!0):o.type===l.Touch&&o.touchButton!==void 0&&(i=e.getButton(l.Touch,o.touchButton),a=!0),a&&t.set(o.sourceId,i)}return t}static collectButtonSourcesWithTransitions(s,e){let t=new Map;for(let n of s)for(let o of n.sources){if(t.has(o.sourceId))continue;let i=!1,a=!1,r=!1,c=!1;o.type===l.Keyboard&&o.key!==void 0?(i=e.getButton(l.Keyboard,o.key),a=e.getButtonJustPressed?.(l.Keyboard,o.key)??!1,r=e.getButtonJustReleased?.(l.Keyboard,o.key)??!1,c=!0):o.type===l.Mouse&&o.mouseButton!==void 0?(i=e.getButton(l.Mouse,o.mouseButton),a=e.getButtonJustPressed?.(l.Mouse,o.mouseButton)??!1,r=e.getButtonJustReleased?.(l.Mouse,o.mouseButton)??!1,c=!0):o.type===l.Gamepad&&o.button!==void 0?(i=e.getButton(l.Gamepad,o.button),a=e.getButtonJustPressed?.(l.Gamepad,o.button)??!1,r=e.getButtonJustReleased?.(l.Gamepad,o.button)??!1,c=!0):o.type===l.Touch&&o.touchButton!==void 0&&(i=e.getButton(l.Touch,o.touchButton),a=e.getButtonJustPressed?.(l.Touch,o.touchButton)??!1,r=e.getButtonJustReleased?.(l.Touch,o.touchButton)??!1,c=!0),c&&t.set(o.sourceId,{pressed:i,justPressed:a,justReleased:r})}return t}static collectMousePosition(s,e,t,n,o){let i=s.getAxis(l.Mouse,Q.PositionX),a=s.getAxis(l.Mouse,Q.PositionY),r=e.getBoundingClientRect(),c=e.width/e.height,k=r.width/r.height,m,g,h,y;c>k?(m=r.width,g=r.width/c,h=0,y=(r.height-g)/2):(m=r.height*c,g=r.height,h=(r.width-m)/2,y=0);let x=o?.offsetX||0,P=o?.offsetY||0;h+=x,y+=P,m-=2*x,g-=2*P;let B=i-r.left-h,D=a-r.top-y,M=m/t,G=g/n,N=Math.floor(B/M),K=Math.floor(D/G),L=B>=0&&B<m&&D>=0&&D<g;return{x:Math.max(0,Math.min(t-1,N)),y:Math.max(0,Math.min(n-1,K)),over:L}}static collectTouchPositions(s,e,t,n,o=10,i){let a=[],r=e.getBoundingClientRect(),c=e.width/e.height,k=r.width/r.height,m,g,h,y;c>k?(m=r.width,g=r.width/c,h=0,y=(r.height-g)/2):(m=r.height*c,g=r.height,h=(r.width-m)/2,y=0);let x=i?.offsetX||0,P=i?.offsetY||0;h+=x,y+=P,m-=2*x,g-=2*P;let B=m/t,D=g/n;for(let M=0;M<o;M++){let G=M;if(s.getButton(l.Touch,G)){let K=100+M*2,L=101+M*2,Z=s.getAxis(l.Touch,K),_=s.getAxis(l.Touch,L),R=Z-r.left-h,A=_-r.top-y,ee=Math.floor(R/B),te=Math.floor(A/D),se=R>=0&&R<m&&A>=0&&A<g;a.push({id:M,x:Math.max(0,Math.min(t-1,ee)),y:Math.max(0,Math.min(n-1,te)),over:se})}}return a}static collectTextInputs(s){return typeof s.getTextInputs=="function"?s.getTextInputs():[]}};p(X,"InputCollector");var Y=X;export{v as BaseInputs,Ne as GamepadInput,I as GamepadInputs,Y as InputCollector,ze as InputDeviceType,O as InputEventType,Ye as KeyboardInput,E as KeyboardInputs,w as MobileInputs,Xe as MouseInput,T as MouseInputs,Fe as TouchInput,U as UnifiedInputRouter,We as Vector2,Ve as Vector3,ne as isInputs,ue as useGamepadInputs,ie as useKeyboardInputs,re as useMobileInputs,ae as useMouseInputs};