public void Run(BuildTarget target, 
			NodeData node, 
			ConnectionPointData inputPoint,
			ConnectionData connectionToOutput, 
			Dictionary<string, List<Asset>> inputGroupAssets, 
			List<string> alreadyCached, 
			Action<ConnectionData, Dictionary<string, List<Asset>>, List<string>> Output)
        {
            var incomingAssets = inputGroupAssets.SelectMany(v => v.Value).ToList();

            var modifier = ModifierUtility.CreateModifier(node, target);
            UnityEngine.Assertions.Assert.IsNotNull(modifier);
            bool isAnyAssetModified = false;

            foreach(var asset in incomingAssets) {
                var loadedAsset = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(asset.importFrom);
                if(modifier.IsModified(loadedAsset)) {
                    modifier.Modify(loadedAsset);
                    isAnyAssetModified = true;
                }
            }

            if(isAnyAssetModified) {
                // apply asset setting changes to AssetDatabase.
                AssetDatabase.Refresh();
            }

            // Modifier does not add, filter or change structure of group, so just pass given group of assets
            Output(connectionToOutput, inputGroupAssets, null);
        }
        public void Run(BuildTarget target, 
			NodeData node, 
			ConnectionPointData inputPoint,
			ConnectionData connectionToOutput, 
			Dictionary<string, List<Asset>> inputGroupAssets, 
			List<string> alreadyCached, 
			Action<ConnectionData, Dictionary<string, List<Asset>>, List<string>> Output)
        {
            var builder = PrefabBuilderUtility.CreatePrefabBuilder(node, target);
            UnityEngine.Assertions.Assert.IsNotNull(builder);

            var prefabOutputDir = FileUtility.EnsurePrefabBuilderCacheDirExists(target, node);
            Dictionary<string, List<Asset>> output = new Dictionary<string, List<Asset>>();

            foreach(var key in inputGroupAssets.Keys) {
                var allAssets = LoadAllAssets(inputGroupAssets[key]);
                var prefabFileName = builder.CanCreatePrefab(key, allAssets);
                UnityEngine.GameObject obj = builder.CreatePrefab(key, allAssets);
                if(obj == null) {
                    throw new AssetBundleGraphException(string.Format("{0} :PrefabBuilder {1} returned null in CreatePrefab() [groupKey:{2}]",
                        node.Name, builder.GetType().FullName, key));
                }

                var prefabSavePath = FileUtility.PathCombine(prefabOutputDir, prefabFileName + ".prefab");
                PrefabUtility.CreatePrefab(prefabSavePath, obj, ReplacePrefabOptions.Default);

                output[key] = new List<Asset> () {
                    Asset.CreateAssetWithImportPath(prefabSavePath)
                };
                GameObject.DestroyImmediate(obj);
            }

            Output(connectionToOutput, output, null);
        }
예제 #3
0
 public ConnectionData(V1.ConnectionData v1)
 {
     m_id         = v1.Id;
     m_fromNodeId = v1.FromNodeId;
     m_fromNodeConnectionPointId = v1.FromNodeConnectionPointId;
     m_toNodeId = v1.ToNodeId;
     m_toNodeConnectionPoiontId = v1.ToNodeConnectionPointId;
     m_label = v1.Label;
 }
        public void Run(BuildTarget target, 
			NodeData node, 
			ConnectionPointData inputPoint,
			ConnectionData connectionToOutput, 
			Dictionary<string, List<Asset>> inputGroupAssets, 
			List<string> alreadyCached, 
			Action<ConnectionData, Dictionary<string, List<Asset>>, List<string>> Output)
        {
            Export(target, node, inputPoint, connectionToOutput, inputGroupAssets, Output, true);
        }
        public void Setup(BuildTarget target, 
			NodeData node, 
			ConnectionPointData inputPoint,
			ConnectionData connectionToOutput, 
			Dictionary<string, List<Asset>> inputGroupAssets, 
			List<string> alreadyCached, 
			Action<ConnectionData, Dictionary<string, List<Asset>>, List<string>> Output)
        {
            ValidateBundleNameTemplate(
                node.BundleNameTemplate[target],
                () => {
                    throw new NodeException(node.Name + ":Bundle Name Template is empty.", node.Id);
                }
            );

            var variantNames = node.Variants.Select(v=>v.Name).ToList();
            foreach(var variant in node.Variants) {
                ValidateVariantName(variant.Name, variantNames,
                    () => {
                        throw new NodeException(node.Name + ":Variant name is empty.", node.Id);
                    },
                    () => {
                        throw new NodeException(node.Name + ":Variant name cannot contain whitespace \"" + variant.Name + "\".", node.Id);
                    },
                    () => {
                        throw new NodeException(node.Name + ":Variant name already exists \"" + variant.Name + "\".", node.Id);
                    });
            }

            /*
             * Check if incoming asset has valid import path
             */
            var invalids = new List<Asset>();
            foreach (var groupKey in inputGroupAssets.Keys) {
                inputGroupAssets[groupKey].ForEach( a => { if (string.IsNullOrEmpty(a.importFrom)) invalids.Add(a); } );
            }
            if (invalids.Any()) {
                throw new NodeException(node.Name +
                    ": Invalid files are found. Following files need to be imported to put into asset bundle: " +
                    string.Join(", ", invalids.Select(a =>a.absoluteAssetPath).ToArray()), node.Id );
            }

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

            var currentVariant = node.Variants.Find( v => v.ConnectionPoint == inputPoint );
            var variantName = (currentVariant == null) ? null : currentVariant.Name;

            // set configured assets in bundle name
            foreach (var groupKey in inputGroupAssets.Keys) {
                var bundleName = GetBundleName(target, node, groupKey, variantName);
                output[bundleName] = ConfigureAssetBundleSettings(variantName, inputGroupAssets[groupKey]);
            }

            Output(connectionToOutput, output, null);
        }
