WebGLSupport.cs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. #if UNITY_WEBGL || UNITY_EDITOR
  2. using UnityEngine.InputSystem.Layouts;
  3. using UnityEngine.InputSystem.WebGL.LowLevel;
  4. using UnityEngine.InputSystem.LowLevel;
  5. using UnityEngine.InputSystem.Utilities;
  6. using System;
  7. namespace UnityEngine.InputSystem.WebGL
  8. {
  9. #if UNITY_DISABLE_DEFAULT_INPUT_PLUGIN_INITIALIZATION
  10. public
  11. #else
  12. internal
  13. #endif
  14. static class WebGLSupport
  15. {
  16. private const string InterfaceName = "WebGL";
  17. public static void Initialize()
  18. {
  19. // We only turn gamepads with the "standard" mapping into actual Gamepads.
  20. InputSystem.RegisterLayout<WebGLGamepad>(
  21. matches: new InputDeviceMatcher()
  22. .WithInterface(InterfaceName)
  23. .WithDeviceClass("Gamepad")
  24. .WithCapability("mapping", "standard"));
  25. InputSystem.onFindLayoutForDevice += OnFindLayoutForDevice;
  26. }
  27. internal static string OnFindLayoutForDevice(ref InputDeviceDescription description,
  28. string matchedLayout, InputDeviceExecuteCommandDelegate executeCommandDelegate)
  29. {
  30. // If the device isn't a WebGL device, we're not interested.
  31. if (string.Compare(description.interfaceName, InterfaceName, StringComparison.InvariantCultureIgnoreCase) != 0)
  32. return null;
  33. // If it was matched by the standard mapping, we don't need to fall back to generating a layout.
  34. if (!string.IsNullOrEmpty(matchedLayout) && matchedLayout != "Gamepad")
  35. return null;
  36. var deviceMatcher = InputDeviceMatcher.FromDeviceDescription(description);
  37. var layout = new WebGLLayoutBuilder {capabilities = WebGLDeviceCapabilities.FromJson(description.capabilities)};
  38. InputSystem.RegisterLayoutBuilder(() => layout.Build(),
  39. description.product, "Joystick", deviceMatcher);
  40. return description.product;
  41. }
  42. [Serializable]
  43. private class WebGLLayoutBuilder
  44. {
  45. public WebGLDeviceCapabilities capabilities;
  46. public InputControlLayout Build()
  47. {
  48. var builder = new InputControlLayout.Builder
  49. {
  50. type = typeof(WebGLJoystick),
  51. extendsLayout = "Joystick",
  52. stateFormat = new FourCC('H', 'T', 'M', 'L')
  53. };
  54. // Best guess: Treat first two axes as stick
  55. uint offset = 0;
  56. if (capabilities.numAxes >= 2)
  57. {
  58. var stickName = "Stick";
  59. builder.AddControl(stickName)
  60. .WithLayout("Stick")
  61. .WithByteOffset(offset)
  62. .WithSizeInBits(64)
  63. .WithFormat(InputStateBlock.FormatFloat);
  64. builder.AddControl(stickName + "/x")
  65. .WithLayout("Axis")
  66. .WithByteOffset(offset)
  67. .WithSizeInBits(32)
  68. .WithFormat(InputStateBlock.FormatFloat);
  69. builder.AddControl(stickName + "/y")
  70. .WithLayout("Axis")
  71. .WithByteOffset(offset + 4)
  72. .WithParameters("invert")
  73. .WithSizeInBits(32)
  74. .WithFormat(InputStateBlock.FormatFloat);
  75. //Need to handle Up/Down/Left/Right
  76. builder.AddControl(stickName + "/up")
  77. .WithLayout("Button")
  78. .WithParameters("clamp=1,clampMin=-1,clampMax=0,invert")
  79. .WithByteOffset(offset + 4)
  80. .WithSizeInBits(32)
  81. .WithFormat(InputStateBlock.FormatFloat);
  82. builder.AddControl(stickName + "/down")
  83. .WithLayout("Button")
  84. .WithParameters("clamp=1,clampMin=0,clampMax=1")
  85. .WithByteOffset(offset + 4)
  86. .WithSizeInBits(32)
  87. .WithFormat(InputStateBlock.FormatFloat);
  88. builder.AddControl(stickName + "/left")
  89. .WithLayout("Button")
  90. .WithParameters("clamp=1,clampMin=-1,clampMax=0,invert")
  91. .WithByteOffset(offset)
  92. .WithSizeInBits(32)
  93. .WithFormat(InputStateBlock.FormatFloat);
  94. builder.AddControl(stickName + "/right")
  95. .WithLayout("Button")
  96. .WithParameters("clamp=1,clampMin=0,clampMax=1")
  97. .WithByteOffset(offset)
  98. .WithSizeInBits(32)
  99. .WithFormat(InputStateBlock.FormatFloat);
  100. offset += 8;
  101. }
  102. for (var axis = 2; axis < capabilities.numAxes; axis++)
  103. {
  104. builder.AddControl($"Axis {axis - 1}")
  105. .WithLayout("Axis")
  106. .WithByteOffset(offset)
  107. .WithSizeInBits(32)
  108. .WithFormat(InputStateBlock.FormatFloat);
  109. offset += 4;
  110. }
  111. var buttonStartOffset = offset;
  112. for (var button = 0; button < capabilities.numButtons; button++)
  113. {
  114. builder.AddControl($"Button {button + 1}")
  115. .WithLayout("Button")
  116. .WithByteOffset(offset)
  117. .WithSizeInBits(32)
  118. .WithFormat(InputStateBlock.FormatFloat);
  119. offset += 4;
  120. }
  121. builder.AddControl("Trigger")
  122. .WithLayout("AnyKey")
  123. .WithByteOffset(buttonStartOffset)
  124. .IsSynthetic(true)
  125. .WithSizeInBits((uint)(32 * capabilities.numButtons))
  126. .WithFormat(InputStateBlock.FormatBit);
  127. return builder.Build();
  128. }
  129. }
  130. }
  131. }
  132. #endif // UNITY_WEBGL || UNITY_EDITOR