< Summary

Class:AvatarSystem.AvatarSystemUtils
Assembly:AvatarSystem
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarSystemUtils.cs
Covered lines:61
Uncovered lines:51
Coverable lines:112
Total lines:234
Line coverage:54.4% (61 of 112)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
IsCategoryRequired(...)0%110100%
UseAssetBundles()0%220100%
GetFacialFeatureTexturesUrls(...)0%7562700%
CopyBones(...)0%30500%
CopyBones(...)0%12300%
PrepareMaterialColors(...)0%550100%
SplitWearables(...)0%72800%
ExtractBodyshapeParts(...)0%10100100%
FilterHiddenWearables(...)0%20400%
GetActiveBodyParts(...)0%880100%
GetActiveBodyPartsRenderers(...)0%550100%
SpawnAvatarLoadedParticles(...)0%6200%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/AvatarSystem/AvatarSystemUtils.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Linq;
 4using DCL;
 5using DCL.Helpers;
 6using UnityEngine;
 7using Object = UnityEngine.Object;
 8
 9namespace AvatarSystem
 10{
 11    public static class AvatarSystemUtils
 12    {
 13        public const float AVATAR_Y_OFFSET = 0.75f;
 14        private const string AB_FEATURE_FLAG_NAME = "wearable_asset_bundles";
 15
 1216        public static bool IsCategoryRequired(string category) { return WearableLiterals.Categories.REQUIRED_CATEGORIES.
 17
 18        public static bool UseAssetBundles()
 19        {
 820            var featureFlags = DataStore.i.featureFlags.flags.Get();
 821            return featureFlags != null && featureFlags.IsFeatureEnabled(AB_FEATURE_FLAG_NAME);
 22        }
 23
 24        public static (string mainTextureUrl, string maskTextureUrl) GetFacialFeatureTexturesUrls(string bodyshapeId, We
 25        {
 026            if (facialFeature.data.category != WearableLiterals.Categories.EYES && facialFeature.data.category == Wearab
 027                return (null, null);
 28
 029            var representation = facialFeature.GetRepresentation(bodyshapeId);
 030            string mainTextureHash = representation?.contents?.FirstOrDefault(x => x.key == representation?.mainFile)?.h
 031            if (string.IsNullOrEmpty(mainTextureHash))
 032                mainTextureHash = representation?.contents?.FirstOrDefault(x => !x.key.ToLower().Contains("_mask.png"))?
 033            if (string.IsNullOrEmpty(mainTextureHash))
 034                return (null, null);
 35
 036            string maskTextureHash = representation?.contents?.FirstOrDefault(x => x.key.ToLower().Contains("_mask.png")
 37
 038            string mainTextureUrl = facialFeature.baseUrl + mainTextureHash;
 039            string maskTextureUrl = maskTextureHash == null ? null : facialFeature.baseUrl + maskTextureHash;
 40
 041            return (mainTextureUrl, maskTextureUrl);
 42        }
 43
 44        public static void CopyBones(Transform rootBone, Transform[] bones, IEnumerable<SkinnedMeshRenderer> targets)
 45        {
 046            if (rootBone == null || bones == null)
 047                return;
 48
 049            foreach (SkinnedMeshRenderer skinnedMeshRenderer in targets)
 50            {
 051                CopyBones(rootBone, bones, skinnedMeshRenderer);
 52            }
 053        }
 54
 55        public static void CopyBones(Transform rootBone, Transform[] bones, SkinnedMeshRenderer skinnedMeshRenderer)
 56        {
 057            if (rootBone == null || bones == null)
 058                return;
 59
 060            skinnedMeshRenderer.rootBone = rootBone;
 061            skinnedMeshRenderer.bones = bones;
 062        }
 63
 64        public static void PrepareMaterialColors(Rendereable rendereable, Color skinColor, Color hairColor)
 65        {
 8866            foreach (Renderer renderer in rendereable.renderers)
 67            {
 12868                foreach (Material material in renderer.materials)
 69                {
 3270                    if (material.name.ToLower().Contains("skin"))
 771                        material.SetColor(ShaderUtils.BaseColor, skinColor);
 2572                    else if (material.name.ToLower().Contains("hair"))
 573                        material.SetColor(ShaderUtils.BaseColor, hairColor);
 74                }
 75            }
 1276        }
 77
 78        public static (WearableItem bodyshape, WearableItem eyes, WearableItem eyebrows, WearableItem mouth, List<Wearab
 79        {
 080            WearableItem bodyshape = null;
 081            WearableItem eyes = null;
 082            WearableItem eyebrows = null;
 083            WearableItem mouth = null;
 084            List<WearableItem> resultWearables = new List<WearableItem>();
 085            foreach (WearableItem wearable in wearables)
 86            {
 087                switch (wearable.data.category)
 88                {
 89                    case WearableLiterals.Categories.BODY_SHAPE:
 090                        bodyshape = wearable;
 091                        break;
 92                    case WearableLiterals.Categories.EYES:
 093                        eyes = wearable;
 094                        break;
 95                    case WearableLiterals.Categories.EYEBROWS:
 096                        eyebrows = wearable;
 097                        break;
 98                    case WearableLiterals.Categories.MOUTH:
 099                        mouth = wearable;
 0100                        break;
 101                    default:
 0102                        resultWearables.Add(wearable);
 103                        break;
 104                }
 105            }
 106
 0107            return (bodyshape, eyes, eyebrows, mouth, resultWearables);
 108        }
 109
 110        /// <summary>
 111        /// Extract bodyparts of a Rendereable.
 112        ///
 113        /// Using this on a Rendereable that doesn't comes from a bodyshape might result in unexpected result
 114        /// </summary>
 115        /// <param name="rendereable"></param>
 116        /// <returns></returns>
 117        public static (
 118            SkinnedMeshRenderer head,
 119            SkinnedMeshRenderer upperBody,
 120            SkinnedMeshRenderer lowerBody,
 121            SkinnedMeshRenderer feet,
 122            SkinnedMeshRenderer eyes,
 123            SkinnedMeshRenderer eyebrows,
 124            SkinnedMeshRenderer mouth
 125            ) ExtractBodyshapeParts(Rendereable rendereable)
 126        {
 1127            SkinnedMeshRenderer head = null;
 1128            SkinnedMeshRenderer upperBody = null;
 1129            SkinnedMeshRenderer lowerBody = null;
 1130            SkinnedMeshRenderer feet = null;
 1131            SkinnedMeshRenderer eyes = null;
 1132            SkinnedMeshRenderer eyebrows = null;
 1133            SkinnedMeshRenderer mouth = null;
 134
 16135            foreach (Renderer r in rendereable.renderers)
 136            {
 7137                if (!(r is SkinnedMeshRenderer renderer))
 138                    continue;
 139
 7140                string parentName = renderer.transform.parent.name.ToLower();
 141
 7142                if (parentName.Contains("head"))
 1143                    head = renderer;
 6144                else if (parentName.Contains("ubody"))
 1145                    upperBody = renderer;
 5146                else if (parentName.Contains("lbody"))
 1147                    lowerBody = renderer;
 4148                else if (parentName.Contains("feet"))
 1149                    feet = renderer;
 3150                else if (parentName.Contains("eyes"))
 1151                    eyes = renderer;
 2152                else if (parentName.Contains("eyebrows"))
 1153                    eyebrows = renderer;
 1154                else if (parentName.Contains("mouth"))
 1155                    mouth = renderer;
 156            }
 157
 1158            return (head, upperBody, lowerBody, feet, eyes, eyebrows, mouth);
 159        }
 160
 161        /// <summary>
 162        /// Filters hidden wearables.
 163        /// Conflicts will be resolved by order in the array
 164        /// </summary>
 165        /// <param name="bodyshapeId"></param>
 166        /// <param name="wearables"></param>
 167        /// <returns></returns>
 168        public static List<WearableItem> FilterHiddenWearables(string bodyshapeId, IEnumerable<WearableItem> wearables)
 169        {
 0170            HashSet<string> hiddenCategories = new HashSet<string>();
 0171            List<WearableItem> filteredWearables = new List<WearableItem>();
 0172            foreach (WearableItem wearable in wearables)
 173            {
 0174                if (hiddenCategories.Contains(wearable.data.category))
 175                {
 176                    continue;
 177                }
 178
 0179                filteredWearables.Add(wearable);
 0180                hiddenCategories.UnionWith(wearable.GetHidesList(bodyshapeId));
 181            }
 182
 0183            return filteredWearables;
 184        }
 185
 186        public static (bool headVisible, bool upperBodyVisible, bool lowerBodyVisible, bool feetVisible) GetActiveBodyPa
 187        {
 5188            bool headVisible = true;
 5189            bool upperBodyVisible = true;
 5190            bool lowerBodyVisible = true;
 5191            bool feetVisible = true;
 192
 5193            HashSet<string> hiddenList = new HashSet<string>();
 5194            HashSet<string> usedCategories = new HashSet<string>();
 195
 52196            foreach (WearableItem wearable in wearables)
 197            {
 21198                usedCategories.Add(wearable.data.category);
 21199                string[] hiddenByThisWearable = wearable.GetHidesList(bodyshapeId);
 21200                if (hiddenByThisWearable != null)
 21201                    hiddenList.UnionWith(hiddenByThisWearable);
 202            }
 203
 5204            headVisible = !hiddenList.Contains(WearableLiterals.Misc.HEAD) && !usedCategories.Contains(WearableLiterals.
 5205            upperBodyVisible = !hiddenList.Contains(WearableLiterals.Categories.UPPER_BODY) && !usedCategories.Contains(
 5206            lowerBodyVisible = !hiddenList.Contains(WearableLiterals.Categories.LOWER_BODY) && !usedCategories.Contains(
 5207            feetVisible = !hiddenList.Contains(WearableLiterals.Categories.FEET) && !usedCategories.Contains(WearableLit
 5208            return (headVisible, upperBodyVisible, lowerBodyVisible, feetVisible);
 209        }
 210
 211        public static List<SkinnedMeshRenderer> GetActiveBodyPartsRenderers(IBodyshapeLoader bodyshapeLoader, bool headV
 212        {
 5213            List<SkinnedMeshRenderer> result = new List<SkinnedMeshRenderer>();
 5214            if (headVisible)
 4215                result.Add(bodyshapeLoader.headRenderer);
 5216            if (upperBodyVisible)
 1217                result.Add(bodyshapeLoader.upperBodyRenderer);
 5218            if (lowerBodyVisible)
 1219                result.Add(bodyshapeLoader.lowerBodyRenderer);
 5220            if (feetVisible)
 1221                result.Add(bodyshapeLoader.feetRenderer);
 5222            return result;
 223        }
 224
 225        public static void SpawnAvatarLoadedParticles(Transform avatarContainer, GameObject particlePrefab)
 226        {
 0227            if (!particlePrefab.TryGetComponent(out DestroyParticlesOnFinish selfDestroyScript))
 0228                throw new Exception("A self destructive particles prefab is expected");
 229
 0230            GameObject particles = Object.Instantiate(particlePrefab);
 0231            particles.transform.position = avatarContainer.position + particlePrefab.transform.position;
 0232        }
 233    }
 234}