예제 #6
0
        public void Setup(BuildTarget target, 
			NodeData node, 
			ConnectionPointData inputPoint,
			ConnectionData connectionToOutput, 
			Dictionary<string, List<Asset>> inputGroupAssets, 
			List<string> alreadyCached, 
			Action<ConnectionData, Dictionary<string, List<Asset>>, List<string>> Output)
        {
            node.ValidateOverlappingFilterCondition(true);
            Filter(node, inputGroupAssets, Output);
        }
        private void GroupingOutput(BuildTarget target, 
			NodeData node, 
			ConnectionPointData inputPoint,
			ConnectionData connectionToOutput, 
			Dictionary<string, List<Asset>> inputGroupAssets, 
			Action<ConnectionData, Dictionary<string, List<Asset>>, List<string>> Output)
        {
            ValidateGroupingKeyword(
                node.GroupingKeywords[target],
                () => {
                    throw new NodeException("Grouping Keyword can not be empty.", node.Id);
                },
                () => {
                    throw new NodeException(String.Format("Grouping Keyword must contain {0} for numbering: currently {1}", AssetBundleGraphSettings.KEYWORD_WILDCARD, node.GroupingKeywords[target]), node.Id);
                }
            );

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

            var mergedGroupedSources = new List<Asset>();

            foreach (var groupKey in inputGroupAssets.Keys) {
                mergedGroupedSources.AddRange(inputGroupAssets[groupKey]);
            }

            var groupingKeyword = node.GroupingKeywords[target];
            var split = groupingKeyword.Split(AssetBundleGraphSettings.KEYWORD_WILDCARD);
            var groupingKeywordPrefix  = split[0];
            var groupingKeywordPostfix = split[1];

            foreach (var source in mergedGroupedSources) {
                var targetPath = source.GetAbsolutePathOrImportedPath();

                var regex = new Regex(groupingKeywordPrefix + "(.*?)" + groupingKeywordPostfix);
                var match = regex.Match(targetPath);

                if (match.Success) {
                    var newGroupingKey = match.Groups[1].Value;
                    if (!outputDict.ContainsKey(newGroupingKey)) outputDict[newGroupingKey] = new List<Asset>();
                    outputDict[newGroupingKey].Add(source);
                }
            }

            Output(connectionToOutput, outputDict, null);
        }
예제 #8
0
        void Load(BuildTarget target, 
			NodeData node, 
			ConnectionData connectionToOutput, 
			Dictionary<string, List<Asset>> inputGroupAssets, 
			Action<ConnectionData, Dictionary<string, List<Asset>>, List<string>> Output)
        {
            // SOMEWHERE_FULLPATH/PROJECT_FOLDER/Assets/
            var assetsFolderPath = Application.dataPath + AssetBundleGraphSettings.UNITY_FOLDER_SEPARATOR;

            var outputSource = new List<Asset>();
            var targetFilePaths = FileUtility.GetAllFilePathsInFolder(node.GetLoaderFullLoadPath(target));

            foreach (var targetFilePath in targetFilePaths) {

                if(targetFilePath.Contains(AssetBundleGraphSettings.ASSETBUNDLEGRAPH_PATH)) {
                    continue;
                }

                // already contained into Assets/ folder.
                // imported path is Assets/SOMEWHERE_FILE_EXISTS.
                if (targetFilePath.StartsWith(assetsFolderPath)) {
                    var relativePath = targetFilePath.Replace(assetsFolderPath, AssetBundleGraphSettings.ASSETS_PATH);

                    var assetType = TypeUtility.GetTypeOfAsset(relativePath);
                    if (assetType == typeof(object)) {
                        continue;
                    }

                    outputSource.Add(Asset.CreateNewAssetFromLoader(targetFilePath, relativePath));
                    continue;
                }

                throw new NodeException(node.Name + ": Invalid Load Path. Path must start with Assets/", node.Name);
            }

            var outputDir = new Dictionary<string, List<Asset>> {
                {"0", outputSource}
            };

            Output(connectionToOutput, outputDir, null);
        }
        public void Setup(BuildTarget target, 
			NodeData node, 
			ConnectionPointData inputPoint,
			ConnectionData connectionToOutput, 
			Dictionary<string, List<Asset>> inputGroupAssets, 
			List<string> alreadyCached, 
			Action<ConnectionData, Dictionary<string, List<Asset>>, List<string>> Output)
        {
            ValidateExportPath(
                node.ExporterExportPath[target],
                node.ExporterExportPath[target],
                () => {
                    throw new NodeException(node.Name + ":Export Path is empty.", node.Id);
                },
                () => {
                    throw new NodeException(node.Name + ":Directory set to Export Path does not exist. Path:" + node.ExporterExportPath[target], node.Id);
                }
            );

            Export(target, node, inputPoint, connectionToOutput, inputGroupAssets, Output, false);
        }
        public void Run(BuildTarget target, 
			NodeData node, 
			ConnectionPointData inputPoint,
			ConnectionData connectionToOutput, 
			Dictionary<string, List<Asset>> inputGroupAssets, 
			List<string> alreadyCached, 
			Action<ConnectionData, Dictionary<string, List<Asset>>, List<string>> Output)
        {
            var output = new Dictionary<string, List<Asset>>();

            var currentVariant = node.Variants.Find( v => v.ConnectionPoint == inputPoint );
            var variantName = (currentVariant == null) ? null : currentVariant.Name;

            // set configured assets in bundle name
            foreach (var groupKey in inputGroupAssets.Keys) {
                var bundleName = GetBundleName(target, node, groupKey, variantName);
                output[bundleName] = ConfigureAssetBundleSettings(variantName, inputGroupAssets[groupKey]);
            }

            Output(connectionToOutput, output, null);
        }
