Nenhuma descrição
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

GroupBrush.cs 8.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.Tilemaps;
  5. namespace UnityEditor.Tilemaps
  6. {
  7. /// <summary>
  8. /// This Brush helps to pick Tiles which are grouped together by position. Gaps can be set to identify if Tiles belong to a Group. Limits can be set to ensure that an over-sized Group will not be picked. Use this as an example to create brushes that have the ability to choose and pick whichever Tiles it is interested in.
  9. /// </summary>
  10. [HelpURL("https://docs.unity3d.com/Packages/com.unity.2d.tilemap.extras@latest/index.html?subfolder=/manual/GroupBrush.html")]
  11. [CustomGridBrush(true, false, false, "Group Brush")]
  12. public class GroupBrush : GridBrush
  13. {
  14. /// <summary>
  15. /// The gap in cell count before stopping to consider a Tile in a Group
  16. /// </summary>
  17. public Vector3Int gap
  18. {
  19. get { return m_Gap; }
  20. set
  21. {
  22. m_Gap = value;
  23. OnValidate();
  24. }
  25. }
  26. /// <summary>
  27. /// The count in cells beyond the initial position before stopping to consider a Tile in a Group
  28. /// </summary>
  29. public Vector3Int limit
  30. {
  31. get { return m_Limit; }
  32. set
  33. {
  34. m_Limit = value;
  35. OnValidate();
  36. }
  37. }
  38. private int visitedLocationsSize
  39. {
  40. get { return (m_Limit.x * 2 + 1) * (m_Limit.y * 2 + 1) * (m_Limit.z * 2 + 1); }
  41. }
  42. [SerializeField]
  43. private Vector3Int m_Gap = Vector3Int.one;
  44. [SerializeField]
  45. private Vector3Int m_Limit = Vector3Int.one * 3;
  46. [SerializeField]
  47. private BitArray m_VisitedLocations = new BitArray(7 * 7 * 7);
  48. [SerializeField]
  49. private Stack<Vector3Int> m_NextPosition = new Stack<Vector3Int>();
  50. private void OnValidate()
  51. {
  52. if (m_Gap.x < 0)
  53. m_Gap.x = 0;
  54. if (m_Gap.y < 0)
  55. m_Gap.y = 0;
  56. if (m_Gap.z < 0)
  57. m_Gap.z = 0;
  58. if (m_Limit.x < 0)
  59. m_Limit.x = 0;
  60. if (m_Limit.y < 0)
  61. m_Limit.y = 0;
  62. if (m_Limit.z < 0)
  63. m_Limit.z = 0;
  64. if (m_VisitedLocations.Length != visitedLocationsSize)
  65. m_VisitedLocations = new BitArray(visitedLocationsSize);
  66. }
  67. /// <summary>
  68. /// Picks tiles from selected Tilemaps and child GameObjects, given the coordinates of the cells.
  69. /// The GroupBrush overrides this to locate groups of Tiles from the picking position.
  70. /// </summary>
  71. /// <param name="grid">Grid to pick data from.</param>
  72. /// <param name="brushTarget">Target of the picking operation. By default the currently selected GameObject.</param>
  73. /// <param name="position">The coordinates of the cells to paint data from.</param>
  74. /// <param name="pickStart">Pivot of the picking brush.</param>
  75. public override void Pick(GridLayout grid, GameObject brushTarget, BoundsInt position, Vector3Int pickStart)
  76. {
  77. // Do standard pick if user has selected a custom bounds
  78. if (position.size.x > 1 || position.size.y > 1 || position.size.z > 1)
  79. {
  80. base.Pick(grid, brushTarget, position, pickStart);
  81. return;
  82. }
  83. Tilemap tilemap = brushTarget.GetComponent<Tilemap>();
  84. if (tilemap == null)
  85. return;
  86. Reset();
  87. // Determine size of picked locations based on gap and limit
  88. Vector3Int limitOrigin = position.position - limit;
  89. Vector3Int limitSize = Vector3Int.one + limit * 2;
  90. BoundsInt limitBounds = new BoundsInt(limitOrigin, limitSize);
  91. BoundsInt pickBounds = new BoundsInt(position.position, Vector3Int.one);
  92. m_VisitedLocations.SetAll(false);
  93. m_VisitedLocations.Set(GetIndex(position.position, limitOrigin, limitSize), true);
  94. m_NextPosition.Clear();
  95. m_NextPosition.Push(position.position);
  96. while (m_NextPosition.Count > 0)
  97. {
  98. Vector3Int next = m_NextPosition.Pop();
  99. if (tilemap.GetTile(next) != null)
  100. {
  101. Encapsulate(ref pickBounds, next);
  102. BoundsInt gapBounds = new BoundsInt(next - gap, Vector3Int.one + gap * 2);
  103. foreach (var gapPosition in gapBounds.allPositionsWithin)
  104. {
  105. if (!limitBounds.Contains(gapPosition))
  106. continue;
  107. int index = GetIndex(gapPosition, limitOrigin, limitSize);
  108. if (!m_VisitedLocations.Get(index))
  109. {
  110. m_NextPosition.Push(gapPosition);
  111. m_VisitedLocations.Set(index, true);
  112. }
  113. }
  114. }
  115. }
  116. UpdateSizeAndPivot(pickBounds.size, position.position - pickBounds.position);
  117. foreach (Vector3Int pos in pickBounds.allPositionsWithin)
  118. {
  119. Vector3Int brushPosition = new Vector3Int(pos.x - pickBounds.x, pos.y - pickBounds.y, pos.z - pickBounds.z);
  120. if (m_VisitedLocations.Get(GetIndex(pos, limitOrigin, limitSize)))
  121. {
  122. PickCell(pos, brushPosition, tilemap);
  123. }
  124. }
  125. }
  126. private void Encapsulate(ref BoundsInt bounds, Vector3Int position)
  127. {
  128. if (bounds.Contains(position))
  129. return;
  130. if (position.x < bounds.position.x)
  131. {
  132. var increase = bounds.x - position.x;
  133. bounds.position = new Vector3Int(position.x, bounds.y, bounds.z);
  134. bounds.size = new Vector3Int(bounds.size.x + increase, bounds.size.y, bounds.size.z);
  135. }
  136. if (position.x >= bounds.xMax)
  137. {
  138. var increase = position.x - bounds.xMax + 1;
  139. bounds.size = new Vector3Int(bounds.size.x + increase, bounds.size.y, bounds.size.z);
  140. }
  141. if (position.y < bounds.position.y)
  142. {
  143. var increase = bounds.y - position.y;
  144. bounds.position = new Vector3Int(bounds.x, position.y, bounds.z);
  145. bounds.size = new Vector3Int(bounds.size.x, bounds.size.y + increase, bounds.size.z);
  146. }
  147. if (position.y >= bounds.yMax)
  148. {
  149. var increase = position.y - bounds.yMax + 1;
  150. bounds.size = new Vector3Int(bounds.size.x, bounds.size.y + increase, bounds.size.z);
  151. }
  152. if (position.z < bounds.position.z)
  153. {
  154. var increase = bounds.z - position.z;
  155. bounds.position = new Vector3Int(bounds.x, bounds.y, position.z);
  156. bounds.size = new Vector3Int(bounds.size.x, bounds.size.y, bounds.size.z + increase);
  157. }
  158. if (position.z >= bounds.zMax)
  159. {
  160. var increase = position.z - bounds.zMax + 1;
  161. bounds.size = new Vector3Int(bounds.size.x, bounds.size.y, bounds.size.z + increase);
  162. }
  163. }
  164. private int GetIndex(Vector3Int position, Vector3Int origin, Vector3Int size)
  165. {
  166. return (position.z - origin.z) * size.y * size.x
  167. + (position.y - origin.y) * size.x
  168. + (position.x - origin.x);
  169. }
  170. private void PickCell(Vector3Int position, Vector3Int brushPosition, Tilemap tilemap)
  171. {
  172. if (tilemap != null)
  173. {
  174. SetTile(brushPosition, tilemap.GetTile(position));
  175. SetMatrix(brushPosition, tilemap.GetTransformMatrix(position));
  176. SetColor(brushPosition, tilemap.GetColor(position));
  177. }
  178. }
  179. }
  180. /// <summary>
  181. /// The Brush Editor for a Group Brush.
  182. /// </summary>
  183. [CustomEditor(typeof(GroupBrush))]
  184. public class GroupBrushEditor : GridBrushEditor
  185. {
  186. private static readonly string iconPath = "Packages/com.unity.2d.tilemap.extras/Editor/Brushes/GroupBrush/GroupBrush.png";
  187. private Texture2D m_BrushIcon;
  188. /// <summary> Returns an icon identifying the Group Brush. </summary>
  189. public override Texture2D icon
  190. {
  191. get
  192. {
  193. if (m_BrushIcon == null)
  194. {
  195. var gui = EditorGUIUtility.TrIconContent(iconPath);
  196. m_BrushIcon = gui.image as Texture2D;
  197. }
  198. return m_BrushIcon;
  199. }
  200. }
  201. }
  202. }