webXRControllerComponent.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. import { Observable } from "../../Misc/observable.js";
  2. /**
  3. * This class represents a single component (for example button or thumbstick) of a motion controller
  4. */
  5. export class WebXRControllerComponent {
  6. /**
  7. * Creates a new component for a motion controller.
  8. * It is created by the motion controller itself
  9. *
  10. * @param id the id of this component
  11. * @param type the type of the component
  12. * @param _buttonIndex index in the buttons array of the gamepad
  13. * @param _axesIndices indices of the values in the axes array of the gamepad
  14. */
  15. constructor(
  16. /**
  17. * the id of this component
  18. */
  19. id,
  20. /**
  21. * the type of the component
  22. */
  23. type, _buttonIndex = -1, _axesIndices = []) {
  24. this.id = id;
  25. this.type = type;
  26. this._buttonIndex = _buttonIndex;
  27. this._axesIndices = _axesIndices;
  28. this._axes = {
  29. x: 0,
  30. y: 0,
  31. };
  32. this._changes = {};
  33. this._currentValue = 0;
  34. this._hasChanges = false;
  35. this._pressed = false;
  36. this._touched = false;
  37. /**
  38. * If axes are available for this component (like a touchpad or thumbstick) the observers will be notified when
  39. * the axes data changes
  40. */
  41. this.onAxisValueChangedObservable = new Observable();
  42. /**
  43. * Observers registered here will be triggered when the state of a button changes
  44. * State change is either pressed / touched / value
  45. */
  46. this.onButtonStateChangedObservable = new Observable();
  47. }
  48. /**
  49. * The current axes data. If this component has no axes it will still return an object { x: 0, y: 0 }
  50. */
  51. get axes() {
  52. return this._axes;
  53. }
  54. /**
  55. * Get the changes. Elements will be populated only if they changed with their previous and current value
  56. */
  57. get changes() {
  58. return this._changes;
  59. }
  60. /**
  61. * Return whether or not the component changed the last frame
  62. */
  63. get hasChanges() {
  64. return this._hasChanges;
  65. }
  66. /**
  67. * is the button currently pressed
  68. */
  69. get pressed() {
  70. return this._pressed;
  71. }
  72. /**
  73. * is the button currently touched
  74. */
  75. get touched() {
  76. return this._touched;
  77. }
  78. /**
  79. * Get the current value of this component
  80. */
  81. get value() {
  82. return this._currentValue;
  83. }
  84. /**
  85. * Dispose this component
  86. */
  87. dispose() {
  88. this.onAxisValueChangedObservable.clear();
  89. this.onButtonStateChangedObservable.clear();
  90. }
  91. /**
  92. * Are there axes correlating to this component
  93. * @returns true is axes data is available
  94. */
  95. isAxes() {
  96. return this._axesIndices.length !== 0;
  97. }
  98. /**
  99. * Is this component a button (hence - pressable)
  100. * @returns true if can be pressed
  101. */
  102. isButton() {
  103. return this._buttonIndex !== -1;
  104. }
  105. /**
  106. * update this component using the gamepad object it is in. Called on every frame
  107. * @param nativeController the native gamepad controller object
  108. */
  109. update(nativeController) {
  110. let buttonUpdated = false;
  111. let axesUpdate = false;
  112. this._hasChanges = false;
  113. this._changes = {};
  114. if (this.isButton()) {
  115. const button = nativeController.buttons[this._buttonIndex];
  116. // defensive, in case a profile was forced
  117. if (!button) {
  118. return;
  119. }
  120. if (this._currentValue !== button.value) {
  121. this.changes.value = {
  122. current: button.value,
  123. previous: this._currentValue,
  124. };
  125. buttonUpdated = true;
  126. this._currentValue = button.value;
  127. }
  128. if (this._touched !== button.touched) {
  129. this.changes.touched = {
  130. current: button.touched,
  131. previous: this._touched,
  132. };
  133. buttonUpdated = true;
  134. this._touched = button.touched;
  135. }
  136. if (this._pressed !== button.pressed) {
  137. this.changes.pressed = {
  138. current: button.pressed,
  139. previous: this._pressed,
  140. };
  141. buttonUpdated = true;
  142. this._pressed = button.pressed;
  143. }
  144. }
  145. if (this.isAxes()) {
  146. if (this._axes.x !== nativeController.axes[this._axesIndices[0]]) {
  147. this.changes.axes = {
  148. current: {
  149. x: nativeController.axes[this._axesIndices[0]],
  150. y: this._axes.y,
  151. },
  152. previous: {
  153. x: this._axes.x,
  154. y: this._axes.y,
  155. },
  156. };
  157. this._axes.x = nativeController.axes[this._axesIndices[0]];
  158. axesUpdate = true;
  159. }
  160. if (this._axes.y !== nativeController.axes[this._axesIndices[1]]) {
  161. if (this.changes.axes) {
  162. this.changes.axes.current.y = nativeController.axes[this._axesIndices[1]];
  163. }
  164. else {
  165. this.changes.axes = {
  166. current: {
  167. x: this._axes.x,
  168. y: nativeController.axes[this._axesIndices[1]],
  169. },
  170. previous: {
  171. x: this._axes.x,
  172. y: this._axes.y,
  173. },
  174. };
  175. }
  176. this._axes.y = nativeController.axes[this._axesIndices[1]];
  177. axesUpdate = true;
  178. }
  179. }
  180. if (buttonUpdated) {
  181. this._hasChanges = true;
  182. this.onButtonStateChangedObservable.notifyObservers(this);
  183. }
  184. if (axesUpdate) {
  185. this._hasChanges = true;
  186. this.onAxisValueChangedObservable.notifyObservers(this._axes);
  187. }
  188. }
  189. }
  190. /**
  191. * button component type
  192. */
  193. WebXRControllerComponent.BUTTON_TYPE = "button";
  194. /**
  195. * squeeze component type
  196. */
  197. WebXRControllerComponent.SQUEEZE_TYPE = "squeeze";
  198. /**
  199. * Thumbstick component type
  200. */
  201. WebXRControllerComponent.THUMBSTICK_TYPE = "thumbstick";
  202. /**
  203. * Touchpad component type
  204. */
  205. WebXRControllerComponent.TOUCHPAD_TYPE = "touchpad";
  206. /**
  207. * trigger component type
  208. */
  209. WebXRControllerComponent.TRIGGER_TYPE = "trigger";
  210. //# sourceMappingURL=webXRControllerComponent.js.map