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 { get { return _CurrentWater; } } public UnityEvent Enter { get { return (_Enter == null) ? (_Enter = new UnityEvent()) : _Enter; } } public UnityEvent Leave { get { return (_Leave == null) ? (_Leave = new UnityEvent()) : _Leave; } } public static WaterVolumeProbe CreateProbe(Transform target, float size = 0f) { GameObject gameObject = new GameObject("Water Volume Probe"); gameObject.hideFlags = HideFlags.HideAndDontSave; GameObject gameObject2 = gameObject; gameObject2.transform.position = target.position; gameObject2.layer = WaterProjectSettings.Instance.WaterCollidersLayer; SphereCollider sphereCollider = gameObject2.AddComponent(); sphereCollider.radius = size; sphereCollider.isTrigger = true; Rigidbody rigidbody = gameObject2.AddComponent(); rigidbody.isKinematic = true; rigidbody.mass = 1E-07f; WaterVolumeProbe waterVolumeProbe = gameObject2.AddComponent(); waterVolumeProbe._Target = target; waterVolumeProbe._Targetted = true; waterVolumeProbe._Size = size; waterVolumeProbe._Exclusions = target.GetComponentsInChildren(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(other); if (waterVolume != null && waterVolume.EnablePhysics) { LeaveCurrentWater(); } } else { WaterVolumeBase waterVolume2 = WaterVolumeBase.GetWaterVolume(other); if (waterVolume2 != null && waterVolume2.EnablePhysics) { EnterWater(waterVolume2.Water); } } } public void OnTriggerExit(Collider other) { if (_CurrentWater == null) { WaterVolumeBase waterVolume = WaterVolumeBase.GetWaterVolume(other); if (waterVolume != null && waterVolume.EnablePhysics) { ScanWaters(); } } else { WaterVolumeBase waterVolume2 = WaterVolumeBase.GetWaterVolume(other); if (waterVolume2 != null && waterVolume2.Water == _CurrentWater && waterVolume2.EnablePhysics) { LeaveCurrentWater(); } } } [ContextMenu("Refresh Probe")] private void ScanWaters() { Vector3 position = base.transform.position; List waters = ApplicationSingleton.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 boundlessWaters = ApplicationSingleton.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; } } } }