/// <summary> /// Coroutine-style implementation of GLTF import. /// </summary> /// <param name="gltfPath">Absolute path to .gltf/.glb file</param> /// <param name="importPath">Absolute path of folder where prefab and /// associated assets will be created. Must be located under /// the "Assets" folder for the current Unity project. /// created</param> /// <param name="progressCallback">Callback for reporting intermediate /// progress during the import.</param> public static GltfImportTask GetImportTask(string gltfPath, string importPath) { GltfImportTask importTask = new GltfImportTask(); EditorGltfImporter importer = new EditorGltfImporter( gltfPath, importPath, (step, completed, total) => importTask.OnProgress?.Invoke(step, completed, total)); importTask.AddTask(importer.ReadUri()); importTask.AddTask(importer.ParseFile()); importTask.AddTask(importer.LoadBuffers()); importTask.AddTask(importer.LoadTextures()); importTask.AddTask(importer.LoadMaterials()); importTask.AddTask(importer.LoadMeshes()); importTask.AddTask(importer.LoadScene()); importTask.AddTask(importer.LoadMorphTargets()); importTask.AddTask(importer.LoadSkins()); // note: the final subtask must return the // root GameObject for the imported model. importTask.AddTask(importer.CreatePrefabEnum()); // callbacks to clean up any imported game objects / files // when the user aborts the import or an exception // occurs importTask.OnAborted += importer.Clear; importTask.OnException += _ => importer.Clear(); return(importTask); }
/// <summary> /// Coroutine to import GLTF files with Piglet's EditorGltfImporter. /// The string value returned via the IEnumerator is the target directory /// for the current import, so that files from an aborted/canceled import /// can be easily cleaned up. /// </summary> private static IEnumerator <string> ImportCoroutine(List <string> gltfPaths, string baseImportDir) { foreach (string gltfPath in gltfPaths) { string gltfBasename = Path.GetFileName(gltfPath); string gltfBasenameNoExt = Path.GetFileNameWithoutExtension(gltfPath); bool abortImport = false; // callback for updating progress during glTF import void OnProgress(GltfImportStep type, int count, int total) { ProgressLog.Instance.OnImportProgress(type, count, total); abortImport = EditorUtility.DisplayCancelableProgressBar( $"Importing {gltfBasename}...", ProgressLog.Instance.GetProgressMessage(), (float)count / total); } string importPath = UnityPathUtil.NormalizePathSeparators( Path.Combine(baseImportDir, gltfBasenameNoExt)); string importProjectPath = UnityPathUtil.GetProjectPath(importPath); if ((Directory.Exists(importPath) || File.Exists(importPath)) && _pigletOptions.PromptBeforeOverwritingFiles) { if (!EditorUtility.DisplayDialog( "Warning!", $"Overwrite \"{importProjectPath}\"?", "OK", "Cancel")) { yield break; } FileUtil.DeleteFileOrDirectory(importPath); AssetDatabase.Refresh(); } GltfImportTask importTask = EditorGltfImporter.GetImportTask(gltfPath, importPath, _pigletOptions.ImportOptions); importTask.OnProgress = OnProgress; GameObject importedPrefab = null; importTask.OnCompleted = (prefab) => importedPrefab = prefab; // restart import timer at zero ProgressLog.Instance.StartImport(); while (true) { if (abortImport) { importTask.Abort(); EditorUtility.ClearProgressBar(); yield break; } try { if (!importTask.MoveNext()) { break; } } catch (Exception e) { Debug.LogException(e); EditorUtility.ClearProgressBar(); EditorUtility.DisplayDialog("Import Failed", String.Format("Import of {0} failed. " + "See Unity console log for details.", gltfBasename), "OK"); yield break; } yield return(importPath); } // Before modifying the selection, store a handle to // the transform of the currently selected game object (if any). Transform selectedTransform = Selection.activeTransform; // Select the prefab file in the Project Browser. if (_pigletOptions.SelectPrefabAfterImport) { Selection.activeObject = importedPrefab; yield return(importPath); } if (_pigletOptions.AddPrefabToScene) { // If we are currently in Prefab Mode, exit // back to the main scene hierarchy view. // // Note: Prefab Mode was introduced in Unity 2018.3. #if UNITY_2018_3_OR_NEWER if (StageUtility.GetCurrentStageHandle() != StageUtility.GetMainStageHandle()) { StageUtility.GoToMainStage(); } #endif GameObject instance = (GameObject)PrefabUtility .InstantiatePrefab(importedPrefab); // parent the prefab instance to the currently // selected GameObject (if any) if (selectedTransform != null) { instance.transform.parent = selectedTransform; } if (_pigletOptions.SelectPrefabInScene) { Selection.activeGameObject = instance; yield return(importPath); } } if (_pigletOptions.OpenPrefabAfterImport) { AssetDatabase.OpenAsset(importedPrefab); // Note: This is the best method I could find // for automatically centering the prefab in // the scene view. For further info, see // https://answers.unity.com/questions/813814/framing-objects-via-script-in-the-unity-editor.html SceneView.FrameLastActiveSceneView(); } EditorUtility.ClearProgressBar(); } }