babylon.gamepads.ts 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. module BABYLON {
  2. export class Gamepads {
  3. private babylonGamepads: Array<Gamepad> = [];
  4. private oneGamepadConnected: boolean = false;
  5. private isMonitoring: boolean = false;
  6. private gamepadEventSupported: boolean = 'GamepadEvent' in window;
  7. private gamepadSupportAvailable: boolean = <boolean>(navigator.getGamepads ||
  8. !!navigator.webkitGetGamepads || !!navigator.msGetGamepads || !!navigator.webkitGamepads);
  9. private _callbackGamepadConnected: (gamepad: Gamepad) => void;
  10. private _onGamepadConnectedEvent: (evt: Event) => void;
  11. private _onGamepadDisonnectedEvent: (evt: Event) => void;
  12. private static gamepadDOMInfo: HTMLElement;
  13. constructor(ongamedpadconnected: (gamepad: Gamepad) => void) {
  14. this._callbackGamepadConnected = ongamedpadconnected;
  15. if (this.gamepadSupportAvailable) {
  16. // Checking if the gamepad connected event is supported (like in Firefox)
  17. if (this.gamepadEventSupported) {
  18. this._onGamepadConnectedEvent = (evt) => {
  19. this._onGamepadConnected(evt);
  20. };
  21. this._onGamepadDisonnectedEvent = (evt) => {
  22. this._onGamepadDisconnected(evt);
  23. };
  24. window.addEventListener('gamepadconnected', this._onGamepadConnectedEvent, false);
  25. window.addEventListener('gamepaddisconnected', this._onGamepadDisonnectedEvent, false);
  26. }
  27. else {
  28. this._startMonitoringGamepads();
  29. }
  30. }
  31. }
  32. public dispose() {
  33. if (Gamepads.gamepadDOMInfo) {
  34. document.body.removeChild(Gamepads.gamepadDOMInfo);
  35. }
  36. if (this._onGamepadConnectedEvent){
  37. window.removeEventListener('gamepadconnected', this._onGamepadConnectedEvent, false);
  38. window.removeEventListener('gamepaddisconnected', this._onGamepadDisonnectedEvent, false);
  39. this._onGamepadConnectedEvent = null;
  40. this._onGamepadDisonnectedEvent = null;
  41. }
  42. }
  43. private _onGamepadConnected(evt) {
  44. var newGamepad = this._addNewGamepad(evt.gamepad);
  45. if (this._callbackGamepadConnected) this._callbackGamepadConnected(newGamepad);
  46. this._startMonitoringGamepads();
  47. }
  48. private _addNewGamepad(gamepad): Gamepad {
  49. if (!this.oneGamepadConnected) {
  50. this.oneGamepadConnected = true;
  51. if (Gamepads.gamepadDOMInfo) {
  52. document.body.removeChild(Gamepads.gamepadDOMInfo);
  53. Gamepads.gamepadDOMInfo = null;
  54. }
  55. }
  56. var newGamepad;
  57. if ((<string>gamepad.id).search("Xbox 360") !== -1 || (<string>gamepad.id).search("xinput") !== -1) {
  58. newGamepad = new Xbox360Pad(gamepad.id, gamepad.index, gamepad);
  59. }
  60. else {
  61. newGamepad = new GenericPad(gamepad.id, gamepad.index, gamepad);
  62. }
  63. this.babylonGamepads.push(newGamepad);
  64. return newGamepad;
  65. }
  66. private _onGamepadDisconnected(evt) {
  67. // Remove the gamepad from the list of gamepads to monitor.
  68. for (var i in this.babylonGamepads) {
  69. if (this.babylonGamepads[i].index == evt.gamepad.index) {
  70. this.babylonGamepads.splice(+i, 1);
  71. break;
  72. }
  73. }
  74. // If no gamepads are left, stop the polling loop.
  75. if (this.babylonGamepads.length == 0) {
  76. this._stopMonitoringGamepads();
  77. }
  78. }
  79. private _startMonitoringGamepads() {
  80. if (!this.isMonitoring) {
  81. this.isMonitoring = true;
  82. this._checkGamepadsStatus();
  83. }
  84. }
  85. private _stopMonitoringGamepads() {
  86. this.isMonitoring = false;
  87. }
  88. private _checkGamepadsStatus() {
  89. // updating gamepad objects
  90. this._updateGamepadObjects();
  91. for (var i in this.babylonGamepads) {
  92. this.babylonGamepads[i].update();
  93. }
  94. if (this.isMonitoring) {
  95. if (window.requestAnimationFrame) {
  96. window.requestAnimationFrame(() => { this._checkGamepadsStatus(); });
  97. } else if (window.mozRequestAnimationFrame) {
  98. window.mozRequestAnimationFrame(() => { this._checkGamepadsStatus(); });
  99. } else if (window.webkitRequestAnimationFrame) {
  100. window.webkitRequestAnimationFrame(() => { this._checkGamepadsStatus(); });
  101. }
  102. }
  103. }
  104. // This function is called only on Chrome, which does not yet support
  105. // connection/disconnection events, but requires you to monitor
  106. // an array for changes.
  107. private _updateGamepadObjects() {
  108. var gamepads = navigator.getGamepads ? navigator.getGamepads() : (navigator.webkitGetGamepads ? navigator.webkitGetGamepads() : []);
  109. for (var i = 0; i < gamepads.length; i++) {
  110. if (gamepads[i]) {
  111. if (!(gamepads[i].index in this.babylonGamepads)) {
  112. var newGamepad = this._addNewGamepad(gamepads[i]);
  113. if (this._callbackGamepadConnected) {
  114. this._callbackGamepadConnected(newGamepad);
  115. }
  116. }
  117. else {
  118. this.babylonGamepads[i].browserGamepad = gamepads[i];
  119. }
  120. }
  121. }
  122. }
  123. }
  124. export class StickValues {
  125. constructor(public x, public y) {
  126. }
  127. }
  128. export class Gamepad {
  129. private _leftStick: StickValues;
  130. private _rightStick: StickValues;
  131. private _onleftstickchanged: (values: StickValues) => void;
  132. private _onrightstickchanged: (values: StickValues) => void;
  133. constructor(public id: string, public index: number, public browserGamepad) {
  134. if (this.browserGamepad.axes.length >= 2) {
  135. this._leftStick = { x: this.browserGamepad.axes[0], y: this.browserGamepad.axes[1] };
  136. }
  137. if (this.browserGamepad.axes.length >= 4) {
  138. this._rightStick = { x: this.browserGamepad.axes[2], y: this.browserGamepad.axes[3] };
  139. }
  140. }
  141. public onleftstickchanged(callback: (values: StickValues) => void) {
  142. this._onleftstickchanged = callback;
  143. }
  144. public onrightstickchanged(callback: (values: StickValues) => void) {
  145. this._onrightstickchanged = callback;
  146. }
  147. public get leftStick(): StickValues {
  148. return this._leftStick;
  149. }
  150. public set leftStick(newValues: StickValues) {
  151. if (this._onleftstickchanged && (this._leftStick.x !== newValues.x || this._leftStick.y !== newValues.y)) {
  152. this._onleftstickchanged(newValues);
  153. }
  154. this._leftStick = newValues;
  155. }
  156. public get rightStick(): StickValues {
  157. return this._rightStick;
  158. }
  159. public set rightStick(newValues: StickValues) {
  160. if (this._onrightstickchanged && (this._rightStick.x !== newValues.x || this._rightStick.y !== newValues.y)) {
  161. this._onrightstickchanged(newValues);
  162. }
  163. this._rightStick = newValues;
  164. }
  165. public update() {
  166. if (this._leftStick) {
  167. this.leftStick = { x: this.browserGamepad.axes[0], y: this.browserGamepad.axes[1] };
  168. }
  169. if (this._rightStick) {
  170. this.rightStick = { x: this.browserGamepad.axes[2], y: this.browserGamepad.axes[3] };
  171. }
  172. }
  173. }
  174. export class GenericPad extends Gamepad {
  175. private _buttons: Array<number>;
  176. private _onbuttondown: (buttonPressed: number) => void;
  177. private _onbuttonup: (buttonReleased: number) => void;
  178. public onbuttondown(callback: (buttonPressed: number) => void) {
  179. this._onbuttondown = callback;
  180. }
  181. public onbuttonup(callback: (buttonReleased: number) => void) {
  182. this._onbuttonup = callback;
  183. }
  184. constructor(public id: string, public index: number, public gamepad) {
  185. super(id, index, gamepad);
  186. this._buttons = new Array(gamepad.buttons.length);
  187. }
  188. private _setButtonValue(newValue: number, currentValue: number, buttonIndex: number): number {
  189. if (newValue !== currentValue) {
  190. if (this._onbuttondown && newValue === 1) {
  191. this._onbuttondown(buttonIndex);
  192. }
  193. if (this._onbuttonup && newValue === 0) {
  194. this._onbuttonup(buttonIndex);
  195. }
  196. }
  197. return newValue;
  198. }
  199. public update() {
  200. super.update();
  201. for (var index = 0; index < this._buttons.length; index++) {
  202. this._buttons[index] = this._setButtonValue(this.gamepad.buttons[index].value, this._buttons[index], index);
  203. }
  204. }
  205. }
  206. export enum Xbox360Button {
  207. A,
  208. B,
  209. X,
  210. Y,
  211. Start,
  212. Back,
  213. LB,
  214. RB,
  215. LeftStick,
  216. RightStick
  217. }
  218. export enum Xbox360Dpad {
  219. Up,
  220. Down,
  221. Left,
  222. Right
  223. }
  224. export class Xbox360Pad extends Gamepad {
  225. private _leftTrigger: number = 0;
  226. private _rightTrigger: number = 0;
  227. private _onlefttriggerchanged: (value: number) => void;
  228. private _onrighttriggerchanged: (value: number) => void;
  229. private _onbuttondown: (buttonPressed: Xbox360Button) => void;
  230. private _onbuttonup: (buttonReleased: Xbox360Button) => void;
  231. private _ondpaddown: (dPadPressed: Xbox360Dpad) => void;
  232. private _ondpadup: (dPadReleased: Xbox360Dpad) => void;
  233. private _buttonA: number = 0;
  234. private _buttonB: number = 0;
  235. private _buttonX: number = 0;
  236. private _buttonY: number = 0;
  237. private _buttonBack: number = 0;
  238. private _buttonStart: number = 0;
  239. private _buttonLB: number = 0;
  240. private _buttonRB: number = 0;
  241. private _buttonLeftStick: number = 0;
  242. private _buttonRightStick: number = 0;
  243. private _dPadUp: number = 0;
  244. private _dPadDown: number = 0;
  245. private _dPadLeft: number = 0;
  246. private _dPadRight: number = 0;
  247. public onlefttriggerchanged(callback: (value: number) => void) {
  248. this._onlefttriggerchanged = callback;
  249. }
  250. public onrighttriggerchanged(callback: (value: number) => void) {
  251. this._onrighttriggerchanged = callback;
  252. }
  253. public get leftTrigger(): number {
  254. return this._leftTrigger;
  255. }
  256. public set leftTrigger(newValue: number) {
  257. if (this._onlefttriggerchanged && this._leftTrigger !== newValue) {
  258. this._onlefttriggerchanged(newValue);
  259. }
  260. this._leftTrigger = newValue;
  261. }
  262. public get rightTrigger(): number {
  263. return this._rightTrigger;
  264. }
  265. public set rightTrigger(newValue: number) {
  266. if (this._onrighttriggerchanged && this._rightTrigger !== newValue) {
  267. this._onrighttriggerchanged(newValue);
  268. }
  269. this._rightTrigger = newValue;
  270. }
  271. public onbuttondown(callback: (buttonPressed: Xbox360Button) => void) {
  272. this._onbuttondown = callback;
  273. }
  274. public onbuttonup(callback: (buttonReleased: Xbox360Button) => void) {
  275. this._onbuttonup = callback;
  276. }
  277. public ondpaddown(callback: (dPadPressed: Xbox360Dpad) => void) {
  278. this._ondpaddown = callback;
  279. }
  280. public ondpadup(callback: (dPadReleased: Xbox360Dpad) => void) {
  281. this._ondpadup = callback;
  282. }
  283. private _setButtonValue(newValue: number, currentValue: number, buttonType: Xbox360Button): number {
  284. if (newValue !== currentValue) {
  285. if (this._onbuttondown && newValue === 1) {
  286. this._onbuttondown(buttonType);
  287. }
  288. if (this._onbuttonup && newValue === 0) {
  289. this._onbuttonup(buttonType);
  290. }
  291. }
  292. return newValue;
  293. }
  294. private _setDPadValue(newValue: number, currentValue: number, buttonType: Xbox360Dpad): number {
  295. if (newValue !== currentValue) {
  296. if (this._ondpaddown && newValue === 1) {
  297. this._ondpaddown(buttonType);
  298. }
  299. if (this._ondpadup && newValue === 0) {
  300. this._ondpadup(buttonType);
  301. }
  302. }
  303. return newValue;
  304. }
  305. public get buttonA(): number {
  306. return this._buttonA;
  307. }
  308. public set buttonA(value) {
  309. this._buttonA = this._setButtonValue(value, this._buttonA, Xbox360Button.A);
  310. }
  311. public get buttonB(): number {
  312. return this._buttonB;
  313. }
  314. public set buttonB(value) {
  315. this._buttonB = this._setButtonValue(value, this._buttonB, Xbox360Button.B);
  316. }
  317. public get buttonX(): number {
  318. return this._buttonX;
  319. }
  320. public set buttonX(value) {
  321. this._buttonX = this._setButtonValue(value, this._buttonX, Xbox360Button.X);
  322. }
  323. public get buttonY(): number {
  324. return this._buttonY;
  325. }
  326. public set buttonY(value) {
  327. this._buttonY = this._setButtonValue(value, this._buttonY, Xbox360Button.Y);
  328. }
  329. public get buttonStart(): number {
  330. return this._buttonStart;
  331. }
  332. public set buttonStart(value) {
  333. this._buttonStart = this._setButtonValue(value, this._buttonStart, Xbox360Button.Start);
  334. }
  335. public get buttonBack(): number {
  336. return this._buttonBack;
  337. }
  338. public set buttonBack(value) {
  339. this._buttonBack = this._setButtonValue(value, this._buttonBack, Xbox360Button.Back);
  340. }
  341. public get buttonLB(): number {
  342. return this._buttonLB;
  343. }
  344. public set buttonLB(value) {
  345. this._buttonLB = this._setButtonValue(value, this._buttonLB, Xbox360Button.LB);
  346. }
  347. public get buttonRB(): number {
  348. return this._buttonRB;
  349. }
  350. public set buttonRB(value) {
  351. this._buttonRB = this._setButtonValue(value, this._buttonRB, Xbox360Button.RB);
  352. }
  353. public get buttonLeftStick(): number {
  354. return this._buttonLeftStick;
  355. }
  356. public set buttonLeftStick(value) {
  357. this._buttonLeftStick = this._setButtonValue(value, this._buttonLeftStick, Xbox360Button.LeftStick);
  358. }
  359. public get buttonRightStick(): number {
  360. return this._buttonRightStick;
  361. }
  362. public set buttonRightStick(value) {
  363. this._buttonRightStick = this._setButtonValue(value, this._buttonRightStick, Xbox360Button.RightStick);
  364. }
  365. public get dPadUp(): number {
  366. return this._dPadUp;
  367. }
  368. public set dPadUp(value) {
  369. this._dPadUp = this._setDPadValue(value, this._dPadUp, Xbox360Dpad.Up);
  370. }
  371. public get dPadDown(): number {
  372. return this._dPadDown;
  373. }
  374. public set dPadDown(value) {
  375. this._dPadDown = this._setDPadValue(value, this._dPadDown, Xbox360Dpad.Down);
  376. }
  377. public get dPadLeft(): number {
  378. return this._dPadLeft;
  379. }
  380. public set dPadLeft(value) {
  381. this._dPadLeft = this._setDPadValue(value, this._dPadLeft, Xbox360Dpad.Left);
  382. }
  383. public get dPadRight(): number {
  384. return this._dPadRight;
  385. }
  386. public set dPadRight(value) {
  387. this._dPadRight = this._setDPadValue(value, this._dPadRight, Xbox360Dpad.Right);
  388. }
  389. public update() {
  390. super.update();
  391. this.buttonA = this.browserGamepad.buttons[0].value;
  392. this.buttonB = this.browserGamepad.buttons[1].value;
  393. this.buttonX = this.browserGamepad.buttons[2].value;
  394. this.buttonY = this.browserGamepad.buttons[3].value;
  395. this.buttonLB = this.browserGamepad.buttons[4].value;
  396. this.buttonRB = this.browserGamepad.buttons[5].value;
  397. this.leftTrigger = this.browserGamepad.buttons[6].value;
  398. this.rightTrigger = this.browserGamepad.buttons[7].value;
  399. this.buttonBack = this.browserGamepad.buttons[8].value;
  400. this.buttonStart = this.browserGamepad.buttons[9].value;
  401. this.buttonLeftStick = this.browserGamepad.buttons[10].value;
  402. this.buttonRightStick = this.browserGamepad.buttons[11].value;
  403. this.dPadUp = this.browserGamepad.buttons[12].value;
  404. this.dPadDown = this.browserGamepad.buttons[13].value;
  405. this.dPadLeft = this.browserGamepad.buttons[14].value;
  406. this.dPadRight = this.browserGamepad.buttons[15].value;
  407. }
  408. }
  409. }
  410. interface Navigator {
  411. getGamepads(func?: any): any;
  412. webkitGetGamepads(func?: any): any
  413. msGetGamepads(func?: any): any;
  414. webkitGamepads(func?: any): any;
  415. }