using System;
using System.Collections.Generic;
using System.Linq;
using Chernobyl.Destruction;
using Chernobyl.Mathematics.Movement;
using UnityEngine;
using Transform = UnityEngine.Transform;
namespace Chernobyl.Unity.Math
{
///
/// Extensions and utility methods for .
///
public static class Vector2Ext
{
///
/// Rounds a to a .
///
public static Vector2Int RoundToInt(this Vector2 value) =>
new Vector2Int(Mathf.RoundToInt(value.x), Mathf.RoundToInt(value.y));
}
///
/// Extensions and utility methods for .
///
public static class Vector2IntExt
{
///
/// Converts from to .
///
public static Tuple ToTuple(this Vector2Int value) =>
Tuple.Create(value.x, value.y);
///
/// Converts from to a .
///
public static (int x, int y) ToValueTuple(this Vector2Int value) =>
(value.x, value.y);
///
/// Get the coordinates for the cell above .
///
public static Vector2Int GetNorthCoordinates(this Vector2Int cell) => cell + new Vector2Int(0, 1);
///
/// Get the coordinates for the cell above and to the right of .
///
public static Vector2Int GetNorthEastCoordinates(this Vector2Int cell) => cell + new Vector2Int(1, 1);
///
/// Get the coordinates for the cell to the right of .
///
public static Vector2Int GetEastCoordinates(this Vector2Int cell) => cell + new Vector2Int(1, 0);
///
/// Get the coordinates for the cell below and to the right .
///
public static Vector2Int GetSouthEastCoordinates(this Vector2Int cell) => cell + new Vector2Int(1, -1);
///
/// Get the coordinates for the cell below .
///
public static Vector2Int GetSouthCoordinates(this Vector2Int cell) => cell + new Vector2Int(0, -1);
///
/// Get the coordinates for the cell below and to the left .
///
public static Vector2Int GetSouthWestCoordinates(this Vector2Int cell) => cell + new Vector2Int(-1, -1);
///
/// Get the coordinates for the cell to the left of .
///
public static Vector2Int GetWestCoordinates(this Vector2Int cell) => cell + new Vector2Int(-1, 0);
///
/// Get the coordinates for the cell above and to the left of .
///
public static Vector2Int GetNorthWestCoordinates(this Vector2Int cell) => cell + new Vector2Int(-1, 1);
///
/// Calculates the center of the . Returns (0, 0) if
/// is empty.
///
public static Vector2Int CalculateCenter(this IReadOnlyCollection cells)
{
Vector2Int result = Vector2Int.zero;
if(cells.Count > 0)
{
var orderedByX = cells.OrderByDescending(p => p.x).ToArray();
var orderedByY = cells.OrderByDescending(p => p.y).ToArray();
var maxX = orderedByX[0].x;
var minX = orderedByX[orderedByX.Length - 1].x;
var maxY = orderedByY[0].y;
var minY = orderedByY[orderedByY.Length - 1].y;
var min = new Vector2(minX, minY);
var halfDistance = new Vector2((float) (maxX - minX) / 2, (float) (maxY - minY) / 2);
result = (min + halfDistance).RoundToInt();
}
return result;
}
}
///
/// Extensions and utility methods for .
///
public static class Vector3Ext
{
///
/// Rounds a to a .
///
public static Vector3Int RoundToInt(this Vector3 value) =>
new Vector3Int(Mathf.RoundToInt(value.x), Mathf.RoundToInt(value.y), Mathf.RoundToInt(value.z));
}
///
/// Extensions and utility methods for .
///
public static class Vector3IntExt
{
///
/// Returns the X and Y components of the .
///
public static Vector2Int Xy(this Vector3Int value) => new Vector2Int(value.x, value.y);
}
///
/// Extension methods for transforms.
///
public static class UnityTransform
{
///
/// Binds together a Chernobyl transform with a Unity transform such that changes to the
/// will be reflected in the .
/// Disposing of the returned will unbind the two transforms.
///
///
/// Remember to dispose of the returned disposable before disposing of the Unity
/// or its . Failing to do so can cause Unity
/// to generate an exception indicating that the is being modified
/// after the has been disposed of, e.g. "MissingReferenceException:
/// The object of type 'Transform' has been destroyed but you are still trying to access it."
///
public static IDisposable Bind(this ITransform chernobylTransform, Transform unityTransform)
{
void OnTransformDirtied(object sender, EventArgs args)
{
unityTransform.localPosition = new Vector3(
chernobylTransform.Position.X, chernobylTransform.Position.Y,
unityTransform.localPosition.z);
}
chernobylTransform.TransformDirtied += OnTransformDirtied;
OnTransformDirtied(chernobylTransform, EventArgs.Empty);
return Disposable.From(() => chernobylTransform.TransformDirtied -= OnTransformDirtied);
}
}
}