DragPoint.cs 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. using System;
  2. using UnityEngine;
  3. using static MeidoPhotoStudio.Plugin.CustomGizmo;
  4. namespace MeidoPhotoStudio.Plugin;
  5. public abstract class DragPoint : MonoBehaviour
  6. {
  7. public const float DefaultAlpha = 0.75f;
  8. public static readonly Color DefaultColour = new(0f, 0f, 0f, 0.4f);
  9. public static Material DragPointMaterial = new(Shader.Find("CM3D2/Trans_AbsoluteFront"));
  10. protected static Camera camera = GameMain.Instance.MainCamera.camera;
  11. private const float DoubleClickSensitivity = 0.3f;
  12. // TODO: Use this value or just throw it away.
  13. private static readonly int DragPointLayer = (int)Mathf.Log(LayerMask.GetMask("AbsolutFront"), 2);
  14. private static GameObject dragPointParent;
  15. private Func<Vector3> position;
  16. private Func<Vector3> rotation;
  17. private Collider collider;
  18. private Renderer renderer;
  19. private bool reinitializeDrag;
  20. private Vector3 startMousePosition;
  21. private float startDoubleClick;
  22. private Vector3 screenPoint;
  23. private Vector3 startOffset;
  24. private Vector3 newOffset;
  25. private Vector3 baseScale;
  26. private DragType oldDragType;
  27. private DragType currentDragType;
  28. private bool dragPointEnabled = true;
  29. private float dragPointScale = 1f;
  30. private bool gizmoEnabled = true;
  31. static DragPoint()
  32. {
  33. InputManager.Register(MpsKey.DragSelect, KeyCode.A, "Select handle mode");
  34. InputManager.Register(MpsKey.DragDelete, KeyCode.D, "Delete handle mode");
  35. InputManager.Register(MpsKey.DragMove, KeyCode.Z, "Move handle mode");
  36. InputManager.Register(MpsKey.DragRotate, KeyCode.X, "Rotate handle mode");
  37. InputManager.Register(MpsKey.DragScale, KeyCode.C, "Scale handle mode");
  38. InputManager.Register(MpsKey.DragFinger, KeyCode.Space, "Show finger handles");
  39. }
  40. public enum DragType
  41. {
  42. None,
  43. Ignore,
  44. Select,
  45. Delete,
  46. MoveXZ,
  47. MoveY,
  48. RotLocalXZ,
  49. RotY,
  50. RotLocalY,
  51. Scale,
  52. }
  53. public Vector3 OriginalScale { get; private set; }
  54. public Transform MyObject { get; protected set; }
  55. public GameObject GizmoGo { get; protected set; }
  56. public CustomGizmo Gizmo { get; protected set; }
  57. public GameObject MyGameObject =>
  58. MyObject.gameObject;
  59. public Vector3 BaseScale
  60. {
  61. get => baseScale;
  62. protected set
  63. {
  64. baseScale = value;
  65. transform.localScale = BaseScale * DragPointScale;
  66. }
  67. }
  68. public float DragPointScale
  69. {
  70. get => dragPointScale;
  71. set
  72. {
  73. dragPointScale = value;
  74. transform.localScale = BaseScale * dragPointScale;
  75. }
  76. }
  77. public bool DragPointEnabled
  78. {
  79. get => dragPointEnabled;
  80. set
  81. {
  82. if (dragPointEnabled == value)
  83. return;
  84. dragPointEnabled = value;
  85. ApplyDragType();
  86. }
  87. }
  88. public bool GizmoEnabled
  89. {
  90. get => GizmoGo && gizmoEnabled;
  91. set
  92. {
  93. if (!GizmoGo || gizmoEnabled == value)
  94. return;
  95. gizmoEnabled = value;
  96. ApplyDragType();
  97. }
  98. }
  99. protected DragType CurrentDragType
  100. {
  101. get => currentDragType;
  102. set
  103. {
  104. if (value == oldDragType)
  105. return;
  106. currentDragType = value;
  107. reinitializeDrag = true;
  108. oldDragType = currentDragType;
  109. ApplyDragType();
  110. }
  111. }
  112. protected bool Transforming =>
  113. CurrentDragType >= DragType.MoveXZ;
  114. protected bool Special =>
  115. CurrentDragType is DragType.Select or DragType.Delete;
  116. protected bool Moving =>
  117. CurrentDragType is DragType.MoveXZ or DragType.MoveY;
  118. protected bool Rotating =>
  119. CurrentDragType is >= DragType.RotLocalXZ and <= DragType.RotLocalY;
  120. protected bool Scaling =>
  121. CurrentDragType is DragType.Scale;
  122. protected bool Selecting =>
  123. CurrentDragType is DragType.Select;
  124. protected bool Deleting =>
  125. CurrentDragType is DragType.Delete;
  126. public static T Make<T>(PrimitiveType primitiveType, Vector3 scale)
  127. where T : DragPoint
  128. {
  129. var dragPointGo = GameObject.CreatePrimitive(primitiveType);
  130. dragPointGo.transform.SetParent(DragPointParent().transform, false);
  131. dragPointGo.transform.localScale = scale;
  132. dragPointGo.layer = 8;
  133. var dragPoint = dragPointGo.AddComponent<T>();
  134. dragPoint.renderer.material = DragPointMaterial;
  135. dragPoint.renderer.material.color = DefaultColour;
  136. return dragPoint;
  137. }
  138. public virtual void Initialize(Func<Vector3> position, Func<Vector3> rotation)
  139. {
  140. this.position = position;
  141. this.rotation = rotation;
  142. }
  143. public virtual void Set(Transform myObject)
  144. {
  145. MyObject = myObject;
  146. gameObject.name = $"[MPS DragPoint: {MyObject.name}]";
  147. }
  148. public virtual void AddGizmo(float scale = 0.25f, GizmoMode mode = GizmoMode.Local)
  149. {
  150. Gizmo = CustomGizmo.Make(MyObject, scale, mode);
  151. GizmoGo = Gizmo.gameObject;
  152. Gizmo.GizmoVisible = false;
  153. ApplyDragType();
  154. }
  155. public void ApplyProperties(bool active = false, bool visible = false, bool gizmo = false)
  156. {
  157. collider.enabled = active;
  158. renderer.enabled = visible;
  159. if (Gizmo)
  160. Gizmo.GizmoVisible = gizmo;
  161. }
  162. protected abstract void UpdateDragType();
  163. protected abstract void Drag();
  164. protected virtual void ApplyDragType()
  165. {
  166. }
  167. protected virtual void Update()
  168. {
  169. transform.position = position();
  170. transform.eulerAngles = rotation();
  171. UpdateDragType();
  172. }
  173. protected virtual void OnMouseDown()
  174. {
  175. screenPoint = camera.WorldToScreenPoint(transform.position);
  176. startMousePosition = Utility.MousePosition;
  177. startOffset = transform.position
  178. - camera.ScreenToWorldPoint(new(startMousePosition.x, startMousePosition.y, screenPoint.z));
  179. newOffset = transform.position - MyObject.position;
  180. }
  181. protected virtual void OnMouseDrag()
  182. {
  183. if (reinitializeDrag)
  184. {
  185. reinitializeDrag = false;
  186. OnMouseDown();
  187. }
  188. if (collider.enabled && startMousePosition != Utility.MousePosition)
  189. Drag();
  190. }
  191. protected virtual void OnMouseUp()
  192. {
  193. if (Time.time - startDoubleClick < DoubleClickSensitivity)
  194. {
  195. startDoubleClick = -1f;
  196. OnDoubleClick();
  197. }
  198. else
  199. {
  200. startDoubleClick = Time.time;
  201. }
  202. }
  203. protected virtual void OnDoubleClick()
  204. {
  205. }
  206. protected virtual void OnDestroy() =>
  207. Destroy(GizmoGo);
  208. protected void ApplyColour(Color colour) =>
  209. renderer.material.color = colour;
  210. protected void ApplyColour(float r, float g, float b, float a = DefaultAlpha) =>
  211. ApplyColour(new(r, g, b, a));
  212. protected Vector3 MouseDelta() =>
  213. Utility.MousePosition - startMousePosition;
  214. protected bool OtherDragType() =>
  215. InputManager.GetKey(MpsKey.DragSelect) || InputManager.GetKey(MpsKey.DragDelete)
  216. || InputManager.GetKey(MpsKey.DragMove) || InputManager.GetKey(MpsKey.DragRotate)
  217. || InputManager.GetKey(MpsKey.DragScale) || InputManager.GetKey(MpsKey.DragFinger);
  218. protected Vector3 CursorPosition()
  219. {
  220. var mousePosition = Utility.MousePosition;
  221. return camera.ScreenToWorldPoint(new(mousePosition.x, mousePosition.y, screenPoint.z)) + startOffset
  222. - newOffset;
  223. }
  224. private static GameObject DragPointParent() =>
  225. dragPointParent ? dragPointParent : (dragPointParent = new("[MPS DragPoint Parent]"));
  226. private void Awake()
  227. {
  228. BaseScale = OriginalScale = transform.localScale;
  229. collider = GetComponent<Collider>();
  230. renderer = GetComponent<Renderer>();
  231. ApplyDragType();
  232. }
  233. private void OnEnable()
  234. {
  235. if (position is not null)
  236. {
  237. transform.position = position();
  238. transform.eulerAngles = rotation();
  239. }
  240. if (GizmoGo)
  241. GizmoGo.SetActive(true);
  242. ApplyDragType();
  243. }
  244. private void OnDisable()
  245. {
  246. if (GizmoGo)
  247. GizmoGo.SetActive(false);
  248. }
  249. }