SelectionTool.cs 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using UnityEditor.U2D.Layout;
  5. using UnityEditor.U2D.Sprites;
  6. using UnityEngine;
  7. namespace UnityEditor.U2D.Animation
  8. {
  9. internal class SelectionTool : BaseTool
  10. {
  11. bool m_ForceSelectedToSpriteEditor = false;
  12. int m_LastMouseButtonDown = -1;
  13. public event Func<bool> CanSelect = () => true;
  14. List<SpriteCache> m_Sprites;
  15. public ISpriteEditor spriteEditor { get; set; }
  16. SpriteCache selectedSprite
  17. {
  18. get => skinningCache.selectedSprite;
  19. set
  20. {
  21. if (selectedSprite != value)
  22. {
  23. skinningCache.vertexSelection.Clear();
  24. if (skinningCache.mode == SkinningMode.SpriteSheet)
  25. {
  26. skinningCache.skeletonSelection.Clear();
  27. skinningCache.events.boneSelectionChanged.Invoke();
  28. }
  29. skinningCache.selectedSprite = value;
  30. SetToSpriteEditor();
  31. skinningCache.events.selectedSpriteChanged.Invoke(value);
  32. }
  33. }
  34. }
  35. string selectedSpriteAssetID
  36. {
  37. get
  38. {
  39. var sprite = Selection.activeObject as Sprite;
  40. if (sprite != null)
  41. return sprite.GetSpriteID().ToString();
  42. return "";
  43. }
  44. }
  45. protected override void OnAfterDeserialize()
  46. {
  47. m_ForceSelectedToSpriteEditor = true;
  48. }
  49. public override void Initialize(LayoutOverlay layoutOverlay)
  50. {
  51. m_Sprites = new List<SpriteCache>(skinningCache.GetSprites());
  52. SetFromSpriteEditor();
  53. }
  54. protected override void OnActivate()
  55. {
  56. SetToSpriteEditor();
  57. skinningCache.events.selectedSpriteChanged.AddListener(OnSpriteSelectionChange);
  58. Selection.selectionChanged -= OnSelectionChanged;
  59. Selection.selectionChanged += OnSelectionChanged;
  60. }
  61. protected override void OnDeactivate()
  62. {
  63. skinningCache.events.selectedSpriteChanged.RemoveListener(OnSpriteSelectionChange);
  64. Selection.selectionChanged -= OnSelectionChanged;
  65. }
  66. private void OnSpriteSelectionChange(SpriteCache sprite)
  67. {
  68. skinningCache.events.selectedSpriteChanged.RemoveListener(OnSpriteSelectionChange);
  69. selectedSprite = sprite;
  70. skinningCache.events.selectedSpriteChanged.AddListener(OnSpriteSelectionChange);
  71. }
  72. void OnSelectionChanged()
  73. {
  74. if (m_ForceSelectedToSpriteEditor)
  75. {
  76. SetToSpriteEditor();
  77. m_ForceSelectedToSpriteEditor = false;
  78. }
  79. else
  80. {
  81. using (skinningCache.UndoScope(TextContent.selectionChange))
  82. {
  83. SetFromSpriteEditor();
  84. }
  85. }
  86. }
  87. void SetFromSpriteEditor()
  88. {
  89. if (selectedSprite == null)
  90. selectedSprite = skinningCache.GetSprite(selectedSpriteAssetID);
  91. spriteEditor.RequestRepaint();
  92. }
  93. void SetToSpriteEditor()
  94. {
  95. var id = "";
  96. if (selectedSprite != null)
  97. id = selectedSprite.id;
  98. spriteEditor.selectedSpriteRect = new SpriteRect() { spriteID = new GUID(id) };
  99. }
  100. protected override void OnGUI()
  101. {
  102. HandleSpriteSelection();
  103. }
  104. void HandleSpriteSelection()
  105. {
  106. Debug.Assert(Event.current != null);
  107. if (Event.current.type == EventType.MouseDown)
  108. {
  109. if (IsSelectionRequested())
  110. {
  111. var mousePosition = Handles.inverseMatrix.MultiplyPoint(Event.current.mousePosition);
  112. var newSelected = TrySelect(mousePosition);
  113. if (selectedSprite != newSelected)
  114. {
  115. using (skinningCache.UndoScope(TextContent.selectionChange))
  116. {
  117. selectedSprite = newSelected;
  118. }
  119. Event.current.Use();
  120. }
  121. }
  122. else
  123. m_LastMouseButtonDown = Event.current.button;
  124. }
  125. }
  126. SpriteCache TrySelect(Vector2 mousePosition)
  127. {
  128. m_Sprites.Remove(selectedSprite);
  129. if (selectedSprite != null)
  130. m_Sprites.Add(selectedSprite);
  131. var currentSelectedIndex = m_Sprites.FindIndex(x => x == selectedSprite) + 1;
  132. var notVisiblePart = skinningCache.hasCharacter && skinningCache.mode == SkinningMode.Character
  133. ? skinningCache.character.parts.Where(x => !x.isVisible).Select(x => x.sprite) : new SpriteCache[0];
  134. for (int index = 0; index < m_Sprites.Count; ++index)
  135. {
  136. var sprite = m_Sprites[(currentSelectedIndex + index) % m_Sprites.Count];
  137. var meshPreview = sprite.GetMeshPreview();
  138. if (notVisiblePart.Contains(sprite))
  139. continue;
  140. Debug.Assert(meshPreview != null);
  141. var spritePosition = sprite.GetLocalToWorldMatrixFromMode().MultiplyPoint3x4(Vector3.zero);
  142. var ray = new Ray((Vector3)mousePosition - spritePosition + Vector3.back, Vector3.forward);
  143. var bounds = meshPreview.mesh.bounds;
  144. if (sprite.GetMesh().indices.Count >= 3)
  145. {
  146. if (bounds.IntersectRay(ray))
  147. {
  148. var mesh = sprite.GetMesh();
  149. Debug.Assert(mesh != null);
  150. var indices = mesh.indices;
  151. for (var i = 0; i < indices.Count; i += 3)
  152. {
  153. var p1 = meshPreview.vertices[indices[i]];
  154. var p2 = meshPreview.vertices[indices[i + 1]];
  155. var p3 = meshPreview.vertices[indices[i + 2]];
  156. if (MathUtility.Intersect(p1, p2, p3, ray))
  157. return sprite;
  158. }
  159. }
  160. }
  161. else
  162. {
  163. if (meshPreview.defaultMesh.bounds.IntersectRay(ray))
  164. {
  165. return sprite;
  166. }
  167. }
  168. }
  169. return null;
  170. }
  171. bool IsSelectionRequested()
  172. {
  173. return Event.current.button == 0 && m_LastMouseButtonDown == 0 && GUIUtility.hotControl == 0 &&
  174. !Event.current.alt && Event.current.clickCount == 2 && CanSelect();
  175. }
  176. }
  177. }