Files
2026-02-21 16:45:37 +08:00

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;
}
}