Files
2026-03-04 10:03:45 +08:00

232 lines
5.2 KiB
C#

using System;
using UltimateWater.Internal;
using UnityEngine;
namespace UltimateWater
{
public sealed class WaterSample
{
public enum DisplacementMode
{
Height = 0,
Displacement = 1,
HeightAndForces = 2
}
public enum ComputationsMode
{
Normal = 0,
ForceCompletion = 2
}
private readonly Water _Water;
private float _X;
private float _Z;
private float _Time;
private Vector3 _Displaced;
private Vector3 _PreviousResult;
private Vector3 _Forces;
private Vector3 _PreviousForces;
private bool _Finished;
private bool _Enqueued;
private readonly DisplacementMode _DisplacementMode;
public bool Finished => _Finished;
public Vector2 Position => new Vector2(_X, _Z);
public WaterSample(Water water, DisplacementMode displacementMode = DisplacementMode.Height, float precision = 1f)
{
if (water == null)
{
throw new ArgumentException("Argument 'water' is null.");
}
if (precision <= 0f || precision > 1f)
{
throw new ArgumentException("Precision has to be between 0.0 and 1.0.");
}
_Water = water;
_DisplacementMode = displacementMode;
_PreviousResult.x = float.NaN;
}
public void Start(Vector3 origin)
{
_Finished = true;
_PreviousResult = (_Displaced = origin);
_PreviousForces = (_Forces = default(Vector3));
GetAndReset(origin.x, origin.z);
}
public void Start(float x, float z)
{
_Finished = true;
_PreviousResult = (_Displaced = new Vector3(x, _Water.transform.position.y, z));
_PreviousForces = (_Forces = default(Vector3));
GetAndReset(x, z);
}
public Vector3 GetAndReset(Vector3 origin, ComputationsMode mode = ComputationsMode.Normal)
{
return GetAndReset(origin.x, origin.z, mode);
}
public Vector3 GetAndReset(float x, float z, ComputationsMode mode = ComputationsMode.Normal)
{
Vector3 forces;
return GetAndReset(x, z, mode, out forces);
}
public Vector3 GetAndReset(float x, float z, ComputationsMode mode, out Vector3 forces)
{
switch (mode)
{
case ComputationsMode.ForceCompletion:
if (!_Finished)
{
_Finished = true;
ComputationStep(ignoreFinishedFlag: true);
}
break;
case ComputationsMode.Normal:
if (!_Finished && !float.IsNaN(_PreviousResult.x))
{
forces = _PreviousForces;
return _PreviousResult;
}
_PreviousResult = _Displaced;
_PreviousForces = _Forces;
break;
}
_Finished = true;
if (!_Enqueued)
{
WaterAsynchronousTasks.Instance.AddWaterSampleComputations(this);
_Enqueued = true;
_Water.OnSamplingStarted();
}
Vector3 displaced = _Displaced;
displaced.y += _Water.transform.position.y;
forces = _Forces;
_X = x;
_Z = z;
_Displaced.x = x;
_Displaced.y = 0f;
_Displaced.z = z;
_Forces.x = 0f;
_Forces.y = 0f;
_Forces.z = 0f;
_Time = _Water.Time;
_Finished = false;
return displaced;
}
public void GetAndResetFast(float x, float z, float time, out Vector3 result, out Vector3 forces)
{
if (!_Finished)
{
forces = _PreviousForces;
result = _PreviousResult;
return;
}
_PreviousResult = _Displaced;
_PreviousForces = _Forces;
result = _Displaced;
result.y += _Water.transform.position.y;
forces = _Forces;
_X = x;
_Z = z;
_Displaced.x = x;
_Displaced.y = 0f;
_Displaced.z = z;
_Forces.x = 0f;
_Forces.y = 0f;
_Forces.z = 0f;
_Time = time;
_Finished = false;
}
public void GetAndResetFast(float x, float z, float time, out float result, out Vector3 forces)
{
if (!_Finished)
{
forces = _PreviousForces;
result = _PreviousResult.y;
return;
}
_PreviousResult = _Displaced;
_PreviousForces = _Forces;
result = _Displaced.y + _Water.transform.position.y;
forces = _Forces;
_X = x;
_Z = z;
_Displaced.x = x;
_Displaced.y = 0f;
_Displaced.z = z;
_Forces.x = 0f;
_Forces.y = 0f;
_Forces.z = 0f;
_Time = time;
_Finished = false;
}
public Vector3 Stop()
{
if (_Enqueued)
{
if (WaterAsynchronousTasks.HasInstance)
{
WaterAsynchronousTasks.Instance.RemoveWaterSampleComputations(this);
}
_Enqueued = false;
if (_Water != null)
{
_Water.OnSamplingStopped();
}
}
return _Displaced;
}
internal void ComputationStep(bool ignoreFinishedFlag = false)
{
if (!(!_Finished || ignoreFinishedFlag))
{
return;
}
if (_DisplacementMode == DisplacementMode.Height || _DisplacementMode == DisplacementMode.HeightAndForces)
{
_Water.CompensateHorizontalDisplacement(ref _X, ref _Z, _Time);
if (_DisplacementMode == DisplacementMode.Height)
{
float uncompensatedHeightAt = _Water.GetUncompensatedHeightAt(_X, _Z, _Time);
_Displaced.y += uncompensatedHeightAt;
}
else
{
Vector4 uncompensatedHeightAndForcesAt = _Water.GetUncompensatedHeightAndForcesAt(_X, _Z, _Time);
_Displaced.y += uncompensatedHeightAndForcesAt.w;
_Forces.x += uncompensatedHeightAndForcesAt.x;
_Forces.y += uncompensatedHeightAndForcesAt.y;
_Forces.z += uncompensatedHeightAndForcesAt.z;
}
}
else
{
Vector3 vector = ((_Water.WaterId != -1) ? _Water.GetUncompensatedDisplacementAt(_X, _Z, _Time) : default(Vector3));
_Displaced += vector;
}
_Finished = true;
}
}
}