< Summary

Class:DCL.Helpers.Utils
Assembly:Utils
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Helpers/Utils/Utils.cs
Covered lines:145
Uncovered lines:117
Coverable lines:262
Total lines:673
Line coverage:55.3% (145 of 262)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
EnsureResourcesMaterial(...)0%440100%
CleanMaterials(...)0%440100%
ToggleRenderFeature[T](...)0%56700%
FloatArrayToV2List(...)0%6200%
FloatArrayToV2List(...)0%220100%
CapGlobalValuesToMax(...)0%12.3310071.43%
SetTransformGlobalValues(...)0%3.032036.36%
ResetLocalTRS(...)0%110100%
SetToMaxStretch(...)0%110100%
SetToCentered(...)0%2100%
SetToBottomLeft(...)0%2100%
ForceUpdateLayout(...)0%4.074083.33%
ForceRebuildLayoutImmediate(...)0%660100%
ForceUpdateLayoutRoutine()0%440100%
InverseTransformChildTraversal[TComponent](...)0%550100%
ForwardTransformChildTraversal[TComponent](...)0%30500%
GetOrCreateComponent[T](...)0%220100%
FetchTexture(...)0%110100%
SafeFromJsonOverwrite(...)0%2100%
FromJsonWithNulls[T](...)0%110100%
SafeFromJson[T](...)0%4.434070%
AttachPlaceholderRendererGameObject(...)0%110100%
SafeDestroy(...)0%4.123050%
GridToWorldPosition(...)0%110100%
WorldToGridPosition(...)0%110100%
WorldToGridPositionUnclamped(...)0%110100%
AproxComparison(...)0%440100%
ParseJsonArray[T](...)0%110100%
Utils()0%110100%
LockedThisFrame()0%2100%
LockCursor()0%220100%
UnlockCursor()0%220100%
BrowserSetCursorState(...)0%12300%
DestroyAllChild(...)0%330100%
GetBottomLeftZoneArray(...)0%12300%
GetCenteredZoneArray(...)0%12300%
DrawRectGizmo(...)0%2100%
ToUpperFirst(...)0%220100%
Sanitize(...)0%770100%
CompareFloats(...)0%2100%
Deconstruct[T1, T2](...)0%110100%
SetLayerRecursively(...)0%330100%
ToVolumeCurve(...)0%2100%
ToAudioMixerGroupVolume(...)0%2100%
Wait()0%5.673033.33%
GetHierarchyPath(...)0%6200%
TryFindChildRecursively(...)0%30500%
IsPointerOverUIElement(...)0%6200%
IsPointerOverUIElement()0%2100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Helpers/Utils/Utils.cs

