CustomGizmo.cs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. using System;
  2. using System.Reflection;
  3. using UnityEngine;
  4. namespace COM3D2.MeidoPhotoStudio.Plugin
  5. {
  6. public class CustomGizmo : GizmoRender
  7. {
  8. private static readonly Camera camera = GameMain.Instance.MainCamera.camera;
  9. private Transform target;
  10. private readonly FieldInfo beSelectedType = Utility.GetFieldInfo<GizmoRender>("beSelectedType");
  11. private int SelectedType => (int)beSelectedType.GetValue(this);
  12. private static readonly FieldInfo is_drag_ = Utility.GetFieldInfo<GizmoRender>("is_drag_");
  13. public static bool IsDrag
  14. {
  15. get => (bool)is_drag_.GetValue(null);
  16. private set => is_drag_.SetValue(null, value);
  17. }
  18. private Vector3 positionOld = Vector3.zero;
  19. private Vector3 deltaPosition = Vector3.zero;
  20. private Vector3 deltaLocalPosition = Vector3.zero;
  21. private Quaternion rotationOld = Quaternion.identity;
  22. private Quaternion deltaRotation = Quaternion.identity;
  23. private Quaternion deltaLocalRotation = Quaternion.identity;
  24. private Vector3 deltaScale = Vector3.zero;
  25. private Vector3 scaleOld = Vector3.one;
  26. private GizmoType gizmoTypeOld;
  27. private GizmoType gizmoType;
  28. public GizmoType CurrentGizmoType
  29. {
  30. get => gizmoType;
  31. set
  32. {
  33. gizmoType = value;
  34. if (gizmoTypeOld == gizmoType) return;
  35. gizmoTypeOld = gizmoType;
  36. eAxis = gizmoType == GizmoType.Move;
  37. eScal = gizmoType == GizmoType.Scale;
  38. eRotate = gizmoType == GizmoType.Rotate;
  39. }
  40. }
  41. public bool IsGizmoDrag => GizmoVisible && IsDrag && SelectedType != 0;
  42. public bool GizmoVisible
  43. {
  44. get => Visible;
  45. set
  46. {
  47. if (value && IsDrag) IsDrag = false;
  48. Visible = value;
  49. }
  50. }
  51. public GizmoMode gizmoMode;
  52. public event EventHandler GizmoDrag;
  53. public enum GizmoType { Rotate, Move, Scale }
  54. public enum GizmoMode { Local, World, Global }
  55. public static CustomGizmo Make(Transform target, float scale = 0.25f, GizmoMode mode = GizmoMode.Local)
  56. {
  57. var gizmoGo = new GameObject($"[MPS Gizmo {target.gameObject.name}]");
  58. gizmoGo.transform.SetParent(target);
  59. var gizmo = gizmoGo.AddComponent<CustomGizmo>();
  60. gizmo.target = target;
  61. gizmo.lineRSelectedThick = 0.25f;
  62. gizmo.offsetScale = scale;
  63. gizmo.gizmoMode = mode;
  64. gizmo.CurrentGizmoType = GizmoType.Rotate;
  65. return gizmo;
  66. }
  67. public override void Update()
  68. {
  69. BeginUpdate();
  70. base.Update();
  71. if (IsGizmoDrag) SetTargetTransform();
  72. SetTransform();
  73. EndUpdate();
  74. }
  75. private void BeginUpdate()
  76. {
  77. Quaternion rotation = transform.rotation;
  78. deltaPosition = transform.position - positionOld;
  79. deltaRotation = rotation * Quaternion.Inverse(rotationOld);
  80. deltaLocalPosition = transform.InverseTransformVector(deltaPosition);
  81. deltaLocalRotation = Quaternion.Inverse(rotationOld) * rotation;
  82. deltaScale = transform.localScale - scaleOld;
  83. }
  84. private void EndUpdate()
  85. {
  86. Transform transform = this.transform;
  87. positionOld = transform.position;
  88. rotationOld = transform.rotation;
  89. scaleOld = transform.localScale;
  90. }
  91. private void SetTargetTransform()
  92. {
  93. bool dragged;
  94. switch (gizmoMode)
  95. {
  96. case GizmoMode.Local:
  97. target.position += target.transform.TransformVector(deltaLocalPosition).normalized
  98. * deltaLocalPosition.magnitude;
  99. target.rotation *= deltaLocalRotation;
  100. target.localScale += deltaScale;
  101. dragged = deltaLocalRotation != Quaternion.identity || deltaLocalPosition != Vector3.zero
  102. || deltaScale != Vector3.zero;
  103. break;
  104. case GizmoMode.World:
  105. case GizmoMode.Global:
  106. target.position += deltaPosition;
  107. target.rotation = deltaRotation * target.rotation;
  108. dragged = deltaRotation != Quaternion.identity || deltaPosition != Vector3.zero;
  109. break;
  110. default: throw new ArgumentOutOfRangeException();
  111. }
  112. if (dragged) OnGizmoDrag();
  113. }
  114. private void SetTransform()
  115. {
  116. Transform transform = this.transform;
  117. transform.position = target.position;
  118. transform.localScale = Vector3.one;
  119. transform.rotation = gizmoMode switch
  120. {
  121. GizmoMode.Local => target.rotation,
  122. GizmoMode.World => Quaternion.identity,
  123. GizmoMode.Global => Quaternion.LookRotation(transform.position - camera.transform.position),
  124. _ => target.rotation
  125. };
  126. }
  127. private void OnGizmoDrag() => GizmoDrag?.Invoke(this, EventArgs.Empty);
  128. }
  129. }