< Summary

Class:DCL.Helpers.UtilsDummyJsonUtilityFromArray[T]
Assembly:Utils
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Helpers/Utils/Utils.cs
Covered lines:2
Uncovered lines:0
Coverable lines:2
Total lines:583
Line coverage:100% (2 of 2)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
GetFromJsonArray(...)0%110100%

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 DCL.Configuration;
 10using Google.Protobuf.Collections;
 11using Newtonsoft.Json;
 12using TMPro;
 13using UnityEngine;
 14using UnityEngine.Assertions;
 15using UnityEngine.EventSystems;
 16using UnityEngine.Networking;
 17using UnityEngine.UI;
 18using Object = UnityEngine.Object;
 19
 20namespace DCL.Helpers
 21{
 22    public static class Utils
 23    {
 24        public static Dictionary<string, Material> staticMaterials;
 25
 26        public static Material EnsureResourcesMaterial(string path)
 27        {
 28            if (staticMaterials == null)
 29            {
 30                staticMaterials = new Dictionary<string, Material>();
 31            }
 32
 33            if (!staticMaterials.ContainsKey(path))
 34            {
 35                Material material = Resources.Load(path) as Material;
 36
 37                if (material != null)
 38                {
 39                    staticMaterials.Add(path, material);
 40                }
 41
 42                return material;
 43            }
 44
 45            return staticMaterials[path];
 46        }
 47
 48        public static void CleanMaterials(Renderer r)
 49        {
 50            if (r != null)
 51            {
 52                foreach (Material m in r.materials)
 53                {
 54                    if (m != null)
 55                    {
 56                        Material.Destroy(m);
 57                    }
 58                }
 59            }
 60        }
 61
 62        public static Vector2[] FloatArrayToV2List(RepeatedField<float> uvs)
 63        {
 64            Vector2[] uvsResult = new Vector2[uvs.Count / 2];
 65            int uvsResultIndex = 0;
 66
 67            for (int i = 0; i < uvs.Count;)
 68            {
 69                Vector2 tmpUv = Vector2.zero;
 70                tmpUv.x = uvs[i++];
 71                tmpUv.y = uvs[i++];
 72
 73                uvsResult[uvsResultIndex++] = tmpUv;
 74            }
 75
 76            return uvsResult;
 77        }
 78
 79        public static Vector2[] FloatArrayToV2List(float[] uvs)
 80        {
 81            Vector2[] uvsResult = new Vector2[uvs.Length / 2];
 82            int uvsResultIndex = 0;
 83
 84            for (int i = 0; i < uvs.Length;)
 85            {
 86                uvsResult[uvsResultIndex++] = new Vector2(uvs[i++],uvs[i++]);
 87            }
 88
 89            return uvsResult;
 90        }
 91
 92        public static void ResetLocalTRS(this Transform t)
 93        {
 94            t.localPosition = Vector3.zero;
 95            t.localRotation = Quaternion.identity;
 96            t.localScale = Vector3.one;
 97        }
 98
 99        public static void SetToMaxStretch(this RectTransform t)
 100        {
 101            t.anchorMin = Vector2.zero;
 102            t.offsetMin = Vector2.zero;
 103            t.anchorMax = Vector2.one;
 104            t.offsetMax = Vector2.one;
 105            t.sizeDelta = Vector2.zero;
 106            t.anchoredPosition = Vector2.zero;
 107        }
 108
 109        public static void SetToCentered(this RectTransform t)
 110        {
 111            t.anchorMin = Vector2.one * 0.5f;
 112            t.offsetMin = Vector2.one * 0.5f;
 113            t.anchorMax = Vector2.one * 0.5f;
 114            t.offsetMax = Vector2.one * 0.5f;
 115            t.sizeDelta = Vector2.one * 100;
 116        }
 117
 118        public static void SetToBottomLeft(this RectTransform t)
 119        {
 120            t.anchorMin = Vector2.zero;
 121            t.offsetMin = Vector2.zero;
 122            t.anchorMax = Vector2.zero;
 123            t.offsetMax = Vector2.zero;
 124            t.sizeDelta = Vector2.one * 100;
 125        }
 126
 127        public static void ForceUpdateLayout(this RectTransform rt, bool delayed = true)
 128        {
 129            if (!rt.gameObject.activeInHierarchy)
 130                return;
 131
 132            if (delayed)
 133                CoroutineStarter.Start(ForceUpdateLayoutRoutine(rt));
 134            else
 135            {
 136                InverseTransformChildTraversal<RectTransform>(
 137                    (x) => { ForceRebuildLayoutImmediate(x); },
 138                    rt);
 139            }
 140        }
 141
 142        /// <summary>
 143        /// Reimplementation of the LayoutRebuilder.ForceRebuildLayoutImmediate() function (Unity UI API) for make it mo
 144        /// </summary>
 145        /// <param name="rectTransformRoot">Root from which to rebuild.</param>
 146        public static void ForceRebuildLayoutImmediate(RectTransform rectTransformRoot)
 147        {
 148            if (rectTransformRoot == null)
 149                return;
 150
 151            // NOTE(Santi): It seems to be very much cheaper to execute the next instructions manually than execute dire
 152            //              'LayoutRebuilder.ForceRebuildLayoutImmediate()', that theorically already contains these ins
 153            var layoutElements = rectTransformRoot.GetComponentsInChildren(typeof(ILayoutElement), true).ToList();
 154            layoutElements.RemoveAll(e => (e is Behaviour && !((Behaviour) e).isActiveAndEnabled) || e is TextMeshProUGU
 155            foreach (var layoutElem in layoutElements)
 156            {
 157                (layoutElem as ILayoutElement).CalculateLayoutInputHorizontal();
 158                (layoutElem as ILayoutElement).CalculateLayoutInputVertical();
 159            }
 160
 161            var layoutControllers = rectTransformRoot.GetComponentsInChildren(typeof(ILayoutController), true).ToList();
 162            layoutControllers.RemoveAll(e => e is Behaviour && !((Behaviour) e).isActiveAndEnabled);
 163            foreach (var layoutCtrl in layoutControllers)
 164            {
 165                (layoutCtrl as ILayoutController).SetLayoutHorizontal();
 166                (layoutCtrl as ILayoutController).SetLayoutVertical();
 167            }
 168        }
 169
 170        private static IEnumerator ForceUpdateLayoutRoutine(RectTransform rt)
 171        {
 172            yield return null;
 173
 174            InverseTransformChildTraversal<RectTransform>(
 175                (x) => { ForceRebuildLayoutImmediate(x); },
 176                rt);
 177        }
 178
 179        public static void InverseTransformChildTraversal<TComponent>(Action<TComponent> action, Transform startTransfor
 180            where TComponent : Component
 181        {
 182            if (startTransform == null)
 183                return;
 184
 185            foreach (Transform t in startTransform)
 186            {
 187                InverseTransformChildTraversal(action, t);
 188            }
 189
 190            var component = startTransform.GetComponent<TComponent>();
 191
 192            if (component != null)
 193            {
 194                action.Invoke(component);
 195            }
 196        }
 197
 198        public static void ForwardTransformChildTraversal<TComponent>(Func<TComponent, bool> action, Transform startTran
 199            where TComponent : Component
 200        {
 201            Assert.IsTrue(startTransform != null, "startTransform must not be null");
 202
 203            var component = startTransform.GetComponent<TComponent>();
 204
 205            if (component != null)
 206            {
 207                if (!action.Invoke(component))
 208                    return;
 209            }
 210
 211            foreach (Transform t in startTransform)
 212            {
 213                ForwardTransformChildTraversal(action, t);
 214            }
 215        }
 216
 217        public static T GetOrCreateComponent<T>(this GameObject gameObject) where T : Component
 218        {
 219            T component = gameObject.GetComponent<T>();
 220
 221            if (!component)
 222            {
 223                return gameObject.AddComponent<T>();
 224            }
 225
 226            return component;
 227        }
 228
 229        public static WebRequestAsyncOperation FetchTexture(string textureURL, bool isReadable, Action<Texture2D> OnSucc
 230        {
 231            //NOTE(Brian): This closure is called when the download is a success.
 232            void SuccessInternal(IWebRequestAsyncOperation request) { OnSuccess?.Invoke(DownloadHandlerTexture.GetConten
 233
 234            var asyncOp = Environment.i.platform.webRequest.GetTexture(
 235                url: textureURL,
 236                OnSuccess: SuccessInternal,
 237                OnFail: OnFail,
 238                isReadable: isReadable);
 239
 240            return asyncOp;
 241        }
 242
 243        public static bool SafeFromJsonOverwrite(string json, object objectToOverwrite)
 244        {
 245            try
 246            {
 247                JsonUtility.FromJsonOverwrite(json, objectToOverwrite);
 248            }
 249            catch (ArgumentException e)
 250            {
 251                Debug.LogError("ArgumentException Fail!... Json = " + json + " " + e.ToString());
 252                return false;
 253            }
 254
 255            return true;
 256        }
 257
 258        public static T FromJsonWithNulls<T>(string json) { return JsonConvert.DeserializeObject<T>(json); }
 259
 260        public static T SafeFromJson<T>(string json)
 261        {
 262            ProfilingEvents.OnMessageDecodeStart?.Invoke("Misc");
 263
 264            T returningValue = default(T);
 265
 266            if (!string.IsNullOrEmpty(json))
 267            {
 268                try
 269                {
 270                    returningValue = JsonUtility.FromJson<T>(json);
 271                }
 272                catch (ArgumentException e)
 273                {
 274                    Debug.LogError("ArgumentException Fail!... Json = " + json + " " + e.ToString());
 275                }
 276            }
 277
 278            ProfilingEvents.OnMessageDecodeEnds?.Invoke("Misc");
 279
 280            return returningValue;
 281        }
 282
 283        public static GameObject AttachPlaceholderRendererGameObject(Transform targetTransform)
 284        {
 285            var placeholderRenderer = GameObject.CreatePrimitive(PrimitiveType.Cube).GetComponent<MeshRenderer>();
 286
 287            placeholderRenderer.material = Resources.Load<Material>("Materials/AssetLoading");
 288            placeholderRenderer.transform.SetParent(targetTransform);
 289            placeholderRenderer.transform.localPosition = Vector3.zero;
 290            placeholderRenderer.name = "PlaceholderRenderer";
 291
 292            return placeholderRenderer.gameObject;
 293        }
 294
 295        public static void SafeDestroy(Object obj)
 296        {
 297            if (obj is Transform)
 298                return;
 299
 300#if UNITY_EDITOR
 301            if (Application.isPlaying)
 302                Object.Destroy(obj);
 303            else
 304                Object.DestroyImmediate(obj, false);
 305#else
 306                UnityEngine.Object.Destroy(obj);
 307#endif
 308        }
 309
 310        /**
 311         * Transforms a grid position into a world-relative 3d position
 312         */
 313        public static Vector3 GridToWorldPosition(float xGridPosition, float yGridPosition)
 314        {
 315            return new Vector3(
 316                x: xGridPosition * ParcelSettings.PARCEL_SIZE,
 317                y: 0f,
 318                z: yGridPosition * ParcelSettings.PARCEL_SIZE
 319            );
 320        }
 321
 322        /**
 323         * Transforms a world position into a grid position
 324         */
 325        public static Vector2Int WorldToGridPosition(Vector3 worldPosition)
 326        {
 327            return new Vector2Int(
 328                (int) Mathf.Floor(worldPosition.x / ParcelSettings.PARCEL_SIZE),
 329                (int) Mathf.Floor(worldPosition.z / ParcelSettings.PARCEL_SIZE)
 330            );
 331        }
 332
 333        public static Vector2 WorldToGridPositionUnclamped(Vector3 worldPosition)
 334        {
 335            return new Vector2(
 336                worldPosition.x / ParcelSettings.PARCEL_SIZE,
 337                worldPosition.z / ParcelSettings.PARCEL_SIZE
 338            );
 339        }
 340
 341        public static bool AproxComparison(this Color color1, Color color2, float tolerance = 0.01f) // tolerance of rou
 342        {
 343            if (Mathf.Abs(color1.r - color2.r) < tolerance
 344                && Mathf.Abs(color1.g - color2.g) < tolerance
 345                && Mathf.Abs(color1.b - color2.b) < tolerance)
 346            {
 347                return true;
 348            }
 349
 350            return false;
 351        }
 352
 353        public static T ParseJsonArray<T>(string jsonArray) where T : IEnumerable => DummyJsonUtilityFromArray<T>.GetFro
 354
 355        [Serializable]
 356        private class DummyJsonUtilityFromArray<T> where T : IEnumerable //UnityEngine.JsonUtility is really fast but ca
 357        {
 358            [SerializeField]
 359            private T value;
 360
 361            public static T GetFromJsonArray(string jsonArray)
 362            {
 5363                string newJson = $"{{ \"value\": {jsonArray}}}";
 5364                return JsonUtility.FromJson<DummyJsonUtilityFromArray<T>>(newJson).value;
 365            }
 366        }
 367
 368        private static int lockedInFrame = -1;
 369        public static bool LockedThisFrame() => lockedInFrame == Time.frameCount;
 370
 371        private static bool isCursorLocked;
 372        //NOTE(Brian): Made as an independent flag because the CI doesn't work well with the Cursor.lockState check.
 373        public static bool IsCursorLocked
 374        {
 375            get => isCursorLocked;
 376            private set
 377            {
 378                if (isCursorLocked == value) return;
 379                isCursorLocked = value;
 380                OnCursorLockChanged?.Invoke(isCursorLocked);
 381            }
 382        }
 383
 384        public static event Action<bool> OnCursorLockChanged;
 385
 386        public static void LockCursor()
 387        {
 388#if WEB_PLATFORM
 389            //TODO(Brian): Encapsulate all this mechanism to a new MouseLockController and branch
 390            //             behaviour using strategy pattern instead of this.
 391            if (IsCursorLocked)
 392            {
 393                return;
 394            }
 395#endif
 396            Cursor.visible = false;
 397            IsCursorLocked = true;
 398            Cursor.lockState = CursorLockMode.Locked;
 399            lockedInFrame = Time.frameCount;
 400
 401            EventSystem.current?.SetSelectedGameObject(null);
 402        }
 403
 404        public static void UnlockCursor()
 405        {
 406#if WEB_PLATFORM
 407            //TODO(Brian): Encapsulate all this mechanism to a new MouseLockController and branch
 408            //             behaviour using strategy pattern instead of this.
 409            if (!IsCursorLocked)
 410            {
 411                return;
 412            }
 413#endif
 414            Cursor.visible = true;
 415            IsCursorLocked = false;
 416            Cursor.lockState = CursorLockMode.None;
 417
 418            EventSystem.current?.SetSelectedGameObject(null);
 419        }
 420
 421        #region BROWSER_ONLY
 422
 423        //TODO(Brian): Encapsulate all this mechanism to a new MouseLockController and branch
 424        //             behaviour using strategy pattern instead of this.
 425        // NOTE: This should come from browser's pointerlockchange callback
 426        public static void BrowserSetCursorState(bool locked)
 427        {
 428            Cursor.lockState = locked ? CursorLockMode.Locked : CursorLockMode.None;
 429
 430            IsCursorLocked = locked;
 431            Cursor.visible = !locked;
 432        }
 433
 434        #endregion
 435
 436        public static void DestroyAllChild(this Transform transform)
 437        {
 438            foreach (Transform child in transform)
 439            {
 440                Object.Destroy(child.gameObject);
 441            }
 442        }
 443
 444        public static List<Vector2Int> GetBottomLeftZoneArray(Vector2Int bottomLeftAnchor, Vector2Int size)
 445        {
 446            List<Vector2Int> coords = new List<Vector2Int>();
 447
 448            for (int x = bottomLeftAnchor.x; x < bottomLeftAnchor.x + size.x; x++)
 449            {
 450                for (int y = bottomLeftAnchor.y; y < bottomLeftAnchor.y + size.y; y++)
 451                {
 452                    coords.Add(new Vector2Int(x, y));
 453                }
 454            }
 455
 456            return coords;
 457        }
 458
 459        public static List<Vector2Int> GetCenteredZoneArray(Vector2Int center, Vector2Int size)
 460        {
 461            List<Vector2Int> coords = new List<Vector2Int>();
 462
 463            for (int x = center.x - size.x; x < center.x + size.x; x++)
 464            {
 465                for (int y = center.y - size.y; y < center.y + size.y; y++)
 466                {
 467                    coords.Add(new Vector2Int(x, y));
 468                }
 469            }
 470
 471            return coords;
 472        }
 473
 474        public static void DrawRectGizmo(Rect rect, Color color, float duration)
 475        {
 476            Vector3 tl2 = new Vector3(rect.xMin, rect.yMax, 0);
 477            Vector3 bl2 = new Vector3(rect.xMin, rect.yMin, 0);
 478            Vector3 tr2 = new Vector3(rect.xMax, rect.yMax, 0);
 479            Vector3 br2 = new Vector3(rect.xMax, rect.yMin, 0);
 480
 481            Debug.DrawLine(tl2, bl2, color, duration);
 482            Debug.DrawLine(tl2, tr2, color, duration);
 483            Debug.DrawLine(bl2, br2, color, duration);
 484            Debug.DrawLine(tr2, br2, color, duration);
 485        }
 486
 487        public static string ToUpperFirst(this string value)
 488        {
 489            if (!string.IsNullOrEmpty(value))
 490            {
 491                var capital = char.ToUpper(value[0]);
 492                value = capital + value.Substring(1);
 493            }
 494
 495            return value;
 496        }
 497
 498        public static Vector3 Sanitize(Vector3 value)
 499        {
 500            float x = float.IsInfinity(value.x) ? 0 : value.x;
 501            float y = float.IsInfinity(value.y) ? 0 : value.y;
 502            float z = float.IsInfinity(value.z) ? 0 : value.z;
 503
 504            return new Vector3(x, y, z);
 505        }
 506
 507        public static bool CompareFloats( float a, float b, float precision = 0.1f ) { return Mathf.Abs(a - b) < precisi
 508
 509        public static void Deconstruct<T1, T2>(this KeyValuePair<T1, T2> tuple, out T1 key, out T2 value)
 510        {
 511            key = tuple.Key;
 512            value = tuple.Value;
 513        }
 514
 515        /// <summary>
 516        /// Set a layer to the given transform and its child
 517        /// </summary>
 518        /// <param name="transform"></param>
 519        public static void SetLayerRecursively(Transform transform, int layer)
 520        {
 521            transform.gameObject.layer = layer;
 522            foreach (Transform child in transform)
 523            {
 524                SetLayerRecursively(child, layer);
 525            }
 526        }
 527
 528        /// <summary>
 529        /// Converts a linear float (between 0 and 1) into an exponential curve fitting for audio volume.
 530        /// </summary>
 531        /// <param name="volume">Linear volume float</param>
 532        /// <returns>Exponential volume curve float</returns>
 533        public static float ToVolumeCurve(float volume) { return volume * (2f - volume); }
 534
 535        /// <summary>
 536        /// Takes a linear volume value between 0 and 1, converts to exponential curve and maps to a value fitting for a
 537        /// </summary>
 538        /// <param name="volume">Linear volume (0 to 1)</param>
 539        /// <returns>Value for audio mixer group volume</returns>
 540        public static float ToAudioMixerGroupVolume(float volume) { return (ToVolumeCurve(volume) * 80f) - 80f; }
 541
 542        public static IEnumerator Wait(float delay, Action onFinishCallback)
 543        {
 544            yield return new WaitForSeconds(delay);
 545            onFinishCallback.Invoke();
 546        }
 547
 548        public static string GetHierarchyPath(this Transform transform)
 549        {
 550            if (transform.parent == null)
 551                return transform.name;
 552            return $"{transform.parent.GetHierarchyPath()}/{transform.name}";
 553        }
 554
 555        public static bool TryFindChildRecursively(this Transform transform, string name, out Transform foundChild)
 556        {
 557            foundChild = transform.Find(name);
 558            if (foundChild != null)
 559                return true;
 560
 561            foreach (Transform child in transform)
 562            {
 563                if (TryFindChildRecursively(child, name, out foundChild))
 564                    return true;
 565            }
 566            return false;
 567        }
 568
 569        public static bool IsPointerOverUIElement(Vector3 mousePosition)
 570        {
 571            if (EventSystem.current == null)
 572                return false;
 573
 574            var eventData = new PointerEventData(EventSystem.current);
 575            eventData.position = mousePosition;
 576            var results = new List<RaycastResult>();
 577            EventSystem.current.RaycastAll(eventData, results);
 578            return results.Count > 1;
 579        }
 580
 581        public static bool IsPointerOverUIElement() { return IsPointerOverUIElement(Input.mousePosition); }
 582    }
 583}

Methods/Properties

GetFromJsonArray(System.String)