Exemple #1
0
        /// <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);
        }
Exemple #2
0
        /// <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();
            }
        }