This commit is contained in:
2026-05-17 15:12:16 +07:00
parent 93da00c206
commit bf0ebe447d
902 changed files with 142169 additions and 31515 deletions

View File

@@ -0,0 +1,351 @@
using UnityEngine;
namespace DA_Assets.Extensions
{
public static class AdaptivityExtensions
{
private static void SetSmartPivot(RectTransform rect, float value, int axis, bool smart, bool parentSpace)
{
Vector3 cornerBefore = GetRectReferenceCorner(rect, !parentSpace);
Vector2 rectPivot = rect.pivot;
rectPivot[axis] = value;
rect.pivot = rectPivot;
if (smart)
{
Vector3 cornerAfter = GetRectReferenceCorner(rect, !parentSpace);
Vector3 cornerOffset = cornerAfter - cornerBefore;
rect.anchoredPosition -= (Vector2)cornerOffset;
Vector3 pos = rect.transform.position;
pos.z -= cornerOffset.z;
rect.transform.position = pos;
}
}
private static Vector3 GetRectReferenceCorner(RectTransform gui, bool worldSpace)
{
Vector3[] s_Corners = new Vector3[4];
if (worldSpace)
{
Transform t = gui.transform;
gui.GetWorldCorners(s_Corners);
if (t.parent)
return t.parent.InverseTransformPoint(s_Corners[0]);
else
return s_Corners[0];
}
return (Vector3)gui.rect.min + gui.transform.localPosition;
}
private static AnchorMinMax GetAnchor(AnchorType anchorPreset)
{
AnchorMinMax minMax = new AnchorMinMax();
switch (anchorPreset)
{
case AnchorType.TopLeft:
{
minMax.Min = new Vector2(0, 1);
minMax.Max = new Vector2(0, 1);
break;
}
case AnchorType.TopCenter:
{
minMax.Min = new Vector2(0.5f, 1);
minMax.Max = new Vector2(0.5f, 1);
break;
}
case AnchorType.TopRight:
{
minMax.Min = new Vector2(1, 1);
minMax.Max = new Vector2(1, 1);
break;
}
case AnchorType.MiddleLeft:
{
minMax.Min = new Vector2(0, 0.5f);
minMax.Max = new Vector2(0, 0.5f);
break;
}
case AnchorType.MiddleCenter:
{
minMax.Min = new Vector2(0.5f, 0.5f);
minMax.Max = new Vector2(0.5f, 0.5f);
break;
}
case AnchorType.MiddleRight:
{
minMax.Min = new Vector2(1, 0.5f);
minMax.Max = new Vector2(1, 0.5f);
break;
}
case AnchorType.BottomLeft:
{
minMax.Min = new Vector2(0, 0);
minMax.Max = new Vector2(0, 0);
break;
}
case AnchorType.BottomCenter:
{
minMax.Min = new Vector2(0.5f, 0);
minMax.Max = new Vector2(0.5f, 0);
break;
}
case AnchorType.BottomRight:
{
minMax.Min = new Vector2(1, 0);
minMax.Max = new Vector2(1, 0);
break;
}
case AnchorType.HorStretchTop:
{
minMax.Min = new Vector2(0, 1);
minMax.Max = new Vector2(1, 1);
break;
}
case AnchorType.HorStretchMiddle:
{
minMax.Min = new Vector2(0, 0.5f);
minMax.Max = new Vector2(1, 0.5f);
break;
}
case AnchorType.HorStretchBottom:
{
minMax.Min = new Vector2(0, 0);
minMax.Max = new Vector2(1, 0);
break;
}
case AnchorType.VertStretchLeft:
{
minMax.Min = new Vector2(0, 0);
minMax.Max = new Vector2(0, 1);
break;
}
case AnchorType.VertStretchCenter:
{
minMax.Min = new Vector2(0.5f, 0);
minMax.Max = new Vector2(0.5f, 1);
break;
}
case AnchorType.VertStretchRight:
{
minMax.Min = new Vector2(1, 0);
minMax.Max = new Vector2(1, 1);
break;
}
case AnchorType.StretchAll:
{
minMax.Min = new Vector2(0, 0);
minMax.Max = new Vector2(1, 1);
break;
}
}
return minMax;
}
private static Vector2 GetPivot(PivotType preset)
{
switch (preset)
{
case PivotType.TopLeft:
{
return new Vector2(0, 1);
}
case PivotType.TopCenter:
{
return new Vector2(0.5f, 1);
}
case PivotType.TopRight:
{
return new Vector2(1, 1);
}
case PivotType.MiddleLeft:
{
return new Vector2(0, 0.5f);
}
case PivotType.MiddleCenter:
{
return new Vector2(0.5f, 0.5f);
}
case PivotType.MiddleRight:
{
return new Vector2(1, 0.5f);
}
case PivotType.BottomLeft:
{
return new Vector2(0, 0);
}
case PivotType.BottomCenter:
{
return new Vector2(0.5f, 0);
}
case PivotType.BottomRight:
{
return new Vector2(1, 0);
}
default:
return GetPivot(PivotType.MiddleCenter);
}
}
private static void SetSmartAnchor(this RectTransform rect, RectAxis rectAxis, float value, bool isMax)
{
bool smart = true;
int _axis = (int)rectAxis;
RectTransform parent = null;
if (rect.transform.parent == null)
{
smart = false;
}
else
{
parent = rect.transform.parent.GetComponent<RectTransform>();
if (parent == null)
{
smart = false;
}
}
float offsetSizePixels = 0;
float offsetPositionPixels = 0;
if (smart)
{
float oldValue = isMax ? rect.anchorMax[_axis] : rect.anchorMin[_axis];
offsetSizePixels = (value - oldValue) * parent.rect.size[_axis];
float roundingDelta = 0;
Canvas canvas = rect.gameObject.GetComponentInParent<Canvas>();
bool shouldDoIntSnapping = canvas != null && canvas.renderMode != RenderMode.WorldSpace;
if (shouldDoIntSnapping)
roundingDelta = Mathf.Round(offsetSizePixels) - offsetSizePixels;
offsetSizePixels += roundingDelta;
offsetPositionPixels = (isMax ? offsetSizePixels * rect.pivot[_axis] : (offsetSizePixels * (1 - rect.pivot[_axis])));
}
if (isMax)
{
Vector2 rectAnchorMax = rect.anchorMax;
rectAnchorMax[_axis] = value;
rect.anchorMax = rectAnchorMax;
Vector2 other = rect.anchorMin;
rect.anchorMin = other;
}
else
{
Vector2 rectAnchorMin = rect.anchorMin;
rectAnchorMin[_axis] = value;
rect.anchorMin = rectAnchorMin;
Vector2 other = rect.anchorMax;
rect.anchorMax = other;
}
if (smart)
{
Vector2 rectPosition = rect.anchoredPosition;
rectPosition[_axis] -= offsetPositionPixels;
rect.anchoredPosition = rectPosition;
Vector2 rectSizeDelta = rect.sizeDelta;
rectSizeDelta[_axis] += offsetSizePixels * (isMax ? -1 : 1);
rect.sizeDelta = rectSizeDelta;
}
}
public static void SetSmartAnchor(this RectTransform rect, AnchorType anchorType)
{
AnchorMinMax anchor = GetAnchor(anchorType);
rect.SetSmartAnchor(RectAxis.Hor, anchor.Min.x, false);
rect.SetSmartAnchor(RectAxis.Hor, anchor.Max.x, true);
rect.SetSmartAnchor(RectAxis.Vert, anchor.Min.y, false);
rect.SetSmartAnchor(RectAxis.Vert, anchor.Max.y, true);
}
public static void SetSmartPivot(this RectTransform rect, PivotType pivotType)
{
Vector2 pivot = GetPivot(pivotType);
SetSmartPivot(rect, pivot.x, 0, true, false);
SetSmartPivot(rect, pivot.y, 1, true, false);
}
public static void SetRotation(this Transform source, float value)
{
source.localRotation = Quaternion.Euler(
source.localRotation.x,
source.localRotation.y,
value);
}
private enum RectAxis
{
Hor,
Vert
}
private struct AnchorMinMax
{
public Vector2 Min;
public Vector2 Max;
}
}
public enum AnchorType
{
TopLeft = 0,
TopCenter = 1,
TopRight = 2,
MiddleLeft = 3,
MiddleCenter = 4,
MiddleRight = 5,
BottomLeft = 6,
BottomCenter = 7,
BottomRight = 8,
BottomStretch = 9,
VertStretchLeft = 10,
VertStretchRight = 11,
VertStretchCenter = 12,
HorStretchTop = 13,
HorStretchMiddle = 14,
HorStretchBottom = 15,
StretchAll = 16,
}
public enum PivotType
{
TopLeft = 0,
TopCenter = 1,
TopRight = 2,
MiddleLeft = 3,
MiddleCenter = 4,
MiddleRight = 5,
BottomLeft = 6,
BottomCenter = 7,
BottomRight = 8,
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6bdb420b2e504b14a90dc566a4741b7c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,22 @@
using System.Collections.Generic;
using System.Linq;
namespace DA_Assets.Extensions
{
public static class AssetDatabaseExtensions
{
public static List<string> FindAssetsPathes<T>(this string path, string customType = null)
{
List<string> assetPathes = new List<string>();
if (customType == null)
customType = $"t:{typeof(T).Name}";
#if UNITY_EDITOR
string[] guids = UnityEditor.AssetDatabase.FindAssets(customType, new string[] { path.ToRelativePath() });
assetPathes = guids.Select(x => UnityEditor.AssetDatabase.GUIDToAssetPath(x)).ToList();
#endif
return assetPathes;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1c19f2ebb8f0b0a4bb4f73a230063a0d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,29 @@
using UnityEngine;
namespace DA_Assets.Extensions
{
public static class ColorBlenderExtensions
{
public static Color Difference(this Color c1, Color c2, float intensity)
{
float r = Mathf.Abs(c1.r - c2.r) * intensity;
float g = Mathf.Abs(c1.g - c2.g) * intensity;
float b = Mathf.Abs(c1.b - c2.b) * intensity;
Color result = new Color(r, g, b, c1.a);
return result;
}
public static Color Multiply(this Color c1, Color c2, float intensity)
{
Color result = c1.Lerp(c1 * c2, intensity);
return result;
}
public static Color Overlay(this Color c1, Color c2, float intensity)
{
Color blendedColor = c1.Lerp(c2, intensity);
return blendedColor;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f4206c7f0cf637b4193c2daad9d99b85
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,48 @@
using System;
using UnityEngine;
namespace DA_Assets.Extensions
{
public static class ColorExtensions
{
public static Color Lerp(this Color a, Color b, float t)
{
t = Mathf.Clamp01(t);
var result = new Color(a.r + (b.r - a.r) * t, a.g + (b.g - a.g) * t, a.b + (b.b - a.b) * t, a.a + (b.a - a.a) * t);
return result;
}
public static Color SetAlpha(this Color color, float? alpha)
{
return new Color(color.r, color.g, color.b, alpha == null ? 1 : alpha.ToFloat());
}
/// <summary>
/// <para>Example: "#ff000099".ToColor() red with alpha ~50%</para>
/// <para>Example: "ffffffff".ToColor() white with alpha 100%</para>
/// <para>Example: "00ff00".ToColor() green with alpha 100%</para>
/// <para>Example: "0000ff00".ToColor() blue with alpha 0%</para>
/// <para><see href="https://github.com/smkplus/KamaliDebug"/></para>
/// </summary>
public static Color ToColor(this string color)
{
if (color.StartsWith("#", StringComparison.InvariantCulture))
{
color = color.Substring(1); // strip #
}
if (color.Length == 6)
{
color += "FF"; // add alpha if missing
}
uint hex = Convert.ToUInt32(color, 16);
float r = ((hex & 0xff000000) >> 0x18) / 255f;
float g = ((hex & 0xff0000) >> 0x10) / 255f;
float b = ((hex & 0xff00) >> 8) / 255f;
float a = (hex & 0xff) / 255f;
return new Color(r, g, b, a);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9b50e7e9b4f60b04f89b3e958fc4ec95
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,128 @@
using System;
using System.Reflection;
using UnityEngine;
namespace DA_Assets.Extensions
{
public static class ComponentExtensions
{
public static void CopySerializedFields(this Component source, Component destination)
{
FieldInfo[] fields = source.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
foreach (FieldInfo field in fields)
{
if (field.IsPublic || field.GetCustomAttribute<SerializeField>() != null)
{
field.SetValue(destination, field.GetValue(source));
}
}
}
public static bool TryGetComponentSafe<T>(this Component gameObject, out T component)
{
component = default;
if (gameObject == null)
return false;
return gameObject.TryGetComponent(out component);
}
/// <summary>
/// Destroying script of Unity GameObject, but as an extension.
/// <para>Works in Editor and Playmode.</para>
/// </summary>
public static bool Destroy(this UnityEngine.Component unityComponent)
{
try
{
if (unityComponent.IsRequiredByAnotherComponents())
return false;
#if UNITY_EDITOR
UnityEngine.Object.DestroyImmediate(unityComponent);
#else
UnityEngine.Object.Destroy(unityComponent);
#endif
return true;
}
catch
{
return false;
}
}
/// <summary>
/// Removes all components from the GameObject that have a 'RequireComponent' attribute pointing to the given component.
/// </summary>
/// <param name="component">The target component which other components might depend on.</param>
/// <returns>True if any dependent components were removed, false otherwise.</returns>
public static bool RemoveComponentsDependingOn(this UnityEngine.Component component)
{
bool removedAny = false; // Flag to indicate if we've removed any components.
Type type = component.GetType();
// Get all components present on the GameObject where the target component resides.
Component[] componentsOnObject = component.gameObject.GetComponents<Component>();
// Iterate through each component on the GameObject.
foreach (Component comp in componentsOnObject)
{
// Fetch all the RequireComponent attributes associated with the component.
object[] requireAttributes = comp.GetType().GetCustomAttributes(typeof(RequireComponent), true);
// Iterate through each RequireComponent attribute to check if our target component type is listed.
foreach (RequireComponent attribute in requireAttributes)
{
// Check if any of the required types match the type of our target component.
if (attribute.m_Type0 == type ||
attribute.m_Type1 == type ||
attribute.m_Type2 == type)
{
// Remove the component that depends on the target component.
comp.Destroy();// UnityEngine.Object.Destroy(comp);
removedAny = true; // Set the flag since we've removed a component.
break; // Exit the inner loop since we've made a modification.
}
}
}
return removedAny; // Return the flag indicating if any components were removed.
}
/// <summary>
/// Checks if the given component is required by any other components on the same GameObject via the RequireComponent attribute.
/// </summary>
/// <param name="component">The component to check for.</param>
/// <returns>True if the component is required by another component on the same GameObject, otherwise false.</returns>
public static bool IsRequiredByAnotherComponents(this UnityEngine.Component component)
{
Type type = component.GetType();
// Get all components present on the GameObject where the target component resides.
Component[] componentsOnObject = component.gameObject.GetComponents<Component>();
// Iterate through each component on the GameObject.
foreach (Component comp in componentsOnObject)
{
// Fetch all the RequireComponent attributes associated with the component.
object[] requireAttributes = comp.GetType().GetCustomAttributes(typeof(RequireComponent), true);
// Iterate through each RequireComponent attribute to check if our target component type is listed.
foreach (RequireComponent attribute in requireAttributes)
{
// Check if any of the required types match the type of our target component.
if (attribute.m_Type0 == type ||
attribute.m_Type1 == type ||
attribute.m_Type2 == type)
{
// If a match is found, return true indicating the component is required by another.
return true;
}
}
}
// If no matches were found, return false.
return false;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1c4f23c9c4c1eaa4887d52c43453738c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,51 @@
using System.Security.Cryptography;
using System.Text;
namespace DA_Assets.Extensions
{
public static class CryptoExtensions
{
public static string CreateShortGuid(this string value, out string result)
{
if (string.IsNullOrWhiteSpace(value))
value = System.Guid.NewGuid().ToString().Split('-')[0];
result = value;
return value;
}
public static byte[] GetSHA1Hash(this string value)
{
byte[] bytes = Encoding.UTF8.GetBytes(value);
using (SHA1 sha1 = SHA1.Create())
{
byte[] result = sha1.ComputeHash(bytes);
return result;
}
}
public static string ToHEX(this byte[] bytes)
{
StringBuilder buffer = new StringBuilder(bytes.Length * 2);
foreach (var byt in bytes)
{
buffer.Append(byt.ToString("X2"));
}
return buffer.ToString();
}
public static string Base64Decode(this string base64EncodedData)
{
var base64EncodedBytes = System.Convert.FromBase64String(base64EncodedData);
return System.Text.Encoding.UTF8.GetString(base64EncodedBytes);
}
public static string Base64Encode(this string plainText)
{
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
return System.Convert.ToBase64String(plainTextBytes);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 43d14e50078ff2c428e6e923c235bde0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,22 @@
using System;
namespace DA_Assets.Extensions
{
public static class EnumExtensions
{
public static bool Contains(this Enum value, string str)
{
return value.ToString().Contains(str);
}
public static string ToLower(this Enum value)
{
return value.ToString().ToLower();
}
public static string ToUpper(this Enum value)
{
return value.ToString().ToUpper();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 82c89c45d46e01c45a1546d7ee9d0f76
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,116 @@
using System;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using UnityEngine;
namespace DA_Assets.Extensions
{
public static class FileExtensions
{
public static void OpenFolderInOS(this string path)
{
Application.OpenURL("file://" + path);
}
public static string GetPathRelativeToProjectDirectory(this string path)
{
char slash = path.Contains('/') ? '/' : '\\';
string result = string.Join(slash.ToString(), path.Split(new char[1] { slash })
.SkipWhile((string s) => s.ToLower() != "assets")
.ToArray());
return result;
}
/// <summary>
/// Replaces text in a file.
/// <para><see href="https://stackoverflow.com/a/58377834/8265642"/></para>
/// </summary>
/// <param name="filePath">Path of the text file.</param>
/// <param name="searchText">Text to search for.</param>
/// <param name="replaceText">Text to replace the search text.</param>
static public void ReplaceInFile(string filePath, string searchText, string replaceText)
{
StreamReader reader = new StreamReader(filePath);
string content = reader.ReadToEnd();
reader.Close();
content = Regex.Replace(content, searchText, replaceText);
StreamWriter writer = new StreamWriter(filePath);
writer.Write(content);
writer.Close();
}
public static void CreateFolderIfNotExists(this string path)
{
if (Directory.Exists(path) == false)
{
Directory.CreateDirectory(path);
}
}
public static bool TryReadAllText(this string path, out string text)
{
try
{
text = File.ReadAllText(path);
return true;
}
catch
{
text = null;
return false;
}
}
public static string GetFullAssetPath(this string assetPath)
{
//TODO: wrong logic when no image
if (assetPath.IsEmpty())
{
return "";
}
string p2 = assetPath.Substring("Assets".Length + 1);
string fullPath = Path.Combine(Application.dataPath, p2);
return fullPath;
}
public static bool IsPathInsideAssetsPath(this string path)
{
if (path.IndexOf(Application.dataPath, System.StringComparison.InvariantCultureIgnoreCase) == -1)
{
return false;
}
return true;
}
/// <summary>
/// http://answers.unity.com/answers/787336/view.html
/// </summary>
public static string ToRelativePath(this string absolutePath)
{
if (absolutePath.StartsWith(Application.dataPath))
{
return "Assets" + absolutePath.Substring(Application.dataPath.Length);
}
return absolutePath;
}
public static string RemoveInvalidCharsFromFileName(this string fileName, char repl = '_')
{
if(string.IsNullOrWhiteSpace(fileName))
return fileName;
char[] invalidChars = Path.GetInvalidFileNameChars();
foreach (char c in invalidChars)
fileName = fileName.Replace(c, repl);
return fileName;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6524e57dc4d98a14f8146352f930e583
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,65 @@
using System;
namespace DA_Assets.Extensions
{
public static class Levenshtein
{
/// <summary>
/// Calculate percentage similarity of two strings
/// <param name="source">Source String to Compare with</param>
/// <param name="target">Targeted String to Compare</param>
/// <returns>Return Similarity between two strings from 0 to 1.0</returns>
/// <para><see cref="https://stackoverflow.com/a/2344347"/></para>
/// </summary>
public static float CalculateSimilarity(this string source, string target)
{
if ((source == null) || (target == null)) return 0.0f;
if ((source.Length == 0) || (target.Length == 0)) return 0.0f;
if (source == target) return 1.0f;
int stepsToSame = ComputeLevenshteinDistance(source, target);
return (1.0f - (stepsToSame / (float)Math.Max(source.Length, target.Length)));
}
/// <summary>
/// Returns the number of steps required to transform the source string
/// into the target string.
/// </summary>
private static int ComputeLevenshteinDistance(string source, string target)
{
if ((source == null) || (target == null)) return 0;
if ((source.Length == 0) || (target.Length == 0)) return 0;
if (source == target) return source.Length;
int sourceWordCount = source.Length;
int targetWordCount = target.Length;
// Step 1
if (sourceWordCount == 0)
return targetWordCount;
if (targetWordCount == 0)
return sourceWordCount;
int[,] distance = new int[sourceWordCount + 1, targetWordCount + 1];
// Step 2
for (int i = 0; i <= sourceWordCount; distance[i, 0] = i++) ;
for (int j = 0; j <= targetWordCount; distance[0, j] = j++) ;
for (int i = 1; i <= sourceWordCount; i++)
{
for (int j = 1; j <= targetWordCount; j++)
{
// Step 3
int cost = (target[j - 1] == source[i - 1]) ? 0 : 1;
// Step 4
distance[i, j] = Math.Min(Math.Min(distance[i - 1, j] + 1, distance[i, j - 1] + 1), distance[i - 1, j - 1] + cost);
}
}
return distance[sourceWordCount, targetWordCount];
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c48acc25efb6e1b48a99548fe4264b03
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,319 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
namespace DA_Assets.Extensions
{
public static class ListExtensions
{
public static ConcurrentBag<T> ToConcurrentBag<T>(this IEnumerable<T> source)
{
return new ConcurrentBag<T>(source);
}
public static ConcurrentDictionary<TKey, TValue> ToConcurrentDictionary<TSource, TKey, TValue>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
Func<TSource, TValue> valueSelector)
{
var dictionary = new ConcurrentDictionary<TKey, TValue>();
foreach (var element in source)
{
dictionary.TryAdd(keySelector(element), valueSelector(element));
}
return dictionary;
}
/// <summary>
/// https://stackoverflow.com/a/55182157
/// </summary>
public static IEnumerable<T> SelectRecursive<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> selector)
{
foreach (var parent in source)
{
yield return parent;
var children = selector(parent);
foreach (var child in SelectRecursive(children, selector))
yield return child;
}
}
public static bool TryAddValue<T>(this HashSet<T> hs, T value)
{
try
{
hs.Add(value);
return true;
}
catch
{
return false;
}
}
public static bool TryAddValue<TKey, TValue>(this IDictionary<TKey, TValue> dic, TKey key, TValue value)
{
try
{
dic.Add(key, value);
return true;
}
catch
{
return false;
}
}
/// <summary>
/// https://stackoverflow.com/a/110570/8265642
/// </summary>
public static void Shuffle<T>(this IList<T> array)
{
System.Random rng = new System.Random();
int n = array.Count();
while (n > 1)
{
int k = rng.Next(n--);
T temp = array[n];
array[n] = array[k];
array[k] = temp;
}
}
public static bool ContainsAll<T>(this List<T> a, List<T> b)
{
return !b.Except(a).Any();
}
public static IEnumerable<T> GetRangeSafe<T>(this IEnumerable<T> _list, int index, int count = 0)
{
if (_list.IsEmpty())
return new List<T>();
if (_list.Count() == 1)
return new List<T>() { _list.First() };
if (index < 0 || count < 0)
return new List<T>();
if (index > _list.Count() - 1)
return new List<T>();
if (index <= _list.Count() - 1 && (_list.Count() - 1 < index + count) || count == 0)
return _list.ToList().GetRange(index, _list.Count() - index);
try
{
return _list.ToList().GetRange(index, count);
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// https://stackoverflow.com/a/6488922
/// </summary>
public static IEnumerable<T2> GetDuplicates<T1, T2>(this Dictionary<T1, List<T2>> data)
{
// find duplicates
var dupes = new HashSet<T2>(
from list1 in data.Values
from list2 in data.Values
where list1 != list2
from item in list1.Intersect(list2)
select item);
// return a list of the duplicates
return dupes;
}
public static IEnumerable<TSource> Exclude<TSource, TKey>(this IEnumerable<TSource> source,
IEnumerable<TSource> exclude, Func<TSource, TKey> keySelector)
{
var excludedSet = new HashSet<TKey>(exclude.Select(keySelector));
return source.Where(item => !excludedSet.Contains(keySelector(item)));
}
/// <summary>
/// https://stackoverflow.com/a/36856433
/// </summary>
public static bool ContainsAll<T>(this IEnumerable<T> source, IEnumerable<T> values)
{
return values.All(value => source.Contains(value));
}
/// <summary>
/// The method checks if collection1 contains at least one element of collection2.
/// </summary>
public static bool ContainsList<T>(this IEnumerable<T> collection1, IEnumerable<T> collection2)
{
foreach (T item1 in collection1)
{
if (collection2.Contains(item1))
{
return true;
}
}
return false;
}
/// <summary>
/// Checks if the IEnumerable contains only duplicates.
/// </summary>
public static bool IsContainsElementOnly<T>(this IEnumerable<T> ienum, T element)
{
if (ienum == null)
{
return false;
}
if (ienum.Count() == 0)
{
return false;
}
foreach (var item in ienum)
{
if (item.Equals(element) == false)
{
return false;
}
}
return true;
}
/// <summary>
/// Finds the maximum element in the list by a specific field, not by all fields of an object.
/// <para><see href="https://stackoverflow.com/a/31864296"/></para>
/// </summary>
public static T MaxBy<T, R>(this IEnumerable<T> en, Func<T, R> evaluate) where R : IComparable<R>
{
return en.Select(t => new Tuple<T, R>(t, evaluate(t)))
.Aggregate((max, next) => next.Item2.CompareTo(max.Item2) > 0 ? next : max).Item1;
}
public static IEnumerable<T> GetBetweenElement<T>(this T element, IEnumerable<T> ienumerable)
{
List<T> between = new List<T>();
foreach (T item in ienumerable)
{
if (element.Equals(item) == false)
{
between.Add(item);
}
else
{
break;
}
}
return between;
}
public static bool IsEmpty(this byte[] byteArray)
{
if (byteArray != null && byteArray.Length > 0)
{
return false;
}
else
{
return true;
}
}
/// <summary>
/// Extensions to shorten the check for the presence of elements in the IEnumerable.
/// </summary>
public static bool IsEmpty<T>(this IEnumerable<T> collection)
{
if (collection != null && collection.Count() > 0)
{
return false;
}
else
{
return true;
}
}
/// <summary>
/// Split's list to X parts.
/// <para><see href="https://stackoverflow.com/a/419063"/></para>
/// </summary>
public static List<List<T>> Split<T>(this IEnumerable<T> array, int batchSize)
{
int i = 0;
List<List<T>> result = array.GroupBy(s => i++ / batchSize).Select(g => g.ToList()).ToList();
return result;
}
public static int CountAll<T>(this IEnumerable<IEnumerable<T>> listOfLists)
{
if (listOfLists.IsEmpty())
{
return 0;
}
int totalCount = 0;
foreach (var innerList in listOfLists)
{
if (innerList.IsEmpty())
continue;
totalCount += innerList.Count();
}
return totalCount;
}
public static List<T> FromChunks<T>(this IEnumerable<IEnumerable<T>> chunks)
{
try
{
var notDefault = chunks.SelectMany(x => x).Where(x => x.IsDefault() == false);
return notDefault.ToList();
}
catch (Exception)
{
return new List<T>();
}
}
/// <summary>
/// Adds dictionary to another dictionary.
/// <para><see href="https://stackoverflow.com/a/3982463"/></para>
/// </summary>
public static void AddRange<T>(this ICollection<T> target, IEnumerable<T> source)
{
if (target == null)
throw new ArgumentNullException(nameof(target));
if (source == null)
throw new ArgumentNullException(nameof(source));
foreach (T element in source)
target.Add(element);
}
public static List<string> Reverse(this List<string> array)
{
for (int i = 0; i < array.Count() / 2; i++)
{
string tmp = array[i];
array[i] = array[array.Count() - i - 1];
array[array.Count() - i - 1] = tmp;
}
return array;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cb488b4e150d26942b4c98b673d4794d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,197 @@
using System;
using System.Globalization;
using UnityEngine;
namespace DA_Assets.Extensions
{
public static class MathExtensions
{
public static bool TryParseWithDot(this string str, out float value) =>
float.TryParse(str, NumberStyles.Float, CultureInfo.InvariantCulture, out value);
public static string ToDotString(this float value) =>
value.ToString(CultureInfo.InvariantCulture);
public static float ToFloat(this float? value)
{
return value.HasValue ? value.Value : 0;
}
public static System.Numerics.BigInteger ToBigInteger(this byte[] data)
{
return new System.Numerics.BigInteger(data);
}
public static int NormalizeAngleToSize(this float val, float width, float height)
{
if (val <= 0)
{
val = 0;
return (int)val;
}
float resW = width / val;
float resH = height / val;
if (resW < 2 || resH < 2)
{
int min = Mathf.Min((int)(width / 2), (int)(height / 2));
val = min;
}
if (val <= 0)
val = 0;
return (int)val;
}
/// <summary>
/// <para><see href="https://stackoverflow.com/a/2722999"/></para>
/// </summary>
public static bool TryParseFloat(this string input, out float result)
{
// try parsing with "fr-FR" first
bool success = float.TryParse(input,
NumberStyles.Float | NumberStyles.AllowThousands,
CultureInfo.GetCultureInfo("fr-FR"),
out result);
if (!success)
{
// parsing with "fr-FR" failed so try parsing with InvariantCulture
success = float.TryParse(input,
NumberStyles.Float | NumberStyles.AllowThousands,
CultureInfo.InvariantCulture,
out result);
}
return success;
}
public static float CalculateIntersectionFactor(this Vector3 lineStart, Vector2 lineEnd, Vector2 origin, Vector2 direction)
{
// Calculate the determinant to check if the line (lineStart to lineEnd) and the direction vector are parallel
float determinant = (lineEnd.x - lineStart.x) * direction.y - (lineEnd.y - lineStart.y) * direction.x;
// Use Mathf.Approximately to check for equality considering floating-point imprecision
if (Mathf.Approximately(determinant, 0f))
{
// Returning -1 to indicate the lines are parallel or overlapping with no distinct intersection
return -1;
}
// Calculate and return the intersection factor along the line from lineStart to lineEnd
// where an intersection with the vector originating from 'origin' in the 'direction' occurs
float intersectionFactor = ((origin.x - lineStart.x) * direction.y - (origin.y - lineStart.y) * direction.x) / determinant;
return intersectionFactor;
}
public static UIVertex Lerp(this UIVertex vertex1, UIVertex vertex2, float interpolationFactor)
{
UIVertex vertex = new UIVertex();
vertex.position = Vector3.Lerp(vertex1.position, vertex2.position, interpolationFactor);
vertex.color = Color.Lerp(vertex1.color, vertex2.color, interpolationFactor);
vertex.uv0 = Vector2.Lerp(vertex1.uv0, vertex2.uv0, interpolationFactor);
vertex.uv1 = Vector2.Lerp(vertex1.uv1, vertex2.uv1, interpolationFactor);
vertex.uv2 = Vector2.Lerp(vertex1.uv2, vertex2.uv2, interpolationFactor);
vertex.uv3 = Vector2.Lerp(vertex1.uv3, vertex2.uv3, interpolationFactor);
return vertex;
}
public static Vector2 Rotate(this Vector2 v, float degrees)
{
float sin = Mathf.Sin(degrees * Mathf.Deg2Rad);
float cos = Mathf.Cos(degrees * Mathf.Deg2Rad);
float tx = v.x;
float ty = v.y;
v.x = (cos * tx) - (sin * ty);
v.y = (sin * tx) + (cos * ty);
return v;
}
public static float NormalizeAngle360(this float angle)
{
if (angle < 0)
{
angle = (angle % 360) + 360;
}
else
{
angle = angle % 360;
}
return angle;
}
/// <summary>
/// <para><see href="https://andrewlock.net/why-is-string-gethashcode-different-each-time-i-run-my-program-in-net-core/"/></para>
/// </summary>
public static int GetDeterministicHashCode(this string str)
{
unchecked
{
int hash1 = (5381 << 16) + 5381;
int hash2 = hash1;
for (int i = 0; i < str.Length; i += 2)
{
hash1 = ((hash1 << 5) + hash1) ^ str[i];
if (i == str.Length - 1)
break;
hash2 = ((hash2 << 5) + hash2) ^ str[i + 1];
}
return hash1 + (hash2 * 1566083941);
}
}
/// <summary>
/// Remap value from these interval to another interval with saving proportion
/// <para><see href="https://forum.unity.com/threads/re-map-a-number-from-one-range-to-another.119437/"/></para>
/// </summary>
/// <param name="value">Value for remapping</param>
/// <param name="sourceMin"></param>
/// <param name="sourceMax"></param>
/// <param name="targetMin"></param>
/// <param name="targetMax"></param>
/// <returns></returns>
public static float Remap(this float value, float sourceMin, float sourceMax, float targetMin, float targetMax)
{
return (value - sourceMin) / (sourceMax - sourceMin) * (targetMax - targetMin) + targetMin;
}
/// <summary>
/// Makes random bool.
/// <para><see href="https://forum.unity.com/threads/random-randomboolean-function.83220/#post-548687"/></para>
/// </summary>
public static bool RandomBool => UnityEngine.Random.value > 0.5f;
public static Vector4 Round(this Vector4 vector4, int dp = 0)
{
float x = (float)System.Math.Round(vector4.x, dp);
float y = (float)System.Math.Round(vector4.y, dp);
float z = (float)System.Math.Round(vector4.z, dp);
float w = (float)System.Math.Round(vector4.w, dp);
return new Vector4(x, y, z, w);
}
public static Vector2 Round(this Vector2 vector2, int dp = 0)
{
float x = (float)System.Math.Round(vector2.x, dp);
float y = (float)System.Math.Round(vector2.y, dp);
return new Vector2(x, y);
}
public static float RoundToNearest025(this float value) => Mathf.Round(value * 4f) / 4f;
public static float Round(this float value, int digits) => (float)Math.Round((double)value, digits);
public static Vector2Int ToVector2Int(this Vector2 vector) => new Vector2Int((int)vector.x, (int)vector.y);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f7d38f396b24c174d8cb981e92dc9d93
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,346 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
#pragma warning disable CS0162
namespace DA_Assets.Extensions
{
public static class MonoBehExtensions
{
public static void DestroyChilds(this GameObject parent)
{
if (parent == null)
return;
int childCount = parent.transform.childCount;
for (int i = childCount - 1; i >= 0; i--)
{
GameObject go = parent.transform.GetChild(i).gameObject;
go.Destroy();
}
Debug.Log("log_current_canvas_childs_destroy " + childCount);
}
public static bool TryGetComponentSafe<T>(this GameObject gameObject, out T component)
{
component = default;
if (gameObject == null)
return false;
return gameObject.TryGetComponent(out component);
}
public static T[] GetChilds<T>(this GameObject gameObject)
{
T[] childs = gameObject.GetComponentsInChildren<T>(true).Skip(1).ToArray();
return childs;
}
/// <summary>
/// Removes the RectTransform component from a GameObject by creating a new GameObject
/// with the same components (excluding RectTransform), children, and parent.
/// </summary>
/// <param name="gameObject">The GameObject from which to remove the RectTransform.</param>
public static GameObject RemoveRectTransform(this GameObject gameObject)
{
// Create a new GameObject
GameObject newGameObject = CreateEmptyGameObject();
newGameObject.name = gameObject.name;
// Save the siblingIndex of the old GameObject
int siblingIndex = gameObject.transform.GetSiblingIndex();
// Assign the parent object
newGameObject.transform.SetParent(gameObject.transform.parent);
newGameObject.transform.localPosition = gameObject.transform.localPosition;
newGameObject.transform.localRotation = gameObject.transform.localRotation;
newGameObject.transform.localScale = gameObject.transform.localScale;
// Set siblingIndex for the new GameObject
newGameObject.transform.SetSiblingIndex(siblingIndex);
// Transfer all child objects
for (int i = gameObject.transform.childCount - 1; i >= 0; i--)
{
Transform child = gameObject.transform.GetChild(i);
// Save the siblingIndex for child objects
int childSiblingIndex = child.GetSiblingIndex();
child.SetParent(newGameObject.transform);
child.SetSiblingIndex(childSiblingIndex);
}
// Copy all components
Component[] components = gameObject.GetComponents<Component>();
foreach (Component component in components)
{
if (!(component is Transform))
{
Component newComponent = newGameObject.AddComponent(component.GetType());
component.CopySerializedFields(newComponent);
}
}
// Destroy the old GameObject
gameObject.Destroy();
return newGameObject;
}
public static List<T> GetComponentsInReverseOrder<T>(this GameObject parent) where T : Component
{
List<T> results = new List<T>();
AddComponentsInReverseOrder(parent.transform);
return results;
void AddComponentsInReverseOrder(Transform current)
{
for (int i = current.childCount - 1; i >= 0; i--)
{
AddComponentsInReverseOrder(current.GetChild(i));
}
T component = current.GetComponent<T>();
if (component != null/* && !results.Contains(component)*/)
{
results.Add(component);
}
}
}
/// <summary>
/// Saves the GameObject as a prefab asset at the specified local path and tries to get the component of type T from the prefab.
/// </summary>
/// <typeparam name="T">The type of the MonoBehaviour to retrieve from the prefab.</typeparam>
/// <param name="gameObject">The GameObject to be saved as a prefab.</param>
/// <param name="localPath">The local path within the project where the prefab should be saved.</param>
/// <param name="savedPrefab">The component of type T retrieved from the prefab, or null if the operation failed.</param>
/// <param name="ex">Any exceptions that occurred during the process.</param>
/// <returns>True if the prefab was saved and the component of type T was successfully retrieved, otherwise false.</returns>
public static bool SaveAsPrefabAsset<T>(this GameObject gameObject, string localPath, out T savedPrefab, out Exception ex) where T : MonoBehaviour
{
// Check for null GameObject
if (gameObject == null)
{
ex = new NullReferenceException("GameObject is null.");
savedPrefab = null;
return false;
}
#if UNITY_EDITOR
// Save the GameObject as a prefab asset in Editor mode.
GameObject prefabGo = null;
try
{
prefabGo = UnityEditor.PrefabUtility.SaveAsPrefabAsset(gameObject, localPath, out bool success);
}
catch (Exception ex1)
{
ex = ex1;
}
if (prefabGo == null)
{
ex = new NullReferenceException("Prefab is null.");
savedPrefab = null;
return false;
}
// Attempt to get the component of type T from the saved prefab.
if (prefabGo.TryGetComponent<T>(out T prefabComponent))
{
ex = null;
savedPrefab = prefabComponent;
return true;
}
else
{
// Handle the case where the component of type T can't be found on the prefab.
ex = new Exception($"Can't get Type '{typeof(T).Name}' from GameObject '{prefabGo.name}'.");
savedPrefab = null;
return false;
}
#endif
// Handle cases outside of Editor mode.
ex = new Exception("Unsupported in not-Editor mode.");
savedPrefab = null;
return false;
}
/// <summary>
/// Checks if the provided UnityEngine.Object is part of any prefab.
/// </summary>
/// <param name="gameObject">The UnityEngine.Object to check.</param>
/// <returns>True if the object is part of a prefab, otherwise false.</returns>
public static bool IsPartOfAnyPrefab(this UnityEngine.Object gameObject)
{
if (gameObject == null)
return false;
#if UNITY_EDITOR
return UnityEditor.PrefabUtility.IsPartOfAnyPrefab(gameObject);
#endif
return false;
}
/// <summary>
/// Checks if any instance of the provided MonoBehaviour type exists on the scene.
/// </summary>
/// <typeparam name="T">Type of MonoBehaviour to check for.</typeparam>
/// <returns>True if at least one instance of T exists on the scene, otherwise false.</returns>
public static bool IsExistsOnScene<T>() where T : MonoBehaviour
{
int count = MonoBehaviour.FindObjectsOfType<T>().Length;
return count != 0;
}
/// <summary>
/// Destroying Unity GameObject, but as an extension.
/// <para>Works in Editor and Playmode.</para>
/// </summary>
/// <summary>
public static bool Destroy(this UnityEngine.Object @object)
{
if (@object == null)
return false;
try
{
if (@object != null)
{
//Debug.LogError($"Destroy | {unityObject.name}");
}
#if UNITY_EDITOR
UnityEngine.Object.DestroyImmediate(@object);
#else
UnityEngine.Object.Destroy(@object);
#endif
return true;
}
catch
{
return false;
}
}
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="gameObject"></param>
/// <param name="component"></param>
/// <returns>Returns whether a component of the input type has been added.</returns>
public static bool TryAddComponent<T>(this GameObject gameObject, out T component, bool supportMultiInstance = false) where T : UnityEngine.Component
{
if (gameObject.TryGetComponent(out component) && !supportMultiInstance)
{
return true;
}
else
{
component = gameObject.AddComponent<T>();
return false;
}
}
public static bool TryGetComponent<T>(this GameObject gameObject, out T component) where T : UnityEngine.Component
{
try
{
component = gameObject.GetComponent<T>();
string _ = component.name;
return true;
}
catch
{
component = default;
return false;
}
}
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="gameObject"></param>
/// <param name="graphic">Found or added graphic component.</param>
/// <returns>Returns whether a component of the input type has been added.</returns>
public static bool TryAddGraphic<T>(this GameObject gameObject, out T graphic) where T : Graphic
{
if (gameObject.TryGetComponent(out graphic))
{
return false;
}
else if (gameObject.TryGetComponent(out Graphic _graphic))
{
return false;
}
else
{
graphic = gameObject.AddComponent<T>();
return true;
}
}
public static bool TryDestroyComponent<T>(this GameObject gameObject) where T : UnityEngine.Component
{
if (gameObject.TryGetComponent(out T component))
{
component.Destroy();
return true;
}
else
{
return false;
}
}
/// <summary>
/// Marks target object as dirty, but as an extension.
/// </summary>
/// <param name="object">The object to mark as dirty.</param>
public static void SetDirtyExt(this UnityEngine.Object @object)
{
#if UNITY_EDITOR
UnityEditor.EditorUtility.SetDirty(@object);
#endif
}
public static void MakeGameObjectSelectedInHierarchy(this GameObject activeGameObject)
{
#if UNITY_EDITOR
UnityEditor.Selection.activeGameObject = activeGameObject;
#endif
}
public static GameObject CreateEmptyGameObject(string name = null, Transform parent = null)
{
GameObject tempGO = new GameObject();
GameObject emptyGO;
if (parent == null)
{
emptyGO = UnityEngine.Object.Instantiate(tempGO);
}
else
{
emptyGO = UnityEngine.Object.Instantiate(tempGO, parent);
}
if (name != null)
{
tempGO.name = name;
}
tempGO.Destroy();
return emptyGO;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6e6e2f8e6cb739b4a909268b9e654ba8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,64 @@
using System;
using System.Linq;
using UnityEngine;
namespace DA_Assets.Extensions
{
public static class OtherExtensions
{
public static bool IsDefault<T>(this T obj)
{
if (obj == null)
{
return true;
}
return obj.Equals(default(T));
}
public static bool IsFlagSet<T>(this T value, T flag) where T : struct
{
long lValue = Convert.ToInt64(value);
long lFlag = Convert.ToInt64(flag);
return (lValue & lFlag) != 0;
}
public static T CopyClass<T>(this T source)
{
string json = JsonUtility.ToJson(source);
T copiedObject = JsonUtility.FromJson<T>(json);
return copiedObject;
}
/// <summary>
/// <para><see href="https://stackoverflow.com/a/33784596/8265642"/></para>
/// </summary>
public static string GetNumbers(this string text)
{
if (string.IsNullOrWhiteSpace(text))
return string.Empty;
return new string(text.Where(p => char.IsDigit(p)).ToArray());
}
public static bool ToBoolNullTrue(this bool? value)
{
if (value == null)
{
return true;
}
return value.Value;
}
public static bool ToBoolNullFalse(this bool? value)
{
if (value == null)
{
return false;
}
return value.Value;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: eed2732e3b885384f89b0955115f3f84
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,69 @@
using UnityEngine;
namespace DA_Assets.Extensions
{
public static class RectTransformExtensions
{
public static void CopyFrom(this RectTransform target, RectTransform source)
{
target.anchorMin = source.anchorMin;
target.anchorMax = source.anchorMax;
target.anchoredPosition = source.anchoredPosition;
target.sizeDelta = source.sizeDelta;
target.localRotation = source.localRotation;
target.localScale = source.localScale;
}
public static float GetWidth(this RectTransform rt)
{
var w = (rt.anchorMax.x - rt.anchorMin.x) * Screen.width + rt.sizeDelta.x;
return w;
}
public static float GetHeight(this RectTransform rt)
{
var h = (rt.anchorMax.y - rt.anchorMin.y) * Screen.height + rt.sizeDelta.y;
return h;
}
public static void SetLeft(this RectTransform rt, float left)
{
rt.offsetMin = new Vector2(left, rt.offsetMin.y);
}
public static float GetLeft(this RectTransform rt)
{
return rt.offsetMin.x;
}
public static void SetRight(this RectTransform rt, float right)
{
rt.offsetMax = new Vector2(-right, rt.offsetMax.y);
}
public static float GetRight(this RectTransform rt)
{
return -rt.offsetMax.x;
}
public static void SetTop(this RectTransform rt, float top)
{
rt.offsetMax = new Vector2(rt.offsetMax.x, -top);
}
public static float GetTop(this RectTransform rt)
{
return -rt.offsetMax.y;
}
public static void SetBottom(this RectTransform rt, float bottom)
{
rt.offsetMin = new Vector2(rt.offsetMin.x, bottom);
}
public static float GetBottom(this RectTransform rt)
{
return rt.offsetMin.y;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 980a5b90d0f184a4fbaf5a38652b3134
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,47 @@
using UnityEngine;
using UnityEngine.SceneManagement;
namespace DA_Assets.Extensions
{
public static class ReflectedExtensions
{
/// <summary>
/// <para><see href="https://forum.unity.com/threads/how-to-collapse-hierarchy-scene-nodes-via-script.605245/#post-6551890"/></para>
/// </summary>
public static void SetExpanded(this Scene scene, bool expand)
{
#if UNITY_EDITOR
foreach (var window in Resources.FindObjectsOfTypeAll<UnityEditor.SearchableEditorWindow>())
{
if (window.GetType().Name != "SceneHierarchyWindow")
continue;
var method = window.GetType().GetMethod("SetExpandedRecursive",
System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Instance, null,
new[] { typeof(int), typeof(bool) }, null);
if (method == null)
{
Debug.LogError(
"Could not find method 'UnityEditor.SceneHierarchyWindow.SetExpandedRecursive(int, bool)'.");
return;
}
var field = scene.GetType().GetField("m_Handle",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
if (field == null)
{
Debug.LogError("Could not find field 'int UnityEngine.SceneManagement.Scene.m_Handle'.");
return;
}
var sceneHandle = field.GetValue(scene);
method.Invoke(window, new[] { sceneHandle, expand });
}
#endif
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 77fec60961ff2d947844b0ee566eafea
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,99 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace DA_Assets.Extensions
{
public static class ReflectionExtensions
{
// ***
// *** MemberInfo Extensions
// https://stackoverflow.com/a/63382419
// ***
public static IEnumerable<MemberInfo> GetPropertiesOrFields(this Type t, BindingFlags bf = BindingFlags.Public | BindingFlags.Instance) =>
t.GetMembers(bf).Where(mi => mi.MemberType == MemberTypes.Field || mi.MemberType == MemberTypes.Property);
public static IEnumerable<string> GetPropertyOrFieldNames(this Type t) => t.GetPropertiesOrFields().Select(mi => mi.Name);
public static MemberInfo GetPropertyOrField(this Type t, string memberName, BindingFlags bf = BindingFlags.Public | BindingFlags.Instance) =>
t.GetMember(memberName, bf).Where(mi => mi.MemberType == MemberTypes.Field || mi.MemberType == MemberTypes.Property).Single();
public static Type GetMemberType(this MemberInfo member)
{
switch (member)
{
case FieldInfo mfi:
return mfi.FieldType;
case PropertyInfo mpi:
return mpi.PropertyType;
case EventInfo mei:
return mei.EventHandlerType;
default:
throw new ArgumentException("MemberInfo must be if type FieldInfo, PropertyInfo or EventInfo", nameof(member));
}
}
public static bool GetCanWrite(this MemberInfo member)
{
switch (member)
{
case FieldInfo mfi:
return true;
case PropertyInfo mpi:
return mpi.CanWrite;
default:
throw new ArgumentException("MemberInfo must be if type FieldInfo or PropertyInfo", nameof(member));
}
}
public static bool GetCanRead(this MemberInfo member)
{
switch (member)
{
case FieldInfo mfi:
return true;
case PropertyInfo mpi:
return mpi.CanRead;
default:
throw new ArgumentException("MemberInfo must be if type FieldInfo or PropertyInfo", nameof(member));
}
}
public static object GetValue(this MemberInfo member, object srcObject)
{
switch (member)
{
case FieldInfo mfi:
return mfi.GetValue(srcObject);
case PropertyInfo mpi:
return mpi.GetValue(srcObject);
case MethodInfo mi:
return mi.Invoke(srcObject, null);
default:
throw new ArgumentException("MemberInfo must be of type FieldInfo, PropertyInfo or MethodInfo", nameof(member));
}
}
public static T GetValue<T>(this MemberInfo member, object srcObject) => (T)member.GetValue(srcObject);
public static void SetValue(this MemberInfo member, object destObject, object value)
{
switch (member)
{
case FieldInfo mfi:
mfi.SetValue(destObject, value);
break;
case PropertyInfo mpi:
mpi.SetValue(destObject, value);
break;
case MethodInfo mi:
mi.Invoke(destObject, new object[] { value });
break;
default:
throw new ArgumentException("MemberInfo must be of type FieldInfo, PropertyInfo or MethodInfo", nameof(member));
}
}
public static void SetValue<T>(this MemberInfo member, object destObject, T value) => member.SetValue(destObject, (object)value);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 04c0579f7a3dc524e8c9f4e6b782554e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,338 @@
using System;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net.Mail;
using System.Text;
using System.Text.RegularExpressions;
namespace DA_Assets.Extensions
{
public static class StringExtensions
{
public static bool IsValidEmail(this string emailaddress)
{
try
{
MailAddress m = new MailAddress(emailaddress);
return true;
}
catch (FormatException)
{
return false;
}
}
public static bool IsSpecialNumber(this string value)
{
if (string.IsNullOrWhiteSpace(value))
return false;
string cleanName = Regex.Replace(value, @"[\%\#\$\€\£\₴\¥\₹\₩\₪\₦\฿\₫\₹\₺\₱\₽]", "").Trim();
return cleanName.TryParseFloat(out float _);
}
const string phonePattern = @"^\+?[0-9\s\-\(\)]+$";
public static bool IsPhoneNumber(this string value)
{
if (string.IsNullOrWhiteSpace(value))
return false;
return Regex.IsMatch(value, phonePattern);
}
public static string MakeCharLower(this string str, int charIndex)
{
if (str == null)
throw new ArgumentNullException(nameof(str));
if (charIndex < 0 || charIndex >= str.Length)
throw new ArgumentOutOfRangeException(nameof(charIndex));
char[] strArray = str.ToCharArray();
strArray[charIndex] = char.ToLower(strArray[charIndex]);
return new string(strArray);
}
public static string MakeCharUpper(this string str, int charIndex)
{
if (str == null)
throw new ArgumentNullException(nameof(str));
if (charIndex < 0 || charIndex >= str.Length)
throw new ArgumentOutOfRangeException(nameof(charIndex));
char[] strArray = str.ToCharArray();
strArray[charIndex] = char.ToUpper(strArray[charIndex]);
return new string(strArray);
}
public static string MakeFirstCharUpper(this string str)
{
return char.ToLower(str[0]) + str.Substring(1);
}
/// <summary>
/// https://stackoverflow.com/a/11161232
/// </summary>
public static long GetNumberOnly(this string str)
{
string result = Regex.Replace(str, @"[^\d]", "");
if (long.TryParse(result, out long res))
{
return res;
}
return 0;
}
public static string ReplaceNotNumbers(this string str, char @char)
{
char[] chars = str.ToCharArray();
for (int i = 0; i < chars.Length; i++)
{
if (!char.IsDigit(chars[i]))
{
chars[i] = @char;
}
}
return new string(chars);
}
public static string RemoveRepeats(this string str, char @char)
{
if (str.IsEmpty())
return str;
return Regex.Replace(str, $"{@char}+", $"{@char}");
}
public static string RemoveRepeatsForNonAlphanumericCharacters(this string str)
{
if (string.IsNullOrEmpty(str))
return str;
return Regex.Replace(str, @"([^a-zA-Z0-9])\1+", "$1");
}
public static float GetSizeMB(this string myString)
{
byte[] byteArray = Encoding.UTF8.GetBytes(myString);
using (MemoryStream stream = new MemoryStream(byteArray))
{
long sizeInBytes = stream.Length;
float sizeInMegabytes = (float)sizeInBytes / (1024 * 1024);
sizeInMegabytes = (float)Math.Floor(sizeInMegabytes * 100) / 100;
return sizeInMegabytes;
}
}
public static string AddWithNewLine(this object source)
{
string result = "";
result += Environment.NewLine;
result += source;
return result;
}
public static bool IsLastChar(this string str, Func<char, bool> condition)
{
if (string.IsNullOrWhiteSpace(str))
{
return false;
}
char lastChar = str.Last();
//UnityEngine.Debug.LogError($"IsLastChar | {str} | {str.Last()} | {condition(lastChar)}");
return condition(lastChar);
}
/// <summary>
/// https://stackoverflow.com/a/448225
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public static bool IsAllUpper(this string input)
{
input = input.RemoveNonLettersAndNonNumbers("");
for (int i = 0; i < input.Length; i++)
{
if (!char.IsUpper(input[i]))
return false;
}
return true;
}
public static string RemoveNonNumbers(this string str, string replace)
{
if (string.IsNullOrWhiteSpace(str))
return str;
return Regex.Replace(str, "[^0-9]", replace);
}
public static string RemoveNonLettersAndNonNumbers(this string str, string replace)
{
if (string.IsNullOrWhiteSpace(str))
return str;
return Regex.Replace(str, "[^a-zA-Z0-9]", replace);
}
public static bool IsLetterOrNumber(this char c) => Regex.IsMatch(c.ToString(), "[a-zA-Z0-9]");
/// <summary>
/// https://stackoverflow.com/a/63055998
/// </summary>
public static string ToSnakeCase(this string str)
{
if (string.IsNullOrWhiteSpace(str))
return str;
if (str.Length < 2)
{
return str.ToLowerInvariant();
}
StringBuilder sb = new StringBuilder();
sb.Append(char.ToLowerInvariant(str[0]));
for (int i = 1; i < str.Length; ++i)
{
char c = str[i];
if (char.IsUpper(c))
{
sb.Append('_');
sb.Append(char.ToLowerInvariant(c));
}
else
{
sb.Append(c);
}
}
return sb.ToString();
}
public static string ToUpperSnakeCase(this string str)
{
string snakeCase = ToSnakeCase(str);
if (snakeCase.IsEmpty())
{
return snakeCase;
}
return snakeCase.ToUpper();
}
/// <summary>
/// https://stackoverflow.com/a/46095771
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public static string ToPascalCase(this string str)
{
Regex invalidCharsRgx = new Regex("[^_a-zA-Z0-9]");
Regex whiteSpace = new Regex(@"(?<=\s)");
Regex startsWithLowerCaseChar = new Regex("^[a-z]");
Regex firstCharFollowedByUpperCasesOnly = new Regex("(?<=[A-Z])[A-Z0-9]+$");
Regex lowerCaseNextToNumber = new Regex("(?<=[0-9])[a-z]");
Regex upperCaseInside = new Regex("(?<=[A-Z])[A-Z]+?((?=[A-Z][a-z])|(?=[0-9]))");
// replace white spaces with undescore, then replace all invalid chars with empty string
var pascalCase = invalidCharsRgx.Replace(whiteSpace.Replace(str, "_"), string.Empty)
// split by underscores
.Split(new char[] { '_' }, StringSplitOptions.RemoveEmptyEntries)
// set first letter to uppercase
.Select(w => startsWithLowerCaseChar.Replace(w, m => m.Value.ToUpper()))
// replace second and all following upper case letters to lower if there is no next lower (ABC -> Abc)
.Select(w => firstCharFollowedByUpperCasesOnly.Replace(w, m => m.Value.ToLower()))
// set upper case the first lower case following a number (Ab9cd -> Ab9Cd)
.Select(w => lowerCaseNextToNumber.Replace(w, m => m.Value.ToUpper()))
// lower second and next upper case letters except the last if it follows by any lower (ABcDEf -> AbcDef)
.Select(w => upperCaseInside.Replace(w, m => m.Value.ToLower()));
return string.Concat(pascalCase);
}
public static string ToPascalSnakeCase(this string original)
{
string normalized = Regex.Replace(original, "[^-_a-zA-Z0-9]", " ");
normalized = Regex.Replace(normalized, "([a-z])([A-Z])", "$1 $2");
normalized = Regex.Replace(normalized, "([0-9])([a-zA-Z])", "$1 $2");
normalized = Regex.Replace(normalized, "([a-zA-Z])([0-9])", "$1 $2");
normalized = normalized.Replace("-", " ").Replace("_", " ");
normalized = Regex.Replace(normalized, @"\s+", " ").Trim();
string[] words = normalized
.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
.Select(word => CultureInfo.InvariantCulture.TextInfo.ToTitleCase(word.ToLowerInvariant()))
.ToArray();
return string.Join("_", words);
}
public static bool IsEmpty(this string value)
{
return string.IsNullOrWhiteSpace(value);
}
/// <summary>
/// Truncates a string to a specific character only if the string really needs to be truncated. Does not cause an exception.
/// https://stackoverflow.com/a/2776689
/// </summary>
public static string SubstringSafe(this string value, int maxLength)
{
return value?.Length > maxLength ? value.Substring(0, maxLength) : value;
}
/// <summary>
/// Removes all HTML tags from string.
/// <para><see href="https://stackoverflow.com/a/18154046"/></para>
/// </summary>
public static string RemoveHTML(this string text)
{
return Regex.Replace(text, "<.*?>", string.Empty);
}
/// <summary>
/// Removing string between two strings.
/// <para><see href="https://stackoverflow.com/q/51891661"/></para>
/// </summary>
public static string RemoveBetween(this string text, string startTag, string endTag)
{
Regex regex = new Regex(string.Format("{0}(.*?){1}", Regex.Escape(startTag), Regex.Escape(endTag)), RegexOptions.RightToLeft);
string result = regex.Replace(text, startTag + endTag);
return result;
}
/// <summary>
/// Get part of string between two strings.
/// <para><see href="https://stackoverflow.com/a/17252672"/></para>
/// </summary>
public static string GetBetween(this string text, string startTag, string endTag)
{
int pFrom = text.IndexOf(startTag) + startTag.Length;
int pTo = text.LastIndexOf(endTag);
string result = text.Substring(pFrom, pTo - pFrom);
return result;
}
/// <summary>
/// Simplified syntax for splitting string by string
/// </summary>
public static string[] SplitByString(this string text, string separator)
{
return text.Split(new string[] { separator }, StringSplitOptions.None);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5aa2532b297bf4047acc3470fdb9d8e1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,126 @@
using System.Reflection;
using UnityEngine;
namespace DA_Assets.Extensions
{
public static class TextureExtensions
{
#if UNITY_EDITOR
/// <summary>
/// <para><see href="https://forum.unity.com/threads/getting-original-size-of-texture-asset-in-pixels.165295/"/></para>
/// </summary>
public static bool GetTextureSize(this UnityEditor.TextureImporter importer, out int width, out int height)
{
if (importer != null)
{
object[] args = new object[2] { 0, 0 };
MethodInfo mi = typeof(UnityEditor.TextureImporter).GetMethod("GetWidthAndHeight", BindingFlags.NonPublic | BindingFlags.Instance);
mi.Invoke(importer, args);
width = (int)args[0];
height = (int)args[1];
return true;
}
height = width = 0;
return false;
}
/// <summary>
/// Sets the maximum size of the texture based on its width and height.
/// <para><see href="https://forum.unity.com/threads/getting-original-size-of-texture-asset-in-pixels.165295/"/></para>
/// </summary>
public static void SetMaxTextureSize(this UnityEditor.TextureImporter importer, int width, int height)
{
int[] maxTextureSizeValues = { 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384 };
int max = Mathf.Max(width, height);
int defsize = 1024; //Default size
for (int i = 0; i < maxTextureSizeValues.Length; i++)
{
if (maxTextureSizeValues[i] >= max)
{
defsize = maxTextureSizeValues[i];
break;
}
}
importer.maxTextureSize = defsize;
}
#endif
public static Texture2D Merge(this Texture2D largeTexture, Texture2D smallTexture)
{
//Create a new texture with the size of the large texture
Texture2D overlayTexture = new Texture2D(largeTexture.width, largeTexture.height, TextureFormat.RGBA32, false);
//Copy pixels of a large texture to a new texture
Color[] pixels = largeTexture.GetPixels();
overlayTexture.SetPixels(pixels);
//Determine the coordinates to center the small texture
int startX = (largeTexture.width - smallTexture.width) / 2;
int startY = (largeTexture.height - smallTexture.height) / 2;
//Overlay pixels of a small texture onto a large texture
Color[] overlayPixels = smallTexture.GetPixels();
for (int x = 0; x < smallTexture.width; x++)
{
for (int y = 0; y < smallTexture.height; y++)
{
int targetX = startX + x;
int targetY = startY + y;
Color overlayPixel = overlayPixels[x + y * smallTexture.width];
//Applying the alpha channel of a small texture to the pixels of a large texture
Color targetPixel = overlayTexture.GetPixel(targetX, targetY);
Color finalPixel = Color.Lerp(targetPixel, overlayPixel, overlayPixel.a);
overlayTexture.SetPixel(targetX, targetY, finalPixel);
}
}
//Applying changes to the texture
overlayTexture.Apply();
return overlayTexture;
}
public static void Colorize(this Texture2D texture, Color32 color)
{
Color32[] pixels = texture.GetPixels32();
for (int i = 0; i < pixels.Length; i++)
{
pixels[i] = new Color32(color.r, color.g, color.b, pixels[i].a);
}
texture.SetPixels32(pixels);
texture.Apply();
}
public static void Resize(this Texture2D texture2D, Vector2Int targetSize, int depth, FilterMode filterMode, RenderTextureFormat rtFormat)
{
RenderTexture rt = RenderTexture.GetTemporary(targetSize.x, targetSize.y, depth, rtFormat, RenderTextureReadWrite.Default);
RenderTexture.active = rt;
Graphics.Blit(texture2D, rt);
#if UNITY_2021_2_OR_NEWER
texture2D.Reinitialize(targetSize.x, targetSize.y, texture2D.format, false);
#else
texture2D.Resize(targetSize.x, targetSize.y, texture2D.format, false);
#endif
texture2D.filterMode = filterMode;
texture2D.ReadPixels(new Rect(0.0f, 0.0f, targetSize.x, targetSize.y), 0, 0);
texture2D.Apply();
RenderTexture.ReleaseTemporary(rt);
RenderTexture.active = null;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2921ff2b1e295e7489748e9fc441b820
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,62 @@
using System.Collections.Generic;
using UnityEngine;
namespace DA_Assets.Extensions
{
public static class TransformExtensions
{
/// <summary>
/// Removes all childs from Transform.
/// <para><see href="https://www.noveltech.dev/unity-delete-children/"/></para>
/// </summary>
public static int ClearChilds(this Transform transform)
{
int childCount = transform.childCount;
for (int i = childCount - 1; i >= 0; i--)
{
GameObject go = transform.GetChild(i).gameObject;
go.Destroy();
}
return childCount;
}
public static List<Transform> GetTopLevelChilds(this Transform parentObject)
{
List<Transform> childs = new List<Transform>();
Transform current = parentObject;
while (current.parent) // Go up until obj does not have a parent
current = current.parent;
foreach (Transform child in current) // iterate over children
{
childs.Add(child);
}
return childs;
}
public static void SetTransformProps(this TransformProps transformProps, Transform source)
{
transformProps.position = source.position;
transformProps.rotation = source.rotation;
transformProps.parent = source.parent;
}
public static void SetTransform(this Transform target, TransformProps transformProps)
{
target.transform.position = transformProps.position;
target.transform.rotation = transformProps.rotation;
target.transform.parent = transformProps.parent;
}
}
public struct TransformProps
{
public Vector3 position;
public Quaternion rotation;
public Transform parent;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b07effcc3a60818479ceb68725f30869
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: