Assignment for RMIT Mixed Reality in 2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

102 lines
3.9 KiB

  1. namespace VRTK
  2. {
  3. using System.Collections;
  4. using System.Linq;
  5. using System.Reflection;
  6. using UnityEngine.EventSystems;
  7. public class VRTK_EventSystem : EventSystem
  8. {
  9. protected EventSystem previousEventSystem;
  10. protected VRTK_VRInputModule vrInputModule;
  11. private static readonly FieldInfo[] EVENT_SYSTEM_FIELD_INFOS = typeof(EventSystem).GetFields(BindingFlags.Public | BindingFlags.Instance);
  12. private static readonly PropertyInfo[] EVENT_SYSTEM_PROPERTY_INFOS = typeof(EventSystem).GetProperties(BindingFlags.Public | BindingFlags.Instance).Except(new[] { typeof(EventSystem).GetProperty("enabled") }).ToArray();
  13. private static readonly FieldInfo BASE_INPUT_MODULE_EVENT_SYSTEM_FIELD_INFO = typeof(BaseInputModule).GetField("m_EventSystem", BindingFlags.NonPublic | BindingFlags.Instance);
  14. protected override void OnEnable()
  15. {
  16. previousEventSystem = current;
  17. if (previousEventSystem != null)
  18. {
  19. previousEventSystem.enabled = false;
  20. CopyValuesFrom(previousEventSystem, this);
  21. }
  22. vrInputModule = gameObject.AddComponent<VRTK_VRInputModule>();
  23. base.OnEnable();
  24. StartCoroutine(SetEventSystemOfBaseInputModulesAfterFrameDelay(this));
  25. }
  26. protected override void OnDisable()
  27. {
  28. base.OnDisable();
  29. Destroy(vrInputModule);
  30. if (previousEventSystem != null)
  31. {
  32. previousEventSystem.enabled = true;
  33. CopyValuesFrom(this, previousEventSystem);
  34. SetEventSystemOfBaseInputModules(previousEventSystem);
  35. }
  36. }
  37. protected override void Update()
  38. {
  39. base.Update();
  40. if (current == this)
  41. {
  42. vrInputModule.Process();
  43. }
  44. }
  45. #if UNITY_5_5_OR_NEWER
  46. protected override void OnApplicationFocus(bool hasFocus)
  47. {
  48. //Don't call the base implementation because it will set a pause flag for this EventSystem
  49. }
  50. #endif
  51. private static void CopyValuesFrom(EventSystem fromEventSystem, EventSystem toEventSystem)
  52. {
  53. foreach (FieldInfo fieldInfo in EVENT_SYSTEM_FIELD_INFOS)
  54. {
  55. fieldInfo.SetValue(toEventSystem, fieldInfo.GetValue(fromEventSystem));
  56. }
  57. foreach (PropertyInfo propertyInfo in EVENT_SYSTEM_PROPERTY_INFOS)
  58. {
  59. if (propertyInfo.CanWrite)
  60. {
  61. propertyInfo.SetValue(toEventSystem, propertyInfo.GetValue(fromEventSystem, null), null);
  62. }
  63. }
  64. }
  65. private static IEnumerator SetEventSystemOfBaseInputModulesAfterFrameDelay(EventSystem eventSystem)
  66. {
  67. yield return null;
  68. SetEventSystemOfBaseInputModules(eventSystem);
  69. }
  70. private static void SetEventSystemOfBaseInputModules(EventSystem eventSystem)
  71. {
  72. /*
  73. BaseInputModule has a private field referencing the current EventSystem. That field is set in
  74. BaseInputModule.OnEnable only. It's used in BaseInputModule.OnEnable and BaseInputModule.OnDisable
  75. to call EventSystem.UpdateModules.
  76. This means we could just disable and enable every enabled BaseInputModule to fix that reference.
  77. But the StandaloneInputModule (which is added by default when adding an EventSystem in the Editor)
  78. requires EventSystem. Which means we can't correctly destroy the old EventSystem first and then add
  79. our own one.
  80. We therefore update that private reference directly here.
  81. */
  82. foreach (BaseInputModule module in FindObjectsOfType<BaseInputModule>())
  83. {
  84. BASE_INPUT_MODULE_EVENT_SYSTEM_FIELD_INFO.SetValue(module, eventSystem);
  85. }
  86. eventSystem.UpdateModules();
  87. }
  88. }
  89. }