Example #1
0
    public void _1_3_RunImporter()
    {
        var projectFolderPath = Directory.GetParent(Application.dataPath).ToString();
        var definedSourcePath = Path.Combine(projectFolderPath, "TestResources/TestResources0/");

        var source = new Dictionary <string, List <InternalAssetData> > {
            { "0",
              new List <InternalAssetData> {
                  InternalAssetData.InternalAssetDataByLoader(Path.Combine(definedSourcePath, "dummy.png"), definedSourcePath),
                  InternalAssetData.InternalAssetDataByLoader(Path.Combine(definedSourcePath, "model/sample.fbx"), definedSourcePath)
              } }
        };

        var results = new Dictionary <string, List <InternalAssetData> >();

        var integratedGUIImporter = new IntegratedGUIImporter(AssetGraphSettings.PLATFORM_DEFAULT_NAME);
        Action <string, string, Dictionary <string, List <InternalAssetData> >, List <string> > Out = (string nodeId, string connectionId, Dictionary <string, List <InternalAssetData> > output, List <string> cached) => {
            results[connectionId] = output["0"];
        };

        integratedGUIImporter.Run("ID_1_3_RunImporter", "CONNECTION_1_3_RunImporter", string.Empty, source, new List <string>(), Out);

        var currentOutputs = results["CONNECTION_1_3_RunImporter"].Where(path => !GraphStackController.IsMetaFile(path.importedPath)).ToList();

        if (currentOutputs.Count == 3)
        {
            Debug.Log("passed _1_3_RunImporter");
            return;
        }

        Debug.LogError("failed to collect importerd resource:" + currentOutputs.Count);
    }
Example #2
0
        public static void RemoveBundleSettings(string nodePath)
        {
            EditorUtility.DisplayProgressBar("AssetBundleGraph unbundlize all resources...", nodePath, 0);
            var filePathsInFolder = FileController.FilePathsInFolder(nodePath);

            foreach (var filePath in filePathsInFolder)
            {
                if (GraphStackController.IsMetaFile(filePath))
                {
                    continue;
                }
                if (GraphStackController.ContainsHiddenFiles(filePath))
                {
                    continue;
                }
                var assetImporter = AssetImporter.GetAtPath(filePath);

                // assetImporter is null when the asset is not accepted by Unity.
                // e.g. file.my_new_extension is ignored by Unity.
                if (assetImporter == null)
                {
                    continue;
                }

                if (assetImporter.GetType() == typeof(UnityEditor.MonoImporter))
                {
                    continue;
                }

                assetImporter.assetBundleName = string.Empty;
            }
            EditorUtility.ClearProgressBar();
        }
        public string BundlizeAssets(string groupkey, List <InternalAssetData> sources, string recommendedBundleOutputDir, bool isRun)
        {
            var invalids = new List <string>();

            foreach (var source in sources)
            {
                if (string.IsNullOrEmpty(source.importedPath))
                {
                    invalids.Add(source.pathUnderSourceBase);
                }
            }
            if (invalids.Any())
            {
                throw new Exception("bundlizer:" + string.Join(", ", invalids.ToArray()) + " is not imported yet, should import before bundlize.");
            }

            var bundleName = bundleNameTemplate;

            /*
             *      if contains KEYWORD_WILDCARD, use group identifier to bundlize name.
             */
            if (bundleNameTemplate.Contains(AssetBundleGraphSettings.KEYWORD_WILDCARD))
            {
                var templateHead = bundleNameTemplate.Split(AssetBundleGraphSettings.KEYWORD_WILDCARD)[0];
                var templateTail = bundleNameTemplate.Split(AssetBundleGraphSettings.KEYWORD_WILDCARD)[1];

                bundleName = (templateHead + groupkey + templateTail + "." + GraphStackController.Platform_Dot_Package()).ToLower();
            }

            var bundlePath = FileController.PathCombine(recommendedBundleOutputDir, bundleName);

            foreach (var source in sources)
            {
                // if already bundled in this running, avoid changing that name.
                if (source.isBundled)
                {
                    continue;
                }

                if (isRun)
                {
                    if (GraphStackController.IsMetaFile(source.importedPath))
                    {
                        continue;
                    }
                    var assetImporter = AssetImporter.GetAtPath(source.importedPath);
                    if (assetImporter == null)
                    {
                        continue;
                    }
                    assetImporter.assetBundleName = bundleName;
                }

                // set as this resource is already bundled.
                source.isBundled = true;
            }

            return(bundlePath);
        }