예제 #11
0
        public void Setup(BuildTarget target, 
			NodeData node, 
			ConnectionPointData inputPoint,
			ConnectionData connectionToOutput, 
			Dictionary<string, List<Asset>> inputGroupAssets, 
			List<string> alreadyCached, 
			Action<ConnectionData, Dictionary<string, List<Asset>>, List<string>> Output)
        {
            ValidateLoadPath(
                node.LoaderLoadPath[target],
                node.GetLoaderFullLoadPath(target),
                () => {
                    //can be empty
                    //throw new NodeException(node.Name + ": Load Path is empty.", node.Id);
                },
                () => {
                    throw new NodeException(node.Name + ": Directory not found: " + node.GetLoaderFullLoadPath(target), node.Id);
                }
            );

            Load(target, node, connectionToOutput, inputGroupAssets, Output);
        }
예제 #12
0
        private void Export(BuildTarget target, 
			NodeData node, 
			ConnectionPointData inputPoint,
			ConnectionData connectionToOutput, 
			Dictionary<string, List<Asset>> inputGroupAssets, 
			Action<ConnectionData, Dictionary<string, List<Asset>>, List<string>> Output,
			bool isRun)
        {
            var outputDict = new Dictionary<string, List<Asset>>();
            outputDict["0"] = new List<Asset>();

            var failedExports = new List<string>();

            foreach (var groupKey in inputGroupAssets.Keys) {
                var exportedAssets = new List<Asset>();
                var inputSources = inputGroupAssets[groupKey];

                foreach (var source in inputSources) {
                    if (isRun) {
                        if (!Directory.Exists(node.ExporterExportPath[target])) {
                            Directory.CreateDirectory(node.ExporterExportPath[target]);
                        }
                    }

                    var destinationSourcePath = source.importFrom;

                    // in bundleBulider, use platform-package folder for export destination.
                    if (destinationSourcePath.StartsWith(AssetBundleGraphSettings.BUNDLEBUILDER_CACHE_PLACE)) {
                        var depth = AssetBundleGraphSettings.BUNDLEBUILDER_CACHE_PLACE.Split(AssetBundleGraphSettings.UNITY_FOLDER_SEPARATOR).Length + 1;

                        var splitted = destinationSourcePath.Split(AssetBundleGraphSettings.UNITY_FOLDER_SEPARATOR);
                        var reducedArray = new string[splitted.Length - depth];

                        Array.Copy(splitted, depth, reducedArray, 0, reducedArray.Length);
                        var fromDepthToEnd = string.Join(AssetBundleGraphSettings.UNITY_FOLDER_SEPARATOR.ToString(), reducedArray);

                        destinationSourcePath = fromDepthToEnd;
                    }

                    var destination = FileUtility.PathCombine(node.ExporterExportPath[target], destinationSourcePath);

                    var parentDir = Directory.GetParent(destination).ToString();

                    if (isRun) {
                        if (!Directory.Exists(parentDir)) {
                            Directory.CreateDirectory(parentDir);
                        }
                        if (File.Exists(destination)) {
                            File.Delete(destination);
                        }
                        if (string.IsNullOrEmpty(source.importFrom)) {
                            failedExports.Add(source.absoluteAssetPath);
                            continue;
                        }
                        try {
                            File.Copy(source.importFrom, destination);
                        } catch(Exception e) {
                            failedExports.Add(source.importFrom);
                            Debug.LogError(node.Name + ": Error occured: " + e.Message);
                        }
                    }

                    var exportedAsset = Asset.CreateAssetWithExportPath(destination);
                    exportedAssets.Add(exportedAsset);
                }
                outputDict["0"].AddRange(exportedAssets);
            }

            if (failedExports.Any()) {
                Debug.LogError(node.Name + ": Failed to export files. All files must be imported before exporting: " + string.Join(", ", failedExports.ToArray()));
            }

            Output(connectionToOutput, outputDict, null);
        }
        public void Setup(BuildTarget target, 
			NodeData node, 
			ConnectionPointData inputPoint,
			ConnectionData connectionToOutput, 
			Dictionary<string, List<Asset>> inputGroupAssets, 
			List<string> alreadyCached, 
			Action<ConnectionData, Dictionary<string, List<Asset>>, List<string>> Output)
        {
            var incomingAssets = inputGroupAssets.SelectMany(v => v.Value).ToList();

            Action<Type, Type, Asset> multipleAssetTypeFound = (Type expectedType, Type foundType, Asset foundAsset) => {
                throw new NodeException(string.Format("{3} :ImportSetting expect {0}, but different type of incoming asset is found({1} {2})",
                    expectedType.FullName, foundType.FullName, foundAsset.fileNameAndExtension, node.Name), node.Id);
            };

            Action<Type> unsupportedType = (Type unsupported) => {
                throw new NodeException(string.Format("{0} :Incoming asset type is not supported by ImportSetting (Incoming type:{1}). Perhaps you want to use Modifier instead?",
                    node.Name, (unsupported != null)?unsupported.FullName:"null"), node.Id);
            };

            Action<Type, Type> incomingTypeMismatch = (Type expected, Type incoming) => {
                throw new NodeException(string.Format("{0} :Incoming asset type is does not match with this ImportSetting (Expected type:{1}, Incoming type:{2}).",
                    node.Name, (expected != null)?expected.FullName:"null", (incoming != null)?incoming.FullName:"null"), node.Id);
            };

            Action<ConfigStatus> errorInConfig = (ConfigStatus _) => {
                // give a try first in sampling file
                if(incomingAssets.Any()) {
                    SaveSampleFile(node, incomingAssets[0]);

                    ValidateInputSetting(node, target, incomingAssets, multipleAssetTypeFound, unsupportedType, incomingTypeMismatch, (ConfigStatus eType) => {
                        if(eType == ConfigStatus.NoSampleFound) {
                            throw new NodeException(node.Name + " :ImportSetting has no sampling file. Please configure it from Inspector.", node.Id);
                        }
                        if(eType == ConfigStatus.TooManySamplesFound) {
                            throw new NodeException(node.Name + " :ImportSetting has too many sampling file. Please fix it from Inspector.", node.Id);
                        }
                    });
                }
            };

            ValidateInputSetting(node, target, incomingAssets, multipleAssetTypeFound, unsupportedType, incomingTypeMismatch, errorInConfig);

            // ImportSettings does not add, filter or change structure of group, so just pass given group of assets
            Output(connectionToOutput, inputGroupAssets, null);
        }
