Update
This commit is contained in:
@@ -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,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6bdb420b2e504b14a90dc566a4741b7c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1c19f2ebb8f0b0a4bb4f73a230063a0d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f4206c7f0cf637b4193c2daad9d99b85
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9b50e7e9b4f60b04f89b3e958fc4ec95
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1c4f23c9c4c1eaa4887d52c43453738c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 43d14e50078ff2c428e6e923c235bde0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 82c89c45d46e01c45a1546d7ee9d0f76
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6524e57dc4d98a14f8146352f930e583
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c48acc25efb6e1b48a99548fe4264b03
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cb488b4e150d26942b4c98b673d4794d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f7d38f396b24c174d8cb981e92dc9d93
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6e6e2f8e6cb739b4a909268b9e654ba8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eed2732e3b885384f89b0955115f3f84
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 980a5b90d0f184a4fbaf5a38652b3134
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 77fec60961ff2d947844b0ee566eafea
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 04c0579f7a3dc524e8c9f4e6b782554e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5aa2532b297bf4047acc3470fdb9d8e1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2921ff2b1e295e7489748e9fc441b820
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b07effcc3a60818479ceb68725f30869
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user