Example #4
0
        public void Run(string nodeId, string labelToNext, string package, Dictionary <string, List <InternalAssetData> > groupedSources, List <string> alreadyCached, Action <string, string, Dictionary <string, List <InternalAssetData> >, List <string> > Output)
        {
            var recommendedBundleOutputDir = FileController.PathCombine(AssetGraphSettings.BUNDLIZER_CACHE_PLACE, nodeId);

            FileController.RemakeDirectory(recommendedBundleOutputDir);

            var outputDict = new Dictionary <string, List <InternalAssetData> >();

            foreach (var groupKey in groupedSources.Keys)
            {
                var inputSources = groupedSources[groupKey];

                var assets = new List <AssetInfo>();
                foreach (var assetData in inputSources)
                {
                    var assetName = assetData.fileNameAndExtension;
                    var assetType = assetData.assetType;
                    var assetPath = assetData.importedPath;
                    var assetId   = assetData.assetId;
                    assets.Add(new AssetInfo(assetName, assetType, assetPath, assetId));
                }

                var localFilePathsBeforeBundlize = FileController.FilePathsInFolder(AssetGraphSettings.UNITY_LOCAL_DATAPATH);
                try {
                    In(groupKey, assets, recommendedBundleOutputDir);
                } catch (Exception e) {
                    Debug.LogError("Bundlizer:" + this + " error:" + e);
                }

                AssetDatabase.Refresh(ImportAssetOptions.ImportRecursive);
                AssetDatabase.SaveAssets();

                var localFilePathsAfterBundlize = FileController.FilePathsInFolder(AssetGraphSettings.UNITY_LOCAL_DATAPATH);

                var outputSources = new List <InternalAssetData>();

                var generatedAssetBundlePaths = localFilePathsAfterBundlize.Except(localFilePathsBeforeBundlize);

                foreach (var newAssetPath in generatedAssetBundlePaths)
                {
                    if (GraphStackController.IsMetaFile(newAssetPath))
                    {
                        continue;
                    }
                    var newAssetData = InternalAssetData.InternalAssetDataGeneratedByImporterOrPrefabricator(
                        newAssetPath,
                        AssetDatabase.AssetPathToGUID(newAssetPath),
                        AssetGraphInternalFunctions.GetAssetType(newAssetPath),
                        true,
                        false
                        );
                    outputSources.Add(newAssetData);
                }

                outputDict[groupKey] = outputSources;
            }

            Output(nodeId, labelToNext, outputDict, new List <string>());
        }
Example #5
0
        /**
         *      returns file paths which are located in the folder.
         *
         *      this method is main point for supporting path format of cross platform.
         *
         *      Usually Unity Editor uses '/' as folder delimter.
         *
         *      e.g.
         *              Application.dataPath returns
         *                      C:/somewhere/projectPath/Assets @ Windows.
         *                              or
         *                      /somewhere/projectPath/Assets @ Mac, Linux.
         *
         *
         *      but "Directory.GetFiles(localFolderPath + "/")" method returns different formatted path by platform.
         *
         *      @ Windows:
         *              localFolderPath + / + somewhere\folder\file.extention
         *
         *      @ Mac/Linux:
         *              localFolderPath + / + somewhere/folder/file.extention
         *
         *      the problem is, "Directory.GetFiles" returns mixed format path of files @ Windows.
         *      this is the point of failure.
         *
         *      this method replaces folder delimiters to '/'.
         */
        public static List <string> FilePathsInFolderOnly1Level(string localFolderPath)
        {
            // change platform-depends folder delimiter -> '/'
            var filePaths = ConvertSeparater(Directory.GetFiles(localFolderPath)
                                             .Where(path => !(Path.GetFileName(path).StartsWith(AssetGraphSettings.DOTSTART_HIDDEN_FILE_HEADSTRING)))
                                             .ToList());

            if (AssetGraphSettings.IGNORE_META)
            {
                filePaths = filePaths.Where(path => !GraphStackController.IsMetaFile(path)).ToList();
            }

            return(filePaths);
        }
        private void RemoveBundleSettings(string nodePath)
        {
            EditorUtility.DisplayProgressBar("AssetGraph BundleBuilder unbundlize resources...", nodePath, 0);
            var filePathsInFolder = FileController.FilePathsInFolder(nodePath);

            foreach (var filePath in filePathsInFolder)
            {
                if (GraphStackController.IsMetaFile(filePath))
                {
                    continue;
                }
                var assetImporter = AssetImporter.GetAtPath(filePath);
                assetImporter.assetBundleName = string.Empty;
            }
            EditorUtility.ClearProgressBar();
        }
Example #7
0
        public static void RemoveBundleSettings(string nodePath)
        {
            EditorUtility.DisplayProgressBar("AssetBundleGraph unbundlize all resources...", nodePath, 0);
            var filePathsInFolder = FileController.FilePathsInFolder(nodePath);

            foreach (var filePath in filePathsInFolder)
            {
                if (GraphStackController.IsMetaFile(filePath))
                {
                    continue;
                }
                var assetImporter = AssetImporter.GetAtPath(filePath);

                if (assetImporter.GetType() == typeof(UnityEditor.MonoImporter))
                {
                    continue;
                }

                assetImporter.assetBundleName = string.Empty;
            }
            EditorUtility.ClearProgressBar();
        }
