Files
UltimateFishing2020/Assets/Scripts/Assembly-CSharp/Gaia/Spawner.cs
2026-03-04 10:03:45 +08:00

2062 lines
61 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using Gaia.FullSerializer;
using UnityEngine;
namespace Gaia
{
[ExecuteInEditMode]
public class Spawner : MonoBehaviour
{
private class SpawnLocation
{
public Vector3 m_location;
public float m_seedDistance;
}
[fsIgnore]
public GaiaResource m_resources;
public string m_resourcesPath;
public string m_spawnerID = Guid.NewGuid().ToString();
public GaiaConstants.OperationMode m_mode;
public int m_seed = DateTime.Now.Millisecond;
public GaiaConstants.SpawnerShape m_spawnerShape;
public GaiaConstants.SpawnerRuleSelector m_spawnRuleSelector = GaiaConstants.SpawnerRuleSelector.WeightedFittest;
public GaiaConstants.SpawnerLocation m_spawnLocationAlgorithm;
public GaiaConstants.SpawnerLocationCheckType m_spawnLocationCheckType;
public float m_locationIncrement = 1f;
public float m_maxJitteredLocationOffsetPct = 0.9f;
public int m_locationChecksPerInt = 1;
public int m_maxRandomClusterSize = 50;
public float m_spawnRange = 500f;
public AnimationCurve m_spawnFitnessAttenuator = new AnimationCurve(new Keyframe(0f, 1f), new Keyframe(1f, 1f));
public GaiaConstants.ImageFitnessFilterMode m_areaMaskMode;
public bool m_enableColliderCacheAtRuntime;
public Texture2D m_imageMask;
public bool m_imageMaskInvert;
public bool m_imageMaskNormalise;
public bool m_imageMaskFlip;
public int m_imageMaskSmoothIterations = 3;
[fsIgnore]
public HeightMap m_imageMaskHM;
private FractalGenerator m_noiseGenerator;
public float m_noiseMaskSeed;
public int m_noiseMaskOctaves = 8;
public float m_noiseMaskPersistence = 0.25f;
public float m_noiseMaskFrequency = 1f;
public float m_noiseMaskLacunarity = 1.5f;
public float m_noiseZoom = 10f;
public bool m_noiseInvert;
public float m_spawnInterval = 5f;
public string m_triggerTags = "Player";
public float m_triggerRange = 130f;
public List<SpawnRule> m_spawnerRules = new List<SpawnRule>();
public LayerMask m_spawnCollisionLayers;
public int m_spawnColliderLayer;
public bool m_showGizmos = true;
public bool m_showDebug;
public bool m_showStatistics = true;
public bool m_showTerrainHelper = true;
public XorshiftPlus m_rndGenerator;
private bool m_cacheDetails;
private Dictionary<int, List<HeightMap>> m_detailMapCache = new Dictionary<int, List<HeightMap>>();
private bool m_cacheTextures;
private bool m_textureMapsDirty;
private Dictionary<int, List<HeightMap>> m_textureMapCache = new Dictionary<int, List<HeightMap>>();
private bool m_cacheTags;
private Dictionary<string, Quadtree<GameObject>> m_taggedGameObjectCache = new Dictionary<string, Quadtree<GameObject>>();
public TreeManager m_treeCache = new TreeManager();
private bool m_cacheHeightMaps;
private bool m_heightMapDirty;
private Dictionary<int, UnityHeightMap> m_heightMapCache = new Dictionary<int, UnityHeightMap>();
private Dictionary<string, HeightMap> m_stampCache = new Dictionary<string, HeightMap>();
[fsIgnore]
public GameObject m_areaBoundsColliderCache;
[fsIgnore]
public GameObject m_goColliderCache;
[fsIgnore]
public GameObject m_goParentGameObject;
private bool m_cancelSpawn;
public int m_totalRuleCnt;
public int m_activeRuleCnt;
public int m_inactiveRuleCnt;
public ulong m_maxInstanceCnt;
public ulong m_activeInstanceCnt;
public ulong m_inactiveInstanceCnt;
public ulong m_totalInstanceCnt;
private float m_terrainHeight;
private float m_checkDistance;
private RaycastHit m_checkHitInfo;
public IEnumerator m_updateCoroutine;
public float m_updateTimeAllowed = 1f / 30f;
public float m_spawnProgress;
public bool m_spawnComplete = true;
public Bounds m_spawnerBounds;
private bool m_isTextureSpawner;
private bool m_isDetailSpawner;
private bool m_isTreeSpawnwer;
private bool m_isGameObjectSpawner;
private void OnEnable()
{
if (m_spawnCollisionLayers.value == 0)
{
m_spawnCollisionLayers = TerrainHelper.GetActiveTerrainLayer();
}
m_spawnColliderLayer = TerrainHelper.GetActiveTerrainLayerAsInt();
if (m_rndGenerator == null)
{
m_rndGenerator = new XorshiftPlus(m_seed);
}
}
private void OnDisable()
{
}
public void StartEditorUpdates()
{
}
public void StopEditorUpdates()
{
}
private void EditorUpdate()
{
}
private void Start()
{
if (Application.isPlaying)
{
Transform transform = base.transform.Find("Bounds_ColliderCache");
if (transform != null)
{
m_areaBoundsColliderCache = transform.gameObject;
m_areaBoundsColliderCache.SetActive(value: false);
}
if (!m_enableColliderCacheAtRuntime)
{
transform = base.transform.Find("GameObject_ColliderCache");
if (transform != null)
{
m_goColliderCache = transform.gameObject;
m_goColliderCache.SetActive(value: false);
}
}
}
if (m_mode == GaiaConstants.OperationMode.RuntimeInterval || m_mode == GaiaConstants.OperationMode.RuntimeTriggeredInterval)
{
Initialise();
InvokeRepeating("RunSpawnerIteration", 1f, m_spawnInterval);
}
}
public void Initialise()
{
if (m_showDebug)
{
Debug.Log("Initialising spawner");
}
m_spawnColliderLayer = TerrainHelper.GetActiveTerrainLayerAsInt();
List<Transform> list = new List<Transform>();
foreach (Transform item in base.transform)
{
list.Add(item);
}
foreach (Transform item2 in list)
{
if (Application.isPlaying)
{
UnityEngine.Object.Destroy(item2.gameObject);
}
else
{
UnityEngine.Object.DestroyImmediate(item2.gameObject);
}
}
SetUpSpawnerTypeFlags();
if (IsGameObjectSpawner())
{
m_goParentGameObject = new GameObject("Spawned_GameObjects");
m_goParentGameObject.transform.parent = base.transform;
m_areaBoundsColliderCache = new GameObject("Bounds_ColliderCache");
m_areaBoundsColliderCache.transform.parent = base.transform;
m_goColliderCache = new GameObject("GameObject_ColliderCache");
m_goColliderCache.transform.parent = base.transform;
}
ResetRandomGenertor();
Terrain terrain = TerrainHelper.GetTerrain(base.transform.position);
if (terrain != null)
{
m_terrainHeight = terrain.terrainData.size.y;
}
m_spawnerBounds = new Bounds(base.transform.position, new Vector3(m_spawnRange * 2f, m_spawnRange * 2f, m_spawnRange * 2f));
foreach (SpawnRule spawnerRule in m_spawnerRules)
{
spawnerRule.m_currInstanceCnt = 0uL;
spawnerRule.m_activeInstanceCnt = 0uL;
spawnerRule.m_inactiveInstanceCnt = 0uL;
}
UpdateCounters();
}
private void PreSpawnInitialise()
{
m_spawnerBounds = new Bounds(base.transform.position, new Vector3(m_spawnRange * 2f, m_spawnRange * 2f, m_spawnRange * 2f));
if (m_rndGenerator == null)
{
ResetRandomGenertor();
}
m_spawnColliderLayer = TerrainHelper.GetActiveTerrainLayerAsInt();
SetUpSpawnerTypeFlags();
if (IsGameObjectSpawner())
{
if (base.transform.Find("Spawned_GameObjects") == null)
{
m_goParentGameObject = new GameObject("Spawned_GameObjects");
m_goParentGameObject.transform.parent = base.transform;
}
if (base.transform.Find("Bounds_ColliderCache") == null)
{
m_areaBoundsColliderCache = new GameObject("Bounds_ColliderCache");
m_areaBoundsColliderCache.transform.parent = base.transform;
}
if (base.transform.Find("GameObject_ColliderCache") == null)
{
m_goColliderCache = new GameObject("GameObject_ColliderCache");
m_goColliderCache.transform.parent = base.transform;
}
}
foreach (SpawnRule spawnerRule in m_spawnerRules)
{
spawnerRule.Initialise(this);
}
if (m_areaMaskMode == GaiaConstants.ImageFitnessFilterMode.PerlinNoise)
{
m_noiseGenerator = new FractalGenerator(m_noiseMaskFrequency, m_noiseMaskLacunarity, m_noiseMaskOctaves, m_noiseMaskPersistence, m_noiseMaskSeed, FractalGenerator.Fractals.Perlin);
}
else if (m_areaMaskMode == GaiaConstants.ImageFitnessFilterMode.BillowNoise)
{
m_noiseGenerator = new FractalGenerator(m_noiseMaskFrequency, m_noiseMaskLacunarity, m_noiseMaskOctaves, m_noiseMaskPersistence, m_noiseMaskSeed, FractalGenerator.Fractals.Billow);
}
else if (m_areaMaskMode == GaiaConstants.ImageFitnessFilterMode.RidgedNoise)
{
m_noiseGenerator = new FractalGenerator(m_noiseMaskFrequency, m_noiseMaskLacunarity, m_noiseMaskOctaves, m_noiseMaskPersistence, m_noiseMaskSeed, FractalGenerator.Fractals.RidgeMulti);
}
UpdateCounters();
}
public void SetUpSpawnerTypeFlags()
{
m_isDetailSpawner = false;
for (int i = 0; i < m_spawnerRules.Count; i++)
{
if (m_spawnerRules[i].m_resourceType == GaiaConstants.SpawnerResourceType.TerrainDetail)
{
m_isDetailSpawner = true;
break;
}
}
m_isTextureSpawner = false;
for (int j = 0; j < m_spawnerRules.Count; j++)
{
if (m_spawnerRules[j].m_resourceType == GaiaConstants.SpawnerResourceType.TerrainTexture)
{
m_isTextureSpawner = true;
break;
}
}
for (int k = 0; k < m_spawnerRules.Count; k++)
{
if (m_spawnerRules[k].m_resourceType == GaiaConstants.SpawnerResourceType.TerrainTree)
{
m_isTreeSpawnwer = true;
break;
}
}
m_isGameObjectSpawner = false;
for (int l = 0; l < m_spawnerRules.Count; l++)
{
if (m_spawnerRules[l].m_resourceType == GaiaConstants.SpawnerResourceType.GameObject)
{
m_isGameObjectSpawner = true;
break;
}
}
}
public void AssociateAssets()
{
if (m_resources != null)
{
m_resources.AssociateAssets();
}
else
{
Debug.LogWarning("Could not associated assets for " + base.name + " - resources file was missing");
}
}
public int[] GetMissingResources()
{
List<int> list = new List<int>();
for (int i = 0; i < m_spawnerRules.Count; i++)
{
if (m_spawnerRules[i].m_isActive && !m_spawnerRules[i].ResourceIsLoadedInTerrain(this))
{
list.Add(i);
}
}
return list.ToArray();
}
public void AddResourcesToTerrain(int[] rules)
{
for (int i = 0; i < rules.GetLength(0); i++)
{
if (!m_spawnerRules[rules[i]].ResourceIsLoadedInTerrain(this))
{
m_spawnerRules[rules[i]].AddResourceToTerrain(this);
}
}
}
private void PostSpawn()
{
m_spawnProgress = 0f;
m_spawnComplete = true;
m_updateCoroutine = null;
UpdateCounters();
}
public bool IsTextureSpawner()
{
return m_isTextureSpawner;
}
public bool IsDetailSpawner()
{
return m_isDetailSpawner;
}
public bool IsTreeSpawner()
{
return m_isTreeSpawnwer;
}
public bool IsGameObjectSpawner()
{
return m_isGameObjectSpawner;
}
public void ResetSpawner()
{
Initialise();
}
public void CancelSpawn()
{
m_cancelSpawn = true;
m_spawnProgress = 0f;
}
public bool IsSpawning()
{
return !m_spawnComplete;
}
private bool CanSpawnInstances()
{
bool result = false;
for (int i = 0; i < m_spawnerRules.Count; i++)
{
SpawnRule spawnRule = m_spawnerRules[i];
if (spawnRule.m_isActive)
{
if (spawnRule.m_ignoreMaxInstances)
{
return true;
}
if (spawnRule.m_activeInstanceCnt < spawnRule.m_maxInstances)
{
return true;
}
}
}
return result;
}
public void RunSpawnerIteration()
{
m_cancelSpawn = false;
m_spawnComplete = false;
PreSpawnInitialise();
if (m_activeRuleCnt <= 0)
{
if (m_showDebug)
{
Debug.Log($"{base.gameObject.name}: There are no active spawn rules. Can't spawn without rules.");
}
m_spawnComplete = true;
return;
}
if (!CanSpawnInstances())
{
if (m_showDebug)
{
Debug.Log($"{base.gameObject.name}: Can't spawn or activate new instance - max instance count reached.");
}
m_spawnComplete = true;
return;
}
Terrain terrain = TerrainHelper.GetTerrain(base.transform.position);
if (terrain != null)
{
m_terrainHeight = terrain.terrainData.size.y;
if (m_resources != null && m_resources.m_terrainHeight != m_terrainHeight)
{
Debug.LogWarning($"There is a mismatch between your resources Terrain Height {m_resources.m_terrainHeight} and your actual Terrain Height {m_terrainHeight}. Your Spawn may not work as intended!");
}
}
if (m_mode == GaiaConstants.OperationMode.RuntimeTriggeredInterval)
{
m_checkDistance = m_triggerRange + 1f;
List<GameObject> list = new List<GameObject>();
string[] array = new string[0];
if (!string.IsNullOrEmpty(m_triggerTags))
{
array = m_triggerTags.Split(',');
}
else
{
Debug.LogError("You have not supplied a trigger tag. Spawner will not spawn!");
}
int num = 0;
if (m_triggerTags.Length <= 0 || array.Length == 0)
{
if (m_showDebug)
{
Debug.Log($"{base.gameObject.name}: No triggers found");
}
m_spawnComplete = true;
return;
}
for (num = 0; num < array.Length; num++)
{
list.AddRange(GameObject.FindGameObjectsWithTag(array[num]));
}
for (num = 0; num < list.Count; num++)
{
m_checkDistance = Vector3.Distance(base.transform.position, list[num].transform.position);
if (m_checkDistance <= m_triggerRange)
{
break;
}
}
if (m_checkDistance > m_triggerRange)
{
if (m_showDebug)
{
Debug.Log($"{base.gameObject.name}: No triggers were close enough");
}
m_spawnComplete = true;
return;
}
}
if (!Application.isPlaying)
{
AddToSession(GaiaOperation.OperationType.Spawn, "Spawning " + base.transform.name);
}
if (m_spawnLocationAlgorithm == GaiaConstants.SpawnerLocation.RandomLocation || m_spawnLocationAlgorithm == GaiaConstants.SpawnerLocation.RandomLocationClustered)
{
StartCoroutine(RunRandomSpawnerIteration());
}
else
{
StartCoroutine(RunAreaSpawnerIteration());
}
}
public IEnumerator RunRandomSpawnerIteration()
{
if (m_showDebug)
{
Debug.Log($"{base.gameObject.name}: Running random iteration");
}
SpawnInfo spawnInfo = new SpawnInfo();
List<SpawnLocation> spawnLocations = new List<SpawnLocation>();
int spawnLocationsIdx = 0;
int failedSpawns = 0;
m_spawnProgress = 0f;
m_spawnComplete = false;
float currentTime = Time.realtimeSinceStartup;
float accumulatedTime = 0f;
spawnInfo.m_textureStrengths = new float[Terrain.activeTerrain.terrainData.alphamapLayers];
CreateSpawnCaches();
LoadImageMask();
for (int checks = 0; checks < m_locationChecksPerInt; checks++)
{
SpawnLocation spawnLocation = new SpawnLocation();
if (m_spawnLocationAlgorithm == GaiaConstants.SpawnerLocation.RandomLocation)
{
spawnLocation.m_location = GetRandomV3(m_spawnRange);
spawnLocation.m_location = base.transform.position + spawnLocation.m_location;
}
else if (spawnLocations.Count == 0 || spawnLocations.Count > m_maxRandomClusterSize || failedSpawns > m_maxRandomClusterSize)
{
spawnLocation.m_location = GetRandomV3(m_spawnRange);
spawnLocation.m_location = base.transform.position + spawnLocation.m_location;
failedSpawns = 0;
spawnLocationsIdx = 0;
spawnLocations.Clear();
}
else
{
if (spawnLocationsIdx >= spawnLocations.Count)
{
spawnLocationsIdx = 0;
}
spawnLocation.m_location = GetRandomV3(spawnLocations[spawnLocationsIdx].m_seedDistance);
spawnLocation.m_location = spawnLocations[spawnLocationsIdx++].m_location + spawnLocation.m_location;
}
if (CheckLocation(spawnLocation.m_location, ref spawnInfo))
{
if (m_spawnRuleSelector == GaiaConstants.SpawnerRuleSelector.All)
{
for (int i = 0; i < m_spawnerRules.Count; i++)
{
SpawnRule rule = m_spawnerRules[i];
spawnInfo.m_fitness = rule.GetFitness(ref spawnInfo);
if (TryExecuteRule(ref rule, ref spawnInfo))
{
failedSpawns = 0;
spawnLocation.m_seedDistance = rule.GetSeedThrowRange(ref spawnInfo);
spawnLocations.Add(spawnLocation);
}
else
{
failedSpawns++;
}
}
}
else if (m_spawnRuleSelector == GaiaConstants.SpawnerRuleSelector.Random)
{
SpawnRule rule = m_spawnerRules[GetRandomInt(0, m_spawnerRules.Count - 1)];
spawnInfo.m_fitness = rule.GetFitness(ref spawnInfo);
if (TryExecuteRule(ref rule, ref spawnInfo))
{
failedSpawns = 0;
spawnLocation.m_seedDistance = rule.GetSeedThrowRange(ref spawnInfo);
spawnLocations.Add(spawnLocation);
}
else
{
failedSpawns++;
}
}
else if (m_spawnRuleSelector == GaiaConstants.SpawnerRuleSelector.Fittest)
{
SpawnRule rule2 = null;
float num = 0f;
for (int i = 0; i < m_spawnerRules.Count; i++)
{
SpawnRule rule = m_spawnerRules[i];
float fitness = rule.GetFitness(ref spawnInfo);
if (fitness > num)
{
num = fitness;
rule2 = rule;
}
else if (GaiaUtils.Math_ApproximatelyEqual(fitness, num, 0.005f) && GetRandomFloat(0f, 1f) > 0.5f)
{
num = fitness;
rule2 = rule;
}
}
spawnInfo.m_fitness = num;
if (TryExecuteRule(ref rule2, ref spawnInfo))
{
failedSpawns = 0;
spawnLocation.m_seedDistance = rule2.GetSeedThrowRange(ref spawnInfo);
spawnLocations.Add(spawnLocation);
}
else
{
failedSpawns++;
}
}
else
{
SpawnRule rule3;
SpawnRule rule2 = (rule3 = null);
float fitness2;
float num = (fitness2 = 0f);
for (int i = 0; i < m_spawnerRules.Count; i++)
{
SpawnRule rule = m_spawnerRules[i];
float fitness = rule.GetFitness(ref spawnInfo);
if (GetRandomFloat(0f, 1f) < fitness)
{
rule3 = rule;
fitness2 = fitness;
}
if (fitness > num)
{
rule2 = rule;
num = fitness;
}
}
if (rule3 == null)
{
rule3 = rule2;
fitness2 = num;
}
if (rule3 != null)
{
spawnInfo.m_fitness = fitness2;
if (TryExecuteRule(ref rule3, ref spawnInfo))
{
failedSpawns = 0;
spawnLocation.m_seedDistance = rule3.GetSeedThrowRange(ref spawnInfo);
spawnLocations.Add(spawnLocation);
}
else
{
failedSpawns++;
}
}
}
}
m_spawnProgress = (float)checks / (float)m_locationChecksPerInt;
float realtimeSinceStartup = Time.realtimeSinceStartup;
float num2 = realtimeSinceStartup - currentTime;
currentTime = realtimeSinceStartup;
accumulatedTime += num2;
if (accumulatedTime > m_updateTimeAllowed)
{
accumulatedTime = 0f;
yield return null;
}
if (!CanSpawnInstances() || m_cancelSpawn)
{
break;
}
}
DeleteSpawnCaches();
PostSpawn();
}
public IEnumerator RunAreaSpawnerIteration()
{
if (m_showDebug)
{
Debug.Log($"{base.gameObject.name}: Running area iteration");
}
SpawnInfo spawnInfo = new SpawnInfo();
Vector3 locationWU = default(Vector3);
m_spawnProgress = 0f;
m_spawnComplete = false;
float currentTime = Time.realtimeSinceStartup;
float accumulatedTime = 0f;
CreateSpawnCaches();
LoadImageMask();
spawnInfo.m_textureStrengths = new float[Terrain.activeTerrain.terrainData.alphamapLayers];
float num = base.transform.position.x - m_spawnRange + m_locationIncrement / 2f;
float xWUMax = num + m_spawnRange * 2f;
float yMid = base.transform.position.y;
float zWUMin = base.transform.position.z - m_spawnRange + m_locationIncrement / 2f;
float zWUMax = zWUMin + m_spawnRange * 2f;
float jitMin = -1f * m_maxJitteredLocationOffsetPct * m_locationIncrement;
float jitMax = 1f * m_maxJitteredLocationOffsetPct * m_locationIncrement;
long currChecks = 0L;
long totalChecks = (long)((xWUMax - num) / m_locationIncrement * ((zWUMax - zWUMin) / m_locationIncrement));
for (float xWU = num; xWU < xWUMax; xWU += m_locationIncrement)
{
for (float zWU = zWUMin; zWU < zWUMax; zWU += m_locationIncrement)
{
currChecks++;
locationWU.x = xWU;
locationWU.y = yMid;
locationWU.z = zWU;
if (m_spawnLocationAlgorithm == GaiaConstants.SpawnerLocation.EveryLocationJittered)
{
locationWU.x += GetRandomFloat(jitMin, jitMax);
locationWU.z += GetRandomFloat(jitMin, jitMax);
}
if (CheckLocation(locationWU, ref spawnInfo))
{
if (m_spawnRuleSelector == GaiaConstants.SpawnerRuleSelector.All)
{
for (int i = 0; i < m_spawnerRules.Count; i++)
{
SpawnRule rule = m_spawnerRules[i];
spawnInfo.m_fitness = rule.GetFitness(ref spawnInfo);
TryExecuteRule(ref rule, ref spawnInfo);
}
}
else if (m_spawnRuleSelector == GaiaConstants.SpawnerRuleSelector.Random)
{
int i = GetRandomInt(0, m_spawnerRules.Count - 1);
SpawnRule rule = m_spawnerRules[i];
spawnInfo.m_fitness = rule.GetFitness(ref spawnInfo);
TryExecuteRule(ref rule, ref spawnInfo);
}
else if (m_spawnRuleSelector == GaiaConstants.SpawnerRuleSelector.Fittest)
{
SpawnRule rule2 = null;
float num2 = 0f;
for (int i = 0; i < m_spawnerRules.Count; i++)
{
SpawnRule rule = m_spawnerRules[i];
float fitness = rule.GetFitness(ref spawnInfo);
if (fitness > num2)
{
num2 = fitness;
rule2 = rule;
}
else if (GaiaUtils.Math_ApproximatelyEqual(fitness, num2, 0.005f) && GetRandomFloat(0f, 1f) > 0.5f)
{
num2 = fitness;
rule2 = rule;
}
}
spawnInfo.m_fitness = num2;
TryExecuteRule(ref rule2, ref spawnInfo);
}
else
{
SpawnRule rule3;
SpawnRule rule2 = (rule3 = null);
float fitness2;
float num2 = (fitness2 = 0f);
for (int i = 0; i < m_spawnerRules.Count; i++)
{
SpawnRule rule = m_spawnerRules[i];
float fitness = rule.GetFitness(ref spawnInfo);
if (GetRandomFloat(0f, 1f) < fitness)
{
rule3 = rule;
fitness2 = fitness;
}
if (fitness > num2)
{
rule2 = rule;
num2 = fitness;
}
}
if (rule3 == null)
{
rule3 = rule2;
fitness2 = num2;
}
if (rule3 != null)
{
spawnInfo.m_fitness = fitness2;
TryExecuteRule(ref rule3, ref spawnInfo);
}
}
if (m_textureMapsDirty)
{
List<HeightMap> textureMaps = spawnInfo.m_spawner.GetTextureMaps(spawnInfo.m_hitTerrain.GetInstanceID());
if (textureMaps != null)
{
for (int j = 0; j < spawnInfo.m_textureStrengths.Length; j++)
{
textureMaps[j][spawnInfo.m_hitLocationNU.z, spawnInfo.m_hitLocationNU.x] = spawnInfo.m_textureStrengths[j];
}
}
}
}
m_spawnProgress = (float)currChecks / (float)totalChecks;
float realtimeSinceStartup = Time.realtimeSinceStartup;
float num3 = realtimeSinceStartup - currentTime;
currentTime = realtimeSinceStartup;
accumulatedTime += num3;
if (accumulatedTime > m_updateTimeAllowed)
{
accumulatedTime = 0f;
yield return null;
}
if (!CanSpawnInstances() || m_cancelSpawn)
{
break;
}
}
}
DeleteSpawnCaches(flushDirty: true);
PostSpawn();
}
public void GroundToTerrain()
{
Terrain terrain = TerrainHelper.GetTerrain(base.transform.position);
if (terrain == null)
{
terrain = Terrain.activeTerrain;
}
if (terrain == null)
{
Debug.LogError("Could not fit to terrain - no terrain present");
return;
}
Bounds bounds = default(Bounds);
if (TerrainHelper.GetTerrainBounds(terrain, ref bounds))
{
base.transform.position = new Vector3(base.transform.position.x, terrain.transform.position.y, base.transform.position.z);
}
}
public void FitToTerrain()
{
Terrain terrain = TerrainHelper.GetTerrain(base.transform.position);
if (terrain == null)
{
terrain = Terrain.activeTerrain;
}
if (terrain == null)
{
Debug.LogError("Could not fit to terrain - no terrain present");
return;
}
Bounds bounds = default(Bounds);
if (TerrainHelper.GetTerrainBounds(terrain, ref bounds))
{
base.transform.position = new Vector3(bounds.center.x, terrain.transform.position.y, bounds.center.z);
m_spawnRange = bounds.extents.x;
}
}
public bool IsFitToTerrain()
{
Terrain terrain = TerrainHelper.GetTerrain(base.transform.position);
if (terrain == null)
{
terrain = Terrain.activeTerrain;
}
if (terrain == null)
{
Debug.LogError("Could not check if fit to terrain - no terrain present");
return false;
}
Bounds bounds = default(Bounds);
if (TerrainHelper.GetTerrainBounds(terrain, ref bounds))
{
if (bounds.center.x != base.transform.position.x || bounds.center.z != base.transform.position.z || bounds.extents.x != m_spawnRange)
{
return false;
}
return true;
}
return false;
}
public bool LoadImageMask()
{
m_imageMaskHM = null;
if (m_areaMaskMode == GaiaConstants.ImageFitnessFilterMode.None || m_areaMaskMode == GaiaConstants.ImageFitnessFilterMode.PerlinNoise)
{
return false;
}
if (m_areaMaskMode == GaiaConstants.ImageFitnessFilterMode.ImageRedChannel || m_areaMaskMode == GaiaConstants.ImageFitnessFilterMode.ImageGreenChannel || m_areaMaskMode == GaiaConstants.ImageFitnessFilterMode.ImageBlueChannel || m_areaMaskMode == GaiaConstants.ImageFitnessFilterMode.ImageAlphaChannel || m_areaMaskMode == GaiaConstants.ImageFitnessFilterMode.ImageGreyScale)
{
if (m_imageMask == null)
{
Debug.LogError("You requested an image mask but did not supply one. Please select mask texture.");
return false;
}
GaiaUtils.MakeTextureReadable(m_imageMask);
GaiaUtils.MakeTextureUncompressed(m_imageMask);
m_imageMaskHM = new HeightMap(m_imageMask.width, m_imageMask.height);
for (int i = 0; i < m_imageMaskHM.Width(); i++)
{
for (int j = 0; j < m_imageMaskHM.Depth(); j++)
{
switch (m_areaMaskMode)
{
case GaiaConstants.ImageFitnessFilterMode.ImageGreyScale:
m_imageMaskHM[i, j] = m_imageMask.GetPixel(i, j).grayscale;
break;
case GaiaConstants.ImageFitnessFilterMode.ImageRedChannel:
m_imageMaskHM[i, j] = m_imageMask.GetPixel(i, j).r;
break;
case GaiaConstants.ImageFitnessFilterMode.ImageGreenChannel:
m_imageMaskHM[i, j] = m_imageMask.GetPixel(i, j).g;
break;
case GaiaConstants.ImageFitnessFilterMode.ImageBlueChannel:
m_imageMaskHM[i, j] = m_imageMask.GetPixel(i, j).b;
break;
case GaiaConstants.ImageFitnessFilterMode.ImageAlphaChannel:
m_imageMaskHM[i, j] = m_imageMask.GetPixel(i, j).a;
break;
}
}
}
}
else
{
if (Terrain.activeTerrain == null)
{
Debug.LogError("You requested an terrain texture mask but there is no active terrain.");
return false;
}
Terrain activeTerrain = Terrain.activeTerrain;
GaiaSplatPrototype[] gaiaSplatPrototypes = GaiaSplatPrototype.GetGaiaSplatPrototypes(activeTerrain);
switch (m_areaMaskMode)
{
case GaiaConstants.ImageFitnessFilterMode.TerrainTexture0:
if (gaiaSplatPrototypes.Length < 1)
{
Debug.LogError("You requested an terrain texture mask 0 but there is no active texture in slot 0.");
return false;
}
m_imageMaskHM = new HeightMap(activeTerrain.terrainData.GetAlphamaps(0, 0, activeTerrain.terrainData.alphamapWidth, activeTerrain.terrainData.alphamapHeight), 0);
break;
case GaiaConstants.ImageFitnessFilterMode.TerrainTexture1:
if (gaiaSplatPrototypes.Length < 2)
{
Debug.LogError("You requested an terrain texture mask 1 but there is no active texture in slot 1.");
return false;
}
m_imageMaskHM = new HeightMap(activeTerrain.terrainData.GetAlphamaps(0, 0, activeTerrain.terrainData.alphamapWidth, activeTerrain.terrainData.alphamapHeight), 1);
break;
case GaiaConstants.ImageFitnessFilterMode.TerrainTexture2:
if (gaiaSplatPrototypes.Length < 3)
{
Debug.LogError("You requested an terrain texture mask 2 but there is no active texture in slot 2.");
return false;
}
m_imageMaskHM = new HeightMap(activeTerrain.terrainData.GetAlphamaps(0, 0, activeTerrain.terrainData.alphamapWidth, activeTerrain.terrainData.alphamapHeight), 2);
break;
case GaiaConstants.ImageFitnessFilterMode.TerrainTexture3:
if (gaiaSplatPrototypes.Length < 4)
{
Debug.LogError("You requested an terrain texture mask 3 but there is no active texture in slot 3.");
return false;
}
m_imageMaskHM = new HeightMap(activeTerrain.terrainData.GetAlphamaps(0, 0, activeTerrain.terrainData.alphamapWidth, activeTerrain.terrainData.alphamapHeight), 3);
break;
case GaiaConstants.ImageFitnessFilterMode.TerrainTexture4:
if (gaiaSplatPrototypes.Length < 5)
{
Debug.LogError("You requested an terrain texture mask 4 but there is no active texture in slot 4.");
return false;
}
m_imageMaskHM = new HeightMap(activeTerrain.terrainData.GetAlphamaps(0, 0, activeTerrain.terrainData.alphamapWidth, activeTerrain.terrainData.alphamapHeight), 4);
break;
case GaiaConstants.ImageFitnessFilterMode.TerrainTexture5:
if (gaiaSplatPrototypes.Length < 6)
{
Debug.LogError("You requested an terrain texture mask 5 but there is no active texture in slot 5.");
return false;
}
m_imageMaskHM = new HeightMap(activeTerrain.terrainData.GetAlphamaps(0, 0, activeTerrain.terrainData.alphamapWidth, activeTerrain.terrainData.alphamapHeight), 5);
break;
case GaiaConstants.ImageFitnessFilterMode.TerrainTexture6:
if (gaiaSplatPrototypes.Length < 7)
{
Debug.LogError("You requested an terrain texture mask 6 but there is no active texture in slot 6.");
return false;
}
m_imageMaskHM = new HeightMap(activeTerrain.terrainData.GetAlphamaps(0, 0, activeTerrain.terrainData.alphamapWidth, activeTerrain.terrainData.alphamapHeight), 6);
break;
case GaiaConstants.ImageFitnessFilterMode.TerrainTexture7:
if (gaiaSplatPrototypes.Length < 8)
{
Debug.LogError("You requested an terrain texture mask 7 but there is no active texture in slot 7.");
return false;
}
m_imageMaskHM = new HeightMap(activeTerrain.terrainData.GetAlphamaps(0, 0, activeTerrain.terrainData.alphamapWidth, activeTerrain.terrainData.alphamapHeight), 7);
break;
}
m_imageMaskHM.Flip();
}
if (m_imageMaskSmoothIterations > 0)
{
m_imageMaskHM.Smooth(m_imageMaskSmoothIterations);
}
if (m_imageMaskFlip)
{
m_imageMaskHM.Flip();
}
if (m_imageMaskNormalise)
{
m_imageMaskHM.Normalise();
}
if (m_imageMaskInvert)
{
m_imageMaskHM.Invert();
}
return true;
}
public void CreateSpawnCaches()
{
m_cacheTextures = false;
m_textureMapsDirty = false;
for (int i = 0; i < m_spawnerRules.Count; i++)
{
if (m_spawnerRules[i].CacheTextures(this))
{
CacheTextureMapsFromTerrain(Terrain.activeTerrain.GetInstanceID());
m_cacheTextures = true;
break;
}
}
m_cacheDetails = false;
for (int i = 0; i < m_spawnerRules.Count; i++)
{
if (m_spawnerRules[i].CacheDetails(this))
{
CacheDetailMapsFromTerrain(Terrain.activeTerrain.GetInstanceID());
m_cacheDetails = true;
break;
}
}
CacheTreesFromTerrain();
m_cacheTags = false;
List<string> tagList = new List<string>();
for (int i = 0; i < m_spawnerRules.Count; i++)
{
m_spawnerRules[i].AddProximityTags(this, ref tagList);
}
if (tagList.Count > 0)
{
CacheTaggedGameObjectsFromScene(tagList);
m_cacheTags = true;
}
m_cacheHeightMaps = false;
for (int i = 0; i < m_spawnerRules.Count; i++)
{
if (m_spawnerRules[i].CacheHeightMaps(this))
{
CacheHeightMapFromTerrain(Terrain.activeTerrain.GetInstanceID());
m_cacheHeightMaps = true;
break;
}
}
}
public void CreateSpawnCaches(GaiaConstants.SpawnerResourceType resourceType, int resourceIdx)
{
m_cacheTextures = false;
m_textureMapsDirty = false;
m_cacheDetails = false;
m_cacheTags = false;
switch (resourceType)
{
case GaiaConstants.SpawnerResourceType.TerrainTexture:
if (resourceIdx < m_resources.m_texturePrototypes.Length)
{
CacheTextureMapsFromTerrain(Terrain.activeTerrain.GetInstanceID());
m_cacheTextures = true;
List<string> tagList3 = new List<string>();
m_resources.m_texturePrototypes[resourceIdx].AddTags(ref tagList3);
if (tagList3.Count > 0)
{
CacheTaggedGameObjectsFromScene(tagList3);
m_cacheTags = true;
}
}
break;
case GaiaConstants.SpawnerResourceType.TerrainDetail:
if (resourceIdx < m_resources.m_detailPrototypes.Length)
{
CacheDetailMapsFromTerrain(Terrain.activeTerrain.GetInstanceID());
m_cacheDetails = true;
if (m_resources.m_detailPrototypes[resourceIdx].ChecksTextures())
{
CacheTextureMapsFromTerrain(Terrain.activeTerrain.GetInstanceID());
m_cacheTextures = true;
}
List<string> tagList2 = new List<string>();
m_resources.m_detailPrototypes[resourceIdx].AddTags(ref tagList2);
if (tagList2.Count > 0)
{
CacheTaggedGameObjectsFromScene(tagList2);
m_cacheTags = true;
}
}
break;
case GaiaConstants.SpawnerResourceType.TerrainTree:
if (resourceIdx < m_resources.m_treePrototypes.Length)
{
if (m_resources.m_treePrototypes[resourceIdx].ChecksTextures())
{
CacheTextureMapsFromTerrain(Terrain.activeTerrain.GetInstanceID());
m_cacheTextures = true;
}
CacheTreesFromTerrain();
List<string> tagList4 = new List<string>();
m_resources.m_treePrototypes[resourceIdx].AddTags(ref tagList4);
if (tagList4.Count > 0)
{
CacheTaggedGameObjectsFromScene(tagList4);
m_cacheTags = true;
}
}
break;
case GaiaConstants.SpawnerResourceType.GameObject:
if (resourceIdx < m_resources.m_gameObjectPrototypes.Length)
{
if (m_resources.m_gameObjectPrototypes[resourceIdx].ChecksTextures())
{
CacheTextureMapsFromTerrain(Terrain.activeTerrain.GetInstanceID());
m_cacheTextures = true;
}
List<string> tagList = new List<string>();
m_resources.m_gameObjectPrototypes[resourceIdx].AddTags(ref tagList);
if (tagList.Count > 0)
{
CacheTaggedGameObjectsFromScene(tagList);
m_cacheTags = true;
}
}
break;
}
}
public void DeleteSpawnCaches(bool flushDirty = false)
{
if (m_cacheTextures)
{
if (flushDirty && m_textureMapsDirty && !m_cancelSpawn)
{
m_textureMapsDirty = false;
SaveTextureMapsToTerrain(Terrain.activeTerrain.GetInstanceID());
}
DeleteTextureMapCache();
m_cacheTextures = false;
}
if (m_cacheDetails)
{
if (!m_cancelSpawn)
{
SaveDetailMapsToTerrain(Terrain.activeTerrain.GetInstanceID());
}
DeleteDetailMapCache();
m_cacheDetails = false;
}
if (m_cacheTags)
{
DeleteTagCache();
m_cacheTags = false;
}
if (m_cacheHeightMaps)
{
if (flushDirty && m_heightMapDirty && !m_cancelSpawn)
{
m_heightMapDirty = false;
SaveHeightMapToTerrain(Terrain.activeTerrain.GetInstanceID());
}
DeleteHeightMapCache();
m_cacheHeightMaps = false;
}
}
public bool TryExecuteRule(ref SpawnRule rule, ref SpawnInfo spawnInfo)
{
if (rule != null && (rule.m_ignoreMaxInstances || rule.m_activeInstanceCnt < rule.m_maxInstances))
{
spawnInfo.m_fitness *= m_spawnFitnessAttenuator.Evaluate(Mathf.Clamp01(spawnInfo.m_hitDistanceWU / m_spawnRange));
if (m_areaMaskMode != GaiaConstants.ImageFitnessFilterMode.None)
{
if (m_areaMaskMode == GaiaConstants.ImageFitnessFilterMode.PerlinNoise || m_areaMaskMode == GaiaConstants.ImageFitnessFilterMode.BillowNoise || m_areaMaskMode == GaiaConstants.ImageFitnessFilterMode.RidgedNoise)
{
if (!m_noiseInvert)
{
spawnInfo.m_fitness *= m_noiseGenerator.GetNormalisedValue(100000f + spawnInfo.m_hitLocationWU.x * (1f / m_noiseZoom), 100000f + spawnInfo.m_hitLocationWU.z * (1f / m_noiseZoom));
}
else
{
spawnInfo.m_fitness *= 1f - m_noiseGenerator.GetNormalisedValue(100000f + spawnInfo.m_hitLocationWU.x * (1f / m_noiseZoom), 100000f + spawnInfo.m_hitLocationWU.z * (1f / m_noiseZoom));
}
}
else if (m_imageMaskHM.HasData())
{
float x = (spawnInfo.m_hitLocationWU.x - (base.transform.position.x - m_spawnRange)) / (m_spawnRange * 2f);
float z = (spawnInfo.m_hitLocationWU.z - (base.transform.position.z - m_spawnRange)) / (m_spawnRange * 2f);
spawnInfo.m_fitness *= m_imageMaskHM[x, z];
}
}
if (spawnInfo.m_fitness > rule.m_minViableFitness && GetRandomFloat(0f, 1f) > rule.m_failureRate)
{
rule.Spawn(ref spawnInfo);
return true;
}
}
return false;
}
public bool CheckLocation(Vector3 locationWU, ref SpawnInfo spawnInfo)
{
spawnInfo.m_spawner = this;
spawnInfo.m_outOfBounds = true;
spawnInfo.m_wasVirginTerrain = false;
spawnInfo.m_spawnRotationY = 0f;
spawnInfo.m_hitDistanceWU = Vector3.Distance(base.transform.position, locationWU);
spawnInfo.m_hitLocationWU = locationWU;
spawnInfo.m_hitNormal = Vector3.zero;
spawnInfo.m_hitObject = null;
spawnInfo.m_hitTerrain = null;
spawnInfo.m_terrainNormalWU = Vector3.one;
spawnInfo.m_terrainHeightWU = 0f;
spawnInfo.m_terrainSlopeWU = 0f;
spawnInfo.m_areaHitSlopeWU = 0f;
spawnInfo.m_areaMinSlopeWU = 0f;
spawnInfo.m_areaAvgSlopeWU = 0f;
spawnInfo.m_areaMaxSlopeWU = 0f;
locationWU.y = m_terrainHeight + 1000f;
if (Physics.Raycast(locationWU, Vector3.down, out m_checkHitInfo, float.PositiveInfinity, m_spawnCollisionLayers))
{
if (spawnInfo.m_spawner.IsDetailSpawner() && (m_checkHitInfo.collider is SphereCollider || m_checkHitInfo.collider is CapsuleCollider) && m_checkHitInfo.collider.name == "_GaiaCollider_Grass")
{
locationWU.y = m_checkHitInfo.point.y - 0.01f;
if (!Physics.Raycast(locationWU, Vector3.down, out m_checkHitInfo, float.PositiveInfinity, m_spawnCollisionLayers))
{
return false;
}
}
spawnInfo.m_hitLocationWU = m_checkHitInfo.point;
spawnInfo.m_hitDistanceWU = Vector3.Distance(base.transform.position, spawnInfo.m_hitLocationWU);
spawnInfo.m_hitNormal = m_checkHitInfo.normal;
spawnInfo.m_hitObject = m_checkHitInfo.transform;
if (m_spawnerShape == GaiaConstants.SpawnerShape.Box)
{
if (!m_spawnerBounds.Contains(spawnInfo.m_hitLocationWU))
{
return false;
}
}
else if (spawnInfo.m_hitDistanceWU > m_spawnRange)
{
return false;
}
spawnInfo.m_outOfBounds = false;
Terrain terrain;
if (m_checkHitInfo.collider is TerrainCollider)
{
terrain = m_checkHitInfo.transform.GetComponent<Terrain>();
spawnInfo.m_wasVirginTerrain = true;
}
else
{
terrain = TerrainHelper.GetTerrain(m_checkHitInfo.point);
}
if (terrain != null)
{
spawnInfo.m_hitTerrain = terrain;
spawnInfo.m_terrainHeightWU = terrain.SampleHeight(m_checkHitInfo.point);
Vector3 vector = terrain.transform.InverseTransformPoint(m_checkHitInfo.point);
Vector3 hitLocationNU = new Vector3(Mathf.InverseLerp(0f, terrain.terrainData.size.x, vector.x), Mathf.InverseLerp(0f, terrain.terrainData.size.y, vector.y), Mathf.InverseLerp(0f, terrain.terrainData.size.z, vector.z));
spawnInfo.m_hitLocationNU = hitLocationNU;
spawnInfo.m_terrainSlopeWU = terrain.terrainData.GetSteepness(hitLocationNU.x, hitLocationNU.z);
spawnInfo.m_areaHitSlopeWU = (spawnInfo.m_areaMinSlopeWU = (spawnInfo.m_areaAvgSlopeWU = (spawnInfo.m_areaMaxSlopeWU = spawnInfo.m_terrainSlopeWU)));
spawnInfo.m_terrainNormalWU = terrain.terrainData.GetInterpolatedNormal(hitLocationNU.x, hitLocationNU.z);
if (spawnInfo.m_wasVirginTerrain && spawnInfo.m_spawner.m_treeCache.Count(spawnInfo.m_hitLocationWU, 0.5f) > 0)
{
spawnInfo.m_wasVirginTerrain = false;
}
if (m_textureMapCache != null && m_textureMapCache.Count > 0)
{
List<HeightMap> list = m_textureMapCache[terrain.GetInstanceID()];
for (int i = 0; i < spawnInfo.m_textureStrengths.Length; i++)
{
spawnInfo.m_textureStrengths[i] = list[i][hitLocationNU.z, hitLocationNU.x];
}
}
else
{
float[,,] alphamaps = terrain.terrainData.GetAlphamaps((int)(hitLocationNU.x * (float)(terrain.terrainData.alphamapWidth - 1)), (int)(hitLocationNU.z * (float)(terrain.terrainData.alphamapHeight - 1)), 1, 1);
for (int j = 0; j < spawnInfo.m_textureStrengths.Length; j++)
{
spawnInfo.m_textureStrengths[j] = alphamaps[0, 0, j];
}
}
}
return true;
}
return false;
}
public bool CheckLocationBounds(ref SpawnInfo spawnInfo, float distance)
{
spawnInfo.m_areaHitSlopeWU = (spawnInfo.m_areaMinSlopeWU = (spawnInfo.m_areaAvgSlopeWU = (spawnInfo.m_areaMaxSlopeWU = spawnInfo.m_terrainSlopeWU)));
if (spawnInfo.m_areaHitsWU == null)
{
spawnInfo.m_areaHitsWU = new Vector3[4];
}
spawnInfo.m_areaHitsWU[0] = new Vector3(spawnInfo.m_hitLocationWU.x + distance, spawnInfo.m_hitLocationWU.y + 3000f, spawnInfo.m_hitLocationWU.z);
spawnInfo.m_areaHitsWU[1] = new Vector3(spawnInfo.m_hitLocationWU.x - distance, spawnInfo.m_hitLocationWU.y + 3000f, spawnInfo.m_hitLocationWU.z);
spawnInfo.m_areaHitsWU[2] = new Vector3(spawnInfo.m_hitLocationWU.x, spawnInfo.m_hitLocationWU.y + 3000f, spawnInfo.m_hitLocationWU.z + distance);
spawnInfo.m_areaHitsWU[3] = new Vector3(spawnInfo.m_hitLocationWU.x, spawnInfo.m_hitLocationWU.y + 3000f, spawnInfo.m_hitLocationWU.z - distance);
if (!Physics.BoxCast(halfExtents: new Vector3(distance, 0.1f, distance), center: new Vector3(spawnInfo.m_hitLocationWU.x, spawnInfo.m_hitLocationWU.y + 3000f, spawnInfo.m_hitLocationWU.z), direction: Vector3.down, hitInfo: out var hitInfo, orientation: Quaternion.identity, maxDistance: float.PositiveInfinity, layerMask: m_spawnCollisionLayers))
{
return false;
}
if (spawnInfo.m_wasVirginTerrain)
{
if (hitInfo.collider is TerrainCollider)
{
if (spawnInfo.m_spawner.m_treeCache.Count(hitInfo.point, 0.5f) > 0)
{
spawnInfo.m_wasVirginTerrain = false;
}
}
else
{
spawnInfo.m_wasVirginTerrain = false;
}
}
if (!Physics.Raycast(spawnInfo.m_areaHitsWU[0], Vector3.down, out hitInfo, float.PositiveInfinity, m_spawnCollisionLayers))
{
return false;
}
spawnInfo.m_areaHitsWU[0] = hitInfo.point;
Terrain terrain = hitInfo.transform.GetComponent<Terrain>();
if (terrain == null)
{
terrain = TerrainHelper.GetTerrain(hitInfo.point);
}
Vector3 zero = Vector3.zero;
Vector3 zero2 = Vector3.zero;
float num = 0f;
if (terrain != null)
{
zero = terrain.transform.InverseTransformPoint(hitInfo.point);
zero2 = new Vector3(Mathf.InverseLerp(0f, terrain.terrainData.size.x, zero.x), Mathf.InverseLerp(0f, terrain.terrainData.size.y, zero.y), Mathf.InverseLerp(0f, terrain.terrainData.size.z, zero.z));
num = terrain.terrainData.GetSteepness(zero2.x, zero2.z);
spawnInfo.m_areaAvgSlopeWU += num;
if (num > spawnInfo.m_areaMaxSlopeWU)
{
spawnInfo.m_areaMaxSlopeWU = num;
}
if (num < spawnInfo.m_areaMinSlopeWU)
{
spawnInfo.m_areaMinSlopeWU = num;
}
if (spawnInfo.m_wasVirginTerrain)
{
if (hitInfo.collider is TerrainCollider)
{
if (spawnInfo.m_spawner.m_treeCache.Count(hitInfo.point, 0.5f) > 0)
{
spawnInfo.m_wasVirginTerrain = false;
}
}
else
{
spawnInfo.m_wasVirginTerrain = false;
}
}
}
if (!Physics.Raycast(spawnInfo.m_areaHitsWU[1], Vector3.down, out hitInfo, float.PositiveInfinity, m_spawnCollisionLayers))
{
return false;
}
spawnInfo.m_areaHitsWU[1] = hitInfo.point;
terrain = hitInfo.transform.GetComponent<Terrain>();
if (terrain == null)
{
terrain = TerrainHelper.GetTerrain(hitInfo.point);
}
if (terrain != null)
{
zero = terrain.transform.InverseTransformPoint(hitInfo.point);
zero2 = new Vector3(Mathf.InverseLerp(0f, terrain.terrainData.size.x, zero.x), Mathf.InverseLerp(0f, terrain.terrainData.size.y, zero.y), Mathf.InverseLerp(0f, terrain.terrainData.size.z, zero.z));
num = terrain.terrainData.GetSteepness(zero2.x, zero2.z);
spawnInfo.m_areaAvgSlopeWU += num;
if (num > spawnInfo.m_areaMaxSlopeWU)
{
spawnInfo.m_areaMaxSlopeWU = num;
}
if (num < spawnInfo.m_areaMinSlopeWU)
{
spawnInfo.m_areaMinSlopeWU = num;
}
if (spawnInfo.m_wasVirginTerrain)
{
if (hitInfo.collider is TerrainCollider)
{
if (spawnInfo.m_spawner.m_treeCache.Count(hitInfo.point, 0.5f) > 0)
{
spawnInfo.m_wasVirginTerrain = false;
}
}
else
{
spawnInfo.m_wasVirginTerrain = false;
}
}
}
if (!Physics.Raycast(spawnInfo.m_areaHitsWU[2], Vector3.down, out hitInfo, float.PositiveInfinity, m_spawnCollisionLayers))
{
return false;
}
spawnInfo.m_areaHitsWU[2] = hitInfo.point;
terrain = hitInfo.transform.GetComponent<Terrain>();
if (terrain == null)
{
terrain = TerrainHelper.GetTerrain(hitInfo.point);
}
if (terrain != null)
{
zero = terrain.transform.InverseTransformPoint(hitInfo.point);
zero2 = new Vector3(Mathf.InverseLerp(0f, terrain.terrainData.size.x, zero.x), Mathf.InverseLerp(0f, terrain.terrainData.size.y, zero.y), Mathf.InverseLerp(0f, terrain.terrainData.size.z, zero.z));
num = terrain.terrainData.GetSteepness(zero2.x, zero2.z);
spawnInfo.m_areaAvgSlopeWU += num;
if (num > spawnInfo.m_areaMaxSlopeWU)
{
spawnInfo.m_areaMaxSlopeWU = num;
}
if (num < spawnInfo.m_areaMinSlopeWU)
{
spawnInfo.m_areaMinSlopeWU = num;
}
if (spawnInfo.m_wasVirginTerrain)
{
if (hitInfo.collider is TerrainCollider)
{
if (spawnInfo.m_spawner.m_treeCache.Count(hitInfo.point, 0.5f) > 0)
{
spawnInfo.m_wasVirginTerrain = false;
}
}
else
{
spawnInfo.m_wasVirginTerrain = false;
}
}
}
if (!Physics.Raycast(spawnInfo.m_areaHitsWU[3], Vector3.down, out hitInfo, float.PositiveInfinity, m_spawnCollisionLayers))
{
return false;
}
spawnInfo.m_areaHitsWU[3] = hitInfo.point;
terrain = hitInfo.transform.GetComponent<Terrain>();
if (terrain == null)
{
terrain = TerrainHelper.GetTerrain(hitInfo.point);
}
if (terrain != null)
{
zero = terrain.transform.InverseTransformPoint(hitInfo.point);
zero2 = new Vector3(Mathf.InverseLerp(0f, terrain.terrainData.size.x, zero.x), Mathf.InverseLerp(0f, terrain.terrainData.size.y, zero.y), Mathf.InverseLerp(0f, terrain.terrainData.size.z, zero.z));
num = terrain.terrainData.GetSteepness(zero2.x, zero2.z);
spawnInfo.m_areaAvgSlopeWU += num;
if (num > spawnInfo.m_areaMaxSlopeWU)
{
spawnInfo.m_areaMaxSlopeWU = num;
}
if (num < spawnInfo.m_areaMinSlopeWU)
{
spawnInfo.m_areaMinSlopeWU = num;
}
if (spawnInfo.m_wasVirginTerrain)
{
if (hitInfo.collider is TerrainCollider)
{
if (spawnInfo.m_spawner.m_treeCache.Count(hitInfo.point, 0.5f) > 0)
{
spawnInfo.m_wasVirginTerrain = false;
}
}
else
{
spawnInfo.m_wasVirginTerrain = false;
}
}
}
spawnInfo.m_areaAvgSlopeWU /= 5f;
float num2 = spawnInfo.m_areaHitsWU[0].y - spawnInfo.m_areaHitsWU[1].y;
float num3 = spawnInfo.m_areaHitsWU[2].y - spawnInfo.m_areaHitsWU[3].y;
spawnInfo.m_areaHitSlopeWU = GaiaUtils.Math_Clamp(0f, 90f, (float)Math.Sqrt(num2 * num2 + num3 * num3));
return true;
}
public void UpdateCounters()
{
m_totalRuleCnt = 0;
m_activeRuleCnt = 0;
m_inactiveRuleCnt = 0;
m_maxInstanceCnt = 0uL;
m_activeInstanceCnt = 0uL;
m_inactiveInstanceCnt = 0uL;
m_totalInstanceCnt = 0uL;
foreach (SpawnRule spawnerRule in m_spawnerRules)
{
m_totalRuleCnt++;
if (spawnerRule.m_isActive)
{
m_activeRuleCnt++;
m_maxInstanceCnt += spawnerRule.m_maxInstances;
m_activeInstanceCnt += spawnerRule.m_activeInstanceCnt;
m_inactiveInstanceCnt += spawnerRule.m_inactiveInstanceCnt;
m_totalInstanceCnt += spawnerRule.m_activeInstanceCnt + spawnerRule.m_inactiveInstanceCnt;
}
else
{
m_inactiveRuleCnt++;
}
}
}
private void OnDrawGizmosSelected()
{
if (m_showGizmos)
{
if (m_spawnerShape == GaiaConstants.SpawnerShape.Sphere)
{
if (m_mode == GaiaConstants.OperationMode.RuntimeTriggeredInterval)
{
Gizmos.color = Color.yellow;
Gizmos.DrawWireSphere(base.transform.position, m_triggerRange);
}
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(base.transform.position, m_spawnRange);
}
else
{
if (m_mode == GaiaConstants.OperationMode.RuntimeTriggeredInterval)
{
Gizmos.color = Color.yellow;
Gizmos.DrawWireCube(base.transform.position, new Vector3(m_triggerRange * 2f, m_triggerRange * 2f, m_triggerRange * 2f));
}
Gizmos.color = Color.red;
Gizmos.DrawWireCube(base.transform.position, new Vector3(m_spawnRange * 2f, m_spawnRange * 2f, m_spawnRange * 2f));
}
if (m_resources != null)
{
Bounds bounds = default(Bounds);
if (TerrainHelper.GetTerrainBounds(base.transform.position, ref bounds))
{
bounds.center = new Vector3(bounds.center.x, m_resources.m_seaLevel, bounds.center.z);
bounds.size = new Vector3(bounds.size.x, 0.05f, bounds.size.z);
Gizmos.color = new Color(Color.blue.r, Color.blue.g, Color.blue.b, Color.blue.a / 4f);
Gizmos.DrawCube(bounds.center, bounds.size);
}
}
}
UpdateCounters();
}
public void CacheTextureMapsFromTerrain(int terrainID)
{
if (m_textureMapCache == null)
{
m_textureMapCache = new Dictionary<int, List<HeightMap>>();
}
for (int i = 0; i < Terrain.activeTerrains.Length; i++)
{
Terrain terrain = Terrain.activeTerrains[i];
if (terrain.GetInstanceID() == terrainID)
{
float[,,] alphamaps = terrain.terrainData.GetAlphamaps(0, 0, terrain.terrainData.alphamapWidth, terrain.terrainData.alphamapHeight);
List<HeightMap> list = new List<HeightMap>();
for (int j = 0; j < terrain.terrainData.alphamapLayers; j++)
{
HeightMap item = new HeightMap(alphamaps, j);
list.Add(item);
}
m_textureMapCache[terrainID] = list;
return;
}
}
Debug.LogError("Attempted to get textures on terrain that does not exist!");
}
public List<HeightMap> GetTextureMaps(int terrainID)
{
if (!m_textureMapCache.TryGetValue(terrainID, out var value))
{
return null;
}
return value;
}
public void SaveTextureMapsToTerrain(int terrainID)
{
if (!m_textureMapCache.TryGetValue(terrainID, out var value))
{
Debug.LogError("Texture map list was not found for terrain ID : " + terrainID + " !");
return;
}
if (value.Count <= 0)
{
Debug.LogError("Texture map list was empty for terrain ID : " + terrainID + " !");
return;
}
for (int i = 0; i < Terrain.activeTerrains.Length; i++)
{
Terrain terrain = Terrain.activeTerrains[i];
if (terrain.GetInstanceID() != terrainID)
{
continue;
}
if (value.Count != terrain.terrainData.alphamapLayers)
{
Debug.LogError("Texture map prototype list does not match terrain prototype list for terrain ID : " + terrainID + " !");
return;
}
float[,,] array = new float[terrain.terrainData.alphamapWidth, terrain.terrainData.alphamapHeight, terrain.terrainData.alphamapLayers];
for (int j = 0; j < terrain.terrainData.alphamapLayers; j++)
{
HeightMap heightMap = value[j];
for (int k = 0; k < heightMap.Width(); k++)
{
for (int l = 0; l < heightMap.Depth(); l++)
{
array[k, l, j] = heightMap[k, l];
}
}
}
terrain.terrainData.SetAlphamaps(0, 0, array);
return;
}
Debug.LogError("Attempted to locate a terrain that does not exist!");
}
public void DeleteTextureMapCache()
{
m_textureMapCache = new Dictionary<int, List<HeightMap>>();
}
public void SetTextureMapsDirty()
{
m_textureMapsDirty = true;
}
public void CacheDetailMapsFromTerrain(int terrainID)
{
if (m_detailMapCache == null)
{
m_detailMapCache = new Dictionary<int, List<HeightMap>>();
}
for (int i = 0; i < Terrain.activeTerrains.Length; i++)
{
Terrain terrain = Terrain.activeTerrains[i];
if (terrain.GetInstanceID() == terrainID)
{
List<HeightMap> list = new List<HeightMap>();
for (int j = 0; j < terrain.terrainData.detailPrototypes.Length; j++)
{
HeightMap item = new HeightMap(terrain.terrainData.GetDetailLayer(0, 0, terrain.terrainData.detailWidth, terrain.terrainData.detailHeight, j));
list.Add(item);
}
m_detailMapCache[terrainID] = list;
return;
}
}
Debug.LogError("Attempted to get details on terrain that does not exist!");
}
public void SaveDetailMapsToTerrain(int terrainID)
{
if (!m_detailMapCache.TryGetValue(terrainID, out var value))
{
Debug.LogWarning(base.gameObject.name + "Detail map list was not found for terrain ID : " + terrainID + " !");
return;
}
if (value.Count <= 0)
{
Debug.LogWarning(base.gameObject.name + ": Detail map list was empty for terrain ID : " + terrainID + " !");
return;
}
for (int i = 0; i < Terrain.activeTerrains.Length; i++)
{
Terrain terrain = Terrain.activeTerrains[i];
if (terrain.GetInstanceID() != terrainID)
{
continue;
}
if (value.Count != terrain.terrainData.detailPrototypes.Length)
{
Debug.LogError("Detail map protoype list does not match terrain prototype list for terrain ID : " + terrainID + " !");
return;
}
int[,] array = new int[value[0].Width(), value[0].Depth()];
for (int j = 0; j < terrain.terrainData.detailPrototypes.Length; j++)
{
HeightMap heightMap = value[j];
for (int k = 0; k < heightMap.Width(); k++)
{
for (int l = 0; l < heightMap.Depth(); l++)
{
array[k, l] = (int)heightMap[k, l];
}
}
terrain.terrainData.SetDetailLayer(0, 0, j, array);
}
terrain.Flush();
return;
}
Debug.LogError("Attempted to locate a terrain that does not exist!");
}
public List<HeightMap> GetDetailMaps(int terrainID)
{
if (!m_detailMapCache.TryGetValue(terrainID, out var value))
{
return null;
}
return value;
}
public HeightMap GetDetailMap(int terrainID, int detailIndex)
{
if (!m_detailMapCache.TryGetValue(terrainID, out var value))
{
return null;
}
if (detailIndex >= 0 && detailIndex < value.Count)
{
return value[detailIndex];
}
return null;
}
public void DeleteDetailMapCache()
{
m_detailMapCache = new Dictionary<int, List<HeightMap>>();
}
public void CacheTreesFromTerrain()
{
m_treeCache.LoadTreesFromTerrain();
}
public void DeleteTreeCache()
{
m_treeCache = new TreeManager();
}
public void AddToSession(GaiaOperation.OperationType opType, string opName)
{
GaiaSessionManager sessionManager = GaiaSessionManager.GetSessionManager();
if (sessionManager != null && !sessionManager.IsLocked())
{
GaiaOperation gaiaOperation = new GaiaOperation();
gaiaOperation.m_description = opName;
gaiaOperation.m_generatedByID = m_spawnerID;
gaiaOperation.m_generatedByName = base.transform.name;
gaiaOperation.m_generatedByType = GetType().ToString();
gaiaOperation.m_isActive = true;
gaiaOperation.m_operationDateTime = DateTime.Now.ToString();
gaiaOperation.m_operationType = opType;
gaiaOperation.m_operationDataJson = new string[1];
gaiaOperation.m_operationDataJson[0] = SerialiseJson();
sessionManager.AddOperation(gaiaOperation);
sessionManager.AddResource(m_resources);
}
}
public string SerialiseJson()
{
new fsSerializer().TrySerialize(this, out var data);
return fsJsonPrinter.CompressedJson(data);
}
public void DeSerialiseJson(string json)
{
fsData data = fsJsonParser.Parse(json);
fsSerializer obj = new fsSerializer();
Spawner instance = this;
obj.TryDeserialize(data, ref instance);
instance.m_resources = GaiaUtils.GetAsset(m_resourcesPath, typeof(GaiaResource)) as GaiaResource;
}
public void FlattenTerrain()
{
AddToSession(GaiaOperation.OperationType.FlattenTerrain, "Flattening terrain");
new GaiaWorldManager(Terrain.activeTerrains).FlattenWorld();
}
public void SmoothTerrain()
{
AddToSession(GaiaOperation.OperationType.SmoothTerrain, "Smoothing terrain");
new GaiaWorldManager(Terrain.activeTerrains).SmoothWorld();
}
public void ClearTrees()
{
AddToSession(GaiaOperation.OperationType.ClearTrees, "Clearing terrain trees");
TerrainHelper.ClearTrees();
}
public void ClearDetails()
{
AddToSession(GaiaOperation.OperationType.ClearDetails, "Clearing terrain details");
TerrainHelper.ClearDetails();
}
public void CacheHeightMapFromTerrain(int terrainID)
{
if (m_heightMapCache == null)
{
m_heightMapCache = new Dictionary<int, UnityHeightMap>();
}
for (int i = 0; i < Terrain.activeTerrains.Length; i++)
{
Terrain terrain = Terrain.activeTerrains[i];
if (terrain.GetInstanceID() == terrainID)
{
m_heightMapCache[terrainID] = new UnityHeightMap(terrain);
return;
}
}
Debug.LogError("Attempted to get height maps on a terrain that does not exist!");
}
public UnityHeightMap GetHeightMap(int terrainID)
{
if (!m_heightMapCache.TryGetValue(terrainID, out var value))
{
return null;
}
return value;
}
public void SaveHeightMapToTerrain(int terrainID)
{
if (!m_heightMapCache.TryGetValue(terrainID, out var value))
{
Debug.LogError("Heightmap was not found for terrain ID : " + terrainID + " !");
return;
}
for (int i = 0; i < Terrain.activeTerrains.Length; i++)
{
Terrain terrain = Terrain.activeTerrains[i];
if (terrain.GetInstanceID() == terrainID)
{
value.SaveToTerrain(terrain);
return;
}
}
Debug.LogError("Attempted to locate a terrain that does not exist!");
}
public void DeleteHeightMapCache()
{
m_heightMapCache = new Dictionary<int, UnityHeightMap>();
}
public void SetHeightMapsDirty()
{
m_heightMapDirty = true;
}
public void CacheStamps(List<string> stampList)
{
if (m_stampCache == null)
{
m_stampCache = new Dictionary<string, HeightMap>();
}
for (int i = 0; i < stampList.Count; i++)
{
}
}
private void CacheTaggedGameObjectsFromScene(List<string> tagList)
{
m_taggedGameObjectCache = new Dictionary<string, Quadtree<GameObject>>();
Rect boundaries = new Rect(Terrain.activeTerrain.transform.position.x, Terrain.activeTerrain.transform.position.z, Terrain.activeTerrain.terrainData.size.x, Terrain.activeTerrain.terrainData.size.z);
for (int i = 0; i < tagList.Count; i++)
{
string text = tagList[i].Trim();
bool flag = false;
if (!string.IsNullOrEmpty(text))
{
flag = true;
}
if (!flag)
{
continue;
}
Quadtree<GameObject> value = null;
if (!m_taggedGameObjectCache.TryGetValue(text, out value))
{
value = new Quadtree<GameObject>(boundaries);
m_taggedGameObjectCache.Add(text, value);
}
GameObject[] array = GameObject.FindGameObjectsWithTag(text);
foreach (GameObject gameObject in array)
{
Vector2 vector = new Vector2(gameObject.transform.position.x, gameObject.transform.position.z);
if (boundaries.Contains(vector))
{
value.Insert(vector, gameObject);
}
}
}
}
private void DeleteTagCache()
{
m_taggedGameObjectCache = null;
}
public List<GameObject> GetNearbyObjects(List<string> tagList, Rect area)
{
List<GameObject> list = new List<GameObject>();
for (int i = 0; i < tagList.Count; i++)
{
Quadtree<GameObject> value = null;
string key = tagList[i];
if (!m_taggedGameObjectCache.TryGetValue(key, out value))
{
continue;
}
foreach (GameObject item in value.Find(area))
{
list.Add(item);
}
}
return list;
}
public GameObject GetClosestObject(List<string> tagList, Rect area)
{
float num = float.MaxValue;
GameObject result = null;
for (int i = 0; i < tagList.Count; i++)
{
Quadtree<GameObject> value = null;
string key = tagList[i];
if (!m_taggedGameObjectCache.TryGetValue(key, out value))
{
continue;
}
foreach (GameObject item in value.Find(area))
{
float num2 = Vector2.Distance(area.center, new Vector2(item.transform.position.x, item.transform.position.z));
if (num2 < num)
{
num = num2;
result = item;
}
}
}
return result;
}
public GameObject GetClosestObject(string tag, Rect area)
{
float num = float.MaxValue;
GameObject result = null;
Quadtree<GameObject> value = null;
if (m_taggedGameObjectCache.TryGetValue(tag, out value))
{
foreach (GameObject item in value.Find(area))
{
float num2 = Vector2.Distance(area.center, new Vector2(item.transform.position.x, item.transform.position.z));
if (num2 < num)
{
num = num2;
result = item;
}
}
}
return result;
}
public void ResetRandomGenertor()
{
m_rndGenerator = new XorshiftPlus(m_seed);
}
public int GetRandomInt(int min, int max)
{
return m_rndGenerator.Next(min, max);
}
public float GetRandomFloat(float min, float max)
{
return m_rndGenerator.Next(min, max);
}
public Vector3 GetRandomV3(float range)
{
return m_rndGenerator.NextVector(0f - range, range);
}
}
}