eventFactory.js 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. import { EventConstants } from "../Events/deviceInputEvents.js";
  2. import { DeviceType, NativePointerInput, PointerInput } from "./InputDevices/deviceEnums.js";
  3. /**
  4. * Class to wrap DeviceInputSystem data into an event object
  5. */
  6. export class DeviceEventFactory {
  7. /**
  8. * Create device input events based on provided type and slot
  9. *
  10. * @param deviceType Type of device
  11. * @param deviceSlot "Slot" or index that device is referenced in
  12. * @param inputIndex Id of input to be checked
  13. * @param currentState Current value for given input
  14. * @param deviceInputSystem Reference to DeviceInputSystem
  15. * @param elementToAttachTo HTMLElement to reference as target for inputs
  16. * @param pointerId PointerId to use for pointer events
  17. * @returns IUIEvent object
  18. */
  19. static CreateDeviceEvent(deviceType, deviceSlot, inputIndex, currentState, deviceInputSystem, elementToAttachTo, pointerId) {
  20. switch (deviceType) {
  21. case DeviceType.Keyboard:
  22. return this._CreateKeyboardEvent(inputIndex, currentState, deviceInputSystem, elementToAttachTo);
  23. case DeviceType.Mouse:
  24. if (inputIndex === PointerInput.MouseWheelX || inputIndex === PointerInput.MouseWheelY || inputIndex === PointerInput.MouseWheelZ) {
  25. return this._CreateWheelEvent(deviceType, deviceSlot, inputIndex, currentState, deviceInputSystem, elementToAttachTo);
  26. }
  27. // eslint-disable-next-line no-fallthrough
  28. case DeviceType.Touch:
  29. return this._CreatePointerEvent(deviceType, deviceSlot, inputIndex, currentState, deviceInputSystem, elementToAttachTo, pointerId);
  30. default:
  31. // eslint-disable-next-line no-throw-literal
  32. throw `Unable to generate event for device ${DeviceType[deviceType]}`;
  33. }
  34. }
  35. /**
  36. * Creates pointer event
  37. *
  38. * @param deviceType Type of device
  39. * @param deviceSlot "Slot" or index that device is referenced in
  40. * @param inputIndex Id of input to be checked
  41. * @param currentState Current value for given input
  42. * @param deviceInputSystem Reference to DeviceInputSystem
  43. * @param elementToAttachTo HTMLElement to reference as target for inputs
  44. * @param pointerId PointerId to use for pointer events
  45. * @returns IUIEvent object (Pointer)
  46. */
  47. static _CreatePointerEvent(deviceType, deviceSlot, inputIndex, currentState, deviceInputSystem, elementToAttachTo, pointerId) {
  48. const evt = this._CreateMouseEvent(deviceType, deviceSlot, inputIndex, currentState, deviceInputSystem, elementToAttachTo);
  49. if (deviceType === DeviceType.Mouse) {
  50. evt.deviceType = DeviceType.Mouse;
  51. evt.pointerId = 1;
  52. evt.pointerType = "mouse";
  53. }
  54. else {
  55. evt.deviceType = DeviceType.Touch;
  56. evt.pointerId = pointerId ?? deviceSlot;
  57. evt.pointerType = "touch";
  58. }
  59. let buttons = 0;
  60. // Populate buttons property with current state of all mouse buttons
  61. // Uses values found on: https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons
  62. buttons += deviceInputSystem.pollInput(deviceType, deviceSlot, PointerInput.LeftClick);
  63. buttons += deviceInputSystem.pollInput(deviceType, deviceSlot, PointerInput.RightClick) * 2;
  64. buttons += deviceInputSystem.pollInput(deviceType, deviceSlot, PointerInput.MiddleClick) * 4;
  65. evt.buttons = buttons;
  66. if (inputIndex === PointerInput.Move) {
  67. evt.type = "pointermove";
  68. }
  69. else if (inputIndex >= PointerInput.LeftClick && inputIndex <= PointerInput.RightClick) {
  70. evt.type = currentState === 1 ? "pointerdown" : "pointerup";
  71. evt.button = inputIndex - 2;
  72. }
  73. return evt;
  74. }
  75. /**
  76. * Create Mouse Wheel Event
  77. * @param deviceType Type of device
  78. * @param deviceSlot "Slot" or index that device is referenced in
  79. * @param inputIndex Id of input to be checked
  80. * @param currentState Current value for given input
  81. * @param deviceInputSystem Reference to DeviceInputSystem
  82. * @param elementToAttachTo HTMLElement to reference as target for inputs
  83. * @returns IUIEvent object (Wheel)
  84. */
  85. static _CreateWheelEvent(deviceType, deviceSlot, inputIndex, currentState, deviceInputSystem, elementToAttachTo) {
  86. const evt = this._CreateMouseEvent(deviceType, deviceSlot, inputIndex, currentState, deviceInputSystem, elementToAttachTo);
  87. // While WheelEvents don't generally have a pointerId, we used to add one in the InputManager
  88. // This line has been added to make the InputManager more platform-agnostic
  89. // Similar code exists in the WebDeviceInputSystem to handle browser created events
  90. evt.pointerId = 1;
  91. evt.type = "wheel";
  92. evt.deltaMode = EventConstants.DOM_DELTA_PIXEL;
  93. evt.deltaX = 0;
  94. evt.deltaY = 0;
  95. evt.deltaZ = 0;
  96. switch (inputIndex) {
  97. case PointerInput.MouseWheelX:
  98. evt.deltaX = currentState;
  99. break;
  100. case PointerInput.MouseWheelY:
  101. evt.deltaY = currentState;
  102. break;
  103. case PointerInput.MouseWheelZ:
  104. evt.deltaZ = currentState;
  105. break;
  106. }
  107. return evt;
  108. }
  109. /**
  110. * Create Mouse Event
  111. * @param deviceType Type of device
  112. * @param deviceSlot "Slot" or index that device is referenced in
  113. * @param inputIndex Id of input to be checked
  114. * @param currentState Current value for given input
  115. * @param deviceInputSystem Reference to DeviceInputSystem
  116. * @param elementToAttachTo HTMLElement to reference as target for inputs
  117. * @returns IUIEvent object (Mouse)
  118. */
  119. static _CreateMouseEvent(deviceType, deviceSlot, inputIndex, currentState, deviceInputSystem, elementToAttachTo) {
  120. const evt = this._CreateEvent(elementToAttachTo);
  121. const pointerX = deviceInputSystem.pollInput(deviceType, deviceSlot, PointerInput.Horizontal);
  122. const pointerY = deviceInputSystem.pollInput(deviceType, deviceSlot, PointerInput.Vertical);
  123. // Handle offsets/deltas based on existence of HTMLElement
  124. if (elementToAttachTo) {
  125. evt.movementX = 0;
  126. evt.movementY = 0;
  127. evt.offsetX = evt.movementX - elementToAttachTo.getBoundingClientRect().x;
  128. evt.offsetY = evt.movementY - elementToAttachTo.getBoundingClientRect().y;
  129. }
  130. else {
  131. evt.movementX = deviceInputSystem.pollInput(deviceType, deviceSlot, NativePointerInput.DeltaHorizontal); // DeltaHorizontal
  132. evt.movementY = deviceInputSystem.pollInput(deviceType, deviceSlot, NativePointerInput.DeltaVertical); // DeltaVertical
  133. evt.offsetX = 0;
  134. evt.offsetY = 0;
  135. }
  136. this._CheckNonCharacterKeys(evt, deviceInputSystem);
  137. evt.clientX = pointerX;
  138. evt.clientY = pointerY;
  139. evt.x = pointerX;
  140. evt.y = pointerY;
  141. evt.deviceType = deviceType;
  142. evt.deviceSlot = deviceSlot;
  143. evt.inputIndex = inputIndex;
  144. return evt;
  145. }
  146. /**
  147. * Create Keyboard Event
  148. * @param inputIndex Id of input to be checked
  149. * @param currentState Current value for given input
  150. * @param deviceInputSystem Reference to DeviceInputSystem
  151. * @param elementToAttachTo HTMLElement to reference as target for inputs
  152. * @returns IEvent object (Keyboard)
  153. */
  154. static _CreateKeyboardEvent(inputIndex, currentState, deviceInputSystem, elementToAttachTo) {
  155. const evt = this._CreateEvent(elementToAttachTo);
  156. this._CheckNonCharacterKeys(evt, deviceInputSystem);
  157. evt.deviceType = DeviceType.Keyboard;
  158. evt.deviceSlot = 0;
  159. evt.inputIndex = inputIndex;
  160. evt.type = currentState === 1 ? "keydown" : "keyup";
  161. evt.key = String.fromCharCode(inputIndex);
  162. evt.keyCode = inputIndex;
  163. return evt;
  164. }
  165. /**
  166. * Add parameters for non-character keys (Ctrl, Alt, Meta, Shift)
  167. * @param evt Event object to add parameters to
  168. * @param deviceInputSystem DeviceInputSystem to pull values from
  169. */
  170. static _CheckNonCharacterKeys(evt, deviceInputSystem) {
  171. const isKeyboardActive = deviceInputSystem.isDeviceAvailable(DeviceType.Keyboard);
  172. const altKey = isKeyboardActive && deviceInputSystem.pollInput(DeviceType.Keyboard, 0, 18) === 1;
  173. const ctrlKey = isKeyboardActive && deviceInputSystem.pollInput(DeviceType.Keyboard, 0, 17) === 1;
  174. const metaKey = isKeyboardActive &&
  175. (deviceInputSystem.pollInput(DeviceType.Keyboard, 0, 91) === 1 ||
  176. deviceInputSystem.pollInput(DeviceType.Keyboard, 0, 92) === 1 ||
  177. deviceInputSystem.pollInput(DeviceType.Keyboard, 0, 93) === 1);
  178. const shiftKey = isKeyboardActive && deviceInputSystem.pollInput(DeviceType.Keyboard, 0, 16) === 1;
  179. evt.altKey = altKey;
  180. evt.ctrlKey = ctrlKey;
  181. evt.metaKey = metaKey;
  182. evt.shiftKey = shiftKey;
  183. }
  184. /**
  185. * Create base event object
  186. * @param elementToAttachTo Value to use as event target
  187. * @returns
  188. */
  189. static _CreateEvent(elementToAttachTo) {
  190. const evt = {};
  191. evt.preventDefault = () => { };
  192. evt.target = elementToAttachTo;
  193. return evt;
  194. }
  195. }
  196. //# sourceMappingURL=eventFactory.js.map