DragPoint.cs 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. using System;
  2. using UnityEngine;
  3. namespace COM3D2.MeidoPhotoStudio.Plugin
  4. {
  5. using static CustomGizmo;
  6. internal abstract class DragPoint : MonoBehaviour
  7. {
  8. private const float doubleClickSensitivity = 0.3f;
  9. private Func<Vector3> position;
  10. private Func<Vector3> rotation;
  11. private Collider collider;
  12. private Renderer renderer;
  13. private bool reinitializeDrag;
  14. protected bool Transforming => CurrentDragType >= DragType.MoveXZ;
  15. protected bool Moving => CurrentDragType == DragType.MoveXZ || CurrentDragType == DragType.MoveY;
  16. protected bool Rotating => CurrentDragType >= DragType.RotLocalXZ && CurrentDragType <= DragType.RotLocalY;
  17. protected bool Special => CurrentDragType == DragType.Select || CurrentDragType == DragType.Delete;
  18. private Vector3 startMousePosition;
  19. protected static Camera camera = GameMain.Instance.MainCamera.camera;
  20. public enum DragType
  21. {
  22. None, Ignore, Select, Delete,
  23. MoveXZ, MoveY,
  24. RotLocalXZ, RotY, RotLocalY,
  25. Scale
  26. }
  27. public Transform MyObject { get; protected set; }
  28. public GameObject MyGameObject => MyObject.gameObject;
  29. private float startDoubleClick;
  30. private Vector3 screenPoint;
  31. private Vector3 startOffset;
  32. private Vector3 newOffset;
  33. public static Material LightBlue = new Material(Shader.Find("Transparent/Diffuse"))
  34. {
  35. color = new Color(0.4f, 0.4f, 1f, 0.3f)
  36. };
  37. public static Material Blue = new Material(Shader.Find("Transparent/Diffuse"))
  38. {
  39. color = new Color(0.5f, 0.5f, 1f, 0.8f)
  40. };
  41. public Vector3 BaseScale { get; private set; }
  42. private float dragPointScale = 1f;
  43. public float DragPointScale
  44. {
  45. get => dragPointScale;
  46. set
  47. {
  48. dragPointScale = value;
  49. transform.localScale = BaseScale * dragPointScale;
  50. }
  51. }
  52. public GameObject GizmoGo { get; protected set; }
  53. public CustomGizmo Gizmo { get; protected set; }
  54. private DragType oldDragType;
  55. private DragType currentDragType;
  56. protected DragType CurrentDragType
  57. {
  58. get => currentDragType;
  59. set
  60. {
  61. if (value != oldDragType)
  62. {
  63. currentDragType = value;
  64. reinitializeDrag = true;
  65. oldDragType = currentDragType;
  66. ApplyDragType();
  67. }
  68. }
  69. }
  70. private bool dragPointEnabled = true;
  71. public bool DragPointEnabled
  72. {
  73. get => dragPointEnabled;
  74. set
  75. {
  76. if (dragPointEnabled == value) return;
  77. dragPointEnabled = value;
  78. ApplyDragType();
  79. }
  80. }
  81. private bool gizmoEnabled = true;
  82. public bool GizmoEnabled
  83. {
  84. get => GizmoGo != null && gizmoEnabled;
  85. set
  86. {
  87. if (GizmoGo == null || (GizmoGo != null && gizmoEnabled == value)) return;
  88. gizmoEnabled = value;
  89. ApplyDragType();
  90. }
  91. }
  92. private void Awake()
  93. {
  94. this.BaseScale = transform.localScale;
  95. this.collider = GetComponent<Collider>();
  96. this.renderer = GetComponent<Renderer>();
  97. ApplyDragType();
  98. }
  99. private static GameObject DragPointParent() => GameObject.Find("[MPS DragPoint Parent]")
  100. ?? new GameObject("[MPS DragPoint Parent]");
  101. public static T Make<T>(PrimitiveType primitiveType, Vector3 scale, Material material) where T : DragPoint
  102. {
  103. GameObject dragPoint = GameObject.CreatePrimitive(primitiveType);
  104. dragPoint.transform.localScale = scale;
  105. dragPoint.GetComponent<Renderer>().material = material;
  106. dragPoint.layer = 8;
  107. dragPoint.transform.SetParent(DragPointParent().transform, true);
  108. return dragPoint.AddComponent<T>();
  109. }
  110. public virtual void Initialize(Func<Vector3> position, Func<Vector3> rotation)
  111. {
  112. this.position = position;
  113. this.rotation = rotation;
  114. }
  115. public virtual void Set(Transform myObject)
  116. {
  117. this.MyObject = myObject;
  118. this.gameObject.name = $"[MPS DragPoint: {this.MyObject.name}]";
  119. }
  120. public virtual void AddGizmo(float scale = 0.25f, GizmoMode mode = GizmoMode.Local)
  121. {
  122. Gizmo = CustomGizmo.Make(this.MyObject, scale, mode);
  123. GizmoGo = Gizmo.gameObject;
  124. Gizmo.GizmoVisible = false;
  125. ApplyDragType();
  126. }
  127. protected virtual void ApplyDragType() { }
  128. public void ApplyProperties(bool active = false, bool visible = false, bool gizmo = false)
  129. {
  130. this.collider.enabled = active;
  131. this.renderer.enabled = visible;
  132. if (this.Gizmo != null) this.Gizmo.GizmoVisible = gizmo;
  133. }
  134. protected Vector3 MouseDelta() => Input.mousePosition - startMousePosition;
  135. protected bool OtherDragType()
  136. {
  137. return Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.D)
  138. || Input.GetKey(KeyCode.Z) || Input.GetKey(KeyCode.X) || Input.GetKey(KeyCode.C);
  139. }
  140. protected Vector3 CursorPosition()
  141. {
  142. Vector3 mousePosition = Input.mousePosition;
  143. return camera.ScreenToWorldPoint(
  144. new Vector3(mousePosition.x, mousePosition.y, screenPoint.z)
  145. ) + startOffset - newOffset;
  146. }
  147. protected virtual void Update()
  148. {
  149. transform.position = position();
  150. transform.eulerAngles = rotation();
  151. UpdateDragType();
  152. }
  153. protected virtual void OnMouseDown()
  154. {
  155. screenPoint = camera.WorldToScreenPoint(transform.position);
  156. startMousePosition = Input.mousePosition;
  157. startOffset = transform.position - camera.ScreenToWorldPoint(
  158. new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z)
  159. );
  160. newOffset = transform.position - MyObject.position;
  161. }
  162. protected virtual void OnMouseDrag()
  163. {
  164. if (reinitializeDrag)
  165. {
  166. reinitializeDrag = false;
  167. OnMouseDown();
  168. }
  169. if (collider.enabled && Input.mousePosition != startMousePosition) Drag();
  170. }
  171. protected abstract void UpdateDragType();
  172. protected abstract void Drag();
  173. protected virtual void OnMouseUp()
  174. {
  175. if ((Time.time - startDoubleClick) < doubleClickSensitivity)
  176. {
  177. startDoubleClick = -1f;
  178. OnDoubleClick();
  179. }
  180. else
  181. {
  182. startDoubleClick = Time.time;
  183. }
  184. }
  185. protected virtual void OnDoubleClick() { }
  186. private void OnEnable()
  187. {
  188. if (position != null)
  189. {
  190. transform.position = position();
  191. transform.eulerAngles = rotation();
  192. }
  193. if (GizmoGo != null) GizmoGo.SetActive(true);
  194. ApplyDragType();
  195. }
  196. private void OnDisable()
  197. {
  198. if (GizmoGo != null) GizmoGo.SetActive(false);
  199. }
  200. protected virtual void OnDestroy() => GameObject.Destroy(GizmoGo);
  201. }
  202. }