Advertisement
Guest User

GeometryGrassPainter.cs

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