Example #8
0
        public void Run(string nodeId, string labelToNext, string package, Dictionary <string, List <InternalAssetData> > groupedSources, List <string> alreadyCached, Action <string, string, Dictionary <string, List <InternalAssetData> >, List <string> > Output)
        {
            var usedCache = new List <string>();


            var outputDict = new Dictionary <string, List <InternalAssetData> >();


            // caution if import setting file is exists already or not.
            var samplingDirectoryPath = FileController.PathCombine(AssetGraphSettings.IMPORTER_SAMPLING_PLACE, nodeId, importerPackage);

            var sampleAssetPath = string.Empty;

            ValidateImportSample(samplingDirectoryPath,
                                 (string noSampleFolder) => {
                Debug.LogWarning("importer:" + noSampleFolder);
            },
                                 (string noSampleFile) => {
                throw new Exception("importer error:" + noSampleFile);
            },
                                 (string samplePath) => {
                Debug.Log("using import setting:" + samplePath);
                sampleAssetPath = samplePath;
            },
                                 (string tooManysample) => {
                throw new Exception("importer error:" + tooManysample);
            }
                                 );


            // ready.
            AssetDatabase.Refresh(ImportAssetOptions.ImportRecursive);


            // construct import path from package info.
            // importer's package is complicated.
            // 1. importer uses their own package informatiom.
            // 2. but imported assets are located at platform-package combined path.(same as other node.)
            // this is comes from the spec: importer node contains platform settings in themselves.
            var nodeDirectoryPath = FileController.PathCombine(AssetGraphSettings.IMPORTER_CACHE_PLACE, nodeId, GraphStackController.Current_Platform_Package_Folder(package));

            // shrink group to 1 group.
            if (1 < groupedSources.Keys.Count)
            {
                Debug.LogWarning("importer shrinking group to \"" + groupedSources.Keys.ToList()[0] + "\" forcely.");
            }

            var inputSources = new List <InternalAssetData>();

            foreach (var groupKey in groupedSources.Keys)
            {
                inputSources.AddRange(groupedSources[groupKey]);
            }

            var oldGeneratedRecord          = GraphStackController.LoadImporterRecord(nodeId, package);
            var oldRemainGeneratedAssetDict = new Dictionary <string, List <string> >();
            var newGeneratedAssetDict       = new Dictionary <string, List <string> >();

            /**
             *      delete unnecessary cache from node.
             */
            {
                var latestInputImportAssumePaths = inputSources.Select(latestImportAsset => FileController.PathCombine(nodeDirectoryPath, latestImportAsset.pathUnderSourceBase)).ToList();
                var oldGeneratedRecordPaths      = oldGeneratedRecord.Keys.ToList();

                var notExistInLatestButRecordedPaths = oldGeneratedRecordPaths.Except(latestInputImportAssumePaths);
                foreach (var shouldDeleteCachePath in notExistInLatestButRecordedPaths)
                {
                    var shouldDetelePaths = oldGeneratedRecord[shouldDeleteCachePath];
                    foreach (var deletingCachePath in shouldDetelePaths)
                    {
                        // unbundlize unused imported cached asset.
                        var assetImporter = AssetImporter.GetAtPath(deletingCachePath);
                        assetImporter.assetBundleName = string.Empty;

                        FileController.DeleteFileThenDeleteFolderIfEmpty(deletingCachePath);
                    }
                }
            }

            /*
             *      copy all sources from outside to inside of Unity.
             *      apply importSetting to new file.
             */
            {
                var samplingAssetImporter = AssetImporter.GetAtPath(sampleAssetPath);
                InternalSamplingImportAdopter.Attach(samplingAssetImporter);
                {
                    var alreadyImported = new List <string>();
                    var ignoredResource = new List <string>();

                    foreach (var inputSource in inputSources)
                    {
                        // non absoluteSoucePath -> not imported. generated one. or else.
                        if (string.IsNullOrEmpty(inputSource.absoluteSourcePath))
                        {
                            if (!string.IsNullOrEmpty(inputSource.importedPath))
                            {
                                alreadyImported.Add(inputSource.importedPath);
                                continue;
                            }

                            // already imported. should ignore.
                            ignoredResource.Add(inputSource.fileNameAndExtension);
                            continue;
                        }

                        // construct imported path.
                        var pathUnderSourceBase = inputSource.pathUnderSourceBase;
                        var targetFilePath      = FileController.PathCombine(nodeDirectoryPath, pathUnderSourceBase);

                        // skip if cached.
                        if (GraphStackController.IsCached(inputSource, alreadyCached, targetFilePath))
                        {
                            var alreadyImportedPathAndGeneratedPaths = oldGeneratedRecord[targetFilePath];

                            // continue using generated info.
                            oldRemainGeneratedAssetDict[targetFilePath] = oldGeneratedRecord[targetFilePath];

                            usedCache.AddRange(alreadyImportedPathAndGeneratedPaths);
                            continue;
                        }

                        var before = FileController.FilePathsOfFile(targetFilePath);

                        /*
                         *      copy files into local.
                         */
                        var absoluteFilePath = inputSource.absoluteSourcePath;
                        FileController.CopyFileFromGlobalToLocal(absoluteFilePath, targetFilePath);

                        AssetDatabase.Refresh(ImportAssetOptions.ImportRecursive);

                        var after = FileController.FilePathsOfFile(targetFilePath);

                        /*
                         *      record relationship of imported file & generated files.
                         */
                        var diff = after.Except(before).Where(path => !GraphStackController.IsMetaFile(path)).ToList();
                        newGeneratedAssetDict[targetFilePath] = diff;
                    }

                    if (alreadyImported.Any())
                    {
                        Debug.LogError("importer:" + string.Join(", ", alreadyImported.ToArray()) + " are already imported.");
                    }
                    if (ignoredResource.Any())
                    {
                        Debug.LogError("importer:" + string.Join(", ", ignoredResource.ToArray()) + " are ignored.");
                    }
                }
                InternalSamplingImportAdopter.Detach();
            }


            /*
             *      input sequence is over.
             */

            // get files, which are imported or cached assets.
            var localFilePathsAfterImport = FileController.FilePathsInFolder(nodeDirectoryPath);

            // modify to local path.
            var localFilePathsWithoutNodeDirectoryPath = localFilePathsAfterImport.Select(path => InternalAssetData.GetPathWithoutBasePath(path, nodeDirectoryPath)).ToList();


            var outputSources = new List <InternalAssetData>();

            /*
             *      treat all assets inside node.
             */
            foreach (var newAssetPath in localFilePathsWithoutNodeDirectoryPath)
            {
                var basePathWithNewAssetPath = InternalAssetData.GetPathWithBasePath(newAssetPath, nodeDirectoryPath);

                if (usedCache.Contains(basePathWithNewAssetPath))
                {
                    // already cached, not new.
                    var newInternalAssetData = InternalAssetData.InternalAssetDataGeneratedByImporterOrPrefabricator(
                        basePathWithNewAssetPath,
                        AssetDatabase.AssetPathToGUID(basePathWithNewAssetPath),
                        AssetGraphInternalFunctions.GetAssetType(basePathWithNewAssetPath),
                        false
                        );
                    outputSources.Add(newInternalAssetData);
                }
                else
                {
                    // now cached. new resource.
                    var newInternalAssetData = InternalAssetData.InternalAssetDataGeneratedByImporterOrPrefabricator(
                        basePathWithNewAssetPath,
                        AssetDatabase.AssetPathToGUID(basePathWithNewAssetPath),
                        AssetGraphInternalFunctions.GetAssetType(basePathWithNewAssetPath),
                        true
                        );
                    outputSources.Add(newInternalAssetData);
                }
            }

            outputDict[groupedSources.Keys.ToList()[0]] = outputSources;


            /*
             *      merge old remains record & new generated record.
             */
            {
                var newAndOldGeneratedAssetDict = new Dictionary <string, List <string> >();

                foreach (var oldRemainGeneratedAssetPath in oldRemainGeneratedAssetDict.Keys)
                {
                    newAndOldGeneratedAssetDict[oldRemainGeneratedAssetPath] = oldRemainGeneratedAssetDict[oldRemainGeneratedAssetPath];
                }
                foreach (var newGeneratedAssetPath in newGeneratedAssetDict.Keys)
                {
                    newAndOldGeneratedAssetDict[newGeneratedAssetPath] = newGeneratedAssetDict[newGeneratedAssetPath];
                }
                GraphStackController.UpdateImporterRecord(nodeId, package, newAndOldGeneratedAssetDict);
            }

            Output(nodeId, labelToNext, outputDict, usedCache);
        }
