MeshSequencePlayerInspector.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEditor;
  5. using System.IO;
  6. namespace VertexAnimationTools_30{
  7. [CanEditMultipleObjects]
  8. [CustomEditor(typeof(MeshSequencePlayer) )]
  9. public sealed class MeshSequencePlayerInspector : InspectorsBase {
  10. #region PLAYBACK_PROPERTIES
  11. public SerializedObject so_player;
  12. GUIContent s_sequence = new GUIContent("Mesh Sequence", "Shared Mesh Sequence asset");
  13. public SerializedProperty prp_sequence;
  14. GUIContent s_framesPerSeconds = new GUIContent("Frames per second", "Auto playback speed in frames per seconds");
  15. public SerializedProperty prp_framesPerSeconds;
  16. public SerializedProperty prp_tabChoise;
  17. #endregion
  18. #region IMPORT_PROPERTIES
  19. static bool EnableAORadiusHandle;
  20. SerializedObject so_sequence;
  21. GUIContent s_updateSequenceInfo;
  22. GUIContent s_importUV = new GUIContent("Enable UV", "Determines whether or not the UV coodinates should be imported (if exist) and applied to mesh. Must be enabled if shader use textures.");
  23. SerializedProperty prp_importUV;
  24. GUIContent s_calculateNormals = new GUIContent("Calculate normals", "When on, calculates mesh normals. Must be enabled for lit shaders");
  25. SerializedProperty prp_calculateNormals;
  26. GUIContent s_calculateTangents = new GUIContent("Calculate tangents", "When on, calculates mesh tangents. Tangents is required for normal-mapped shaders");
  27. SerializedProperty prp_calculateTangents;
  28. GUIContent s_vertexColor = new GUIContent("Vertex color settings", "Generate a per vertex colors based on mesh surface. Not requared texture maps and UV attributes. Note that vertex color displaying requare shader that utilize it. There is simple vertex color shaders at 'custom/pc2unity'");
  29. GUIContent s_cavity = new GUIContent("Cavity", "Generate a per vertex grayscale color alpha value that displays how convex or concave the surface of an mesh is at given point. The more concave the surface is the darker the vertex will be.");
  30. SerializedProperty prp_cavity;
  31. GUIContent s_cavityAngles = new GUIContent("Angles", "Determines how minimal concavity and maximal convexity angles in degrees is used to generate cavity effect");
  32. SerializedProperty prp_cavityAngleMin;
  33. SerializedProperty prp_cavityAngleMax;
  34. GUIContent s_cavityAmount = new GUIContent("Amount", "Amount of cavity effect to use. At 1.0 cavity has its greatest effect; at 0 the cavity not visible at all");
  35. SerializedProperty prp_cavityAmount;
  36. GUIContent s_cavityBlur = new GUIContent("Blur Amount", "Determine how cavity effect is blurred or how it softened");
  37. SerializedProperty prp_cavityBlur;
  38. GUIContent s_cavityBlurIterations = new GUIContent("Blur iterations", "Sets the number of calculations used to blur cavity. More iterations leads to cavity affects more adjacent vertices.");
  39. SerializedProperty prp_cavityBlurIterations;
  40. GUIContent s_innerVertexOcclusion = new GUIContent("Inner Vertex Occlusion", "Generate a per vertex grayscale color alpha value that displays vertices within the mesh volume.");
  41. SerializedProperty prp_innerVertexOcclusion;
  42. GUIContent s_innerVertexOcclusionAmount = new GUIContent("Amount", "Amount of inner vertex occlusion effect to use ");
  43. SerializedProperty prp_innerVertexOcclusionAmount;
  44. GUIContent s_innerVertexOcclusionBlur = new GUIContent("Blur Amount", "Determine how Inner Vertex Occlusion effect is blurred or how it softened");
  45. SerializedProperty prp_innerVertexOcclusionBlur;
  46. GUIContent s_innerVertexOcclusionBlurIterations = new GUIContent("Blur iterations", "Sets the number of calculations used to blur Inner Vertex Occlusion effect. More iterations leads to Inner Vertex Occlusion affects more adjacent vertices.");
  47. SerializedProperty prp_innerVertexOcclusionBlurIterations;
  48. GUIContent s_ambientOcclusion = new GUIContent("Ambient Occlusion", "Ambient Occlusion is an per vertex effect for emulating the look of true global illumination by using method that calculate the extend to wich area is occluded, or prevented from receiving incoming light");
  49. SerializedProperty prp_ambientOcclusion;
  50. SerializedProperty prp_ambientOcclusionAmount;
  51. GUIContent s_ambientOcclusionRadius = new GUIContent("Radius", "Ambient Occlusion Radius defines the maximum distance within which looking for occluding surfaces. Smaller values restrict the AO effect.");
  52. SerializedProperty prp_ambientOcclusionRadius;
  53. SerializedProperty prp_ambientOcclusionBlur;
  54. SerializedProperty prp_ambientOcclusionBlurIterations;
  55. SerializedProperty prp_ambientOcclusionQuality;
  56. #endregion
  57. void CollectProperties(){
  58. so_player = new SerializedObject(targets);
  59. prp_clipPlaybackMode = so_player.FindProperty("PlaybackMode");
  60. prp_playerUpdateMode = so_player.FindProperty("UpdateMode");
  61. prp_framesPerSeconds = so_player.FindProperty("FramesPerSecond");
  62. prp_normalizedTime = so_player.FindProperty("NormalizedTime");
  63. prp_useTimescale = so_player.FindProperty("UseTimescale");
  64. prp_tabChoise = so_player.FindProperty("TabChoise");
  65. prp_sequence = so_player.FindProperty("meshSequence");
  66. MeshSequence sequence = (target as MeshSequencePlayer).meshSequence;
  67. if(sequence == null){
  68. return;
  69. }
  70. so_sequence = new SerializedObject( sequence );
  71. SerializedProperty prp_preImport = so_sequence.FindProperty( "PreImport" );
  72. prp_filesSortMode = prp_preImport.FindPropertyRelative("FilesSortMode");
  73. prp_importCustomRange = prp_preImport.FindPropertyRelative("ImportCustomRange");
  74. prp_importFrom = prp_preImport.FindPropertyRelative("ImportFromFrame");
  75. prp_importTo = prp_preImport.FindPropertyRelative("ImportToFrame");
  76. prp_swapYZAxis = prp_preImport.FindPropertyRelative("SwapYZAxis");
  77. prp_pivotOffset = prp_preImport.FindPropertyRelative("PivotOffset");
  78. prp_scaleFactor = prp_preImport.FindPropertyRelative("ScaleFactor");
  79. prp_flipNormals = prp_preImport.FindPropertyRelative("FlipNormals");
  80. prp_importUV = prp_preImport.FindPropertyRelative("ImportUV");
  81. prp_calculateNormals = prp_preImport.FindPropertyRelative("CalculateNormals");
  82. prp_calculateTangents = prp_preImport.FindPropertyRelative("CalculateTangents");
  83. prp_smoothingGroupImportMode = prp_preImport.FindPropertyRelative("SmoothingGroupImportMode");
  84. prp_normalRecalculationMode = prp_preImport.FindPropertyRelative("NormalRecalculationMode");
  85. prp_meshCompression = prp_preImport.FindPropertyRelative("MeshCompression");
  86. prp_OptimizeMesh = prp_preImport.FindPropertyRelative("OptimizeMesh");
  87. #if UNITY_2017_3_OR_NEWER
  88. prp_IndexFormat = prp_preImport.FindPropertyRelative("IndexFormat");
  89. #endif
  90. prp_generateMaterials = prp_preImport.FindPropertyRelative("GenerateMaterials");
  91. SerializedProperty prp_VColorSettings = prp_preImport.FindPropertyRelative("VColorSettings");
  92. prp_cavity = prp_VColorSettings.FindPropertyRelative("Cavity");
  93. prp_cavityAmount = prp_VColorSettings.FindPropertyRelative("CavityAmount");
  94. prp_cavityAngleMin = prp_VColorSettings.FindPropertyRelative("CavityAngleMin");
  95. prp_cavityAngleMax = prp_VColorSettings.FindPropertyRelative("CavityAngleMax");
  96. prp_cavityBlur = prp_VColorSettings.FindPropertyRelative("CavityBlur");
  97. prp_cavityBlurIterations = prp_VColorSettings.FindPropertyRelative("CavityBlurIterations");
  98. prp_innerVertexOcclusion = prp_VColorSettings.FindPropertyRelative("InnerVertexOcclusion");
  99. prp_innerVertexOcclusionAmount = prp_VColorSettings.FindPropertyRelative("InnerVertexOcclusionAmount");
  100. prp_innerVertexOcclusionBlur = prp_VColorSettings.FindPropertyRelative("InnerVertexOcclusionBlur");
  101. prp_innerVertexOcclusionBlurIterations = prp_VColorSettings.FindPropertyRelative("InnerVertexOcclusionBlurIterations");
  102. prp_ambientOcclusion = prp_VColorSettings.FindPropertyRelative("AmbientOcclusion");
  103. prp_ambientOcclusionAmount = prp_VColorSettings.FindPropertyRelative("AmbientOcclusionAmount");
  104. prp_ambientOcclusionRadius = prp_VColorSettings.FindPropertyRelative("AmbientOcclusionRadius");
  105. prp_ambientOcclusionBlur = prp_VColorSettings.FindPropertyRelative("AmbientOcclusionBlur");
  106. prp_ambientOcclusionBlurIterations = prp_VColorSettings.FindPropertyRelative("AmbientOcclusionBlurIterations");
  107. prp_ambientOcclusionQuality = prp_VColorSettings.FindPropertyRelative("quality");
  108. }
  109. void OnEnable(){
  110. s_updateSequenceInfo = new GUIContent( RefreshButtonTexture, "Update source info");
  111. OnEnableBase();
  112. CollectProperties();
  113. }
  114. public override void OnInspectorGUI (){
  115. EditorGUI.showMixedValue = so_player.isEditingMultipleObjects;
  116. so_player.Update();
  117. EditorGUI.BeginChangeCheck();
  118. prp_sequence.objectReferenceValue = (MeshSequence)EditorGUILayout.ObjectField(s_sequence, prp_sequence.objectReferenceValue, typeof(MeshSequence), false );
  119. if(EditorGUI.EndChangeCheck()){
  120. so_player.ApplyModifiedProperties();
  121. CollectProperties();
  122. }
  123. if(prp_sequence.objectReferenceValue == null){
  124. EditorGUILayout.HelpBox( "Select mesh sequence asset", MessageType.Warning);
  125. return;
  126. }
  127. EditorGUI.showMixedValue = so_sequence.isEditingMultipleObjects;
  128. EditorGUI.BeginChangeCheck();
  129. prp_tabChoise.intValue = GUILayout.Toolbar(prp_tabChoise.intValue, new string[2]{"Playback", "Import"});
  130. if(EditorGUI.EndChangeCheck()){
  131. so_player.ApplyModifiedProperties();
  132. }
  133. if(prp_tabChoise.intValue == 0){
  134. DrawPlaybackInspector();
  135. } else if (prp_tabChoise.intValue == 1) {
  136. DrawImportInspector();
  137. }
  138. }
  139. void DrawPlaybackInspector (){
  140. MeshSequence t = (target as MeshSequencePlayer).meshSequence;
  141. if (t.FramesCount == 0) {
  142. EditorGUILayout.HelpBox("No frames yet", MessageType.Warning);
  143. return;
  144. }
  145. EditorGUI.BeginChangeCheck();
  146. EditorGUILayout.PropertyField(prp_playerUpdateMode, s_playerUpdateMode);
  147. EditorGUILayout.Slider( prp_normalizedTime, 0, 1f, s_normalizedTime);
  148. EditorGUILayout.PropertyField( prp_clipPlaybackMode, s_clipPlaybackMode );
  149. if(prp_clipPlaybackMode.enumValueIndex != 3){
  150. EditorGUI.indentLevel ++;
  151. EditorGUILayout.PropertyField(prp_framesPerSeconds, s_framesPerSeconds);
  152. EditorGUILayout.PropertyField(prp_useTimescale, s_useTimescale);
  153. EditorGUI.indentLevel --;
  154. }
  155. if( EditorGUI.EndChangeCheck()){
  156. so_player.ApplyModifiedProperties();
  157. }
  158. }
  159. void UpdateSequenceInfo() {
  160. MeshSequence t = (target as MeshSequencePlayer).meshSequence;
  161. t.PreImport.MSI = new MeshSequenceInfo(t.PreImport.PathToObj, t.PreImport.FilesSortMode );
  162. if (t.PreImport.MSI.State == MeshSequenceInfo.StateEnum.Ready) {
  163. SetResentDirectory(t.PreImport.PathToObj);
  164. }
  165. if (t.PreImport.MSI.State == MeshSequenceInfo.StateEnum.Empty_path) {
  166. t.PreImport.PathToObj = "Select obj file";
  167. }
  168. }
  169. void DrawImportInspector(){
  170. MeshSequence t = (target as MeshSequencePlayer).meshSequence;
  171. so_sequence.Update();
  172. EditorGUI.BeginChangeCheck();
  173. GUILayout.Label(".obj sequence:");
  174. string pathButtonName = string.IsNullOrEmpty(t.PreImport.PathToObj) ? " Select .obj file" : t.PreImport.PathToObj;
  175. if (GUILayout.Button( pathButtonName )) {
  176. t.PreImport.PathToObj = EditorUtility.OpenFilePanelWithFilters("Select point cache", GetResentDirectory(), new string[2] { "OBJ", "obj" });
  177. UpdateSequenceInfo();
  178. }
  179. GUILayout.BeginHorizontal();
  180. if (GUILayout.Button(s_updateSequenceInfo, QuadButtonStyle)) {
  181. UpdateSequenceInfo();
  182. }
  183. EditorGUILayout.LabelField( t.PreImport.MSI.ShortInfo);
  184. GUILayout.EndHorizontal();
  185. EditorGUILayout.PropertyField(prp_filesSortMode, s_filesSortMode);
  186. prp_importCustomRange.boolValue = EditorGUILayout.Toggle(s_importCustomRange, prp_importCustomRange.boolValue);
  187. if(prp_importCustomRange.boolValue){
  188. EditorGUI.indentLevel ++;
  189. prp_importFrom.intValue = EditorGUILayout.IntField( "From", prp_importFrom.intValue );
  190. prp_importTo.intValue = EditorGUILayout.IntField( "To", prp_importTo.intValue );
  191. EditorGUI.indentLevel --;
  192. }
  193. prp_importUV.boolValue = EditorGUILayout.Toggle(s_importUV, prp_importUV.boolValue);
  194. prp_calculateNormals.boolValue = EditorGUILayout.Toggle(s_calculateNormals, prp_calculateNormals.boolValue);
  195. if(prp_calculateNormals.boolValue){
  196. EditorGUI.indentLevel ++;
  197. EditorGUILayout.PropertyField( prp_smoothingGroupImportMode, new GUIContent( "Smoothing groups" ) );
  198. EditorGUILayout.PropertyField( prp_normalRecalculationMode, new GUIContent( "Normals") );
  199. EditorGUI.indentLevel --;
  200. }
  201. if(prp_calculateNormals.boolValue && prp_importUV.boolValue ){
  202. prp_calculateTangents.boolValue = EditorGUILayout.Toggle(s_calculateTangents, prp_calculateTangents.boolValue);
  203. }
  204. EditorGUILayout.PropertyField(prp_flipNormals, s_flipNormals );
  205. EditorGUILayout.PropertyField(prp_swapYZAxis, s_swapYZAxis);
  206. EditorGUILayout.PropertyField(prp_pivotOffset, s_pivotOffset);
  207. EditorGUILayout.PropertyField(prp_scaleFactor, s_scaleFactor);
  208. EditorGUILayout.PropertyField(prp_generateMaterials, s_generateMaterials);
  209. EditorGUILayout.IntPopup( prp_meshCompression, MeshCompressionNames, MeshCompressionIndeces, s_meshCompression );
  210. EditorGUILayout.PropertyField(prp_OptimizeMesh, s_OptimizeMesh);
  211. #if UNITY_2017_3_OR_NEWER
  212. EditorGUILayout.PropertyField(prp_IndexFormat, s_IndexFormat);
  213. #endif
  214. bool nbrightIcons = EditorGUILayout.Toggle(s_brightIcons, brightIcons);
  215. if (nbrightIcons != brightIcons) {
  216. brightIcons = nbrightIcons;
  217. OnEnable();
  218. }
  219. EditorGUILayout.LabelField(s_vertexColor);
  220. EditorGUI.indentLevel ++;
  221. prp_cavity.boolValue = EditorGUILayout.Toggle(s_cavity, prp_cavity.boolValue);
  222. if(prp_cavity.boolValue){
  223. EditorGUI.indentLevel ++;
  224. EditorGUILayout.Slider( prp_cavityAmount, 0, 10f, s_cavityAmount );
  225. float cavityMin = prp_cavityAngleMin.floatValue;
  226. float cavityMax = prp_cavityAngleMax.floatValue;
  227. s_cavityAngles.text = string.Format("Range [{0}-{1}]",cavityMin.ToString("F0") , cavityMax.ToString("F0"));
  228. EditorGUILayout.MinMaxSlider( s_cavityAngles, ref cavityMin, ref cavityMax, 45, 135f );
  229. prp_cavityAngleMin.floatValue = cavityMin;
  230. prp_cavityAngleMax.floatValue = cavityMax;
  231. EditorGUILayout.Slider( prp_cavityBlur, 0, 1f, s_cavityBlur );
  232. EditorGUILayout.IntSlider( prp_cavityBlurIterations, 0, 8, s_cavityBlurIterations);
  233. EditorGUI.indentLevel --;
  234. }
  235. prp_innerVertexOcclusion.boolValue = EditorGUILayout.Toggle(s_innerVertexOcclusion, prp_innerVertexOcclusion.boolValue);
  236. if(prp_innerVertexOcclusion.boolValue){
  237. EditorGUI.indentLevel ++;
  238. EditorGUILayout.Slider( prp_innerVertexOcclusionAmount, 0, 5f, s_innerVertexOcclusionAmount);
  239. EditorGUILayout.Slider( prp_innerVertexOcclusionBlur, 0, 5f, s_innerVertexOcclusionBlur);
  240. EditorGUILayout.IntSlider( prp_innerVertexOcclusionBlurIterations, 0, 8, s_innerVertexOcclusionBlurIterations);
  241. EditorGUI.indentLevel --;
  242. }
  243. prp_ambientOcclusion.boolValue = EditorGUILayout.Toggle(s_ambientOcclusion, prp_ambientOcclusion.boolValue);
  244. if(prp_ambientOcclusion.boolValue){
  245. EditorGUI.indentLevel ++;
  246. EditorGUILayout.Slider( prp_ambientOcclusionAmount, 0, 5f, "Amount");
  247. EditorGUILayout.PropertyField( prp_ambientOcclusionRadius, s_ambientOcclusionRadius );
  248. bool nEnableAORadiusHandle = EditorGUILayout.Toggle( "Radius Handle", EnableAORadiusHandle );
  249. if(nEnableAORadiusHandle != EnableAORadiusHandle){
  250. EnableAORadiusHandle = nEnableAORadiusHandle;
  251. SceneView.RepaintAll();
  252. }
  253. EditorGUILayout.Slider( prp_ambientOcclusionBlur, 0, 5f, "Blur amount");
  254. EditorGUILayout.IntSlider( prp_ambientOcclusionBlurIterations, 0, 8, "Blur iterations");
  255. EditorGUILayout.PropertyField( prp_ambientOcclusionQuality, new GUIContent("Quality") );
  256. EditorGUI.indentLevel --;
  257. }
  258. EditorGUI.indentLevel --;
  259. if( EditorGUI.EndChangeCheck()){
  260. so_sequence.ApplyModifiedProperties();
  261. }
  262. if (GUILayout.Button(t.IsImportSettingsDirty? s_importButtonRequireReimport : s_importButton)){
  263. Import();
  264. so_player.ApplyModifiedProperties();
  265. so_sequence.ApplyModifiedProperties();
  266. }
  267. }
  268. void OnSceneGUI(){
  269. MeshSequencePlayer t = target as MeshSequencePlayer;
  270. if (t.meshSequence != null && EnableAORadiusHandle) {
  271. Tools.hidden = true;
  272. Handles.color = Color.red;
  273. float scale = t.transform.localScale.magnitude;
  274. float nradius = Handles.RadiusHandle(Quaternion.identity, t.transform.position, t.meshSequence.PreImport.VColorSettings.AmbientOcclusionRadius * scale);
  275. if (nradius != t.meshSequence.PreImport.VColorSettings.AmbientOcclusionRadius) {
  276. t.meshSequence.PreImport.VColorSettings.AmbientOcclusionRadius = nradius / scale;
  277. Repaint();
  278. }
  279. } else {
  280. Tools.hidden = false;
  281. }
  282. }
  283. void Import() {
  284. MeshSequencePlayer t = target as MeshSequencePlayer;
  285. MeshSequence ms = t.meshSequence;
  286. foreach (TaskInfo ti in t.ImportIE(t.meshSequence)) {
  287. if (ti.Persentage < 0) {
  288. EditorUtility.ClearProgressBar();
  289. EditorUtility.DisplayDialog( string.Format( "Error importing {0}", t.name), ti.Name, "OK", "");
  290. return;
  291. }
  292. EditorUtility.DisplayProgressBar(string.Format("Importing {0} {1}%", ms.name, (ti.Persentage * 100).ToString("F0")), ti.Name, ti.Persentage);
  293. }
  294. List<Object> usedAssets = new List<Object>();
  295. for (int f = 0; f<ms.FramesCount; f++) {
  296. int vertcesCountBeforeCompression = ms[f].FrameMesh.vertexCount;
  297. MeshUtility.SetMeshCompression(ms[f].FrameMesh, (ModelImporterMeshCompression)ms.PreImport.MeshCompression);
  298. if (ms.PreImport.OptimizeMesh) {
  299. MeshUtility.Optimize(ms[f].FrameMesh);
  300. }
  301. int vertcesCountAfterCompression = ms[f].FrameMesh.vertexCount;
  302. //Debug.LogFormat("Before:{0} after:{1}", vertcesCountBeforeCompression, vertcesCountAfterCompression);
  303. ms[f].FrameMesh = (Mesh)AddToAsset(ms, ms[f].FrameMesh);
  304. usedAssets.Add( ms[f].FrameMesh );
  305. }
  306. for (int m = 0; m<ms.Materials.Count; m++) {
  307. ms.Materials[m].Mat = (Material)AddToAsset(ms, ms.Materials[m].Mat);
  308. usedAssets.Add(ms.Materials[m].Mat);
  309. }
  310. CleanupAsset(ms, usedAssets);
  311. EditorUtility.SetDirty(ms);
  312. AssetDatabase.SaveAssets();
  313. AssetDatabase.Refresh();
  314. CollectProperties();
  315. EditorUtility.ClearProgressBar();
  316. string path = AssetDatabase.GetAssetPath(ms).Remove(0,6);
  317. string gPath = Application.dataPath + path;
  318. FileInfo fi = new FileInfo(gPath);
  319. ms.AssetFileSize = fi.Length / 1000000f;
  320. EditorUtility.SetDirty(ms);
  321. AssetDatabase.SaveAssets();
  322. AssetDatabase.Refresh();
  323. GUIUtility.ExitGUI();
  324. }
  325. }
  326. }