예제 #14
0
        private void Export(BuildTarget target,
                            NodeData node,
                            ConnectionPointData inputPoint,
                            ConnectionData connectionToOutput,
                            Dictionary <string, List <Asset> > inputGroupAssets,
                            Action <ConnectionData, Dictionary <string, List <Asset> >, List <string> > Output,
                            bool isRun)
        {
            var outputDict = new Dictionary <string, List <Asset> >();

            outputDict["0"] = new List <Asset>();

            var exportPath = FileUtility.GetPathWithProjectPath(node.ExporterExportPath[target]);

            if (isRun)
            {
                if (node.ExporterExportOption[target] == (int)ExporterExportOption.DeleteAndRecreateExportDirectory)
                {
                    if (Directory.Exists(exportPath))
                    {
                        Directory.Delete(exportPath, true);
                    }
                }

                if (node.ExporterExportOption[target] != (int)ExporterExportOption.ErrorIfNoExportDirectoryFound)
                {
                    if (!Directory.Exists(exportPath))
                    {
                        Directory.CreateDirectory(exportPath);
                    }
                }
            }

            var failedExports = new List <string>();

            foreach (var groupKey in inputGroupAssets.Keys)
            {
                var exportedAssets = new List <Asset>();
                var inputSources   = inputGroupAssets[groupKey];

                foreach (var source in inputSources)
                {
                    var destinationSourcePath = source.importFrom;

                    // in bundleBulider, use platform-package folder for export destination.
                    if (destinationSourcePath.StartsWith(AssetBundleGraphSettings.BUNDLEBUILDER_CACHE_PLACE))
                    {
                        var depth = AssetBundleGraphSettings.BUNDLEBUILDER_CACHE_PLACE.Split(AssetBundleGraphSettings.UNITY_FOLDER_SEPARATOR).Length + 1;

                        var splitted     = destinationSourcePath.Split(AssetBundleGraphSettings.UNITY_FOLDER_SEPARATOR);
                        var reducedArray = new string[splitted.Length - depth];

                        Array.Copy(splitted, depth, reducedArray, 0, reducedArray.Length);
                        var fromDepthToEnd = string.Join(AssetBundleGraphSettings.UNITY_FOLDER_SEPARATOR.ToString(), reducedArray);

                        destinationSourcePath = fromDepthToEnd;
                    }

                    var destination = FileUtility.PathCombine(exportPath, destinationSourcePath);

                    var parentDir = Directory.GetParent(destination).ToString();

                    if (isRun)
                    {
                        if (!Directory.Exists(parentDir))
                        {
                            Directory.CreateDirectory(parentDir);
                        }
                        if (File.Exists(destination))
                        {
                            File.Delete(destination);
                        }
                        if (string.IsNullOrEmpty(source.importFrom))
                        {
                            failedExports.Add(source.absoluteAssetPath);
                            continue;
                        }
                        try {
                            File.Copy(source.importFrom, destination);
                        } catch (Exception e) {
                            failedExports.Add(source.importFrom);
                            Debug.LogError(node.Name + ": Error occured: " + e.Message);
                        }
                    }

                    var exportedAsset = Asset.CreateAssetWithExportPath(destination);
                    exportedAssets.Add(exportedAsset);
                }
                outputDict["0"].AddRange(exportedAssets);
            }

            if (failedExports.Any())
            {
                Debug.LogError(node.Name + ": Failed to export files. All files must be imported before exporting: " + string.Join(", ", failedExports.ToArray()));
            }

            Output(connectionToOutput, outputDict, null);
        }
        public void Run(BuildTarget target,
                        NodeData node,
                        ConnectionPointData inputPoint,
                        ConnectionData connectionToOutput,
                        Dictionary <string, List <Asset> > inputGroupAssets,
                        List <string> alreadyCached,
                        Action <ConnectionData, Dictionary <string, List <Asset> >, List <string> > Output)
        {
            var bundleOutputDir = FileUtility.EnsureAssetBundleCacheDirExists(target, node);

            var bundleNames    = inputGroupAssets.Keys.ToList();
            var bundleVariants = new Dictionary <string, List <string> >();

            // get all variant name for bundles
            foreach (var name in bundleNames)
            {
                bundleVariants[name] = new List <string>();
                var assets = inputGroupAssets[name];
                foreach (var a in assets)
                {
                    var variantName = a.variantName;
                    if (!bundleVariants[name].Contains(variantName))
                    {
                        bundleVariants[name].Add(variantName);
                    }
                }
            }

            int validNames = 0;

            foreach (var name in bundleNames)
            {
                var assets = inputGroupAssets[name];
                // we do not build bundle without any asset
                if (assets.Count > 0)
                {
                    validNames += bundleVariants[name].Count;
                }
            }

            AssetBundleBuild[] bundleBuild = new AssetBundleBuild[validNames];

            int bbIndex = 0;

            foreach (var name in bundleNames)
            {
                foreach (var v in bundleVariants[name])
                {
                    var bundleName = name;
                    var assets     = inputGroupAssets[name];

                    if (assets.Count <= 0)
                    {
                        continue;
                    }

                    bundleBuild[bbIndex].assetBundleName    = bundleName;
                    bundleBuild[bbIndex].assetBundleVariant = v;
                    bundleBuild[bbIndex].assetNames         = assets.Where(x => x.variantName == v).Select(x => x.importFrom).ToArray();
                    ++bbIndex;
                }
            }


            BuildPipeline.BuildAssetBundles(bundleOutputDir, bundleBuild, (BuildAssetBundleOptions)node.BundleBuilderBundleOptions[target], target);


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

            output[key] = new List <Asset>();

            var generatedFiles = FileUtility.GetAllFilePathsInFolder(bundleOutputDir);

            // add manifest file
            bundleNames.Add(BuildTargetUtility.TargetToAssetBundlePlatformName(target));
            foreach (var path in generatedFiles)
            {
                var fileName = Path.GetFileName(path);
                if (IsFileIntendedItem(fileName, bundleNames))
                {
                    output[key].Add(Asset.CreateAssetWithImportPath(path));
                }
                else
                {
                    Debug.LogWarning(node.Name + ":Irrelevant file found in assetbundle cache folder:" + fileName);
                }
            }

            Output(connectionToOutput, output, alreadyCached);
        }
        public void Setup(BuildTarget target, 
			NodeData node, 
			ConnectionPointData inputPoint,
			ConnectionData connectionToOutput, 
			Dictionary<string, List<Asset>> inputGroupAssets, 
			List<string> alreadyCached, 
			Action<ConnectionData, Dictionary<string, List<Asset>>, List<string>> Output)
        {
            ValidatePrefabBuilder(node, target, inputGroupAssets,
                () => {
                    throw new NodeException(node.Name + " :PrefabBuilder is not configured. Please configure from Inspector.", node.Id);
                },
                () => {
                    throw new NodeException(node.Name + " :Failed to create PrefabBuilder from settings. Please fix settings from Inspector.", node.Id);
                },
                (string groupKey) => {
                    throw new NodeException(string.Format("{0} :Can not create prefab with incoming assets for group {1}.", node.Name, groupKey), node.Id);
                },
                (Asset badAsset) => {
                    throw new NodeException(string.Format("{0} :Can not import incoming asset {1}.", node.Name, badAsset.fileNameAndExtension), node.Id);
                }
            );

            var builder = PrefabBuilderUtility.CreatePrefabBuilder(node, target);
            UnityEngine.Assertions.Assert.IsNotNull(builder);

            var prefabOutputDir = FileUtility.EnsurePrefabBuilderCacheDirExists(target, node);
            Dictionary<string, List<Asset>> output = new Dictionary<string, List<Asset>>();

            foreach(var key in inputGroupAssets.Keys) {
                var prefabFileName = builder.CanCreatePrefab(key, LoadAllAssets(inputGroupAssets[key]));
                output[key] = new List<Asset> () {
                    Asset.CreateAssetWithImportPath(FileUtility.PathCombine(prefabOutputDir, prefabFileName + ".prefab"))
                };
            }

            Output(connectionToOutput, output, null);
        }
        public void Run(BuildTarget target, 
			NodeData node, 
			ConnectionPointData inputPoint,
			ConnectionData connectionToOutput, 
			Dictionary<string, List<Asset>> inputGroupAssets, 
			List<string> alreadyCached, 
			Action<ConnectionData, Dictionary<string, List<Asset>>, List<string>> Output)
        {
            var incomingAssets = inputGroupAssets.SelectMany(v => v.Value).ToList();

            ApplyImportSetting(node, incomingAssets);

            Output(connectionToOutput, inputGroupAssets, null);
        }
        public void Run(BuildTarget target, 
			NodeData node, 
			ConnectionPointData inputPoint,
			ConnectionData connectionToOutput, 
			Dictionary<string, List<Asset>> inputGroupAssets, 
			List<string> alreadyCached, 
			Action<ConnectionData, Dictionary<string, List<Asset>>, List<string>> Output)
        {
            var bundleOutputDir = FileUtility.EnsureAssetBundleCacheDirExists(target, node);

            var bundleNames = inputGroupAssets.Keys.ToList();
            var bundleVariants = new Dictionary<string, List<string>>();

            // get all variant name for bundles
            foreach (var name in bundleNames) {
                bundleVariants[name] = new List<string>();
                var assets = inputGroupAssets[name];
                foreach(var a in assets) {
                    var variantName = a.variantName;
                    if(!bundleVariants[name].Contains(variantName)) {
                        bundleVariants[name].Add(variantName);
                    }
                }
            }

            int validNames = 0;
            foreach (var name in bundleNames) {
                var assets = inputGroupAssets[name];
                // we do not build bundle without any asset
                if( assets.Count > 0 ) {
                    validNames += bundleVariants[name].Count;
                }
            }

            AssetBundleBuild[] bundleBuild = new AssetBundleBuild[validNames];

            int bbIndex = 0;
            foreach(var name in bundleNames) {
                foreach(var v in bundleVariants[name]) {
                    var bundleName = name;
                    var assets = inputGroupAssets[name];

                    if(assets.Count <= 0) {
                        continue;
                    }

                    bundleBuild[bbIndex].assetBundleName = bundleName;
                    bundleBuild[bbIndex].assetBundleVariant = v;
                    bundleBuild[bbIndex].assetNames = assets.Where(x => x.variantName == v).Select(x => x.importFrom).ToArray();
                    ++bbIndex;
                }
            }

            BuildPipeline.BuildAssetBundles(bundleOutputDir, bundleBuild, (BuildAssetBundleOptions)node.BundleBuilderBundleOptions[target], target);

            var output = new Dictionary<string, List<Asset>>();
            output[key] = new List<Asset>();

            var generatedFiles = FileUtility.GetAllFilePathsInFolder(bundleOutputDir);
            // add manifest file
            bundleNames.Add( BuildTargetUtility.TargetToAssetBundlePlatformName(target) );
            foreach (var path in generatedFiles) {
                var fileName = Path.GetFileName(path);
                if( IsFileIntendedItem(fileName, bundleNames) ) {
                    output[key].Add( Asset.CreateAssetWithImportPath(path) );
                } else {
                    Debug.LogWarning(node.Name + ":Irrelevant file found in assetbundle cache folder:" + fileName);
                }
            }

            Output(connectionToOutput, output, alreadyCached);
        }
        /**
            Perform Run or Setup from parent of given terminal node recursively.
        */
        private static void DoNodeOperation(
			BuildTarget target,
			NodeData currentNodeData,
			ConnectionPointData currentInputPoint,
			ConnectionData connectionToOutput,
			SaveData saveData,
			Dictionary<ConnectionData, Dictionary<string, List<Asset>>> resultDict, 
			Dictionary<NodeData, List<string>> cachedDict,
			List<string> performedIds,
			bool isActualRun,
			Action<NodeException> errorHandler,
			Action<NodeData, float> updateHandler
		)
        {
            if (performedIds.Contains(currentNodeData.Id) || (currentInputPoint != null && performedIds.Contains(currentInputPoint.Id))) {
                return;
            }

            /*
             * Find connections coming into this node from parent node, and traverse recursively
            */
            var connectionsToParents = saveData.Connections.FindAll(con => con.ToNodeId == currentNodeData.Id);

            foreach (var c in connectionsToParents) {

                var parentNode = saveData.Nodes.Find(node => node.Id == c.FromNodeId);
                UnityEngine.Assertions.Assert.IsNotNull(parentNode);

                // check if nodes can connect together
                ConnectionData.ValidateConnection(parentNode, currentNodeData);
                if( parentNode.InputPoints.Count > 0 ) {
                    // if node has multiple input, node is operated per input
                    foreach(var parentInputPoint in parentNode.InputPoints) {
                        DoNodeOperation(target, parentNode, parentInputPoint, c, saveData, resultDict, cachedDict, performedIds, isActualRun, errorHandler, updateHandler);
                    }
                }
                // if parent does not have input point, call with inputPoint==null
                else {
                    DoNodeOperation(target, parentNode, null, c, saveData, resultDict, cachedDict, performedIds, isActualRun, errorHandler, updateHandler);
                }
            }

            // mark this point as performed
            if(currentInputPoint != null) {
                performedIds.Add(currentInputPoint.Id);
            }
            // Root node does not have input point, so we are storing node id instead.
            else {
                performedIds.Add(currentNodeData.Id);
            }

            /*
             * Perform node operation for this node
            */

            if (updateHandler != null) {
                updateHandler(currentNodeData, 0f);
            }

            /*
                has next node, run first time.
            */

            var alreadyCachedPaths = new List<string>();
            if (cachedDict.ContainsKey(currentNodeData)) {
                alreadyCachedPaths.AddRange(cachedDict[currentNodeData]);
            }
            // load already exist cache from node.
            alreadyCachedPaths.AddRange(GetCachedDataByNode(target, currentNodeData));

            // Grab incoming assets from result by refering connections to parents
            var inputGroupAssets = new Dictionary<string, List<Asset>>();
            if(currentInputPoint != null) {
                // aggregates all input assets coming from current inputPoint
                var connToParentsFromCurrentInput = saveData.Connections.FindAll(con => con.ToNodeConnectionPointId == currentInputPoint.Id);
                foreach (var rCon in connToParentsFromCurrentInput) {
                    if (!resultDict.ContainsKey(rCon)) {
                        continue;
                    }

                    var result = resultDict[rCon];
                    foreach (var groupKey in result.Keys) {
                        if (!inputGroupAssets.ContainsKey(groupKey)) {
                            inputGroupAssets[groupKey] = new List<Asset>();
                        }
                        inputGroupAssets[groupKey].AddRange(result[groupKey]);
                    }
                }
            }

            /*
                the Action passes to NodeOperaitons.
                It stores result to resultDict.
            */
            Action<ConnectionData, Dictionary<string, List<Asset>>, List<string>> Output =
                (ConnectionData destinationConnection, Dictionary<string, List<Asset>> outputGroupAsset, List<string> cachedItems) =>
            {
                if(destinationConnection != null ) {
                    if (!resultDict.ContainsKey(destinationConnection)) {
                        resultDict[destinationConnection] = new Dictionary<string, List<Asset>>();
                    }
                    /*
                    merge connection result by group key.
                    */
                    foreach (var groupKey in outputGroupAsset.Keys) {
                        if (!resultDict[destinationConnection].ContainsKey(groupKey)) {
                            resultDict[destinationConnection][groupKey] = new List<Asset>();
                        }
                        resultDict[destinationConnection][groupKey].AddRange(outputGroupAsset[groupKey]);
                    }
                }

                if (isActualRun) {
                    if (!cachedDict.ContainsKey(currentNodeData)) {
                        cachedDict[currentNodeData] = new List<string>();
                    }
                    if(cachedItems != null) {
                        cachedDict[currentNodeData].AddRange(cachedItems);
                    }
                }
            };

            try {
                INodeOperation executor = CreateOperation(saveData, currentNodeData, errorHandler);
                if(executor != null) {
                    if(isActualRun) {
                        executor.Run(target, currentNodeData, currentInputPoint, connectionToOutput, inputGroupAssets, alreadyCachedPaths, Output);
                    }
                    else {
                        executor.Setup(target, currentNodeData, currentInputPoint, connectionToOutput, inputGroupAssets, alreadyCachedPaths, Output);
                    }
                }

            } catch (NodeException e) {
                errorHandler(e);
                // since error occured, this node should stop running for other inputpoints. Adding node id to stop.
                if(!performedIds.Contains(currentNodeData.Id)) {
                    performedIds.Add(currentNodeData.Id);
                }
            }

            if (updateHandler != null) {
                updateHandler(currentNodeData, 1f);
            }
        }
