@flyskypie/joypad-ts
Version:
A JavaScript library that lets you connect various gaming controllers to your browser using the Gamepad API.
2 lines (1 loc) • 5.19 kB
JavaScript
(function(l,i){typeof exports=="object"&&typeof module<"u"?module.exports=i():typeof define=="function"&&define.amd?define(i):(l=typeof globalThis<"u"?globalThis:l||self,l.joypadTs=i())})(this,function(){"use strict";var y=Object.defineProperty;var P=(l,i,n)=>i in l?y(l,i,{enumerable:!0,configurable:!0,writable:!0,value:n}):l[i]=n;var u=(l,i,n)=>(P(l,typeof i!="symbol"?i+"":i,n),n);class l{constructor(){u(this,"events",{})}publish(e,s){this.events.hasOwnProperty(e)&&this.events[e].forEach(o=>o(s))}subscribe(e,s){return this.events.hasOwnProperty(e)||(this.events[e]=[]),this.events[e].push(s),{unsubscribe:()=>{const o=this.events[e].indexOf(s);o!==-1&&this.events[e].splice(o,1)}}}}const i=new l;var n=(t=>(t.CONNECT_NATIVE="gamepadconnected",t.CONNECT_ALIAS="connect",t.DISCONNECT_NATIVE="gamepaddisconnected",t.DISCONNECT_ALIAS="disconnect",t.BUTTON_PRESS_ALIAS="button_press",t.BUTTON_RELEASE_ALIAS="button_release",t.AXIS_MOVEMENT_ALIAS="axis_move",t))(n||{});const T={LEFT:{NAME:"left_stick",AXES:{X:0,Y:1}},RIGHT:{NAME:"right_stick",AXES:{X:2,Y:3}}},E={LEFT:"left",RIGHT:"right",TOP:"top",BOTTOM:"bottom"},I={button_0:0,button_1:1,button_2:2,button_3:3,button_4:4,button_5:5,button_6:6,button_7:7,button_8:8,button_9:9,button_10:10,button_11:11,button_12:12,button_13:13,button_14:14,button_15:15,button_16:16,button_17:17},O=.8,f=(...t)=>{console.warn&&typeof console.warn=="function"?console.warn(...t):console.log(...t)},L=(t,e)=>{let s=[];return Object.keys(e).forEach(o=>{e[o]===t&&s.push(o);const r=e[o];Array.isArray(r)&&r.indexOf(t)!==-1&&s.push(o)}),s},N=t=>!!(t&&t.type&&t.playEffect&&typeof t.playEffect=="function"),b=()=>!!(window.navigator.getGamepads&&typeof window.navigator.getGamepads=="function");class M{constructor(){u(this,"loopStarted",!1);u(this,"instances",{});u(this,"buttonEvents",{joypad:[]});u(this,"settings",{axisMovementThreshold:O})}remove(e){return delete this.instances[e]}on(e,s){switch(e){case n.CONNECT_ALIAS:return i.subscribe(n.CONNECT_ALIAS,s);case n.DISCONNECT_ALIAS:return i.subscribe(n.DISCONNECT_ALIAS,s);case n.BUTTON_PRESS_ALIAS:return i.subscribe(n.BUTTON_PRESS_ALIAS,s);case n.BUTTON_RELEASE_ALIAS:return i.subscribe(n.BUTTON_RELEASE_ALIAS,s);case n.AXIS_MOVEMENT_ALIAS:return i.subscribe(n.AXIS_MOVEMENT_ALIAS,s)}}vibrate(e,s){const{vibrationActuator:o}=e,r=s||this.settings.vibration;if(N(o)){const{type:a}=o;return o.playEffect(a,r)}else f("No vibration actuator interface found - https://developer.mozilla.org/en-US/docs/Web/API/GamepadHapticActuator")}set(e){const{axisMovementThreshold:s,vibration:o,customButtonMapping:r}=e;if(s!==void 0){const a=typeof s=="string"?parseFloat(s):s;this.settings.axisMovementThreshold=a}this.settings.vibration=o,this.settings.customButtonMapping=r}trigger(e,s){return i.publish(e,s)}}const d=new M;class w{constructor(){u(this,"id",null);u(this,"start",()=>{const e=window.requestAnimationFrame,{buttonEvents:s}=d;let o=window.navigator.getGamepads();o=Array.prototype.slice.call(o),o.forEach((r,a)=>{r&&(s.joypad[a]||(s.joypad[a]={}),d.instances[a]=r,v(r),C(r))}),s.joypad.forEach(r=>{r&&Object.keys(r).forEach(a=>{B(a,r)})}),this.id=e(this.start)})}stop(e){if(e===null)return;const s=window.cancelAnimationFrame;return s(e)}}const S=new w,g=()=>{window.addEventListener(n.CONNECT_NATIVE,t=>{if(i.publish(n.CONNECT_ALIAS,t),!d.loopStarted)return d.loopStarted=!0,S.start()}),window.addEventListener(n.DISCONNECT_NATIVE,t=>{if(i.publish(n.DISCONNECT_ALIAS,t),d.remove(t.gamepad.index),d.buttonEvents.joypad[t.gamepad.index]=null,!Object.keys(d.instances).length)return d.loopStarted=!1,S.stop(S.id)}),window.addEventListener(n.BUTTON_PRESS_ALIAS,t=>i.publish(n.BUTTON_PRESS_ALIAS,t)),window.addEventListener(n.BUTTON_RELEASE_ALIAS,t=>i.publish(n.BUTTON_RELEASE_ALIAS,t)),window.addEventListener(n.AXIS_MOVEMENT_ALIAS,t=>i.publish(n.AXIS_MOVEMENT_ALIAS,t))},v=t=>{t.buttons.forEach((e,s)=>{const{customButtonMapping:o}=d.settings,a=L(s,o||I),{buttonEvents:p}=d;a&&a.length&&a.forEach(c=>{const A=p.joypad[t.index];A&&(e.pressed?(A[c]||(A[c]={pressed:!0,hold:!1,released:!1}),A[c].button=e,A[c].index=s,A[c].gamepad=t):!e.pressed&&A[c]&&(A[c].released=!0,A[c].hold=!1))})})},C=t=>{const e=p=>new CustomEvent(n.AXIS_MOVEMENT_ALIAS,{detail:p}),{axisMovementThreshold:s}=d.settings,{axes:o}=t,a=o.length/2;o.forEach((p,c)=>{if(s&&Math.abs(p)>s){let A=null,_=E.BOTTOM,R=p;c<a?A=T.LEFT.NAME:A=T.RIGHT.NAME,(c===T.LEFT.AXES.X||c===T.RIGHT.AXES.X)&&(_=p<0?E.LEFT:E.RIGHT),(c===T.LEFT.AXES.Y||c===T.RIGHT.AXES.Y)&&(_=p<0?E.TOP:E.BOTTOM);const m={gamepad:t,totalSticks:a,stickMoved:A,directionOfMovement:_,axisMovementValue:R,axis:c};return window.dispatchEvent(e(m))}})},h=(t,e,s)=>{const o=c=>new CustomEvent(t,{detail:c}),{index:r,gamepad:a}=e[s],p={buttonName:s,button:e[s].button,index:r,gamepad:a};window.dispatchEvent(o(p))},B=(t,e)=>{e[t].pressed?(h(n.BUTTON_PRESS_ALIAS,e,t),e[t].pressed=!1,e[t].hold=!0,e[t].last_event=n.BUTTON_PRESS_ALIAS):e[t].hold||e[t].released&&e[t].last_event===n.BUTTON_PRESS_ALIAS&&(h(n.BUTTON_RELEASE_ALIAS,e,t),delete e[t])};return g(),b()||f("Your browser does not support the Gamepad API - https://developer.mozilla.org/en-US/docs/Web/API/Gamepad_API"),d});