void _applyProgramChanges() { if (prog == null) { return; } prog.importTriggeredByInspector = true; // 1st erase the store program if (storedProg) { KMImportSettings.RemoveProgram(storedProg); } // now store the prog in memory to the asset KMImportSettings.AddProgram(prog); // Trigger mesh reimport -> import processor will execute program EditorUtility.DisplayProgressBar(KMImportProcessor.ProgressTitle(prog), "Unity3D reimports model file", 0.0f); KMImportSettings.IncrementMasterImportRevision(); // float dt = Time.realtimeSinceStartup; AssetDatabase.ImportAsset(assetPath); // dt = ; //Debug.LogError("Reimport took " + (Time.realtimeSinceStartup - dt)*1000.0f + " ms."); hasChanges = false; EditorUtility.ClearProgressBar(); // Reload prog _initializeProgram(); }
static string assetPath = "Assets/MeshProcessors/MeshImportProcessorSettings.asset"; // TODO: make this configurable? static void _assureInstance() { if (_instance == null) { _instance = AssetDatabase.LoadAssetAtPath(assetPath, typeof(KMImportSettings)) as KMImportSettings; if (_instance == null) { // Create a new file. // Maybe this could also search for moved files in the future. _instance = ScriptableObject.CreateInstance <KMImportSettings>(); AssetDatabase.CreateAsset(_instance, assetPath); // AssetDatabase.SaveAssets(); // maybe this crashes on first launch? // searching would be similar to this: /* // Search for renamed prefab in project (maybe there's a more efficient way?) * string[] paths = AssetDatabase.GetAllAssetPaths(); * foreach (string p in paths) { * GameObject candidate = AssetDatabase.LoadAssetAtPath(p, typeof(GameObject)) as GameObject; * if (candidate != null && candidate.GetComponent<KMImportSettingsRoot>() != null) { * prefabPath = p; * return candidate; * } * } */ } } }
void _initializeProgram() { storedProg = null; prog = null; progGUI = null; // Look for a program stored in the asset. storedProg = KMImportSettings.ProgramForMesh(assetGUID, meshPath); if (storedProg != null) { // Create a copy of the program to work with. prog = ScriptableObject.CreateInstance <KMProcessorProgram>(); EditorUtility.CopySerialized(storedProg, prog); int numProcessors = prog.processors.Length; for (int i = 0; i < numProcessors; ++i) { KrablMesh.Processor proc = prog.processors[i]; KrablMesh.Processor clone = ScriptableObject.CreateInstance(proc.GetType()) as KrablMesh.Processor; EditorUtility.CopySerialized(proc, clone); clone.hideFlags = HideFlags.DontSave; prog.processors[i] = clone; } prog.hideFlags = HideFlags.DontSave; progGUI = (KMProcessorProgramGUI)Editor.CreateEditor(prog); if (progGUI != null) { progGUI.usedByMeshImporter = true; } } }
// Called from progGUI public void DeleteProgram() { if (prog == null) { return; } bool del = true; if (prog.processors.Length > 0) { del = EditorUtility.DisplayDialog("Delete Import Program", "Do you want to permanently delete this mesh import program?", "Delete", "Cancel"); } if (del) { if (storedProg != null) { EditorUtility.DisplayProgressBar(KMImportProcessor.ProgressTitle(prog), "Unity3D reimports model file", 0.0f); KMImportSettings.RemoveProgram(storedProg); // Trigger model reimport AssetDatabase.ImportAsset(assetPath); EditorUtility.ClearProgressBar(); } prog = null; progGUI = null; storedProg = null; } }
static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromPath) { for (int i = 0; i < importedAssets.Length; ++i) { KMImportSettings kmis = AssetDatabase.LoadAssetAtPath(importedAssets[i], typeof(KMImportSettings)) as KMImportSettings; if (kmis != null) { KMImportSettings.SettingsReimported(); } } }
void AddProgram() { // Create an empty program in memory prog = KMImportSettings.CreateProgram(assetGUID, meshPath, mesh); // Now create the GUI progGUI = (KMProcessorProgramGUI)Editor.CreateEditor(prog); if (progGUI != null) { progGUI.usedByMeshImporter = true; } hasChanges = true; }
void OnPostprocessModel(GameObject g) { dummy.Dummy(); // dummy call to silence the compiler. kmiphelper is needed to get messages if the build target changes importRevision = KMImportSettings.GetMasterImportRevision(); // Collect all the meshes and their paths. -> to find duplicates that annoy me. // List<Mesh> meshes = new List<Mesh>(); // List<string> meshnames = new List<string>(); bool didProcess = false; foreach (MeshFilter mf in g.GetComponentsInChildren <MeshFilter>()) { Mesh mesh = mf.sharedMesh; if (_processMesh(g, mesh)) { didProcess = true; } if (mesh != null) { mf.sharedMesh = mesh; } } foreach (SkinnedMeshRenderer smr in g.GetComponentsInChildren <SkinnedMeshRenderer>()) { Mesh mesh = smr.sharedMesh; if (_processMesh(g, mesh)) { didProcess = true; } if (mesh != null) { smr.sharedMesh = mesh; } } // Write the revision to the revision database inside the Library folder. if (didProcess) { Dictionary <string, int> db = GetModelImportRevisionDictionary(); db[AssetDatabase.AssetPathToGUID(assetPath)] = importRevision; StoreModelImportRevisionDictionary(db); } }
override public void OnInspectorGUI() { EditorGUILayout.HelpBox("This object holds all the information the Krabl mesh processor framework needs to import meshes.\n\n" + "DO NOT touch this unless you wish to loose your processor programs.\n\n", MessageType.Warning); if (KMImportSettings.DoDebug()) { GUILayout.BeginHorizontal(); if (GUILayout.Button("Show Child Assets")) { _showChildAssets(true); } if (GUILayout.Button("Hide Child Assets")) { _showChildAssets(false); } GUILayout.EndHorizontal(); } }
public static void SettingsReimported() { _assureInstance(); float tm = 0.0f; if (KMImportSettings.DoDebug()) { tm = Time.realtimeSinceStartup; Debug.Log("Mesh Processor Settings were reimported."); } Dictionary <string, int> revisionDB = KMImportProcessor.GetModelImportRevisionDictionary(); KMProcessorProgram[] programs = _instance.programs; for (int i = 0; i < programs.Length; ++i) { KMProcessorProgram prog = programs[i]; if (prog != null) { int modelImportRevision = 0; // this is the revision number of the import on the running machine // prog.importRevision is the revision stored inside the importer asset // They need to be the same in order for the mesh to have the correct state. revisionDB.TryGetValue(prog.inAssetGUID, out modelImportRevision); //Debug.Log("P: " + path + " Rev New: " + rev); // If the importsettings changed on a different machine, // we need to reimport the changed assets if (modelImportRevision != prog.importRevision) { string path = AssetDatabase.GUIDToAssetPath(prog.inAssetGUID); if (path != null && path != "") { AssetDatabase.ImportAsset(path); } } } } if (KMImportSettings.DoDebug()) { Debug.Log("Settings reimported took " + (Time.realtimeSinceStartup - tm) * 1000.0f + " ms."); } }
bool _processMesh(GameObject container, Mesh umesh) { #if UNITY_4_3 || UNITY_4_4 || UNITY_4_5 if (umesh.blendShapeCount > 0) { Debug.Log("Krabl Mesh Processors can not yet process meshes with blendshapes."); return(false); } #endif string assetGUID = AssetDatabase.AssetPathToGUID(assetPath); //Debug.Log("Container guid: " + assetGUID); string meshPath = KrablMesh.UnityEditorUtils.MeshPathInAsset(umesh, container); //Debug.Log("Meshpath: " + meshPath); KMProcessorProgram program = KMImportSettings.ProgramForMesh(assetGUID, meshPath); if (program == null) { return(false); } if (program.bypass) { return(true); } // Debug.Log("KMImportProcessor Process " + container.name + "/" + umesh.name + " PRG: " + ((program == null) ? "NULL" : program.ToString()), umesh); KrablMesh.Processor[] processors = program.processors; if (true) //program.importTriggeredByInspector == true) { // Set up progress indicators { program.importTriggeredByInspector = false; float numEnabled = 0.0f; for (int i = 0; i < processors.Length; ++i) { if (processors[i].enabled) { numEnabled += 1.0f; } } float progStep = (numEnabled > 0.0f) ? 1.0f / numEnabled : 1.0f; float progOffset = 0.0f; string title = ProgressTitle(program); for (int i = 0; i < processors.Length; ++i) { if (processors[i].enabled == true) { float offset = progOffset; processors[i].progressDelegate = delegate(string text, float val) { EditorUtility.DisplayProgressBar(title, text, val * progStep + offset); }; progOffset += progStep; } } } Mesh processedMesh = program.Process(umesh, EditorUserBuildSettings.selectedBuildTargetGroup.ToString()); processedMesh.name = umesh.name; if (program.unityOptimizeMesh) { ; } EditorUtility.ClearProgressBar(); // Store Revision to program program.importRevision = importRevision; EditorUtility.SetDirty(program); //AssetDatabase.SaveAssets(); if (program.targetPath.Equals("replace")) { umesh.Clear(); EditorUtility.CopySerialized(processedMesh, umesh); } else { _outputToAsset(processedMesh, program.targetPath); } GameObject.DestroyImmediate(processedMesh); return(true); }
public static void buildTargetChanged() { //Debug.Log("Build Target Changed."); KMImportSettings.PlatformChanged(); }
public void DrawImporterGUI(KMMeshInspector inspector) { serializedObject.Update(); modifiedDuringLastUpdate = false; if (prog == null) { return; } // Adding processors at the end. Triggered from the menu callback // During the callback this does no longer work in Unity 4.3 if (processorToAddID != null) { AddProcessor(processorToAddID); processorToAddID = null; } //KrablMesh.Processor[] processors = prog.processors; if (titleBoxStyle == null) { titleBoxStyle = new GUIStyle("Box"); titleBoxStyle.margin = new RectOffset(0, 0, 0, 0); titleBoxStyle.padding = new RectOffset(0, 0, 4, 4); } GUILayout.BeginVertical(titleBoxStyle); GUILayout.BeginHorizontal(); if (titleStyle == null) { titleStyle = new GUIStyle(EditorStyles.largeLabel); titleStyle.fontStyle = FontStyle.Bold; } string titleString = "Mesh Import Program"; if (KMImportSettings.DoDebug()) { titleString += " (r" + prog.importRevision + ")"; } GUILayout.Label(titleString, titleStyle); GUILayout.FlexibleSpace(); if (GUILayout.Button(new GUIContent("Delete", "Delete the mesh import program for this mesh"))) { // Call the inspector as only it can delete the program (and this editor). inspector.DeleteProgram(); } GUILayout.EndHorizontal(); EditorGUILayout.Separator(); EditorGUILayout.PropertyField(inputToleranceProp, new GUIContent("Input Tolerance", "The maximum difference considered equal for vertices and normals when they are fed into the processor chain. " + "Usually 0 should work fine, but apparently some modelling software produces only nearly equal vertices/normals. " + "" + "If weird topology is produced, try setting the value to something like 1e-6")); /* EditorGUILayout.LabelField("Output Mesh Path"); * EditorGUILayout.BeginHorizontal(); * if (!prog.targetPath.Equals("replace")) { * EditorGUILayout.PropertyField(targetPathProp, GUIContent.none); * if (GUILayout.Button("Replace", EditorStyles.miniButton, GUILayout.ExpandWidth(false))) { * targetPathProp.stringValue = "replace"; * } * } else { * EditorGUILayout.LabelField("Replace imported Mesh"); * if (GUILayout.Button("Override", EditorStyles.miniButton, GUILayout.ExpandWidth(false))) { * targetPathProp.stringValue = KrablMeshUnityPreferences.defaultExtraMeshOutputPath + "/" + prog.inContainerName + "/" + prog.inMeshPath; * } * } * EditorGUILayout.EndHorizontal(); */ EditorGUILayout.PropertyField(unityOptimizeMeshProp, new GUIContent("Optimize Mesh", "Improve the mesh element order after processing to render faster on the GPU")); EditorGUILayout.PropertyField(bypassProp, new GUIContent("Bypass Program", "Disable all processors and output the originally imported mesh")); GUILayout.EndVertical(); if (bypassProp.boolValue == true) { GUI.enabled = false; } // Draw processor GUIs below for importer if (processorsProp != null) { int toDelete = -1, moveUp = -1, moveDown = -1; KrablMesh.ProcessorEditor edit; for (int i = 0; i < processorsProp.arraySize; ++i) { KrablMesh.Processor p = processorsProp.GetArrayElementAtIndex(i).objectReferenceValue as KrablMesh.Processor; edit = null; if (p != null && processorEditors.TryGetValue(p, out edit) == false) { edit = (p == null) ? null : Editor.CreateEditor(p) as KrablMesh.ProcessorEditor; edit.usedByMeshImporter = usedByMeshImporter; processorEditors.Add(p, edit); } //fold = EditorGUILayout.InspectorTitlebar(fold, p); EditorGUILayout.BeginHorizontal(); if (p == null) { EditorGUILayout.LabelField("-- NULL PROCESSOR --"); } else { if (processorNameStyle == null) { processorNameStyle = new GUIStyle(EditorStyles.toggle); processorNameStyle.fontStyle = FontStyle.Bold; } edit.serializedObject.Update(); SerializedProperty enabledProp = edit.serializedObject.FindProperty("enabled"); if (enabledProp != null) { enabledProp.boolValue = GUILayout.Toggle(enabledProp.boolValue, new GUIContent(p.Name(), edit.ProcessorToolTip()), processorNameStyle, GUILayout.Width(146.0f)); } if (edit.serializedObject.ApplyModifiedProperties()) { modifiedDuringLastUpdate = true; } } GUILayout.FlexibleSpace(); if (GUILayout.Button("Up", EditorStyles.miniButtonLeft)) { moveUp = i; } if (GUILayout.Button("Down", EditorStyles.miniButtonRight)) { moveDown = i; } GUILayout.Space(5.0f); if (GUILayout.Button("DEL", EditorStyles.miniButton)) { toDelete = i; } EditorGUILayout.EndHorizontal(); EditorGUILayout.Separator(); if (p != null && edit != null) { edit.OnInspectorGUI(); if (edit.modifiedDuringLastUpdate) { modifiedDuringLastUpdate = true; } } EditorGUILayout.Separator(); KrablMesh.UnityEditorUtils.GUILayoutAddHoriLine(); } if (toDelete >= 0) { int last = processorsProp.arraySize - 1; processorsProp.MoveArrayElement(toDelete, last); processorsProp.DeleteArrayElementAtIndex(last); processorsProp.arraySize--; } else if (moveUp > 0) { processorsProp.MoveArrayElement(moveUp, moveUp - 1); } else if (moveDown >= 0 && moveDown < processorsProp.arraySize - 1) { processorsProp.MoveArrayElement(moveDown, moveDown + 1); } } EditorGUILayout.Separator(); GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); AddProcessorPopupButton("Add Processor here...", largeButtonStyle, _addProcessorCallback); GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); EditorGUILayout.Separator(); KrablMesh.UnityEditorUtils.GUILayoutAddHoriLine(); if (serializedObject.ApplyModifiedProperties()) { modifiedDuringLastUpdate = true; } }
override public void OnInspectorGUI() { if (target == null || serializedObject == null) { return; } if (!KMImportSettings.DoDebug()) { EditorGUILayout.HelpBox("Mesh processors programs can only be used in imported programs displayed in the mesh inspector.", MessageType.Info); } else { DrawDefaultInspector(); } return; #if false serializedObject.Update(); // This will become the realtime section eventually maybe. modifiedDuringLastUpdate = false; //float dummy = 0.0f; // Input Section: // GUIStyle headerStyle = new GUIStyle("Box"); // headerStyle.margin = new RectOffset(0, 0 ,0, 0); //EditorGUILayout.LabelField("Global Settings", EditorStyles.boldLabel); //EditorGUILayout.Separator(); // EditorGUILayout.BeginVertical(headerStyle); // if (GUI.Button(r, GUIContent.none, GUIStyle.none)) { // Debug.Log("BG clicked."); // } //EditorGUILayout.BeginHorizontal(); //EditorGUILayout.PrefixLabel("Original Mesh"); EditorGUILayout.LabelField("Original Mesh", prog.inMeshDescription); //EditorGUILayout.EndHorizontal(); /* EditorGUILayout.LabelField("Output Mesh Path"); * EditorGUILayout.BeginHorizontal(); * if (!prog.targetPath.Equals("replace")) { * EditorGUILayout.PropertyField(targetPathProp, GUIContent.none); * if (GUILayout.Button("Replace", EditorStyles.miniButton, GUILayout.ExpandWidth(false))) { * targetPathProp.stringValue = "replace"; * } * } else { * EditorGUILayout.LabelField("Replace imported Mesh"); * if (GUILayout.Button("Override", EditorStyles.miniButton, GUILayout.ExpandWidth(false))) { * targetPathProp.stringValue = KrablMeshUnityPreferences.defaultExtraMeshOutputPath + "/" + prog.inContainerName + "/" + prog.inMeshPath; * } * } * EditorGUILayout.EndHorizontal(); */ // EditorGUILayout.Separator(); // EditorGUILayout.EndVertical(); KrablMesh.UnityEditorUtils.GUILayoutAddHoriLine(); EditorGUILayout.PropertyField(unityOptimizeMeshProp, new GUIContent("Optimize Mesh", "Improve the mesh element order to render faster on the GPU")); if (GUILayout.Button("Calculate")) { // TODO: move this to ProcessorProgramm class UnityEngine.Mesh mesh = null; MeshFilter mf = prog.GetComponent <MeshFilter>(); SkinnedMeshRenderer smr = null; if (mf) { mesh = mf.sharedMesh; } else { smr = prog.GetComponent <SkinnedMeshRenderer>(); if (smr) { mesh = smr.sharedMesh; } } if (mesh == null) { Debug.LogError("Can't process without Mesh"); } else { mesh = prog.Process(mesh); mesh.name = "TEMP"; if (mf != null) { mf.sharedMesh = mesh; } else if (smr != null) { smr.sharedMesh = mesh; } } } if (serializedObject.ApplyModifiedProperties()) { modifiedDuringLastUpdate = true; } #endif }