private void OnGUI()
        {
            skinnedMeshRoot    = EditorGUILayout.ObjectField($"Root game-object of the skinned-mesh root", skinnedMeshRoot, typeof(GameObject), allowSceneObjects: true) as GameObject;
            boneColorLookup    = EditorGUILayout.ObjectField($"{nameof(BoneColorLookup)}", boneColorLookup, typeof(BoneColorLookup), allowSceneObjects: true) as BoneColorLookup;
            boneIndexUVChannel = EditorGUILayout.IntField($"{nameof(boneIndexUVChannel)}", boneIndexUVChannel);
            textureSize        = EditorGUILayout.IntField($"{nameof(textureSize)}", textureSize);
            meshOutputPath     = EditorGUILayout.TextField($"{nameof(meshOutputPath)}", meshOutputPath);
            textureOutputPath  = EditorGUILayout.TextField($"{nameof(textureOutputPath)}", textureOutputPath);

            if (GUILayout.Button("Export mesh + texture") && skinnedMeshRoot != null)
            {
                Animation           anim = skinnedMeshRoot.GetComponent <Animation>();
                SkinnedMeshRenderer smr  = skinnedMeshRoot.GetComponentInChildren <SkinnedMeshRenderer>(includeInactive: true);
                if (anim != null && anim.clip != null && smr != null && smr.sharedMesh != null)
                {
                    float uniformScale = GetUniformLocalScale(smr.transform); //Get base scale for the mesh (can be non-zero if a fbx export scale is used)

                    CreateAnimationTexture(smr, boneColorLookup, anim.clip, textureSize, uniformScale, textureOutputPath);
                    ExportMeshWithBoneInUV(smr.sharedMesh, boneIndexUVChannel, uniformScale, $"Assets/{meshOutputPath}");
                }
            }
        }
        private static void CreateAnimationTexture(SkinnedMeshRenderer smr, BoneColorLookup bcl, AnimationClip ac, int texSize, float refScale, string outputPath)
        {
            Debug.Log($"Creating animation texture for mesh-renderer: {smr.name}");

            Texture2D texture = new Texture2D(texSize, texSize, TextureFormat.RGBAFloat, mipChain: false, linear: true);

            for (int boneIndex = 0; boneIndex < smr.bones.Length; boneIndex++)
            {
                int startY = boneIndex * 2; //because 2 elements per bone: color and (position, scale)
                for (int x = 0; x < texSize; x++)
                {
                    float prog = x == 0 ? 0 : ((float)x / (texSize - 1));

                    //Get color
                    Color color = bcl == null ? Color.white : bcl.GetColor(smr.bones[boneIndex].name, prog);

                    //Get position
                    ac.SampleAnimation(smr.transform.root.gameObject, prog * ac.length);
                    Vector3 position = smr.bones[boneIndex].localPosition;

                    //Get scale
                    float boneScale     = GetUniformLocalScale(smr.bones[boneIndex]) / refScale;
                    float bindposeScale = GetUniformScale(smr.sharedMesh.bindposes[boneIndex].lossyScale);
                    float scale         = boneScale * bindposeScale;

                    //Save the data in the texture
                    texture.SetPixel(x, startY, color);
                    texture.SetPixel(x, startY + 1, new Color(position.x, position.y, position.z, scale));
                }
            }
            texture.Apply(updateMipmaps: false, makeNoLongerReadable: false);

            byte[] exrData = ImageConversion.EncodeToEXR(texture, Texture2D.EXRFlags.OutputAsFloat);
            File.WriteAllBytes($"{Application.dataPath}/{outputPath}", exrData);
            AssetDatabase.Refresh();
        }