Unstable 1.8.4.0
This commit is contained in:
@@ -7,8 +7,13 @@ namespace Barotrauma.Extensions
|
||||
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));
|
||||
new Color(color.R, color.G, color.B, MultiplyComponent(color.A, value)) :
|
||||
new Color(MultiplyComponent(color.R, value), MultiplyComponent(color.G, value), MultiplyComponent(color.B, value), MultiplyComponent(color.A, value));
|
||||
|
||||
static byte MultiplyComponent(float colorComponent, float multiplier)
|
||||
{
|
||||
return (byte)MathHelper.Clamp(colorComponent * multiplier, 0.0f, 255.0f);
|
||||
}
|
||||
}
|
||||
|
||||
public static Color Multiply(this Color thisColor, Color color)
|
||||
|
||||
@@ -1,17 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
// NOTE: We should use struct in addition to Enum in all the type constraints (at the end of the method signatures), as it
|
||||
// tells the compiler that we're only ever using value types, which enums always are anyway.
|
||||
// This avoids a lot of allocations caused by the compiler preparing for anything, which in turn happens because despite
|
||||
// how it works in practice, Enum is counted as a reference type in C#... for historical reasons.
|
||||
|
||||
// We use the (int)(object) cast because generic types can't be cast directly to int, so we box into object and unbox into int instead.
|
||||
// It avoids some memory allocations that Convert.ToInt32() seems to do.
|
||||
// NOTE: This should work fine as long as the enum values stay within - to + 2^31, so let's not use uint or long for them.
|
||||
|
||||
namespace Barotrauma.Extensions
|
||||
{
|
||||
public static class EnumExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Enum.HasFlag() checks if all flags matches. This method checks if any of them matches.
|
||||
/// Enum.HasFlag() checks if all flags matches. This method checks if any of them matches. It also avoids boxing allocations that the built-in version might still sometimes cause.
|
||||
/// E.g. when myEnum = SomeEnum.First | SomeEnum.Second, myEnum.HasFlag(SomeEnum.First | SomeEnum.Third) returns false, because not all of the flags match, but HasAnyFlag(SomeEnum.First | SomeEnum.Third) returns true, because some of the flags match.
|
||||
/// </summary>
|
||||
public static bool HasAnyFlag<T>(this T type, T value) where T : Enum
|
||||
public static bool HasAnyFlag<T>(this T type, T value) where T : struct, Enum
|
||||
{
|
||||
int typeValue = Convert.ToInt32(type);
|
||||
int flagValue = Convert.ToInt32(value);
|
||||
int typeValue = (int)(object)type;
|
||||
int flagValue = (int)(object)value;
|
||||
return (typeValue & flagValue) != 0;
|
||||
}
|
||||
|
||||
@@ -19,10 +29,10 @@ namespace Barotrauma.Extensions
|
||||
/// Adds a flag value to an enum.
|
||||
/// Note that enums are value types, so you need to use the value returned from this method.
|
||||
/// </summary>
|
||||
public static T AddFlag<T>(this T @enum, T flag) where T : Enum
|
||||
public static T AddFlag<T>(this T @enum, T flag) where T : struct, Enum
|
||||
{
|
||||
int enumValue = Convert.ToInt32(@enum);
|
||||
int flagValue = Convert.ToInt32(flag);
|
||||
int enumValue = (int)(object)@enum;
|
||||
int flagValue = (int)(object)flag;
|
||||
return (T)(object)(enumValue | flagValue);
|
||||
}
|
||||
|
||||
@@ -30,11 +40,19 @@ namespace Barotrauma.Extensions
|
||||
/// Removes a flag value from an enum.
|
||||
/// Note that enums are value types, so you need to use the value returned from this method.
|
||||
/// </summary>
|
||||
public static T RemoveFlag<T>(this T @enum, T flag) where T : Enum
|
||||
public static T RemoveFlag<T>(this T @enum, T flag) where T : struct, Enum
|
||||
{
|
||||
int enumValue = Convert.ToInt32(@enum);
|
||||
int flagValue = Convert.ToInt32(flag);
|
||||
int enumValue = (int)(object)@enum;
|
||||
int flagValue = (int)(object)flag;
|
||||
return (T)(object)(enumValue & ~flagValue);
|
||||
}
|
||||
|
||||
public static IEnumerable<T> GetIndividualFlags<T>(T flagsEnum) where T : struct, Enum
|
||||
{
|
||||
foreach (T value in Enum.GetValues(typeof(T)))
|
||||
{
|
||||
if (flagsEnum.HasAnyFlag(value)) { yield return value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -24,6 +24,9 @@ public sealed class EpicAccountId : AccountId
|
||||
public new static Option<EpicAccountId> Parse(string str)
|
||||
{
|
||||
if (str.IsNullOrWhiteSpace()) { return Option.None; }
|
||||
//according to the documentation, this is the maximum length of the ID
|
||||
const int MaxEpicAccountIDLength = 32 + 1;
|
||||
if (str.Length > MaxEpicAccountIDLength + prefix.Length) { return Option.None; }
|
||||
if (str.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) { str = str[prefix.Length..]; }
|
||||
if (!str.IsHexString()) { return Option.None; }
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
@@ -140,7 +141,25 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
public static Identifier[] ToIdentifiers(this string[] strings)
|
||||
=> ((IEnumerable<string>)strings).ToIdentifiers().ToArray();
|
||||
=> strings.AsEnumerable().ToIdentifiers().ToArray();
|
||||
|
||||
/// <summary>
|
||||
/// Parses identifiers from a comma separated string.
|
||||
/// </summary>
|
||||
public static IEnumerable<Identifier> ToIdentifiers(this string tagsString, string separator = ",")
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(tagsString))
|
||||
{
|
||||
return Enumerable.Empty<Identifier>();
|
||||
}
|
||||
return tagsString.Split(separator, StringSplitOptions.TrimEntries).AsEnumerable().ToIdentifiers();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses a comma separated string from a collection of identifier.
|
||||
/// </summary>
|
||||
public static string ConvertToString(this IEnumerable<Identifier> tags, string separator = ",")
|
||||
=> string.Join(separator, tags);
|
||||
|
||||
public static Identifier ToIdentifier(this string? s)
|
||||
{
|
||||
|
||||
@@ -375,7 +375,19 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the point where the line segment between a1 and a2 intersects the rectangle. Note that the rectangle's y-coordinate is handled so that up is lower and bottom is higher (the way rectangles work by default in XNA).
|
||||
/// </summary>
|
||||
public static bool GetLineRectangleIntersection(Vector2 a1, Vector2 a2, Rectangle rect, out Vector2 intersection)
|
||||
{
|
||||
rect.Y += rect.Height;
|
||||
return GetLineWorldRectangleIntersection(a1, a2, rect, out intersection);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the point where the line segment between a1 and a2 intersects the rectangle. Note that the rectangle's y-coordinate is handled so that up is greater and down is lower (the way e.g. MapEntity rects are defined).
|
||||
/// </summary>
|
||||
public static bool GetLineWorldRectangleIntersection(Vector2 a1, Vector2 a2, Rectangle rect, out Vector2 intersection)
|
||||
{
|
||||
if (GetAxisAlignedLineIntersection(a1, a2,
|
||||
new Vector2(rect.X, rect.Y),
|
||||
@@ -678,7 +690,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// divide a convex hull into triangles
|
||||
/// Divide a convex hull into triangles
|
||||
/// </summary>
|
||||
/// <returns>List of triangle vertices (sorted counter-clockwise)</returns>
|
||||
public static List<Vector2[]> TriangulateConvexHull(List<Vector2> vertices, Vector2 center)
|
||||
@@ -1100,6 +1112,52 @@ namespace Barotrauma
|
||||
while (val > po2) { po2 <<= 1; }
|
||||
return po2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resizes an array of vectors to a different size. Uses bilinear interpolation to "scale" the values to the size of the new array:
|
||||
/// for instance, an array such as "1, 0" would become "1, 0.5, 0" when the width is scaled from 2 to 3.
|
||||
/// </summary>
|
||||
public static Vector2[,] ResizeVector2Array(Vector2[,] sourceArray, int newWidth, int newHeight)
|
||||
{
|
||||
if (newWidth < 1)
|
||||
{
|
||||
throw new ArgumentException("Width must be larger than zero.", nameof(newWidth));
|
||||
}
|
||||
if (newHeight < 1)
|
||||
{
|
||||
throw new ArgumentException("Height must be larger than zero.", nameof(newHeight));
|
||||
}
|
||||
|
||||
var destinationArray = new Vector2[newWidth, newHeight];
|
||||
int oldWidth = sourceArray.GetLength(0), oldHeight = sourceArray.GetLength(1);
|
||||
|
||||
for (int x = 0; x < newWidth; x++)
|
||||
{
|
||||
for (int y = 0; y < newHeight; y++)
|
||||
{
|
||||
// Calculate the position in the original array
|
||||
float sourceX = oldWidth == 1 ? 0 : (x / (float)(newWidth - 1)) * (oldWidth - 1);
|
||||
float sourceY = oldHeight == 1 ? 0 : (y / (float)(newHeight - 1)) * (oldHeight - 1);
|
||||
|
||||
// Find the indices of the surrounding points
|
||||
int startIndexX = (int)Math.Floor(sourceX);
|
||||
int endIndexX = Math.Min(startIndexX + 1, oldWidth - 1);
|
||||
int startIndexY = (int)Math.Floor(sourceY);
|
||||
int endIndexY = Math.Min(startIndexY + 1, oldHeight - 1);
|
||||
|
||||
// Calculate interpolation weights
|
||||
float tx = sourceX - startIndexX;
|
||||
float ty = sourceY - startIndexY;
|
||||
|
||||
// Perform bilinear interpolation
|
||||
Vector2 top = Vector2.Lerp(sourceArray[startIndexX, startIndexY], sourceArray[endIndexX, startIndexY], tx);
|
||||
Vector2 bottom = Vector2.Lerp(sourceArray[startIndexX, endIndexY], sourceArray[endIndexX, endIndexY], tx);
|
||||
destinationArray[x, y] = Vector2.Lerp(top, bottom, ty);
|
||||
}
|
||||
}
|
||||
|
||||
return destinationArray;
|
||||
}
|
||||
}
|
||||
|
||||
public class CompareCW : IComparer<Vector2>
|
||||
@@ -1156,4 +1214,5 @@ namespace Barotrauma
|
||||
return -CompareCW.Compare(a, b, center);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -113,10 +113,9 @@ namespace Barotrauma
|
||||
/// Gets a type by its name, with backwards compatibility for types that have been renamed.
|
||||
/// <see cref="TypePreviouslyKnownAs"/>
|
||||
/// </summary>
|
||||
public static Type? GetTypeWithBackwardsCompatibility(string nameSpace, string typeName, bool throwOnError, bool ignoreCase)
|
||||
public static Type? GetTypeWithBackwardsCompatibility(Assembly assembly, string nameSpace, string typeName, bool throwOnError, bool ignoreCase)
|
||||
{
|
||||
if (Assembly.GetEntryAssembly() is not { } entryAssembly) { return null; }
|
||||
var types = entryAssembly
|
||||
var types = assembly
|
||||
.GetTypes()
|
||||
.Where(t => NameMatches(t.Namespace, nameSpace, ignoreCase));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user