< Summary

Class:DCL.AssetPromise_AB_GameObject
Assembly:AssetPromiseKeeper
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/AssetManager/AssetBundles/AB_GameObject/AssetPromise_AB_GameObject.cs
Covered lines:96
Uncovered lines:22
Coverable lines:118
Total lines:268
Line coverage:81.3% (96 of 118)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
AssetPromise_AB_GameObject(...)0%110100%
OnFeatureFlagChange(...)0%110100%
OnLoad(...)0%110100%
AddToLibrary()0%3.033085.71%
OnReuse(...)0%110100%
OnAfterLoadOrReuse()0%110100%
OnBeforeLoadOrReuse()0%110100%
OnCancelLoading()0%330100%
ToString()0%6200%
LoadingCoroutine()0%11110100%
InstantiateABGameObjects()0%11.0311093.55%
UploadMeshesToGPU(...)0%4.14081.82%
GetAsset(...)0%220100%
OnForget()0%110100%
SetMaterialTransition()0%30.777021.43%
IsTransitionFinished(...)0%12300%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/AssetManager/AssetBundles/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 AssetPromiseSettings_Rendering();
 15        AssetPromise_AB subPromise;
 16        Coroutine loadingCoroutine;
 17
 13218        private BaseVariable<FeatureFlag> featureFlags => DataStore.i.featureFlags.flags;
 19        private const string AB_LOAD_ANIMATION = "ab_load_animation";
 20        private const string GPU_ONLY_MESHES = "use_gpu_only_meshes_variant:enabled";
 21        private bool doTransitionAnimation;
 22
 4423        public AssetPromise_AB_GameObject(string contentUrl, string hash) : base(contentUrl, hash)
 24        {
 4425            featureFlags.OnChange += OnFeatureFlagChange;
 4426            OnFeatureFlagChange(featureFlags.Get(), null);
 4427        }
 28
 8829        private void OnFeatureFlagChange(FeatureFlag current, FeatureFlag previous) { doTransitionAnimation = current.Is
 30
 3831        protected override void OnLoad(Action OnSuccess, Action<Exception> OnFail) { loadingCoroutine = CoroutineStarter
 32
 33        protected override bool AddToLibrary()
 34        {
 1235            if (!library.Add(asset))
 36            {
 037                return false;
 38            }
 39
 1240            if (settings.forceNewInstance)
 41            {
 242                asset = (library as AssetLibrary_AB_GameObject).GetCopyFromOriginal(asset.id);
 43            }
 44            else
 45            {
 1046                asset = library.Get(asset.id);
 47            }
 48
 49            //NOTE(Brian): Call again this method because we are replacing the asset.
 1250            settings.ApplyBeforeLoad(asset.container.transform);
 51
 1252            return true;
 53        }
 54
 55        protected override void OnReuse(Action OnSuccess)
 56        {
 2557            asset.renderers = MeshesInfoUtils.ExtractUniqueRenderers(asset.container);
 2558            asset.Show(OnSuccess);
 2559        }
 60
 61        protected override void OnAfterLoadOrReuse()
 62        {
 3763            asset.renderers = MeshesInfoUtils.ExtractUniqueRenderers(asset.container);
 3764            settings.ApplyAfterLoad(asset.container.transform);
 3765        }
 66
 8867        protected override void OnBeforeLoadOrReuse() { settings.ApplyBeforeLoad(asset.container.transform); }
 68
 69        protected override void OnCancelLoading()
 70        {
 771            if (loadingCoroutine != null)
 72            {
 373                PerformanceAnalytics.ABTracker.TrackCancelled();
 374                CoroutineStarter.Stop(loadingCoroutine);
 375                loadingCoroutine = null;
 76            }
 77
 778            if (asset != null)
 779                UnityEngine.Object.Destroy(asset.container);
 80
 781            AssetPromiseKeeper_AB.i.Forget(subPromise);
 782        }
 83
 84        public override string ToString()
 85        {
 086            if (subPromise != null)
 087                return $"{subPromise.ToString()} ... AB_GameObject state = {state}";
 88            else
 089                return $"subPromise == null? state = {state}";
 90        }
 91
 92        public IEnumerator LoadingCoroutine(Action OnSuccess, Action<Exception> OnFail)
 93        {
 1994            PerformanceAnalytics.ABTracker.TrackLoading();
 1995            subPromise = new AssetPromise_AB(contentUrl, hash, asset.container.transform);
 1996            bool success = false;
 1997            Exception loadingException = null;
 3498            subPromise.OnSuccessEvent += (x) => success = true;
 99
 19100            subPromise.OnFailEvent += ( ab,  exception) =>
 101            {
 1102                loadingException = exception;
 1103                success = false;
 1104            };
 105
 19106            asset.ownerPromise = subPromise;
 19107            AssetPromiseKeeper_AB.i.Keep(subPromise);
 108
 19109            yield return subPromise;
 110
 16111            if (success)
 112            {
 15113                yield return InstantiateABGameObjects();
 114
 15115                if (subPromise.asset == null || asset.container == null)
 3116                    success = false;
 117            }
 118
 16119            loadingCoroutine = null;
 120
 16121            if (success)
 122            {
 12123                PerformanceAnalytics.ABTracker.TrackLoaded();
 12124                OnSuccess?.Invoke();
 125            }
 126            else
 127            {
 4128                PerformanceAnalytics.ABTracker.TrackFailed();
 4129                loadingException ??= new Exception($"AB sub-promise asset or container is null. Asset: {subPromise.asset
 4130                Debug.LogException(loadingException);
 4131                OnFail?.Invoke(loadingException);
 132            }
 16133        }
 134
 135        public IEnumerator InstantiateABGameObjects()
 136        {
 15137            var goList = subPromise.asset.GetAssetsByExtensions<GameObject>("glb", "ltf");
 138
 15139            if (goList.Count == 0)
 140            {
 2141                if (asset.container != null)
 2142                    UnityEngine.Object.Destroy(asset.container);
 143
 2144                asset.container = null;
 145
 2146                AssetPromiseKeeper_AB.i.Forget(subPromise);
 147
 2148                yield break;
 149            }
 150
 50151            for (int i = 0; i < goList.Count; i++)
 152            {
 13153                if (loadingCoroutine == null)
 154                    break;
 155
 13156                if (asset.container == null)
 157                    break;
 158
 12159                GameObject assetBundleModelGO = UnityEngine.Object.Instantiate(goList[i], asset.container.transform);
 160
 12161                asset.renderers = MeshesInfoUtils.ExtractUniqueRenderers(assetBundleModelGO);
 12162                asset.materials = MeshesInfoUtils.ExtractUniqueMaterials(asset.renderers);
 12163                asset.SetTextures(MeshesInfoUtils.ExtractUniqueTextures(asset.materials));
 164
 12165                UploadMeshesToGPU(MeshesInfoUtils.ExtractUniqueMeshes(asset.renderers));
 12166                asset.totalTriangleCount = MeshesInfoUtils.ComputeTotalTriangles(asset.renderers, asset.meshToTriangleCo
 167
 168                //NOTE(Brian): Renderers are enabled in settings.ApplyAfterLoad
 12169                yield return MaterialCachingHelper.Process(asset.renderers.ToList(), enableRenderers: false, settings.ca
 170
 12171                var animators = MeshesInfoUtils.ExtractUniqueAnimations(assetBundleModelGO);
 12172                asset.animationClipSize = subPromise.asset.metrics.animationsEstimatedSize;
 12173                asset.meshDataSize = subPromise.asset.metrics.meshesEstimatedSize;
 174
 24175                foreach (var animator in animators)
 176                {
 0177                    animator.cullingType = AnimationCullingType.AlwaysAnimate;
 178                }
 179
 180#if UNITY_EDITOR
 12181                assetBundleModelGO.name = subPromise.asset.GetName();
 182#endif
 183
 12184                yield return null;
 185
 12186                yield return SetMaterialTransition();
 12187            }
 13188        }
 189
 190        private void UploadMeshesToGPU(HashSet<Mesh> meshesList)
 191        {
 12192            var uploadToGPU = featureFlags.Get().IsFeatureEnabled(GPU_ONLY_MESHES);
 193
 48194            foreach ( Mesh mesh in meshesList )
 195            {
 12196                if ( !mesh.isReadable )
 197                    continue;
 198
 12199                asset.meshToTriangleCount[mesh] = mesh.triangles.Length;
 12200                asset.meshes.Add(mesh);
 201
 12202                if (uploadToGPU)
 203                {
 0204                    Physics.BakeMesh(mesh.GetInstanceID(), false);
 0205                    mesh.UploadMeshData(true);
 206                }
 207            }
 12208        }
 209
 210        protected override Asset_AB_GameObject GetAsset(object id)
 211        {
 25212            if (settings.forceNewInstance)
 213            {
 9214                return ((AssetLibrary_AB_GameObject) library).GetCopyFromOriginal(id);
 215            }
 216            else
 217            {
 16218                return base.GetAsset(id);
 219            }
 220        }
 221
 222        internal override void OnForget()
 223        {
 32224            base.OnForget();
 32225            featureFlags.OnChange -= OnFeatureFlagChange;
 32226        }
 227
 228        IEnumerator SetMaterialTransition(Action OnSuccess = null)
 229        {
 12230            if (settings.visibleFlags != AssetPromiseSettings_Rendering.VisibleFlags.INVISIBLE && doTransitionAnimation)
 231            {
 0232                MaterialTransitionController[] materialTransitionControllers = new MaterialTransitionController[asset.re
 0233                int index = 0;
 0234                foreach (Renderer assetRenderer in asset.renderers)
 235                {
 0236                    MaterialTransitionController transition = assetRenderer.gameObject.AddComponent<MaterialTransitionCo
 0237                    materialTransitionControllers[index] = transition;
 0238                    transition.delay = 0;
 0239                    transition.OnDidFinishLoading(assetRenderer.sharedMaterial);
 240
 0241                    index++;
 242                }
 243                // Wait until MaterialTransitionController finishes its effect
 0244                yield return new WaitUntil(() => IsTransitionFinished(materialTransitionControllers));
 245            }
 12246            OnSuccess?.Invoke();
 12247        }
 248
 249        private bool IsTransitionFinished(MaterialTransitionController[] matTransitions)
 250        {
 0251            bool finishedTransition = true;
 252
 0253            for (int i = 0; i < matTransitions.Length; i++)
 254            {
 0255                if (matTransitions[i] != null)
 256                {
 0257                    finishedTransition = false;
 258
 0259                    break;
 260                }
 261            }
 262
 0263            return finishedTransition;
 264        }
 265
 266    }
 267
 268}