Example #9
0
    public void _0_5_RunPrefabricator()
    {
        GraphStackController.CleanCache();

        var importedPath = "Assets/AssetGraphTest/PrefabricatorTestResource/SpanPath/a.png";

        var source = new Dictionary <string, List <InternalAssetData> > {
            { "0",
              new List <InternalAssetData> {
                  InternalAssetData.InternalAssetDataByImporter(
                      "traceId_0_5_RunPrefabricator",
                      Path.Combine(Application.dataPath, importedPath),
                      Application.dataPath,
                      Path.GetFileName(importedPath),
                      string.Empty,
                      importedPath,
                      AssetDatabase.AssetPathToGUID(importedPath),
                      AssetGraphInternalFunctions.GetAssetType(importedPath)
                      )
              } }
        };

        var results = new Dictionary <string, List <InternalAssetData> >();

        var sPrefabricator = new SamplePrefabricator_0();
        Action <string, string, Dictionary <string, List <InternalAssetData> >, List <string> > Out = (string nodeId, string connectionId, Dictionary <string, List <InternalAssetData> > output, List <string> cached) => {
            results[connectionId] = output["0"];
        };

        sPrefabricator.Run("ID_0_5_RunPrefabricator", "CONNECTION_0_5_RunPrefabricator", string.Empty, source, new List <string>(), Out);

        var currentOutputs = results["CONNECTION_0_5_RunPrefabricator"].Where(assetData => !GraphStackController.IsMetaFile(assetData.importedPath)).ToList();

        if (currentOutputs.Count == 3)
        {
            // material.mat
            // prefab.prefab
            // a.png

            if (!currentOutputs[0].fileNameAndExtension.Contains("material.mat"))
            {
                Debug.LogError("not contained 'material.mat'");
            }
            if (!currentOutputs[1].fileNameAndExtension.Contains("prefab.prefab"))
            {
                Debug.LogError("not contained 'prefab.prefab'");
            }
            if (!currentOutputs[2].fileNameAndExtension.Contains("a.png"))
            {
                Debug.LogError("not contained 'a.png'");
            }

            Debug.Log("passed _0_5_RunPrefabricator");
            return;
        }

        Debug.LogError("failed to prefabricate:" + currentOutputs.Count);
    }
