v1.3.0.1 (Epic Store release)
This commit is contained in:
@@ -1,54 +0,0 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace Barotrauma.Extensions
|
||||
{
|
||||
public static class ColorExtensions
|
||||
{
|
||||
public static Color Multiply(this Color color, float value, bool onlyAlpha = false)
|
||||
{
|
||||
return onlyAlpha ?
|
||||
new Color(color.R, color.G, color.B, (byte)(color.A * value)) :
|
||||
new Color((byte)(color.R * value), (byte)(color.G * value), (byte)(color.B * value), (byte)(color.A * value));
|
||||
}
|
||||
|
||||
public static Color Multiply(this Color thisColor, Color color)
|
||||
{
|
||||
return new Color((byte)(thisColor.R * color.R / 255f), (byte)(thisColor.G * color.G / 255f), (byte)(thisColor.B * color.B / 255f), (byte)(thisColor.A * color.A / 255f));
|
||||
}
|
||||
|
||||
public static Color Opaque(this Color color)
|
||||
{
|
||||
return new Color(color.R, color.G, color.B, (byte)255);
|
||||
}
|
||||
|
||||
private static bool IsFirstColorChannelDominant(byte first, byte second, byte third, float minimumRatio = 2)
|
||||
=> first > second * minimumRatio && first > third * minimumRatio;
|
||||
|
||||
/// <summary>
|
||||
/// Is the value of the red channel at least 'minimumRatio' larger than the blue and green
|
||||
/// </summary>
|
||||
public static bool IsRedDominant(Color color, float minimumRatio = 2, byte minimumAlpha = 0)
|
||||
=> color.A > minimumAlpha &&
|
||||
IsFirstColorChannelDominant(
|
||||
first: color.R,
|
||||
color.G, color.B, minimumRatio);
|
||||
|
||||
/// <summary>
|
||||
/// Is the value of the green channel at least 'minimumRatio' larger than the red and blue
|
||||
/// </summary>
|
||||
public static bool IsGreenDominant(Color color, float minimumRatio = 2, byte minimumAlpha = 0)
|
||||
=> color.A > minimumAlpha &&
|
||||
IsFirstColorChannelDominant(
|
||||
first: color.G,
|
||||
color.R, color.B, minimumRatio);
|
||||
|
||||
/// <summary>
|
||||
/// Is the value of the blue channel at least 'minimumRatio' larger than the red and green
|
||||
/// </summary>
|
||||
public static bool IsBlueDominant(Color color, float minimumRatio = 2, byte minimumAlpha = 0)
|
||||
=> color.A > minimumAlpha &&
|
||||
IsFirstColorChannelDominant(
|
||||
first: color.B,
|
||||
color.G, color.R, minimumRatio);
|
||||
}
|
||||
}
|
||||
@@ -185,27 +185,6 @@ namespace Barotrauma.Extensions
|
||||
if (value != null) { source.Add(value); }
|
||||
}
|
||||
|
||||
public static ImmutableDictionary<TKey, TValue> ToImmutableDictionary<TKey, TValue>(this IEnumerable<(TKey, TValue)> enumerable)
|
||||
{
|
||||
return enumerable.ToDictionary().ToImmutableDictionary();
|
||||
}
|
||||
|
||||
public static Dictionary<TKey, TValue> ToDictionary<TKey, TValue>(this IEnumerable<(TKey, TValue)> enumerable)
|
||||
{
|
||||
var dictionary = new Dictionary<TKey, TValue>();
|
||||
foreach (var (k,v) in enumerable)
|
||||
{
|
||||
dictionary.Add(k, v);
|
||||
}
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
public static Dictionary<TKey, TValue> ToMutable<TKey, TValue>(this ImmutableDictionary<TKey, TValue> immutableDictionary)
|
||||
{
|
||||
if (immutableDictionary == null) { return null; }
|
||||
return new Dictionary<TKey, TValue>(immutableDictionary);
|
||||
}
|
||||
|
||||
public static NetCollection<T> ToNetCollection<T>(this IEnumerable<T> enumerable) => new NetCollection<T>(enumerable.ToImmutableArray());
|
||||
|
||||
/// <summary>
|
||||
@@ -236,87 +215,5 @@ namespace Barotrauma.Extensions
|
||||
|
||||
public static IReadOnlyList<T> ListConcat<T>(this IEnumerable<T> self, IEnumerable<T> other)
|
||||
=> new ListConcat<T>(self, other);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the maximum element in a given enumerable, or null if there
|
||||
/// aren't any elements in the input.
|
||||
/// </summary>
|
||||
/// <param name="enumerable">Input collection</param>
|
||||
/// <returns>Maximum element or null</returns>
|
||||
public static T? MaxOrNull<T>(this IEnumerable<T> enumerable) where T : struct, IComparable<T>
|
||||
{
|
||||
T? retVal = null;
|
||||
foreach (T v in enumerable)
|
||||
{
|
||||
if (!retVal.HasValue || v.CompareTo(retVal.Value) > 0) { retVal = v; }
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static TOut? MaxOrNull<TIn, TOut>(this IEnumerable<TIn> enumerable, Func<TIn, TOut> conversion)
|
||||
where TOut : struct, IComparable<TOut>
|
||||
=> enumerable.Select(conversion).MaxOrNull();
|
||||
|
||||
public static int FindIndex<T>(this IReadOnlyList<T> list, Predicate<T> predicate)
|
||||
{
|
||||
for (int i=0; i<list.Count; i++)
|
||||
{
|
||||
if (predicate(list[i])) { return i; }
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Same as FirstOrDefault but will always return null instead of default(T) when no element is found
|
||||
/// </summary>
|
||||
public static T? FirstOrNull<T>(this IEnumerable<T> source, Func<T, bool> predicate) where T : struct
|
||||
{
|
||||
if (source.FirstOrDefault(predicate) is var first && !first.Equals(default(T)))
|
||||
{
|
||||
return first;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static T? FirstOrNull<T>(this IEnumerable<T> source) where T : struct
|
||||
{
|
||||
if (source.FirstOrDefault() is var first && !first.Equals(default(T)))
|
||||
{
|
||||
return first;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static IEnumerable<T> NotNull<T>(this IEnumerable<T?> source) where T : struct
|
||||
=> source
|
||||
.Where(nullable => nullable.HasValue)
|
||||
.Select(nullable => nullable.Value);
|
||||
|
||||
public static IEnumerable<T> NotNull<T>(this IEnumerable<T> source) where T : class
|
||||
=> source
|
||||
.Where(nullable => nullable != null)
|
||||
.Select(nullable => nullable!);
|
||||
|
||||
public static IEnumerable<T> NotNone<T>(this IEnumerable<Option<T>> source)
|
||||
{
|
||||
foreach (var o in source)
|
||||
{
|
||||
if (o.TryUnwrap(out var v)) { yield return v; }
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<TSuccess> Successes<TSuccess, TFailure>(
|
||||
this IEnumerable<Result<TSuccess, TFailure>> source)
|
||||
=> source
|
||||
.OfType<Success<TSuccess, TFailure>>()
|
||||
.Select(s => s.Value);
|
||||
|
||||
public static IEnumerable<TFailure> Failures<TSuccess, TFailure>(
|
||||
this IEnumerable<Result<TSuccess, TFailure>> source)
|
||||
=> source
|
||||
.OfType<Failure<TSuccess, TFailure>>()
|
||||
.Select(f => f.Error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace Barotrauma.Extensions
|
||||
{
|
||||
public static class PointExtensions
|
||||
{
|
||||
public static Point Multiply(this Point p, float f)
|
||||
{
|
||||
return new Point((int)(p.X * f), (int)(p.Y * f));
|
||||
}
|
||||
|
||||
public static Point Multiply(this Point p, int i)
|
||||
{
|
||||
return new Point(p.X * i, p.Y * i);
|
||||
}
|
||||
|
||||
public static Point Multiply(this Point p, Vector2 v)
|
||||
{
|
||||
return new Point((int)(p.X * v.X), (int)(p.Y * v.Y));
|
||||
}
|
||||
|
||||
public static Point Divide(this Point p, int i)
|
||||
{
|
||||
if (i == 0) { return Point.Zero; }
|
||||
return new Point(p.X / i, p.Y / i);
|
||||
}
|
||||
|
||||
public static Point Divide(this Point p, float f)
|
||||
{
|
||||
if (f == 0) { return Point.Zero; }
|
||||
return new Point((int)(p.X / f), (int)(p.Y / f));
|
||||
}
|
||||
|
||||
public static Point Divide(this Point p, Vector2 v)
|
||||
{
|
||||
if (v.X == 0 || v.Y == 0) { return Point.Zero; }
|
||||
return new Point((int)(p.X / v.X), (int)(p.Y / v.Y));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Negates the X and Y components.
|
||||
/// </summary>
|
||||
public static Point Inverse(this Point p)
|
||||
{
|
||||
return new Point(-p.X, -p.Y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Flips the X and Y components.
|
||||
/// </summary>
|
||||
public static Point Flip(this Point p)
|
||||
{
|
||||
return new Point(p.Y, p.X);
|
||||
}
|
||||
|
||||
public static Point Clamp(this Point p, Point min, Point max)
|
||||
{
|
||||
return new Point(MathHelper.Clamp(p.X, min.X, max.X), MathHelper.Clamp(p.Y, min.Y, max.Y));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace Barotrauma.Extensions
|
||||
{
|
||||
public static class RectangleExtensions
|
||||
{
|
||||
public static Rectangle Multiply(this Rectangle rect, float f)
|
||||
{
|
||||
Vector2 location = new Vector2(rect.X, rect.Y) * f;
|
||||
return new Rectangle(new Point((int)location.X, (int)location.Y), rect.MultiplySize(f));
|
||||
}
|
||||
|
||||
public static Rectangle Divide(this Rectangle rect, float f)
|
||||
{
|
||||
Vector2 location = new Vector2(rect.X, rect.Y) / f;
|
||||
return new Rectangle(new Point((int)location.X, (int)location.Y), rect.DivideSize(f));
|
||||
}
|
||||
|
||||
public static Point DivideSize(this Rectangle rect, float f)
|
||||
{
|
||||
return new Point((int)(rect.Width / f), (int)(rect.Height / f));
|
||||
}
|
||||
|
||||
public static Point DivideSize(this Rectangle rect, Vector2 f)
|
||||
{
|
||||
return new Point((int)(rect.Width / f.X), (int)(rect.Height / f.Y));
|
||||
}
|
||||
|
||||
public static Point MultiplySize(this Rectangle rect, float f)
|
||||
{
|
||||
return new Point((int)(rect.Width * f), (int)(rect.Height * f));
|
||||
}
|
||||
|
||||
public static Point MultiplySize(this Rectangle rect, Vector2 f)
|
||||
{
|
||||
return new Point((int)(rect.Width * f.X), (int)(rect.Height * f.Y));
|
||||
}
|
||||
|
||||
public static Vector2 CalculateRelativeSize(this Rectangle rect, Rectangle relativeRect)
|
||||
{
|
||||
return new Vector2(rect.Width, rect.Height) / new Vector2(relativeRect.Width, relativeRect.Height);
|
||||
}
|
||||
|
||||
public static Rectangle ScaleSize(this Rectangle rect, Rectangle relativeTo)
|
||||
{
|
||||
return rect.ScaleSize(rect.CalculateRelativeSize(relativeTo));
|
||||
}
|
||||
|
||||
public static Rectangle ScaleSize(this Rectangle rect, Vector2 scale)
|
||||
{
|
||||
var size = rect.MultiplySize(scale);
|
||||
return new Rectangle(rect.X, rect.Y, size.X, size.Y);
|
||||
}
|
||||
|
||||
public static Rectangle ScaleSize(this Rectangle rect, float scale)
|
||||
{
|
||||
var size = rect.MultiplySize(scale);
|
||||
return new Rectangle(rect.X, rect.Y, size.X, size.Y);
|
||||
}
|
||||
|
||||
public static bool IntersectsWorld(this Rectangle rect, Rectangle value)
|
||||
{
|
||||
int bottom = rect.Y - rect.Height;
|
||||
int otherBottom = value.Y - value.Height;
|
||||
return value.Left < rect.Right && rect.Left < value.Right &&
|
||||
value.Top > bottom && rect.Top > otherBottom;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Like the XNA method, but treats the y-coordinate so that up is greater and down is lower.
|
||||
/// </summary>
|
||||
public static bool ContainsWorld(this Rectangle rect, Rectangle other)
|
||||
{
|
||||
return
|
||||
(rect.X <= other.X) && ((other.X + other.Width) <= (rect.X + rect.Width)) &&
|
||||
(rect.Y >= other.Y) && ((other.Y - other.Height) >= (rect.Y - rect.Height));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Like the XNA method, but treats the y-coordinate so that up is greater and down is lower.
|
||||
/// </summary>
|
||||
public static bool ContainsWorld(this Rectangle rect, Vector2 point)
|
||||
{
|
||||
return
|
||||
(rect.X <= point.X) && (point.X < (rect.X + rect.Width)) &&
|
||||
(rect.Y >= point.Y) && (point.Y > (rect.Y - rect.Height));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Like the XNA method, but treats the y-coordinate so that up is greater and down is lower.
|
||||
/// </summary>
|
||||
public static bool ContainsWorld(this Rectangle rect, Point point)
|
||||
{
|
||||
return
|
||||
(rect.X <= point.X) && (point.X < (rect.X + rect.Width)) &&
|
||||
(rect.Y >= point.Y) && (point.Y > (rect.Y - rect.Height));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,25 +6,13 @@ namespace Barotrauma
|
||||
{
|
||||
static class StringExtensions
|
||||
{
|
||||
public static string FallbackNullOrEmpty(this string s, string fallback) => string.IsNullOrEmpty(s) ? fallback : s;
|
||||
|
||||
public static bool IsNullOrEmpty([NotNullWhen(returnValue: false)]this string? s) => string.IsNullOrEmpty(s);
|
||||
public static bool IsNullOrWhiteSpace([NotNullWhen(returnValue: false)]this string? s) => string.IsNullOrWhiteSpace(s);
|
||||
|
||||
public static bool IsNullOrEmpty([NotNullWhen(returnValue: false)]this ContentPath? p) => p?.IsPathNullOrEmpty() ?? true;
|
||||
public static bool IsNullOrWhiteSpace([NotNullWhen(returnValue: false)]this ContentPath? p) => p?.IsPathNullOrWhiteSpace() ?? true;
|
||||
|
||||
public static bool IsNullOrEmpty([NotNullWhen(returnValue: false)]this LocalizedString? s) => s is null || string.IsNullOrEmpty(s.Value);
|
||||
public static bool IsNullOrWhiteSpace([NotNullWhen(returnValue: false)]this LocalizedString? s) => s is null || string.IsNullOrWhiteSpace(s.Value);
|
||||
public static bool IsNullOrEmpty([NotNullWhen(returnValue: false)]this RichString? s) => s is null || s.NestedStr.IsNullOrEmpty();
|
||||
public static bool IsNullOrWhiteSpace([NotNullWhen(returnValue: false)]this RichString? s) => s is null || s.NestedStr.IsNullOrWhiteSpace();
|
||||
|
||||
public static string RemoveFromEnd(this string s, string substr, StringComparison stringComparison = StringComparison.Ordinal)
|
||||
=> s.EndsWith(substr, stringComparison) ? s.Substring(0, s.Length - substr.Length) : s;
|
||||
|
||||
public static bool IsTrueString(this string s)
|
||||
=> s.Length == 4
|
||||
&& s[0] is 'T' or 't'
|
||||
&& s[1] is 'R' or 'r'
|
||||
&& s[2] is 'U' or 'u'
|
||||
&& s[3] is 'E' or 'e';
|
||||
}
|
||||
}
|
||||
@@ -1,179 +0,0 @@
|
||||
using System.Globalization;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
public static class StringFormatter
|
||||
{
|
||||
public static string Replace(this string s, string replacement, Func<char, bool> predicate)
|
||||
{
|
||||
var newString = new string[s.Length];
|
||||
for (int i = 0; i < s.Length; i++)
|
||||
{
|
||||
char letter = s[i];
|
||||
string newLetter = letter.ToString();
|
||||
if (predicate(letter))
|
||||
{
|
||||
newLetter = replacement;
|
||||
}
|
||||
newString[i] = newLetter;
|
||||
}
|
||||
return new string(newString.SelectMany(str => str.ToCharArray()).ToArray());
|
||||
}
|
||||
|
||||
public static string Remove(this string s, string substring, StringComparison comparisonType = StringComparison.Ordinal)
|
||||
{
|
||||
return s.Replace(substring, string.Empty, comparisonType);
|
||||
}
|
||||
|
||||
public static string Remove(this string s, Func<char, bool> predicate)
|
||||
{
|
||||
return new string(s.ToCharArray().Where(c => !predicate(c)).ToArray());
|
||||
}
|
||||
|
||||
public static string RemoveWhitespace(this string s)
|
||||
{
|
||||
return s.Remove(c => char.IsWhiteSpace(c));
|
||||
}
|
||||
|
||||
public static string FormatSingleDecimal(this float value)
|
||||
{
|
||||
return value.ToString("F1", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
public static string FormatDoubleDecimal(this float value)
|
||||
{
|
||||
return value.ToString("F2", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
public static string FormatZeroDecimal(this float value)
|
||||
{
|
||||
return value.ToString("F0", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
public static string Format(this float value, int decimalCount)
|
||||
{
|
||||
return value.ToString($"F{decimalCount}", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
public static string FormatSingleDecimal(this Vector2 value)
|
||||
{
|
||||
return $"({value.X.FormatSingleDecimal()}, {value.Y.FormatSingleDecimal()})";
|
||||
}
|
||||
|
||||
public static string FormatSingleDecimal(this Vector3 value)
|
||||
{
|
||||
return $"({value.X.FormatSingleDecimal()}, {value.Y.FormatSingleDecimal()}, {value.Z.FormatSingleDecimal()})";
|
||||
}
|
||||
|
||||
public static string FormatSingleDecimal(this Vector4 value)
|
||||
{
|
||||
return $"({value.X.FormatSingleDecimal()}, {value.Y.FormatSingleDecimal()}, {value.Z.FormatSingleDecimal()}, {value.W.FormatSingleDecimal()})";
|
||||
}
|
||||
|
||||
public static string FormatDoubleDecimal(this Vector2 value)
|
||||
{
|
||||
return $"({value.X.FormatDoubleDecimal()}, {value.Y.FormatDoubleDecimal()})";
|
||||
}
|
||||
|
||||
public static string FormatZeroDecimal(this Vector2 value)
|
||||
{
|
||||
return $"({value.X.FormatZeroDecimal()}, {value.Y.FormatZeroDecimal()})";
|
||||
}
|
||||
|
||||
public static string Format(this Vector2 value, int decimalCount)
|
||||
{
|
||||
return $"({value.X.Format(decimalCount)}, {value.Y.Format(decimalCount)})";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Capitalises the first letter (invariant) and forces the rest to lower case (invariant).
|
||||
/// </summary>
|
||||
public static string CapitaliseFirstInvariant(this string s)
|
||||
{
|
||||
if (string.IsNullOrEmpty(s)) { return string.Empty; }
|
||||
return s.Substring(0, 1).ToUpperInvariant() + s.Substring(1, s.Length - 1).ToLowerInvariant();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds spaces into a CamelCase string.
|
||||
/// </summary>
|
||||
public static string FormatCamelCaseWithSpaces(this string str)
|
||||
{
|
||||
return new string(InsertSpacesBeforeCaps(str).ToArray());
|
||||
IEnumerable<char> InsertSpacesBeforeCaps(IEnumerable<char> input)
|
||||
{
|
||||
int i = 0;
|
||||
int lastChar = input.Count() - 1;
|
||||
foreach (char c in input)
|
||||
{
|
||||
if (char.IsUpper(c) && i > 0)
|
||||
{
|
||||
yield return ' ';
|
||||
}
|
||||
|
||||
yield return c;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static ICollection<string> ParseCommaSeparatedStringToCollection(string input, ICollection<string> texts = null, bool convertToLowerInvariant = true)
|
||||
{
|
||||
if (texts == null)
|
||||
{
|
||||
texts = new HashSet<string>();
|
||||
}
|
||||
else
|
||||
{
|
||||
texts.Clear();
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(input))
|
||||
{
|
||||
foreach (string value in input.Split(','))
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value)) { continue; }
|
||||
if (convertToLowerInvariant)
|
||||
{
|
||||
texts.Add(value.ToLowerInvariant());
|
||||
}
|
||||
else
|
||||
{
|
||||
texts.Add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return texts;
|
||||
}
|
||||
|
||||
public static ICollection<string> ParseSeparatedStringToCollection(string input, string[] separators, ICollection<string> texts = null, bool convertToLowerInvariant = true)
|
||||
{
|
||||
if (texts == null)
|
||||
{
|
||||
texts = new HashSet<string>();
|
||||
}
|
||||
else
|
||||
{
|
||||
texts.Clear();
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(input))
|
||||
{
|
||||
foreach (string value in input.Split(separators, StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
if (convertToLowerInvariant)
|
||||
{
|
||||
texts.Add(value.ToLowerInvariant());
|
||||
}
|
||||
else
|
||||
{
|
||||
texts.Add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return texts;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
namespace Barotrauma.Extensions
|
||||
{
|
||||
public static class StructExtensions
|
||||
{
|
||||
public static bool TryGetValue<T>(this T? nullableStruct, out T nonNullable) where T : struct
|
||||
{
|
||||
if (nullableStruct.HasValue)
|
||||
{
|
||||
nonNullable = nullableStruct.Value;
|
||||
return true;
|
||||
}
|
||||
nonNullable = default(T);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace Barotrauma.Extensions
|
||||
{
|
||||
public static class VectorExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Unity's Angle implementation without the conversion to degrees.
|
||||
/// Returns the angle in radians between two vectors.
|
||||
/// 0 - Pi.
|
||||
/// </summary>
|
||||
public static float Angle(this Vector2 from, Vector2 to)
|
||||
{
|
||||
return (float)Math.Acos(MathHelper.Clamp(Vector2.Dot(Vector2.Normalize(from), Vector2.Normalize(to)), -1f, 1f));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a forward pointing vector based on the rotation (in radians).
|
||||
/// </summary>
|
||||
public static Vector2 Forward(float radians, float length = 1)
|
||||
{
|
||||
return new Vector2((float)Math.Cos(radians), (float)Math.Sin(radians)) * length;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a backward pointing vector based on the rotation (in radians).
|
||||
/// </summary>
|
||||
public static Vector2 Backward(float radians, float length = 1)
|
||||
{
|
||||
return -Forward(radians, length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a forward pointing vector based on the rotation (in radians). TODO: remove when the implications have been neutralized
|
||||
/// </summary>
|
||||
public static Vector2 ForwardFlipped(float radians, float length = 1)
|
||||
{
|
||||
return new Vector2((float)Math.Sin(radians), (float)Math.Cos(radians)) * length;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a backward pointing vector based on the rotation (in radians). TODO: remove when the implications have been neutralized
|
||||
/// </summary>
|
||||
public static Vector2 BackwardFlipped(float radians, float length = 1)
|
||||
{
|
||||
return -ForwardFlipped(radians, length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a normalized perpendicular vector to the right from a forward vector.
|
||||
/// </summary>
|
||||
public static Vector2 Right(this Vector2 forward)
|
||||
{
|
||||
var normV = Vector2.Normalize(forward);
|
||||
return new Vector2(normV.Y, -normV.X);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a normalized perpendicular vector to the left from a forward vector.
|
||||
/// </summary>
|
||||
public static Vector2 Left(this Vector2 forward)
|
||||
{
|
||||
return -forward.Right();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms a vector relative to the given up vector.
|
||||
/// </summary>
|
||||
public static Vector2 TransformVector(this Vector2 v, Vector2 up)
|
||||
{
|
||||
up = Vector2.Normalize(up);
|
||||
return (up * v.Y) + (up.Right() * v.X);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Flips the x and y components.
|
||||
/// </summary>
|
||||
public static Vector2 Flip(this Vector2 v) => new Vector2(v.Y, v.X);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the sum of the x and y components.
|
||||
/// </summary>
|
||||
public static float Combine(this Vector2 v) => v.X + v.Y;
|
||||
|
||||
public static Vector2 Clamp(this Vector2 v, Vector2 min, Vector2 max)
|
||||
{
|
||||
return Vector2.Clamp(v, min, max);
|
||||
}
|
||||
|
||||
public static bool NearlyEquals(this Vector2 v, Vector2 other)
|
||||
{
|
||||
return MathUtils.NearlyEqual(v.X, other.X) && MathUtils.NearlyEqual(v.Y, other.Y);
|
||||
}
|
||||
|
||||
public static Vector2 Pad(this Vector2 v, Vector4 padding)
|
||||
{
|
||||
v.X += padding.X + padding.Z;
|
||||
v.Y += padding.Y + padding.W;
|
||||
return v;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user