Singularity/Assets/Plugins/crosstales/Common/Scripts/ExtensionMethods.cs

2711 lines
93 KiB
C#
Raw Permalink Normal View History

2024-05-06 14:45:45 -04:00
using UnityEngine;
using System.Linq;
namespace Crosstales
{
/// <summary>Various extension methods.</summary>
public static class ExtensionMethods
{
#region Variables
private static readonly Vector3 FLAT_VECTOR = new Vector3(1, 0, 1);
#endregion
#region Strings
/// <summary>
/// Extension method for strings.
/// Converts a string to title case (first letter uppercase).
/// </summary>
/// <param name="str">String-instance.</param>
/// <returns>Converted string in title case.</returns>
public static string CTToTitleCase(this string str)
{
if (str == null)
return str;
#if UNITY_WSA || UNITY_XBOXONE
return toTitleCase(str);
#else
return System.Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(str.ToLower());
#endif
}
#if UNITY_WSA || UNITY_XBOXONE
/// <summary>
/// Converts to title case: each word starts with an upper case.
/// </summary>
private static string toTitleCase(string str)
{
if (str.Length == 0)
return str;
System.Text.StringBuilder result = new System.Text.StringBuilder(str);
result[0] = char.ToUpper(result[0]);
for (int ii = 1; ii < result.Length; ii++)
{
if (char.IsWhiteSpace(result[ii - 1]))
result[ii] = char.ToUpper(result[ii]);
else
result[ii] = char.ToLower(result[ii]);
}
return result.ToString();
}
#endif
/// <summary>
/// Extension method for strings.
/// Reverses a string.
/// </summary>
/// <param name="str">String-instance.</param>
/// <returns>Reversed string.</returns>
public static string CTReverse(this string str)
{
if (str == null)
return str;
char[] charArray = str.ToCharArray();
System.Array.Reverse(charArray);
return new string(charArray);
}
/// <summary>
/// Extension method for strings.
/// Default: case insensitive 'Replace'.
/// </summary>
/// <param name="str">String-instance.</param>
/// <param name="oldString">String to replace.</param>
/// <param name="newString">New replacement string.</param>
/// <param name="comp">StringComparison-method (optional, default: StringComparison.OrdinalIgnoreCase)</param>
/// <returns>Replaced string.</returns>
public static string CTReplace(this string str, string oldString, string newString, System.StringComparison comp = System.StringComparison.OrdinalIgnoreCase)
{
if (str == null)
return str;
if (oldString == null)
return str;
if (newString == null)
return str;
bool matchFound;
do
{
int index = str.IndexOf(oldString, comp);
matchFound = index >= 0;
if (matchFound)
{
str = str.Remove(index, oldString.Length);
str = str.Insert(index, newString);
}
} while (matchFound);
return str;
}
/// <summary>
/// Extension method for strings.
/// Removes characters from a string
/// </summary>
/// <param name="str">String-instance.</param>
/// <param name="removeChars">Characters to remove.</param>
/// <returns>String without the given characters.</returns>
public static string CTRemoveChars(this string str, params char[] removeChars)
{
if (str == null)
return str;
if (removeChars == null)
return str;
return removeChars.Aggregate(str, (current, rmChar) => current.Replace($"{rmChar}", string.Empty));
}
/// <summary>
/// Extension method for strings.
/// Default: case insensitive 'Equals'.
/// </summary>
/// <param name="str">String-instance.</param>
/// <param name="toCheck">String to check.</param>
/// <param name="comp">StringComparison-method (optional, default: StringComparison.OrdinalIgnoreCase)</param>
/// <returns>True if the string contains the given string.</returns>
public static bool CTEquals(this string str, string toCheck, System.StringComparison comp = System.StringComparison.OrdinalIgnoreCase)
{
return str?.Equals(toCheck, comp) == true;
//if (toCheck == null)
// throw new System.ArgumentNullException("toCheck");
}
/// <summary>
/// Extension method for strings.
/// Default: case insensitive 'Contains'.
/// </summary>
/// <param name="str">String-instance.</param>
/// <param name="toCheck">String to check.</param>
/// <param name="comp">StringComparison-method (optional, default: StringComparison.OrdinalIgnoreCase)</param>
/// <returns>True if the string contains the given string.</returns>
public static bool CTContains(this string str, string toCheck, System.StringComparison comp = System.StringComparison.OrdinalIgnoreCase)
{
return str?.IndexOf(toCheck, comp) >= 0;
}
/// <summary>
/// Extension method for strings.
/// Contains any given string.
/// </summary>
/// <param name="str">String-instance.</param>
/// <param name="searchTerms">Search terms separated by the given split-character.</param>
/// <param name="splitChar">Split-character (optional, default: ' ')</param>
/// <returns>True if the string contains any parts of the given string.</returns>
public static bool CTContainsAny(this string str, string searchTerms, char splitChar = ' ')
{
if (str == null)
return false;
if (string.IsNullOrEmpty(searchTerms))
return true;
char[] split = { splitChar };
return searchTerms.Split(split, System.StringSplitOptions.RemoveEmptyEntries).Any(searchTerm => str.CTContains(searchTerm));
}
/// <summary>
/// Extension method for strings.
/// Contains all given strings.
/// </summary>
/// <param name="str">String-instance.</param>
/// <param name="searchTerms">Search terms separated by the given split-character.</param>
/// <param name="splitChar">Split-character (optional, default: ' ')</param>
/// <returns>True if the string contains all parts of the given string.</returns>
public static bool CTContainsAll(this string str, string searchTerms, char splitChar = ' ')
{
if (str == null)
return false;
if (string.IsNullOrEmpty(searchTerms))
return true;
char[] split = { splitChar };
return searchTerms.Split(split, System.StringSplitOptions.RemoveEmptyEntries).All(searchTerm => str.CTContains(searchTerm));
}
/// <summary>
/// Extension method for strings.
/// Replaces new lines with a replacement string pattern.
/// </summary>
/// <param name="str">String-instance.</param>
/// <param name="replacement">Replacement string pattern (optional, default: "#nl#").</param>
/// <param name="newLine">New line string (optional, default: System.Environment.NewLine).</param>
/// <returns>Replaced string without new lines.</returns>
public static string CTRemoveNewLines(this string str, string replacement = "#nl#", string newLine = null)
{
return str?.Replace(string.IsNullOrEmpty(newLine) ? System.Environment.NewLine : newLine, replacement);
}
/// <summary>
/// Extension method for strings.
/// Replaces a given string pattern with new lines in a string.
/// </summary>
/// <param name="str">String-instance.</param>
/// <param name="replacement">Replacement string pattern (optional, default: "#nl#").</param>
/// <param name="newLine">New line string (optional, default: System.Environment.NewLine).</param>
/// <returns>Replaced string with new lines.</returns>
public static string CTAddNewLines(this string str, string replacement = "#nl#", string newLine = null)
{
return str?.CTReplace(replacement, string.IsNullOrEmpty(newLine) ? System.Environment.NewLine : newLine);
}
/// <summary>
/// Extension method for strings.
/// Checks if the string is numeric.
/// </summary>
/// <param name="str">String-instance.</param>
/// <returns>True if the string is numeric.</returns>
[System.Obsolete("Please use 'CTIsNumeric' instead.")]
public static bool CTisNumeric(this string str)
{
return CTIsNumeric(str);
}
/// <summary>
/// Extension method for strings.
/// Checks if the string is numeric.
/// </summary>
/// <param name="str">String-instance.</param>
/// <returns>True if the string is numeric.</returns>
public static bool CTIsNumeric(this string str)
{
return str != null && double.TryParse(str, out double output);
}
/// <summary>
/// Extension method for strings.
/// Checks if the string is integer.
/// </summary>
/// <param name="str">String-instance.</param>
/// <returns>True if the string is integer.</returns>
[System.Obsolete("Please use 'CTIsInteger' instead.")]
public static bool CTisInteger(this string str)
{
return CTIsInteger(str);
}
/// <summary>
/// Extension method for strings.
/// Checks if the string is integer.
/// </summary>
/// <param name="str">String-instance.</param>
/// <returns>True if the string is integer.</returns>
public static bool CTIsInteger(this string str)
{
if (str == null)
return false;
return !str.Contains(".") && long.TryParse(str, out long output);
}
/// <summary>
/// Extension method for strings.
/// Checks if the string is an email address.
/// </summary>
/// <param name="str">String-instance.</param>
/// <returns>True if the string is an email address.</returns>
[System.Obsolete("Please use 'CTIsEmail' instead.")]
public static bool CTisEmail(this string str)
{
return CTIsEmail(str);
}
/// <summary>
/// Extension method for strings.
/// Checks if the string is an email address.
/// </summary>
/// <param name="str">String-instance.</param>
/// <returns>True if the string is an email address.</returns>
public static bool CTIsEmail(this string str)
{
return str != null && Crosstales.Common.Util.BaseConstants.REGEX_EMAIL.IsMatch(str);
}
/// <summary>
/// Extension method for strings.
/// Checks if the string is a website address.
/// </summary>
/// <param name="str">String-instance.</param>
/// <returns>True if the string is a website address.</returns>
[System.Obsolete("Please use 'CTIsWebsite' instead.")]
public static bool CTisWebsite(this string str)
{
return CTIsWebsite(str);
}
/// <summary>
/// Extension method for strings.
/// Checks if the string is a website address.
/// </summary>
/// <param name="str">String-instance.</param>
/// <returns>True if the string is a website address.</returns>
public static bool CTIsWebsite(this string str)
{
return str != null && Crosstales.Common.Util.BaseConstants.REGEX_URL_WEB.IsMatch(str);
}
/// <summary>
/// Extension method for strings.
/// Checks if the string is a creditcard.
/// </summary>
/// <param name="str">String-instance.</param>
/// <returns>True if the string is a creditcard.</returns>
[System.Obsolete("Please use 'CTIsCreditcard' instead.")]
public static bool CTisCreditcard(this string str)
{
return CTIsCreditcard(str);
}
/// <summary>
/// Extension method for strings.
/// Checks if the string is a creditcard.
/// </summary>
/// <param name="str">String-instance.</param>
/// <returns>True if the string is a creditcard.</returns>
public static bool CTIsCreditcard(this string str)
{
return str != null && Crosstales.Common.Util.BaseConstants.REGEX_CREDITCARD.IsMatch(str);
}
/// <summary>
/// Extension method for strings.
/// Checks if the string is an IPv4 address.
/// </summary>
/// <param name="str">String-instance.</param>
/// <returns>True if the string is an IPv4 address.</returns>
[System.Obsolete("Please use 'CTIsIPv4' instead.")]
public static bool CTisIPv4(this string str)
{
return CTIsIPv4(str);
}
/// <summary>
/// Extension method for strings.
/// Checks if the string is an IPv4 address.
/// </summary>
/// <param name="str">String-instance.</param>
/// <returns>True if the string is an IPv4 address.</returns>
public static bool CTIsIPv4(this string str)
{
return str != null && Crosstales.Common.Util.NetworkHelper.isIPv4(str);
}
/// <summary>
/// Extension method for strings.
/// Checks if the string is alphanumeric.
/// </summary>
/// <param name="str">String-instance.</param>
/// <returns>True if the string is alphanumeric.</returns>
[System.Obsolete("Please use 'CTIsAlphanumeric' instead.")]
public static bool CTisAlphanumeric(this string str)
{
return CTIsAlphanumeric(str);
}
/// <summary>
/// Extension method for strings.
/// Checks if the string is alphanumeric.
/// </summary>
/// <param name="str">String-instance.</param>
/// <returns>True if the string is alphanumeric.</returns>
public static bool CTIsAlphanumeric(this string str)
{
return str != null && Crosstales.Common.Util.BaseConstants.REGEX_ALPHANUMERIC.IsMatch(str);
}
/// <summary>
/// Extension method for strings.
/// Checks if the string has line endings.
/// </summary>
/// <param name="str">String-instance.</param>
/// <returns>True if the string has line endings.</returns>
[System.Obsolete("Please use 'CTHasLineEndings' instead.")]
public static bool CThasLineEndings(this string str)
{
return CTHasLineEndings(str);
}
/// <summary>
/// Extension method for strings.
/// Checks if the string has line endings.
/// </summary>
/// <param name="str">String-instance.</param>
/// <returns>True if the string has line endings.</returns>
public static bool CTHasLineEndings(this string str)
{
return str != null && Crosstales.Common.Util.BaseConstants.REGEX_LINEENDINGS.IsMatch(str);
}
/// <summary>
/// Extension method for strings.
/// Checks if the string has invalid characters.
/// </summary>
/// <param name="str">String-instance.</param>
/// <returns>True if the string has invalid characters.</returns>
[System.Obsolete("Please use 'CTHasInvalidChars' instead.")]
public static bool CThasInvalidChars(this string str)
{
return CTHasInvalidChars(str);
}
/// <summary>
/// Extension method for strings.
/// Checks if the string has invalid characters.
/// </summary>
/// <param name="str">String-instance.</param>
/// <returns>True if the string has invalid characters.</returns>
public static bool CTHasInvalidChars(this string str)
{
return str != null && Crosstales.Common.Util.BaseConstants.REGEX_INVALID_CHARS.IsMatch(str);
}
/// <summary>
/// Extension method for strings.
/// Checks if the string starts with another string.
/// </summary>
/// <param name="str">String-instance.</param>
/// <param name="toCheck">String to check.</param>
/// <param name="comp">StringComparison-method (optional, default: StringComparison.OrdinalIgnoreCase)</param>
/// <returns>True if the string is integer.</returns>
public static bool CTStartsWith(this string str, string toCheck, System.StringComparison comp = System.StringComparison.OrdinalIgnoreCase)
{
if (str == null)
return false;
return string.IsNullOrEmpty(toCheck) || str.StartsWith(toCheck, comp);
}
/// <summary>
/// Extension method for strings.
/// Checks if the string ends with another string.
/// </summary>
/// <param name="str">String-instance.</param>
/// <param name="toCheck">String to check.</param>
/// <param name="comp">StringComparison-method (optional, default: StringComparison.OrdinalIgnoreCase)</param>
/// <returns>True if the string is integer.</returns>
public static bool CTEndsWith(this string str, string toCheck, System.StringComparison comp = System.StringComparison.OrdinalIgnoreCase)
{
if (str == null)
return false;
return string.IsNullOrEmpty(toCheck) || str.EndsWith(toCheck, comp);
}
/// <summary>
/// Extension method for strings.
/// Returns the index of the last occurence of a given string.
/// </summary>
/// <param name="str">String-instance.</param>
/// <param name="toCheck">String for the index.</param>
/// <param name="comp">StringComparison-method (optional, default: StringComparison.OrdinalIgnoreCase)</param>
/// <returns>The index of the last occurence of the given string if the string is integer.</returns>
public static int CTLastIndexOf(this string str, string toCheck, System.StringComparison comp = System.StringComparison.OrdinalIgnoreCase)
{
if (str == null)
throw new System.ArgumentNullException(nameof(str));
return string.IsNullOrEmpty(toCheck) ? 0 : str.LastIndexOf(toCheck, comp);
}
/// <summary>
/// Extension method for strings.
/// Returns the index of the first occurence of a given string.
/// </summary>
/// <param name="str">String-instance.</param>
/// <param name="toCheck">String for the index.</param>
/// <param name="comp">StringComparison-method (optional, default: StringComparison.OrdinalIgnoreCase)</param>
/// <returns>The index of the first occurence of the given string if the string is integer.</returns>
public static int CTIndexOf(this string str, string toCheck, System.StringComparison comp = System.StringComparison.OrdinalIgnoreCase)
{
if (str == null)
throw new System.ArgumentNullException(nameof(str));
return string.IsNullOrEmpty(toCheck) ? 0 : str.IndexOf(toCheck, comp);
}
/// <summary>
/// Extension method for strings.
/// Returns the index of the first occurence of a given string.
/// </summary>
/// <param name="str">String-instance.</param>
/// <param name="toCheck">String for the index.</param>
/// <param name="startIndex">Start index for the check.</param>
/// <param name="comp">StringComparison-method (optional, default: StringComparison.OrdinalIgnoreCase)</param>
/// <returns>The index of the first occurence of the given string if the string is integer.</returns>
public static int CTIndexOf(this string str, string toCheck, int startIndex, System.StringComparison comp = System.StringComparison.OrdinalIgnoreCase)
{
if (str == null)
throw new System.ArgumentNullException(nameof(str));
return string.IsNullOrEmpty(toCheck) ? 0 : str.IndexOf(toCheck, startIndex, comp);
}
/// <summary>
/// Extension method for strings.
/// Converts the value of a string to a Base64-string.
/// </summary>
/// <param name="str">Input string.</param>
/// <param name="encoding">Encoding of the string (optional, default: UTF8).</param>
/// <returns>String value as converted Base64-string.</returns>
public static string CTToBase64(this string str, System.Text.Encoding encoding = null)
{
if (str == null)
return null;
System.Text.Encoding _encoding = System.Text.Encoding.UTF8;
if (encoding != null)
_encoding = encoding;
return _encoding.GetBytes(str).CTToBase64();
}
/// <summary>
/// Extension method for strings.
/// Converts the value of a Base64-string to a string.
/// </summary>
/// <param name="str">Input Base64-string.</param>
/// <param name="encoding">Encoding of the string (optional, default: UTF8).</param>
/// <returns>Base64-string value as converted string.</returns>
public static string CTFromBase64(this string str, System.Text.Encoding encoding = null)
{
if (str == null)
return null;
System.Text.Encoding _encoding = System.Text.Encoding.UTF8;
if (encoding != null)
_encoding = encoding;
return _encoding.GetString(str.CTFromBase64ToByteArray());
}
/// <summary>
/// Extension method for strings.
/// Converts the value of a Base64-string to a byte-array.
/// </summary>
/// <param name="str">Input Base64-string.</param>
/// <returns>Base64-Byte-array from the Base64-string.</returns>
public static byte[] CTFromBase64ToByteArray(this string str)
{
return str == null ? null : System.Convert.FromBase64String(str);
}
/// <summary>
/// Extension method for strings.
/// Converts the value of a string to a Hex-string (with Unicode support).
/// </summary>
/// <param name="str">Input string.</param>
/// <param name="addPrefix">Add "0x"-as prefix (optional, default: false).</param>
/// <returns>String value as converted Hex-string.</returns>
public static string CTToHex(this string str, bool addPrefix = false)
{
if (str == null)
return null;
System.Text.StringBuilder sb = new System.Text.StringBuilder();
if (addPrefix)
sb.Append("0x");
byte[] bytes = System.Text.Encoding.Unicode.GetBytes(str);
foreach (byte t in bytes)
{
sb.Append(t.ToString("X2"));
}
return sb.ToString(); // returns: "48656C6C6F20776F726C64" for "Hello world"
}
/// <summary>
/// Extension method for strings.
/// Converts the Hex-value of a string to a string (with Unicode support).
/// </summary>
/// <param name="hexString">Input as Hex-string.</param>
/// <returns>Hex-string value as converted string.</returns>
public static string CTHexToString(this string hexString)
{
if (hexString == null)
return null;
string _hex = hexString;
if (_hex.StartsWith("0x"))
_hex = _hex.Substring(2);
if (hexString.Length % 2 != 0)
throw new System.FormatException($"String seems to be an invalid hex-code: {hexString}");
byte[] bytes = new byte[_hex.Length / 2];
for (int ii = 0; ii < bytes.Length; ii++)
{
bytes[ii] = System.Convert.ToByte(hexString.Substring(ii * 2, 2), 16);
}
//return System.Text.Encoding.ASCII.GetString(bytes);
return System.Text.Encoding.Unicode.GetString(bytes); // returns: "Hello world" for "48656C6C6F20776F726C64"
}
/// <summary>
/// Extension method for strings.
/// Converts the Hex-value of a string to a Color32.
/// </summary>
/// <param name="hexString">Input as Hex-string.</param>
/// <returns>Hex-string value as Color32.</returns>
public static Color32 CTHexToColor32(this string hexString)
{
if (hexString == null)
throw new System.ArgumentNullException(nameof(hexString));
string _hex = hexString;
if (_hex.StartsWith("0x"))
_hex = _hex.Substring(2);
if (_hex.StartsWith("#"))
_hex = _hex.Substring(1);
/*
Color color = Color.white;
if (ColorUtility.TryParseHtmlString(_hex, out color))
{
Debug.LogWarning($"Could not convert string to color: {hexString}");
}
return color;
*/
if (_hex.Length != 6 && _hex.Length != 8)
throw new System.FormatException($"String seems to be an invalid color: {_hex}");
byte r = System.Convert.ToByte(_hex.Substring(0, 2), 16);
byte g = System.Convert.ToByte(_hex.Substring(2, 2), 16);
byte b = System.Convert.ToByte(_hex.Substring(4, 2), 16);
byte a = 0xFF;
if (_hex.Length == 8)
a = System.Convert.ToByte(_hex.Substring(6, 2), 16);
Color32 color = new Color32(r, g, b, a);
//Debug.Log("Hex orig: '" + _hex + "'");
//Debug.Log("Color: " + color);
return color;
}
/// <summary>
/// Extension method for strings.
/// Converts the Hex-value of a string to a Color.
/// </summary>
/// <param name="hexString">Input as Hex-string.</param>
/// <returns>Hex-string value as Color.</returns>
public static Color CTHexToColor(this string hexString)
{
return CTHexToColor32(hexString);
}
/// <summary>
/// Extension method for strings.
/// Converts the value of a string to a byte-array.
/// </summary>
/// <param name="str">Input string.</param>
/// <param name="encoding">Encoding of the string (optional, default: UTF8).</param>
/// <returns>Byte-array with the string.</returns>
public static byte[] CTToByteArray(this string str, System.Text.Encoding encoding = null)
{
if (str == null)
return null;
System.Text.Encoding _encoding = System.Text.Encoding.UTF8;
if (encoding != null)
_encoding = encoding;
return _encoding.GetBytes(str);
}
/// <summary>
/// Extension method for strings.
/// Cleans a given text from tags.
/// </summary>
/// <param name="str">Input to clean.</param>
/// <returns>Clean text without tags.</returns>
public static string CTClearTags(this string str)
{
return str != null ? Crosstales.Common.Util.BaseConstants.REGEX_CLEAN_TAGS.Replace(str, string.Empty).Trim() : null;
}
/// <summary>
/// Extension method for strings.
/// Cleans a given text from multiple spaces.
/// </summary>
/// <param name="str">Input to clean.</param>
/// <returns>Clean text without multiple spaces.</returns>
public static string CTClearSpaces(this string str)
{
return str != null ? Crosstales.Common.Util.BaseConstants.REGEX_CLEAN_SPACES.Replace(str, " ").Trim() : null;
}
/// <summary>
/// Extension method for strings.
/// Cleans a given text from line endings.
/// </summary>
/// <param name="str">Input to clean.</param>
/// <returns>Clean text without line endings.</returns>
public static string CTClearLineEndings(this string str)
{
return str != null ? Crosstales.Common.Util.BaseConstants.REGEX_LINEENDINGS.Replace(str, string.Empty).Trim() : null;
}
#endregion
#region Arrays
/// <summary>
/// Extension method for arrays.
/// Shuffles an array.
/// </summary>
/// <param name="array">Array-instance to shuffle.</param>
/// <param name="seed">Seed for the PRNG (optional, default: 0 (=standard))</param>
public static void CTShuffle<T>(this T[] array, int seed = 0)
{
#if UNITY_WSA
return;
#else
if (array == null || array.Length <= 0)
throw new System.ArgumentNullException(nameof(array));
System.Random rnd = seed == 0 ? new System.Random() : new System.Random(seed);
int n = array.Length;
while (n > 1)
{
int k = rnd.Next(n--);
(array[n], array[k]) = (array[k], array[n]);
}
#endif
}
/// <summary>
/// Extension method for arrays.
/// Dumps an array to a string.
/// </summary>
/// <param name="array">Array-instance to dump.</param>
/// <param name="prefix">Prefix for every element (optional, default: empty).</param>
/// <param name="postfix">Postfix for every element (optional, default: empty).</param>
/// <param name="appendNewLine">Append new line, otherwise use the given delimiter (optional, default: false).</param>
/// <param name="delimiter">Delimiter if appendNewLine is false (optional, default: "; ").</param>
/// <returns>String with lines for all array entries.</returns>
public static string CTDump<T>(this T[] array, string prefix = "", string postfix = "", bool appendNewLine = true, string delimiter = "; ")
{
if (array == null) // || array.Length <= 0)
return null;
System.Text.StringBuilder sb = new System.Text.StringBuilder();
foreach (T element in array)
{
if (0 < sb.Length)
{
sb.Append(appendNewLine ? System.Environment.NewLine : delimiter);
}
sb.Append(prefix);
sb.Append(element);
sb.Append(postfix);
}
return sb.ToString();
}
/// <summary>
/// Extension method for Quaternion-arrays.
/// Dumps an array to a string.
/// </summary>
/// <param name="array">Quaternion-array-instance to dump.</param>
/// <returns>String with lines for all array entries.</returns>
public static string CTDump(this Quaternion[] array)
{
if (array == null) // || array.Length <= 0)
return null;
System.Text.StringBuilder sb = new System.Text.StringBuilder();
foreach (Quaternion element in array)
{
if (0 < sb.Length)
sb.Append(System.Environment.NewLine);
sb.Append(element.x);
sb.Append(", ");
sb.Append(element.y);
sb.Append(", ");
sb.Append(element.z);
sb.Append(", ");
sb.Append(element.w);
}
return sb.ToString();
}
/// <summary>
/// Extension method for Vector2-arrays.
/// Dumps an array to a string.
/// </summary>
/// <param name="array">Vector2-array-instance to dump.</param>
/// <returns>String with lines for all array entries.</returns>
public static string CTDump(this Vector2[] array)
{
if (array == null) // || array.Length <= 0)
return null;
System.Text.StringBuilder sb = new System.Text.StringBuilder();
foreach (Vector2 element in array)
{
if (0 < sb.Length)
sb.Append(System.Environment.NewLine);
sb.Append(element.x);
sb.Append(", ");
sb.Append(element.y);
}
return sb.ToString();
}
/// <summary>
/// Extension method for Vector3-arrays.
/// Dumps an array to a string.
/// </summary>
/// <param name="array">Vector3-array-instance to dump.</param>
/// <returns>String with lines for all array entries.</returns>
public static string CTDump(this Vector3[] array)
{
if (array == null) // || array.Length <= 0)
return null;
System.Text.StringBuilder sb = new System.Text.StringBuilder();
foreach (Vector3 element in array)
{
if (0 < sb.Length)
sb.Append(System.Environment.NewLine);
sb.Append(element.x);
sb.Append(", ");
sb.Append(element.y);
sb.Append(", ");
sb.Append(element.z);
}
return sb.ToString();
}
/// <summary>
/// Extension method for Vector4-arrays.
/// Dumps an array to a string.
/// </summary>
/// <param name="array">Vector4-array-instance to dump.</param>
/// <returns>String with lines for all array entries.</returns>
public static string CTDump(this Vector4[] array)
{
if (array == null) // || array.Length <= 0)
return null;
System.Text.StringBuilder sb = new System.Text.StringBuilder();
foreach (Vector4 element in array)
{
if (0 < sb.Length)
sb.Append(System.Environment.NewLine);
sb.Append(element.x);
sb.Append(", ");
sb.Append(element.y);
sb.Append(", ");
sb.Append(element.z);
sb.Append(", ");
sb.Append(element.w);
}
return sb.ToString();
}
/// <summary>
/// Extension method for arrays.
/// Generates a string array with all entries (via ToString).
/// </summary>
/// <param name="array">Array-instance to ToString.</param>
/// <returns>String array with all entries (via ToString).</returns>
public static string[] CTToStringArray<T>(this T[] array)
{
if (array == null) // || array.Length <= 0)
throw new System.ArgumentNullException(nameof(array));
string[] result = new string[array.Length];
for (int ii = 0; ii < array.Length; ii++)
{
result[ii] = null == array[ii] ? "null" : array[ii].ToString();
}
return result;
}
/// <summary>
/// Extension method for byte-arrays.
/// Converts a byte-array to a float-array.
/// </summary>
/// <param name="array">Array-instance to convert.</param>
/// <param name="count">Number of bytes to convert (optional).</param>
/// <returns>Converted float-array.</returns>
public static float[] CTToFloatArray(this byte[] array, int count = 0)
{
if (array == null) // || array.Length <= 0)
throw new System.ArgumentNullException(nameof(array));
int _count = count;
if (_count <= 0)
_count = array.Length;
float[] floats = new float[_count / 2];
int ii = 0;
for (int zz = 0; zz < _count; zz += 2)
{
floats[ii] = bytesToFloat(array[zz], array[zz + 1]);
ii++;
}
return floats;
}
/// <summary>
/// Extension method for float-arrays.
/// Converts a float-array to a byte-array.
/// </summary>
/// <param name="array">Array-instance to convert.</param>
/// <param name="count">Number of floats to convert (optional).</param>
/// <returns>Converted byte-array.</returns>
public static byte[] CTToByteArray(this float[] array, int count = 0)
{
if (array == null) // || array.Length <= 0)
throw new System.ArgumentNullException(nameof(array));
int _count = count;
if (_count <= 0)
_count = array.Length;
byte[] bytes = new byte[_count * 2];
int byteIndex = 0;
for (int ii = 0; ii < _count; ii++)
{
short outsample = (short)(array[ii] * short.MaxValue);
bytes[byteIndex] = (byte)(outsample & 0xff);
bytes[byteIndex + 1] = (byte)((outsample >> 8) & 0xff);
byteIndex += 2;
}
return bytes;
}
/// <summary>
/// Extension method for byte-arrays.
/// Converts a byte-array to a Texture. Supported image formats: PNG and JPG.
/// </summary>
/// <param name="data">byte-array-instance to convert.</param>
/// <param name="supportTexture">Support texture to prevent possible texture garbage (optional).</param>
/// <returns>Converted Texture.</returns>
public static Texture2D CTToTexture(this byte[] data, Texture2D supportTexture = null)
{
if (data == null)
throw new System.ArgumentNullException(nameof(data));
Texture2D tex = supportTexture;
if (tex == null)
tex = new Texture2D(1, 1); // note that the size is overridden
tex.LoadImage(data);
return tex;
}
/// <summary>
/// Extension method for byte-arrays.
/// Converts a byte-array to a Sprite. Supported image formats: PNG and JPG.
/// </summary>
/// <param name="data">byte-array-instance to convert.</param>
/// <param name="supportTexture">Support texture to prevent possible texture garbage (optional).</param>
/// <returns>Converted Sprite.</returns>
public static Sprite CTToSprite(this byte[] data, Texture2D supportTexture = null)
{
if (data == null)
throw new System.ArgumentNullException(nameof(data));
if (supportTexture == null)
{
Texture2D tex = data.CTToTexture();
return Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(tex.width / 2, tex.height / 2));
}
supportTexture = data.CTToTexture(supportTexture);
return Sprite.Create(supportTexture, new Rect(0, 0, supportTexture.width, supportTexture.height), new Vector2(supportTexture.width / 2, supportTexture.height / 2));
}
/// <summary>
/// Extension method for byte-arrays.
/// Converts a byte-array to a string.
/// </summary>
/// <param name="data">Input string as byte-array.</param>
/// <param name="encoding">Encoding of the string (optional, default: UTF8).</param>
/// <returns>Byte-array with the string.</returns>
public static string CTToString(this byte[] data, System.Text.Encoding encoding = null)
{
if (data == null)
return null;
System.Text.Encoding _encoding = encoding ?? System.Text.Encoding.UTF8;
return _encoding.GetString(data);
}
/// <summary>
/// Extension method for byte-arrays.
/// Converts a byte-array to a Base64-string.
/// </summary>
/// <param name="data">Input as byte-array.</param>
/// <returns>Base64-string from the byte-array.</returns>
public static string CTToBase64(this byte[] data)
{
return data == null ? null : System.Convert.ToBase64String(data);
}
/// <summary>
/// Extension method for 2D-arrays.
/// Returns the column of a 2D-array as array.
/// </summary>
/// <param name="matrix">Input as 2D-array.</param>
/// <param name="columnNumber">Desired column of the 2D-array</param>
/// <returns>Column of a 2D-array as array.</returns>
public static T[] GetColumn<T>(this T[,] matrix, int columnNumber)
{
return Enumerable.Range(0, matrix.GetLength(0)).Select(x => matrix[x, columnNumber]).ToArray();
}
/// <summary>
/// Extension method for 2D-arrays.
/// Returns the row of a 2D-array as array.
/// </summary>
/// <param name="matrix">Input as 2D-array.</param>
/// <param name="columnNumber">Desired row of the 2D-array</param>
/// <returns>Row of a 2D-array as array.</returns>
public static T[] GetRow<T>(this T[,] matrix, int rowNumber)
{
return Enumerable.Range(0, matrix.GetLength(1)).Select(x => matrix[rowNumber, x]).ToArray();
}
#endregion
#region Lists
/// <summary>
/// Extension method for IList.
/// Shuffles a List.
/// </summary>
/// <param name="list">IList-instance to shuffle.</param>
/// <param name="seed">Seed for the PRNG (optional, default: 0 (=standard))</param>
public static void CTShuffle<T>(this System.Collections.Generic.IList<T> list, int seed = 0)
{
#if UNITY_WSA
return;
#else
if (list == null)
throw new System.ArgumentNullException(nameof(list));
System.Random rnd = seed == 0 ? new System.Random() : new System.Random(seed);
int n = list.Count;
while (n > 1)
{
int k = rnd.Next(n--);
(list[n], list[k]) = (list[k], list[n]);
}
#endif
}
/// <summary>
/// Extension method for IList.
/// Dumps a list to a string.
/// </summary>
/// <param name="list">IList-instance to dump.</param>
/// <param name="prefix">Prefix for every element (optional, default: empty).</param>
/// <param name="postfix">Postfix for every element (optional, default: empty).</param>
/// <param name="appendNewLine">Append new line, otherwise use the given delimiter (optional, default: false).</param>
/// <param name="delimiter">Delimiter if appendNewLine is false (optional, default: "; ").</param>
/// <returns>String with lines for all list entries.</returns>
public static string CTDump<T>(this System.Collections.Generic.IList<T> list, string prefix = "", string postfix = "", bool appendNewLine = true, string delimiter = "; ")
{
if (list == null)
return null;
System.Text.StringBuilder sb = new System.Text.StringBuilder();
foreach (T element in list)
{
if (0 < sb.Length)
{
sb.Append(appendNewLine ? System.Environment.NewLine : delimiter);
}
sb.Append(prefix);
sb.Append(element);
sb.Append(postfix);
}
return sb.ToString();
}
/// <summary>
/// Extension method for Quaternion-IList.
/// Dumps a list to a string.
/// </summary>
/// <param name="list">Quaternion-IList-instance to dump.</param>
/// <returns>String with lines for all list entries.</returns>
public static string CTDump(this System.Collections.Generic.IList<Quaternion> list)
{
if (list == null)
return null;
System.Text.StringBuilder sb = new System.Text.StringBuilder();
foreach (Quaternion element in list)
{
if (0 < sb.Length)
sb.Append(System.Environment.NewLine);
sb.Append(element.x);
sb.Append(", ");
sb.Append(element.y);
sb.Append(", ");
sb.Append(element.z);
sb.Append(", ");
sb.Append(element.w);
}
return sb.ToString();
}
/// <summary>
/// Extension method for Vector2-IList.
/// Dumps a list to a string.
/// </summary>
/// <param name="list">Vector2-IList-instance to dump.</param>
/// <returns>String with lines for all list entries.</returns>
public static string CTDump(this System.Collections.Generic.IList<Vector2> list)
{
if (list == null)
return null;
System.Text.StringBuilder sb = new System.Text.StringBuilder();
foreach (Vector2 element in list)
{
if (0 < sb.Length)
sb.Append(System.Environment.NewLine);
sb.Append(element.x);
sb.Append(", ");
sb.Append(element.y);
}
return sb.ToString();
}
/// <summary>
/// Extension method for Vector3-IList.
/// Dumps a list to a string.
/// </summary>
/// <param name="list">Vector3-IList-instance to dump.</param>
/// <returns>String with lines for all list entries.</returns>
public static string CTDump(this System.Collections.Generic.IList<Vector3> list)
{
if (list == null)
return null;
System.Text.StringBuilder sb = new System.Text.StringBuilder();
foreach (Vector3 element in list)
{
if (0 < sb.Length)
sb.Append(System.Environment.NewLine);
sb.Append(element.x);
sb.Append(", ");
sb.Append(element.y);
sb.Append(", ");
sb.Append(element.z);
}
return sb.ToString();
}
/// <summary>
/// Extension method for Vector4-IList.
/// Dumps a list to a string.
/// </summary>
/// <param name="list">Vector4-IList-instance to dump.</param>
/// <returns>String with lines for all list entries.</returns>
public static string CTDump(this System.Collections.Generic.IList<Vector4> list)
{
if (list == null)
return null;
System.Text.StringBuilder sb = new System.Text.StringBuilder();
foreach (Vector4 element in list)
{
if (0 < sb.Length)
sb.Append(System.Environment.NewLine);
sb.Append(element.x);
sb.Append(", ");
sb.Append(element.y);
sb.Append(", ");
sb.Append(element.z);
sb.Append(", ");
sb.Append(element.w);
}
return sb.ToString();
}
/// <summary>
/// Extension method for IList.
/// Generates a string list with all entries (via ToString).
/// </summary>
/// <param name="list">IList-instance to ToString.</param>
/// <returns>String list with all entries (via ToString).</returns>
public static System.Collections.Generic.List<string> CTToString<T>(this System.Collections.Generic.IList<T> list)
{
if (list == null)
throw new System.ArgumentNullException(nameof(list));
System.Collections.Generic.List<string> result = new System.Collections.Generic.List<string>(list.Count);
result.AddRange(list.Select(element => null == element ? "null" : element.ToString()));
return result;
}
#endregion
#region Dictionaries
/// <summary>
/// Extension method for IDictionary.
/// Dumps a dictionary to a string.
/// </summary>
/// <param name="dict">IDictionary-instance to dump.</param>
/// <param name="prefix">Prefix for every element (optional, default: empty).</param>
/// <param name="postfix">Postfix for every element (optional, default: empty).</param>
/// <param name="appendNewLine">Append new line, otherwise use the given delimiter (optional, default: false).</param>
/// <param name="delimiter">Delimiter if appendNewLine is false (optional, default: "; ").</param>
/// <returns>String with lines for all dictionary entries.</returns>
public static string CTDump<K, V>(this System.Collections.Generic.IDictionary<K, V> dict, string prefix = "", string postfix = "", bool appendNewLine = true, string delimiter = "; ")
{
if (dict == null)
return null;
System.Text.StringBuilder sb = new System.Text.StringBuilder();
foreach (System.Collections.Generic.KeyValuePair<K, V> kvp in dict)
{
if (0 < sb.Length)
{
sb.Append(appendNewLine ? System.Environment.NewLine : delimiter);
}
sb.Append(prefix);
sb.Append("Key = ");
sb.Append(kvp.Key);
sb.Append(", Value = ");
sb.Append(kvp.Value);
sb.Append(postfix);
}
return sb.ToString();
}
/// <summary>
/// Extension method for IDictionary.
/// Adds a dictionary to an existing one.
/// </summary>
/// <param name="dict">IDictionary-instance.</param>
/// <param name="collection">Dictionary to add.</param>
public static void CTAddRange<K, V>(this System.Collections.Generic.IDictionary<K, V> dict, System.Collections.Generic.IDictionary<K, V> collection)
{
if (dict == null)
throw new System.ArgumentNullException(nameof(dict));
if (collection == null)
throw new System.ArgumentNullException(nameof(collection));
foreach (System.Collections.Generic.KeyValuePair<K, V> item in collection)
{
if (!dict.ContainsKey(item.Key))
{
dict.Add(item.Key, item.Value);
}
else
{
// handle duplicate key issue here
Debug.LogWarning($"Duplicate key found: {item.Key}");
}
}
}
#endregion
#region Streams
/// <summary>
/// Extension method for Stream.
/// Reads the full content of a Stream.
/// </summary>
/// <param name="input">Stream-instance to read.</param>
/// <returns>Byte-array of the Stream content.</returns>
public static byte[] CTReadFully(this System.IO.Stream input)
{
if (input == null)
throw new System.ArgumentNullException(nameof(input));
using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
{
input.CopyTo(ms);
return ms.ToArray();
}
}
#endregion
#region Color
/// <summary>
/// Extension method for Color32.
/// Converts the value of a color to a RGB Hex-string.
/// </summary>
/// <param name="input">Color to convert.</param>
/// <returns>Color value as Hex (format "RRGGBB").</returns>
public static string CTToHexRGB(this Color32 input)
{
return CTToHexRGB((Color)input);
}
/// <summary>
/// Extension method for Color.
/// Converts the value of a color to a RGB Hex-string.
/// </summary>
/// <param name="input">Color to convert.</param>
/// <returns>Color value as Hex (format "RRGGBB").</returns>
public static string CTToHexRGB(this Color input)
{
if (input == null)
throw new System.ArgumentNullException(nameof(input));
string hexColor = ColorUtility.ToHtmlStringRGB(input);
//if (hexColor.Length != 6)
// Debug.LogError("HEX invalid: " + hexColor);
return hexColor;
/*
Color32 color = input;
string hexColor = $"{(color.r + 0x01):X2}{(color.g + 0x01):X2}{(color.b + 0x01):X2}";
Debug.LogWarning("HEX: " + hexColor);
if (hexColor.Length != 6)
Debug.LogError("HEX invalid: " + hexColor);
return hexColor;
*/
}
/// <summary>
/// Extension method for Color32.
/// Converts the value of a color to a RGBA Hex-string.
/// </summary>
/// <param name="input">Color to convert.</param>
/// <returns>Color value as Hex (format "RRGGBBAA").</returns>
public static string CTToHexRGBA(this Color32 input)
{
return CTToHexRGBA((Color)input);
}
/// <summary>
/// Extension method for Color.
/// Converts the value of a color to a RGBA Hex-string.
/// </summary>
/// <param name="input">Color to convert.</param>
/// <returns>Color value as Hex (format "RRGGBBAA").</returns>
public static string CTToHexRGBA(this Color input)
{
if (input == null)
throw new System.ArgumentNullException(nameof(input));
return ColorUtility.ToHtmlStringRGBA(input);
}
/// <summary>
/// Extension method for Color32.
/// Convert it to a Vector3.
/// </summary>
/// <param name="color">Color-instance to convert.</param>
/// <returns>Vector3 from color.</returns>
public static Vector3 CTVector3(this Color32 color)
{
return CTVector3((Color)color);
}
/// <summary>
/// Extension method for Color.
/// Convert it to a Vector3.
/// </summary>
/// <param name="color">Color-instance to convert.</param>
/// <returns>Vector3 from color.</returns>
public static Vector3 CTVector3(this Color color)
{
if (color == null)
throw new System.ArgumentNullException(nameof(color));
return new Vector3(color.r, color.g, color.b);
}
/// <summary>
/// Extension method for Color32.
/// Convert it to a Vector4.
/// </summary>
/// <param name="color">Color-instance to convert.</param>
/// <returns>Vector4 from color.</returns>
public static Vector4 CTVector4(this Color32 color)
{
return CTVector4((Color)color);
}
/// <summary>
/// Extension method for Color.
/// Convert it to a Vector4.
/// </summary>
/// <param name="color">Color-instance to convert.</param>
/// <returns>Vector4 from color.</returns>
public static Vector4 CTVector4(this Color color)
{
if (color == null)
throw new System.ArgumentNullException(nameof(color));
return new Vector4(color.r, color.g, color.b, color.a);
}
#endregion
#region Vector2
/// <summary>
/// Allows you to multiply two Vector2s together, something Unity sorely lacks by default.
/// </summary>
/// <param name="a">First vector</param>
/// <param name="b">Second vector</param>
/// <returns>The ax*bx, ay*by result.</returns>
public static Vector2 CTMultiply(this Vector2 a, Vector2 b)
{
return new Vector2(a.x * b.x, a.y * b.y);
}
#endregion
#region Vector3
/// <summary>
/// Allows you to multiply two Vector3s together, something Unity sorely lacks by default.
/// </summary>
/// <param name="a">First vector</param>
/// <param name="b">Second vector</param>
/// <returns>The ax*bx, ay*by, az*bz result.</returns>
public static Vector3 CTMultiply(this Vector3 a, Vector3 b)
{
return new Vector3(a.x * b.x, a.y * b.y, a.z * b.z);
}
/// <summary>
/// Returns a Vector3 with a 0 y-axis. This is useful for keeping entities oriented perpendicular to the ground.
/// </summary>
public static Vector3 CTFlatten(this Vector3 a)
{
return a.CTMultiply(FLAT_VECTOR);
}
/// <summary>
/// Extension method for Vector3.
/// Convert it to a Quaternion.
/// </summary>
/// <param name="eulerAngle">Vector3-instance to convert.</param>
/// <returns>Quaternion from euler angles.</returns>
public static Quaternion CTQuaternion(this Vector3 eulerAngle)
{
return Quaternion.Euler(eulerAngle);
}
/// <summary>
/// Extension method for Vector3.
/// Convert it to a Color.
/// </summary>
/// <param name="rgb">Vector3-instance to convert (RGB = xyz).</param>
/// <param name="alpha">Alpha-value of the color (optional, default: 1).</param>
/// <returns>Color from RGB.</returns>
public static Color CTColorRGB(this Vector3 rgb, float alpha = 1f)
{
return new Color(Mathf.Clamp01(rgb.x), Mathf.Clamp01(rgb.y), Mathf.Clamp01(rgb.z), Mathf.Clamp01(alpha));
}
#endregion
#region Vector4
/// <summary>
/// Allows you to multiply two Vector4s together, something Unity sorely lacks by default.
/// </summary>
/// <param name="a">First vector</param>
/// <param name="b">Second vector</param>
/// <returns>The ax*bx, ay*by, az*bz, aw*bw result.</returns>
public static Vector4 CTMultiply(this Vector4 a, Vector4 b)
{
return new Vector4(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w);
}
/// <summary>
/// Extension method for Vector4.
/// Convert it to a Quaternion.
/// </summary>
/// <param name="angle">Vector4-instance to convert.</param>
/// <returns>Quaternion from Vector4.</returns>
public static Quaternion CTQuaternion(this Vector4 angle)
{
return new Quaternion(angle.x, angle.y, angle.z, angle.w);
}
/// <summary>
/// Extension method for Vector4.
/// Convert it to a Color.
/// </summary>
/// <param name="rgba">Vector4-instance to convert (RGBA = xyzw).</param>
/// <returns>Color from RGBA.</returns>
public static Color CTColorRGBA(this Vector4 rgba)
{
return new Color(Mathf.Clamp01(rgba.x), Mathf.Clamp01(rgba.y), Mathf.Clamp01(rgba.z), Mathf.Clamp01(rgba.w));
}
#endregion
#region Quaternion
/// <summary>
/// Extension method for Quaternion.
/// Convert it to a Vector3.
/// </summary>
/// <param name="angle">Quaternion-instance to convert.</param>
/// <returns>Vector3 from Quaternion.</returns>
public static Vector3 CTVector3(this Quaternion angle)
{
return angle.eulerAngles;
}
/// <summary>
/// Extension method for Quaternion.
/// Convert it to a Vector4.
/// </summary>
/// <param name="angle">Quaternion-instance to convert.</param>
/// <returns>Vector4 from Quaternion.</returns>
public static Vector4 CTVector4(this Quaternion angle)
{
return new Vector4(angle.x, angle.y, angle.z, angle.w);
}
#endregion
#region Canvas
/// <summary>
/// Extension method for Canvas.
/// Convert current resolution scale.
/// </summary>
/// <param name="canvas">Canvas to convert.</param>
/// <returns>Vector3 with the correct scale.</returns>
public static Vector3 CTCorrectLossyScale(this Canvas canvas)
{
if (canvas == null)
throw new System.ArgumentNullException(nameof(canvas));
if (!Application.isPlaying)
return Vector3.one;
if (canvas.renderMode == RenderMode.ScreenSpaceCamera)
{
UnityEngine.UI.CanvasScaler scaler = canvas.GetComponent<UnityEngine.UI.CanvasScaler>();
if (scaler && scaler.enabled)
{
scaler.enabled = false;
Vector3 before = canvas.GetComponent<RectTransform>().lossyScale;
scaler.enabled = true;
Vector3 after = canvas.GetComponent<RectTransform>().lossyScale;
return new Vector3(after.x / before.x, after.y / before.y, after.z / before.z);
}
return Vector3.one;
}
return canvas.GetComponent<RectTransform>().lossyScale;
}
#endregion
#region RectTransform
/// <summary>
/// Extension method for RectTransform.
/// Sets the local corners of a RectTransform to a given array.
/// </summary>
/// <param name="transform">RectTransform-instance.</param>
/// <param name="fourCornersArray">Corners for the RectTransform.</param>
/// <param name="canvas">Relevant canvas.</param>
/// <param name="inset">Inset from the corners (optional, default: 0).</param>
/// <param name="corrected">Automatically adjust scaling (optional, default: false).</param>
public static void CTGetLocalCorners(this RectTransform transform, Vector3[] fourCornersArray, Canvas canvas, float inset = 0, bool corrected = false)
{
if (transform == null)
throw new System.ArgumentNullException(nameof(transform));
if (fourCornersArray == null)
throw new System.ArgumentNullException(nameof(fourCornersArray));
if (canvas == null)
throw new System.ArgumentNullException(nameof(canvas));
transform.GetLocalCorners(fourCornersArray);
if (corrected)
{
Vector3 uis = canvas.CTCorrectLossyScale();
fourCornersArray[0].x /= uis.x;
fourCornersArray[0].y /= uis.y;
fourCornersArray[1].x /= uis.x;
fourCornersArray[1].y /= uis.y;
fourCornersArray[2].x /= uis.x;
fourCornersArray[2].y /= uis.y;
fourCornersArray[3].x /= uis.x;
fourCornersArray[3].y /= uis.y;
}
if (inset != 0)
{
Vector3 uis = canvas.CTCorrectLossyScale();
fourCornersArray[0].x += inset * uis.x;
fourCornersArray[0].y += inset * uis.y;
fourCornersArray[1].x += inset * uis.x;
fourCornersArray[1].y -= inset * uis.y;
fourCornersArray[2].x -= inset * uis.x;
fourCornersArray[2].y -= inset * uis.y;
fourCornersArray[3].x -= inset * uis.x;
fourCornersArray[3].y += inset * uis.y;
}
}
/// <summary>
/// Extension method for RectTransform.
/// Returns the local corners of a RectTransform.
/// </summary>
/// <param name="transform">RectTransform-instance.</param>
/// <param name="canvas">Relevant canvas.</param>
/// <param name="inset">Inset from the corners (optional, default: 0).</param>
/// <param name="corrected">Automatically adjust scaling (optional, default: false).</param>
/// <returns>Array of the four local corners of the RectTransform.</returns>
public static Vector3[] CTGetLocalCorners(this RectTransform transform, Canvas canvas, float inset = 0, bool corrected = false)
{
Vector3[] fourCornersArray = new Vector3[4];
CTGetLocalCorners(transform, fourCornersArray, canvas, inset, corrected);
return fourCornersArray;
}
/// <summary>
/// Extension method for RectTransform.
/// Sets the world corners of a RectTransform to a given array.
/// </summary>
/// <param name="transform">RectTransform-instance.</param>
/// <param name="fourCornersArray">Corners for the RectTransform.</param>
/// <param name="canvas">Relevant canvas.</param>
/// <param name="inset">Inset from the corners (optional, default: 0).</param>
/// <param name="corrected">Automatically adjust scaling (optional, default: false).</param>
public static void CTGetScreenCorners(this RectTransform transform, Vector3[] fourCornersArray, Canvas canvas, float inset = 0, bool corrected = false)
{
if (transform == null)
throw new System.ArgumentNullException(nameof(transform));
if (fourCornersArray == null)
throw new System.ArgumentNullException(nameof(fourCornersArray));
if (canvas == null)
throw new System.ArgumentNullException(nameof(canvas));
// if screen space overlay mode then world corners are already in screen space
// if screen space camera mode then screen settings are in world and need to be converted to screen
transform.GetWorldCorners(fourCornersArray);
if (canvas.renderMode == RenderMode.ScreenSpaceCamera)
{
for (int ii = 0; ii < 4; ii++)
{
fourCornersArray[ii] = canvas.worldCamera.WorldToScreenPoint(fourCornersArray[ii]);
fourCornersArray[ii].z = 0;
}
}
if (corrected)
{
Vector3 uis = canvas.CTCorrectLossyScale();
fourCornersArray[0].x /= uis.x;
fourCornersArray[0].y /= uis.y;
fourCornersArray[1].x /= uis.x;
fourCornersArray[1].y /= uis.y;
fourCornersArray[2].x /= uis.x;
fourCornersArray[2].y /= uis.y;
fourCornersArray[3].x /= uis.x;
fourCornersArray[3].y /= uis.y;
}
if (inset != 0)
{
Vector3 uis = canvas.CTCorrectLossyScale();
fourCornersArray[0].x += inset * uis.x;
fourCornersArray[0].y += inset * uis.y;
fourCornersArray[1].x += inset * uis.x;
fourCornersArray[1].y -= inset * uis.y;
fourCornersArray[2].x -= inset * uis.x;
fourCornersArray[2].y -= inset * uis.y;
fourCornersArray[3].x -= inset * uis.x;
fourCornersArray[3].y += inset * uis.y;
}
}
/// <summary>
/// Extension method for RectTransform.
/// Returns the screen (world) corners of a RectTransform.
/// </summary>
/// <param name="transform">RectTransform-instance.</param>
/// <param name="canvas">Relevant canvas.</param>
/// <param name="inset">Inset from the corners (optional, default: 0).</param>
/// <param name="corrected">Automatically adjust scaling (optional, default: false).</param>
/// <returns>Array of the four screen (world) corners of the RectTransform.</returns>
public static Vector3[] CTGetScreenCorners(this RectTransform transform, Canvas canvas, float inset = 0, bool corrected = false)
{
Vector3[] fourCornersArray = new Vector3[4];
CTGetScreenCorners(transform, fourCornersArray, canvas, inset, corrected);
return fourCornersArray;
}
/// <summary>
/// Extension method for RectTransform.
/// Returns the bounds of a RectTransform including the children.
/// </summary>
/// <param name="transform">RectTransform to calculate the bounds.</param>
/// <param name="uiScaleFactor">Scale of the UI (optional, default: 1.0).</param>
/// <returns>Bounds of the RectTransform.</returns>
public static Bounds CTGetBounds(this RectTransform transform, float uiScaleFactor = 1f)
{
if (transform == null)
throw new System.ArgumentNullException(nameof(transform));
//Debug.Log($"Root: {transform.anchoredPosition}");
Rect rect;
Bounds bounds = new Bounds(transform.anchoredPosition, new Vector3((rect = transform.rect).width, rect.height, 0.0f) * uiScaleFactor);
if (transform.childCount > 0)
{
foreach (Bounds childBounds in from RectTransform child in transform select new Bounds(child.anchoredPosition, new Vector3(child.rect.width, child.rect.height, 0.0f) * uiScaleFactor))
{
bounds.Encapsulate(childBounds);
}
}
return bounds;
}
/// <summary>
/// Extension method for RectTransform.
/// Sets the Left-property of a RectTransform.
/// </summary>
/// <param name="transform">RectTransform to set the Left-property.</param>
/// <param name="value">Value for the Left-property.</param>
public static void CTSetLeft(this RectTransform transform, float value)
{
if (transform == null)
throw new System.ArgumentNullException(nameof(transform));
transform.offsetMin = new Vector2(value, transform.offsetMin.y);
}
/// <summary>
/// Extension method for RectTransform.
/// Sets the Right-property of a RectTransform.
/// </summary>
/// <param name="transform">RectTransform to set the Right-property.</param>
/// <param name="value">Value for the Right-property.</param>
public static void CTSetRight(this RectTransform transform, float value)
{
if (transform == null)
throw new System.ArgumentNullException(nameof(transform));
transform.offsetMax = new Vector2(value, transform.offsetMax.y);
}
/// <summary>
/// Extension method for RectTransform.
/// Sets the Top-property of a RectTransform.
/// </summary>
/// <param name="transform">RectTransform to set the Top-property.</param>
/// <param name="value">Value for the Top-property.</param>
public static void CTSetTop(this RectTransform transform, float value)
{
if (transform == null)
throw new System.ArgumentNullException(nameof(transform));
transform.offsetMax = new Vector2(transform.offsetMax.x, value);
}
/// <summary>
/// Extension method for RectTransform.
/// Sets the Bottom-property of a RectTransform.
/// </summary>
/// <param name="transform">RectTransform to set the Bottom-property.</param>
/// <param name="value">Value for the Bottom-property.</param>
public static void CTSetBottom(this RectTransform transform, float value)
{
if (transform == null)
throw new System.ArgumentNullException(nameof(transform));
transform.offsetMin = new Vector2(transform.offsetMin.x, value);
}
/// <summary>
/// Extension method for RectTransform.
/// Gets the Left-property of a RectTransform.
/// </summary>
/// <param name="transform">RectTransform to get the Left-property.</param>
/// <returns>Left-property of the RectTransform.</returns>
public static float CTGetLeft(this RectTransform transform)
{
if (transform == null)
throw new System.ArgumentNullException(nameof(transform));
return transform.offsetMin.x;
}
/// <summary>
/// Extension method for RectTransform.
/// Gets the Right-property of a RectTransform.
/// </summary>
/// <param name="transform">RectTransform to get the Right-property.</param>
/// <returns>Right-property of the RectTransform.</returns>
public static float CTGetRight(this RectTransform transform)
{
if (transform == null)
throw new System.ArgumentNullException(nameof(transform));
return transform.offsetMax.x;
}
/// <summary>
/// Extension method for RectTransform.
/// Gets the Top-property of a RectTransform.
/// </summary>
/// <param name="transform">RectTransform to get the Top-property.</param>
/// <returns>Top-property of the RectTransform.</returns>
public static float CTGetTop(this RectTransform transform)
{
if (transform == null)
throw new System.ArgumentNullException(nameof(transform));
return transform.offsetMax.y;
}
/// <summary>
/// Extension method for RectTransform.
/// Gets the Bottom-property of a RectTransform.
/// </summary>
/// <param name="transform">RectTransform to get the Bottom-property.</param>
/// <returns>Bottom-property of the RectTransform.</returns>
public static float CTGetBottom(this RectTransform transform)
{
if (transform == null)
throw new System.ArgumentNullException(nameof(transform));
return transform.offsetMin.y;
}
/// <summary>
/// Extension method for RectTransform.
/// Gets the Left/Right/Top/Bottom-properties of a RectTransform.
/// </summary>
/// <param name="transform">RectTransform to get the Left/Right/Top/Bottom-properties.</param>
/// <returns>Left/Right/Top/Bottom-properties of the RectTransform as Vector4.</returns>
public static Vector4 CTGetLRTB(this RectTransform transform)
{
if (transform == null)
throw new System.ArgumentNullException(nameof(transform));
Vector2 offsetMax;
return new Vector4(transform.offsetMin.x, (offsetMax = transform.offsetMax).x, offsetMax.y, transform.offsetMin.y);
}
/// <summary>
/// Extension method for RectTransform.
/// Sets the Left/Right/Top/Bottom-properties of a RectTransform.
/// </summary>
/// <param name="transform">RectTransform to set the Left/Right/Top/Bottom-properties.</param>
/// <param name="lrtb">Left/Right/Top/Bottom-properties as Vector4.</param>
public static void CTSetLRTB(this RectTransform transform, Vector4 lrtb)
{
if (transform == null)
throw new System.ArgumentNullException(nameof(transform));
transform.offsetMin = new Vector2(lrtb.x, lrtb.w);
transform.offsetMax = new Vector2(lrtb.y, lrtb.z);
}
#endregion
#region Component
/// <summary>
/// Extension method for Component.
/// Recursively searches all children of a parent Component for specific named GameObjects
/// </summary>
/// <param name="component">Parent of the current children.</param>
/// <param name="name">Name of the GameObject.</param>
/// <param name="maxDepth">Maximal depth of the search (default 0, optional).</param>
/// <returns>List of GameObjects with the given name or empty list.</returns>
public static System.Collections.Generic.List<GameObject> CTFindAll(this Component component, string name, int maxDepth = 0)
{
if (component == null)
throw new System.ArgumentNullException(nameof(component));
if (name == null)
throw new System.ArgumentNullException(nameof(name));
System.Collections.Generic.List<GameObject> children = new System.Collections.Generic.List<GameObject>();
System.Collections.Generic.List<Transform> childrenTf = getAllChildren(component.transform, maxDepth);
foreach (var child in childrenTf)
{
children.Add(child.gameObject);
}
return children.Where(child => child.name == name).ToList();
}
/// <summary>
/// Extension method for Component.
/// Recursively searches all children of a parent Component for specific named GameObjects
/// </summary>
/// <param name="component">Parent of the current children.</param>
/// <param name="name">Name of the GameObject.</param>
/// <returns>List of GameObjects with the given name or empty list.</returns>
public static System.Collections.Generic.List<T> CTFindAll<T>(this Component component, string name) where T : Component
{
if (component == null)
throw new System.ArgumentNullException(nameof(component));
if (name == null)
throw new System.ArgumentNullException(nameof(name));
T[] children = component.GetComponentsInChildren<T>();
return children.Where(child => child.name == name).ToList();
}
#endregion
#region MonoBehaviour
/// <summary>
/// Extension method for MonoBehaviour.
/// Recursively searches all children of a parent MonoBehaviour for specific named GameObject
/// </summary>
/// <param name="mb">Parent of the current children.</param>
/// <param name="name">Name of the GameObject.</param>
/// <returns>GameObject with the given name or null.</returns>
public static GameObject CTFind(this MonoBehaviour mb, string name)
{
if (mb == null)
throw new System.ArgumentNullException(nameof(mb));
return mb.transform.CTFind(name).gameObject;
}
/// <summary>
/// Extension method for MonoBehaviour.
/// Recursively searches all children of a parent MonoBehaviour for specific named GameObject and returns a component.
/// </summary>
/// <param name="mb">Parent of the current children.</param>
/// <param name="name">Name of the GameObject.</param>
/// <returns>Component with the given type or null.</returns>
public static T CTFind<T>(this MonoBehaviour mb, string name)
{
if (mb == null)
throw new System.ArgumentNullException(nameof(mb));
return mb.transform.CTFind<T>(name);
}
#endregion
#region GameObject
/// <summary>
/// Extension method for GameObject.
/// Recursively searches all children of a parent GameObject for specific named GameObject
/// </summary>
/// <param name="go">Parent of the current children.</param>
/// <param name="name">Name of the GameObject.</param>
/// <returns>GameObject with the given name or null.</returns>
public static GameObject CTFind(this GameObject go, string name)
{
if (go == null)
throw new System.ArgumentNullException(nameof(go));
return go.transform.CTFind(name).gameObject;
}
/// <summary>
/// Extension method for GameObject.
/// Recursively searches all children of a parent GameObject for specific named GameObject and returns a component.
/// </summary>
/// <param name="go">Parent of the current children.</param>
/// <param name="name">Name of the GameObject.</param>
/// <returns>Component with the given type or null.</returns>
public static T CTFind<T>(this GameObject go, string name)
{
if (go == null)
throw new System.ArgumentNullException(nameof(go));
return go.transform.CTFind<T>(name);
}
/// <summary>
/// Extension method for GameObject.
/// Returns the bounds of a GameObject including the children.
/// </summary>
/// <param name="go">GameObject to calculate the bounds.</param>
/// <returns>Bounds of the GameObject.</returns>
public static Bounds CTGetBounds(this GameObject go)
{
if (go == null)
throw new System.ArgumentNullException(nameof(go));
Renderer[] renderers = go.GetComponentsInChildren<Renderer>();
if (renderers.Length == 0)
return new Bounds(go.transform.position, Vector3.zero);
Bounds b = renderers[0].bounds;
foreach (Renderer r in renderers)
{
b.Encapsulate(r.bounds);
}
return b;
}
#endregion
#region Transform
/// <summary>
/// Extension method for Transform.
/// Recursively searches all children of a parent transform for specific named transform
/// </summary>
/// <param name="transform">Parent of the current children.</param>
/// <param name="name">Name of the transform.</param>
/// <returns>Transform with the given name or null.</returns>
public static Transform CTFind(this Transform transform, string name)
{
if (transform == null)
throw new System.ArgumentNullException(nameof(transform));
if (name == null)
throw new System.ArgumentNullException(nameof(name));
return deepSearch(transform, name);
}
/// <summary>
/// Extension method for Transform.
/// Recursively searches all children of a parent transform for specific named transform and returns a component.
/// </summary>
/// <param name="transform">Parent of the current children.</param>
/// <param name="name">Name of the transform.</param>
/// <returns>Component with the given type or null.</returns>
public static T CTFind<T>(this Transform transform, string name)
{
if (transform == null)
throw new System.ArgumentNullException(nameof(transform));
Transform tf = transform.CTFind(name);
return tf != null ? tf.gameObject.GetComponent<T>() : default;
}
#endregion
#region Sprite
/// <summary>
/// Extension method for Sprite.
/// Converts a Sprite to a PNG byte-array.
/// </summary>
/// <param name="sprite">Sprite to convert.</param>
/// <returns>Converted Sprite as PNG byte-array.</returns>
public static byte[] CTToPNG(this Sprite sprite)
{
if (sprite == null)
throw new System.ArgumentNullException(nameof(sprite));
return sprite.texture.CTToPNG();
}
/// <summary>
/// Extension method for Sprite.
/// Converts a Sprite to a JPG byte-array.
/// </summary>
/// <param name="sprite">Sprite to convert.</param>
/// <returns>Converted Sprite as JPG byte-array.</returns>
public static byte[] CTToJPG(this Sprite sprite)
{
if (sprite == null)
throw new System.ArgumentNullException(nameof(sprite));
return sprite.texture.CTToJPG();
}
/// <summary>
/// Extension method for Sprite.
/// Converts a Sprite to a TGA byte-array.
/// </summary>
/// <param name="sprite">Sprite to convert.</param>
/// <returns>Converted Sprite as TGA byte-array.</returns>
public static byte[] CTToTGA(this Sprite sprite)
{
if (sprite == null)
throw new System.ArgumentNullException(nameof(sprite));
return sprite.texture.CTToTGA();
}
/// <summary>
/// Extension method for Sprite.
/// Converts a Sprite to a EXR byte-array.
/// </summary>
/// <param name="sprite">Sprite to convert.</param>
/// <returns>Converted Sprite as EXR byte-array.</returns>
public static byte[] CTToEXR(this Sprite sprite)
{
if (sprite == null)
throw new System.ArgumentNullException(nameof(sprite));
return sprite.texture.CTToEXR();
}
#endregion
#region Texture
/// <summary>
/// Extension method for Texture.
/// Converts a Texture to a PNG byte-array.
/// </summary>
/// <param name="texture">Texture to convert.</param>
/// <returns>Converted Texture as PNG byte-array.</returns>
public static byte[] CTToPNG(this Texture2D texture)
{
if (texture == null)
throw new System.ArgumentNullException(nameof(texture));
return texture.EncodeToPNG();
}
/// <summary>
/// Extension method for Texture.
/// Converts a Texture to a JPG byte-array.
/// </summary>
/// <param name="texture">Texture to convert.</param>
/// <returns>Converted Texture as JPG byte-array.</returns>
public static byte[] CTToJPG(this Texture2D texture)
{
if (texture == null)
throw new System.ArgumentNullException(nameof(texture));
return texture.EncodeToJPG();
}
/// <summary>
/// Extension method for Texture.
/// Converts a Texture to a TGA byte-array.
/// </summary>
/// <param name="texture">Texture to convert.</param>
/// <returns>Converted Texture as TGA byte-array.</returns>
public static byte[] CTToTGA(this Texture2D texture)
{
if (texture == null)
throw new System.ArgumentNullException(nameof(texture));
return texture.EncodeToTGA();
}
/// <summary>
/// Extension method for Texture.
/// Converts a Texture to a EXR byte-array.
/// </summary>
/// <param name="texture">Texture to convert.</param>
/// <returns>Converted Texture as EXR byte-array.</returns>
public static byte[] CTToEXR(this Texture2D texture)
{
if (texture == null)
throw new System.ArgumentNullException(nameof(texture));
return texture.EncodeToEXR();
}
/// <summary>
/// Extension method for Texture.
/// Converts a Texture to a Sprite.
/// </summary>
/// <param name="texture">Texture to convert.</param>
/// <param name="pixelsPerUnit">Pixels per unit for the Sprite (optional, default: 100).</param>
/// <returns>Converted Texture as Sprite.</returns>
public static Sprite CTToSprite(this Texture2D texture, float pixelsPerUnit = 100f)
{
if (texture == null)
throw new System.ArgumentNullException(nameof(texture));
return Sprite.Create(texture, new Rect(0f, 0f, texture.width, texture.height), new Vector2(0.5f, 0.5f), pixelsPerUnit);
}
/// <summary>
/// Extension method for Texture.
/// Rotates a Texture by 90 degrees.
/// </summary>
/// <param name="texture">Texture to rotate.</param>
/// <returns>Rotated Texture.</returns>
public static Texture2D CTRotate90(this Texture2D texture)
{
if (texture == null)
throw new System.ArgumentNullException(nameof(texture));
Color32[] origpix = texture.GetPixels32(0);
Color32[] newpix = new Color32[texture.width * texture.height];
for (int cc = 0; cc < texture.height; cc++)
{
for (int rr = 0; rr < texture.width; rr++)
{
newpix[texture.width * texture.height - (texture.height * rr + texture.height) + cc] =
origpix[texture.width * texture.height - (texture.width * cc + texture.width) + rr];
}
}
Texture2D newtex = new Texture2D(texture.height, texture.width, texture.format, false);
newtex.SetPixels32(newpix, 0);
newtex.Apply();
return newtex;
}
/// <summary>
/// Extension method for Texture.
/// Rotates a Texture by 180 degrees.
/// </summary>
/// <param name="texture">Texture to rotate.</param>
/// <returns>Rotated Texture.</returns>
public static Texture2D CTRotate180(this Texture2D texture)
{
if (texture == null)
throw new System.ArgumentNullException(nameof(texture));
Color32[] origpix = texture.GetPixels32(0);
Color32[] newpix = new Color32[texture.width * texture.height];
for (int ii = 0; ii < origpix.Length; ii++)
{
newpix[origpix.Length - ii - 1] = origpix[ii];
}
Texture2D newtex = new Texture2D(texture.width, texture.height, texture.format, false);
newtex.SetPixels32(newpix, 0);
newtex.Apply();
return newtex;
}
/// <summary>
/// Extension method for Texture.
/// Rotates a Texture by 270 degrees.
/// </summary>
/// <param name="texture">Texture to rotate.</param>
/// <returns>Rotated Texture.</returns>
public static Texture2D CTRotate270(this Texture2D texture)
{
if (texture == null)
throw new System.ArgumentNullException(nameof(texture));
Color32[] origpix = texture.GetPixels32(0);
Color32[] newpix = new Color32[texture.width * texture.height];
int ii = 0;
for (int cc = 0; cc < texture.height; cc++)
{
for (int rr = 0; rr < texture.width; rr++)
{
newpix[texture.width * texture.height - (texture.height * rr + texture.height) + cc] = origpix[ii];
ii++;
}
}
Texture2D newtex = new Texture2D(texture.height, texture.width, texture.format, false);
newtex.SetPixels32(newpix, 0);
newtex.Apply();
return newtex;
}
/// <summary>
/// Extension method for Texture.
/// Convert a Texture to a Texture2D
/// </summary>
/// <param name="texture">Texture to convert.</param>
/// <returns>Converted Texture2D.</returns>
public static Texture2D CTToTexture2D(this Texture texture)
{
if (texture == null)
throw new System.ArgumentNullException(nameof(texture));
return Texture2D.CreateExternalTexture(
texture.width,
texture.height,
TextureFormat.RGB24,
false, false,
texture.GetNativeTexturePtr());
}
#if CT_WEBCAM
/// <summary>
/// Extension method for WebCamTexture.
/// Convert a WebCamTexture to a Texture2D
/// </summary>
/// <param name="texture">WebCamTexture to convert.</param>
/// <returns>Converted Texture2D.</returns>
public static Texture2D CTToTexture2D(this WebCamTexture texture)
{
if (texture == null)
throw new System.ArgumentNullException(nameof(texture));
Texture2D texture2D = new Texture2D(texture.width, texture.height);
if (texture.isPlaying)
{
Color32[] data = new Color32[texture.width * texture.height];
texture.GetPixels32(data);
texture2D.SetPixels32(data, 0);
texture2D.Apply();
}
return texture2D;
}
#endif
/// <summary>
/// Extension method for Texture.
/// Flips a Texture2D horizontally
/// </summary>
/// <param name="texture">Texture to flip.</param>
/// <returns>Horizontally flipped Texture2D.</returns>
public static Texture2D CTFlipHorizontal(this Texture2D texture)
{
Texture2D flipped = new Texture2D(texture.width, texture.height);
int width = texture.width;
int height = texture.height;
for (int xx = 0; xx < width; xx++)
{
for (int yy = 0; yy < height; yy++)
{
flipped.SetPixel(width - xx - 1, yy, texture.GetPixel(xx, yy));
}
}
flipped.Apply();
return flipped;
}
/// <summary>
/// Extension method for Texture.
/// Flips a Texture2D vertically
/// </summary>
/// <param name="texture">Texture to flip.</param>
/// <returns>Vertically flipped Texture2D.</returns>
public static Texture2D CTFlipVertical(this Texture2D texture)
{
Texture2D flipped = new Texture2D(texture.width, texture.height);
int width = texture.width;
int height = texture.height;
for (int xx = 0; xx < width; xx++)
{
for (int yy = 0; yy < height; yy++)
{
flipped.SetPixel(xx, height - yy - 1, texture.GetPixel(xx, yy));
}
}
flipped.Apply();
return flipped;
}
#endregion
#region AudioSource
/// <summary>
/// Extension method for AudioSource.
/// Determines if an AudioSource has an active clip.
/// </summary>
/// <param name="source">AudioSource to check.</param>
/// <returns>True if the AudioSource has an active clip.</returns>
public static bool CTHasActiveClip(this AudioSource source)
{
if (source == null)
return false;
if (source.clip == null)
return false;
bool loop;
int timeSamples;
return (source.isPlaying ||
(loop = source.loop) ||
(!loop && (timeSamples = source.timeSamples) > 0 && timeSamples < source.clip.samples - 1024));
}
#endregion
#region C# specific
#if (!UNITY_WSA && !UNITY_WEBGL && !UNITY_XBOXONE) || UNITY_EDITOR
/// <summary>
/// Extension method for Thread.
/// Aborts a Thread safely and optional silently
/// </summary>
/// <param name="thread">Thread to abort.</param>
/// <param name="silent">Silently abort the Thread (optional, default: true).</param>
public static void CTAbort(this System.Threading.Thread thread, bool silent = true)
{
if (thread == null)
return;
if (thread.IsAlive)
{
try
{
thread.Abort();
}
catch (System.Exception ex)
{
if (!silent)
Debug.LogWarning(ex);
}
}
}
#endif
#endregion
#region Unity specific
/// <summary>
/// Extension method for Renderer.
/// Determines if the renderer is visible from a certain camera.
/// </summary>
/// <param name="renderer">Renderer to test the visibility.</param>
/// <param name="camera">Camera for the test.</param>
/// <returns>True if the renderer is visible by the given camera.</returns>
public static bool CTIsVisibleFrom(this Renderer renderer, Camera camera)
{
if (renderer == null)
throw new System.ArgumentNullException(nameof(renderer));
if (camera == null)
throw new System.ArgumentNullException(nameof(camera));
Plane[] planes = GeometryUtility.CalculateFrustumPlanes(camera);
return GeometryUtility.TestPlanesAABB(planes, renderer.bounds);
}
#endregion
#region Private methods
private static Transform deepSearch(Transform parent, string name)
{
Transform tf = parent.Find(name);
if (tf != null)
return tf;
foreach (Transform child in parent)
{
tf = deepSearch(child, name);
if (tf != null)
return tf;
}
return null;
}
private static System.Collections.Generic.List<Transform> getAllChildren(this Transform parent, int maxDepth = 0, System.Collections.Generic.List<Transform> transformList = null, int depth = 0)
{
if (transformList == null) transformList = new System.Collections.Generic.List<Transform>();
if (maxDepth != 0)
depth++;
if (depth <= maxDepth)
{
foreach (Transform child in parent)
{
transformList.Add(child);
child.getAllChildren(maxDepth, transformList, depth);
}
}
return transformList;
}
private static float bytesToFloat(byte firstByte, byte secondByte)
{
// convert two bytes to one short (little endian) and convert it to range from -1 to (just below) 1
return (short)((secondByte << 8) | firstByte) / Crosstales.Common.Util.BaseConstants.FLOAT_32768;
}
#endregion
/*
/// <summary>
/// Perform a deep Copy of the object.
/// </summary>
/// <typeparam name="T">The type of object being copied.</typeparam>
/// <param name="source">The object instance to copy.</param>
/// <returns>The copied object.</returns>
public static T Clone<T>(this T source)
{
if (!typeof(T).IsSerializable)
{
throw new ArgumentException("The type must be serializable.", "source");
}
// Don't serialize a null object, simply return the default for that object
if (Object.ReferenceEquals(source, null))
{
return default(T);
}
IFormatter formatter = new BinaryFormatter();
Stream stream = new MemoryStream();
using (stream)
{
formatter.Serialize(stream, source);
stream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
}
}
*/
/*
/// <summary>
/// Clone a List with elememts containing a copy constructor.
/// </summary>
/// <param name="list">List-instance to clone.</param>
/// <returns>Clones list.</returns>
public static List<T> CTClone<T>(this List<T> listToClone) where T : ICopyable
{
List<T> newList = new List<T>(listToClone.Count);
listToClone.ForEach((item) =>
{
newList.Add(new T(item));
});
return newList;
//return listToClone.Select(item => (T)item.Clone()).ToList();
}
*/
/*
public static string[] CTToUppercase(string[] array)
{
if (array == null || array.Length <= 0)
throw new ArgumentNullException("array");
string[] result = new string[array.Length];
for (int ii = 0; ii < array.Length; ii++)
{
result[ii] = array[ii].ToUpper();
}
return result;
}
public static string[] CTToLowercase(string[] array)
{
if (array == null || array.Length <= 0)
throw new ArgumentNullException("array");
string[] result = new string[array.Length];
for (int ii = 0; ii < array.Length; ii++)
{
result[ii] = array[ii].ToLower();
}
return result;
}
*/
}
}
// © 2016-2023 crosstales LLC (https://www.crosstales.com)