Guest User

GrassPainter.cs

a guest
Jul 16th, 2021
4,373
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.94 KB | None | 0 0
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4.  
  5. using UnityEditor;
  6.  
  7.  
  8.  
  9. [RequireComponent(typeof(MeshFilter))]
  10. [ExecuteInEditMode]
  11. public class GrassPainter : MonoBehaviour
  12. {
  13.  
  14. public Mesh mesh;
  15. MeshFilter filter;
  16.  
  17. public Color AdjustedColor;
  18.  
  19. [Range(1, 600000)]
  20. public int grassLimit = 50000;
  21.  
  22. private Vector3 lastPosition = Vector3.zero;
  23.  
  24. public int toolbarInt = 0;
  25.  
  26. public int toolbarIntEdit = 0;
  27.  
  28. [SerializeField]
  29. List<Vector3> positions = new List<Vector3>();
  30. [SerializeField]
  31. List<Color> colors = new List<Color>();
  32. [SerializeField]
  33. List<int> indicies = new List<int>();
  34. [SerializeField]
  35. List<Vector3> normals = new List<Vector3>();
  36. [SerializeField]
  37. List<Vector2> length = new List<Vector2>();
  38.  
  39. public int i = 0;
  40.  
  41. public float sizeWidth = 1f;
  42. public float sizeLength = 1f;
  43. public float density = 1f;
  44.  
  45.  
  46. public float normalLimit = 1;
  47.  
  48. public float rangeR, rangeG, rangeB;
  49. public LayerMask hitMask = 1;
  50. public LayerMask paintMask = 1;
  51. public float brushSize;
  52. public float brushFalloffSize;
  53.  
  54.  
  55. public float Flow;
  56.  
  57. private int flowTimer;
  58.  
  59. Vector3 mousePos;
  60.  
  61. [HideInInspector]
  62. public Vector3 hitPosGizmo;
  63.  
  64. Vector3 hitPos;
  65.  
  66. [HideInInspector]
  67. public Vector3 hitNormal;
  68.  
  69.  
  70. int[] indi;
  71.  
  72.  
  73. #if UNITY_EDITOR
  74. void OnFocus()
  75. {
  76. // Remove delegate listener if it has previously
  77. // been assigned.
  78. SceneView.duringSceneGui -= this.OnScene;
  79. // Add (or re-add) the delegate.
  80. SceneView.duringSceneGui += this.OnScene;
  81. }
  82.  
  83. void OnDestroy()
  84. {
  85. // When the window is destroyed, remove the delegate
  86. // so that it will no longer do any drawing.
  87. SceneView.duringSceneGui -= this.OnScene;
  88. }
  89.  
  90. private void OnEnable()
  91. {
  92. filter = GetComponent<MeshFilter>();
  93. SceneView.duringSceneGui += this.OnScene;
  94. }
  95.  
  96. public void ClearMesh()
  97. {
  98. i = 0;
  99. positions = new List<Vector3>();
  100. indicies = new List<int>();
  101. colors = new List<Color>();
  102. normals = new List<Vector3>();
  103. length = new List<Vector2>();
  104. }
  105.  
  106. void OnScene(SceneView scene)
  107. {
  108. // only allow painting while this object is selected
  109. if ((Selection.Contains(gameObject)))
  110. {
  111.  
  112. Event e = Event.current;
  113. RaycastHit terrainHit;
  114. mousePos = e.mousePosition;
  115. float ppp = EditorGUIUtility.pixelsPerPoint;
  116. mousePos.y = scene.camera.pixelHeight - mousePos.y * ppp;
  117. mousePos.x *= ppp;
  118.  
  119. // ray for gizmo(disc)
  120. Ray rayGizmo = scene.camera.ScreenPointToRay(mousePos);
  121. RaycastHit hitGizmo;
  122.  
  123. if (Physics.Raycast(rayGizmo, out hitGizmo, 200f, hitMask.value))
  124. {
  125. hitPosGizmo = hitGizmo.point;
  126. }
  127.  
  128. if (e.type == EventType.MouseDrag && e.button == 1 && toolbarInt == 0)
  129. {
  130. // place based on density
  131. for (int k = 0; k < density; k++)
  132. {
  133.  
  134. // brushrange
  135. float t = 2f * Mathf.PI * Random.Range(0f, brushSize);
  136. float u = Random.Range(0f, brushSize) + Random.Range(0f, brushSize);
  137. float r = (u > 1 ? 2 - u : u);
  138. Vector3 origin = Vector3.zero;
  139.  
  140. // place random in radius, except for first one
  141. if (k != 0)
  142. {
  143. origin.x += r * Mathf.Cos(t);
  144. origin.y += r * Mathf.Sin(t);
  145. }
  146. else
  147. {
  148. origin = Vector3.zero;
  149. }
  150.  
  151. // add random range to ray
  152. Ray ray = scene.camera.ScreenPointToRay(mousePos);
  153. ray.origin += origin;
  154.  
  155. // if the ray hits something thats on the layer mask, within the grass limit and within the y normal limit
  156. if (Physics.Raycast(ray, out terrainHit, 200f, hitMask.value) && i < grassLimit && terrainHit.normal.y <= (1 + normalLimit) && terrainHit.normal.y >= (1 - normalLimit))
  157. {
  158. if ((paintMask.value & (1 << terrainHit.transform.gameObject.layer)) > 0)
  159. {
  160. hitPos = terrainHit.point;
  161. hitNormal = terrainHit.normal;
  162. if (k != 0)
  163. {
  164. var grassPosition = hitPos;// + Vector3.Cross(origin, hitNormal);
  165. grassPosition -= this.transform.position;
  166.  
  167. positions.Add((grassPosition));
  168. indicies.Add(i);
  169. length.Add(new Vector2(sizeWidth, sizeLength));
  170. // add random color variations
  171. colors.Add(new Color(AdjustedColor.r + (Random.Range(0, 1.0f) * rangeR), AdjustedColor.g + (Random.Range(0, 1.0f) * rangeG), AdjustedColor.b + (Random.Range(0, 1.0f) * rangeB), 1));
  172.  
  173. //colors.Add(temp);
  174. normals.Add(terrainHit.normal);
  175. i++;
  176. }
  177. else
  178. {// to not place everything at once, check if the first placed point far enough away from the last placed first one
  179. if (Vector3.Distance(terrainHit.point, lastPosition) > brushSize)
  180. {
  181. var grassPosition = hitPos;
  182. grassPosition -= this.transform.position;
  183. positions.Add((grassPosition));
  184. indicies.Add(i);
  185. length.Add(new Vector2(sizeWidth, sizeLength));
  186. colors.Add(new Color(AdjustedColor.r + (Random.Range(0, 1.0f) * rangeR), AdjustedColor.g + (Random.Range(0, 1.0f) * rangeG), AdjustedColor.b + (Random.Range(0, 1.0f) * rangeB), 1));
  187. normals.Add(terrainHit.normal);
  188. i++;
  189.  
  190. if (origin == Vector3.zero)
  191. {
  192. lastPosition = hitPos;
  193. }
  194. }
  195. }
  196. }
  197.  
  198. }
  199.  
  200. }
  201. e.Use();
  202. }
  203. // removing mesh points
  204. if (e.type == EventType.MouseDrag && e.button == 1 && toolbarInt == 1)
  205. {
  206. Ray ray = scene.camera.ScreenPointToRay(mousePos);
  207.  
  208. if (Physics.Raycast(ray, out terrainHit, 200f, hitMask.value))
  209. {
  210. hitPos = terrainHit.point;
  211. hitPosGizmo = hitPos;
  212. hitNormal = terrainHit.normal;
  213. for (int j = 0; j < positions.Count; j++)
  214. {
  215. Vector3 pos = positions[j];
  216.  
  217. pos += this.transform.position;
  218. float dist = Vector3.Distance(terrainHit.point, pos);
  219.  
  220. // if its within the radius of the brush, remove all info
  221. if (dist <= brushSize)
  222. {
  223. positions.RemoveAt(j);
  224. colors.RemoveAt(j);
  225. normals.RemoveAt(j);
  226. length.RemoveAt(j);
  227. indicies.RemoveAt(j);
  228. i--;
  229. for (int i = 0; i < indicies.Count; i++)
  230. {
  231. indicies[i] = i;
  232. }
  233. }
  234. }
  235. }
  236. e.Use();
  237. }
  238. //edit
  239. if (e.type == EventType.MouseDrag && e.button == 1 && toolbarInt == 2)
  240. {
  241. Ray ray = scene.camera.ScreenPointToRay(mousePos);
  242.  
  243. if (Physics.Raycast(ray, out terrainHit, 200f, hitMask.value))
  244. {
  245. hitPos = terrainHit.point;
  246. hitPosGizmo = hitPos;
  247. hitNormal = terrainHit.normal;
  248. for (int j = 0; j < positions.Count; j++)
  249. {
  250. Vector3 pos = positions[j];
  251.  
  252. pos += this.transform.position;
  253. float dist = Vector3.Distance(terrainHit.point, pos);
  254.  
  255. // if its within the radius of the brush, remove all info
  256. if (dist <= brushSize)
  257. {
  258. brushFalloffSize = Mathf.Clamp(brushFalloffSize, 0, brushSize);
  259. float falloff = Mathf.Clamp01((dist - brushFalloffSize) / (brushSize - brushFalloffSize));
  260.  
  261. Color OrigColor = colors[j];
  262.  
  263. Color newCol = (new Color(AdjustedColor.r + (Random.Range(0, 1.0f) * rangeR), AdjustedColor.g + (Random.Range(0, 1.0f) * rangeG), AdjustedColor.b + (Random.Range(0, 1.0f) * rangeB), 1));
  264.  
  265. Vector2 origLength = length[j];
  266. Vector2 newLength = new Vector2(sizeWidth, sizeLength); ;
  267.  
  268. flowTimer++;
  269. if (flowTimer > Flow)
  270. {
  271. if (toolbarIntEdit == 0 || toolbarIntEdit == 2)
  272. {
  273. colors[j] = Color.Lerp(newCol, OrigColor, falloff);
  274. }
  275. if (toolbarIntEdit == 1 || toolbarIntEdit == 2)
  276. {
  277. length[j] = Vector2.Lerp(newLength, origLength, falloff);
  278. }
  279.  
  280. flowTimer = 0;
  281. }
  282.  
  283. }
  284. }
  285. }
  286. e.Use();
  287.  
  288. }
  289. // set all info to mesh
  290. mesh = new Mesh();
  291. mesh.SetVertices(positions);
  292. indi = indicies.ToArray();
  293. mesh.SetIndices(indi, MeshTopology.Points, 0);
  294. mesh.SetUVs(0, length);
  295. mesh.SetColors(colors);
  296. mesh.SetNormals(normals);
  297. filter.mesh = mesh;
  298.  
  299.  
  300. }
  301. }
  302. #endif
  303. }
  304.  
Advertisement
Add Comment
Please, Sign In to add comment