rimworld-animation-studio/Assets/Scripts/Math/SimpleCurve.cs

291 lines
5.1 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace RimWorldAnimationStudio
{
public class SimpleCurve : IEnumerable<CurvePoint>, IEnumerable
{
public void Clear()
{
this.points.Clear();
}
public int PointsCount
{
get
{
return this.points.Count;
}
}
public List<CurvePoint> Points
{
get
{
return this.points;
}
}
public SimpleCurve(IEnumerable<CurvePoint> points)
{
this.SetPoints(points);
}
public SimpleCurve()
{
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
public IEnumerator<CurvePoint> GetEnumerator()
{
foreach (CurvePoint curvePoint in this.points)
{
yield return curvePoint;
}
List<CurvePoint>.Enumerator enumerator = default(List<CurvePoint>.Enumerator);
yield break;
yield break;
}
public CurvePoint this[int i]
{
get
{
return this.points[i];
}
set
{
this.points[i] = value;
}
}
public void SetPoints(IEnumerable<CurvePoint> newPoints)
{
this.points.Clear();
foreach (CurvePoint item in newPoints)
{
this.points.Add(item);
}
this.SortPoints();
}
public void Add(float x, float y, bool sort = true)
{
CurvePoint newPoint = new CurvePoint(x, y);
this.Add(newPoint, sort);
}
public void Add(CurvePoint newPoint, bool sort = true)
{
this.points.Add(newPoint);
if (sort)
{
this.SortPoints();
}
}
public void SortPoints()
{
this.points.Sort(SimpleCurve.CurvePointsComparer);
}
public float ClampToCurve(float value)
{
if (this.points.Count == 0)
{
Debug.Log("Clamping a value to an empty SimpleCurve.");
return value;
}
return Mathf.Clamp(value, this.points[0].y, this.points[this.points.Count - 1].y);
}
public void RemovePointNear(CurvePoint point)
{
for (int i = 0; i < this.points.Count; i++)
{
if ((this.points[i].Loc - point.Loc).sqrMagnitude < 0.001f)
{
this.points.RemoveAt(i);
return;
}
}
}
public float Evaluate(float x)
{
if (this.points.Count == 0)
{
Debug.Log("Evaluating a SimpleCurve with no points.");
return 0f;
}
if (x <= this.points[0].x)
{
return this.points[0].y;
}
if (x >= this.points[this.points.Count - 1].x)
{
return this.points[this.points.Count - 1].y;
}
CurvePoint curvePoint = this.points[0];
CurvePoint curvePoint2 = this.points[this.points.Count - 1];
int i = 0;
while (i < this.points.Count)
{
if (x <= this.points[i].x)
{
curvePoint2 = this.points[i];
if (i > 0)
{
curvePoint = this.points[i - 1];
break;
}
break;
}
else
{
i++;
}
}
float t = (x - curvePoint.x) / (curvePoint2.x - curvePoint.x);
return Mathf.Lerp(curvePoint.y, curvePoint2.y, t);
}
public float EvaluateInverted(float y)
{
if (this.points.Count == 0)
{
Debug.Log("Evaluating a SimpleCurve with no points.");
return 0f;
}
if (this.points.Count == 1)
{
return this.points[0].x;
}
int i = 0;
while (i < this.points.Count - 1)
{
if ((y >= this.points[i].y && y <= this.points[i + 1].y) || (y <= this.points[i].y && y >= this.points[i + 1].y))
{
if (y == this.points[i].y)
{
return this.points[i].x;
}
if (y == this.points[i + 1].y)
{
return this.points[i + 1].x;
}
return GenMath.LerpDouble(this.points[i].y, this.points[i + 1].y, this.points[i].x, this.points[i + 1].x, y);
}
else
{
i++;
}
}
if (y < this.points[0].y)
{
float result = 0f;
float num = 0f;
for (int j = 0; j < this.points.Count; j++)
{
if (j == 0 || this.points[j].y < num)
{
num = this.points[j].y;
result = this.points[j].x;
}
}
return result;
}
float result2 = 0f;
float num2 = 0f;
for (int k = 0; k < this.points.Count; k++)
{
if (k == 0 || this.points[k].y > num2)
{
num2 = this.points[k].y;
result2 = this.points[k].x;
}
}
return result2;
}
public float PeriodProbabilityFromCumulative(float startX, float span)
{
if (this.points.Count < 2)
{
return 0f;
}
if (this.points[0].y != 0f)
{
Debug.Log("PeriodProbabilityFromCumulative should only run on curves whose first point is 0.");
}
float num = this.Evaluate(startX + span) - this.Evaluate(startX);
if (num < 0f)
{
Debug.Log("PeriodicProbability got negative probability from " + this + ": slope should never be negative.");
num = 0f;
}
if (num > 1f)
{
num = 1f;
}
return num;
}
public IEnumerable<string> ConfigErrors(string prefix)
{
for (int i = 0; i < this.points.Count - 1; i++)
{
if (this.points[i + 1].x < this.points[i].x)
{
yield return prefix + ": points are out of order";
break;
}
}
yield break;
}
private List<CurvePoint> points = new List<CurvePoint>();
private static Comparison<CurvePoint> CurvePointsComparer = delegate (CurvePoint a, CurvePoint b)
{
if (a.x < b.x)
{
return -1;
}
if (b.x < a.x)
{
return 1;
}
return 0;
};
}
}