< Summary

Class:MainScripts.DCL.Components.Avatar.VRMExporter.VRMExporter
Assembly:AvatarShape
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Avatar/VRMExporter/VRMExporter.cs
Covered lines:0
Uncovered lines:75
Coverable lines:75
Total lines:165
Line coverage:0% (0 of 75)
Covered branches:0
Total branches:0
Covered methods:0
Total methods:6
Method coverage:0% (0 of 6)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
ExportingState()0%2100%
Dispose()0%6200%
VRMExporter(...)0%2100%
Export(...)0%20400%
AddWearableToExport(...)0%42600%
ConvertMaterials(...)0%30500%

File(s)

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

#LineLine coverage
 1using Cysharp.Threading.Tasks;
 2using DCL.Helpers;
 3using System;
 4using System.Collections.Generic;
 5using System.IO;
 6using System.Linq;
 7using System.Threading;
 8using UnityEngine;
 9using VRM;
 10using VRMShaders;
 11using Object = UnityEngine.Object;
 12
 13namespace MainScripts.DCL.Components.Avatar.VRMExporter
 14{
 15    public interface IVRMExporter
 16    {
 17        UniTask<byte[]> Export(string name, string reference, IEnumerable<SkinnedMeshRenderer> wearables, CancellationTo
 18    }
 19
 20    public class VRMExporter : IVRMExporter
 21    {
 22        internal class ExportingState : IDisposable
 23        {
 024            public readonly List<Object> objects = new ();
 25
 26            public void Dispose()
 27            {
 028                foreach (Object obj in objects) { Object.Destroy(obj); }
 29
 030                objects.Clear();
 031            }
 32        }
 33
 34        private readonly VRMExporterReferences vrmExporterReferences;
 35        private readonly IReadOnlyDictionary<string, Transform> toExportBones;
 036        private readonly ExportingState exportingState = new ();
 037        private readonly UniGLTF.GltfExportSettings settings = new ();
 038        private readonly RuntimeTextureSerializer textureSerializer = new ();
 39
 040        public VRMExporter(VRMExporterReferences vrmExporterReferences)
 41        {
 042            this.vrmExporterReferences = vrmExporterReferences;
 043            toExportBones = VRMExporterUtils.CacheFBXBones(vrmExporterReferences.bonesRoot);
 044            vrmExporterReferences.metaObject.Version = "1.0, UniVRM v0.112.0";
 045        }
 46
 47        public UniTask<byte[]> Export(string name, string reference, IEnumerable<SkinnedMeshRenderer> wearables, Cancell
 48        {
 049            exportingState.Dispose();
 50
 051            using var _ = exportingState;
 52
 53            // Adding new wearables
 054            foreach (SkinnedMeshRenderer wearable in wearables)
 055                AddWearableToExport(wearable);
 56
 057            vrmExporterReferences.metaObject.Author = name;
 058            vrmExporterReferences.metaObject.Reference = reference;
 59
 60            // Normalize Bones
 061            GameObject toExportNormalized = VRMBoneNormalizer.Execute(vrmExporterReferences.toExport, true);
 062            exportingState.objects.Add(toExportNormalized);
 063            var vrmNormalized = VRM.VRMExporter.Export(settings, toExportNormalized, textureSerializer);
 64
 065            return new UniTask<byte[]>(vrmNormalized.ToGlbBytes());
 066        }
 67
 68        private void AddWearableToExport(SkinnedMeshRenderer wearable)
 69        {
 070            if (wearable == null)
 071                return;
 72
 73            bool TryGetFbxBone(Transform originalBone, out Transform fbxBone)
 74            {
 075                fbxBone = null;
 76
 077                if (!vrmExporterReferences.vrmbonesMapping.TryGetFBXBone(originalBone.name, out string fbxName))
 78                {
 079                    Debug.Log($"Couldnt find a mapping for bone {originalBone.name}");
 080                    return false;
 81                }
 82
 083                if (!toExportBones.TryGetValue(fbxName, out Transform fbxTransform))
 84                {
 085                    Debug.Log($"Couldnt find a bone with name {fbxName}");
 086                    return false;
 87                }
 88
 089                fbxBone = fbxTransform;
 090                return true;
 91            }
 92
 093            var holder = new GameObject(wearable.name);
 094            holder.transform.parent = vrmExporterReferences.meshesContainer;
 095            holder.transform.ResetLocalTRS();
 096            exportingState.objects.Add(holder);
 97
 098            var copiedWearable = VRMExporterUtils.CloneSmr(holder, wearable);
 099            copiedWearable.materials = ConvertMaterials(wearable.materials, vrmExporterReferences.vrmToonMaterial, vrmEx
 100
 0101            Transform[] originalBones = wearable.bones;
 0102            Transform[] newBones = new Transform[originalBones.Length];
 103
 0104            for (var i = 0; i < originalBones.Length; i++)
 105            {
 0106                Transform originalBone = originalBones[i];
 107
 0108                if (TryGetFbxBone(originalBone, out var fbxBone))
 109                {
 0110                    if (fbxBone == null)
 111                    {
 0112                        Debug.LogError($"Couldnt find a bone with name {originalBone.name} for mesh {wearable.sharedMesh
 0113                        continue;
 114                    }
 0115                    newBones[i] = fbxBone;}
 116            }
 117
 0118            copiedWearable.bones = newBones;
 119
 0120            if (TryGetFbxBone(wearable.rootBone, out var rootBone))
 0121                copiedWearable.rootBone = rootBone;
 0122        }
 123
 124        private Material[] ConvertMaterials(Material[] materials, Material toonMaterial, Material unlitMaterial)
 125        {
 0126            Material[] outputMaterial = new Material[materials.Length];
 127
 0128            for (var i = 0; i < materials.Length; i++)
 129            {
 0130                var material = materials[i];
 131
 0132                switch (material.shader.name)
 133                {
 134                    case "DCL/Eyes Shader":
 135                    {
 0136                        outputMaterial[i] = new Material(unlitMaterial);
 0137                        exportingState.objects.Add(outputMaterial[i]);
 0138                        var texture = VRMExporterUtils.ExtractComposedEyesTexture(material);
 0139                        exportingState.objects.Add(texture);
 0140                        VRMExporterUtils.ConvertEyesMaterial(material, texture, outputMaterial[i]);
 0141                        break;
 142                    }
 143                    case "DCL/Unlit Cutout Tinted":
 144                    {
 0145                        outputMaterial[i] = new Material(unlitMaterial);
 0146                        exportingState.objects.Add(outputMaterial[i]);
 0147                        var texture = VRMExporterUtils.ExtractComposedBaseMapTexture(material);
 0148                        exportingState.objects.Add(texture);
 0149                        VRMExporterUtils.ConvertEyesMaterial(material, texture, outputMaterial[i]);
 0150                        break;
 151                    }
 152                    case "DCL/Universal Render Pipeline/Lit":
 0153                        outputMaterial[i] = new Material(toonMaterial);
 0154                        exportingState.objects.Add(outputMaterial[i]);
 0155                        VRMExporterUtils.ConvertLitMaterial(material, outputMaterial[i]);
 0156                        break;
 157                    default:
 0158                        throw new Exception($"Material {material.name} with shader {material.shader.name} is not support
 159                }
 160            }
 161
 0162            return outputMaterial;
 163        }
 164    }
 165}