346 lines
9.4 KiB
C#
346 lines
9.4 KiB
C#
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<Texture> groundsToAvoid = new List<Texture>();
|
|
|
|
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<Terrain>();
|
|
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;
|
|
}
|
|
}
|