Guest User

Untitled

a guest
Apr 20th, 2018
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.37 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using UnityEngine;
  5. using UnityEngine.Tilemaps;
  6. namespace UnityEditor
  7. {
  8. [CreateAssetMenu, CustomGridBrush(false, true, false, "Test Random Brush")]
  9. public class TestRandomBrush : GridBrush
  10. {
  11. [Flags]
  12. public enum Orientation
  13. {
  14. None = 0,
  15. FlipX = 1,
  16. FlipY = (1 << 1),
  17. Rot90 = (1 << 2),
  18. }
  19. public Orientation orientation = Orientation.None;
  20. private bool RandomBool => UnityEngine.Random.value > .5f;
  21. private bool FlipX => (orientation & Orientation.FlipX) == Orientation.FlipX ? RandomBool : false;
  22. private bool FlipY => (orientation & Orientation.FlipY) == Orientation.FlipY ? RandomBool : false;
  23. private bool Rot90 => (orientation & Orientation.Rot90) == Orientation.Rot90 ? RandomBool : false;
  24. private static Quaternion rotateClockwise = Quaternion.Euler(0, 0, -90f);
  25. private static Quaternion rotateCounter = Quaternion.Euler(0, 0, 90f);
  26. private Matrix4x4 RandomMatrix => Matrix4x4.TRS(Vector3.zero,
  27. Rot90 ? rotateClockwise : Quaternion.identity, new Vector3(FlipX ? -1f : 1f, FlipY ? -1f : 1f, 1f));
  28. public TileBase[] randomTiles;
  29. public int[] probabilities;
  30. private TileBase RandomTile
  31. {
  32. get
  33. {
  34. if (probabilities?.Length == randomTiles.Length)
  35. {
  36. var total = 0f;
  37. var roll = UnityEngine.Random.Range(0, probabilities.Sum());
  38. for (var i = 0; i < probabilities.Length; i++)
  39. {
  40. total += probabilities[i];
  41. if (roll < total)
  42. return randomTiles[i];
  43. }
  44. return null;
  45. }
  46. else
  47. return randomTiles[UnityEngine.Random.Range(0, randomTiles.Length)];
  48. }
  49. }
  50. private Vector3Int? lastPosition;
  51. private Dictionary<Vector3Int, Tuple<TileBase, Matrix4x4>> cache = new Dictionary<Vector3Int, Tuple<TileBase, Matrix4x4>>();
  52. public Tuple<TileBase, Matrix4x4> this[Vector3Int key]
  53. {
  54. get
  55. {
  56. if (!cache.ContainsKey(key))
  57. this[key] = new Tuple<TileBase, Matrix4x4>(RandomTile, RandomMatrix);
  58. return cache[key];
  59. }
  60. set
  61. {
  62. cache[key] = value;
  63. lastPosition = key;
  64. }
  65. }
  66. public void CacheClear(Vector3Int? position = null)
  67. {
  68. if (position == null || position != lastPosition)
  69. cache.Clear();
  70. }
  71. private FlipAxis? flipAxis;
  72. private RotationDirection? rotationDirection;
  73. public void CacheUpdate()
  74. {
  75. if (flipAxis.HasValue || rotationDirection.HasValue)
  76. {
  77. foreach (var i in cache.ToList())
  78. {
  79. var m = i.Value.Item2;
  80. var p = m.GetColumn(3);
  81. var r = Quaternion.LookRotation(m.GetColumn(2), m.GetColumn(1));
  82. var s = new Vector3(m.GetColumn(0).magnitude, m.GetColumn(1).magnitude, m.GetColumn(2).magnitude);
  83. if (flipAxis.HasValue)
  84. s = new Vector3(flipAxis.Value == FlipAxis.X ? s.x * -1f : s.x,
  85. flipAxis.Value == FlipAxis.Y ? s.y * -1f : s.y, s.z);
  86. if (rotationDirection.HasValue)
  87. r *= rotationDirection.Value == RotationDirection.Clockwise ? rotateClockwise : rotateCounter;
  88. m.SetTRS(p, r, s);
  89. cache[i.Key] = new Tuple<TileBase, Matrix4x4>(i.Value.Item1, m);
  90. }
  91. flipAxis = null;
  92. rotationDirection = null;
  93. }
  94. }
  95. public BoundsInt Bounds(Vector3Int position)
  96. {
  97. var min = position - pivot;
  98. var max = min + size;
  99. return new BoundsInt(min, max - min);
  100. }
  101. public override void Flip(FlipAxis flip, GridLayout.CellLayout layout)
  102. {
  103. flipAxis = flip;
  104. base.Flip(flip, layout);
  105. }
  106. public override void Rotate(RotationDirection direction, GridLayout.CellLayout layout)
  107. {
  108. rotationDirection = direction;
  109. base.Rotate(direction, layout);
  110. }
  111. public override void Select(GridLayout gridLayout, GameObject brushTarget, BoundsInt position)
  112. {
  113. var map = brushTarget?.GetComponent<Tilemap>();
  114. if (map == null)
  115. return;
  116. foreach (var i in position.allPositionsWithin)
  117. {
  118. var tile = map.GetTile(i);
  119. this[i] = new Tuple<TileBase, Matrix4x4>(tile, map.GetTransformMatrix(i));
  120. }
  121. }
  122. public override void Move(GridLayout gridLayout, GameObject brushTarget, BoundsInt from, BoundsInt to)
  123. {
  124. Vector3Int offset = to.min - from.min;
  125. foreach (var i in cache.ToList())
  126. {
  127. cache[i.Key] = null;
  128. cache[i.Key + offset] = i.Value;
  129. }
  130. base.Move(gridLayout, brushTarget, from, to);
  131. }
  132. public override void Paint(GridLayout gridLayout, GameObject brushTarget, Vector3Int position)
  133. {
  134. if (randomTiles?.Length > 0)
  135. Common(gridLayout, brushTarget, position);
  136. }
  137. public override void BoxFill(GridLayout gridLayout, GameObject brushTarget, BoundsInt position)
  138. {
  139. if (randomTiles?.Length > 0)
  140. foreach (var i in position.allPositionsWithin)
  141. Common(gridLayout, brushTarget, i);
  142. }
  143. public override void FloodFill(GridLayout gridLayout, GameObject brushTarget, Vector3Int position)
  144. {
  145. if (randomTiles?.Length > 0)
  146. {
  147. var map = brushTarget?.GetComponent<Tilemap>();
  148. if (map == null)
  149. return;
  150. FloodFill(map, gridLayout, brushTarget, position);
  151. }
  152. }
  153. private void FloodFill(Tilemap map, GridLayout gridLayout, GameObject brushTarget, Vector3Int position)
  154. {
  155. var exist = map.GetTile(position);
  156. var points = new Stack<Vector3Int>();
  157. var used = new List<Vector3Int>();
  158. points.Push(position);
  159. while (points.Count > 0)
  160. {
  161. var p = points.Pop();
  162. used.Add(p);
  163. Common(map, gridLayout, brushTarget, p);
  164. for (var y = p.y - 1; y <= p.y + 1; y++)
  165. {
  166. for (var x = p.x - 1; x <= p.x + 1; x++)
  167. {
  168. var test = new Vector3Int(x, y, p.z);
  169. if ((test.y != p.y || test.x != p.x) && map.cellBounds.Contains(test) &&
  170. (exist ? map.GetTile(test) : !map.GetTile(test)) && !used.Contains(test))
  171. points.Push(test);
  172. }
  173. }
  174. }
  175. }
  176. private void Common(GridLayout gridLayout, GameObject brushTarget, Vector3Int position)
  177. {
  178. var map = brushTarget?.GetComponent<Tilemap>();
  179. if (map == null)
  180. return;
  181. foreach (var i in Bounds(position).allPositionsWithin)
  182. Common(map, gridLayout, brushTarget, i);
  183. }
  184. private void Common(Tilemap map, GridLayout gridLayout, GameObject brushTarget, Vector3Int position)
  185. {
  186. var c = this[position];
  187. map.SetTile(position, c.Item1);
  188. map.SetTransformMatrix(position, c.Item2);
  189. }
  190. }
  191. [CustomEditor(typeof(TestRandomBrush))]
  192. public class TestRandomBrushEditor : GridBrushEditor
  193. {
  194. private TestRandomBrush RandomBrush => target as TestRandomBrush;
  195. private GameObject lastBrush;
  196. public override void PaintPreview(GridLayout gridLayout, GameObject brushTarget, Vector3Int position)
  197. {
  198. var brush = RandomBrush;
  199. brush.CacheClear(position);
  200. if (brush.randomTiles?.Length > 0)
  201. Common(gridLayout, brushTarget, position);
  202. }
  203. public override void BoxFillPreview(GridLayout gridLayout, GameObject brushTarget, BoundsInt position)
  204. {
  205. var brush = RandomBrush;
  206. brush.CacheClear();
  207. if (brush.randomTiles?.Length > 0)
  208. foreach (var i in position.allPositionsWithin)
  209. Common(gridLayout, brushTarget, i);
  210. }
  211. public override void FloodFillPreview(GridLayout gridLayout, GameObject brushTarget, Vector3Int position)
  212. {
  213. var brush = RandomBrush;
  214. brush.CacheClear(position);
  215. if (brush.randomTiles?.Length > 0)
  216. {
  217. var map = brushTarget?.GetComponent<Tilemap>();
  218. if (map == null)
  219. return;
  220. FloodFill(map, gridLayout, brushTarget, position);
  221. }
  222. }
  223. private void FloodFill(Tilemap map, GridLayout gridLayout, GameObject brushTarget, Vector3Int position)
  224. {
  225. var exist = map.GetTile(position);
  226. var points = new Stack<Vector3Int>();
  227. var used = new List<Vector3Int>();
  228. var bounds = map.cellBounds;
  229. var size = new Vector2Int((int)map.cellSize.x, (int)map.cellSize.y);
  230. points.Push(position);
  231. while (points.Count > 0)
  232. {
  233. var p = points.Pop();
  234. used.Add(p);
  235. if (!bounds.Contains(p))
  236. bounds.SetMinMax(new Vector3Int(Math.Min(bounds.xMin, p.x), Math.Min(bounds.yMin, p.y), 0),
  237. new Vector3Int(Math.Max(bounds.xMax, p.x) + size.x, Math.Max(bounds.yMax, p.y) + size.y, 1));
  238. Common(map, gridLayout, brushTarget, p);
  239. for (var y = p.y - 1; y <= p.y + 1; y++)
  240. {
  241. for (var x = p.x - 1; x <= p.x + 1; x++)
  242. {
  243. var test = new Vector3Int(x, y, p.z);
  244. if ((test.y != p.y || test.x != p.x) && map.cellBounds.Contains(test) &&
  245. (exist ? map.GetTile(test) : !map.GetTile(test)) && !used.Contains(test))
  246. points.Push(test);
  247. }
  248. }
  249. }
  250. }
  251. private void Common(GridLayout gridLayout, GameObject brushTarget, Vector3Int position)
  252. {
  253. var map = brushTarget?.GetComponent<Tilemap>();
  254. if (map == null)
  255. return;
  256. foreach (var i in RandomBrush.Bounds(position).allPositionsWithin)
  257. Common(map, gridLayout, brushTarget, i);
  258. }
  259. private void Common(Tilemap map, GridLayout gridLayout, GameObject brushTarget, Vector3Int position)
  260. {
  261. var c = RandomBrush[position];
  262. map.SetEditorPreviewTile(position, c.Item1);
  263. map.SetEditorPreviewTransformMatrix(position, c.Item2);
  264. lastBrush = brushTarget;
  265. }
  266. public override void ClearPreview()
  267. {
  268. if (lastBrush != null)
  269. {
  270. RandomBrush.CacheUpdate();
  271. var map = lastBrush.GetComponent<Tilemap>();
  272. if (map == null)
  273. return;
  274. map.ClearAllEditorPreviewTiles();
  275. lastBrush = null;
  276. }
  277. }
  278. public override void OnPaintInspectorGUI() => GUI();
  279. public override void OnInspectorGUI() => GUI();
  280. private void GUI()
  281. {
  282. var brush = RandomBrush;
  283. EditorGUI.BeginChangeCheck();
  284. brush.orientation = (TestRandomBrush.Orientation)EditorGUILayout.EnumFlagsField("Random Orientation", brush.orientation);
  285. if (EditorGUI.EndChangeCheck())
  286. EditorUtility.SetDirty(brush);
  287. var so = serializedObject;
  288. EditorGUILayout.PropertyField(so.FindProperty(nameof(brush.randomTiles)), true);
  289. if (so.ApplyModifiedProperties())
  290. EditorUtility.SetDirty(brush);
  291. EditorGUILayout.PropertyField(so.FindProperty(nameof(brush.probabilities)), true);
  292. if (so.ApplyModifiedProperties())
  293. EditorUtility.SetDirty(brush);
  294. }
  295. }
  296. }
Add Comment
Please, Sign In to add comment