rabidus-test/Assets/Dreamteck/Splines/Core/SplineUtility.cs

119 lines
4.9 KiB
C#
Raw Permalink Normal View History

2023-07-24 16:38:13 +03:00
namespace Dreamteck.Splines
{
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public static class SplineUtility
{
public enum MergeSide { Start, End }
/// <summary>
/// Merges two spline objects into one. The result will be merged into <paramref name="baseSpline"/>
/// </summary>
/// <param name="baseSpline">The base spline object that</param>
/// <param name="addedSpline">The object that will be merged into the base spline</param>
/// <param name="side">Which side of the base spline to append to - beginning or end?</param>
/// <param name="mergeEndpoints">Should the end points of the splines be merged or should they be bridged?</param>
/// <param name="destroyAddedSpline">If true, the added spline's game object will be destroyed after merge</param>
public static void Merge(SplineComputer baseSpline, SplineComputer addedSpline, MergeSide side, bool mergeEndpoints = false, bool destroyAddedSpline = false)
{
SplinePoint[] mergedPoints = addedSpline.GetPoints();
SplinePoint[] basePoints = baseSpline.GetPoints();
List<SplinePoint> pointsList = new List<SplinePoint>();
SplinePoint[] points;
if (!mergeEndpoints) points = new SplinePoint[mergedPoints.Length + basePoints.Length];
else points = new SplinePoint[mergedPoints.Length + basePoints.Length - 1];
if (side == MergeSide.End)
{
if (side == MergeSide.Start)
{
for (int i = 0; i < basePoints.Length; i++) pointsList.Add(basePoints[i]);
for (int i = mergeEndpoints ? 1 : 0; i < mergedPoints.Length; i++) pointsList.Add(mergedPoints[i]);
}
else
{
for (int i = 0; i < basePoints.Length; i++) pointsList.Add(basePoints[i]);
for (int i = 0; i < mergedPoints.Length - (mergeEndpoints ? 1 : 0); i++) pointsList.Add(mergedPoints[(mergedPoints.Length - 1) - i]);
}
}
else
{
if (side == MergeSide.Start)
{
for (int i = 0; i < mergedPoints.Length - (mergeEndpoints ? 1 : 0); i++) pointsList.Add(mergedPoints[(mergedPoints.Length - 1) - i]);
for (int i = 0; i < basePoints.Length; i++) pointsList.Add(basePoints[i]);
}
else
{
for (int i = mergeEndpoints ? 1 : 0; i < mergedPoints.Length; i++) pointsList.Add(mergedPoints[i]);
for (int i = 0; i < basePoints.Length; i++) pointsList.Add(basePoints[i]);
}
}
points = pointsList.ToArray();
double mergedPercent = (double)(mergedPoints.Length - 1) / (points.Length - 1);
double from = 0.0;
double to = 1.0;
if (side == MergeSide.End)
{
from = 1.0 - mergedPercent;
to = 1.0;
}
else
{
from = 0.0;
to = mergedPercent;
}
List<Node> mergedNodes = new List<Node>();
List<int> mergedIndices = new List<int>();
for (int i = 0; i < addedSpline.pointCount; i++)
{
Node node = addedSpline.GetNode(i);
if (node != null)
{
mergedNodes.Add(node);
mergedIndices.Add(i);
addedSpline.DisconnectNode(i);
i--;
}
}
SplineUser[] subs = addedSpline.GetSubscribers();
for (int i = 0; i < subs.Length; i++)
{
addedSpline.Unsubscribe(subs[i]);
subs[i].spline = baseSpline;
subs[i].clipFrom = DMath.Lerp(from, to, subs[i].clipFrom);
subs[i].clipTo = DMath.Lerp(from, to, subs[i].clipTo);
}
baseSpline.SetPoints(points);
if (side == MergeSide.Start)
{
baseSpline.ShiftNodes(0, baseSpline.pointCount - 1, addedSpline.pointCount);
for (int i = 0; i < mergedNodes.Count; i++)
{
baseSpline.ConnectNode(mergedNodes[i], mergedIndices[i]);
}
}
else
{
for (int i = 0; i < mergedNodes.Count; i++)
{
int connectIndex = mergedIndices[i] + basePoints.Length;
if (mergeEndpoints) connectIndex--;
baseSpline.ConnectNode(mergedNodes[i], connectIndex);
}
}
if (destroyAddedSpline)
{
Object.Destroy(addedSpline.gameObject);
}
}
}
}