webXRMotionControllerManager.ts 4.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. import {
  2. WebXRAbstractMotionController,
  3. } from './webXRAbstractController';
  4. import { WebXRGenericTriggerMotionController } from './webXRGenericMotionController';
  5. import { Scene } from '../../../scene';
  6. export type MotionControllerConstructor = (xrInput: XRInputSource, scene: Scene) => WebXRAbstractMotionController;
  7. /**
  8. * The MotionController Manager manages all registered motion controllers and loads the right one when needed.
  9. *
  10. * When this repository is complete: https://github.com/immersive-web/webxr-input-profiles/tree/master/packages/assets
  11. * it should be replaced with auto-loaded controllers.
  12. *
  13. * When using a model try to stay as generic as possible. Eventually there will be no need in any of the controller classes
  14. */
  15. export class WebXRMotionControllerManager {
  16. private static _AvailableControllers: { [type: string]: MotionControllerConstructor } = {};
  17. private static _Fallbacks: { [profileId: string]: string[] } = {};
  18. public static RegisterController(type: string, constructFunction: MotionControllerConstructor) {
  19. this._AvailableControllers[type] = constructFunction;
  20. }
  21. public static GetMotionControllerWithXRInput(xrInput: XRInputSource, scene: Scene) {
  22. for (let i = 0; i < xrInput.profiles.length; ++i) {
  23. const constructionFunction = this._AvailableControllers[xrInput.profiles[i]];
  24. if (constructionFunction) {
  25. return constructionFunction(xrInput, scene);
  26. }
  27. }
  28. // try using the gamepad id
  29. if (xrInput.gamepad) {
  30. switch (xrInput.gamepad.id) {
  31. case (xrInput.gamepad.id.match(/oculus touch/gi) ? xrInput.gamepad.id : undefined):
  32. // oculus in gamepad id - legacy mapping
  33. return this._AvailableControllers["oculus-touch-legacy"](xrInput, scene);
  34. case (xrInput.gamepad.id.match(/Spatial Controller/gi) ? xrInput.gamepad.id : undefined):
  35. // oculus in gamepad id - legacy mapping
  36. return this._AvailableControllers["microsoft-mixed-reality"](xrInput, scene);
  37. }
  38. }
  39. // check fallbacks
  40. for (let i = 0; i < xrInput.profiles.length; ++i) {
  41. const fallbacks = this.FindFallbackWithProfileId(xrInput.profiles[i]);
  42. if (fallbacks) {
  43. for (let j = 0; j < fallbacks.length; ++j) {
  44. const constructionFunction = this._AvailableControllers[fallbacks[j]];
  45. if (constructionFunction) {
  46. return constructionFunction(xrInput, scene);
  47. }
  48. }
  49. }
  50. }
  51. // return the most generic thing we have
  52. return this._AvailableControllers[WebXRGenericTriggerMotionController.ProfileId](xrInput, scene);
  53. }
  54. public static FindFallbackWithProfileId(profileId: string): string[] {
  55. return this._Fallbacks[profileId];
  56. }
  57. public static RegisterFallbacksForProfileId(profileId: string, fallbacks: string[]) {
  58. if (this._Fallbacks[profileId]) {
  59. this._Fallbacks[profileId].push(...fallbacks);
  60. } else {
  61. this._Fallbacks[profileId] = fallbacks;
  62. }
  63. }
  64. public static DefaultFallbacks() {
  65. this.RegisterFallbacksForProfileId("google-daydream", ["generic-touchpad"]);
  66. this.RegisterFallbacksForProfileId("htc-vive-focus", ["generic-trigger-touchpad"]);
  67. this.RegisterFallbacksForProfileId("htc-vive", ["generic-trigger-squeeze-touchpad"]);
  68. this.RegisterFallbacksForProfileId("magicleap-one", ["generic-trigger-squeeze-touchpad"]);
  69. this.RegisterFallbacksForProfileId("microsoft-mixed-reality", ["generic-trigger-squeeze-touchpad-thumbstick"]);
  70. this.RegisterFallbacksForProfileId("oculus-go", ["generic-trigger-touchpad"]);
  71. this.RegisterFallbacksForProfileId("oculus-touch-v2", ["oculus-touch", "generic-trigger-squeeze-thumbstick"]);
  72. this.RegisterFallbacksForProfileId("oculus-touch", ["generic-trigger-squeeze-thumbstick"]);
  73. this.RegisterFallbacksForProfileId("samsung-gearvr", ["microsoft-mixed-reality", "generic-trigger-squeeze-touchpad-thumbstick"]);
  74. this.RegisterFallbacksForProfileId("samsung-odyssey", ["generic-touchpad"]);
  75. this.RegisterFallbacksForProfileId("valve-index", ["generic-trigger-squeeze-touchpad-thumbstick"]);
  76. }
  77. }
  78. // register the generic profile(s) here so we will at least have them
  79. WebXRMotionControllerManager.RegisterController(WebXRGenericTriggerMotionController.ProfileId, (xrInput: XRInputSource, scene: Scene) => {
  80. return new WebXRGenericTriggerMotionController(scene, <any>(xrInput.gamepad), xrInput.handedness);
  81. });
  82. // register fallbacks
  83. WebXRMotionControllerManager.DefaultFallbacks();