< Summary

Class:DCL.AvatarMeshCombinerHelper
Assembly:AvatarMeshCombiner
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarMeshCombiner/AvatarMeshCombinerHelper.cs
Covered lines:56
Uncovered lines:4
Coverable lines:60
Total lines:149
Line coverage:93.3% (56 of 60)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
AvatarMeshCombinerHelper()0%330100%
AvatarMeshCombinerHelper(...)0%110100%
Combine(...)0%440100%
CombineInternal(...)0%6.036090.62%
UnloadAssets()0%550100%
Dispose()0%110100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/AvatarMeshCombiner/AvatarMeshCombinerHelper.cs

#LineLine coverage
 1using System;
 2using System.Linq;
 3using GPUSkinning;
 4using UnityEngine;
 5using UnityEngine.Assertions;
 6using Object = UnityEngine.Object;
 7
 8namespace DCL
 9{
 10    /// <summary>
 11    /// AvatarMeshCombinerHelper uses the AvatarMeshCombiner utility class to combine many skinned renderers
 12    /// into a single one.
 13    ///
 14    /// This class will recycle the same gameObject and renderer each time it is called,
 15    /// and binds the AvatarMeshCombiner output to a proper well configured SkinnedMeshRenderer.
 16    /// </summary>
 17    public class AvatarMeshCombinerHelper : IDisposable
 18    {
 119        private static bool VERBOSE = false;
 120        private static ILogger logger = new Logger(Debug.unityLogger.logHandler) { filterLogType = VERBOSE ? LogType.Log
 21
 85822        public GameObject container { get; private set; }
 023        public SkinnedMeshRenderer renderer { get; private set; }
 24
 25        public bool prepareMeshForGpuSkinning = false;
 85826        public bool uploadMeshToGpu = true;
 27
 28        private AvatarMeshCombiner.Output? lastOutput;
 29
 257430        public AvatarMeshCombinerHelper (GameObject container = null) { this.container = container; }
 31
 32        /// <summary>
 33        /// Combine will use AvatarMeshCombiner to generate a combined avatar mesh.
 34        /// After the avatar is combined, it will generate a new GameObject with a SkinnedMeshRenderer that contains
 35        /// the generated mesh. This GameObject and Renderer will be preserved over any number of Combine() calls.
 36        ///
 37        /// For more details on the combining check out AvatarMeshCombiner.CombineSkinnedMeshes.
 38        /// </summary>
 39        /// <param name="bonesContainer">A SkinnedMeshRenderer that must contain the bones and bindposes that will be us
 40        /// <param name="renderersToCombine">A list of avatar parts to be combined</param>
 41        /// <param name="materialAsset">A material asset that will serve as the base of the combine result. A new materi
 42        /// <returns>true if succeeded, false if not</returns>
 43        public bool Combine(SkinnedMeshRenderer bonesContainer, SkinnedMeshRenderer[] renderersToCombine, Material mater
 44        {
 1645            Assert.IsTrue(bonesContainer != null, "bonesContainer should never be null!");
 1646            Assert.IsTrue(renderersToCombine != null, "renderersToCombine should never be null!");
 1647            Assert.IsTrue(materialAsset != null, "materialAsset should never be null!");
 48
 1649            SkinnedMeshRenderer[] renderers = renderersToCombine;
 50
 51            // Sanitize renderers list
 9352            renderers = renderers.Where( (x) => x != null && x.enabled && x.sharedMesh != null ).ToArray();
 53
 1654            if ( renderers.Length == 0 )
 155                return false;
 56
 1557            bool success = CombineInternal(
 58                bonesContainer,
 59                renderers,
 60                materialAsset);
 61
 62            // Disable original renderers
 16463            for ( int i = 0; i < renderers.Length; i++ )
 64            {
 6765                renderers[i].enabled = false;
 66            }
 67
 1568            return success;
 69        }
 70
 71        private bool CombineInternal(SkinnedMeshRenderer bonesContainer, SkinnedMeshRenderer[] renderers, Material mater
 72        {
 1573            Assert.IsTrue(bonesContainer != null, "bonesContainer should never be null!");
 1574            Assert.IsTrue(bonesContainer.sharedMesh != null, "bonesContainer should never be null!");
 1575            Assert.IsTrue(bonesContainer.sharedMesh.bindposes != null, "bonesContainer bindPoses should never be null!")
 1576            Assert.IsTrue(bonesContainer.bones != null, "bonesContainer bones should never be null!");
 1577            Assert.IsTrue(renderers != null, "renderers should never be null!");
 1578            Assert.IsTrue(materialAsset != null, "materialAsset should never be null!");
 79
 1580            AvatarMeshCombiner.Output output = AvatarMeshCombiner.CombineSkinnedMeshes(
 81                bonesContainer.sharedMesh.bindposes,
 82                bonesContainer.bones,
 83                renderers,
 84                materialAsset);
 85
 1586            if ( !output.isValid )
 87            {
 088                logger.LogError("AvatarMeshCombiner", "Combine failed!");
 089                return false;
 90            }
 91
 1592            Transform rootBone = bonesContainer.rootBone;
 93
 1594            if ( container == null )
 1395                this.container = new GameObject("CombinedAvatar");
 96
 1597            if ( renderer == null )
 1398                renderer = container.AddComponent<SkinnedMeshRenderer>();
 99
 15100            UnloadAssets();
 15101            lastOutput = output;
 102
 15103            container.layer = bonesContainer.gameObject.layer;
 15104            renderer.sharedMesh = output.mesh;
 15105            renderer.bones = bonesContainer.bones;
 15106            renderer.rootBone = rootBone;
 15107            renderer.sharedMaterials = output.materials;
 15108            renderer.quality = SkinQuality.Bone4;
 15109            renderer.updateWhenOffscreen = false;
 15110            renderer.skinnedMotionVectors = false;
 15111            renderer.enabled = true;
 112
 15113            if (prepareMeshForGpuSkinning)
 0114                GPUSkinningUtils.EncodeBindPosesIntoMesh(renderer);
 115
 15116            if (uploadMeshToGpu)
 13117                output.mesh.UploadMeshData(true);
 118
 15119            logger.Log("AvatarMeshCombiner", "Finish combining avatar. Click here to focus on GameObject.", container);
 15120            return true;
 121        }
 122
 123        private void UnloadAssets()
 124        {
 3044125            if (!lastOutput.HasValue)
 3016126                return;
 127
 28128            if (lastOutput.Value.mesh != null)
 13129                Object.Destroy(lastOutput.Value.mesh);
 130
 28131            if (lastOutput.Value.materials != null)
 132            {
 148133                foreach ( var material in lastOutput.Value.materials )
 134                {
 46135                    Object.Destroy(material);
 136                }
 137            }
 28138        }
 139
 140        /// <summary>
 141        /// Disposes the created mesh, materials, GameObject and Renderer.
 142        /// </summary>
 143        public void Dispose()
 144        {
 3029145            UnloadAssets();
 3029146            Object.Destroy(container);
 3029147        }
 148    }
 149}