using System; using System.Collections.Generic; using UnityEngine; namespace UltimateWater.Internal { public sealed class WaterSystem : ApplicationSingleton { private readonly List _Waters = new List(); private readonly List _BoundlessWaters = new List(); private static readonly List _PossibleWaters = new List(); private static readonly List _ExcludedWaters = new List(); private static readonly Collider[] _CollidersBuffer = new Collider[30]; private static int _CurrentId = 1; private static readonly List _FreeIds = new List(); public List Waters => _Waters; public List BoundlessWaters => _BoundlessWaters; public event Action OnQuit; public static bool IsWaterPossiblyVisible() { WaterSystem instance = ApplicationSingleton.Instance; if (instance == null) { return false; } return instance.Waters.Count != 0; } public static void Register(Water water) { RequestId(water); WaterSystem instance = ApplicationSingleton.Instance; if (!(instance == null)) { if (!instance._Waters.Contains(water)) { instance._Waters.Add(water); } if ((water.Volume == null || water.Volume.Boundless) && !instance._BoundlessWaters.Contains(water)) { instance._BoundlessWaters.Add(water); } } } public static void Unregister(Water water) { FreeId(water); WaterSystem instance = ApplicationSingleton.Instance; if (!(instance == null)) { instance._Waters.Remove(water); instance._BoundlessWaters.Remove(water); } } public static Water FindWater(Vector3 position, float radius) { bool isInsideSubtractiveVolume; bool isInsideAdditiveVolume; return FindWater(position, radius, null, out isInsideSubtractiveVolume, out isInsideAdditiveVolume); } public static Water FindWater(Vector3 position, float radius, out bool isInsideSubtractiveVolume, out bool isInsideAdditiveVolume) { return FindWater(position, radius, null, out isInsideSubtractiveVolume, out isInsideAdditiveVolume); } public static Water FindWater(Vector3 position, float radius, List allowedWaters, out bool isInsideSubtractiveVolume, out bool isInsideAdditiveVolume) { isInsideSubtractiveVolume = false; isInsideAdditiveVolume = false; int num = Physics.OverlapSphereNonAlloc(position, radius, _CollidersBuffer, 1 << WaterProjectSettings.Instance.WaterCollidersLayer, QueryTriggerInteraction.Collide); _PossibleWaters.Clear(); _ExcludedWaters.Clear(); for (int i = 0; i < num; i++) { WaterVolumeBase waterVolume = WaterVolumeBase.GetWaterVolume(_CollidersBuffer[i]); if (!(waterVolume != null)) { continue; } if (waterVolume is WaterVolumeAdd) { isInsideAdditiveVolume = true; if (allowedWaters == null || allowedWaters.Contains(waterVolume.Water)) { _PossibleWaters.Add(waterVolume.Water); } } else { isInsideSubtractiveVolume = true; _ExcludedWaters.Add(waterVolume.Water); } } for (int j = 0; j < _PossibleWaters.Count; j++) { if (!_ExcludedWaters.Contains(_PossibleWaters[j])) { return _PossibleWaters[j]; } } List boundlessWaters = ApplicationSingleton.Instance.BoundlessWaters; int count = boundlessWaters.Count; for (int k = 0; k < count; k++) { Water water = boundlessWaters[k]; if ((allowedWaters == null || allowedWaters.Contains(water)) && water.Volume.IsPointInsideMainVolume(position, radius) && !_ExcludedWaters.Contains(water)) { return water; } } return null; } protected override void OnDestroy() { if (this.OnQuit != null) { this.OnQuit(); } base.OnDestroy(); } private static bool RequestId(Water water) { if (water._WaterId != -1) { return false; } if (_FreeIds.Count == 0) { water._WaterId = _CurrentId++; } else { int index = _FreeIds.Count - 1; water._WaterId = _FreeIds[index]; _FreeIds.RemoveAt(index); } return true; } private static void FreeId(Water water) { if (water._WaterId != -1) { _FreeIds.Add(water._WaterId); water._WaterId = -1; } } } }