165 lines
4.2 KiB
C#
165 lines
4.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace UltimateWater.Internal
|
|
{
|
|
public sealed class WaterSystem : ApplicationSingleton<WaterSystem>
|
|
{
|
|
private readonly List<Water> _Waters = new List<Water>();
|
|
|
|
private readonly List<Water> _BoundlessWaters = new List<Water>();
|
|
|
|
private static readonly List<Water> _PossibleWaters = new List<Water>();
|
|
|
|
private static readonly List<Water> _ExcludedWaters = new List<Water>();
|
|
|
|
private static readonly Collider[] _CollidersBuffer = new Collider[30];
|
|
|
|
private static int _CurrentId = 1;
|
|
|
|
private static readonly List<int> _FreeIds = new List<int>();
|
|
|
|
public List<Water> Waters => _Waters;
|
|
|
|
public List<Water> BoundlessWaters => _BoundlessWaters;
|
|
|
|
public event Action OnQuit;
|
|
|
|
public static bool IsWaterPossiblyVisible()
|
|
{
|
|
WaterSystem instance = ApplicationSingleton<WaterSystem>.Instance;
|
|
if (instance == null)
|
|
{
|
|
return false;
|
|
}
|
|
return instance.Waters.Count != 0;
|
|
}
|
|
|
|
public static void Register(Water water)
|
|
{
|
|
RequestId(water);
|
|
WaterSystem instance = ApplicationSingleton<WaterSystem>.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<WaterSystem>.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<Water> 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<Water> boundlessWaters = ApplicationSingleton<WaterSystem>.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;
|
|
}
|
|
}
|
|
}
|
|
}
|