< Summary

Class:DCL.AssetPromise_AB_GameObject
Assembly:AssetPromiseKeeper
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/AssetManager/AssetBundles/AB/AB_GameObject/AssetPromise_AB_GameObject.cs
Covered lines:87
Uncovered lines:8
Coverable lines:95
Total lines:216
Line coverage:91.5% (87 of 95)
Covered branches:0
Total branches:0
Covered methods:14
Total methods:15
Method coverage:93.3% (14 of 15)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
AssetPromise_AB_GameObject(...)0%110100%
OnLoad(...)0%110100%
AddToLibrary()0%3.073080%
OnReuse(...)0%110100%
OnAfterLoadOrReuse()0%110100%
OnBeforeLoadOrReuse()0%110100%
OnCancelLoading()0%330100%
ToString()0%6200%
LoadingCoroutine()0%11110100%
InstantiateABGameObjects()0%8.028092.86%
OptimizeMaterials(...)0%220100%
UploadMeshesToGPU(...)0%5.735069.23%
GetAsset(...)0%220100%
IsUploadMeshToGPUEnabled()0%110100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/AssetManager/AssetBundles/AB/AB_GameObject/AssetPromise_AB_GameObject.cs

#LineLine coverage
 1using System;
 2using System.Collections;
 3using System.Linq;
 4using DCL.Helpers;
 5using UnityEngine;
 6using System.Collections.Generic;
 7using DCL.Models;
 8using MainScripts.DCL.Analytics.PerformanceAnalytics;
 9
 10namespace DCL
 11{
 12    public class AssetPromise_AB_GameObject : AssetPromise_WithUrl<Asset_AB_GameObject>
 13    {
 4414        public AssetPromiseSettings_Rendering settings = new ();
 15        AssetPromise_AB subPromise;
 16        Coroutine loadingCoroutine;
 17
 1218        private BaseVariable<FeatureFlag> featureFlags => DataStore.i.featureFlags.flags;
 19        private const string FEATURE_AB_MESH_GPU = "ab-mesh-gpu";
 20
 4421        public AssetPromise_AB_GameObject(string contentUrl, string hash) : base(contentUrl, hash)
 22        {
 23
 4424        }
 25
 26        protected override void OnLoad(Action OnSuccess, Action<Exception> OnFail)
 27        {
 1928            loadingCoroutine = CoroutineStarter.Start(LoadingCoroutine(OnSuccess, OnFail));
 1929        }
 30
 31        protected override bool AddToLibrary()
 32        {
 1233            if (!library.Add(asset))
 034                return false;
 35
 1236            asset = settings.forceNewInstance
 37                ? ((AssetLibrary_AB_GameObject)library).GetCopyFromOriginal(asset.id)
 38                : library.Get(asset.id);
 39
 40            //NOTE(Brian): Call again this method because we are replacing the asset.
 1241            settings.ApplyBeforeLoad(asset.container.transform);
 42
 1243            return true;
 44        }
 45
 46        protected override void OnReuse(Action OnSuccess)
 47        {
 2548            asset.renderers = MeshesInfoUtils.ExtractUniqueRenderers(asset.container);
 2549            asset.Show(OnSuccess);
 2550        }
 51
 52        protected override void OnAfterLoadOrReuse()
 53        {
 3754            asset.renderers = MeshesInfoUtils.ExtractUniqueRenderers(asset.container);
 3755            settings.ApplyAfterLoad(asset.container.transform);
 3756        }
 57
 58        protected override void OnBeforeLoadOrReuse()
 59        {
 4460            settings.ApplyBeforeLoad(asset.container.transform);
 4461        }
 62
 63        protected override void OnCancelLoading()
 64        {
 765            if (loadingCoroutine != null)
 66            {
 367                PerformanceAnalytics.ABTracker.TrackCancelled();
 368                CoroutineStarter.Stop(loadingCoroutine);
 369                loadingCoroutine = null;
 70            }
 71
 772            if (asset != null)
 773                UnityEngine.Object.Destroy(asset.container);
 74
 775            AssetPromiseKeeper_AB.i.Forget(subPromise);
 776        }
 77
 78        public override string ToString()
 79        {
 080            if (subPromise != null)
 081                return $"{subPromise} ... AB_GameObject state = {state}";
 82
 083            return $"subPromise == null? state = {state}";
 84        }
 85
 86        private IEnumerator LoadingCoroutine(Action OnSuccess, Action<Exception> OnFail)
 87        {
 1988            PerformanceAnalytics.ABTracker.TrackLoading();
 1989            subPromise = new AssetPromise_AB(contentUrl, hash, asset.container.transform);
 1990            bool success = false;
 1991            Exception loadingException = null;
 3492            subPromise.OnSuccessEvent += (x) => success = true;
 93
 1994            subPromise.OnFailEvent += (ab, exception) =>
 95            {
 196                loadingException = exception;
 197                success = false;
 198            };
 99
 19100            asset.ownerPromise = subPromise;
 19101            AssetPromiseKeeper_AB.i.Keep(subPromise);
 102
 19103            yield return subPromise;
 104
 16105            if (success)
 106            {
 15107                yield return InstantiateABGameObjects();
 108
 15109                if (subPromise.asset == null || asset.container == null)
 3110                    success = false;
 111            }
 112
 16113            loadingCoroutine = null;
 114
 16115            if (success)
 116            {
 12117                PerformanceAnalytics.ABTracker.TrackLoaded();
 12118                OnSuccess?.Invoke();
 119            }
 120            else
 121            {
 4122                PerformanceAnalytics.ABTracker.TrackFailed();
 4123                loadingException ??= new Exception($"AB sub-promise asset or container is null. Asset: {subPromise.asset
 4124                OnFail?.Invoke(loadingException);
 125            }
 16126        }
 127
 128        private IEnumerator InstantiateABGameObjects()
 129        {
 15130            var goList = subPromise.asset.GetAssetsByExtensions<GameObject>("glb", "ltf");
 131
 15132            if (goList.Count == 0)
 133            {
 2134                if (asset.container != null)
 2135                    UnityEngine.Object.Destroy(asset.container);
 136
 2137                asset.container = null;
 138
 2139                AssetPromiseKeeper_AB.i.Forget(subPromise);
 140
 2141                yield break;
 142            }
 143
 50144            for (int i = 0; i < goList.Count; i++)
 145            {
 13146                if (loadingCoroutine == null)
 147                    break;
 148
 13149                if (asset.container == null)
 150                    break;
 151
 12152                GameObject assetBundleModelGO = UnityEngine.Object.Instantiate(goList[i], asset.container.transform);
 153
 12154                asset.renderers = MeshesInfoUtils.ExtractUniqueRenderers(assetBundleModelGO);
 12155                asset.materials = MeshesInfoUtils.ExtractUniqueMaterials(asset.renderers);
 12156                asset.SetTextures(MeshesInfoUtils.ExtractUniqueTextures(asset.materials));
 12157                OptimizeMaterials(MeshesInfoUtils.ExtractUniqueMaterials(asset.renderers));
 12158                UploadMeshesToGPU(MeshesInfoUtils.ExtractUniqueMeshes(asset.renderers));
 12159                asset.totalTriangleCount = MeshesInfoUtils.ComputeTotalTriangles(asset.renderers, asset.meshToTriangleCo
 160
 12161                var animators = MeshesInfoUtils.ExtractUniqueAnimations(assetBundleModelGO);
 12162                asset.animationClipSize = subPromise.asset.metrics.animationsEstimatedSize;
 12163                asset.meshDataSize = subPromise.asset.metrics.meshesEstimatedSize;
 164
 24165                foreach (var animator in animators) { animator.cullingType = AnimationCullingType.AlwaysAnimate; }
 166
 167#if UNITY_EDITOR
 12168                assetBundleModelGO.name = subPromise.asset.GetName();
 169#endif
 170
 171            }
 13172        }
 173
 174        private void OptimizeMaterials(HashSet<Material> materials)
 175        {
 48176            foreach (Material material in materials)
 12177                SRPBatchingHelper.OptimizeMaterial(material);
 12178        }
 179
 180        private void UploadMeshesToGPU(HashSet<Mesh> meshesList)
 181        {
 12182            bool uploadMesh = IsUploadMeshToGPUEnabled();
 183
 48184            foreach (Mesh mesh in meshesList)
 185            {
 12186                if (!mesh.isReadable)
 187                    continue;
 188
 12189                asset.meshToTriangleCount[mesh] = mesh.triangles.Length;
 12190                asset.meshes.Add(mesh);
 191
 12192                if (!uploadMesh) continue;
 193
 0194                bool isCollider = mesh.name.Contains("_collider", StringComparison.InvariantCultureIgnoreCase);
 195
 196                // colliders will fail to be created if they are not readable on WebGL
 0197                if (!isCollider)
 198                {
 0199                    Physics.BakeMesh(mesh.GetInstanceID(), false);
 0200                    mesh.UploadMeshData(true);
 201                }
 202            }
 12203        }
 204
 205        protected override Asset_AB_GameObject GetAsset(object id)
 206        {
 25207            if (settings.forceNewInstance)
 9208                return ((AssetLibrary_AB_GameObject)library).GetCopyFromOriginal(id);
 209
 16210            return base.GetAsset(id);
 211        }
 212
 213        private bool IsUploadMeshToGPUEnabled() =>
 12214            featureFlags.Get().IsFeatureEnabled(FEATURE_AB_MESH_GPU);
 215    }
 216}