using System; using System.Collections.Generic; using Unity.CodeEditor.Editing; using UnityEngine; namespace Unity.CodeEditor.Utils { //PENDING TO COMPLETE internal static class ExtensionMethods { #region Rectangle internal static Rect WithY(this Rect rect, float y) { return new Rect(rect.x, y, rect.width, rect.height); } internal static Rect WithWidth(this Rect rect, float width) { return new Rect(rect.x, rect.y, width, rect.height); } #endregion #region Vector2 internal static bool IsClose(this Vector2 v, Vector2 other) { return IsClose(v.x, other.x) && IsClose(v.y, other.y); } internal static Vector2 RelativeTo(this Vector2 v, Rect rect) { return new Vector2(v.x - rect.x, v.y - rect.y); } #endregion #region Epsilon / IsClose / CoerceValue /// /// Epsilon used for IsClose() implementations. /// We can use up quite a few digits in front of the decimal point (due to visual positions being relative to document origin), /// and there's no need to be too accurate (we're dealing with pixels here), /// so we will use the value 0.01. /// Previosly we used 1e-8 but that was causing issues: /// https://community.sharpdevelop.net/forums/t/16048.aspx /// internal const float Epsilon = 0.01f; /// /// Returns true if the doubles are close (difference smaller than 0.01). /// internal static bool IsClose(this float d1, float d2) { // ReSharper disable once CompareOfFloatsByEqualityOperator if (d1 == d2) // required for infinities return true; return Math.Abs(d1 - d2) < Epsilon; } /// /// Returns true if the doubles are close (difference smaller than 0.01). /// internal static bool IsClose(this double d1, double d2) { // ReSharper disable once CompareOfFloatsByEqualityOperator if (d1 == d2) // required for infinities return true; return Math.Abs(d1 - d2) < Epsilon; } /// /// Returns true if the doubles are close (difference smaller than 0.01). /// /*public static bool IsClose(this Size d1, Size d2) { return IsClose(d1.Width, d2.Width) && IsClose(d1.Height, d2.Height); }*/ /// /// Forces the value to stay between mininum and maximum. /// /// minimum, if value is less than minimum. /// Maximum, if value is greater than maximum. /// Otherwise, value. internal static double CoerceValue(this double value, double minimum, double maximum) { return Math.Max(Math.Min(value, maximum), minimum); } /// /// Forces the value to stay between mininum and maximum. /// /// minimum, if value is less than minimum. /// Maximum, if value is greater than maximum. /// Otherwise, value. internal static int CoerceValue(this int value, int minimum, int maximum) { return Math.Max(Math.Min(value, maximum), minimum); } #endregion #region AddRange / Sequence internal static void AddRange(this ICollection collection, IEnumerable elements) { foreach (T e in elements) collection.Add(e); } /// /// Creates an IEnumerable with a single value. /// internal static IEnumerable Sequence(T value) { yield return value; } #endregion internal static T PeekOrDefault(this ImmutableStack stack) { return stack.IsEmpty ? default(T) : stack.Peek(); } /// /// Gets the union of two rectangles. /// /// The other rectangle. /// The union. internal static Rect Union(this Rect rect, Rect other) { if (rect.width == 0 && rect.height == 0) { return other; } else if (other.width == 0 && other.height == 0) { return rect; } else { var x1 = Math.Min(rect.x, other.x); var x2 = Math.Max(rect.xMax, other.xMax); var y1 = Math.Min(rect.y, other.y); var y2 = Math.Max(rect.yMax, other.yMax); return new Rect(new Vector2(x1, y1), new Vector2(x2, y2)); } } } }