InputManager.cs 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using BepInEx.Configuration;
  5. using UnityEngine;
  6. namespace MeidoPhotoStudio.Plugin;
  7. public enum MpsKey
  8. {
  9. // MeidoPhotoStudio
  10. Activate,
  11. Screenshot,
  12. ToggleUI,
  13. ToggleMessage,
  14. // MeidoManager
  15. MeidoUndressing,
  16. // Camera
  17. CameraLayer,
  18. CameraReset,
  19. CameraSave,
  20. CameraLoad,
  21. // Dragpoint
  22. DragSelect,
  23. DragDelete,
  24. DragMove,
  25. DragRotate,
  26. DragScale,
  27. DragFinger,
  28. // Scene management
  29. SaveScene,
  30. LoadScene,
  31. OpenSceneManager,
  32. }
  33. public static class InputManager
  34. {
  35. public const KeyCode UpperKeyCode = KeyCode.F15;
  36. public const string ConfigHeader = "Controls";
  37. public static readonly AcceptableValueBase ControlRange;
  38. private static readonly Dictionary<MpsKey, KeyCode> ActionKeys = new();
  39. private static readonly Dictionary<MpsKey, ConfigEntry<KeyCode>> ConfigEntries = new();
  40. private static InputListener inputListener;
  41. static InputManager() =>
  42. ControlRange = new AcceptableValueRange<KeyCode>(default, UpperKeyCode);
  43. public static event EventHandler KeyChange;
  44. public static KeyCode CurrentKeyCode { get; private set; }
  45. public static bool Listening { get; private set; }
  46. public static bool Control =>
  47. Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl);
  48. public static bool Alt =>
  49. Input.GetKey(KeyCode.LeftAlt) || Input.GetKey(KeyCode.RightAlt);
  50. public static bool Shift =>
  51. Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift);
  52. public static void Register(MpsKey action, KeyCode key, string description)
  53. {
  54. key = Clamp(key, default, UpperKeyCode);
  55. if (ConfigEntries.ContainsKey(action))
  56. {
  57. Rebind(action, key);
  58. }
  59. else
  60. {
  61. var configDescription = new ConfigDescription(description, ControlRange);
  62. ConfigEntries[action] =
  63. Configuration.Config.Bind(ConfigHeader, action.ToString(), key, configDescription);
  64. key = ConfigEntries[action].Value;
  65. ActionKeys[action] = key;
  66. }
  67. }
  68. public static void Rebind(MpsKey action, KeyCode key)
  69. {
  70. key = Clamp(key, default, UpperKeyCode);
  71. if (ConfigEntries.ContainsKey(action))
  72. ConfigEntries[action].Value = key;
  73. ActionKeys[action] = key;
  74. }
  75. public static KeyCode Clamp(KeyCode value, KeyCode min, KeyCode max) =>
  76. value < min ? min : value > max ? max : value;
  77. public static KeyCode GetActionKey(MpsKey action) =>
  78. ActionKeys.TryGetValue(action, out var keyCode) ? keyCode : default;
  79. public static void StartListening()
  80. {
  81. if (!inputListener)
  82. inputListener = new GameObject().AddComponent<InputListener>();
  83. else if (inputListener.gameObject.activeSelf)
  84. StopListening();
  85. inputListener.gameObject.SetActive(true);
  86. inputListener.KeyChange += OnKeyChange;
  87. CurrentKeyCode = KeyCode.None;
  88. Listening = true;
  89. }
  90. public static void StopListening()
  91. {
  92. if (!inputListener || !inputListener.gameObject.activeSelf)
  93. return;
  94. inputListener.gameObject.SetActive(false);
  95. inputListener.KeyChange -= OnKeyChange;
  96. CurrentKeyCode = KeyCode.None;
  97. Listening = false;
  98. Input.ResetInputAxes();
  99. }
  100. public static bool GetKey(MpsKey action) =>
  101. !Listening && ActionKeys.ContainsKey(action) && Input.GetKey(ActionKeys[action]);
  102. public static bool GetKeyDown(MpsKey action) =>
  103. !Listening && ActionKeys.ContainsKey(action) && Input.GetKeyDown(ActionKeys[action]);
  104. public static void Deactivate()
  105. {
  106. StopListening();
  107. // TODO: Null propagation does not work with UnityEngine.Object
  108. UnityEngine.Object.Destroy(inputListener?.gameObject);
  109. inputListener = null;
  110. }
  111. private static void OnKeyChange(object sender, KeyChangeEventArgs args)
  112. {
  113. CurrentKeyCode = args.Key;
  114. KeyChange?.Invoke(null, EventArgs.Empty);
  115. StopListening();
  116. }
  117. /* Listener taken from https://forum.unity.com/threads/find-out-which-key-was-pressed.385250/ */
  118. private class InputListener : MonoBehaviour
  119. {
  120. private static readonly KeyCode[] KeyCodes;
  121. static InputListener() =>
  122. KeyCodes = Enum.GetValues(typeof(KeyCode))
  123. .Cast<KeyCode>()
  124. .Where(keyCode => keyCode <= UpperKeyCode)
  125. .ToArray();
  126. public event EventHandler<KeyChangeEventArgs> KeyChange;
  127. private void Awake() =>
  128. DontDestroyOnLoad(this);
  129. private void Update()
  130. {
  131. if (!Input.anyKeyDown)
  132. return;
  133. foreach (var key in KeyCodes)
  134. {
  135. if (!Input.GetKeyDown(key))
  136. continue;
  137. KeyChange?.Invoke(this, new(key));
  138. break;
  139. }
  140. }
  141. }
  142. private class KeyChangeEventArgs : EventArgs
  143. {
  144. public KeyChangeEventArgs(KeyCode key) =>
  145. Key = key;
  146. public KeyCode Key { get; }
  147. }
  148. }