< 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
 86422        public GameObject container { get; private set; }
 023        public SkinnedMeshRenderer renderer { get; private set; }
 24
 25        public bool useCullOpaqueHeuristic = false;
 26        public bool prepareMeshForGpuSkinning = false;
 86427        public bool uploadMeshToGpu = true;
 28
 29        private AvatarMeshCombiner.Output? lastOutput;
 30
 259231        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        {
 1646            Assert.IsTrue(bonesContainer != null, "bonesContainer should never be null!");
 1647            Assert.IsTrue(renderersToCombine != null, "renderersToCombine should never be null!");
 1648            Assert.IsTrue(materialAsset != null, "materialAsset should never be null!");
 49
 1650            SkinnedMeshRenderer[] renderers = renderersToCombine;
 51
 52            // Sanitize renderers list
 9353            renderers = renderers.Where( (x) => x != null && x.enabled && x.sharedMesh != null ).ToArray();
 54
 1655            if ( renderers.Length == 0 )
 156                return false;
 57
 1558            bool success = CombineInternal(
 59                bonesContainer,
 60                renderers,
 61                materialAsset);
 62
 63            // Disable original renderers
 16464            for ( int i = 0; i < renderers.Length; i++ )
 65            {
 6766                renderers[i].enabled = false;
 67            }
 68
 1569            return success;
 70        }
 71
 72        private bool CombineInternal(SkinnedMeshRenderer bonesContainer, SkinnedMeshRenderer[] renderers, Material mater
 73        {
 1574            Assert.IsTrue(bonesContainer != null, "bonesContainer should never be null!");
 1575            Assert.IsTrue(bonesContainer.sharedMesh != null, "bonesContainer should never be null!");
 1576            Assert.IsTrue(bonesContainer.sharedMesh.bindposes != null, "bonesContainer bindPoses should never be null!")
 1577            Assert.IsTrue(bonesContainer.bones != null, "bonesContainer bones should never be null!");
 1578            Assert.IsTrue(renderers != null, "renderers should never be null!");
 1579            Assert.IsTrue(materialAsset != null, "materialAsset should never be null!");
 80
 1581            CombineLayerUtils.ENABLE_CULL_OPAQUE_HEURISTIC = useCullOpaqueHeuristic;
 82
 1583            AvatarMeshCombiner.Output output = AvatarMeshCombiner.CombineSkinnedMeshes(
 84                bonesContainer.sharedMesh.bindposes,
 85                bonesContainer.bones,
 86                renderers,
 87                materialAsset);
 88
 1589            if ( !output.isValid )
 90            {
 091                logger.LogError("AvatarMeshCombiner", "Combine failed!");
 092                return false;
 93            }
 94
 1595            Transform rootBone = bonesContainer.rootBone;
 96
 1597            if ( container == null )
 1398                this.container = new GameObject("CombinedAvatar");
 99
 15100            if ( renderer == null )
 13101                renderer = container.AddComponent<SkinnedMeshRenderer>();
 102
 15103            UnloadAssets();
 15104            lastOutput = output;
 105
 15106            container.layer = bonesContainer.gameObject.layer;
 15107            renderer.sharedMesh = output.mesh;
 15108            renderer.bones = bonesContainer.bones;
 15109            renderer.rootBone = rootBone;
 15110            renderer.sharedMaterials = output.materials;
 15111            renderer.quality = SkinQuality.Bone4;
 15112            renderer.updateWhenOffscreen = false;
 15113            renderer.skinnedMotionVectors = false;
 15114            renderer.enabled = true;
 115
 15116            if (prepareMeshForGpuSkinning)
 0117                GPUSkinningUtils.EncodeBindPosesIntoMesh(renderer);
 118
 15119            if (uploadMeshToGpu)
 13120                output.mesh.UploadMeshData(true);
 121
 15122            logger.Log("AvatarMeshCombiner", "Finish combining avatar. Click here to focus on GameObject.", container);
 15123            return true;
 124        }
 125
 126        private void UnloadAssets()
 127        {
 3070128            if (!lastOutput.HasValue)
 3042129                return;
 130
 28131            if (lastOutput.Value.mesh != null)
 13132                Object.Destroy(lastOutput.Value.mesh);
 133
 28134            if (lastOutput.Value.materials != null)
 135            {
 148136                foreach ( var material in lastOutput.Value.materials )
 137                {
 46138                    Object.Destroy(material);
 139                }
 140            }
 28141        }
 142
 143        /// <summary>
 144        /// Disposes the created mesh, materials, GameObject and Renderer.
 145        /// </summary>
 146        public void Dispose()
 147        {
 3055148            UnloadAssets();
 3055149            Object.Destroy(container);
 3055150        }
 151    }
 152}