Example #10
0
    public void _4_0_RunThenCachedGUI()
    {
        GraphStackController.CleanCache();

        var cacheDict = new Dictionary <string, List <string> >();

        var dataPath      = Path.Combine(Application.dataPath, "AssetGraphTest/Editor/TestData");
        var graphDataPath = Path.Combine(dataPath, "_4_0_RunThenCachedGUI.json");

        // load
        var dataStr = string.Empty;

        using (var sr = new StreamReader(graphDataPath)) {
            dataStr = sr.ReadToEnd();
        }
        var graphDict = Json.Deserialize(dataStr) as Dictionary <string, object>;

        // get cached asset dictionary.
        var createdDataDict = new Dictionary <string, List <string> >();


        Action act = () => {
            var EndpointNodeIdsAndNodeDatasAndConnectionDatas = GraphStackController.SerializeNodeRoute(graphDict, string.Empty);

            var endpointNodeIds = EndpointNodeIdsAndNodeDatasAndConnectionDatas.endpointNodeIds;
            var nodeDatas       = EndpointNodeIdsAndNodeDatasAndConnectionDatas.nodeDatas;
            var connectionDatas = EndpointNodeIdsAndNodeDatasAndConnectionDatas.connectionDatas;

            var resultDict = new Dictionary <string, Dictionary <string, List <InternalAssetData> > >();

            foreach (var endNodeId in endpointNodeIds)
            {
                GraphStackController.RunSerializedRoute(endNodeId, nodeDatas, connectionDatas, resultDict, cacheDict, string.Empty);
            }

            /*
             *      create first data result.
             */
            foreach (var node in nodeDatas)
            {
                var nodeId          = node.nodeId;
                var nodeKind        = node.nodeKind;
                var cachedDataPaths = GraphStackController.GetCachedDataByNodeKind(nodeKind, nodeId, string.Empty);

                createdDataDict[nodeId] = cachedDataPaths;
            }
        };

        act();

        // reset cacheDict for retake.
        cacheDict = new Dictionary <string, List <string> >();


        act();

        /*
         *      check results.
         */
        foreach (var nodeId in createdDataDict.Keys)
        {
            if (!cacheDict.Keys.Contains(nodeId))
            {
                if (nodeId == "TestExporter")
                {
                    continue;
                }
                Debug.LogError("cacheDict did not contained:" + nodeId);
            }
        }

        foreach (var nodeId in cacheDict.Keys)
        {
            if (!createdDataDict.Keys.Contains(nodeId))
            {
                Debug.LogError("createdDataDict did not contained:" + nodeId);
            }
        }


        foreach (var key in createdDataDict.Keys)
        {
            if (!cacheDict.ContainsKey(key))
            {
                continue;
            }

            var basePaths   = createdDataDict[key];
            var targetPaths = cacheDict[key];

            foreach (var basePath in basePaths)
            {
                // ignore meta files.
                if (GraphStackController.IsMetaFile(basePath))
                {
                    continue;
                }

                // avoid sub-creating assets. sub-creating assets never appear as cached.
                if (basePath.StartsWith("Assets/AssetGraph/Cache/Imported/Testimporter1/" + GraphStackController.Current_Platform_Package_Folder(string.Empty) + "/models/ID_0/Materials"))
                {
                    continue;
                }
                if (basePath.StartsWith("Assets/AssetGraph/Cache/Imported/Testimporter1/" + GraphStackController.Current_Platform_Package_Folder(string.Empty) + "/models/ID_1/Materials"))
                {
                    continue;
                }
                if (basePath.StartsWith("Assets/AssetGraph/Cache/Imported/Testimporter1/" + GraphStackController.Current_Platform_Package_Folder(string.Empty) + "/models/ID_2/Materials"))
                {
                    continue;
                }

                if (!targetPaths.Contains(basePath))
                {
                    Debug.LogError("contained in result, but not in cached:" + basePath);
                }
            }

            foreach (var targetPath in targetPaths)
            {
                // ignore meta files.
                if (GraphStackController.IsMetaFile(targetPath))
                {
                    continue;
                }

                if (!basePaths.Contains(targetPath))
                {
                    Debug.LogError("contained in cache, but not in result:" + targetPath);
                }
            }
        }
    }