예제 #20
0
        public void Setup(BuildTarget target, 
			NodeData node, 
			ConnectionPointData inputPoint,
			ConnectionData connectionToOutput, 
			Dictionary<string, List<Asset>> inputGroupAssets, 
			List<string> alreadyCached, 
			Action<ConnectionData, Dictionary<string, List<Asset>>, List<string>> Output)
        {
            var incomingAssets = inputGroupAssets.SelectMany(v => v.Value).ToList();

            ValidateModifier(node, target, incomingAssets,
                (Type expectedType, Type foundType, Asset foundAsset) => {
                    throw new NodeException(string.Format("{3} :Modifier expect {0}, but different type of incoming asset is found({1} {2})",
                        expectedType.FullName, foundType.FullName, foundAsset.fileNameAndExtension, node.Name), node.Id);
                },
                () => {
                    throw new NodeException(node.Name + " :Modifier is not configured. Please configure from Inspector.", node.Id);
                },
                () => {
                    throw new NodeException(node.Name + " :Failed to create Modifier from settings. Please fix settings from Inspector.", node.Id);
                },
                (Type expected, Type incoming) => {
                    throw new NodeException(string.Format("{0} :Incoming asset type is does not match with this Modifier (Expected type:{1}, Incoming type:{2}).",
                        node.Name, (expected != null)?expected.FullName:"null", (incoming != null)?incoming.FullName:"null"), node.Id);
                }
            );

            // Modifier does not add, filter or change structure of group, so just pass given group of assets
            Output(connectionToOutput, inputGroupAssets, null);
        }
        public void Setup(BuildTarget target, 
			NodeData node, 
			ConnectionPointData inputPoint,
			ConnectionData connectionToOutput, 
			Dictionary<string, List<Asset>> inputGroupAssets, 
			List<string> alreadyCached, 
			Action<ConnectionData, Dictionary<string, List<Asset>>, List<string>> Output)
        {
            var outputDict = new Dictionary<string, List<Asset>>();
            outputDict[key] = new List<Asset>();

            var bundleNames = inputGroupAssets.Keys.ToList();

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

            // get all variant name for bundles
            foreach (var name in bundleNames) {
                bundleVariants[name] = new List<string>();
                var assets = inputGroupAssets[name];
                foreach(var a in assets) {
                    var variantName = a.variantName;
                    if(!bundleVariants[name].Contains(variantName)) {
                        bundleVariants[name].Add(variantName);
                    }
                }
            }

            // add manifest file
            var manifestName = BuildTargetUtility.TargetToAssetBundlePlatformName(target);
            bundleNames.Add( manifestName );
            bundleVariants[manifestName] = new List<string>();

            var bundleOutputDir = FileUtility.EnsureAssetBundleCacheDirExists(target, node);

            foreach (var name in bundleNames) {
                foreach(var v in bundleVariants[name]) {
                    string bundleName = (string.IsNullOrEmpty(v))? name : name + "." + v;
                    Asset bundle = Asset.CreateAssetWithImportPath( FileUtility.PathCombine(bundleOutputDir, bundleName) );
                    Asset manifest = Asset.CreateAssetWithImportPath( FileUtility.PathCombine(bundleOutputDir, bundleName + AssetBundleGraphSettings.MANIFEST_FOOTER) );
                    outputDict[key].Add(bundle);
                    outputDict[key].Add(manifest);
                }
            }

            Output(connectionToOutput, outputDict, new List<string>());
        }
