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); } } }