Example #11
0
        public void Run(string nodeId, string labelToNext, string package, Dictionary <string, List <InternalAssetData> > groupedSources, List <string> alreadyCached, Action <string, string, Dictionary <string, List <InternalAssetData> >, List <string> > Output)
        {
            var usedCache = new List <string>();

            var invalids = new List <string>();

            foreach (var sources in groupedSources.Values)
            {
                foreach (var source in sources)
                {
                    if (string.IsNullOrEmpty(source.importedPath))
                    {
                        invalids.Add(source.pathUnderSourceBase);
                    }
                }
            }

            if (invalids.Any())
            {
                throw new Exception("prefabricator:" + string.Join(", ", invalids.ToArray()) + " are not imported yet, should import before prefabricate.");
            }

            var recommendedPrefabOutputDirectoryPath = FileController.PathCombine(AssetGraphSettings.PREFABRICATOR_CACHE_PLACE, nodeId, GraphStackController.Current_Platform_Package_Folder(package));

            var outputDict        = new Dictionary <string, List <InternalAssetData> >();
            var cachedOrGenerated = new List <string>();

            foreach (var groupKey in groupedSources.Keys)
            {
                var inputSources = groupedSources[groupKey];

                var recommendedPrefabPath = FileController.PathCombine(recommendedPrefabOutputDirectoryPath, groupKey);
                if (!recommendedPrefabPath.EndsWith(AssetGraphSettings.UNITY_FOLDER_SEPARATOR.ToString()))
                {
                    recommendedPrefabPath = recommendedPrefabPath + AssetGraphSettings.UNITY_FOLDER_SEPARATOR.ToString();
                }

                /*
                 *      ready input resource info for execute. not contains cache in this node.
                 */
                var assets = new List <AssetInfo>();
                foreach (var assetData in inputSources)
                {
                    var assetName = assetData.fileNameAndExtension;
                    var assetType = assetData.assetType;
                    var assetPath = assetData.importedPath;
                    var assetId   = assetData.assetId;
                    assets.Add(new AssetInfo(assetName, assetType, assetPath, assetId));
                }

                // collect generated prefab path.
                var generated     = new List <string>();
                var outputSources = new List <InternalAssetData>();

                Func <GameObject, string, bool, string> Prefabricate = (GameObject baseObject, string prefabName, bool forceGenerate) => {
                    var newPrefabOutputPath = Path.Combine(recommendedPrefabPath, prefabName);

                    if (forceGenerate || !GraphStackController.IsCachedForEachSource(inputSources, alreadyCached, newPrefabOutputPath))
                    {
                        // not cached, create new.
                        UnityEngine.Object prefabFile = PrefabUtility.CreateEmptyPrefab(newPrefabOutputPath);

                        // export prefab data.
                        PrefabUtility.ReplacePrefab(baseObject, prefabFile);

                        // save prefab.
                        AssetDatabase.Refresh(ImportAssetOptions.ImportRecursive);
                        AssetDatabase.SaveAssets();
                        generated.Add(newPrefabOutputPath);
                        cachedOrGenerated.Add(newPrefabOutputPath);
                        Debug.Log("AssetGraph prefab:" + newPrefabOutputPath + " is newly generated.");
                    }
                    else
                    {
                        // cached.
                        usedCache.Add(newPrefabOutputPath);
                        cachedOrGenerated.Add(newPrefabOutputPath);
                        Debug.Log("AssetGraph prefab:" + newPrefabOutputPath + " is already cached. if want to regenerate forcely, set Prefabricate(baseObject, prefabName, true) <- forcely regenerate prefab.");
                    }

                    // set used.
                    PrefabricateIsUsed();

                    return(newPrefabOutputPath);
                };

                if (!Directory.Exists(recommendedPrefabPath))
                {
                    // create recommended directory.
                    Directory.CreateDirectory(recommendedPrefabPath);
                }

                /*
                 *      execute inheritee's input method.
                 */
                try {
                    In(groupKey, assets, recommendedPrefabPath, Prefabricate);
                } catch (Exception e) {
                    Debug.LogError("Prefabricator:" + this + " error:" + e);
                }

                if (!isUsed)
                {
                    Debug.LogWarning("should use 'Prefabricate' method for create prefab in Prefabricator for cache.");
                }


                /*
                 *      add assets in this node to next output.
                 *      it contains "cached" or "generated as prefab" or "else" assets.
                 *      output all assets.
                 */
                var currentAssetsInThisNode = FileController.FilePathsInFolder(recommendedPrefabPath);
                foreach (var newAssetPath in currentAssetsInThisNode)
                {
                    if (generated.Contains(newAssetPath))
                    {
                        var newAsset = InternalAssetData.InternalAssetDataGeneratedByImporterOrPrefabricator(
                            newAssetPath,
                            AssetDatabase.AssetPathToGUID(newAssetPath),
                            AssetGraphInternalFunctions.GetAssetType(newAssetPath),
                            true
                            );
                        outputSources.Add(newAsset);
                    }
                    else
                    {
                        var newAsset = InternalAssetData.InternalAssetDataGeneratedByImporterOrPrefabricator(
                            newAssetPath,
                            AssetDatabase.AssetPathToGUID(newAssetPath),
                            AssetGraphInternalFunctions.GetAssetType(newAssetPath),
                            false
                            );
                        outputSources.Add(newAsset);
                    }
                }


                /*
                 *      add current resources to next node's resources.
                 */
                foreach (var assetData in inputSources)
                {
                    var inheritedInternalAssetData = InternalAssetData.InternalAssetDataByImporter(
                        assetData.traceId,
                        assetData.absoluteSourcePath,
                        assetData.sourceBasePath,
                        assetData.fileNameAndExtension,
                        assetData.pathUnderSourceBase,
                        assetData.importedPath,
                        assetData.assetId,
                        assetData.assetType
                        );
                    outputSources.Add(inheritedInternalAssetData);
                }

                outputDict[groupKey] = outputSources;
            }

            // delete unused cached prefabs.
            var unusedCachePaths = alreadyCached.Except(cachedOrGenerated).Where(path => !GraphStackController.IsMetaFile(path)).ToList();

            foreach (var unusedCachePath in unusedCachePaths)
            {
                // unbundlize unused prefabricated cached asset.
                var assetImporter = AssetImporter.GetAtPath(unusedCachePath);
                assetImporter.assetBundleName = string.Empty;

                FileController.DeleteFileThenDeleteFolderIfEmpty(unusedCachePath);
            }


            Output(nodeId, labelToNext, outputDict, usedCache);
        }
        public void Run(string nodeName, string nodeId, string connectionIdToNextNode, Dictionary <string, List <InternalAssetData> > groupedSources, List <string> alreadyCached, Action <string, string, Dictionary <string, List <InternalAssetData> >, List <string> > Output)
        {
            var usedCache = new List <string>();

            var invalids = new List <string>();

            foreach (var sources in groupedSources.Values)
            {
                foreach (var source in sources)
                {
                    if (string.IsNullOrEmpty(source.importedPath))
                    {
                        invalids.Add(source.pathUnderSourceBase);
                    }
                }
            }

            if (invalids.Any())
            {
                throw new NodeException(string.Join(", ", invalids.ToArray()) + " are not imported yet. These assets need to be imported before prefabricated.", nodeId);
            }

            var recommendedPrefabOutputDirectoryPath = FileController.PathCombine(AssetBundleGraphSettings.PREFABRICATOR_CACHE_PLACE, nodeId, GraphStackController.GetCurrentPlatformPackageFolder());

            var outputDict        = new Dictionary <string, List <InternalAssetData> >();
            var cachedOrGenerated = new List <string>();

            foreach (var groupKey in groupedSources.Keys)
            {
                var inputSources = groupedSources[groupKey];

                var recommendedPrefabPath = FileController.PathCombine(recommendedPrefabOutputDirectoryPath, groupKey);
                if (!recommendedPrefabPath.EndsWith(AssetBundleGraphSettings.UNITY_FOLDER_SEPARATOR.ToString()))
                {
                    recommendedPrefabPath = recommendedPrefabPath + AssetBundleGraphSettings.UNITY_FOLDER_SEPARATOR.ToString();
                }

                /*
                 *      ready input resource info for execute. not contains cache in this node.
                 */
                var assets = new List <AssetInfo>();
                foreach (var assetData in inputSources)
                {
                    var assetName = assetData.fileNameAndExtension;
                    var assetType = assetData.assetType;
                    var assetPath = assetData.importedPath;
                    var assetId   = assetData.assetId;
                    assets.Add(new AssetInfo(assetName, assetType, assetPath, assetId));
                }

                // collect generated prefab path.
                var generated     = new List <string>();
                var outputSources = new List <InternalAssetData>();


                /*
                 *      Prefabricate(GameObject baseObject, string prefabName, bool forceGenerate) method.
                 */
                Func <GameObject, string, bool, string> Prefabricate = (GameObject baseObject, string prefabName, bool forceGenerate) => {
                    var newPrefabOutputPath = Path.Combine(recommendedPrefabPath, prefabName);

                    if (forceGenerate || !GraphStackController.IsCachedForEachSource(inputSources, alreadyCached, newPrefabOutputPath))
                    {
                        // not cached, create new.
                        UnityEngine.Object prefabFile = PrefabUtility.CreateEmptyPrefab(newPrefabOutputPath);

                        // export prefab data.
                        PrefabUtility.ReplacePrefab(baseObject, prefabFile);

                        // save prefab.
                        AssetDatabase.Refresh(ImportAssetOptions.ImportRecursive);
                        AssetDatabase.SaveAssets();
                        generated.Add(newPrefabOutputPath);
                        cachedOrGenerated.Add(newPrefabOutputPath);
                        Debug.Log(nodeName + " created new prefab: " + newPrefabOutputPath);
                    }
                    else
                    {
                        // cached.
                        usedCache.Add(newPrefabOutputPath);
                        cachedOrGenerated.Add(newPrefabOutputPath);
                        Debug.Log(nodeName + " used cached prefab: " + newPrefabOutputPath);
                    }

                    isPrefabricateFunctionCalled = true;

                    return(newPrefabOutputPath);
                };

                if (!Directory.Exists(recommendedPrefabPath))
                {
                    // create recommended directory.
                    Directory.CreateDirectory(recommendedPrefabPath);
                }

                /*
                 *      execute inheritee's input method.
                 */
                try {
                    CreatePrefab(nodeName, nodeId, groupKey, assets, recommendedPrefabPath, Prefabricate);
                } catch (Exception e) {
                    Debug.LogError(nodeName + " Error:" + e);
                    throw new NodeException(nodeName + " Error:" + e, nodeId);
                }

                if (!isPrefabricateFunctionCalled)
                {
                    Debug.LogWarning(nodeName + ": Prefabricate delegate was not called. Prefab might not be created properly.");
                }

                /*
                 *      ready assets-output-data from this node to next output.
                 *      it contains "cached" or "generated as prefab" or "else" assets.
                 *      output all assets.
                 */
                var currentAssetsInThisNode = FileController.FilePathsInFolder(recommendedPrefabPath);
                foreach (var generatedCandidateAssetPath in currentAssetsInThisNode)
                {
                    /*
                     *      candidate is new, regenerated prefab.
                     */
                    if (generated.Contains(generatedCandidateAssetPath))
                    {
                        var newAsset = InternalAssetData.InternalAssetDataGeneratedByImporterOrModifierOrPrefabricator(
                            generatedCandidateAssetPath,
                            AssetDatabase.AssetPathToGUID(generatedCandidateAssetPath),
                            AssetBundleGraphInternalFunctions.GetAssetType(generatedCandidateAssetPath),
                            true,
                            false
                            );
                        outputSources.Add(newAsset);
                        continue;
                    }

                    /*
                     *      candidate is not new prefab.
                     */
                    var cachedPrefabAsset = InternalAssetData.InternalAssetDataGeneratedByImporterOrModifierOrPrefabricator(
                        generatedCandidateAssetPath,
                        AssetDatabase.AssetPathToGUID(generatedCandidateAssetPath),
                        AssetBundleGraphInternalFunctions.GetAssetType(generatedCandidateAssetPath),
                        false,
                        false
                        );
                    outputSources.Add(cachedPrefabAsset);
                }


                /*
                 *      add current resources to next node's resources.
                 */
                outputSources.AddRange(inputSources);

                outputDict[groupKey] = outputSources;
            }

            // delete unused cached prefabs.
            var unusedCachePaths = alreadyCached.Except(cachedOrGenerated).Where(path => !GraphStackController.IsMetaFile(path)).ToList();

            foreach (var unusedCachePath in unusedCachePaths)
            {
                // unbundlize unused prefabricated cached asset.
                var assetImporter = AssetImporter.GetAtPath(unusedCachePath);
                assetImporter.assetBundleName = string.Empty;

                FileController.DeleteFileThenDeleteFolderIfEmpty(unusedCachePath);
            }


            Output(nodeId, connectionIdToNextNode, outputDict, usedCache);
        }