< 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:99
Uncovered lines:22
Coverable lines:121
Total lines:269
Line coverage:81.8% (99 of 121)
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.023087.5%
OnReuse(...)0%110100%
OnAfterLoadOrReuse()0%110100%
OnBeforeLoadOrReuse()0%110100%
OnCancelLoading()0%330100%
ToString()0%6200%
LoadingCoroutine()0%11110100%
InstantiateABGameObjects()0%11.0311093.75%
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";
 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);
 243            }
 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();
 12125            }
 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
 12183                assetBundleModelGO.transform.ResetLocalTRS();
 184
 12185                yield return null;
 186
 12187                yield return SetMaterialTransition();
 12188            }
 13189        }
 190
 191        private void UploadMeshesToGPU(HashSet<Mesh> meshesList)
 192        {
 12193            var uploadToGPU = featureFlags.Get().IsFeatureEnabled(GPU_ONLY_MESHES);
 194
 48195            foreach ( Mesh mesh in meshesList )
 196            {
 12197                if ( !mesh.isReadable )
 198                    continue;
 199
 12200                asset.meshToTriangleCount[mesh] = mesh.triangles.Length;
 12201                asset.meshes.Add(mesh);
 202
 12203                if (uploadToGPU)
 204                {
 0205                    Physics.BakeMesh(mesh.GetInstanceID(), false);
 0206                    mesh.UploadMeshData(true);
 207                }
 208            }
 12209        }
 210
 211        protected override Asset_AB_GameObject GetAsset(object id)
 212        {
 25213            if (settings.forceNewInstance)
 214            {
 9215                return ((AssetLibrary_AB_GameObject) library).GetCopyFromOriginal(id);
 216            }
 217            else
 218            {
 16219                return base.GetAsset(id);
 220            }
 221        }
 222
 223        internal override void OnForget()
 224        {
 32225            base.OnForget();
 32226            featureFlags.OnChange -= OnFeatureFlagChange;
 32227        }
 228
 229        IEnumerator SetMaterialTransition(Action OnSuccess = null)
 230        {
 12231            if (settings.visibleFlags != AssetPromiseSettings_Rendering.VisibleFlags.INVISIBLE && doTransitionAnimation)
 232            {
 0233                MaterialTransitionController[] materialTransitionControllers = new MaterialTransitionController[asset.re
 0234                int index = 0;
 0235                foreach (Renderer assetRenderer in asset.renderers)
 236                {
 0237                    MaterialTransitionController transition = assetRenderer.gameObject.AddComponent<MaterialTransitionCo
 0238                    materialTransitionControllers[index] = transition;
 0239                    transition.delay = 0;
 0240                    transition.OnDidFinishLoading(assetRenderer.sharedMaterial);
 241
 0242                    index++;
 243                }
 244                // Wait until MaterialTransitionController finishes its effect
 0245                yield return new WaitUntil(() => IsTransitionFinished(materialTransitionControllers));
 246            }
 12247            OnSuccess?.Invoke();
 12248        }
 249
 250        private bool IsTransitionFinished(MaterialTransitionController[] matTransitions)
 251        {
 0252            bool finishedTransition = true;
 253
 0254            for (int i = 0; i < matTransitions.Length; i++)
 255            {
 0256                if (matTransitions[i] != null)
 257                {
 0258                    finishedTransition = false;
 259
 0260                    break;
 261                }
 262            }
 263
 0264            return finishedTransition;
 265        }
 266
 267    }
 268
 269}