221 lines
4.8 KiB
C#
221 lines
4.8 KiB
C#
using System.Collections.Generic;
|
|
using UltimateWater.Internal;
|
|
using UnityEngine;
|
|
using UnityEngine.Events;
|
|
using UnityEngine.Serialization;
|
|
|
|
namespace UltimateWater
|
|
{
|
|
public sealed class WaterVolumeProbe : MonoBehaviour
|
|
{
|
|
[SerializeField]
|
|
[FormerlySerializedAs("enter")]
|
|
private UnityEvent _Enter;
|
|
|
|
[SerializeField]
|
|
[FormerlySerializedAs("leave")]
|
|
private UnityEvent _Leave;
|
|
|
|
private Water _CurrentWater;
|
|
|
|
private Transform _Target;
|
|
|
|
private bool _Targetted;
|
|
|
|
private WaterVolumeSubtract[] _Exclusions;
|
|
|
|
private float _Size;
|
|
|
|
public Water CurrentWater => _CurrentWater;
|
|
|
|
public UnityEvent Enter
|
|
{
|
|
get
|
|
{
|
|
if (_Enter == null)
|
|
{
|
|
return _Enter = new UnityEvent();
|
|
}
|
|
return _Enter;
|
|
}
|
|
}
|
|
|
|
public UnityEvent Leave
|
|
{
|
|
get
|
|
{
|
|
if (_Leave == null)
|
|
{
|
|
return _Leave = new UnityEvent();
|
|
}
|
|
return _Leave;
|
|
}
|
|
}
|
|
|
|
public static WaterVolumeProbe CreateProbe(Transform target, float size = 0f)
|
|
{
|
|
GameObject obj = new GameObject("Water Volume Probe");
|
|
obj.hideFlags = HideFlags.HideAndDontSave;
|
|
obj.transform.position = target.position;
|
|
obj.layer = WaterProjectSettings.Instance.WaterCollidersLayer;
|
|
SphereCollider sphereCollider = obj.AddComponent<SphereCollider>();
|
|
sphereCollider.radius = size;
|
|
sphereCollider.isTrigger = true;
|
|
Rigidbody rigidbody = obj.AddComponent<Rigidbody>();
|
|
rigidbody.isKinematic = true;
|
|
rigidbody.mass = 1E-07f;
|
|
WaterVolumeProbe waterVolumeProbe = obj.AddComponent<WaterVolumeProbe>();
|
|
waterVolumeProbe._Target = target;
|
|
waterVolumeProbe._Targetted = true;
|
|
waterVolumeProbe._Size = size;
|
|
waterVolumeProbe._Exclusions = target.GetComponentsInChildren<WaterVolumeSubtract>(includeInactive: true);
|
|
return waterVolumeProbe;
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
ScanWaters();
|
|
}
|
|
|
|
private void FixedUpdate()
|
|
{
|
|
if (_Targetted)
|
|
{
|
|
if (_Target == null)
|
|
{
|
|
Object.Destroy(base.gameObject);
|
|
return;
|
|
}
|
|
base.transform.position = _Target.position;
|
|
}
|
|
if (_CurrentWater != null && _CurrentWater.Volume.Boundless)
|
|
{
|
|
if (!_CurrentWater.Volume.IsPointInsideMainVolume(base.transform.position) && !_CurrentWater.Volume.IsPointInside(base.transform.position, _Exclusions, _Size))
|
|
{
|
|
LeaveCurrentWater();
|
|
}
|
|
}
|
|
else if (_CurrentWater == null)
|
|
{
|
|
ScanBoundlessWaters();
|
|
}
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
_CurrentWater = null;
|
|
if (_Enter != null)
|
|
{
|
|
_Enter.RemoveAllListeners();
|
|
_Enter = null;
|
|
}
|
|
if (_Leave != null)
|
|
{
|
|
_Leave.RemoveAllListeners();
|
|
_Leave = null;
|
|
}
|
|
}
|
|
|
|
public void OnTriggerEnter(Collider other)
|
|
{
|
|
if (_CurrentWater != null)
|
|
{
|
|
WaterVolumeBase waterVolume = WaterVolumeBase.GetWaterVolume<WaterVolumeSubtract>(other);
|
|
if (waterVolume != null && waterVolume.EnablePhysics)
|
|
{
|
|
LeaveCurrentWater();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WaterVolumeBase waterVolume2 = WaterVolumeBase.GetWaterVolume<WaterVolumeAdd>(other);
|
|
if (waterVolume2 != null && waterVolume2.EnablePhysics)
|
|
{
|
|
EnterWater(waterVolume2.Water);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void OnTriggerExit(Collider other)
|
|
{
|
|
if (_CurrentWater == null)
|
|
{
|
|
WaterVolumeBase waterVolume = WaterVolumeBase.GetWaterVolume<WaterVolumeSubtract>(other);
|
|
if (waterVolume != null && waterVolume.EnablePhysics)
|
|
{
|
|
ScanWaters();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WaterVolumeBase waterVolume2 = WaterVolumeBase.GetWaterVolume<WaterVolumeAdd>(other);
|
|
if (waterVolume2 != null && waterVolume2.Water == _CurrentWater && waterVolume2.EnablePhysics)
|
|
{
|
|
LeaveCurrentWater();
|
|
}
|
|
}
|
|
}
|
|
|
|
[ContextMenu("Refresh Probe")]
|
|
private void ScanWaters()
|
|
{
|
|
Vector3 position = base.transform.position;
|
|
List<Water> waters = ApplicationSingleton<WaterSystem>.Instance.Waters;
|
|
int count = waters.Count;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
if (waters[i].Volume.IsPointInside(position, _Exclusions, _Size))
|
|
{
|
|
EnterWater(waters[i]);
|
|
return;
|
|
}
|
|
}
|
|
LeaveCurrentWater();
|
|
}
|
|
|
|
private void ScanBoundlessWaters()
|
|
{
|
|
Vector3 position = base.transform.position;
|
|
List<Water> boundlessWaters = ApplicationSingleton<WaterSystem>.Instance.BoundlessWaters;
|
|
int count = boundlessWaters.Count;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
Water water = boundlessWaters[i];
|
|
if (water.Volume.IsPointInsideMainVolume(position) && water.Volume.IsPointInside(position, _Exclusions, _Size))
|
|
{
|
|
EnterWater(water);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void EnterWater(Water water)
|
|
{
|
|
if (!(_CurrentWater == water))
|
|
{
|
|
if (_CurrentWater != null)
|
|
{
|
|
LeaveCurrentWater();
|
|
}
|
|
_CurrentWater = water;
|
|
if (_Enter != null)
|
|
{
|
|
_Enter.Invoke();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void LeaveCurrentWater()
|
|
{
|
|
if (_CurrentWater != null)
|
|
{
|
|
if (_Leave != null)
|
|
{
|
|
_Leave.Invoke();
|
|
}
|
|
_CurrentWater = null;
|
|
}
|
|
}
|
|
}
|
|
}
|