using UnityEngine;
using System.Collections.Generic;
namespace PathBerserker2d
{
///
/// Creates links to interconnect a collection.
///
///
/// Consists of a list of points.
/// At runtime a link is generated for each point to connect it with each other point.
/// This is a convenience component. It drastically reduces the amount of work required to setup an elevator or ladder for example.
///
/// Otherwise it functions and behaves the same as a NavLink.
/// Reference the documentation for NavLink for further details.
///
[AddComponentMenu("PathBerserker2d/Nav Link Cluster")]
public sealed class NavLinkCluster : BaseNavLink
{
internal enum PointTraversalType
{
Exit,
Entry,
Both
}
internal LinkPoint[] LinkPoints => linkPoints;
[SerializeField]
internal LinkPoint[] linkPoints = new LinkPoint[] { new LinkPoint(Vector2.left * 2), new LinkPoint(Vector2.right * 2) };
private List linkInstances;
#region UNITY
private void OnEnable()
{
if (linkInstances == null)
linkInstances = new List();
if (autoMap)
UpdateMapping();
}
private void OnDisable()
{
foreach (var li in linkInstances)
li.RemoveFromWorld();
}
#endregion
///
/// Update the mapping for all link instances. Call after link positions have been changed.
///
public void UpdateMapping()
{
NavSegmentPositionPointer navStart, navGoal;
int instanceCounter = 0;
foreach (var startPoint in linkPoints)
{
if (startPoint.traversalType == PointTraversalType.Exit)
continue;
Vector2 worldStart = transform.TransformPoint(startPoint.point);
foreach (var goalPoint in linkPoints)
{
if (goalPoint.traversalType == PointTraversalType.Entry || goalPoint.point == startPoint.point)
continue;
Vector2 worldGoal = transform.TransformPoint(goalPoint.point);
if (instanceCounter >= linkInstances.Count)
{
linkInstances.Add(new NavLinkInstance(this));
}
var linkInstance = linkInstances[instanceCounter++];
if (PBWorld.TryMapPointWithStaged(worldStart, out navStart)
&& PBWorld.TryMapPointWithStaged(worldGoal, out navGoal))
{
linkInstance.UpdateMapping(navStart, navGoal, worldStart, worldGoal);
linkInstance.AddToWorld();
}
else
{
linkInstance.RemoveFromWorld();
}
}
}
}
///
/// Set link instances to be traversable based on their start and end points.
///
/// Determines whether to enable or disable the given link instance. Link instance is given as its start and goal position.
public void SetLinksTraversable(System.Func traversableFunc)
{
foreach (var link in linkInstances)
{
if (link.IsAdded)
link.IsTraversable = traversableFunc(link.Start.Position, link.Goal.Position);
}
}
[System.Serializable]
internal struct LinkPoint
{
[SerializeField]
public Vector2 point;
[SerializeField]
public PointTraversalType traversalType;
public LinkPoint(Vector2 point)
{
this.point = point;
this.traversalType = PointTraversalType.Both;
}
}
}
}