diff --git a/Assets/BetterExtensions/Runtime/Extensions/AssetBundleRequestAwaiterExtensions.cs b/Assets/BetterExtensions/Runtime/Extensions/AssetBundleRequestAwaiterExtensions.cs new file mode 100644 index 0000000..eef4f4c --- /dev/null +++ b/Assets/BetterExtensions/Runtime/Extensions/AssetBundleRequestAwaiterExtensions.cs @@ -0,0 +1,19 @@ +using System; +using Better.Extensions.Runtime.Helpers; +using UnityEngine; + +namespace Better.Extensions.Runtime +{ + public static class AssetBundleRequestAwaiterExtensions + { + public static AssetBundleRequestAwaiter GetAwaiter(this AssetBundleRequest self) + { + if (self == null) + { + throw new ArgumentNullException(nameof(self)); + } + + return new AssetBundleRequestAwaiter(self); + } + } +} \ No newline at end of file diff --git a/Assets/BetterExtensions/Runtime/Extensions/AssetBundleRequestAwaiterExtensions.cs.meta b/Assets/BetterExtensions/Runtime/Extensions/AssetBundleRequestAwaiterExtensions.cs.meta new file mode 100644 index 0000000..75523af --- /dev/null +++ b/Assets/BetterExtensions/Runtime/Extensions/AssetBundleRequestAwaiterExtensions.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ca077a45a303487ca43745e539249493 +timeCreated: 1709131442 \ No newline at end of file diff --git a/Assets/BetterExtensions/Runtime/Extensions/AsyncOperationAwaiterExtensions.cs b/Assets/BetterExtensions/Runtime/Extensions/AsyncOperationAwaiterExtensions.cs new file mode 100644 index 0000000..34be353 --- /dev/null +++ b/Assets/BetterExtensions/Runtime/Extensions/AsyncOperationAwaiterExtensions.cs @@ -0,0 +1,19 @@ +using System; +using Better.Extensions.Runtime.Helpers; +using UnityEngine; + +namespace Better.Extensions.Runtime +{ + public static class AsyncOperationAwaiterExtensions + { + public static AsyncOperationAwaiter GetAwaiter(this AsyncOperation self) + { + if (self == null) + { + throw new ArgumentNullException(nameof(self)); + } + + return new AsyncOperationAwaiter(self); + } + } +} \ No newline at end of file diff --git a/Assets/BetterExtensions/Runtime/Extensions/AsyncOperationAwaiterExtensions.cs.meta b/Assets/BetterExtensions/Runtime/Extensions/AsyncOperationAwaiterExtensions.cs.meta new file mode 100644 index 0000000..25e6d49 --- /dev/null +++ b/Assets/BetterExtensions/Runtime/Extensions/AsyncOperationAwaiterExtensions.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ba1202f52f2c4e77bd401b7ce86a0fb3 +timeCreated: 1709131411 \ No newline at end of file diff --git a/Assets/BetterExtensions/Runtime/Extensions/ComponentExtensions.cs b/Assets/BetterExtensions/Runtime/Extensions/ComponentExtensions.cs new file mode 100644 index 0000000..f0a5e6b --- /dev/null +++ b/Assets/BetterExtensions/Runtime/Extensions/ComponentExtensions.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace Better.Extensions.Runtime +{ + public static class ComponentExtensions + { + public static void DestroyGameObject(this Component self) + { + if (self == null) + { + DebugUtility.LogException(nameof(self)); + return; + } + + self.gameObject.Destroy(); + } + + public static void DestroyGameObject(this Component self, float delay) + { + if (self == null) + { + DebugUtility.LogException(nameof(self)); + return; + } + + self.gameObject.Destroy(delay); + } + + public static void DestroyGameObject(this IEnumerable self) + { + if (self == null) + { + DebugUtility.LogException(nameof(self)); + return; + } + + var cached = self.ToArray(); + for (var i = 0; i < cached.Length; i++) + { + cached[i].DestroyGameObject(); + } + } + + public static void DestroyGameObject(this IEnumerable self, float delay) + { + if (self == null) + { + DebugUtility.LogException(nameof(self)); + return; + } + + var cached = self.ToArray(); + for (var i = 0; i < cached.Length; i++) + { + cached[i].DestroyGameObject(delay); + } + } + + public static IEnumerable GetGameObjects(this IEnumerable self) + { + if (self == null) + { + DebugUtility.LogException(nameof(self)); + return Enumerable.Empty(); + } + + return self.Select(c => c.gameObject); + } + + public static IEnumerable GetTransforms(this IEnumerable self) + { + if (self == null) + { + DebugUtility.LogException(nameof(self)); + return Enumerable.Empty(); + } + + return self.Select(c => c.transform); + } + + public static T GetOrAddComponent(this Component self) + where T : Component + { + if (self == null) + { + DebugUtility.LogException(nameof(self)); + return default; + } + + return self.gameObject.GetOrAddComponent(); + } + + public static bool TryGetComponentInParent(this Component self, out T component) + { + if (self == null) + { + DebugUtility.LogException(nameof(self)); + component = default; + return false; + } + + return self.gameObject.TryGetComponentInParent(out component); + } + + public static bool TryGetComponentInChildren(this Component self, out T component) + { + if (self == null) + { + DebugUtility.LogException(nameof(self)); + component = default; + return false; + } + + return self.gameObject.TryGetComponentInChildren(out component); + } + } +} \ No newline at end of file diff --git a/Assets/BetterExtensions/Runtime/Extensions/ComponentExtensions.cs.meta b/Assets/BetterExtensions/Runtime/Extensions/ComponentExtensions.cs.meta new file mode 100644 index 0000000..ddb3523 --- /dev/null +++ b/Assets/BetterExtensions/Runtime/Extensions/ComponentExtensions.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a1e35ba963b24d3da183e062afd94744 +timeCreated: 1709107592 \ No newline at end of file diff --git a/Assets/BetterExtensions/Runtime/Extensions/GameObjectExtensions.cs b/Assets/BetterExtensions/Runtime/Extensions/GameObjectExtensions.cs new file mode 100644 index 0000000..8bcfe40 --- /dev/null +++ b/Assets/BetterExtensions/Runtime/Extensions/GameObjectExtensions.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace Better.Extensions.Runtime +{ + public static class GameObjectExtensions + { + public static void SetActive(this IEnumerable self, bool value) + { + if (self == null) + { + DebugUtility.LogException(nameof(self)); + return; + } + + var cached = self.ToArray(); + for (var i = 0; i < cached.Length; i++) + { + cached[i].SetActive(value); + } + } + + public static T GetOrAddComponent(this GameObject self) + where T : Component + { + if (self == null) + { + DebugUtility.LogException(nameof(self)); + return default; + } + + if (self.TryGetComponent(out T component)) + { + return component; + } + + return self.AddComponent(); + } + + public static bool TryGetComponentInParent(this GameObject self, out T component) + { + if (self == null) + { + DebugUtility.LogException(nameof(self)); + component = default; + return false; + } + + component = self.GetComponentInParent(); + return component != null; + } + + public static bool TryGetComponentInChildren(this GameObject self, out T component) + { + if (self == null) + { + DebugUtility.LogException(nameof(self)); + component = default; + return false; + } + + component = self.GetComponentInChildren(); + return component != null; + } + + public static void RecursiveSetLayer(this GameObject self, int layer) + { + self.layer = layer; + + foreach (Transform child in self.transform) + { + RecursiveSetLayer(child.gameObject, layer); + } + } + + public static void RecursiveSetLayer(this GameObject self, LayerMask layerMask) + { + self.RecursiveSetLayer(layerMask.value); + } + } +} \ No newline at end of file diff --git a/Assets/BetterExtensions/Runtime/Extensions/GameObjectExtensions.cs.meta b/Assets/BetterExtensions/Runtime/Extensions/GameObjectExtensions.cs.meta new file mode 100644 index 0000000..3bfd9ff --- /dev/null +++ b/Assets/BetterExtensions/Runtime/Extensions/GameObjectExtensions.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: b661b7610f59402f8220cefe0212b336 +timeCreated: 1709108900 \ No newline at end of file diff --git a/Assets/BetterExtensions/Runtime/Extensions/QuaternionExtensions.cs b/Assets/BetterExtensions/Runtime/Extensions/QuaternionExtensions.cs index b7f4805..634cd72 100644 --- a/Assets/BetterExtensions/Runtime/Extensions/QuaternionExtensions.cs +++ b/Assets/BetterExtensions/Runtime/Extensions/QuaternionExtensions.cs @@ -13,5 +13,15 @@ public static bool Approximately(this Quaternion self, Quaternion other) { return QuaternionUtility.Approximately(self, other); } + + public static Quaternion Scale(this Quaternion self, Vector3 scale) + { + return QuaternionUtility.Scale(self, scale); + } + + public static Quaternion Scale(this Quaternion self, float scale) + { + return QuaternionUtility.Scale(self, scale); + } } } \ No newline at end of file diff --git a/Assets/BetterExtensions/Runtime/Extensions/RectExtensions.cs b/Assets/BetterExtensions/Runtime/Extensions/RectExtensions.cs new file mode 100644 index 0000000..abb9a71 --- /dev/null +++ b/Assets/BetterExtensions/Runtime/Extensions/RectExtensions.cs @@ -0,0 +1,12 @@ +using UnityEngine; + +namespace Better.Extensions.Runtime +{ + public static class RectExtensions + { + public static float GetRatio(this Rect self) + { + return self.size.y / self.size.y; + } + } +} \ No newline at end of file diff --git a/Assets/BetterExtensions/Runtime/Extensions/RectExtensions.cs.meta b/Assets/BetterExtensions/Runtime/Extensions/RectExtensions.cs.meta new file mode 100644 index 0000000..3366dd2 --- /dev/null +++ b/Assets/BetterExtensions/Runtime/Extensions/RectExtensions.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 928fa70d62364c25aa6743c3761a49e2 +timeCreated: 1709113267 \ No newline at end of file diff --git a/Assets/BetterExtensions/Runtime/Extensions/RectTransformExtensions.cs b/Assets/BetterExtensions/Runtime/Extensions/RectTransformExtensions.cs index adb18bb..07a1a72 100644 --- a/Assets/BetterExtensions/Runtime/Extensions/RectTransformExtensions.cs +++ b/Assets/BetterExtensions/Runtime/Extensions/RectTransformExtensions.cs @@ -156,5 +156,33 @@ public static bool IsVisibleFrom(this RectTransform self, Camera camera) return CountCornersVisible(self, camera) > 0; // True if any corners are visible } + + public static bool IsFullyStretched(this RectTransform self) + { + if (self == null) + { + DebugUtility.LogException(nameof(self)); + return false; + } + + return self.localScale == Vector3.one + && self.anchorMin == Vector2.zero + && self.anchorMax == Vector2.one + && self.sizeDelta == Vector2.zero; + } + + public static void FullyStretch(this RectTransform self) + { + if (self == null) + { + DebugUtility.LogException(nameof(self)); + return; + } + + self.LocalReset(); + self.anchorMin = Vector2.zero; + self.anchorMax = Vector2.one; + self.sizeDelta = Vector2.zero; + } } } \ No newline at end of file diff --git a/Assets/BetterExtensions/Runtime/Extensions/ResourceRequestAwaiterExtensions.cs b/Assets/BetterExtensions/Runtime/Extensions/ResourceRequestAwaiterExtensions.cs new file mode 100644 index 0000000..7c69f83 --- /dev/null +++ b/Assets/BetterExtensions/Runtime/Extensions/ResourceRequestAwaiterExtensions.cs @@ -0,0 +1,19 @@ +using System; +using Better.Extensions.Runtime.Helpers; +using UnityEngine; + +namespace Better.Extensions.Runtime +{ + public static class ResourceRequestAwaiterExtensions + { + public static ResourceRequestAwaiter GetAwaiter(this ResourceRequest self) + { + if (self == null) + { + throw new ArgumentNullException(nameof(self)); + } + + return new ResourceRequestAwaiter(self); + } + } +} \ No newline at end of file diff --git a/Assets/BetterExtensions/Runtime/Extensions/ResourceRequestAwaiterExtensions.cs.meta b/Assets/BetterExtensions/Runtime/Extensions/ResourceRequestAwaiterExtensions.cs.meta new file mode 100644 index 0000000..d481a98 --- /dev/null +++ b/Assets/BetterExtensions/Runtime/Extensions/ResourceRequestAwaiterExtensions.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5c24099b1a40414a8d84119509f26e0c +timeCreated: 1709131445 \ No newline at end of file diff --git a/Assets/BetterExtensions/Runtime/Extensions/TransformExtensions.cs b/Assets/BetterExtensions/Runtime/Extensions/TransformExtensions.cs new file mode 100644 index 0000000..a3ce102 --- /dev/null +++ b/Assets/BetterExtensions/Runtime/Extensions/TransformExtensions.cs @@ -0,0 +1,224 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace Better.Extensions.Runtime +{ + public static class TransformExtensions + { + public static Transform CreateChild(this Transform self, string name) + { + if (self == null) + { + DebugUtility.LogException(nameof(self)); + return default; + } + + var created = new GameObject(name); + created.transform.parent = self; + created.transform.LocalReset(); + return created.transform; + } + + public static Transform CreateChild(this Transform self) + { + var name = "GameObject (new)"; + return self.CreateChild(name); + } + + /// + /// Copies rotation and position from another transform + /// + public static void Copy(this Transform self, Transform root) + { + if (self == null) + { + DebugUtility.LogException(nameof(self)); + return; + } + + if (root == null) + { + DebugUtility.LogException(nameof(root)); + return; + } + + self.position = root.position; + self.rotation = root.rotation; + } + + /// + /// Copies localPosition, localRotation and optional - localScale from another transform + /// + public static void LocalCopy(this Transform self, Transform root, bool scaleCopy = true) + { + if (self == null) + { + DebugUtility.LogException(nameof(self)); + return; + } + + if (root == null) + { + DebugUtility.LogException(nameof(root)); + return; + } + + self.localPosition = root.localPosition; + self.localRotation = root.localRotation; + + if (scaleCopy) + { + self.localScale = root.localScale; + } + } + + public static void CopyPosition(this Transform self, Transform root) + { + if (self == null) + { + DebugUtility.LogException(nameof(self)); + return; + } + + if (root == null) + { + DebugUtility.LogException(nameof(root)); + return; + } + + self.position = root.position; + } + + public static void CopyLocalPosition(this Transform self, Transform root) + { + if (self == null) + { + DebugUtility.LogException(nameof(self)); + return; + } + + if (root == null) + { + DebugUtility.LogException(nameof(root)); + return; + } + + self.localPosition = root.localPosition; + } + + public static void CopyRotation(this Transform self, Transform root) + { + if (self == null) + { + DebugUtility.LogException(nameof(self)); + return; + } + + if (root == null) + { + DebugUtility.LogException(nameof(root)); + return; + } + + self.rotation = root.rotation; + } + + public static void CopyLocalRotation(this Transform self, Transform root) + { + if (self == null) + { + DebugUtility.LogException(nameof(self)); + return; + } + + if (root == null) + { + DebugUtility.LogException(nameof(root)); + return; + } + + self.localRotation = root.localRotation; + } + + /// + /// Resets rotation (identity) and position (0, 0, 0) relative to world space + /// + public static void Reset(this Transform self) + { + if (self == null) + { + DebugUtility.LogException(nameof(self)); + return; + } + + self.position = Vector3.zero; + self.rotation = Quaternion.identity; + } + + /// + /// Resets rotation (identity), position (0, 0, 0) + /// and optional - scale (1, 1, 1), relative to local space + /// + public static void LocalReset(this Transform self, bool scaleReset = true) + { + if (self == null) + { + DebugUtility.LogException(nameof(self)); + return; + } + + self.localPosition = Vector3.zero; + self.localRotation = Quaternion.identity; + + if (scaleReset) + { + self.localScale = Vector3.one; + } + } + + public static IEnumerable GetChildren(this Transform self) + { + if (self == null) + { + DebugUtility.LogException(nameof(self)); + return Enumerable.Empty(); + } + + var result = new List(); + for (var i = 0; i < self.childCount; i++) + { + result.Add(self.GetChild(i)); + } + + return result; + } + + public static void DestroyChildren(this Transform self) + { + if (self == null) + { + DebugUtility.LogException(nameof(self)); + return; + } + + self.GetChildren() + .GetGameObjects() + .Destroy(); + } + + public static void DestroyChildren(this Transform self, float delay) + { + if (self == null) + { + DebugUtility.LogException(nameof(self)); + return; + } + + self.GetChildren() + .GetGameObjects() + .Destroy(delay); + } + } +} \ No newline at end of file diff --git a/Assets/BetterExtensions/Runtime/Extensions/TransformExtensions.cs.meta b/Assets/BetterExtensions/Runtime/Extensions/TransformExtensions.cs.meta new file mode 100644 index 0000000..cd952f0 --- /dev/null +++ b/Assets/BetterExtensions/Runtime/Extensions/TransformExtensions.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 86ec4f9967f34b98b1762467b188245b +timeCreated: 1709109949 \ No newline at end of file diff --git a/Assets/BetterExtensions/Runtime/Extensions/TypeExtensions.cs b/Assets/BetterExtensions/Runtime/Extensions/TypeExtensions.cs index e40b679..3c10a2d 100644 --- a/Assets/BetterExtensions/Runtime/Extensions/TypeExtensions.cs +++ b/Assets/BetterExtensions/Runtime/Extensions/TypeExtensions.cs @@ -148,7 +148,7 @@ public static bool IsSubclassOf(this Type self) return self.IsSubclassOf(type); } - public static bool IsSubclassOf(this Type self, IEnumerable anyTypes) + public static bool IsSubclassOfAny(this Type self, IEnumerable anyTypes) { if (self == null) { @@ -173,6 +173,59 @@ public static bool IsSubclassOf(this Type self, IEnumerable anyTypes) return false; } + public static bool IsSubclassOfRawGeneric(this Type self, Type genericType) + { + if (self == null) + { + DebugUtility.LogException(nameof(self)); + return false; + } + + if (genericType == null) + { + DebugUtility.LogException(nameof(genericType)); + return false; + } + + while (self != null && self != typeof(object)) + { + var definition = self.IsGenericType ? self.GetGenericTypeDefinition() : self; + if (genericType == definition && self != genericType) + { + return true; + } + + self = self.BaseType; + } + + return false; + } + + public static bool IsSubclassOfAnyRawGeneric(this Type self, IEnumerable genericTypes) + { + if (self == null) + { + DebugUtility.LogException(nameof(self)); + return false; + } + + if (genericTypes == null) + { + DebugUtility.LogException(nameof(genericTypes)); + return false; + } + + foreach (var anyType in genericTypes) + { + if (anyType != null && self.IsSubclassOfRawGeneric(anyType)) + { + return true; + } + } + + return false; + } + public static Type GetElementType(this Type self) { if (self == null) diff --git a/Assets/BetterExtensions/Runtime/Extensions/UnityEventExtensions.cs b/Assets/BetterExtensions/Runtime/Extensions/UnityEventExtensions.cs new file mode 100644 index 0000000..3a2e137 --- /dev/null +++ b/Assets/BetterExtensions/Runtime/Extensions/UnityEventExtensions.cs @@ -0,0 +1,35 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using Better.Extensions.Runtime.Helpers; +using UnityEngine.Events; + +namespace Better.Extensions.Runtime +{ + public static class UnityEventExtensions + { + public static Task Await(this UnityEvent self, CancellationToken cancellationToken = default) + { + if (self == null) + { + DebugUtility.LogException(nameof(self)); + return Task.CompletedTask; + } + + var completionAwaiter = new UnityEventCompletionAwaiter(self, cancellationToken); + return completionAwaiter.Task; + } + + public static Task Await(this UnityEvent self, CancellationToken cancellationToken = default) + { + if (self == null) + { + DebugUtility.LogException(nameof(self)); + return Task.FromResult(default(T)); + } + + var completionAwaiter = new UnityEventCompletionAwaiter(self, cancellationToken); + return completionAwaiter.Task; + } + } +} \ No newline at end of file diff --git a/Assets/BetterExtensions/Runtime/Extensions/UnityEventExtensions.cs.meta b/Assets/BetterExtensions/Runtime/Extensions/UnityEventExtensions.cs.meta new file mode 100644 index 0000000..b69be7f --- /dev/null +++ b/Assets/BetterExtensions/Runtime/Extensions/UnityEventExtensions.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a124bdff0b4c43a48ce2ac36ca6172e6 +timeCreated: 1661897841 \ No newline at end of file diff --git a/Assets/BetterExtensions/Runtime/Extensions/UnityObjectExtensions.cs b/Assets/BetterExtensions/Runtime/Extensions/UnityObjectExtensions.cs index df02ac0..4f71f19 100644 --- a/Assets/BetterExtensions/Runtime/Extensions/UnityObjectExtensions.cs +++ b/Assets/BetterExtensions/Runtime/Extensions/UnityObjectExtensions.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Linq; using Object = UnityEngine.Object; namespace Better.Extensions.Runtime @@ -39,5 +41,60 @@ public static string GetPrettyObjectName(this Object self, params string[] remov return self.name.PrettyCamelCase(); } + + public static void Destroy(this Object self) + { + if (self.IsNullOrDestroyed()) + { + var message = $"{nameof(self)} already null or destroyed"; + DebugUtility.LogException(message); + return; + } + + Object.Destroy(self); + } + + public static void Destroy(this Object self, float delay) + { + if (self.IsNullOrDestroyed()) + { + var message = $"{nameof(self)} already null or destroyed"; + DebugUtility.LogException(message); + return; + } + + delay = MathF.Max(delay, 0f); + Object.Destroy(self, delay); + } + + public static void Destroy(this IEnumerable self) + { + if (self == null) + { + DebugUtility.LogException(nameof(self)); + return; + } + + var cached = self.ToArray(); + for (var i = 0; i < cached.Length; i++) + { + cached[i].Destroy(); + } + } + + public static void Destroy(this IEnumerable self, float delay) + { + if (self == null) + { + DebugUtility.LogException(nameof(self)); + return; + } + + var cached = self.ToArray(); + for (var i = 0; i < cached.Length; i++) + { + cached[i].Destroy(delay); + } + } } } \ No newline at end of file diff --git a/Assets/BetterExtensions/Runtime/Extensions/UnityWebRequestAsyncOperationExtensions.cs b/Assets/BetterExtensions/Runtime/Extensions/UnityWebRequestAsyncOperationExtensions.cs new file mode 100644 index 0000000..3b528f2 --- /dev/null +++ b/Assets/BetterExtensions/Runtime/Extensions/UnityWebRequestAsyncOperationExtensions.cs @@ -0,0 +1,19 @@ +using System; +using Better.Extensions.Runtime.Helpers; +using UnityEngine.Networking; + +namespace Better.Extensions.Runtime +{ + public static class UnityWebRequestAsyncOperationExtensions + { + public static UnityWebRequestAwaiter GetAwaiter(this UnityWebRequestAsyncOperation self) + { + if (self == null) + { + throw new ArgumentNullException(nameof(self)); + } + + return new UnityWebRequestAwaiter(self); + } + } +} \ No newline at end of file diff --git a/Assets/BetterExtensions/Runtime/Extensions/UnityWebRequestAsyncOperationExtensions.cs.meta b/Assets/BetterExtensions/Runtime/Extensions/UnityWebRequestAsyncOperationExtensions.cs.meta new file mode 100644 index 0000000..3130b7e --- /dev/null +++ b/Assets/BetterExtensions/Runtime/Extensions/UnityWebRequestAsyncOperationExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b07b1130bc32e864eb94eee0a852e0e3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/BetterExtensions/Runtime/Extensions/Vector2Extensions.cs b/Assets/BetterExtensions/Runtime/Extensions/Vector2Extensions.cs index 63e03e0..8f5a162 100644 --- a/Assets/BetterExtensions/Runtime/Extensions/Vector2Extensions.cs +++ b/Assets/BetterExtensions/Runtime/Extensions/Vector2Extensions.cs @@ -8,5 +8,25 @@ public static bool Approximately(this Vector2 self, Vector2 other) { return Vector2Utility.Approximately(self, other); } + + public static Vector2 DirectionTo(this Vector2 self, Vector2 to) + { + return Vector2Utility.Direction(self, to); + } + + public static float DistanceTo(this Vector2 self, Vector2 to) + { + return Vector2.Distance(self, to); + } + + public static float SqrDistanceTo(this Vector2 self, Vector2 to) + { + return Vector2Utility.SqrDistanceTo(self, to); + } + + public static Vector2 Abs(this Vector2 self) + { + return Vector2Utility.Abs(self); + } } } \ No newline at end of file diff --git a/Assets/BetterExtensions/Runtime/Extensions/Vector3Extensions.cs b/Assets/BetterExtensions/Runtime/Extensions/Vector3Extensions.cs index 6193856..5920cbc 100644 --- a/Assets/BetterExtensions/Runtime/Extensions/Vector3Extensions.cs +++ b/Assets/BetterExtensions/Runtime/Extensions/Vector3Extensions.cs @@ -31,5 +31,30 @@ public static Vector3 Average(this IEnumerable self) { return Vector3Utility.Average(self); } + + public static Vector3 Flat(this Vector3 self) + { + return Vector3Utility.Flat(self); + } + + public static Vector3 DirectionTo(this Vector3 self, Vector3 to) + { + return Vector3Utility.Direction(self, to); + } + + public static float DistanceTo(this Vector3 self, Vector3 to) + { + return Vector3.Distance(self, to); + } + + public static float SqrDistanceTo(this Vector3 self, Vector3 to) + { + return Vector3Utility.SqrDistanceTo(self, to); + } + + public static Vector3 Abs(this Vector3 self) + { + return Vector3Utility.Abs(self); + } } } \ No newline at end of file diff --git a/Assets/BetterExtensions/Runtime/Helpers.meta b/Assets/BetterExtensions/Runtime/Helpers.meta new file mode 100644 index 0000000..7927421 --- /dev/null +++ b/Assets/BetterExtensions/Runtime/Helpers.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3d6e5b51746a4be1bb028aa421f26655 +timeCreated: 1709047095 \ No newline at end of file diff --git a/Assets/BetterExtensions/Runtime/Helpers/CompletionAwaiters.meta b/Assets/BetterExtensions/Runtime/Helpers/CompletionAwaiters.meta new file mode 100644 index 0000000..20d2e03 --- /dev/null +++ b/Assets/BetterExtensions/Runtime/Helpers/CompletionAwaiters.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9734a1978cb1cae4896533adc1df57a2 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/BetterExtensions/Runtime/Helpers/CompletionAwaiters/BaseCompletionAwaiter.cs b/Assets/BetterExtensions/Runtime/Helpers/CompletionAwaiters/BaseCompletionAwaiter.cs new file mode 100644 index 0000000..a9ea13f --- /dev/null +++ b/Assets/BetterExtensions/Runtime/Helpers/CompletionAwaiters/BaseCompletionAwaiter.cs @@ -0,0 +1,37 @@ +using System.Threading; +using System.Threading.Tasks; + +namespace Better.Extensions.Runtime.Helpers +{ + internal abstract class BaseCompletionAwaiter + { + private readonly TaskCompletionSource _completionSource; + public Task Task => _completionSource.Task; + + public BaseCompletionAwaiter(CancellationToken cancellationToken) + { + _completionSource = new(); + cancellationToken.Register(Cancel); + + if (cancellationToken.IsCancellationRequested) + { + SetResult(default); + } + } + + protected void SetResult(T value) + { + if (!_completionSource.TrySetResult(value)) + { + OnCompleted(value); + } + } + + private void Cancel() + { + SetResult(default); + } + + protected abstract void OnCompleted(T result); + } +} \ No newline at end of file diff --git a/Assets/BetterExtensions/Runtime/Helpers/CompletionAwaiters/BaseCompletionAwaiter.cs.meta b/Assets/BetterExtensions/Runtime/Helpers/CompletionAwaiters/BaseCompletionAwaiter.cs.meta new file mode 100644 index 0000000..b982476 --- /dev/null +++ b/Assets/BetterExtensions/Runtime/Helpers/CompletionAwaiters/BaseCompletionAwaiter.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 872e453b20eb42d78ab92a6e3132ee2c +timeCreated: 1661898951 \ No newline at end of file diff --git a/Assets/BetterExtensions/Runtime/Helpers/CompletionAwaiters/UnityEventCompletionAwaiter.cs b/Assets/BetterExtensions/Runtime/Helpers/CompletionAwaiters/UnityEventCompletionAwaiter.cs new file mode 100644 index 0000000..6ba8318 --- /dev/null +++ b/Assets/BetterExtensions/Runtime/Helpers/CompletionAwaiters/UnityEventCompletionAwaiter.cs @@ -0,0 +1,35 @@ +using System.Threading; +using UnityEngine.Events; + +namespace Better.Extensions.Runtime.Helpers +{ + internal class UnityEventCompletionAwaiter : BaseCompletionAwaiter + { + private UnityEvent _sourceEvent; + + public UnityEventCompletionAwaiter(UnityEvent sourceEvent, CancellationToken cancellationToken) + : base(cancellationToken) + { + _sourceEvent = sourceEvent; + _sourceEvent.AddListener(OnSourceInvoked); + } + + private void OnSourceInvoked(T value) => SetResult(value); + protected override void OnCompleted(T result) => _sourceEvent.RemoveListener(OnSourceInvoked); + } + + internal class UnityEventCompletionAwaiter : BaseCompletionAwaiter + { + private UnityEvent _sourceEvent; + + public UnityEventCompletionAwaiter(UnityEvent sourceEvent, CancellationToken cancellationToken) + : base(cancellationToken) + { + _sourceEvent = sourceEvent; + _sourceEvent.AddListener(OnSourceInvoked); + } + + private void OnSourceInvoked() => SetResult(true); + protected override void OnCompleted(bool result) => _sourceEvent.RemoveListener(OnSourceInvoked); + } +} \ No newline at end of file diff --git a/Assets/BetterExtensions/Runtime/Helpers/CompletionAwaiters/UnityEventCompletionAwaiter.cs.meta b/Assets/BetterExtensions/Runtime/Helpers/CompletionAwaiters/UnityEventCompletionAwaiter.cs.meta new file mode 100644 index 0000000..d411927 --- /dev/null +++ b/Assets/BetterExtensions/Runtime/Helpers/CompletionAwaiters/UnityEventCompletionAwaiter.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 41e801e976584c998882c427c23abca8 +timeCreated: 1661904618 \ No newline at end of file diff --git a/Assets/BetterExtensions/Runtime/Helpers/NotifyCompletions.meta b/Assets/BetterExtensions/Runtime/Helpers/NotifyCompletions.meta new file mode 100644 index 0000000..601fb81 --- /dev/null +++ b/Assets/BetterExtensions/Runtime/Helpers/NotifyCompletions.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 21e930de513653940ac4d594b3bc3a36 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/BetterExtensions/Runtime/Helpers/NotifyCompletions/AssetBundleRequestAwaiter.cs b/Assets/BetterExtensions/Runtime/Helpers/NotifyCompletions/AssetBundleRequestAwaiter.cs new file mode 100644 index 0000000..4c6c32b --- /dev/null +++ b/Assets/BetterExtensions/Runtime/Helpers/NotifyCompletions/AssetBundleRequestAwaiter.cs @@ -0,0 +1,30 @@ +using System; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using UnityEngine; +using Object = UnityEngine.Object; + +namespace Better.Extensions.Runtime.Helpers +{ + [DebuggerNonUserCode] + public readonly struct AssetBundleRequestAwaiter : INotifyCompletion + { + private readonly AssetBundleRequest _asyncOperation; + public bool IsCompleted => _asyncOperation.isDone; + + public AssetBundleRequestAwaiter(AssetBundleRequest asyncOperation) + { + _asyncOperation = asyncOperation; + } + + public void OnCompleted(Action continuation) + { + _asyncOperation.completed += _ => continuation(); + } + + public Object GetResult() + { + return _asyncOperation.asset; + } + } +} \ No newline at end of file diff --git a/Assets/BetterExtensions/Runtime/Helpers/NotifyCompletions/AssetBundleRequestAwaiter.cs.meta b/Assets/BetterExtensions/Runtime/Helpers/NotifyCompletions/AssetBundleRequestAwaiter.cs.meta new file mode 100644 index 0000000..1384952 --- /dev/null +++ b/Assets/BetterExtensions/Runtime/Helpers/NotifyCompletions/AssetBundleRequestAwaiter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d76730a1e758d8a4fbdc6ea917c7820e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/BetterExtensions/Runtime/Helpers/NotifyCompletions/AsyncOperationAwaiter.cs b/Assets/BetterExtensions/Runtime/Helpers/NotifyCompletions/AsyncOperationAwaiter.cs new file mode 100644 index 0000000..2f7812c --- /dev/null +++ b/Assets/BetterExtensions/Runtime/Helpers/NotifyCompletions/AsyncOperationAwaiter.cs @@ -0,0 +1,29 @@ +using System; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using UnityEngine; + +namespace Better.Extensions.Runtime.Helpers +{ + [DebuggerNonUserCode] + public readonly struct AsyncOperationAwaiter : INotifyCompletion + { + private readonly AsyncOperation _asyncOperation; + public bool IsCompleted => _asyncOperation.isDone; + + public AsyncOperationAwaiter(AsyncOperation asyncOperation) + { + _asyncOperation = asyncOperation; + } + + public void OnCompleted(Action continuation) + { + _asyncOperation.completed += _ => continuation(); + } + + public AsyncOperation GetResult() + { + return _asyncOperation; + } + } +} \ No newline at end of file diff --git a/Assets/BetterExtensions/Runtime/Helpers/NotifyCompletions/AsyncOperationAwaiter.cs.meta b/Assets/BetterExtensions/Runtime/Helpers/NotifyCompletions/AsyncOperationAwaiter.cs.meta new file mode 100644 index 0000000..4a6edb9 --- /dev/null +++ b/Assets/BetterExtensions/Runtime/Helpers/NotifyCompletions/AsyncOperationAwaiter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 77ded2fb603c7514fb41c6ff21489404 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/BetterExtensions/Runtime/Helpers/NotifyCompletions/ResourceRequestAwaiter.cs b/Assets/BetterExtensions/Runtime/Helpers/NotifyCompletions/ResourceRequestAwaiter.cs new file mode 100644 index 0000000..6617b13 --- /dev/null +++ b/Assets/BetterExtensions/Runtime/Helpers/NotifyCompletions/ResourceRequestAwaiter.cs @@ -0,0 +1,29 @@ +using System; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using UnityEngine; + +namespace Better.Extensions.Runtime.Helpers +{ + [DebuggerNonUserCode] + public readonly struct ResourceRequestAwaiter : INotifyCompletion + { + private readonly ResourceRequest _asyncOperation; + public bool IsCompleted => _asyncOperation.isDone; + + public ResourceRequestAwaiter(ResourceRequest asyncOperation) + { + _asyncOperation = asyncOperation; + } + + public void OnCompleted(Action continuation) + { + _asyncOperation.completed += _ => continuation(); + } + + public ResourceRequest GetResult() + { + return _asyncOperation; + } + } +} \ No newline at end of file diff --git a/Assets/BetterExtensions/Runtime/Helpers/NotifyCompletions/ResourceRequestAwaiter.cs.meta b/Assets/BetterExtensions/Runtime/Helpers/NotifyCompletions/ResourceRequestAwaiter.cs.meta new file mode 100644 index 0000000..d253c18 --- /dev/null +++ b/Assets/BetterExtensions/Runtime/Helpers/NotifyCompletions/ResourceRequestAwaiter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b53d2eae0f82f5f458caf4c948c5e3d5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/BetterExtensions/Runtime/Helpers/NotifyCompletions/UnityWebRequestAwaiter.cs b/Assets/BetterExtensions/Runtime/Helpers/NotifyCompletions/UnityWebRequestAwaiter.cs new file mode 100644 index 0000000..bfcff2c --- /dev/null +++ b/Assets/BetterExtensions/Runtime/Helpers/NotifyCompletions/UnityWebRequestAwaiter.cs @@ -0,0 +1,30 @@ +using System; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using UnityEngine.Networking; + +namespace Better.Extensions.Runtime.Helpers +{ + [DebuggerNonUserCode] + public readonly struct UnityWebRequestAwaiter : INotifyCompletion + { + private readonly UnityWebRequestAsyncOperation _asyncOperation; + + public bool IsCompleted => _asyncOperation.isDone; + + public UnityWebRequestAwaiter(UnityWebRequestAsyncOperation asyncOperation) + { + _asyncOperation = asyncOperation; + } + + public void OnCompleted(Action continuation) + { + _asyncOperation.completed += _ => continuation(); + } + + public UnityWebRequest GetResult() + { + return _asyncOperation.webRequest; + } + } +} \ No newline at end of file diff --git a/Assets/BetterExtensions/Runtime/Helpers/NotifyCompletions/UnityWebRequestAwaiter.cs.meta b/Assets/BetterExtensions/Runtime/Helpers/NotifyCompletions/UnityWebRequestAwaiter.cs.meta new file mode 100644 index 0000000..d27d95a --- /dev/null +++ b/Assets/BetterExtensions/Runtime/Helpers/NotifyCompletions/UnityWebRequestAwaiter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d2312f0077350d04ca0f4cd66a5113b0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/BetterExtensions/Runtime/Utility/QuaternionUtility.cs b/Assets/BetterExtensions/Runtime/Utility/QuaternionUtility.cs index 28ae16c..5eaf61c 100644 --- a/Assets/BetterExtensions/Runtime/Utility/QuaternionUtility.cs +++ b/Assets/BetterExtensions/Runtime/Utility/QuaternionUtility.cs @@ -9,10 +9,21 @@ public static bool IsNormalized(Quaternion quaternion) var magnitudeSquared = quaternion.x * quaternion.x + quaternion.y * quaternion.y + quaternion.z * quaternion.z + quaternion.w * quaternion.w; return Mathf.Approximately(magnitudeSquared, 1.0f); } - + public static bool Approximately(Quaternion current, Quaternion other) { return Mathf.Approximately(Quaternion.Dot(current, other), 1.0f); } + + public static Quaternion Scale(Quaternion quaternion, Vector3 scale) + { + quaternion.eulerAngles = Vector3.Scale(quaternion.eulerAngles, scale); + return quaternion; + } + + public static Quaternion Scale(Quaternion quaternion, float scale) + { + return Scale(quaternion, Vector3.one * scale); + } } } \ No newline at end of file diff --git a/Assets/BetterExtensions/Runtime/Utility/TaskUtility.cs b/Assets/BetterExtensions/Runtime/Utility/TaskUtility.cs index 5a3e06a..8ace64e 100644 --- a/Assets/BetterExtensions/Runtime/Utility/TaskUtility.cs +++ b/Assets/BetterExtensions/Runtime/Utility/TaskUtility.cs @@ -1,4 +1,5 @@ -using System.Threading; +using System; +using System.Threading; using System.Threading.Tasks; namespace Better.Extensions.Runtime @@ -10,5 +11,53 @@ public static Task WaitForSeconds(float seconds, CancellationToken cancellationT var millisecondsDelay = TimeUtility.SecondsToMilliseconds(seconds); return Task.Delay(millisecondsDelay, cancellationToken); } + + public static async Task WaitWhile(Func condition, CancellationToken cancellationToken = default) + { + if (condition == null) + { + DebugUtility.LogException(nameof(condition)); + return; + } + + while (!cancellationToken.IsCancellationRequested && condition.Invoke()) + { + await Task.Yield(); + } + } + + public static async Task WaitUntil(Func condition, CancellationToken cancellationToken = default) + { + if (condition == null) + { + DebugUtility.LogException(nameof(condition)); + return; + } + + while (!cancellationToken.IsCancellationRequested && !condition.Invoke()) + { + await Task.Yield(); + } + } + + public static async Task WaitFrame(int count, CancellationToken cancellationToken = default) + { + if (count < 1) + { + var message = $"{nameof(count)} cannot be less 1"; + DebugUtility.LogException(message); + return; + } + + for (int i = 0; i < count; i++) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + await Task.Yield(); + } + } } } \ No newline at end of file diff --git a/Assets/BetterExtensions/Runtime/Utility/Vector2Utility.cs b/Assets/BetterExtensions/Runtime/Utility/Vector2Utility.cs index 4cf6dd1..f384e03 100644 --- a/Assets/BetterExtensions/Runtime/Utility/Vector2Utility.cs +++ b/Assets/BetterExtensions/Runtime/Utility/Vector2Utility.cs @@ -43,5 +43,24 @@ public static float InverseLerp(Vector2 a, Vector2 b, Vector2 value) var result = Vector2.Dot(av, ab) / Vector2.Dot(ab, ab); return Mathf.Clamp01(result); } + + public static Vector2 Direction(Vector2 from, Vector2 to) + { + var difference = to - from; + return difference.normalized; + } + + public static float SqrDistanceTo(Vector2 from, Vector2 to) + { + var difference = to - from; + return difference.sqrMagnitude; + } + + public static Vector2 Abs(Vector2 source) + { + source.x = Mathf.Abs(source.x); + source.y = Mathf.Abs(source.y); + return source; + } } } \ No newline at end of file diff --git a/Assets/BetterExtensions/Runtime/Utility/Vector3Utility.cs b/Assets/BetterExtensions/Runtime/Utility/Vector3Utility.cs index e627495..e7201ce 100644 --- a/Assets/BetterExtensions/Runtime/Utility/Vector3Utility.cs +++ b/Assets/BetterExtensions/Runtime/Utility/Vector3Utility.cs @@ -140,5 +140,31 @@ public static Vector3 AxesInverseLerp(Vector3 a, Vector3 b, Vector3 value) Mathf.InverseLerp(a.z, b.z, value.z) ); } + + public static Vector3 Flat(Vector3 source) + { + source.y = default; + return source; + } + + public static Vector3 Direction(Vector3 from, Vector3 to) + { + var difference = to - from; + return difference.normalized; + } + + public static float SqrDistanceTo(Vector3 from, Vector3 to) + { + var difference = to - from; + return difference.sqrMagnitude; + } + + public static Vector3 Abs(Vector3 self) + { + self.x = Mathf.Abs(self.x); + self.y = Mathf.Abs(self.y); + self.z = Mathf.Abs(self.z); + return self; + } } } \ No newline at end of file diff --git a/Assets/BetterExtensions/package.json b/Assets/BetterExtensions/package.json index a9e9640..8a9ff63 100644 --- a/Assets/BetterExtensions/package.json +++ b/Assets/BetterExtensions/package.json @@ -2,7 +2,7 @@ "name": "com.uurha.betterextensions", "displayName": "Better Extensions", "description": "Unity extensions, serialize extension, async extension, string extension and UI extensions", - "version": "1.5.1", + "version": "1.5.2", "unity": "2020.1", "author": { "name": "Better Plugins",