public void Run(string nodeName, string connectionIdToNextNode, string labelToNext, Dictionary <string, List <InternalAssetData> > groupedSources, List <string> alreadyCached, Action <string, string, Dictionary <string, List <InternalAssetData> >, List <string> > Output) { var recommendedBundleOutputDirSource = FileController.PathCombine(AssetBundleGraphSettings.BUNDLEBUILDER_CACHE_PLACE, connectionIdToNextNode); var recommendedBundleOutputDir = FileController.PathCombine(recommendedBundleOutputDirSource, GraphStackController.GetCurrentPlatformPackageFolder()); if (!Directory.Exists(recommendedBundleOutputDir)) { Directory.CreateDirectory(recommendedBundleOutputDir); } /* * merge multi group into ["0"] group. */ var intendedAssetNames = new List <string>(); foreach (var groupKey in groupedSources.Keys) { var internalAssetsOfCurrentGroup = groupedSources[groupKey]; foreach (var internalAsset in internalAssetsOfCurrentGroup) { intendedAssetNames.Add(internalAsset.fileNameAndExtension); intendedAssetNames.Add(internalAsset.fileNameAndExtension + AssetBundleGraphSettings.MANIFEST_FOOTER); } } /* * platform's bundle & manifest. * e.g. iOS & iOS.manifest. */ var currentPlatform_Package_BundleFile = GraphStackController.GetCurrentPlatformPackageFolder(); var currentPlatform_Package_BundleFileManifest = currentPlatform_Package_BundleFile + AssetBundleGraphSettings.MANIFEST_FOOTER; intendedAssetNames.Add(currentPlatform_Package_BundleFile); intendedAssetNames.Add(currentPlatform_Package_BundleFileManifest); /* * delete not intended assets. */ foreach (var alreadyCachedPath in alreadyCached) { var cachedFileName = Path.GetFileName(alreadyCachedPath); if (intendedAssetNames.Contains(cachedFileName)) { continue; } File.Delete(alreadyCachedPath); } var assetBundleOptions = BuildAssetBundleOptions.None; foreach (var enabled in bundleOptions) { switch (enabled) { case "Uncompressed AssetBundle": { assetBundleOptions = assetBundleOptions | BuildAssetBundleOptions.UncompressedAssetBundle; break; } case "Disable Write TypeTree": { assetBundleOptions = assetBundleOptions | BuildAssetBundleOptions.DisableWriteTypeTree; break; } case "Deterministic AssetBundle": { assetBundleOptions = assetBundleOptions | BuildAssetBundleOptions.DeterministicAssetBundle; break; } case "Force Rebuild AssetBundle": { assetBundleOptions = assetBundleOptions | BuildAssetBundleOptions.ForceRebuildAssetBundle; break; } case "Ignore TypeTree Changes": { assetBundleOptions = assetBundleOptions | BuildAssetBundleOptions.IgnoreTypeTreeChanges; break; } case "Append Hash To AssetBundle Name": { assetBundleOptions = assetBundleOptions | BuildAssetBundleOptions.AppendHashToAssetBundleName; break; } #if UNITY_5_3 case "ChunkBased Compression": { assetBundleOptions = assetBundleOptions | BuildAssetBundleOptions.ChunkBasedCompression; break; } #endif } } BuildPipeline.BuildAssetBundles(recommendedBundleOutputDir, assetBundleOptions, EditorUserBuildSettings.activeBuildTarget); /* * check assumed bundlized resources and actual generated assetbundles. * * "assuned bundlized resources info from bundlizer" are contained by "actual bundlized resources". */ var outputDict = new Dictionary <string, List <InternalAssetData> >(); var outputSources = new List <InternalAssetData>(); var newAssetPaths = new List <string>(); var generatedAssetBundlePaths = FileController.FilePathsInFolder(recommendedBundleOutputDir); foreach (var newAssetPath in generatedAssetBundlePaths) { newAssetPaths.Add(newAssetPath); var newAssetData = InternalAssetData.InternalAssetDataGeneratedByBundleBuilder(newAssetPath); outputSources.Add(newAssetData); } // compare, erase & notice. var containedAssetBundles = new List <string>(); // collect intended output. foreach (var generatedAssetPath in newAssetPaths) { var generatedAssetName = Path.GetFileName(generatedAssetPath); // collect intended assetBundle & assetBundleManifest file. foreach (var bundledName in intendedAssetNames) { if (generatedAssetName == bundledName) { containedAssetBundles.Add(generatedAssetPath); continue; } var bundleManifestName = bundledName + AssetBundleGraphSettings.MANIFEST_FOOTER; if (generatedAssetName == bundleManifestName) { containedAssetBundles.Add(generatedAssetPath); continue; } } } var diffs = newAssetPaths.Except(containedAssetBundles); foreach (var diff in diffs) { Debug.LogWarning(nodeName + ": AssetBundle " + diff + " is not intended to build. Check if unnecessary importer or prefabricator exists in the graph."); } outputDict["0"] = outputSources; var usedCache = new List <string>(alreadyCached); Output(connectionIdToNextNode, 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); }
public void Run(string nodeName, string nodeId, string unused_connectionIdToNextNode, Dictionary <string, List <InternalAssetData> > groupedSources, List <string> alreadyCached, Action <string, string, Dictionary <string, List <InternalAssetData> >, List <string> > Output) { ValidateBundleNameTemplate( bundleNameTemplate, () => { throw new AssetBundleGraphBuildException(nodeName + ": Bundle Name Template is empty."); } ); var recommendedBundleOutputDir = FileController.PathCombine(AssetBundleGraphSettings.BUNDLIZER_CACHE_PLACE, nodeId, GraphStackController.GetCurrentPlatformPackageFolder()); var outputDict = new Dictionary <string, List <InternalAssetData> >(); foreach (var groupKey in groupedSources.Keys) { var inputSources = groupedSources[groupKey]; var reservedBundlePath = BundlizeAssets(nodeName, groupKey, inputSources, recommendedBundleOutputDir, true); if (string.IsNullOrEmpty(reservedBundlePath)) { continue; } var outputSources = new List <InternalAssetData>(); var newAssetData = InternalAssetData.InternalAssetDataGeneratedByBundlizer(reservedBundlePath); outputSources.Add(newAssetData); outputDict[groupKey] = outputSources; } if (assetsOutputConnectionId != AssetBundleGraphSettings.BUNDLIZER_FAKE_CONNECTION_ID) { Output(nodeId, assetsOutputConnectionId, outputDict, new List <string>()); } /* * generate additional output: * output bundle resources for next node, for generate another AssetBundles with dependency. */ if (outputResource) { if (resourcesOutputConnectionId != AssetBundleGraphSettings.BUNDLIZER_FAKE_CONNECTION_ID) { Output(nodeId, resourcesOutputConnectionId, groupedSources, new List <string>()); } } }
public void Setup(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 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> >(); 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>(); /* * Prefabricate(string prefabName) method. */ Func <string, string> Prefabricate = (string prefabName) => { var newPrefabOutputPath = Path.Combine(recommendedPrefabPath, prefabName); generated.Add(newPrefabOutputPath); isPrefabricateFunctionCalled = true; return(newPrefabOutputPath); }; ValidateCanCreatePrefab(nodeName, nodeId, groupKey, assets, recommendedPrefabPath, Prefabricate); if (!isPrefabricateFunctionCalled) { Debug.LogWarning(nodeName + ": Prefabricate delegate was not called. Prefab might not be created properly."); } foreach (var generatedPrefabPath in generated) { var newAsset = InternalAssetData.InternalAssetDataGeneratedByImporterOrModifierOrPrefabricator( generatedPrefabPath, string.Empty, // dummy data typeof(string), // dummy data true, // absolutely new in setup. false ); if (!outputDict.ContainsKey(groupKey)) { outputDict[groupKey] = new List <InternalAssetData>(); } outputDict[groupKey].Add(newAsset); } outputDict[groupKey].AddRange(inputSources); } Output(nodeId, connectionIdToNextNode, outputDict, new List <string>()); }