void DrawPlaybackInspector()
        {
            MeshSequence t = (target as MeshSequencePlayer).meshSequence;

            if (t.FramesCount == 0)
            {
                EditorGUILayout.HelpBox("No frames yet", MessageType.Warning);
                return;
            }

            EditorGUI.BeginChangeCheck();
            EditorGUILayout.PropertyField(prp_playerUpdateMode, s_playerUpdateMode);
            EditorGUILayout.Slider(prp_normalizedTime, 0, 1f, s_normalizedTime);
            EditorGUILayout.PropertyField(prp_clipPlaybackMode, s_clipPlaybackMode);
            if (prp_clipPlaybackMode.enumValueIndex != 3)
            {
                EditorGUI.indentLevel++;
                EditorGUILayout.PropertyField(prp_framesPerSeconds, s_framesPerSeconds);
                EditorGUILayout.PropertyField(prp_useTimescale, s_useTimescale);
                EditorGUI.indentLevel--;
            }
            if (EditorGUI.EndChangeCheck())
            {
                so_player.ApplyModifiedProperties();
            }
        }
        void Import()
        {
            MeshSequencePlayer t  = target as MeshSequencePlayer;
            MeshSequence       ms = t.meshSequence;

            foreach (TaskInfo ti in t.ImportIE(t.meshSequence))
            {
                if (ti.Persentage < 0)
                {
                    EditorUtility.ClearProgressBar();
                    EditorUtility.DisplayDialog(string.Format("Error importing {0}", t.name), ti.Name, "OK", "");
                    return;
                }
                EditorUtility.DisplayProgressBar(string.Format("Importing {0} {1}%", ms.name, (ti.Persentage * 100).ToString("F0")), ti.Name, ti.Persentage);
            }

            List <Object> usedAssets = new List <Object>();

            for (int f = 0; f < ms.FramesCount; f++)
            {
                int vertcesCountBeforeCompression = ms[f].FrameMesh.vertexCount;
                MeshUtility.SetMeshCompression(ms[f].FrameMesh, (ModelImporterMeshCompression)ms.PreImport.MeshCompression);

                if (ms.PreImport.OptimizeMesh)
                {
                    MeshUtility.Optimize(ms[f].FrameMesh);
                }
                int vertcesCountAfterCompression = ms[f].FrameMesh.vertexCount;
                //Debug.LogFormat("Before:{0} after:{1}", vertcesCountBeforeCompression, vertcesCountAfterCompression);
                ms[f].FrameMesh = (Mesh)AddToAsset(ms, ms[f].FrameMesh);
                usedAssets.Add(ms[f].FrameMesh);
            }

            for (int m = 0; m < ms.Materials.Count; m++)
            {
                ms.Materials[m].Mat = (Material)AddToAsset(ms, ms.Materials[m].Mat);
                usedAssets.Add(ms.Materials[m].Mat);
            }


            CleanupAsset(ms, usedAssets);
            EditorUtility.SetDirty(ms);
            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
            CollectProperties();
            EditorUtility.ClearProgressBar();
            string   path  = AssetDatabase.GetAssetPath(ms).Remove(0, 6);
            string   gPath = Application.dataPath + path;
            FileInfo fi    = new FileInfo(gPath);

            ms.AssetFileSize = fi.Length / 1000000f;
            EditorUtility.SetDirty(ms);
            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
            GUIUtility.ExitGUI();
        }
        void UpdateSequenceInfo()
        {
            MeshSequence t = (target as MeshSequencePlayer).meshSequence;

            t.PreImport.MSI = new MeshSequenceInfo(t.PreImport.PathToObj, t.PreImport.FilesSortMode);
            if (t.PreImport.MSI.State == MeshSequenceInfo.StateEnum.Ready)
            {
                SetResentDirectory(t.PreImport.PathToObj);
            }
            if (t.PreImport.MSI.State == MeshSequenceInfo.StateEnum.Empty_path)
            {
                t.PreImport.PathToObj = "Select obj file";
            }
        }
        public override void OnInspectorGUI()
        {
            GUIContent polyVertHeader  = new GUIContent("poly | vert", "polygons and vertcses count of obj file");
            GUIContent trisVertsHeader = new GUIContent("tris | vert", "triangles and vertcses count of Unity Mesh");
            GUIContent submeshHeader   = new GUIContent("submeshes", "Submeshes (Material IDs) count");

            MeshSequence t = target as MeshSequence;

            GUILayout.Label("Mesh Sequence Asset", EditorStyles.boldLabel);

            if (t.FramesCount <= 0)
            {
                EditorGUILayout.HelpBox(" 1) Create player \n 2) Set sources in Import Tab \n 3) Press Import button", MessageType.Info);
            }
            else
            {
                EditorGUI.indentLevel++;
                EditorGUILayout.LabelField(string.Format("Imported {0} frames", t.FramesCount));
                EditorGUILayout.LabelField(string.Format("{0}-{1} vertices", t.SequenceVerticesCount.Min, t.SequenceVerticesCount.Max));
                EditorGUILayout.LabelField(string.Format("{0}-{1} triangles", t.SequenceTrianglesCount.Min, t.SequenceTrianglesCount.Max));
                EditorGUILayout.LabelField(string.Format("{0}-{1} obj vertices", t.SequenceObjVerticesCount.Min, t.SequenceObjVerticesCount.Max));
                EditorGUILayout.LabelField(string.Format("{0}-{1} obj polygons", t.SequenceObjPolygonsCount.Min, t.SequenceObjPolygonsCount.Max));
                EditorGUILayout.LabelField(string.Format("{0}-{1} submeshes", t.SequenceSubmeshesCount.Min, t.SequenceSubmeshesCount.Max));
                GUILayout.Space(4);
                EditorGUILayout.LabelField(string.Format("Directory: {0}", t.PostImport.MSI.DirectoryPath));
                EditorGUILayout.LabelField(string.Format("Sequence: {0} , {1} files", t.PostImport.MSI.SequenceName, t.PostImport.MSI.Count));
                EditorGUILayout.LabelField(string.Format("Imported at: {0}", t.PostImport.ImportDate));
                EditorGUILayout.LabelField(string.Format("Asset file size: {0} MB", t.AssetFileSize.ToString("F4")));

                GUILayout.Space(4);

                ShowDetailedFramesInfo      = EditorGUILayout.Foldout(ShowDetailedFramesInfo, "Show detailed frames info");
                detailedFramesInfoAB.target = ShowDetailedFramesInfo;

                if (EditorGUILayout.BeginFadeGroup(detailedFramesInfoAB.faded))
                {
                    float nameWidth = 50;
                    for (int f = 0; f < t.FramesCount; f++)
                    {
                        nameWidth = Mathf.Max(nameWidth, EditorStyles.label.CalcSize(new GUIContent(t[f].Name)).x);
                    }
                    nameWidth += 4;
                    GUILayout.BeginHorizontal();
                    EditorGUILayout.LabelField("Idx", GUILayout.Width(40));
                    EditorGUILayout.LabelField("obj name", GUILayout.Width(164));
                    EditorGUILayout.LabelField(polyVertHeader, GUILayout.Width(120));
                    EditorGUILayout.LabelField(trisVertsHeader, GUILayout.Width(120));
                    EditorGUILayout.LabelField(submeshHeader, GUILayout.Width(90));
                    GUILayout.EndHorizontal();
                    GUILayout.Space(4);


                    for (int f = 0; f < t.FramesCount; f++)
                    {
                        GUILayout.BeginHorizontal();
                        EditorGUILayout.LabelField(string.Format("#{0}", f.ToString()), GUILayout.Width(50));
                        EditorGUILayout.LabelField(t[f].Name, GUILayout.Width(150));
                        EditorGUILayout.LabelField(string.Format("{0} | {1}", t[f].ObjPolygonsCount, t[f].ObjVerticesCount), GUILayout.Width(120));
                        EditorGUILayout.LabelField(string.Format("{0} | {1}", t[f].MeshTrisCount, t[f].MeshVertsCount), GUILayout.Width(120));
                        EditorGUILayout.LabelField(string.Format("      {0} ", t[f].Materials == null? 0 : t[f].Materials.Length), GUILayout.Width(100));
                        GUILayout.EndHorizontal();
                    }
                }
                EditorGUILayout.EndFadeGroup();
                EditorGUI.indentLevel--;
            }

            GUILayout.Space(4);

            if (GUILayout.Button("Create Mesh Sequence Player"))
            {
                t.SpawnMeshSequencePlayer();
            }
            // DrawDefaultInspector();
        }
        public override void Action(int instanceId, string pathName, string resourceFile)
        {
            MeshSequence data = ObjSequenceFactory.CreateMeshSequenceAtPath(pathName);

            ProjectWindowUtil.ShowCreatedAsset(data);
        }
        public IEnumerable <TaskInfo> ImportIE(MeshSequence t)
        {
            yield return(new TaskInfo("Prepare importing", 0));

            if (ProjectionSamples.Get == null)
            {
                yield return(new TaskInfo("Missing Projection Samples asset. Reinstal Vertex Animation Tools package", -1));

                yield break;
            }

            t.PreImport.MSI = new MeshSequenceInfo(t.PreImport.PathToObj, t.PreImport.FilesSortMode);
            if (t.PreImport.MSI.State != MeshSequenceInfo.StateEnum.Ready)
            {
                yield return(new TaskInfo(t.PreImport.MSI.ShortInfo, -1));
            }

            t.PreImport.VColorSettings.go = gameObject;
            int importFrom       = 0;
            int importTo         = t.PreImport.MSI.Count;
            int totalFramesCount = t.PreImport.MSI.Count;

            if (t.PreImport.ImportCustomRange)
            {
                importFrom       = Mathf.Clamp(t.PreImport.ImportFromFrame, 0, t.PreImport.MSI.Count);
                importTo         = Mathf.Clamp(t.PreImport.ImportToFrame, 0, t.PreImport.MSI.Count);
                totalFramesCount = Mathf.Clamp(importTo - importFrom, 0, int.MaxValue);
            }

            t.SequenceVerticesCount    = new NumbersRange(true);
            t.SequenceObjVerticesCount = new NumbersRange(true);
            t.SequenceTrianglesCount   = new NumbersRange(true);
            t.SequenceObjPolygonsCount = new NumbersRange(true);
            t.SequenceSubmeshesCount   = new NumbersRange(true);

            t.SetMaterialsUnused();
            List <MeshSequence.Frame> nframes = new List <MeshSequence.Frame>();
            int counter = 0;

            for (int f = importFrom; f < importTo; f++)
            {
                string             objName = Path.GetFileNameWithoutExtension(t.PreImport.MSI[f].fi.FullName);
                MeshSequence.Frame frame   = t.GetFrameByName(objName);
                ObjData            od      = new ObjData(t.PreImport.MSI[f].fi.FullName);
                od.NormalsRecalculationMode = t.PreImport.NormalRecalculationMode;
                od.FlipNormals         = t.PreImport.FlipNormals;
                od.SmoothingGroupsMode = t.PreImport.SmoothingGroupImportMode;
                od.ImportUV            = t.PreImport.ImportUV;
                od.CalculateNormals    = t.PreImport.CalculateNormals;
                od.CalculateTangents   = t.PreImport.CalculateTangents;
                #if UNITY_2017_3_OR_NEWER
                od.IndexFormat = t.PreImport.IndexFormat;
                #endif

                od.Build();

                od.Apply(t.PreImport.SwapYZAxis, t.PreImport.ScaleFactor);
                od.CopyTo(frame.FrameMesh);

                if (t.PreImport.GenerateMaterials)
                {
                    frame.Materials = t.GetPolygonalMeshMaterials(od.SubMeshes.GetNames());
                }

                if (od.CalcVertexColor(t.PreImport.VColorSettings))
                {
                    frame.FrameMesh.colors = od.UM_colors;
                }

                frame.MeshTrisCount    = frame.FrameMesh.triangles.Length / 3;
                frame.MeshVertsCount   = frame.FrameMesh.vertexCount;
                frame.ObjVerticesCount = od.Vertices.Count;
                frame.ObjPolygonsCount = od.AllPolygons.Count;

                t.SequenceSubmeshesCount.Set(od.SubMeshes.Count);
                t.SequenceVerticesCount.Set(frame.FrameMesh.vertexCount);
                t.SequenceObjVerticesCount.Set(frame.FrameMesh.triangles.Length / 3);
                t.SequenceTrianglesCount.Set(od.Vertices.Count);
                t.SequenceObjPolygonsCount.Set(od.AllPolygons.Count);

                nframes.Add(frame);

                TaskInfo ti = new TaskInfo(string.Format("Importing frame #{0}", f), counter / (float)totalFramesCount);
                counter++;
                yield return(ti);
            }


            t.PreImport.NormalizedPerFrame = 1f / (float)nframes.Count;
            t.PreImport.ImportDate         = System.DateTime.Now.ToString();
            t.PostImport = t.PreImport;
            t.Frames     = nframes;
            t.ClearUnusedMaterials();
        }
        void CollectProperties()
        {
            so_player            = new SerializedObject(targets);
            prp_clipPlaybackMode = so_player.FindProperty("PlaybackMode");
            prp_playerUpdateMode = so_player.FindProperty("UpdateMode");
            prp_framesPerSeconds = so_player.FindProperty("FramesPerSecond");
            prp_normalizedTime   = so_player.FindProperty("NormalizedTime");
            prp_useTimescale     = so_player.FindProperty("UseTimescale");
            prp_tabChoise        = so_player.FindProperty("TabChoise");
            prp_sequence         = so_player.FindProperty("meshSequence");

            MeshSequence sequence = (target as MeshSequencePlayer).meshSequence;

            if (sequence == null)
            {
                return;
            }

            so_sequence = new SerializedObject(sequence);
            SerializedProperty prp_preImport = so_sequence.FindProperty("PreImport");

            prp_filesSortMode     = prp_preImport.FindPropertyRelative("FilesSortMode");
            prp_importCustomRange = prp_preImport.FindPropertyRelative("ImportCustomRange");
            prp_importFrom        = prp_preImport.FindPropertyRelative("ImportFromFrame");
            prp_importTo          = prp_preImport.FindPropertyRelative("ImportToFrame");

            prp_swapYZAxis  = prp_preImport.FindPropertyRelative("SwapYZAxis");
            prp_pivotOffset = prp_preImport.FindPropertyRelative("PivotOffset");
            prp_scaleFactor = prp_preImport.FindPropertyRelative("ScaleFactor");

            prp_flipNormals = prp_preImport.FindPropertyRelative("FlipNormals");

            prp_importUV          = prp_preImport.FindPropertyRelative("ImportUV");
            prp_calculateNormals  = prp_preImport.FindPropertyRelative("CalculateNormals");
            prp_calculateTangents = prp_preImport.FindPropertyRelative("CalculateTangents");

            prp_smoothingGroupImportMode = prp_preImport.FindPropertyRelative("SmoothingGroupImportMode");
            prp_normalRecalculationMode  = prp_preImport.FindPropertyRelative("NormalRecalculationMode");
            prp_meshCompression          = prp_preImport.FindPropertyRelative("MeshCompression");
            prp_OptimizeMesh             = prp_preImport.FindPropertyRelative("OptimizeMesh");
#if UNITY_2017_3_OR_NEWER
            prp_IndexFormat = prp_preImport.FindPropertyRelative("IndexFormat");
#endif
            prp_generateMaterials = prp_preImport.FindPropertyRelative("GenerateMaterials");

            SerializedProperty prp_VColorSettings = prp_preImport.FindPropertyRelative("VColorSettings");
            prp_cavity               = prp_VColorSettings.FindPropertyRelative("Cavity");
            prp_cavityAmount         = prp_VColorSettings.FindPropertyRelative("CavityAmount");
            prp_cavityAngleMin       = prp_VColorSettings.FindPropertyRelative("CavityAngleMin");
            prp_cavityAngleMax       = prp_VColorSettings.FindPropertyRelative("CavityAngleMax");
            prp_cavityBlur           = prp_VColorSettings.FindPropertyRelative("CavityBlur");
            prp_cavityBlurIterations = prp_VColorSettings.FindPropertyRelative("CavityBlurIterations");

            prp_innerVertexOcclusion               = prp_VColorSettings.FindPropertyRelative("InnerVertexOcclusion");
            prp_innerVertexOcclusionAmount         = prp_VColorSettings.FindPropertyRelative("InnerVertexOcclusionAmount");
            prp_innerVertexOcclusionBlur           = prp_VColorSettings.FindPropertyRelative("InnerVertexOcclusionBlur");
            prp_innerVertexOcclusionBlurIterations = prp_VColorSettings.FindPropertyRelative("InnerVertexOcclusionBlurIterations");

            prp_ambientOcclusion               = prp_VColorSettings.FindPropertyRelative("AmbientOcclusion");
            prp_ambientOcclusionAmount         = prp_VColorSettings.FindPropertyRelative("AmbientOcclusionAmount");
            prp_ambientOcclusionRadius         = prp_VColorSettings.FindPropertyRelative("AmbientOcclusionRadius");
            prp_ambientOcclusionBlur           = prp_VColorSettings.FindPropertyRelative("AmbientOcclusionBlur");
            prp_ambientOcclusionBlurIterations = prp_VColorSettings.FindPropertyRelative("AmbientOcclusionBlurIterations");
            prp_ambientOcclusionQuality        = prp_VColorSettings.FindPropertyRelative("quality");
        }
        void DrawImportInspector()
        {
            MeshSequence t = (target as MeshSequencePlayer).meshSequence;

            so_sequence.Update();
            EditorGUI.BeginChangeCheck();


            GUILayout.Label(".obj sequence:");

            string pathButtonName = string.IsNullOrEmpty(t.PreImport.PathToObj) ? " Select .obj file" : t.PreImport.PathToObj;

            if (GUILayout.Button(pathButtonName))
            {
                t.PreImport.PathToObj = EditorUtility.OpenFilePanelWithFilters("Select point cache", GetResentDirectory(), new string[2] {
                    "OBJ", "obj"
                });
                UpdateSequenceInfo();
            }
            GUILayout.BeginHorizontal();
            if (GUILayout.Button(s_updateSequenceInfo, QuadButtonStyle))
            {
                UpdateSequenceInfo();
            }
            EditorGUILayout.LabelField(t.PreImport.MSI.ShortInfo);
            GUILayout.EndHorizontal();

            EditorGUILayout.PropertyField(prp_filesSortMode, s_filesSortMode);

            prp_importCustomRange.boolValue = EditorGUILayout.Toggle(s_importCustomRange, prp_importCustomRange.boolValue);
            if (prp_importCustomRange.boolValue)
            {
                EditorGUI.indentLevel++;
                prp_importFrom.intValue = EditorGUILayout.IntField("From", prp_importFrom.intValue);
                prp_importTo.intValue   = EditorGUILayout.IntField("To", prp_importTo.intValue);
                EditorGUI.indentLevel--;
            }

            prp_importUV.boolValue         = EditorGUILayout.Toggle(s_importUV, prp_importUV.boolValue);
            prp_calculateNormals.boolValue = EditorGUILayout.Toggle(s_calculateNormals, prp_calculateNormals.boolValue);
            if (prp_calculateNormals.boolValue)
            {
                EditorGUI.indentLevel++;
                EditorGUILayout.PropertyField(prp_smoothingGroupImportMode, new GUIContent("Smoothing groups"));
                EditorGUILayout.PropertyField(prp_normalRecalculationMode, new GUIContent("Normals"));
                EditorGUI.indentLevel--;
            }
            if (prp_calculateNormals.boolValue && prp_importUV.boolValue)
            {
                prp_calculateTangents.boolValue = EditorGUILayout.Toggle(s_calculateTangents, prp_calculateTangents.boolValue);
            }

            EditorGUILayout.PropertyField(prp_flipNormals, s_flipNormals);
            EditorGUILayout.PropertyField(prp_swapYZAxis, s_swapYZAxis);
            EditorGUILayout.PropertyField(prp_pivotOffset, s_pivotOffset);
            EditorGUILayout.PropertyField(prp_scaleFactor, s_scaleFactor);
            EditorGUILayout.PropertyField(prp_generateMaterials, s_generateMaterials);

            EditorGUILayout.IntPopup(prp_meshCompression, MeshCompressionNames, MeshCompressionIndeces, s_meshCompression);
            EditorGUILayout.PropertyField(prp_OptimizeMesh, s_OptimizeMesh);

#if UNITY_2017_3_OR_NEWER
            EditorGUILayout.PropertyField(prp_IndexFormat, s_IndexFormat);
#endif

            bool nbrightIcons = EditorGUILayout.Toggle(s_brightIcons, brightIcons);
            if (nbrightIcons != brightIcons)
            {
                brightIcons = nbrightIcons;
                OnEnable();
            }


            EditorGUILayout.LabelField(s_vertexColor);
            EditorGUI.indentLevel++;
            prp_cavity.boolValue = EditorGUILayout.Toggle(s_cavity, prp_cavity.boolValue);
            if (prp_cavity.boolValue)
            {
                EditorGUI.indentLevel++;
                EditorGUILayout.Slider(prp_cavityAmount, 0, 10f, s_cavityAmount);
                float cavityMin = prp_cavityAngleMin.floatValue;
                float cavityMax = prp_cavityAngleMax.floatValue;
                s_cavityAngles.text = string.Format("Range [{0}-{1}]", cavityMin.ToString("F0"), cavityMax.ToString("F0"));
                EditorGUILayout.MinMaxSlider(s_cavityAngles, ref cavityMin, ref cavityMax, 45, 135f);
                prp_cavityAngleMin.floatValue = cavityMin;
                prp_cavityAngleMax.floatValue = cavityMax;
                EditorGUILayout.Slider(prp_cavityBlur, 0, 1f, s_cavityBlur);
                EditorGUILayout.IntSlider(prp_cavityBlurIterations, 0, 8, s_cavityBlurIterations);
                EditorGUI.indentLevel--;
            }

            prp_innerVertexOcclusion.boolValue = EditorGUILayout.Toggle(s_innerVertexOcclusion, prp_innerVertexOcclusion.boolValue);
            if (prp_innerVertexOcclusion.boolValue)
            {
                EditorGUI.indentLevel++;
                EditorGUILayout.Slider(prp_innerVertexOcclusionAmount, 0, 5f, s_innerVertexOcclusionAmount);
                EditorGUILayout.Slider(prp_innerVertexOcclusionBlur, 0, 5f, s_innerVertexOcclusionBlur);
                EditorGUILayout.IntSlider(prp_innerVertexOcclusionBlurIterations, 0, 8, s_innerVertexOcclusionBlurIterations);
                EditorGUI.indentLevel--;
            }

            prp_ambientOcclusion.boolValue = EditorGUILayout.Toggle(s_ambientOcclusion, prp_ambientOcclusion.boolValue);
            if (prp_ambientOcclusion.boolValue)
            {
                EditorGUI.indentLevel++;
                EditorGUILayout.Slider(prp_ambientOcclusionAmount, 0, 5f, "Amount");
                EditorGUILayout.PropertyField(prp_ambientOcclusionRadius, s_ambientOcclusionRadius);
                bool nEnableAORadiusHandle = EditorGUILayout.Toggle("Radius Handle", EnableAORadiusHandle);
                if (nEnableAORadiusHandle != EnableAORadiusHandle)
                {
                    EnableAORadiusHandle = nEnableAORadiusHandle;
                    SceneView.RepaintAll();
                }
                EditorGUILayout.Slider(prp_ambientOcclusionBlur, 0, 5f, "Blur amount");
                EditorGUILayout.IntSlider(prp_ambientOcclusionBlurIterations, 0, 8, "Blur iterations");
                EditorGUILayout.PropertyField(prp_ambientOcclusionQuality, new GUIContent("Quality"));
                EditorGUI.indentLevel--;
            }
            EditorGUI.indentLevel--;

            if (EditorGUI.EndChangeCheck())
            {
                so_sequence.ApplyModifiedProperties();
            }

            if (GUILayout.Button(t.IsImportSettingsDirty? s_importButtonRequireReimport :  s_importButton))
            {
                Import();
                so_player.ApplyModifiedProperties();
                so_sequence.ApplyModifiedProperties();
            }
        }