ObjectVertexSnapSession.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. #if UNITY_EDITOR
  2. using UnityEngine;
  3. using System.Collections.Generic;
  4. namespace O3DWB
  5. {
  6. public class ObjectVertexSnapSession
  7. {
  8. #region Private Variables
  9. private GameObject _sourceObject;
  10. private List<GameObject> _sourceObjects;
  11. private List<GameObject> _sourceParents;
  12. private GameObject _destinationObject;
  13. private XZGridCell _destinationGridCell;
  14. private Vector3 _sourceVertex;
  15. private Vector3 _snapPosition;
  16. private ObjectVertexSnapSessionState _state;
  17. private bool _isActive;
  18. private ObjectMask _objectMask = new ObjectMask();
  19. #endregion
  20. #region Public Properties
  21. public bool IsActive { get { return _isActive; } }
  22. public GameObject SourceGameObject { get { return _sourceObject; } }
  23. public bool HasMultipleSourceObjects { get { return _sourceObjects != null && _sourceObjects.Count != 0; } }
  24. public GameObject DestinationGameObject { get { return _destinationObject; } }
  25. public XZGridCell DestinationGridCell { get { return _destinationGridCell != null ? new XZGridCell(_destinationGridCell) : null; } }
  26. public Vector3 SourceVertex { get { return _sourceVertex; } }
  27. public Vector3 SnapPosition { get { return _snapPosition; } }
  28. public ObjectVertexSnapSessionState State { get { return _state; } }
  29. #endregion
  30. #region Public Methods
  31. public void Begin()
  32. {
  33. if (_isActive) return;
  34. _isActive = true;
  35. ResetData();
  36. _state = ObjectVertexSnapSessionState.SelectSourceVertex;
  37. }
  38. public void Begin(List<GameObject> sourceObjects)
  39. {
  40. if (_isActive) return;
  41. if (sourceObjects.Count == 0) return;
  42. _isActive = true;
  43. ResetData();
  44. _sourceObjects = new List<GameObject>(sourceObjects);
  45. _sourceParents = Octave3DWorldBuilder.ActiveInstance.GetRoots(_sourceObjects);
  46. foreach (var parent in _sourceParents)
  47. _objectMask.ObjectCollectionMask.Mask(parent.GetAllChildrenIncludingSelf());
  48. _state = ObjectVertexSnapSessionState.SelectSourceVertex;
  49. }
  50. public void End()
  51. {
  52. _isActive = false;
  53. ResetData();
  54. }
  55. public void UpdateForMouseMovement()
  56. {
  57. if (!_isActive) return;
  58. if (MouseButtonStates.Instance.IsMouseButtonDown(MouseButton.Left)) _state = ObjectVertexSnapSessionState.SnapToDestination;
  59. else _state = ObjectVertexSnapSessionState.SelectSourceVertex;
  60. if (_state == ObjectVertexSnapSessionState.SelectSourceVertex)
  61. {
  62. if (_sourceObjects == null || _sourceObjects.Count == 0)
  63. {
  64. _objectMask.ObjectCollectionMask.UnmaskAll();
  65. MouseCursorRayHit cursorRayHit = GetCursorRayHit();
  66. if (cursorRayHit.WasAnObjectHit)
  67. {
  68. GameObjectRayHit objectRayHit = cursorRayHit.ClosestObjectRayHit;
  69. MeshRayHit meshRayHit = objectRayHit.ObjectMeshHit;
  70. if (meshRayHit != null)
  71. {
  72. Octave3DMesh octaveMesh = meshRayHit.HitMesh;
  73. Triangle3D sourceTriangle = octaveMesh.GetTriangle(meshRayHit.HitTriangleIndex);
  74. sourceTriangle.TransformPoints(objectRayHit.HitObject.transform.localToWorldMatrix);
  75. _sourceVertex = sourceTriangle.GetPointClosestToPoint(meshRayHit.HitPoint);
  76. _sourceObject = objectRayHit.HitObject;
  77. _objectMask.ObjectCollectionMask.Mask(_sourceObject.transform.root.gameObject.GetAllChildrenIncludingSelf());
  78. }
  79. else
  80. {
  81. SpriteRenderer spriteRenderer = objectRayHit.HitObject.GetComponent<SpriteRenderer>();
  82. if (spriteRenderer != null)
  83. {
  84. _sourceObject = objectRayHit.HitObject;
  85. _sourceVertex = Vector3Extensions.GetClosestPointToPoint(objectRayHit.ObjectBoxHit.HitBox.GetCenterAndCornerPoints(), objectRayHit.HitPoint);
  86. _objectMask.ObjectCollectionMask.Mask(_sourceObject.transform.root.gameObject.GetAllChildrenIncludingSelf());
  87. }
  88. }
  89. }
  90. }
  91. else
  92. {
  93. MouseCursorRayHit cursorRayHit = GetCursorRayHit();
  94. if (cursorRayHit.WasAnObjectHit)
  95. {
  96. GameObjectRayHit objectRayHit = cursorRayHit.ClosestObjectRayHit;
  97. MeshRayHit meshRayHit = objectRayHit.ObjectMeshHit;
  98. if (meshRayHit != null)
  99. {
  100. Octave3DMesh octaveMesh = meshRayHit.HitMesh;
  101. Triangle3D sourceTriangle = octaveMesh.GetTriangle(meshRayHit.HitTriangleIndex);
  102. sourceTriangle.TransformPoints(objectRayHit.HitObject.transform.localToWorldMatrix);
  103. _sourceVertex = sourceTriangle.GetPointClosestToPoint(meshRayHit.HitPoint);
  104. }
  105. else
  106. {
  107. SpriteRenderer spriteRenderer = objectRayHit.HitObject.GetComponent<SpriteRenderer>();
  108. if (spriteRenderer != null)
  109. {
  110. _sourceVertex = Vector3Extensions.GetClosestPointToPoint(objectRayHit.ObjectBoxHit.HitBox.GetCenterAndCornerPoints(), objectRayHit.HitPoint);
  111. }
  112. }
  113. }
  114. foreach (var parent in _sourceParents)
  115. _objectMask.ObjectCollectionMask.Mask(parent.GetAllChildrenIncludingSelf());
  116. }
  117. }
  118. else
  119. {
  120. MouseCursorRayHit cursorRayHit = GetCursorRayHit();
  121. if (cursorRayHit.WasAnythingHit)
  122. {
  123. bool useGridCellHit = false;
  124. if (!cursorRayHit.WasAnObjectHit) useGridCellHit = true;
  125. else
  126. if (cursorRayHit.WasAnObjectHit && cursorRayHit.WasACellHit)
  127. {
  128. float gridCellHitEnter = cursorRayHit.GridCellRayHit.HitEnter;
  129. float objectHitEnter = cursorRayHit.ClosestObjectRayHit.HitEnter;
  130. if (gridCellHitEnter < Mathf.Max(0.0f, (objectHitEnter - 1e-3f))) useGridCellHit = true;
  131. }
  132. if (useGridCellHit)
  133. {
  134. XZGridCell hitCell = cursorRayHit.GridCellRayHit.HitCell;
  135. XZOrientedQuad3D cellQuad = hitCell.Quad;
  136. _destinationObject = null;
  137. _destinationGridCell = hitCell;
  138. _snapPosition = cellQuad.GetPointClosestToPoint(cursorRayHit.GridCellRayHit.HitPoint, true);
  139. SnapToDestination();
  140. }
  141. else
  142. {
  143. GameObjectRayHit objectRayHit = cursorRayHit.ClosestObjectRayHit;
  144. MeshRayHit meshRayHit = objectRayHit.ObjectMeshHit;
  145. if (meshRayHit != null)
  146. {
  147. _destinationObject = objectRayHit.HitObject;
  148. Triangle3D destinationTriangle = meshRayHit.HitMesh.GetTriangle(meshRayHit.HitTriangleIndex);
  149. destinationTriangle.TransformPoints(_destinationObject.transform.localToWorldMatrix);
  150. _destinationGridCell = null;
  151. _snapPosition = destinationTriangle.GetPointClosestToPoint(meshRayHit.HitPoint);
  152. SnapToDestination();
  153. }
  154. else
  155. {
  156. SpriteRenderer spriteRenderer = objectRayHit.HitObject.GetComponent<SpriteRenderer>();
  157. if (spriteRenderer != null)
  158. {
  159. _destinationGridCell = null;
  160. _destinationObject = objectRayHit.HitObject;
  161. _snapPosition = Vector3Extensions.GetClosestPointToPoint(objectRayHit.ObjectBoxHit.HitBox.GetCenterAndCornerPoints(), objectRayHit.HitPoint);
  162. SnapToDestination();
  163. }
  164. }
  165. }
  166. }
  167. }
  168. }
  169. #endregion
  170. #region Private Methods
  171. private void ResetData()
  172. {
  173. _sourceObject = null;
  174. if (_sourceObjects != null) _sourceObjects.Clear();
  175. _sourceObjects = null;
  176. _destinationObject = null;
  177. _destinationGridCell = null;
  178. _objectMask.ObjectCollectionMask.UnmaskAll();
  179. }
  180. private MouseCursorRayHit GetCursorRayHit()
  181. {
  182. if (_sourceObjects == null || _state == ObjectVertexSnapSessionState.SnapToDestination)
  183. {
  184. MouseCursor.Instance.PushObjectMask(_objectMask);
  185. MouseCursor.Instance.PushObjectPickMaskFlags(MouseCursorObjectPickFlags.ObjectBox | MouseCursorObjectPickFlags.ObjectTerrain);
  186. MouseCursorRayHit cursorRayHit = MouseCursor.Instance.GetRayHit();
  187. MouseCursor.Instance.PopObjectPickMaskFlags();
  188. MouseCursor.Instance.PopObjectMask();
  189. return cursorRayHit;
  190. }
  191. else
  192. {
  193. return MouseCursor.Instance.GetRayHitForMeshAndSpriteObjects(_sourceObjects);
  194. }
  195. }
  196. private void SnapToDestination()
  197. {
  198. Vector3 snapVector = _snapPosition - _sourceVertex;
  199. if (_sourceObjects == null)
  200. {
  201. GameObject root = Octave3DWorldBuilder.ActiveInstance.GetRoot(_sourceObject);
  202. if (root != null)
  203. {
  204. Transform parentTransform = root.transform;
  205. UndoEx.RecordForToolAction(parentTransform);
  206. parentTransform.position += snapVector;
  207. _sourceVertex += snapVector;
  208. }
  209. }
  210. else
  211. {
  212. foreach (var parent in _sourceParents)
  213. {
  214. Transform parentTransform = parent.transform;
  215. UndoEx.RecordForToolAction(parentTransform);
  216. parentTransform.position += snapVector;
  217. }
  218. _sourceVertex += snapVector;
  219. }
  220. }
  221. #endregion
  222. }
  223. }
  224. #endif