< 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:137
Uncovered lines:135
Coverable lines:272
Total lines:698
Line coverage:50.3% (137 of 272)
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%
StringToVector2Int(...)0%4.254075%
CapGlobalValuesToMax(...)0%63.0510019.05%
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%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%110100%
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%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%

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        {
 58130            if (staticMaterials == null)
 31            {
 132                staticMaterials = new Dictionary<string, Material>();
 33            }
 34
 58135            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
 57747            return staticMaterials[path];
 48        }
 49
 50        public static void CleanMaterials(Renderer r)
 51        {
 12252            if (r != null)
 53            {
 48854                foreach (Material m in r.materials)
 55                {
 12256                    if (m != null)
 57                    {
 12258                        Material.Destroy(m);
 59                    }
 60                }
 61            }
 12262        }
 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        public static Vector2Int StringToVector2Int(string coords)
 126        {
 6127            string[] coordSplit = coords.Split(',');
 6128            if (coordSplit.Length == 2 && int.TryParse(coordSplit[0], out int x) && int.TryParse(coordSplit[1], out int 
 129            {
 6130                return new Vector2Int(x, y);
 131            }
 132
 0133            return Vector2Int.zero;
 134        }
 135
 136        private const int MAX_TRANSFORM_VALUE = 10000;
 137        public static void CapGlobalValuesToMax(this Transform transform)
 138        {
 242139            bool positionOutsideBoundaries = transform.position.sqrMagnitude > MAX_TRANSFORM_VALUE * MAX_TRANSFORM_VALUE
 242140            bool scaleOutsideBoundaries = transform.lossyScale.sqrMagnitude > MAX_TRANSFORM_VALUE * MAX_TRANSFORM_VALUE;
 141
 242142            if (positionOutsideBoundaries || scaleOutsideBoundaries)
 143            {
 0144                Vector3 newPosition = transform.position;
 0145                if (positionOutsideBoundaries)
 146                {
 0147                    if (Mathf.Abs(newPosition.x) > MAX_TRANSFORM_VALUE)
 0148                        newPosition.x = MAX_TRANSFORM_VALUE * Mathf.Sign(newPosition.x);
 149
 0150                    if (Mathf.Abs(newPosition.y) > MAX_TRANSFORM_VALUE)
 0151                        newPosition.y = MAX_TRANSFORM_VALUE * Mathf.Sign(newPosition.y);
 152
 0153                    if (Mathf.Abs(newPosition.z) > MAX_TRANSFORM_VALUE)
 0154                        newPosition.z = MAX_TRANSFORM_VALUE * Mathf.Sign(newPosition.z);
 155                }
 156
 0157                Vector3 newScale = transform.lossyScale;
 0158                if (scaleOutsideBoundaries)
 159                {
 0160                    if (Mathf.Abs(newScale.x) > MAX_TRANSFORM_VALUE)
 0161                        newScale.x = MAX_TRANSFORM_VALUE * Mathf.Sign(newScale.x);
 162
 0163                    if (Mathf.Abs(newScale.y) > MAX_TRANSFORM_VALUE)
 0164                        newScale.y = MAX_TRANSFORM_VALUE * Mathf.Sign(newScale.y);
 165
 0166                    if (Mathf.Abs(newScale.z) > MAX_TRANSFORM_VALUE)
 0167                        newScale.z = MAX_TRANSFORM_VALUE * Mathf.Sign(newScale.z);
 168                }
 169
 0170                SetTransformGlobalValues(transform, newPosition, transform.rotation, newScale, scaleOutsideBoundaries);
 171            }
 242172        }
 173
 174        public static void SetTransformGlobalValues(Transform transform, Vector3 newPos, Quaternion newRot, Vector3 newS
 175        {
 0176            transform.position = newPos;
 0177            transform.rotation = newRot;
 178
 0179            if (setScale)
 180            {
 0181                transform.localScale = Vector3.one;
 0182                var m = transform.worldToLocalMatrix;
 183
 0184                m.SetColumn(0, new Vector4(m.GetColumn(0).magnitude, 0f));
 0185                m.SetColumn(1, new Vector4(0f, m.GetColumn(1).magnitude));
 0186                m.SetColumn(2, new Vector4(0f, 0f, m.GetColumn(2).magnitude));
 0187                m.SetColumn(3, new Vector4(0f, 0f, 0f, 1f));
 188
 0189                transform.localScale = m.MultiplyPoint(newScale);
 190            }
 0191        }
 192
 193        public static void ResetLocalTRS(this Transform t)
 194        {
 2496195            t.localPosition = Vector3.zero;
 2496196            t.localRotation = Quaternion.identity;
 2496197            t.localScale = Vector3.one;
 2496198        }
 199
 200        public static void SetToMaxStretch(this RectTransform t)
 201        {
 198202            t.anchorMin = Vector2.zero;
 198203            t.offsetMin = Vector2.zero;
 198204            t.anchorMax = Vector2.one;
 198205            t.offsetMax = Vector2.one;
 198206            t.sizeDelta = Vector2.zero;
 198207            t.anchoredPosition = Vector2.zero;
 198208        }
 209
 210        public static void SetToCentered(this RectTransform t)
 211        {
 0212            t.anchorMin = Vector2.one * 0.5f;
 0213            t.offsetMin = Vector2.one * 0.5f;
 0214            t.anchorMax = Vector2.one * 0.5f;
 0215            t.offsetMax = Vector2.one * 0.5f;
 0216            t.sizeDelta = Vector2.one * 100;
 0217        }
 218
 219        public static void SetToBottomLeft(this RectTransform t)
 220        {
 0221            t.anchorMin = Vector2.zero;
 0222            t.offsetMin = Vector2.zero;
 0223            t.anchorMax = Vector2.zero;
 0224            t.offsetMax = Vector2.zero;
 0225            t.sizeDelta = Vector2.one * 100;
 0226        }
 227
 228        public static void ForceUpdateLayout(this RectTransform rt, bool delayed = true)
 229        {
 58230            if (!rt.gameObject.activeInHierarchy)
 0231                return;
 232
 58233            if (delayed)
 54234                CoroutineStarter.Start(ForceUpdateLayoutRoutine(rt));
 235            else
 236            {
 4237                InverseTransformChildTraversal<RectTransform>(
 426238                    (x) => { ForceRebuildLayoutImmediate(x); },
 239                    rt);
 240            }
 4241        }
 242
 243        /// <summary>
 244        /// Reimplementation of the LayoutRebuilder.ForceRebuildLayoutImmediate() function (Unity UI API) for make it mo
 245        /// </summary>
 246        /// <param name="rectTransformRoot">Root from which to rebuild.</param>
 247        public static void ForceRebuildLayoutImmediate(RectTransform rectTransformRoot)
 248        {
 16457249            if (rectTransformRoot == null)
 3250                return;
 251
 252            // NOTE(Santi): It seems to be very much cheaper to execute the next instructions manually than execute dire
 253            //              'LayoutRebuilder.ForceRebuildLayoutImmediate()', that theorically already contains these ins
 16454254            var layoutElements = rectTransformRoot.GetComponentsInChildren(typeof(ILayoutElement), true).ToList();
 309351255            layoutElements.RemoveAll(e => (e is Behaviour && !((Behaviour) e).isActiveAndEnabled) || e is TextMeshProUGU
 51760256            foreach (var layoutElem in layoutElements)
 257            {
 9426258                (layoutElem as ILayoutElement).CalculateLayoutInputHorizontal();
 9426259                (layoutElem as ILayoutElement).CalculateLayoutInputVertical();
 260            }
 261
 16454262            var layoutControllers = rectTransformRoot.GetComponentsInChildren(typeof(ILayoutController), true).ToList();
 78201263            layoutControllers.RemoveAll(e => e is Behaviour && !((Behaviour) e).isActiveAndEnabled);
 40178264            foreach (var layoutCtrl in layoutControllers)
 265            {
 3635266                (layoutCtrl as ILayoutController).SetLayoutHorizontal();
 3635267                (layoutCtrl as ILayoutController).SetLayoutVertical();
 268            }
 16454269        }
 270
 271        private static IEnumerator ForceUpdateLayoutRoutine(RectTransform rt)
 272        {
 54273            yield return null;
 274
 54275            InverseTransformChildTraversal<RectTransform>(
 6124276                (x) => { ForceRebuildLayoutImmediate(x); },
 277                rt);
 54278        }
 279
 280        public static void InverseTransformChildTraversal<TComponent>(Action<TComponent> action, Transform startTransfor
 281            where TComponent : Component
 282        {
 97524283            if (startTransform == null)
 15284                return;
 285
 386672286            foreach (Transform t in startTransform)
 287            {
 95827288                InverseTransformChildTraversal(action, t);
 289            }
 290
 97509291            var component = startTransform.GetComponent<TComponent>();
 292
 97509293            if (component != null)
 294            {
 16107295                action.Invoke(component);
 296            }
 97509297        }
 298
 299        public static void ForwardTransformChildTraversal<TComponent>(Func<TComponent, bool> action, Transform startTran
 300            where TComponent : Component
 301        {
 0302            Assert.IsTrue(startTransform != null, "startTransform must not be null");
 303
 0304            var component = startTransform.GetComponent<TComponent>();
 305
 0306            if (component != null)
 307            {
 0308                if (!action.Invoke(component))
 0309                    return;
 310            }
 311
 0312            foreach (Transform t in startTransform)
 313            {
 0314                ForwardTransformChildTraversal(action, t);
 315            }
 0316        }
 317
 318        public static T GetOrCreateComponent<T>(this GameObject gameObject) where T : Component
 319        {
 76320            T component = gameObject.GetComponent<T>();
 321
 76322            if (!component)
 323            {
 61324                return gameObject.AddComponent<T>();
 325            }
 326
 15327            return component;
 328        }
 329
 330        public static IWebRequestAsyncOperation FetchTexture(string textureURL, bool isReadable, Action<Texture2D> OnSuc
 331        {
 332            //NOTE(Brian): This closure is called when the download is a success.
 0333            void SuccessInternal(IWebRequestAsyncOperation request) { OnSuccess?.Invoke(DownloadHandlerTexture.GetConten
 334
 147335            var asyncOp = Environment.i.platform.webRequest.GetTexture(
 336                url: textureURL,
 337                OnSuccess: SuccessInternal,
 338                OnFail: OnFail,
 339                isReadable: isReadable);
 340
 147341            return asyncOp;
 342        }
 343
 344        public static bool SafeFromJsonOverwrite(string json, object objectToOverwrite)
 345        {
 346            try
 347            {
 0348                JsonUtility.FromJsonOverwrite(json, objectToOverwrite);
 0349            }
 0350            catch (ArgumentException e)
 351            {
 0352                Debug.LogError("ArgumentException Fail!... Json = " + json + " " + e.ToString());
 0353                return false;
 354            }
 355
 0356            return true;
 0357        }
 358
 46359        public static T FromJsonWithNulls<T>(string json) { return JsonConvert.DeserializeObject<T>(json); }
 360
 361        public static T SafeFromJson<T>(string json)
 362        {
 890363            ProfilingEvents.OnMessageDecodeStart?.Invoke("Misc");
 364
 890365            T returningValue = default(T);
 366
 890367            if (!string.IsNullOrEmpty(json))
 368            {
 369                try
 370                {
 889371                    returningValue = JsonUtility.FromJson<T>(json);
 889372                }
 0373                catch (ArgumentException e)
 374                {
 0375                    Debug.LogError("ArgumentException Fail!... Json = " + json + " " + e.ToString());
 0376                }
 377            }
 378
 890379            ProfilingEvents.OnMessageDecodeEnds?.Invoke("Misc");
 380
 890381            return returningValue;
 382        }
 383
 384        public static GameObject AttachPlaceholderRendererGameObject(Transform targetTransform)
 385        {
 1386            var placeholderRenderer = GameObject.CreatePrimitive(PrimitiveType.Cube).GetComponent<MeshRenderer>();
 387
 1388            placeholderRenderer.material = Resources.Load<Material>("Materials/AssetLoading");
 1389            placeholderRenderer.transform.SetParent(targetTransform);
 1390            placeholderRenderer.transform.localPosition = Vector3.zero;
 1391            placeholderRenderer.name = "PlaceholderRenderer";
 392
 1393            return placeholderRenderer.gameObject;
 394        }
 395
 396        public static void SafeDestroy(Object obj)
 397        {
 10975398            if (obj is Transform)
 0399                return;
 400
 401#if UNITY_EDITOR
 10975402            if (Application.isPlaying)
 10975403                Object.Destroy(obj);
 404            else
 0405                Object.DestroyImmediate(obj, false);
 406#else
 407                UnityEngine.Object.Destroy(obj);
 408#endif
 0409        }
 410
 411        /**
 412         * Transforms a grid position into a world-relative 3d position
 413         */
 414        public static Vector3 GridToWorldPosition(float xGridPosition, float yGridPosition)
 415        {
 1380416            return new Vector3(
 417                x: xGridPosition * ParcelSettings.PARCEL_SIZE,
 418                y: 0f,
 419                z: yGridPosition * ParcelSettings.PARCEL_SIZE
 420            );
 421        }
 422
 423        /**
 424         * Transforms a world position into a grid position
 425         */
 426        public static Vector2Int WorldToGridPosition(Vector3 worldPosition)
 427        {
 15011428            return new Vector2Int(
 429                (int) Mathf.Floor(worldPosition.x / ParcelSettings.PARCEL_SIZE),
 430                (int) Mathf.Floor(worldPosition.z / ParcelSettings.PARCEL_SIZE)
 431            );
 432        }
 433
 434        public static Vector2 WorldToGridPositionUnclamped(Vector3 worldPosition)
 435        {
 6436            return new Vector2(
 437                worldPosition.x / ParcelSettings.PARCEL_SIZE,
 438                worldPosition.z / ParcelSettings.PARCEL_SIZE
 439            );
 440        }
 441
 442        public static bool AproxComparison(this Color color1, Color color2, float tolerance = 0.01f) // tolerance of rou
 443        {
 3825444            if (Mathf.Abs(color1.r - color2.r) < tolerance
 445                && Mathf.Abs(color1.g - color2.g) < tolerance
 446                && Mathf.Abs(color1.b - color2.b) < tolerance)
 447            {
 55448                return true;
 449            }
 450
 3770451            return false;
 452        }
 453
 5454        public static T ParseJsonArray<T>(string jsonArray) where T : IEnumerable => DummyJsonUtilityFromArray<T>.GetFro
 455
 456        [Serializable]
 457        private class DummyJsonUtilityFromArray<T> where T : IEnumerable //UnityEngine.JsonUtility is really fast but ca
 458        {
 459            [SerializeField]
 460            private T value;
 461
 462            public static T GetFromJsonArray(string jsonArray)
 463            {
 464                string newJson = $"{{ \"value\": {jsonArray}}}";
 465                return JsonUtility.FromJson<DummyJsonUtilityFromArray<T>>(newJson).value;
 466            }
 467        }
 468
 1469        private static int lockedInFrame = -1;
 16773470        public static bool LockedThisFrame() => lockedInFrame == Time.frameCount;
 471
 472        private static bool isCursorLocked;
 473        //NOTE(Brian): Made as an independent flag because the CI doesn't work well with the Cursor.lockState check.
 474        public static bool IsCursorLocked
 475        {
 191583476            get => isCursorLocked;
 477            private set
 478            {
 184479                if (isCursorLocked == value) return;
 78480                isCursorLocked = value;
 78481                OnCursorLockChanged?.Invoke(isCursorLocked);
 0482            }
 483        }
 484
 485        public static event Action<bool> OnCursorLockChanged;
 486
 487        public static void LockCursor()
 488        {
 489#if WEB_PLATFORM
 490            //TODO(Brian): Encapsulate all this mechanism to a new MouseLockController and branch
 491            //             behaviour using strategy pattern instead of this.
 492            if (IsCursorLocked)
 493            {
 494                return;
 495            }
 496#endif
 39497            Cursor.visible = false;
 39498            IsCursorLocked = true;
 39499            Cursor.lockState = CursorLockMode.Locked;
 39500            lockedInFrame = Time.frameCount;
 501
 39502            EventSystem.current?.SetSelectedGameObject(null);
 33503        }
 504
 505        public static void UnlockCursor()
 506        {
 507#if WEB_PLATFORM
 508            //TODO(Brian): Encapsulate all this mechanism to a new MouseLockController and branch
 509            //             behaviour using strategy pattern instead of this.
 510            if (!IsCursorLocked)
 511            {
 512                return;
 513            }
 514#endif
 92515            Cursor.visible = true;
 92516            IsCursorLocked = false;
 92517            Cursor.lockState = CursorLockMode.None;
 518
 92519            EventSystem.current?.SetSelectedGameObject(null);
 38520        }
 521
 522        #region BROWSER_ONLY
 523
 524        //TODO(Brian): Encapsulate all this mechanism to a new MouseLockController and branch
 525        //             behaviour using strategy pattern instead of this.
 526        // NOTE: This should come from browser's pointerlockchange callback
 527        public static void BrowserSetCursorState(bool locked)
 528        {
 0529            Cursor.lockState = locked ? CursorLockMode.Locked : CursorLockMode.None;
 530
 0531            IsCursorLocked = locked;
 0532            Cursor.visible = !locked;
 0533        }
 534
 535        #endregion
 536
 537        public static void DestroyAllChild(this Transform transform)
 538        {
 82539            foreach (Transform child in transform)
 540            {
 3541                Object.Destroy(child.gameObject);
 542            }
 38543        }
 544
 545        public static List<Vector2Int> GetBottomLeftZoneArray(Vector2Int bottomLeftAnchor, Vector2Int size)
 546        {
 0547            List<Vector2Int> coords = new List<Vector2Int>();
 548
 0549            for (int x = bottomLeftAnchor.x; x < bottomLeftAnchor.x + size.x; x++)
 550            {
 0551                for (int y = bottomLeftAnchor.y; y < bottomLeftAnchor.y + size.y; y++)
 552                {
 0553                    coords.Add(new Vector2Int(x, y));
 554                }
 555            }
 556
 0557            return coords;
 558        }
 559
 560        public static List<Vector2Int> GetCenteredZoneArray(Vector2Int center, Vector2Int size)
 561        {
 0562            List<Vector2Int> coords = new List<Vector2Int>();
 563
 0564            for (int x = center.x - size.x; x < center.x + size.x; x++)
 565            {
 0566                for (int y = center.y - size.y; y < center.y + size.y; y++)
 567                {
 0568                    coords.Add(new Vector2Int(x, y));
 569                }
 570            }
 571
 0572            return coords;
 573        }
 574
 575        public static void DrawRectGizmo(Rect rect, Color color, float duration)
 576        {
 0577            Vector3 tl2 = new Vector3(rect.xMin, rect.yMax, 0);
 0578            Vector3 bl2 = new Vector3(rect.xMin, rect.yMin, 0);
 0579            Vector3 tr2 = new Vector3(rect.xMax, rect.yMax, 0);
 0580            Vector3 br2 = new Vector3(rect.xMax, rect.yMin, 0);
 581
 0582            Debug.DrawLine(tl2, bl2, color, duration);
 0583            Debug.DrawLine(tl2, tr2, color, duration);
 0584            Debug.DrawLine(bl2, br2, color, duration);
 0585            Debug.DrawLine(tr2, br2, color, duration);
 0586        }
 587
 588        public static string ToUpperFirst(this string value)
 589        {
 4590            if (!string.IsNullOrEmpty(value))
 591            {
 4592                var capital = char.ToUpper(value[0]);
 4593                value = capital + value.Substring(1);
 594            }
 595
 4596            return value;
 597        }
 598
 599        public static Vector3 Sanitize(Vector3 value)
 600        {
 266601            float x = float.IsInfinity(value.x) ? 0 : value.x;
 266602            float y = float.IsInfinity(value.y) ? 0 : value.y;
 266603            float z = float.IsInfinity(value.z) ? 0 : value.z;
 604
 266605            return new Vector3(x, y, z);
 606        }
 607
 0608        public static bool CompareFloats( float a, float b, float precision = 0.1f ) { return Mathf.Abs(a - b) < precisi
 609
 610        public static void Deconstruct<T1, T2>(this KeyValuePair<T1, T2> tuple, out T1 key, out T2 value)
 611        {
 0612            key = tuple.Key;
 0613            value = tuple.Value;
 0614        }
 615
 616        /// <summary>
 617        /// Set a layer to the given transform and its child
 618        /// </summary>
 619        /// <param name="transform"></param>
 620        public static void SetLayerRecursively(Transform transform, int layer)
 621        {
 545622            transform.gameObject.layer = layer;
 2150623            foreach (Transform child in transform)
 624            {
 530625                SetLayerRecursively(child, layer);
 626            }
 545627        }
 628
 629        /// <summary>
 630        /// Converts a linear float (between 0 and 1) into an exponential curve fitting for audio volume.
 631        /// </summary>
 632        /// <param name="volume">Linear volume float</param>
 633        /// <returns>Exponential volume curve float</returns>
 92634        public static float ToVolumeCurve(float volume) { return volume * (2f - volume); }
 635
 636        /// <summary>
 637        /// Takes a linear volume value between 0 and 1, converts to exponential curve and maps to a value fitting for a
 638        /// </summary>
 639        /// <param name="volume">Linear volume (0 to 1)</param>
 640        /// <returns>Value for audio mixer group volume</returns>
 8641        public static float ToAudioMixerGroupVolume(float volume) { return (ToVolumeCurve(volume) * 80f) - 80f; }
 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;
 0653            return $"{transform.parent.GetHierarchyPath()}/{transform.name}";
 654        }
 655
 656        public static bool TryFindChildRecursively(this Transform transform, string name, out Transform foundChild)
 657        {
 0658            foundChild = transform.Find(name);
 0659            if (foundChild != null)
 0660                return true;
 661
 0662            foreach (Transform child in transform)
 663            {
 0664                if (TryFindChildRecursively(child, name, out foundChild))
 0665                    return true;
 666            }
 0667            return false;
 0668        }
 669
 670        public static bool IsPointerOverUIElement(Vector3 mousePosition)
 671        {
 0672            if (EventSystem.current == null)
 0673                return false;
 674
 0675            var eventData = new PointerEventData(EventSystem.current);
 0676            eventData.position = mousePosition;
 0677            var results = new List<RaycastResult>();
 0678            EventSystem.current.RaycastAll(eventData, results);
 0679            return results.Count > 1;
 680        }
 681
 0682        public static bool IsPointerOverUIElement() { return IsPointerOverUIElement(Input.mousePosition); }
 683
 684        public static string UnixTimeStampToLocalTime(ulong unixTimeStampMilliseconds)
 685        {
 3686            DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
 3687            dtDateTime = dtDateTime.AddMilliseconds(unixTimeStampMilliseconds).ToLocalTime();
 3688            return $"{dtDateTime.Hour}:{dtDateTime.Minute.ToString("D2")}";
 689        }
 690
 691        public static DateTime UnixToDateTimeWithTime(ulong unixTimeStampMilliseconds)
 692        {
 28693            DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
 28694            dtDateTime = dtDateTime.AddMilliseconds(unixTimeStampMilliseconds).ToLocalTime();
 28695            return dtDateTime;
 696        }
 697    }
 698}

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])
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)
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)