예제 #22
0
        /**
         *      Perform Run or Setup from parent of given terminal node recursively.
         */
        private static void DoNodeOperation(
            BuildTarget target,
            NodeData currentNodeData,
            ConnectionPointData currentInputPoint,
            ConnectionData connectionToOutput,
            SaveData saveData,
            Dictionary <ConnectionData, Dictionary <string, List <Asset> > > resultDict,
            Dictionary <NodeData, List <string> > cachedDict,
            List <string> performedIds,
            bool isActualRun,
            Action <NodeException> errorHandler,
            Action <NodeData, float> updateHandler
            )
        {
            if (performedIds.Contains(currentNodeData.Id) || (currentInputPoint != null && performedIds.Contains(currentInputPoint.Id)))
            {
                return;
            }

            /*
             * Find connections coming into this node from parent node, and traverse recursively
             */
            var connectionsToParents = saveData.Connections.FindAll(con => con.ToNodeId == currentNodeData.Id);

            foreach (var c in connectionsToParents)
            {
                var parentNode = saveData.Nodes.Find(node => node.Id == c.FromNodeId);
                UnityEngine.Assertions.Assert.IsNotNull(parentNode);

                // check if nodes can connect together
                ConnectionData.ValidateConnection(parentNode, currentNodeData);
                if (parentNode.InputPoints.Count > 0)
                {
                    // if node has multiple input, node is operated per input
                    foreach (var parentInputPoint in parentNode.InputPoints)
                    {
                        DoNodeOperation(target, parentNode, parentInputPoint, c, saveData, resultDict, cachedDict, performedIds, isActualRun, errorHandler, updateHandler);
                    }
                }
                // if parent does not have input point, call with inputPoint==null
                else
                {
                    DoNodeOperation(target, parentNode, null, c, saveData, resultDict, cachedDict, performedIds, isActualRun, errorHandler, updateHandler);
                }
            }

            // mark this point as performed
            if (currentInputPoint != null)
            {
                performedIds.Add(currentInputPoint.Id);
            }
            // Root node does not have input point, so we are storing node id instead.
            else
            {
                performedIds.Add(currentNodeData.Id);
            }

            /*
             * Perform node operation for this node
             */

            if (updateHandler != null)
            {
                updateHandler(currentNodeData, 0f);
            }

            /*
             *      has next node, run first time.
             */

            var alreadyCachedPaths = new List <string>();

            if (cachedDict.ContainsKey(currentNodeData))
            {
                alreadyCachedPaths.AddRange(cachedDict[currentNodeData]);
            }
            // load already exist cache from node.
            alreadyCachedPaths.AddRange(GetCachedDataByNode(target, currentNodeData));

            // Grab incoming assets from result by refering connections to parents
            var inputGroupAssets = new Dictionary <string, List <Asset> >();

            if (currentInputPoint != null)
            {
                // aggregates all input assets coming from current inputPoint
                var connToParentsFromCurrentInput = saveData.Connections.FindAll(con => con.ToNodeConnectionPointId == currentInputPoint.Id);
                foreach (var rCon in connToParentsFromCurrentInput)
                {
                    if (!resultDict.ContainsKey(rCon))
                    {
                        continue;
                    }

                    var result = resultDict[rCon];
                    foreach (var groupKey in result.Keys)
                    {
                        if (!inputGroupAssets.ContainsKey(groupKey))
                        {
                            inputGroupAssets[groupKey] = new List <Asset>();
                        }
                        inputGroupAssets[groupKey].AddRange(result[groupKey]);
                    }
                }
            }

            /*
             *      the Action passes to NodeOperaitons.
             *      It stores result to resultDict.
             */
            Action <ConnectionData, Dictionary <string, List <Asset> >, List <string> > Output =
                (ConnectionData destinationConnection, Dictionary <string, List <Asset> > outputGroupAsset, List <string> cachedItems) =>
            {
                if (destinationConnection != null)
                {
                    if (!resultDict.ContainsKey(destinationConnection))
                    {
                        resultDict[destinationConnection] = new Dictionary <string, List <Asset> >();
                    }

                    /*
                     * merge connection result by group key.
                     */
                    foreach (var groupKey in outputGroupAsset.Keys)
                    {
                        if (!resultDict[destinationConnection].ContainsKey(groupKey))
                        {
                            resultDict[destinationConnection][groupKey] = new List <Asset>();
                        }
                        resultDict[destinationConnection][groupKey].AddRange(outputGroupAsset[groupKey]);
                    }
                }

                if (isActualRun)
                {
                    if (!cachedDict.ContainsKey(currentNodeData))
                    {
                        cachedDict[currentNodeData] = new List <string>();
                    }
                    if (cachedItems != null)
                    {
                        cachedDict[currentNodeData].AddRange(cachedItems);
                    }
                }
            };

            try {
                INodeOperation executor = CreateOperation(saveData, currentNodeData, errorHandler);
                if (executor != null)
                {
                    if (isActualRun)
                    {
                        executor.Run(target, currentNodeData, currentInputPoint, connectionToOutput, inputGroupAssets, alreadyCachedPaths, Output);
                    }
                    else
                    {
                        executor.Setup(target, currentNodeData, currentInputPoint, connectionToOutput, inputGroupAssets, alreadyCachedPaths, Output);
                    }
                }
            } catch (NodeException e) {
                errorHandler(e);
                // since error occured, this node should stop running for other inputpoints. Adding node id to stop.
                if (!performedIds.Contains(currentNodeData.Id))
                {
                    performedIds.Add(currentNodeData.Id);
                }
            }

            if (updateHandler != null)
            {
                updateHandler(currentNodeData, 1f);
            }
        }