// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace FlaxEngine.Utilities
{
///
/// Collection of various extension methods.
///
public static partial class Extensions
{
///
/// Creates deep clone for a class if all members of this class are marked as serializable (uses Json serialization).
///
/// The input instance of an object.
/// The instance type of an object.
/// Returns new object of provided class.
public static T DeepClone(this T instance)
where T : new()
{
var json = Json.JsonSerializer.Serialize(instance);
return Json.JsonSerializer.Deserialize(json);
}
///
/// Creates raw clone for a structure using memory copy. Valid only for value types.
///
/// The input instance of an object.
/// The instance type of an object.
/// Returns new object of provided structure.
public static T RawClone(this T instance)
{
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(instance));
try
{
Marshal.StructureToPtr(instance, ptr, false);
return (T)Marshal.PtrToStructure(ptr, instance.GetType());
}
finally
{
Marshal.FreeHGlobal(ptr);
}
}
///
/// Splits string into lines
///
/// Text to split
/// True if remove empty lines, otherwise keep them
/// Array with all lines
public static string[] GetLines(this string str, bool removeEmptyLines = false)
{
return str.Split(new[]
{
"\r\n",
"\r",
"\n"
}, removeEmptyLines ? StringSplitOptions.RemoveEmptyEntries : StringSplitOptions.None);
}
///
/// Gets a random double.
///
/// The random.
/// The maximum value
/// A random double
public static double NextDouble(this Random random, double maxValue)
{
return random.NextDouble() * maxValue;
}
///
/// Gets a random double.
///
/// The random.
/// The minimum value
/// The maximum value
/// A random double
public static double NextDouble(this Random random, double minValue, double maxValue)
{
return random.NextDouble() * (maxValue - minValue) + minValue;
}
///
/// Gets a random float.
///
/// The random.
/// A random float
public static float NextFloat(this Random random)
{
return (float)random.NextDouble();
}
///
/// Gets a random float.
///
/// The random.
/// The maximum value
/// A random float
public static float NextFloat(this Random random, float maxValue)
{
return (float)random.NextDouble() * maxValue;
}
///
/// Gets a random float.
///
/// The random.
/// The minimum value
/// The maximum value
///
public static float NextFloat(this Random random, float minValue, float maxValue)
{
return (float)random.NextDouble() * (maxValue - minValue) + minValue;
}
///
/// Gets a random Color.
///
/// The random.
///
public static Color NextColor(this Random random)
{
return new Color(NextFloat(random, 1.0f),
NextFloat(random, 1.0f),
NextFloat(random, 1.0f),
NextFloat(random, 1.0f));
}
///
/// Gets a random Vector2 with components in range [0;1].
///
/// The random.
///
public static Vector2 NextVector2(this Random random)
{
return new Vector2(NextFloat(random, 1.0f),
NextFloat(random, 1.0f));
}
///
/// Gets a random Vector3 with components in range [0;1].
///
/// The random.
///
public static Vector3 NextVector3(this Random random)
{
return new Vector3(NextFloat(random, 1.0f),
NextFloat(random, 1.0f),
NextFloat(random, 1.0f));
}
///
/// Gets a random Vector4 with components in range [0;1].
///
/// The random.
///
public static Vector4 NextVector4(this Random random)
{
return new Vector4(NextFloat(random, 1.0f),
NextFloat(random, 1.0f),
NextFloat(random, 1.0f),
NextFloat(random, 1.0f));
}
///
/// Gets a random Quaternion.
///
/// The random.
///
public static Quaternion NextQuaternion(this Random random)
{
return Quaternion.Euler(NextFloat(random, -180, 180),
NextFloat(random, -180, 180),
NextFloat(random, -180, 180));
}
///
/// Gets a random 64-bit signed integer value.
///
/// The random.
///
internal static long NextLong(this Random random)
{
var numArray = new byte[8];
random.NextBytes(numArray);
return (long)(BitConverter.ToUInt64(numArray, 0) & 9223372036854775807L);
}
///
/// Generates a random normalized 2D direction vector.
///
/// An instance of .
/// A random normalized 2D direction vector.
public static Vector2 NextDirection2D(this Random random)
{
return Vector2.Normalize(new Vector2((float)random.NextDouble(), (float)random.NextDouble()));
}
///
/// Generates a random normalized 3D direction vector.
///
/// An instance of .
/// A random normalized 3D direction vector.
public static Vector3 NextDirection3D(this Random random)
{
return Vector3.Normalize(new Vector3((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble()));
}
///
/// Generates a random point in a circle of a given radius.
///
/// An instance of .
/// Radius of circle. Default 1.0f.
/// A random point in a circle of a given radius.
public static Vector2 PointInACircle(this Random random, float radius = 1.0f)
{
var randomRadius = (float)random.NextDouble() * radius;
return new Vector2
{
X = (float)Math.Cos(random.NextDouble()) * randomRadius,
Y = (float)Math.Sin(random.NextDouble()) * randomRadius,
};
}
///
/// Adds the elements of the specified collection to the end of the .
///
/// The type of elements in the collection.
/// The to add items to.
/// The collection whose elements should be added to the end of the . It can contain elements that are , if type is a reference type.
/// If or are .
public static void AddRange(this ICollection destination, IEnumerable collection)
{
if (destination == null)
{
throw new ArgumentNullException(nameof(destination));
}
if (collection == null)
{
throw new ArgumentNullException(nameof(collection));
}
foreach (var item in collection)
{
destination.Add(item);
}
}
///
/// Enqueues the elements of the specified collection to the .
///
/// The type of elements in the collection.
/// The to add items to.
/// The collection whose elements should be added to the . It can contain elements that are , if type is a reference type.
/// If or are .
public static void EnqueueRange(this Queue queue, IEnumerable collection)
{
if (queue == null)
{
throw new ArgumentNullException(nameof(queue));
}
if (collection == null)
{
throw new ArgumentNullException(nameof(collection));
}
foreach (var item in collection)
{
queue.Enqueue(item);
}
}
///
/// Pushes the elements of the specified collection to the .
///
/// The type of elements in the collection.
/// The to add items to.
/// The collection whose elements should be pushed on to the . It can contain elements that are , if type is a reference type.
/// If or are .
public static void PushRange(this Stack stack, IEnumerable collection)
{
if (stack == null)
{
throw new ArgumentNullException(nameof(stack));
}
if (collection == null)
{
throw new ArgumentNullException(nameof(collection));
}
foreach (var item in collection)
{
stack.Push(item);
}
}
///
/// Performs the specified action on each element of the .
///
/// The type of the elements of the input sequence.
/// The sequence of elements to execute the .
/// The delegate to perform on each element of the 1.
/// or is .
public static void ForEach(this IEnumerable source, Action action)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
if (action == null)
{
throw new ArgumentNullException(nameof(action));
}
foreach (var item in source)
{
action(item);
}
}
///
/// Chooses a random item from the collection.
///
/// The type of the elements of the input sequence.
/// An instance of .
/// Collection to choose item from.
/// A random item from collection
/// If the random argument is null.
/// If the collection is null.
public static T Choose(this Random random, IList collection)
{
if (random == null)
{
throw new ArgumentNullException(nameof(random));
}
if (collection == null)
{
throw new ArgumentNullException(nameof(collection));
}
return collection[random.Next(collection.Count)];
}
///
/// Chooses a random item.
///
/// The type of the elements of the input sequence.
/// An instance of .
/// Collection to choose item from.
/// A random item from collection
/// If the random is null.
/// If the collection is null.
public static T Choose(this Random random, params T[] collection)
{
if (random == null)
{
throw new ArgumentNullException(nameof(random));
}
if (collection == null)
{
throw new ArgumentNullException(nameof(collection));
}
return collection[random.Next(collection.Length)];
}
///
/// Shuffles the collection in place.
///
/// The type of the elements of the input sequence.
/// An instance of .
/// Collection to shuffle.
/// If the random argument is null.
/// If the random collection is null.
public static void Shuffle(this Random random, IList collection)
{
if (random == null)
{
throw new ArgumentNullException(nameof(random));
}
if (collection == null)
{
throw new ArgumentNullException(nameof(collection));
}
int n = collection.Count;
while (n > 1)
{
n--;
int k = random.Next(n + 1);
T value = collection[k];
collection[k] = collection[n];
collection[n] = value;
}
}
}
}