#LineLine coverage
 1#if UNITY_WEBGL && !UNITY_EDITOR
 2#define WEB_PLATFORM
 3#endif
 4
 5using System;
 6using System.Collections;
 7using System.Collections.Generic;
 8using System.Linq;
 9using System.Reflection;
 10using DCL.Configuration;
 11using Google.Protobuf.Collections;
 12using Newtonsoft.Json;
 13using TMPro;
 14using UnityEngine;
 15using UnityEngine.Assertions;
 16using UnityEngine.EventSystems;
 17using UnityEngine.Networking;
 18using UnityEngine.UI;
 19using Object = UnityEngine.Object;
 20using UnityEngine.Rendering.Universal;
 21
 22namespace DCL.Helpers
 23{
 24    public static class Utils
 25    {
 26        public static Dictionary<string, Material> staticMaterials;
 27
 28        public static Material EnsureResourcesMaterial(string path)
 29        {
 71130            if (staticMaterials == null)
 31            {
 132                staticMaterials = new Dictionary<string, Material>();
 33            }
 34
 71135            if (!staticMaterials.ContainsKey(path))
 36            {
 437                Material material = Resources.Load(path) as Material;
 38
 439                if (material != null)
 40                {
 441                    staticMaterials.Add(path, material);
 42                }
 43
 444                return material;
 45            }
 46
 70747            return staticMaterials[path];
 48        }
 49
 50        public static void CleanMaterials(Renderer r)
 51        {
 12352            if (r != null)
 53            {
 49254                foreach (Material m in r.materials)
 55                {
 12356                    if (m != null)
 57                    {
 12358                        Material.Destroy(m);
 59                    }
 60                }
 61            }
 12362        }
 63
 64        public static ScriptableRendererFeature ToggleRenderFeature<T>(this UniversalRenderPipelineAsset asset, bool ena
 65        {
 066            var type = asset.GetType();
 067            var propertyInfo = type.GetField("m_RendererDataList", BindingFlags.Instance | BindingFlags.NonPublic);
 68
 069            if (propertyInfo == null)
 70            {
 071                return null;
 72            }
 73
 074            var scriptableRenderData = (ScriptableRendererData[])propertyInfo.GetValue(asset);
 75
 076            if (scriptableRenderData != null && scriptableRenderData.Length > 0)
 77            {
 078                foreach (var renderData in scriptableRenderData)
 79                {
 080                    foreach (var rendererFeature in renderData.rendererFeatures)
 81                    {
 082                        if (rendererFeature is T)
 83                        {
 084                            rendererFeature.SetActive(enable);
 85
 086                            return rendererFeature;
 87                        }
 88                    }
 89                }
 90            }
 91
 092            return null;
 093        }
 94
 95        public static Vector2[] FloatArrayToV2List(RepeatedField<float> uvs)
 96        {
 097            Vector2[] uvsResult = new Vector2[uvs.Count / 2];
 098            int uvsResultIndex = 0;
 99
 0100            for (int i = 0; i < uvs.Count;)
 101            {
 0102                Vector2 tmpUv = Vector2.zero;
 0103                tmpUv.x = uvs[i++];
 0104                tmpUv.y = uvs[i++];
 105
 0106                uvsResult[uvsResultIndex++] = tmpUv;
 107            }
 108
 0109            return uvsResult;
 110        }
 111
 112        public static Vector2[] FloatArrayToV2List(IList<float> uvs)
 113        {
 7114            Vector2[] uvsResult = new Vector2[uvs.Count / 2];
 7115            int uvsResultIndex = 0;
 116
 118117            for (int i = 0; i < uvs.Count;)
 118            {
 104119                uvsResult[uvsResultIndex++] = new Vector2(uvs[i++],uvs[i++]);
 120            }
 121
 7122            return uvsResult;
 123        }
 124
 125        private const int MAX_TRANSFORM_VALUE = 10000;
 126        public static void CapGlobalValuesToMax(this Transform transform)
 127        {
 278128            bool positionOutsideBoundaries = transform.position.sqrMagnitude > MAX_TRANSFORM_VALUE * MAX_TRANSFORM_VALUE
 278129            bool scaleOutsideBoundaries = transform.lossyScale.sqrMagnitude > MAX_TRANSFORM_VALUE * MAX_TRANSFORM_VALUE;
 130
 278131            if (positionOutsideBoundaries || scaleOutsideBoundaries)
 132            {
 2133                Vector3 newPosition = transform.position;
 2134                if (positionOutsideBoundaries)
 135                {
 2136                    if (Mathf.Abs(newPosition.x) > MAX_TRANSFORM_VALUE)
 2137                        newPosition.x = MAX_TRANSFORM_VALUE * Mathf.Sign(newPosition.x);
 138
 2139                    if (Mathf.Abs(newPosition.y) > MAX_TRANSFORM_VALUE)
 2140                        newPosition.y = MAX_TRANSFORM_VALUE * Mathf.Sign(newPosition.y);
 141
 2142                    if (Mathf.Abs(newPosition.z) > MAX_TRANSFORM_VALUE)
 2143                        newPosition.z = MAX_TRANSFORM_VALUE * Mathf.Sign(newPosition.z);
 144                }
 145
 2146                Vector3 newScale = transform.lossyScale;
 2147                if (scaleOutsideBoundaries)
 148                {
 0149                    if (Mathf.Abs(newScale.x) > MAX_TRANSFORM_VALUE)
 0150                        newScale.x = MAX_TRANSFORM_VALUE * Mathf.Sign(newScale.x);
 151
 0152                    if (Mathf.Abs(newScale.y) > MAX_TRANSFORM_VALUE)
 0153                        newScale.y = MAX_TRANSFORM_VALUE * Mathf.Sign(newScale.y);
 154
 0155                    if (Mathf.Abs(newScale.z) > MAX_TRANSFORM_VALUE)
 0156                        newScale.z = MAX_TRANSFORM_VALUE * Mathf.Sign(newScale.z);
 157                }
 158
 2159                SetTransformGlobalValues(transform, newPosition, transform.rotation, newScale, scaleOutsideBoundaries);
 160            }
 278161        }
 162
 163        public static void SetTransformGlobalValues(Transform transform, Vector3 newPos, Quaternion newRot, Vector3 newS
 164        {
 2165            transform.position = newPos;
 2166            transform.rotation = newRot;
 167
 2168            if (setScale)
 169            {
 0170                transform.localScale = Vector3.one;
 0171                var m = transform.worldToLocalMatrix;
 172
 0173                m.SetColumn(0, new Vector4(m.GetColumn(0).magnitude, 0f));
 0174                m.SetColumn(1, new Vector4(0f, m.GetColumn(1).magnitude));
 0175                m.SetColumn(2, new Vector4(0f, 0f, m.GetColumn(2).magnitude));
 0176                m.SetColumn(3, new Vector4(0f, 0f, 0f, 1f));
 177
 0178                transform.localScale = m.MultiplyPoint(newScale);
 179            }
 2180        }
 181
 182        public static void ResetLocalTRS(this Transform t)
 183        {
 2853184            t.localPosition = Vector3.zero;
 2853185            t.localRotation = Quaternion.identity;
 2853186            t.localScale = Vector3.one;
 2853187        }
 188
 189        public static void SetToMaxStretch(this RectTransform t)
 190        {
 198191            t.anchorMin = Vector2.zero;
 198192            t.offsetMin = Vector2.zero;
 198193            t.anchorMax = Vector2.one;
 198194            t.offsetMax = Vector2.one;
 198195            t.sizeDelta = Vector2.zero;
 198196            t.anchoredPosition = Vector2.zero;
 198197        }
 198
 199        public static void SetToCentered(this RectTransform t)
 200        {
 0201            t.anchorMin = Vector2.one * 0.5f;
 0202            t.offsetMin = Vector2.one * 0.5f;
 0203            t.anchorMax = Vector2.one * 0.5f;
 0204            t.offsetMax = Vector2.one * 0.5f;
 0205            t.sizeDelta = Vector2.one * 100;
 0206        }
 207
 208        public static void SetToBottomLeft(this RectTransform t)
 209        {
 0210            t.anchorMin = Vector2.zero;
 0211            t.offsetMin = Vector2.zero;
 0212            t.anchorMax = Vector2.zero;
 0213            t.offsetMax = Vector2.zero;
 0214            t.sizeDelta = Vector2.one * 100;
 0215        }
 216
 217        public static void ForceUpdateLayout(this RectTransform rt, bool delayed = true)
 218        {
 53219            if (!rt.gameObject.activeInHierarchy)
 0220                return;
 221
 53222            if (delayed)
 45223                CoroutineStarter.Start(ForceUpdateLayoutRoutine(rt));
 224            else
 225            {
 8226                InverseTransformChildTraversal<RectTransform>(
 450227                    (x) => { ForceRebuildLayoutImmediate(x); },
 228                    rt);
 229            }
 8230        }
 231
 232        /// <summary>
 233        /// Reimplementation of the LayoutRebuilder.ForceRebuildLayoutImmediate() function (Unity UI API) for make it mo
 234        /// </summary>
 235        /// <param name="rectTransformRoot">Root from which to rebuild.</param>
 236        public static void ForceRebuildLayoutImmediate(RectTransform rectTransformRoot)
 237        {
 15176238            if (rectTransformRoot == null)
 3239                return;
 240
 241            // NOTE(Santi): It seems to be very much cheaper to execute the next instructions manually than execute dire
 242            //              'LayoutRebuilder.ForceRebuildLayoutImmediate()', that theorically already contains these ins
 15173243            var layoutElements = rectTransformRoot.GetComponentsInChildren(typeof(ILayoutElement), true).ToList();
 287299244            layoutElements.RemoveAll(e => (e is Behaviour && !((Behaviour) e).isActiveAndEnabled) || e is TextMeshProUGU
 43558245            foreach (var layoutElem in layoutElements)
 246            {
 6606247                (layoutElem as ILayoutElement).CalculateLayoutInputHorizontal();
 6606248                (layoutElem as ILayoutElement).CalculateLayoutInputVertical();
 249            }
 250
 15173251            var layoutControllers = rectTransformRoot.GetComponentsInChildren(typeof(ILayoutController), true).ToList();
 72861252            layoutControllers.RemoveAll(e => e is Behaviour && !((Behaviour) e).isActiveAndEnabled);
 35054253            foreach (var layoutCtrl in layoutControllers)
 254            {
 2354255                (layoutCtrl as ILayoutController).SetLayoutHorizontal();
 2354256                (layoutCtrl as ILayoutController).SetLayoutVertical();
 257            }
 15173258        }
 259
 260        private static IEnumerator ForceUpdateLayoutRoutine(RectTransform rt)
 261        {
 45262            yield return null;
 263
 45264            InverseTransformChildTraversal<RectTransform>(
 4136265                (x) => { ForceRebuildLayoutImmediate(x); },
 266                rt);
 45267        }
 268
 269        public static void InverseTransformChildTraversal<TComponent>(Action<TComponent> action, Transform startTransfor
 270            where TComponent : Component
 271        {
 96537272            if (startTransform == null)
 10273                return;
 274
 382744275            foreach (Transform t in startTransform)
 276            {
 94845277                InverseTransformChildTraversal(action, t);
 278            }
 279
 96527280            var component = startTransform.GetComponent<TComponent>();
 281
 96527282            if (component != null)
 283            {
 15125284                action.Invoke(component);
 285            }
 96527286        }
 287
 288        public static void ForwardTransformChildTraversal<TComponent>(Func<TComponent, bool> action, Transform startTran
 289            where TComponent : Component
 290        {
 0291            Assert.IsTrue(startTransform != null, "startTransform must not be null");
 292
 0293            var component = startTransform.GetComponent<TComponent>();
 294
 0295            if (component != null)
 296            {
 0297                if (!action.Invoke(component))
 0298                    return;
 299            }
 300
 0301            foreach (Transform t in startTransform)
 302            {
 0303                ForwardTransformChildTraversal(action, t);
 304            }
 0305        }
 306
 307        public static T GetOrCreateComponent<T>(this GameObject gameObject) where T : Component
 308        {
 97309            T component = gameObject.GetComponent<T>();
 310
 97311            if (!component)
 312            {
 82313                return gameObject.AddComponent<T>();
 314            }
 315
 15316            return component;
 317        }
 318
 319        public static WebRequestAsyncOperation FetchTexture(string textureURL, bool isReadable, Action<Texture2D> OnSucc
 320        {
 321            //NOTE(Brian): This closure is called when the download is a success.
 0322            void SuccessInternal(IWebRequestAsyncOperation request) { OnSuccess?.Invoke(DownloadHandlerTexture.GetConten
 323
 147324            var asyncOp = Environment.i.platform.webRequest.GetTexture(
 325                url: textureURL,
 326                OnSuccess: SuccessInternal,
 327                OnFail: OnFail,
 328                isReadable: isReadable);
 329
 147330            return asyncOp;
 331        }
 332
 333        public static bool SafeFromJsonOverwrite(string json, object objectToOverwrite)
 334        {
 335            try
 336            {
 0337                JsonUtility.FromJsonOverwrite(json, objectToOverwrite);
 0338            }
 0339            catch (ArgumentException e)
 340            {
 0341                Debug.LogError("ArgumentException Fail!... Json = " + json + " " + e.ToString());
 0342                return false;
 343            }
 344
 0345            return true;
 0346        }
 347
 46348        public static T FromJsonWithNulls<T>(string json) { return JsonConvert.DeserializeObject<T>(json); }
 349
 350        public static T SafeFromJson<T>(string json)
 351        {
 903352            ProfilingEvents.OnMessageDecodeStart?.Invoke("Misc");
 353
 903354            T returningValue = default(T);
 355
 903356            if (!string.IsNullOrEmpty(json))
 357            {
 358                try
 359                {
 902360                    returningValue = JsonUtility.FromJson<T>(json);
 902361                }
 0362                catch (ArgumentException e)
 363                {
 0364                    Debug.LogError("ArgumentException Fail!... Json = " + json + " " + e.ToString());
 0365                }
 366            }
 367
 903368            ProfilingEvents.OnMessageDecodeEnds?.Invoke("Misc");
 369
 903370            return returningValue;
 371        }
 372
 373        public static GameObject AttachPlaceholderRendererGameObject(Transform targetTransform)
 374        {
 1375            var placeholderRenderer = GameObject.CreatePrimitive(PrimitiveType.Cube).GetComponent<MeshRenderer>();
 376
 1377            placeholderRenderer.material = Resources.Load<Material>("Materials/AssetLoading");
 1378            placeholderRenderer.transform.SetParent(targetTransform);
 1379            placeholderRenderer.transform.localPosition = Vector3.zero;
 1380            placeholderRenderer.name = "PlaceholderRenderer";
 381
 1382            return placeholderRenderer.gameObject;
 383        }
 384
 385        public static void SafeDestroy(Object obj)
 386        {
 603387            if (obj is Transform)
 0388                return;
 389
 390#if UNITY_EDITOR
 603391            if (Application.isPlaying)
 603392                Object.Destroy(obj);
 393            else
 0394                Object.DestroyImmediate(obj, false);
 395#else
 396                UnityEngine.Object.Destroy(obj);
 397#endif
 0398        }
 399
 400        /**
 401         * Transforms a grid position into a world-relative 3d position
 402         */
 403        public static Vector3 GridToWorldPosition(float xGridPosition, float yGridPosition)
 404        {
 1812405            return new Vector3(
 406                x: xGridPosition * ParcelSettings.PARCEL_SIZE,
 407                y: 0f,
 408                z: yGridPosition * ParcelSettings.PARCEL_SIZE
 409            );
 410        }
 411
 412        /**
 413         * Transforms a world position into a grid position
 414         */
 415        public static Vector2Int WorldToGridPosition(Vector3 worldPosition)
 416        {
 5371417            return new Vector2Int(
 418                (int) Mathf.Floor(worldPosition.x / ParcelSettings.PARCEL_SIZE),
 419                (int) Mathf.Floor(worldPosition.z / ParcelSettings.PARCEL_SIZE)
 420            );
 421        }
 422
 423        public static Vector2 WorldToGridPositionUnclamped(Vector3 worldPosition)
 424        {
 10425            return new Vector2(
 426                worldPosition.x / ParcelSettings.PARCEL_SIZE,
 427                worldPosition.z / ParcelSettings.PARCEL_SIZE
 428            );
 429        }
 430
 431        public static bool AproxComparison(this Color color1, Color color2, float tolerance = 0.01f) // tolerance of rou
 432        {
 4875433            if (Mathf.Abs(color1.r - color2.r) < tolerance
 434                && Mathf.Abs(color1.g - color2.g) < tolerance
 435                && Mathf.Abs(color1.b - color2.b) < tolerance)
 436            {
 55437                return true;
 438            }
 439
 4820440            return false;
 441        }
 442
 5443        public static T ParseJsonArray<T>(string jsonArray) where T : IEnumerable => DummyJsonUtilityFromArray<T>.GetFro
 444
 445        [Serializable]
 446        private class DummyJsonUtilityFromArray<T> where T : IEnumerable //UnityEngine.JsonUtility is really fast but ca
 447        {
 448            [SerializeField]
 449            private T value;
 450
 451            public static T GetFromJsonArray(string jsonArray)
 452            {
 453                string newJson = $"{{ \"value\": {jsonArray}}}";
 454                return JsonUtility.FromJson<DummyJsonUtilityFromArray<T>>(newJson).value;
 455            }
 456        }
 457
 1458        private static int lockedInFrame = -1;
 0459        public static bool LockedThisFrame() => lockedInFrame == Time.frameCount;
 460
 461        private static bool isCursorLocked;
 462        //NOTE(Brian): Made as an independent flag because the CI doesn't work well with the Cursor.lockState check.
 463        public static bool IsCursorLocked
 464        {
 5324465            get => isCursorLocked;
 466            private set
 467            {
 322468                if (isCursorLocked == value) return;
 90469                isCursorLocked = value;
 90470                OnCursorLockChanged?.Invoke(isCursorLocked);
 10471            }
 472        }
 473
 474        public static event Action<bool> OnCursorLockChanged;
 475
 476        public static void LockCursor()
 477        {
 478#if WEB_PLATFORM
 479            //TODO(Brian): Encapsulate all this mechanism to a new MouseLockController and branch
 480            //             behaviour using strategy pattern instead of this.
 481            if (IsCursorLocked)
 482            {
 483                return;
 484            }
 485#endif
 45486            Cursor.visible = false;
 45487            IsCursorLocked = true;
 45488            Cursor.lockState = CursorLockMode.Locked;
 45489            lockedInFrame = Time.frameCount;
 490
 45491            EventSystem.current?.SetSelectedGameObject(null);
 34492        }
 493
 494        public static void UnlockCursor()
 495        {
 496#if WEB_PLATFORM
 497            //TODO(Brian): Encapsulate all this mechanism to a new MouseLockController and branch
 498            //             behaviour using strategy pattern instead of this.
 499            if (!IsCursorLocked)
 500            {
 501                return;
 502            }
 503#endif
 161504            Cursor.visible = true;
 161505            IsCursorLocked = false;
 161506            Cursor.lockState = CursorLockMode.None;
 507
 161508            EventSystem.current?.SetSelectedGameObject(null);
 74509        }
 510
 511        #region BROWSER_ONLY
 512
 513        //TODO(Brian): Encapsulate all this mechanism to a new MouseLockController and branch
 514        //             behaviour using strategy pattern instead of this.
 515        // NOTE: This should come from browser's pointerlockchange callback
 516        public static void BrowserSetCursorState(bool locked)
 517        {
 0518            Cursor.lockState = locked ? CursorLockMode.Locked : CursorLockMode.None;
 519
 0520            IsCursorLocked = locked;
 0521            Cursor.visible = !locked;
 0522        }
 523
 524        #endregion
 525
 526        public static void DestroyAllChild(this Transform transform)
 527        {
 82528            foreach (Transform child in transform)
 529            {
 3530                Object.Destroy(child.gameObject);
 531            }
 38532        }
 533
 534        public static List<Vector2Int> GetBottomLeftZoneArray(Vector2Int bottomLeftAnchor, Vector2Int size)
 535        {
 0536            List<Vector2Int> coords = new List<Vector2Int>();
 537
 0538            for (int x = bottomLeftAnchor.x; x < bottomLeftAnchor.x + size.x; x++)
 539            {
 0540                for (int y = bottomLeftAnchor.y; y < bottomLeftAnchor.y + size.y; y++)
 541                {
 0542                    coords.Add(new Vector2Int(x, y));
 543                }
 544            }
 545
 0546            return coords;
 547        }
 548
 549        public static List<Vector2Int> GetCenteredZoneArray(Vector2Int center, Vector2Int size)
 550        {
 0551            List<Vector2Int> coords = new List<Vector2Int>();
 552
 0553            for (int x = center.x - size.x; x < center.x + size.x; x++)
 554            {
 0555                for (int y = center.y - size.y; y < center.y + size.y; y++)
 556                {
 0557                    coords.Add(new Vector2Int(x, y));
 558                }
 559            }
 560
 0561            return coords;
 562        }
 563
 564        public static void DrawRectGizmo(Rect rect, Color color, float duration)
 565        {
 0566            Vector3 tl2 = new Vector3(rect.xMin, rect.yMax, 0);
 0567            Vector3 bl2 = new Vector3(rect.xMin, rect.yMin, 0);
 0568            Vector3 tr2 = new Vector3(rect.xMax, rect.yMax, 0);
 0569            Vector3 br2 = new Vector3(rect.xMax, rect.yMin, 0);
 570
 0571            Debug.DrawLine(tl2, bl2, color, duration);
 0572            Debug.DrawLine(tl2, tr2, color, duration);
 0573            Debug.DrawLine(bl2, br2, color, duration);
 0574            Debug.DrawLine(tr2, br2, color, duration);
 0575        }
 576
 577        public static string ToUpperFirst(this string value)
 578        {
 12579            if (!string.IsNullOrEmpty(value))
 580            {
 12581                var capital = char.ToUpper(value[0]);
 12582                value = capital + value.Substring(1);
 583            }
 584
 12585            return value;
 586        }
 587
 588        public static Vector3 Sanitize(Vector3 value)
 589        {
 266590            float x = float.IsInfinity(value.x) ? 0 : value.x;
 266591            float y = float.IsInfinity(value.y) ? 0 : value.y;
 266592            float z = float.IsInfinity(value.z) ? 0 : value.z;
 593
 266594            return new Vector3(x, y, z);
 595        }
 596
 0597        public static bool CompareFloats( float a, float b, float precision = 0.1f ) { return Mathf.Abs(a - b) < precisi
 598
 599        public static void Deconstruct<T1, T2>(this KeyValuePair<T1, T2> tuple, out T1 key, out T2 value)
 600        {
 148601            key = tuple.Key;
 148602            value = tuple.Value;
 148603        }
 604
 605        /// <summary>
 606        /// Set a layer to the given transform and its child
 607        /// </summary>
 608        /// <param name="transform"></param>
 609        public static void SetLayerRecursively(Transform transform, int layer)
 610        {
 545611            transform.gameObject.layer = layer;
 2150612            foreach (Transform child in transform)
 613            {
 530614                SetLayerRecursively(child, layer);
 615            }
 545616        }
 617
 618        /// <summary>
 619        /// Converts a linear float (between 0 and 1) into an exponential curve fitting for audio volume.
 620        /// </summary>
 621        /// <param name="volume">Linear volume float</param>
 622        /// <returns>Exponential volume curve float</returns>
 0623        public static float ToVolumeCurve(float volume) { return volume * (2f - volume); }
 624
 625        /// <summary>
 626        /// Takes a linear volume value between 0 and 1, converts to exponential curve and maps to a value fitting for a
 627        /// </summary>
 628        /// <param name="volume">Linear volume (0 to 1)</param>
 629        /// <returns>Value for audio mixer group volume</returns>
 0630        public static float ToAudioMixerGroupVolume(float volume) { return (ToVolumeCurve(volume) * 80f) - 80f; }
 631
 632        public static IEnumerator Wait(float delay, Action onFinishCallback)
 633        {
 4634            yield return new WaitForSeconds(delay);
 0635            onFinishCallback.Invoke();
 0636        }
 637
 638        public static string GetHierarchyPath(this Transform transform)
 639        {
 0640            if (transform.parent == null)
 0641                return transform.name;
 0642            return $"{transform.parent.GetHierarchyPath()}/{transform.name}";
 643        }
 644
 645        public static bool TryFindChildRecursively(this Transform transform, string name, out Transform foundChild)
 646        {
 0647            foundChild = transform.Find(name);
 0648            if (foundChild != null)
 0649                return true;
 650
 0651            foreach (Transform child in transform)
 652            {
 0653                if (TryFindChildRecursively(child, name, out foundChild))
 0654                    return true;
 655            }
 0656            return false;
 0657        }
 658
 659        public static bool IsPointerOverUIElement(Vector3 mousePosition)
 660        {
 0661            if (EventSystem.current == null)
 0662                return false;
 663
 0664            var eventData = new PointerEventData(EventSystem.current);
 0665            eventData.position = mousePosition;
 0666            var results = new List<RaycastResult>();
 0667            EventSystem.current.RaycastAll(eventData, results);
 0668            return results.Count > 1;
 669        }
 670
 0671        public static bool IsPointerOverUIElement() { return IsPointerOverUIElement(Input.mousePosition); }
 672    }
 673}

Methods/Properties

EnsureResourcesMaterial(System.String)
CleanMaterials(UnityEngine.Renderer)
ToggleRenderFeature[T](UnityEngine.Rendering.Universal.UniversalRenderPipelineAsset, System.Boolean)
FloatArrayToV2List(Google.Protobuf.Collections.RepeatedField[Single])
FloatArrayToV2List(System.Collections.Generic.IList[Single])
CapGlobalValuesToMax(UnityEngine.Transform)
SetTransformGlobalValues(UnityEngine.Transform, UnityEngine.Vector3, UnityEngine.Quaternion, UnityEngine.Vector3, System.Boolean)
ResetLocalTRS(UnityEngine.Transform)
SetToMaxStretch(UnityEngine.RectTransform)
SetToCentered(UnityEngine.RectTransform)
SetToBottomLeft(UnityEngine.RectTransform)
ForceUpdateLayout(UnityEngine.RectTransform, System.Boolean)
ForceRebuildLayoutImmediate(UnityEngine.RectTransform)
ForceUpdateLayoutRoutine()
InverseTransformChildTraversal[TComponent](System.Action[TComponent], UnityEngine.Transform)
ForwardTransformChildTraversal[TComponent](System.Func[TComponent,Boolean], UnityEngine.Transform)
GetOrCreateComponent[T](UnityEngine.GameObject)
FetchTexture(System.String, System.Boolean, System.Action[Texture2D], System.Action[IWebRequestAsyncOperation])
SafeFromJsonOverwrite(System.String, System.Object)
FromJsonWithNulls[T](System.String)
SafeFromJson[T](System.String)
AttachPlaceholderRendererGameObject(UnityEngine.Transform)
SafeDestroy(UnityEngine.Object)
GridToWorldPosition(System.Single, System.Single)
WorldToGridPosition(UnityEngine.Vector3)
WorldToGridPositionUnclamped(UnityEngine.Vector3)
AproxComparison(UnityEngine.Color, UnityEngine.Color, System.Single)
ParseJsonArray[T](System.String)
Utils()
LockedThisFrame()
IsCursorLocked()
IsCursorLocked(System.Boolean)
LockCursor()
UnlockCursor()
BrowserSetCursorState(System.Boolean)
DestroyAllChild(UnityEngine.Transform)
GetBottomLeftZoneArray(UnityEngine.Vector2Int, UnityEngine.Vector2Int)
GetCenteredZoneArray(UnityEngine.Vector2Int, UnityEngine.Vector2Int)
DrawRectGizmo(UnityEngine.Rect, UnityEngine.Color, System.Single)
ToUpperFirst(System.String)
Sanitize(UnityEngine.Vector3)
CompareFloats(System.Single, System.Single, System.Single)
Deconstruct[T1, T2](System.Collections.Generic.KeyValuePair[T1,T2], , )
SetLayerRecursively(UnityEngine.Transform, System.Int32)
ToVolumeCurve(System.Single)
ToAudioMixerGroupVolume(System.Single)
Wait()
GetHierarchyPath(UnityEngine.Transform)
TryFindChildRecursively(UnityEngine.Transform, System.String, UnityEngine.Transform&)
IsPointerOverUIElement(UnityEngine.Vector3)
IsPointerOverUIElement()