Example #1
0
        static void ImportDatabase(bool assetsOnly)
        {
            string inputDirectory        = "Assets/Input";
            string bundleOutputDirectory = "Assets/Bundles";
            string prefabTempDirectory   = "Assets/Prefabs/FromImporter";
            string bundleName            = "elements.db";
            int    errorCount            = 0;

            if (!Directory.Exists(inputDirectory))
            {
                EditorUtility.DisplayDialog("Input Not Found", $"Input directory “{inputDirectory}” not found.", "Close");
                return;
            }

            // Load JSON file to process.
            var jsonAssets = new List <TextAsset>();

            foreach (string guid in AssetDatabase.FindAssets("t:TextAsset", new[] { inputDirectory }))
            {
                var assetPath = AssetDatabase.GUIDToAssetPath(guid);
                if (Path.GetExtension(assetPath).ToLower() == ".json")
                {
                    jsonAssets.Add(AssetDatabase.LoadAssetAtPath <TextAsset>(assetPath));
                }
            }
            if (jsonAssets.Count == 0)
            {
                EditorUtility.DisplayDialog("No Files", $"No JSON files were found in “{inputDirectory}”.", "Close");
                return;
            }
            if (jsonAssets.Count > 1)
            {
                EditorUtility.DisplayDialog("Too Many Files", $"More than one JSON file found in “{inputDirectory}”.", "Close");
                return;
            }

            // Parse the database from JSON.
            var fm = FeatureModel.FromJson(jsonAssets[0].text);

            // Generate prefab assets that will represent placeable elements at runtime.
            if (!Directory.Exists(prefabTempDirectory))
            {
                Directory.CreateDirectory(prefabTempDirectory);
            }
            var generatedAssetPaths = new List <string>();

            foreach (Feature feature in fm.FeatureMap.Values)
            {
                // Skip features that cannot be turned into prefabs.
                if (!feature.IsPhysical || feature.Metadata == null)
                {
                    continue;
                }

                var prefab   = new GameObject(feature.Name);
                var metadata = prefab.AddComponent <ElementMetadata>();
                metadata.Init(feature);

                // Attach 3D model.
                string[] modelFileGUIDs = AssetDatabase.FindAssets(metadata.ModelFilename, new[] { inputDirectory });
                if (modelFileGUIDs.Length == 0)
                {
                    Debug.Log($"Could not find 3D model with name: {metadata.ModelFilename}");
                    Object.DestroyImmediate(prefab);
                    errorCount++;
                    continue;
                }

                var modelAsset = AssetDatabase.LoadMainAssetAtPath(AssetDatabase.GUIDToAssetPath(modelFileGUIDs[0])) as GameObject;
                if (modelAsset == null)
                {
                    Debug.Log($"Model {metadata.ModelFilename} could not be loaded.");
                    Object.DestroyImmediate(prefab);
                    errorCount++;
                    continue;
                }

                var model = Object.Instantiate(modelAsset, prefab.transform, false);
                if (model == null)
                {
                    Debug.Log($"Model {metadata.ModelFilename} could not be instantiated.");
                    Object.DestroyImmediate(prefab);
                    errorCount++;
                    continue;
                }
                model.name = "3D Model";

                // Generate a collider mesh.
                var submeshes = model.GetComponentsInChildren <MeshFilter>();
                var combine   = new CombineInstance[submeshes.Length];
                for (int i = 0; i < submeshes.Length; i++)
                {
                    combine[i].mesh      = submeshes[i].sharedMesh;
                    combine[i].transform = submeshes[i].transform.localToWorldMatrix;
                }
                var combinedMesh = new Mesh();
                combinedMesh.CombineMeshes(combine);
                prefab.AddComponent <ElementController>().SaveColliderMesh(combinedMesh);

                // Set AssetBundle label and save the prefab.
                bool       saveSuccess;
                string     prefabAssetPath = AssetDatabase.GenerateUniqueAssetPath($"{prefabTempDirectory}/{prefab.name}.prefab");
                GameObject prefabAsset     = PrefabUtility.SaveAsPrefabAsset(prefab, prefabAssetPath, out saveSuccess);
                if (prefabAsset == null || !saveSuccess)
                {
                    Debug.Log($"Prefab {prefab.name} could not be saved as prefab asset.");
                    Object.DestroyImmediate(prefab);
                    errorCount++;
                    continue;
                }
                AssetImporter.GetAtPath(prefabAssetPath).SetAssetBundleNameAndVariant(bundleName, "");
                generatedAssetPaths.Add(prefabAssetPath);

                Object.DestroyImmediate(prefab);
            }

            // Mark linked textures to be put into the bundle.
            foreach (Feature feature in fm.FeatureMap.Values)
            {
                if (!feature.IsMaterial || feature.Material == null)
                {
                    continue;
                }

                var textureFileGUIDs = AssetDatabase.FindAssets(feature.Material.TextureFilename, new[] { inputDirectory });
                if (textureFileGUIDs.Length == 0)
                {
                    Debug.Log($"Could not find texture with name: {feature.Material.TextureFilename}");
                    errorCount++;
                    continue;
                }

                var assetPath = AssetDatabase.GUIDToAssetPath(textureFileGUIDs[0]);
                AssetImporter.GetAtPath(assetPath).SetAssetBundleNameAndVariant(bundleName, "");
            }

            // Save the feature model as JSON asset.
            var featureModelJson     = new TextAsset(jsonAssets[0].text);
            var featureModelSavePath = $"{prefabTempDirectory}/featuremodel.asset";

            AssetDatabase.CreateAsset(featureModelJson, featureModelSavePath);
            AssetImporter.GetAtPath(featureModelSavePath).SetAssetBundleNameAndVariant(bundleName, "");
            generatedAssetPaths.Add(featureModelSavePath);


            // If only prefabs were requested, we are done.
            if (assetsOnly)
            {
                return;
            }


            // Build the bundle.
            if (!Directory.Exists(bundleOutputDirectory))
            {
                Directory.CreateDirectory(bundleOutputDirectory);
            }
            BuildPipeline.BuildAssetBundles(bundleOutputDirectory, BuildAssetBundleOptions.None, BuildTarget.Android);

            // AssetBundle is now saved. Delete the generated content.
            foreach (string path in generatedAssetPaths)
            {
                bool deleteSuccess = AssetDatabase.DeleteAsset(path);
                if (!deleteSuccess)
                {
                    Debug.Log($"Failed to delete generated prefab asset at: {path}");
                    errorCount++;
                }
            }
            Directory.Delete(prefabTempDirectory, true);
            AssetDatabase.Refresh();

            if (errorCount > 0)
            {
                EditorUtility.DisplayDialog("Import Errors",
                                            (errorCount == 1 ? "There was an error" : $"There were {errorCount} errors") + " during import." +
                                            "\nSee console log for more information.",
                                            "Close");
            }
            else
            {
                EditorUtility.DisplayDialog("Import Complete",
                                            "Database was imported with no errors." +
                                            $"\nResults were saved to {bundleOutputDirectory}/{bundleName}",
                                            "Close");
            }
        }
 public void Init(string featureModelJson)
 {
     Model = FeatureModel.FromJson(featureModelJson);
 }