< 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:124
Uncovered lines:168
Coverable lines:292
Total lines:775
Line coverage:42.4% (124 of 292)
Covered branches:0
Total branches:0
Covered methods:34
Total methods:62
Method coverage:54.8% (34 of 62)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
EnsureResourcesMaterial(...)0%440100%
QuitApplication()0%2100%
CleanMaterials(...)0%440100%
ToggleRenderFeature[T](...)0%56700%
FloatArrayToV2List(...)0%6200%
FloatArrayToV2List(...)0%220100%
StringToVector2Int(...)0%4.254075%
CapGlobalValuesToMax(...)0%96.8613020.83%
SetTransformGlobalValues(...)0%6200%
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%2100%
SafeFromJsonOverwrite(...)0%2100%
FromJsonWithNulls[T](...)0%110100%
SafeFromJson[T](...)0%4.434070%
SafeUnimplemented[TComponent, TModel](...)0%2100%
AttachPlaceholderRendererGameObject(...)0%110100%
SafeDestroy(...)0%4.123050%
GridToWorldPosition(...)0%110100%
WorldToGridPosition(...)0%110100%
WorldToGridPositionUnclamped(...)0%110100%
AproxComparison(...)0%20400%
ParseJsonArray[T](...)0%2100%
Utils()0%110100%
LockedThisFrame()0%110100%
LockCursor()0%220100%
UnlockCursor()0%220100%
BrowserSetCursorState(...)0%12300%
DestroyAllChild(...)0%12300%
GetBottomLeftZoneArray(...)0%12300%
GetCenteredZoneArray(...)0%12300%
DrawRectGizmo(...)0%2100%
ToUpperFirst(...)0%6200%
Sanitize(...)0%770100%
CompareFloats(...)0%2100%
Deconstruct[T1, T2](...)0%2100%
SetLayerRecursively(...)0%330100%
ToVolumeCurve(...)0%110100%
ToAudioMixerGroupVolume(...)0%110100%
Wait()0%12300%
GetHierarchyPath(...)0%6200%
TryFindChildRecursively(...)0%30500%
IsPointerOverUIElement(...)0%6200%
IsPointerOverUIElement()0%2100%
UnixTimeStampToLocalTime(...)0%110100%
UnixToDateTimeWithTime(...)0%110100%
ConvertStringToVector(...)0%3.583060%
GetRandomColorInGradient(...)0%110100%
ToUniTaskInstantCancelation(...)0%12300%
RemoveDuplicatesFromList[T](...)0%30500%
RemoveDuplicatesFromArray[T]()0%2100%
CanBeUnEquipped(...)0%330100%

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 Cysharp.Threading.Tasks;
 6using System;
 7using System.Collections;
 8using System.Collections.Generic;
 9using System.Linq;
 10using System.Reflection;
 11using DCL.Configuration;
 12using DG.Tweening;
 13using Google.Protobuf.Collections;
 14using Newtonsoft.Json;
 15using System.Text.RegularExpressions;
 16using System.Threading;
 17using TMPro;
 18using UnityEngine;
 19using UnityEngine.Assertions;
 20using UnityEngine.EventSystems;
 21using UnityEngine.Networking;
 22using UnityEngine.UI;
 23using Object = UnityEngine.Object;
 24using UnityEngine.Rendering.Universal;
 25using static Decentraland.Sdk.Ecs6.ComponentBodyPayload;
 26
 27namespace DCL.Helpers
 28{
 29    public static class Utils
 30    {
 31        public static Dictionary<string, Material> staticMaterials;
 32
 33        public static Material EnsureResourcesMaterial(string path)
 34        {
 56935            if (staticMaterials == null) { staticMaterials = new Dictionary<string, Material>(); }
 36
 56837            if (!staticMaterials.ContainsKey(path))
 38            {
 439                Material material = Resources.Load(path) as Material;
 40
 841                if (material != null) { staticMaterials.Add(path, material); }
 42
 443                return material;
 44            }
 45
 56446            return staticMaterials[path];
 47        }
 48
 49        public static void QuitApplication()
 50        {
 51#if UNITY_EDITOR
 52
 53            // Application.Quit() does not work in the editor so
 54            // UnityEditor.EditorApplication.isPlaying need to be set to false to end the game
 055            UnityEditor.EditorApplication.isPlaying = false;
 56#else
 57            Application.Quit();
 58#endif
 059        }
 60
 61        public static void CleanMaterials(Renderer r)
 62        {
 12163            if (r != null)
 64            {
 48465                foreach (Material m in r.materials)
 66                {
 24267                    if (m != null) { Material.Destroy(m); }
 68                }
 69            }
 12170        }
 71
 72        public static ScriptableRendererFeature ToggleRenderFeature<T>(this UniversalRenderPipelineAsset asset, bool ena
 73        {
 074            var type = asset.GetType();
 075            var propertyInfo = type.GetField("m_RendererDataList", BindingFlags.Instance | BindingFlags.NonPublic);
 76
 077            if (propertyInfo == null) { return null; }
 78
 079            var scriptableRenderData = (ScriptableRendererData[])propertyInfo.GetValue(asset);
 80
 081            if (scriptableRenderData != null && scriptableRenderData.Length > 0)
 82            {
 083                foreach (var renderData in scriptableRenderData)
 84                {
 085                    foreach (var rendererFeature in renderData.rendererFeatures)
 86                    {
 087                        if (rendererFeature is T)
 88                        {
 089                            rendererFeature.SetActive(enable);
 90
 091                            return rendererFeature;
 92                        }
 93                    }
 94                }
 95            }
 96
 097            return null;
 098        }
 99
 100        public static Vector2[] FloatArrayToV2List(RepeatedField<float> uvs)
 101        {
 0102            Vector2[] uvsResult = new Vector2[uvs.Count / 2];
 0103            int uvsResultIndex = 0;
 104
 0105            for (int i = 0; i < uvs.Count;)
 106            {
 0107                Vector2 tmpUv = Vector2.zero;
 0108                tmpUv.x = uvs[i++];
 0109                tmpUv.y = uvs[i++];
 110
 0111                uvsResult[uvsResultIndex++] = tmpUv;
 112            }
 113
 0114            return uvsResult;
 115        }
 116
 117        public static Vector2[] FloatArrayToV2List(IList<float> uvs)
 118        {
 7119            Vector2[] uvsResult = new Vector2[uvs.Count / 2];
 7120            int uvsResultIndex = 0;
 121
 222122            for (int i = 0; i < uvs.Count;) { uvsResult[uvsResultIndex++] = new Vector2(uvs[i++], uvs[i++]); }
 123
 7124            return uvsResult;
 125        }
 126
 127        public static Vector2Int StringToVector2Int(string coords)
 128        {
 12129            string[] coordSplit = coords.Split(',');
 130
 24131            if (coordSplit.Length == 2 && int.TryParse(coordSplit[0], out int x) && int.TryParse(coordSplit[1], out int 
 132
 0133            return Vector2Int.zero;
 134        }
 135
 136        private const int MAX_TRANSFORM_VALUE = 10000;
 137        private const float MIN_TRANSFORM_SCALE_Z_VALUE = 0.00001f;
 138
 139        public static void CapGlobalValuesToMax(this Transform transform)
 140        {
 229141            bool positionOutsideBoundaries = transform.position.sqrMagnitude > MAX_TRANSFORM_VALUE * MAX_TRANSFORM_VALUE
 229142            bool scaleOutsideBoundaries = transform.lossyScale.sqrMagnitude > MAX_TRANSFORM_VALUE * MAX_TRANSFORM_VALUE;
 143
 144            //Extra check to prevent rendering artifacts when bloom is on
 145            //More description: https://github.com/decentraland/unity-renderer/issues/5698
 229146            bool scaleZAxisBelowMinimum = Mathf.Abs(transform.localScale.z) < MIN_TRANSFORM_SCALE_Z_VALUE;
 147
 229148            if (positionOutsideBoundaries || scaleOutsideBoundaries || scaleZAxisBelowMinimum)
 149            {
 0150                Vector3 newPosition = transform.position;
 151
 0152                if (positionOutsideBoundaries)
 153                {
 0154                    if (Mathf.Abs(newPosition.x) > MAX_TRANSFORM_VALUE)
 0155                        newPosition.x = MAX_TRANSFORM_VALUE * Mathf.Sign(newPosition.x);
 156
 0157                    if (Mathf.Abs(newPosition.y) > MAX_TRANSFORM_VALUE)
 0158                        newPosition.y = MAX_TRANSFORM_VALUE * Mathf.Sign(newPosition.y);
 159
 0160                    if (Mathf.Abs(newPosition.z) > MAX_TRANSFORM_VALUE)
 0161                        newPosition.z = MAX_TRANSFORM_VALUE * Mathf.Sign(newPosition.z);
 162                }
 163
 0164                Vector3 newScale = transform.lossyScale;
 165
 0166                if (scaleOutsideBoundaries || scaleZAxisBelowMinimum)
 167                {
 0168                    if (Mathf.Abs(newScale.x) > MAX_TRANSFORM_VALUE)
 0169                        newScale.x = MAX_TRANSFORM_VALUE * Mathf.Sign(newScale.x);
 170
 0171                    if (Mathf.Abs(newScale.y) > MAX_TRANSFORM_VALUE)
 0172                        newScale.y = MAX_TRANSFORM_VALUE * Mathf.Sign(newScale.y);
 173
 0174                    if (Mathf.Abs(newScale.z) > MAX_TRANSFORM_VALUE)
 0175                        newScale.z = MAX_TRANSFORM_VALUE * Mathf.Sign(newScale.z);
 0176                    else if (scaleZAxisBelowMinimum)
 0177                        newScale.z = MIN_TRANSFORM_SCALE_Z_VALUE * Mathf.Sign(newScale.z == 0 ? 1 : newScale.z);
 178                }
 179
 0180                SetTransformGlobalValues(transform, newPosition, transform.rotation, newScale, scaleOutsideBoundaries ||
 181            }
 229182        }
 183
 184        public static void SetTransformGlobalValues(Transform transform, Vector3 newPos, Quaternion newRot, Vector3 newS
 185        {
 0186            transform.position = newPos;
 0187            transform.rotation = newRot;
 188
 0189            if (setScale)
 190            {
 0191                transform.localScale = Vector3.one;
 0192                var m = transform.worldToLocalMatrix;
 193
 0194                m.SetColumn(0, new Vector4(m.GetColumn(0).magnitude, 0f));
 0195                m.SetColumn(1, new Vector4(0f, m.GetColumn(1).magnitude));
 0196                m.SetColumn(2, new Vector4(0f, 0f, m.GetColumn(2).magnitude));
 0197                m.SetColumn(3, new Vector4(0f, 0f, 0f, 1f));
 198
 0199                transform.localScale = m.MultiplyPoint(newScale);
 200            }
 0201        }
 202
 203        public static void ResetLocalTRS(this Transform t)
 204        {
 1870205            t.localPosition = Vector3.zero;
 1870206            t.localRotation = Quaternion.identity;
 1870207            t.localScale = Vector3.one;
 1870208        }
 209
 210        public static void SetToMaxStretch(this RectTransform t)
 211        {
 200212            t.anchorMin = Vector2.zero;
 200213            t.offsetMin = Vector2.zero;
 200214            t.anchorMax = Vector2.one;
 200215            t.offsetMax = Vector2.one;
 200216            t.sizeDelta = Vector2.zero;
 200217            t.anchoredPosition = Vector2.zero;
 200218        }
 219
 220        public static void SetToCentered(this RectTransform t)
 221        {
 0222            t.anchorMin = Vector2.one * 0.5f;
 0223            t.offsetMin = Vector2.one * 0.5f;
 0224            t.anchorMax = Vector2.one * 0.5f;
 0225            t.offsetMax = Vector2.one * 0.5f;
 0226            t.sizeDelta = Vector2.one * 100;
 0227        }
 228
 229        public static void SetToBottomLeft(this RectTransform t)
 230        {
 0231            t.anchorMin = Vector2.zero;
 0232            t.offsetMin = Vector2.zero;
 0233            t.anchorMax = Vector2.zero;
 0234            t.offsetMax = Vector2.zero;
 0235            t.sizeDelta = Vector2.one * 100;
 0236        }
 237
 238        public static void ForceUpdateLayout(this RectTransform rt, bool delayed = true)
 239        {
 246240            if (!rt.gameObject.activeInHierarchy)
 0241                return;
 242
 246243            if (delayed)
 243244                CoroutineStarter.Start(ForceUpdateLayoutRoutine(rt));
 245            else
 246            {
 3247                InverseTransformChildTraversal<RectTransform>(
 22248                    (x) => { ForceRebuildLayoutImmediate(x); },
 249                    rt);
 250            }
 3251        }
 252
 253        /// <summary>
 254        /// Reimplementation of the LayoutRebuilder.ForceRebuildLayoutImmediate() function (Unity UI API) for make it mo
 255        /// </summary>
 256        /// <param name="rectTransformRoot">Root from which to rebuild.</param>
 257        public static void ForceRebuildLayoutImmediate(RectTransform rectTransformRoot)
 258        {
 4842259            if (rectTransformRoot == null)
 3260                return;
 261
 262            // NOTE(Santi): It seems to be very much cheaper to execute the next instructions manually than execute dire
 263            //              'LayoutRebuilder.ForceRebuildLayoutImmediate()', that theorically already contains these ins
 4839264            var layoutElements = rectTransformRoot.GetComponentsInChildren(typeof(ILayoutElement), true).ToList();
 61886265            layoutElements.RemoveAll(e => (e is Behaviour && !((Behaviour)e).isActiveAndEnabled) || e is TextMeshProUGUI
 266
 28712267            foreach (var layoutElem in layoutElements)
 268            {
 9517269                (layoutElem as ILayoutElement).CalculateLayoutInputHorizontal();
 9517270                (layoutElem as ILayoutElement).CalculateLayoutInputVertical();
 271            }
 272
 4839273            var layoutControllers = rectTransformRoot.GetComponentsInChildren(typeof(ILayoutController), true).ToList();
 15633274            layoutControllers.RemoveAll(e => e is Behaviour && !((Behaviour)e).isActiveAndEnabled);
 275
 16998276            foreach (var layoutCtrl in layoutControllers)
 277            {
 3660278                (layoutCtrl as ILayoutController).SetLayoutHorizontal();
 3660279                (layoutCtrl as ILayoutController).SetLayoutVertical();
 280            }
 4839281        }
 282
 283        private static IEnumerator ForceUpdateLayoutRoutine(RectTransform rt)
 284        {
 243285            yield return null;
 286
 243287            InverseTransformChildTraversal<RectTransform>(
 7928288                (x) => { ForceRebuildLayoutImmediate(x); },
 289                rt);
 243290        }
 291
 292        public static void InverseTransformChildTraversal<TComponent>(Action<TComponent> action, Transform startTransfor
 293            where TComponent: Component
 294        {
 7441295            if (startTransform == null)
 168296                return;
 297
 34997298            foreach (Transform t in startTransform) { InverseTransformChildTraversal(action, t); }
 299
 7273300            var component = startTransform.GetComponent<TComponent>();
 301
 12118302            if (component != null) { action.Invoke(component); }
 7273303        }
 304
 305        public static void ForwardTransformChildTraversal<TComponent>(Func<TComponent, bool> action, Transform startTran
 306            where TComponent: Component
 307        {
 0308            Assert.IsTrue(startTransform != null, "startTransform must not be null");
 309
 0310            var component = startTransform.GetComponent<TComponent>();
 311
 0312            if (component != null)
 313            {
 0314                if (!action.Invoke(component))
 0315                    return;
 316            }
 317
 0318            foreach (Transform t in startTransform) { ForwardTransformChildTraversal(action, t); }
 0319        }
 320
 321        public static T GetOrCreateComponent<T>(this GameObject gameObject) where T: Component
 322        {
 194323            T component = gameObject.GetComponent<T>();
 324
 258325            if (!component) { return gameObject.AddComponent<T>(); }
 326
 130327            return component;
 328        }
 329
 330        public static IWebRequestAsyncOperation FetchTexture(string textureURL, bool isReadable, Action<Texture2D> OnSuc
 331        {
 332            void SuccessInternal(IWebRequestAsyncOperation request)
 333            {
 0334                OnSuccess?.Invoke(DownloadHandlerTexture.GetContent(request.webRequest));
 0335            }
 336
 0337            var asyncOp = Environment.i.platform.webRequest.GetTexture(
 338                url: textureURL,
 339                OnSuccess: SuccessInternal,
 340                OnFail: OnFail,
 341                isReadable: isReadable);
 342
 0343            return asyncOp;
 344        }
 345
 346        public static bool SafeFromJsonOverwrite(string json, object objectToOverwrite)
 347        {
 0348            try { JsonUtility.FromJsonOverwrite(json, objectToOverwrite); }
 0349            catch (ArgumentException e)
 350            {
 0351                Debug.LogError("ArgumentException Fail!... Json = " + json + " " + e.ToString());
 0352                return false;
 353            }
 354
 0355            return true;
 0356        }
 357
 358        public static T FromJsonWithNulls<T>(string json)
 359        {
 46360            return JsonConvert.DeserializeObject<T>(json);
 361        }
 362
 363        public static T SafeFromJson<T>(string json)
 364        {
 990365            ProfilingEvents.OnMessageDecodeStart?.Invoke("Misc");
 366
 990367            T returningValue = default(T);
 368
 990369            if (!string.IsNullOrEmpty(json))
 370            {
 1980371                try { returningValue = JsonUtility.FromJson<T>(json); }
 0372                catch (ArgumentException e) { Debug.LogError("ArgumentException Fail!... Json = " + json + " " + e.ToStr
 373            }
 374
 990375            ProfilingEvents.OnMessageDecodeEnds?.Invoke("Misc");
 376
 990377            return returningValue;
 378        }
 379
 380        public static TModel SafeUnimplemented<TComponent, TModel>(PayloadOneofCase expected, PayloadOneofCase actual)
 381        {
 0382            Debug.LogError($"Payload provided for SDK6 {typeof(TComponent).Name} component is not a {expected} but {actu
 0383            return default(TModel);
 384        }
 385
 386        public static GameObject AttachPlaceholderRendererGameObject(Transform targetTransform)
 387        {
 1388            var placeholderRenderer = GameObject.CreatePrimitive(PrimitiveType.Cube).GetComponent<MeshRenderer>();
 389
 1390            placeholderRenderer.material = Resources.Load<Material>("Materials/AssetLoading");
 1391            placeholderRenderer.transform.SetParent(targetTransform);
 1392            placeholderRenderer.transform.localPosition = Vector3.zero;
 1393            placeholderRenderer.name = "PlaceholderRenderer";
 394
 1395            return placeholderRenderer.gameObject;
 396        }
 397
 398        public static void SafeDestroy(Object obj)
 399        {
 19825400            if (obj is Transform)
 0401                return;
 402
 403#if UNITY_EDITOR
 19825404            if (Application.isPlaying)
 19825405                Object.Destroy(obj);
 406            else
 0407                Object.DestroyImmediate(obj, false);
 408#else
 409                UnityEngine.Object.Destroy(obj);
 410#endif
 0411        }
 412
 413        /**
 414         * Transforms a grid position into a world-relative 3d position
 415         */
 416        public static Vector3 GridToWorldPosition(float xGridPosition, float yGridPosition)
 417        {
 1603418            return new Vector3(
 419                x: xGridPosition * ParcelSettings.PARCEL_SIZE,
 420                y: 0f,
 421                z: yGridPosition * ParcelSettings.PARCEL_SIZE
 422            );
 423        }
 424
 425        /**
 426         * Transforms a world position into a grid position
 427         */
 428        public static Vector2Int WorldToGridPosition(Vector3 worldPosition)
 429        {
 6095430            return new Vector2Int(
 431                (int)Mathf.Floor(worldPosition.x / ParcelSettings.PARCEL_SIZE),
 432                (int)Mathf.Floor(worldPosition.z / ParcelSettings.PARCEL_SIZE)
 433            );
 434        }
 435
 436        public static Vector2 WorldToGridPositionUnclamped(Vector3 worldPosition)
 437        {
 296438            return new Vector2(
 439                worldPosition.x / ParcelSettings.PARCEL_SIZE,
 440                worldPosition.z / ParcelSettings.PARCEL_SIZE
 441            );
 442        }
 443
 444        public static bool AproxComparison(this Color color1, Color color2, float tolerance = 0.01f) // tolerance of rou
 445        {
 0446            if (Mathf.Abs(color1.r - color2.r) < tolerance
 447                && Mathf.Abs(color1.g - color2.g) < tolerance
 0448                && Mathf.Abs(color1.b - color2.b) < tolerance) { return true; }
 449
 0450            return false;
 451        }
 452
 453        public static T ParseJsonArray<T>(string jsonArray) where T: IEnumerable =>
 0454            DummyJsonUtilityFromArray<T>.GetFromJsonArray(jsonArray);
 455
 456        [Serializable]
 457        private class DummyJsonUtilityFromArray<T> where T: IEnumerable //UnityEngine.JsonUtility is really fast but can
 458        {
 459            [SerializeField]
 460            private T value;
 461
 462            public static T GetFromJsonArray(string jsonArray)
 463            {
 464                var newJson = $"{{ \"value\": {jsonArray}}}";
 465                return JsonUtility.FromJson<DummyJsonUtilityFromArray<T>>(newJson).value;
 466            }
 467        }
 468
 1469        private static int lockedInFrame = -1;
 470
 471        public static bool LockedThisFrame() =>
 6782472            lockedInFrame == Time.frameCount;
 473
 474        private static bool isCursorLocked;
 475
 476        //NOTE(Brian): Made as an independent flag because the CI doesn't work well with the Cursor.lockState check.
 477        public static bool IsCursorLocked
 478        {
 79184479            get => isCursorLocked;
 480
 481            private set
 482            {
 104483                if (isCursorLocked == value) return;
 78484                isCursorLocked = value;
 78485                OnCursorLockChanged?.Invoke(isCursorLocked);
 1486            }
 487        }
 488
 489        public static event Action<bool> OnCursorLockChanged;
 490
 491        public static void LockCursor()
 492        {
 493#if WEB_PLATFORM
 494            //TODO(Brian): Encapsulate all this mechanism to a new MouseLockController and branch
 495            //             behaviour using strategy pattern instead of this.
 496            if (IsCursorLocked)
 497            {
 498                return;
 499            }
 500#endif
 40501            Cursor.visible = false;
 40502            IsCursorLocked = true;
 40503            Cursor.lockState = CursorLockMode.Locked;
 40504            lockedInFrame = Time.frameCount;
 505
 40506            EventSystem.current?.SetSelectedGameObject(null);
 33507        }
 508
 509        public static void UnlockCursor()
 510        {
 511#if WEB_PLATFORM
 512            //TODO(Brian): Encapsulate all this mechanism to a new MouseLockController and branch
 513            //             behaviour using strategy pattern instead of this.
 514            if (!IsCursorLocked)
 515            {
 516                return;
 517            }
 518#endif
 51519            Cursor.visible = true;
 51520            IsCursorLocked = false;
 51521            Cursor.lockState = CursorLockMode.None;
 522
 51523            EventSystem.current?.SetSelectedGameObject(null);
 38524        }
 525
 526#region BROWSER_ONLY
 527        //TODO(Brian): Encapsulate all this mechanism to a new MouseLockController and branch
 528        //             behaviour using strategy pattern instead of this.
 529        // NOTE: This should come from browser's pointerlockchange callback
 530        public static void BrowserSetCursorState(bool locked)
 531        {
 0532            Cursor.lockState = locked ? CursorLockMode.Locked : CursorLockMode.None;
 533
 0534            IsCursorLocked = locked;
 0535            Cursor.visible = !locked;
 0536        }
 537#endregion
 538
 539        public static void DestroyAllChild(this Transform transform)
 540        {
 0541            foreach (Transform child in transform) { Object.Destroy(child.gameObject); }
 0542        }
 543
 544        public static List<Vector2Int> GetBottomLeftZoneArray(Vector2Int bottomLeftAnchor, Vector2Int size)
 545        {
 0546            List<Vector2Int> coords = new List<Vector2Int>();
 547
 0548            for (int x = bottomLeftAnchor.x; x < bottomLeftAnchor.x + size.x; x++)
 549            {
 0550                for (int y = bottomLeftAnchor.y; y < bottomLeftAnchor.y + size.y; y++) { coords.Add(new Vector2Int(x, y)
 551            }
 552
 0553            return coords;
 554        }
 555
 556        public static List<Vector2Int> GetCenteredZoneArray(Vector2Int center, Vector2Int size)
 557        {
 0558            List<Vector2Int> coords = new List<Vector2Int>();
 559
 0560            for (int x = center.x - size.x; x < center.x + size.x; x++)
 561            {
 0562                for (int y = center.y - size.y; y < center.y + size.y; y++) { coords.Add(new Vector2Int(x, y)); }
 563            }
 564
 0565            return coords;
 566        }
 567
 568        public static void DrawRectGizmo(Rect rect, Color color, float duration)
 569        {
 0570            Vector3 tl2 = new Vector3(rect.xMin, rect.yMax, 0);
 0571            Vector3 bl2 = new Vector3(rect.xMin, rect.yMin, 0);
 0572            Vector3 tr2 = new Vector3(rect.xMax, rect.yMax, 0);
 0573            Vector3 br2 = new Vector3(rect.xMax, rect.yMin, 0);
 574
 0575            Debug.DrawLine(tl2, bl2, color, duration);
 0576            Debug.DrawLine(tl2, tr2, color, duration);
 0577            Debug.DrawLine(bl2, br2, color, duration);
 0578            Debug.DrawLine(tr2, br2, color, duration);
 0579        }
 580
 581        public static string ToUpperFirst(this string value)
 582        {
 0583            if (!string.IsNullOrEmpty(value))
 584            {
 0585                var capital = char.ToUpper(value[0]);
 0586                value = capital + value.Substring(1);
 587            }
 588
 0589            return value;
 590        }
 591
 592        public static Vector3 Sanitize(Vector3 value)
 593        {
 269594            float x = float.IsInfinity(value.x) ? 0 : value.x;
 269595            float y = float.IsInfinity(value.y) ? 0 : value.y;
 269596            float z = float.IsInfinity(value.z) ? 0 : value.z;
 597
 269598            return new Vector3(x, y, z);
 599        }
 600
 601        public static bool CompareFloats(float a, float b, float precision = 0.1f)
 602        {
 0603            return Mathf.Abs(a - b) < precision;
 604        }
 605
 606        public static void Deconstruct<T1, T2>(this KeyValuePair<T1, T2> tuple, out T1 key, out T2 value)
 607        {
 0608            key = tuple.Key;
 0609            value = tuple.Value;
 0610        }
 611
 612        /// <summary>
 613        /// Set a layer to the given transform and its child
 614        /// </summary>
 615        /// <param name="transform"></param>
 616        public static void SetLayerRecursively(Transform transform, int layer)
 617        {
 133618            transform.gameObject.layer = layer;
 619
 656620            foreach (Transform child in transform) { SetLayerRecursively(child, layer); }
 133621        }
 622
 623        /// <summary>
 624        /// Converts a linear float (between 0 and 1) into an exponential curve fitting for audio volume.
 625        /// </summary>
 626        /// <param name="volume">Linear volume float</param>
 627        /// <returns>Exponential volume curve float</returns>
 628        public static float ToVolumeCurve(float volume)
 629        {
 536630            return volume * (2f - volume);
 631        }
 632
 633        /// <summary>
 634        /// Takes a linear volume value between 0 and 1, converts to exponential curve and maps to a value fitting for a
 635        /// </summary>
 636        /// <param name="volume">Linear volume (0 to 1)</param>
 637        /// <returns>Value for audio mixer group volume</returns>
 638        public static float ToAudioMixerGroupVolume(float volume)
 639        {
 8640            return (ToVolumeCurve(volume) * 80f) - 80f;
 641        }
 642
 643        public static IEnumerator Wait(float delay, Action onFinishCallback)
 644        {
 0645            yield return new WaitForSeconds(delay);
 0646            onFinishCallback.Invoke();
 0647        }
 648
 649        public static string GetHierarchyPath(this Transform transform)
 650        {
 0651            if (transform.parent == null)
 0652                return transform.name;
 653
 0654            return $"{transform.parent.GetHierarchyPath()}/{transform.name}";
 655        }
 656
 657        public static bool TryFindChildRecursively(this Transform transform, string name, out Transform foundChild)
 658        {
 0659            foundChild = transform.Find(name);
 660
 0661            if (foundChild != null)
 0662                return true;
 663
 0664            foreach (Transform child in transform)
 665            {
 0666                if (TryFindChildRecursively(child, name, out foundChild))
 0667                    return true;
 668            }
 669
 0670            return false;
 0671        }
 672
 673        public static bool IsPointerOverUIElement(Vector3 mousePosition)
 674        {
 0675            if (EventSystem.current == null)
 0676                return false;
 677
 0678            var eventData = new PointerEventData(EventSystem.current);
 0679            eventData.position = mousePosition;
 0680            var results = new List<RaycastResult>();
 0681            EventSystem.current.RaycastAll(eventData, results);
 0682            return results.Count > 1;
 683        }
 684
 685        public static bool IsPointerOverUIElement()
 686        {
 0687            return IsPointerOverUIElement(Input.mousePosition);
 688        }
 689
 690        public static string UnixTimeStampToLocalTime(ulong unixTimeStampMilliseconds)
 691        {
 5692            DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
 5693            dtDateTime = dtDateTime.AddMilliseconds(unixTimeStampMilliseconds).ToLocalTime();
 5694            return $"{dtDateTime.Hour}:{dtDateTime.Minute:D2}";
 695        }
 696
 697        public static DateTime UnixToDateTimeWithTime(ulong unixTimeStampMilliseconds)
 698        {
 30699            DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
 30700            dtDateTime = dtDateTime.AddMilliseconds(unixTimeStampMilliseconds).ToLocalTime();
 30701            return dtDateTime;
 702        }
 703
 1704        private static readonly Regex COORDINATES_REGEX = new Regex(@"^(-?\d+),(-?\d+)$");
 705
 706        public static Vector2Int ConvertStringToVector(string input)
 707        {
 60708            Match match = COORDINATES_REGEX.Match(input.Replace(" ",""));
 709
 60710            if (!int.TryParse(match.Groups[1].Value, out int x) || !int.TryParse(match.Groups[2].Value, out int y))
 711            {
 0712                Debug.LogError("Coordinates parsing error for coords " + input);
 0713                return new Vector2Int(0, 0);
 714            }
 715
 60716            return new Vector2Int(x, y);
 717        }
 718
 719        public static Color GetRandomColorInGradient(Color minColor, Color maxColor)
 720        {
 2721            Color.RGBToHSV(minColor, out float startH, out float startS, out float startV);
 2722            Color.RGBToHSV(maxColor, out float endH, out float _, out float _);
 2723            return Color.HSVToRGB(UnityEngine.Random.Range(startH, endH), startS, startV);
 724        }
 725
 726        public static UniTask ToUniTaskInstantCancelation(this Tween tween, bool completeWhenCancel = false, Cancellatio
 727        {
 0728            cancellationToken.RegisterWithoutCaptureExecutionContext(() =>
 729            {
 730                // We cannot use the built in TweenCancelBehavior because we are manually killing the tween
 0731                if (completeWhenCancel)
 0732                    tween.Complete(false);
 733
 0734                tween.Kill();
 0735            });
 736
 0737            return tween.ToUniTask(tweenCancelBehaviour: completeWhenCancel ? TweenCancelBehaviour.Complete : TweenCance
 738        }
 739
 740        public static List<T> RemoveDuplicatesFromList<T>(List<T> items)
 741        {
 0742            List<T> result = new List<T>();
 0743            for (int i = 0; i < items.Count; i++)
 744            {
 0745                bool duplicate = false;
 0746                for (int z = 0; z < i; z++)
 747                {
 0748                    if (Equals(items[z], items[i]))
 749                    {
 0750                        duplicate = true;
 0751                        break;
 752                    }
 753                }
 0754                if (!duplicate)
 755                {
 0756                    result.Add(items[i]);
 757                }
 758            }
 0759            return result;
 760        }
 761
 762        public static T[] RemoveDuplicatesFromArray<T>(T[] s)
 763        {
 0764            HashSet<T> set = new HashSet<T>(s);
 0765            T[] result = new T[set.Count];
 0766            set.CopyTo(result);
 0767            return result;
 768        }
 769
 770        public static bool CanBeUnEquipped(this WearableItem wearable) =>
 22771            wearable.data.category != WearableLiterals.Categories.BODY_SHAPE &&
 772            wearable.data.category != WearableLiterals.Categories.EYES &&
 773            wearable.data.category != WearableLiterals.Categories.MOUTH;
 774    }
 775}

Methods/Properties

EnsureResourcesMaterial(System.String)
QuitApplication()
CleanMaterials(UnityEngine.Renderer)
ToggleRenderFeature[T](UnityEngine.Rendering.Universal.UniversalRenderPipelineAsset, System.Boolean)
FloatArrayToV2List(Google.Protobuf.Collections.RepeatedField[Single])
FloatArrayToV2List(System.Collections.Generic.IList[Single])
StringToVector2Int(System.String)
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)
SafeUnimplemented[TComponent, TModel](Decentraland.Sdk.Ecs6.ComponentBodyPayload/PayloadOneofCase, Decentraland.Sdk.Ecs6.ComponentBodyPayload/PayloadOneofCase)
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()
UnixTimeStampToLocalTime(System.UInt64)
UnixToDateTimeWithTime(System.UInt64)
ConvertStringToVector(System.String)
GetRandomColorInGradient(UnityEngine.Color, UnityEngine.Color)
ToUniTaskInstantCancelation(DG.Tweening.Tween, System.Boolean, System.Threading.CancellationToken)
RemoveDuplicatesFromList[T](System.Collections.Generic.List[T])
RemoveDuplicatesFromArray[T]()
CanBeUnEquipped(WearableItem)