private static void CreateMeshForAnimations(Mesh sourceMesh, TEXCOORD boneIdChannel, TEXCOORD boneWeightChannel, int bonesPerVertex, string path)
                    {
                        Mesh mesh = CreateMeshWithExtraData(sourceMesh, boneIdChannel, boneWeightChannel, bonesPerVertex);

                        mesh.UploadMeshData(true);

                        string assetPath = FileUtil.GetProjectRelativePath(path);

                        AssetDatabase.CreateAsset(mesh, assetPath);
                        AssetDatabase.SaveAssets();
                    }
                    private static Mesh CreateMeshWithExtraData(Mesh sourceMesh, TEXCOORD boneIdsUVChanel, TEXCOORD boneWeightsUVChanel, int bonesPerVertex)
                    {
                        Mesh mesh = Instantiate(sourceMesh);

                        //Add bone IDs and weights as texture data
                        {
                            List <Vector4> boneIdsData     = new List <Vector4>();
                            List <Vector4> boneWeightsData = new List <Vector4>();

                            for (int i = 0; i != mesh.vertexCount; ++i)
                            {
                                BoneWeight weight = mesh.boneWeights[i];

                                Vector4 boneIds;

                                boneIds.x = weight.boneIndex0;
                                boneIds.y = weight.boneIndex1;
                                boneIds.z = weight.boneIndex2;
                                boneIds.w = weight.boneIndex3;

                                boneIdsData.Add(boneIds);

                                Vector4 boneWeights;

                                boneWeights.x = weight.weight0;
                                boneWeights.y = weight.weight1;
                                boneWeights.z = weight.weight2;
                                boneWeights.w = weight.weight3;

                                if (bonesPerVertex == 3)
                                {
                                    float rate = 1.0f / (weight.boneIndex0 + weight.boneIndex1 + weight.boneIndex2);
                                    boneWeights.x = boneWeights.x * rate;
                                    boneWeights.y = boneWeights.y * rate;
                                    boneWeights.z = boneWeights.z * rate;
                                    boneWeights.w = -0.1f;
                                }
                                else if (bonesPerVertex == 2)
                                {
                                    float rate = 1.0f / (weight.boneIndex0 + weight.boneIndex1);
                                    boneWeights.x = boneWeights.x * rate;
                                    boneWeights.y = boneWeights.y * rate;
                                    boneWeights.z = -0.1f;
                                    boneWeights.w = -0.1f;
                                }
                                else if (bonesPerVertex == 1)
                                {
                                    boneWeights.x = 1.0f;
                                    boneWeights.y = -0.1f;
                                    boneWeights.z = -0.1f;
                                    boneWeights.w = -0.1f;
                                }

                                boneWeightsData.Add(boneWeights);
                            }

                            mesh.SetUVs((int)boneIdsUVChanel, boneIdsData);
                            mesh.SetUVs((int)boneWeightsUVChanel, boneWeightsData);
                        }

                        return(mesh);
                    }
                    private void OnGUI()
                    {
                        ScriptableObject target = this;
                        SerializedObject so     = new SerializedObject(target);

                        GUI.skin.label.richText = true;
                        GUILayout.BeginHorizontal();
                        {
                            GUILayout.FlexibleSpace();
                        }
                        GUILayout.EndHorizontal();

                        EditorGUILayout.Separator();

                        GUILayout.BeginVertical();
                        {
                            EditorGUILayout.LabelField("Generate GPU Animation Texture", EditorStyles.largeLabel);
                            EditorGUILayout.Separator();

                            GameObject prefab = EditorGUILayout.ObjectField("Asset to Evaluate", _evaluatedObject, typeof(GameObject), true) as GameObject;
                            if (prefab != _evaluatedObject)
                            {
                                _evaluatedObject = prefab;
                                _skinnedMeshes   = prefab != null?prefab.GetComponentsInChildren <SkinnedMeshRenderer>() : new SkinnedMeshRenderer[0];

                                _skinnedMeshIndex = 0;
                                _boneNames        = _skinnedMeshIndex < _skinnedMeshes.Length ? GetBoneNames(_skinnedMeshes[_skinnedMeshIndex]) : null;
                                _exposedBones     = new List <int>();
                                _useAnimator      = prefab != null && GameObjectUtils.GetComponent <Animator>(_evaluatedObject, true) != null;
                            }

                            if (_evaluatedObject != null && _skinnedMeshes != null && _skinnedMeshes.Length > 0)
                            {
                                //Draw Skinned Mesh Popup
                                {
                                    string[] skinnedMeshes = new string[_skinnedMeshes.Length];

                                    for (int i = 0; i < skinnedMeshes.Length; i++)
                                    {
                                        skinnedMeshes[i] = _skinnedMeshes[i].gameObject.name;
                                    }

                                    int skinnedMeshIndex = EditorGUILayout.Popup("Skinned Mesh", _skinnedMeshIndex, skinnedMeshes);

                                    if (skinnedMeshIndex != _skinnedMeshIndex)
                                    {
                                        _skinnedMeshIndex = skinnedMeshIndex;
                                        _boneNames        = GetBoneNames(_skinnedMeshes[_skinnedMeshIndex]);
                                        _exposedBones     = new List <int>();
                                    }
                                }

                                //Draw option for sampling with animator if object has one
                                {
                                    Animator animator = GameObjectUtils.GetComponent <Animator>(_evaluatedObject, true);

                                    if (animator != null)
                                    {
                                        _useAnimator = EditorGUILayout.Toggle("Use Animator", _useAnimator);
                                    }
                                    else
                                    {
                                        _useAnimator = false;
                                    }
                                }

                                //If not usign animator, draw array for animations instead
                                if (!_useAnimator)
                                {
                                    //Draw list showing animation clip,
                                    SerializedProperty animationsProperty = so.FindProperty("_animations");
                                    EditorGUILayout.PropertyField(animationsProperty, true);
                                    so.ApplyModifiedProperties();
                                }

                                //Draw options for Exposed bones
                                EditorGUILayout.BeginHorizontal();
                                {
                                    EditorGUILayout.LabelField(new GUIContent("Exposed Bones"));

                                    string exposedBones = _exposedBones.Count == 0 ? "None" : _boneNames[_exposedBones[0]];

                                    for (int i = 1; i < _exposedBones.Count; i++)
                                    {
                                        exposedBones += ", " + _boneNames[_exposedBones[i]];
                                    }

                                    if (EditorGUILayout.DropdownButton(new GUIContent(exposedBones), FocusType.Keyboard))
                                    {
                                        GenericMenu menu = new GenericMenu();

                                        for (int i = 0; i < _boneNames.Length; i++)
                                        {
                                            menu.AddItem(new GUIContent(_boneNames[i]), _exposedBones.Contains(i), OnClickExposedBone, i);
                                        }

                                        menu.ShowAsContext();
                                    }
                                }
                                EditorGUILayout.EndHorizontal();

                                if (_working)
                                {
                                    EditorGUILayout.LabelField("Generating Animation Texture", EditorStyles.helpBox);
                                }
                                else if (_skinnedMeshes != null && (_useAnimator || (_animations != null && _animations.Length > 0)))
                                {
                                    if (GUILayout.Button("Generate"))
                                    {
                                        string path = EditorUtility.SaveFilePanelInProject("Save Animation Texture", Path.GetFileNameWithoutExtension(""), "bytes", "Please enter a file name to save the animation texture to");

                                        if (!string.IsNullOrEmpty(path))
                                        {
                                            Run(BakeAnimationTexture(path));
                                        }
                                    }
                                }
                            }
                        }
                        GUILayout.EndVertical();

                        EditorGUILayout.Separator();
                        EditorGUILayout.Separator();
                        EditorGUILayout.Separator();

                        GUILayout.BeginVertical();
                        {
                            EditorGUILayout.LabelField("Generate GPU Animated Mesh", EditorStyles.largeLabel);
                            EditorGUILayout.Separator();

                            _mesh = EditorGUILayout.ObjectField("Mesh", _mesh, typeof(Mesh), true) as Mesh;

                            _boneIdChanel      = (TEXCOORD)EditorGUILayout.EnumPopup("Bone IDs UV Channel", _boneIdChanel);
                            _boneWeightChannel = (TEXCOORD)EditorGUILayout.EnumPopup("Bone Weights UV Channel", _boneWeightChannel);
                            _numBonesPerVertex = EditorGUILayout.IntSlider(new GUIContent("Bones Per Vertex"), _numBonesPerVertex, 1, 4);

                            if (_mesh != null)
                            {
                                if (GUILayout.Button("Generate Animated Texture Ready Mesh"))
                                {
                                    string path = EditorUtility.SaveFilePanel("Save Mesh Asset", "Assets/", name, "asset");

                                    if (!string.IsNullOrEmpty(path))
                                    {
                                        CreateMeshForAnimations(_mesh, _boneIdChanel, _boneWeightChannel, _numBonesPerVertex, path);
                                    }
                                }
                            }
                        }
                        GUILayout.EndVertical();
                    }