< 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:57
Uncovered lines:4
Coverable lines:61
Total lines:152
Line coverage:93.4% (57 of 61)
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.91%
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
 133922        public GameObject container { get; private set; }
 023        public SkinnedMeshRenderer renderer { get; private set; }
 24
 25        public bool useCullOpaqueHeuristic = false;
 26        public bool prepareMeshForGpuSkinning = false;
 133927        public bool uploadMeshToGpu = true;
 28
 29        private AvatarMeshCombiner.Output? lastOutput;
 30
 401731        public AvatarMeshCombinerHelper (GameObject container = null) { this.container = container; }
 32
 33        /// <summary>
 34        /// Combine will use AvatarMeshCombiner to generate a combined avatar mesh.
 35        /// After the avatar is combined, it will generate a new GameObject with a SkinnedMeshRenderer that contains
 36        /// the generated mesh. This GameObject and Renderer will be preserved over any number of Combine() calls.
 37        ///
 38        /// For more details on the combining check out AvatarMeshCombiner.CombineSkinnedMeshes.
 39        /// </summary>
 40        /// <param name="bonesContainer">A SkinnedMeshRenderer that must contain the bones and bindposes that will be us
 41        /// <param name="renderersToCombine">A list of avatar parts to be combined</param>
 42        /// <param name="materialAsset">A material asset that will serve as the base of the combine result. A new materi
 43        /// <returns>true if succeeded, false if not</returns>
 44        public bool Combine(SkinnedMeshRenderer bonesContainer, SkinnedMeshRenderer[] renderersToCombine, Material mater
 45        {
 1546            Assert.IsTrue(bonesContainer != null, "bonesContainer should never be null!");
 1547            Assert.IsTrue(renderersToCombine != null, "renderersToCombine should never be null!");
 1548            Assert.IsTrue(materialAsset != null, "materialAsset should never be null!");
 49
 1550            SkinnedMeshRenderer[] renderers = renderersToCombine;
 51
 52            // Sanitize renderers list
 9053            renderers = renderers.Where( (x) => x != null && x.enabled && x.sharedMesh != null ).ToArray();
 54
 1555            if ( renderers.Length == 0 )
 156                return false;
 57
 1458            bool success = CombineInternal(
 59                bonesContainer,
 60                renderers,
 61                materialAsset);
 62
 63            // Disable original renderers
 15864            for ( int i = 0; i < renderers.Length; i++ )
 65            {
 6566                renderers[i].enabled = false;
 67            }
 68
 1469            return success;
 70        }
 71
 72        private bool CombineInternal(SkinnedMeshRenderer bonesContainer, SkinnedMeshRenderer[] renderers, Material mater
 73        {
 1474            Assert.IsTrue(bonesContainer != null, "bonesContainer should never be null!");
 1475            Assert.IsTrue(bonesContainer.sharedMesh != null, "bonesContainer should never be null!");
 1476            Assert.IsTrue(bonesContainer.sharedMesh.bindposes != null, "bonesContainer bindPoses should never be null!")
 1477            Assert.IsTrue(bonesContainer.bones != null, "bonesContainer bones should never be null!");
 1478            Assert.IsTrue(renderers != null, "renderers should never be null!");
 1479            Assert.IsTrue(materialAsset != null, "materialAsset should never be null!");
 80
 1481            CombineLayerUtils.ENABLE_CULL_OPAQUE_HEURISTIC = useCullOpaqueHeuristic;
 82
 1483            AvatarMeshCombiner.Output output = AvatarMeshCombiner.CombineSkinnedMeshes(
 84                bonesContainer.sharedMesh.bindposes,
 85                bonesContainer.bones,
 86                renderers,
 87                materialAsset);
 88
 1489            if ( !output.isValid )
 90            {
 091                logger.LogError("AvatarMeshCombiner", "Combine failed!");
 092                return false;
 93            }
 94
 1495            Transform rootBone = bonesContainer.rootBone;
 96
 1497            if ( container == null )
 1298                this.container = new GameObject("CombinedAvatar");
 99
 14100            if ( renderer == null )
 12101                renderer = container.AddComponent<SkinnedMeshRenderer>();
 102
 14103            UnloadAssets();
 14104            lastOutput = output;
 105
 14106            container.layer = bonesContainer.gameObject.layer;
 14107            renderer.sharedMesh = output.mesh;
 14108            renderer.bones = bonesContainer.bones;
 14109            renderer.rootBone = rootBone;
 14110            renderer.sharedMaterials = output.materials;
 14111            renderer.quality = SkinQuality.Bone4;
 14112            renderer.updateWhenOffscreen = false;
 14113            renderer.skinnedMotionVectors = false;
 14114            renderer.enabled = true;
 115
 14116            if (prepareMeshForGpuSkinning)
 0117                GPUSkinningUtils.EncodeBindPosesIntoMesh(renderer);
 118
 14119            if (uploadMeshToGpu)
 12120                output.mesh.UploadMeshData(true);
 121
 14122            logger.Log("AvatarMeshCombiner", "Finish combining avatar. Click here to focus on GameObject.", container);
 14123            return true;
 124        }
 125
 126        private void UnloadAssets()
 127        {
 4035128            if (!lastOutput.HasValue)
 4013129                return;
 130
 22131            if (lastOutput.Value.mesh != null)
 12132                Object.Destroy(lastOutput.Value.mesh);
 133
 22134            if (lastOutput.Value.materials != null)
 135            {
 120136                foreach ( var material in lastOutput.Value.materials )
 137                {
 38138                    Object.Destroy(material);
 139                }
 140            }
 22141        }
 142
 143        /// <summary>
 144        /// Disposes the created mesh, materials, GameObject and Renderer.
 145        /// </summary>
 146        public void Dispose()
 147        {
 4021148            UnloadAssets();
 4021149            Object.Destroy(container);
 4021150        }
 151    }
 152}