using System.Collections.Generic; using BitStrap; using EnvSpawn; using UnityEngine; [AddComponentMenu("Enviro Spawn/ Enviro Spawn C#")] public class EnviroSpawn_CS : MonoBehaviour { public bool updateDataOnSelect; public bool updateActivate = true; public float maxCreateHeight = 9999f; public float minCreateHeight = -999f; public Color gizmoColor = new Color(0f, 0f, 1f); public GameObject[] prefabs; public int population = 1; public Vector2 dimensions = new Vector2(2f, 2f); public Vector2 scaleVariation = new Vector2(0.5f, 1.5f); public Vector2 rotationVariation = new Vector2(0f, 360f); public Vector2 rotationVariationX = new Vector2(0f, 0f); public Vector2 rotationVariationZ = new Vector2(0f, 0f); public LayerMask ignoreMask = 0; public LayerMask avoidMask = 0; public List groundsToAvoid = new List(); public Vector2 offset = Vector2.zero; [HideInInspector] public GameObject[] instanceObjects; [HideInInspector] public Vector3[] raycastPositions; [HideInInspector] public Vector3[] raycastPositionsBeta; public Bitmask bitmask; public bool followNormalsOrientation = true; [HideInInspector] public bool fixedPositioning; [HideInInspector] public bool offsetInEachCell = true; [HideInInspector] public float fixedGridScale = 1f; [HideInInspector] public int scatterMode; [HideInInspector] public float[] xRotations; [HideInInspector] public float[] yRotations; [HideInInspector] public float[] zRotations; [HideInInspector] public float[] offsets; [HideInInspector] public bool cCheck; private void OnDrawGizmos() { Matrix4x4 matrix = Matrix4x4.TRS(base.transform.position, base.transform.rotation, base.transform.lossyScale); Gizmos.matrix = matrix; Gizmos.color = gizmoColor; Gizmos.DrawWireCube(Vector3.zero, new Vector3(dimensions.x * base.transform.localScale.x, 0.1f, dimensions.y * base.transform.localScale.z)); Gizmos.color = new Color(gizmoColor.r, gizmoColor.g, gizmoColor.b, gizmoColor.a * 0.1f); Gizmos.DrawCube(Vector3.zero, new Vector3(dimensions.x * base.transform.localScale.x, 0.1f, dimensions.y * base.transform.localScale.z)); } public void MassInstantiateNew() { EnviroSpawn_CS[] array = Object.FindObjectsOfType(typeof(EnviroSpawn_CS)) as EnviroSpawn_CS[]; for (uint num = 0u; num < array.Length; num++) { array[num].InstantiateNew(); array[num].UpdateData(); array[num].UpdateData(); } } [Button] public void InstantiateNew() { cCheck = false; Reset(); raycastPositions = new Vector3[population]; raycastPositionsBeta = new Vector3[population]; instanceObjects = new GameObject[population]; xRotations = new float[population]; yRotations = new float[population]; zRotations = new float[population]; offsets = new float[population]; bitmask = new Bitmask(population); GenerateRaycastPoints(); for (uint num = 0u; num < population; num++) { if (!instanceObjects[num] && prefabs.Length > 0) { int num2 = Random.Range(0, prefabs.Length); GameObject gameObject = null; if ((bool)prefabs[num2] && 0 == 0) { gameObject = Object.Instantiate(prefabs[num2], raycastPositionsBeta[num], Quaternion.identity); } if ((bool)gameObject) { xRotations[num] = Random.Range(rotationVariationX.x, rotationVariationX.y); yRotations[num] = Random.Range(rotationVariation.x, rotationVariation.y); zRotations[num] = Random.Range(rotationVariationZ.x, rotationVariationZ.y); offsets[num] = Random.Range(offset.x, offset.y); float num3 = Random.Range(scaleVariation.x, scaleVariation.y); gameObject.transform.localScale = new Vector3(num3, num3, num3); gameObject.transform.parent = base.transform; instanceObjects[num] = gameObject; } } } } public void UpdateData(bool onUpdate = false) { if (fixedPositioning && 0 == 0) { fixedPositioning = false; scatterMode = 1; } if (population < 0) { population = 0; } else { if (raycastPositions == null) { return; } if (raycastPositions.Length != population) { InstantiateNew(); return; } bitmask = new Bitmask(population); for (uint num = 0u; num < population; num++) { RaycastHit hit; if (!Raycast(out hit, (int)num) && scatterMode != 0) { raycastPositionsBeta[num] = base.transform.position + raycastPositions[num]; } else if (bitmask != null && bitmask.EvaluateAll()) { while (!Raycast(out hit, (int)num) || ((int)avoidMask & (1 << hit.transform.gameObject.layer)) == 1 << hit.transform.gameObject.layer) { raycastPositions[num] = GenerateRandomRaycast(); } } Quaternion quaternion = Quaternion.FromToRotation(Vector3.up, hit.normal); if (!followNormalsOrientation) { quaternion = Quaternion.identity; } if (instanceObjects.Length > 0 && (bool)instanceObjects[num]) { if (bitmask != null && (instanceObjects[num].activeSelf || updateActivate)) { instanceObjects[num].SetActive(bitmask.Evaluate(num)); } offsets[num] = Mathf.Clamp(offsets[num], offset.x, offset.y); instanceObjects[num].transform.position = raycastPositionsBeta[num] + hit.normal * offsets[num]; instanceObjects[num].transform.eulerAngles = new Vector3(quaternion.eulerAngles.x, quaternion.eulerAngles.y, quaternion.eulerAngles.z); instanceObjects[num].transform.Rotate(xRotations[num], yRotations[num], zRotations[num], Space.Self); float num2 = Mathf.Clamp(instanceObjects[num].transform.localScale.x, scaleVariation.x, scaleVariation.y); instanceObjects[num].transform.localScale = new Vector3(num2, num2, num2); } } } } public void DeleteInactive() { GameObject[] array = instanceObjects; foreach (GameObject gameObject in array) { if (!gameObject.activeSelf) { Object.DestroyImmediate(gameObject); } } } private bool Raycast(out RaycastHit hit, int r) { if (Physics.Raycast(base.transform.position + base.transform.right * raycastPositions[r].x + base.transform.up * raycastPositions[r].y + base.transform.forward * raycastPositions[r].z, Vector3.down, out hit, float.PositiveInfinity, ~(int)ignoreMask)) { raycastPositionsBeta[r] = hit.point; if (hit.point.y < minCreateHeight) { bitmask.Replace(r, 0); return false; } if (hit.point.y > maxCreateHeight) { bitmask.Replace(r, 0); return false; } if (!CheckTerrainType(hit)) { bitmask.Replace(r, 0); return false; } if (bitmask != null) { bitmask.Replace(r, 1); } return true; } if (bitmask != null) { bitmask.Replace(r, 0); } return false; } private Vector3 GenerateRandomRaycast() { Vector3 result = new Vector3(Random.Range((0f - dimensions.x) / 2f * base.transform.localScale.x, dimensions.x / 2f * base.transform.localScale.z), 0f, Random.Range((0f - dimensions.y) / 2f * base.transform.localScale.x, dimensions.y / 2f * base.transform.localScale.z)); return result; } private void GenerateRaycastPoints() { float x = dimensions.x; float y = dimensions.y; int num = 0; if (scatterMode == 0) { for (uint num2 = 0u; num2 < population; num2++) { raycastPositions[num2] = GenerateRandomRaycast(); } } if (scatterMode == 1) { float num3 = float.Parse(string.Empty + population); float num4 = num3 / float.Parse(string.Empty + x * y); cCheck = false; if (Mathf.Floor(num4) > 0f) { cCheck = true; } num = 0; for (uint num5 = 0u; (float)num5 < num4; num5++) { float num6 = fixedGridScale / num4 * (float)num5; for (uint num7 = 0u; (float)num7 < y; num7++) { for (uint num8 = 0u; (float)num8 < x; num8++) { if (num < raycastPositions.Length) { raycastPositions[num] = new Vector3((float)num8 * fixedGridScale - x / 2f + fixedGridScale / 2f, 0f, (float)num7 * fixedGridScale - y / 2f + fixedGridScale / 2f); } num++; } } } } if (scatterMode != 2) { return; } int num9 = (int)Mathf.Sqrt(float.Parse(string.Empty + population) * dimensions.x / dimensions.y); int num10 = (int)(float.Parse(string.Empty + population) / float.Parse(string.Empty + num9)); num = 0; for (uint num11 = 0u; num11 < num9; num11++) { for (uint num12 = 0u; num12 < num10; num12++) { raycastPositions[num] = new Vector3(dimensions.x / (float)num9 * (float)num11 - (dimensions.x / 2f - dimensions.x / (float)num9 / 2f), 0f, dimensions.y / (float)num10 * (float)num12 - (dimensions.y / 2f - dimensions.y / (float)num10 / 2f)); num++; } } } public void Reset() { if (instanceObjects == null) { return; } for (uint num = 0u; num < instanceObjects.Length; num++) { if (instanceObjects[num] != null) { Object.DestroyImmediate(instanceObjects[num].gameObject); } } raycastPositions = new Vector3[0]; raycastPositionsBeta = new Vector3[0]; instanceObjects = new GameObject[0]; } private bool CheckTerrainType(RaycastHit hit) { Terrain component = hit.collider.GetComponent(); Texture2D texture2D = null; if (component != null) { int mainTerrainTexture = vp_FootstepManager.GetMainTerrainTexture(hit.point, component); if (mainTerrainTexture <= component.terrainData.splatPrototypes.Length - 1) { texture2D = component.terrainData.splatPrototypes[mainTerrainTexture].texture; for (int i = 0; i < groundsToAvoid.Count; i++) { if (texture2D == groundsToAvoid[i]) { return false; } } } } return true; } }