private void DoInspectorBundlizerGUI(NodeGUI node) { if (node.bundleNameTemplate == null) { return; } EditorGUILayout.HelpBox("Bundlizer: Create asset bundle settings with given group of assets.", MessageType.Info); UpdateNodeName(node); GUILayout.Space(10f); node.currentPlatform = UpdateCurrentPlatform(node.currentPlatform); using (new EditorGUILayout.VerticalScope(GUI.skin.box)) { var bundleNameTemplate = EditorGUILayout.TextField( "Bundle Name Template", SystemDataUtility.GetPlatformValue( node.bundleNameTemplate.ReadonlyDict(), node.currentPlatform ).ToString() ).ToLower(); IntegratedGUIBundlizer.ValidateBundleNameTemplate( bundleNameTemplate, () => { // EditorGUILayout.HelpBox("No Bundle Name Template set.", MessageType.Error); } ); if (bundleNameTemplate != SystemDataUtility.GetPlatformValue( node.bundleNameTemplate.ReadonlyDict(), node.currentPlatform ).ToString() ) { node.BeforeSave(); node.bundleNameTemplate.Add(SystemDataUtility.CreateKeyNameFromString(node.currentPlatform), bundleNameTemplate); node.Save(); } GUILayout.Label("Variants:"); for (int i = 0; i < node.variants.Keys.Count; ++i) { var inputConnectionId = node.variants.Keys[i]; using (new GUILayout.HorizontalScope()) { if (GUILayout.Button("-", GUILayout.Width(30))) { node.BeforeSave(); node.variants.Remove(inputConnectionId); node.DeleteInputPoint(inputConnectionId); } else { var variantName = node.variants.Values[i]; GUIStyle s = new GUIStyle((GUIStyle)"TextFieldDropDownText"); Action makeStyleBold = () => { s.fontStyle = FontStyle.Bold; s.fontSize = 12; }; IntegratedGUIBundlizer.ValidateVariantName(variantName, node.variants.Values, makeStyleBold, makeStyleBold, makeStyleBold); variantName = EditorGUILayout.TextField(variantName, s); if (variantName != node.variants.Values[i]) { node.BeforeSave(); node.variants.Values[i] = variantName; node.RenameInputPoint(inputConnectionId, variantName); } } } } if (GUILayout.Button("+")) { node.BeforeSave(); var newid = Guid.NewGuid().ToString(); node.variants.Add(newid, AssetBundleGraphSettings.BUNDLIZER_VARIANTNAME_DEFAULT); node.AddInputPoint(newid, AssetBundleGraphSettings.BUNDLIZER_VARIANTNAME_DEFAULT); } } UpdateDeleteSetting(node); }
/** * Perform Run or Setup from parent of given terminal node recursively. */ private static void DoNodeOperation( string nodeId, List <NodeData> allNodes, List <ConnectionData> allConnections, Dictionary <string, Dictionary <string, List <Asset> > > resultDict, Dictionary <string, List <string> > cachedDict, List <string> usedConnectionIds, bool isActualRun, Action <string, float> updateHandler = null ) { var relatedNodes = allNodes.Where(relation => relation.nodeId == nodeId).ToList(); if (!relatedNodes.Any()) { return; } var currentNodeData = relatedNodes[0]; if (currentNodeData.IsAlreadyDone()) { return; } var nodeName = currentNodeData.nodeName; var nodeKind = currentNodeData.nodeKind; /* * Perform prarent node recursively from this node */ foreach (var connectionToParent in currentNodeData.connectionToParents) { var parentNodeId = connectionToParent.fromNodeId; var usedConnectionId = connectionToParent.connectionId; if (usedConnectionIds.Contains(usedConnectionId)) { throw new NodeException("connection loop detected.", parentNodeId); } usedConnectionIds.Add(usedConnectionId); var parentNode = allNodes.Where(node => node.nodeId == parentNodeId).ToList(); if (!parentNode.Any()) { return; } var parentNodeKind = parentNode[0].nodeKind; // check node kind order. SystemDataValidator.ValidateAssertNodeOrder(parentNodeKind, nodeKind); DoNodeOperation(parentNodeId, allNodes, allConnections, resultDict, cachedDict, usedConnectionIds, isActualRun, updateHandler); } /* * Perform node operation for this node */ // connections Ids from this node to child nodes. non-ordered. // actual running order depends on order of Node's OutputPoint order. var nonOrderedConnectionsFromThisNodeToChildNode = allConnections .Where(con => con.fromNodeId == nodeId) .ToList(); var orderedNodeOutputPointIds = allNodes.Where(node => node.nodeId == nodeId).SelectMany(node => node.outputPointIds).ToList(); /* * get connection ids which is orderd by node's outputPoint-order. */ var orderedConnectionIds = new List <string>(nonOrderedConnectionsFromThisNodeToChildNode.Count); foreach (var orderedNodeOutputPointId in orderedNodeOutputPointIds) { foreach (var nonOrderedConnectionFromThisNodeToChildNode in nonOrderedConnectionsFromThisNodeToChildNode) { var nonOrderedConnectionOutputPointId = nonOrderedConnectionFromThisNodeToChildNode.fromNodeOutputPointId; if (orderedNodeOutputPointId == nonOrderedConnectionOutputPointId) { orderedConnectionIds.Add(nonOrderedConnectionFromThisNodeToChildNode.connectionId); continue; } } } /* * FilterNode and BundlizerNode uses specific multiple output connections. * ExportNode does not have output. * but all other nodes has only one output connection and uses first connection. */ var firstConnectionIdFromThisNodeToChildNode = string.Empty; if (orderedConnectionIds.Any()) { firstConnectionIdFromThisNodeToChildNode = orderedConnectionIds[0]; } if (updateHandler != null) { updateHandler(nodeId, 0f); } /* * has next node, run first time. */ var alreadyCachedPaths = new List <string>(); if (cachedDict.ContainsKey(nodeId)) { alreadyCachedPaths.AddRange(cachedDict[nodeId]); } /* * load already exist cache from node. */ alreadyCachedPaths.AddRange(GetCachedDataByNodeKind(nodeKind, nodeId)); var inputParentResults = new Dictionary <string, List <Asset> >(); var receivingConnectionIds = allConnections .Where(con => con.toNodeId == nodeId) .Select(con => con.connectionId) .ToList(); foreach (var connecionId in receivingConnectionIds) { if (!resultDict.ContainsKey(connecionId)) { continue; } var result = resultDict[connecionId]; foreach (var groupKey in result.Keys) { if (!inputParentResults.ContainsKey(groupKey)) { inputParentResults[groupKey] = new List <Asset>(); } inputParentResults[groupKey].AddRange(result[groupKey]); } } /* * the Action passes to NodeOperaitons. * It stores result to resultDict. */ Action <string, string, Dictionary <string, List <Asset> >, List <string> > Output = (string dataSourceNodeId, string targetConnectionId, Dictionary <string, List <Asset> > result, List <string> justCached) => { var targetConnectionIds = allConnections .Where(con => con.connectionId == targetConnectionId) .Select(con => con.connectionId) .ToList(); if (!targetConnectionIds.Any()) { // if next connection does not exist, no results for next. // save results to resultDict with this endpoint node's id. resultDict[dataSourceNodeId] = new Dictionary <string, List <Asset> >(); foreach (var groupKey in result.Keys) { if (!resultDict[dataSourceNodeId].ContainsKey(groupKey)) { resultDict[dataSourceNodeId][groupKey] = new List <Asset>(); } resultDict[dataSourceNodeId][groupKey].AddRange(result[groupKey]); } return; } if (!resultDict.ContainsKey(targetConnectionId)) { resultDict[targetConnectionId] = new Dictionary <string, List <Asset> >(); } /* * merge connection result by group key. */ foreach (var groupKey in result.Keys) { if (!resultDict[targetConnectionId].ContainsKey(groupKey)) { resultDict[targetConnectionId][groupKey] = new List <Asset>(); } resultDict[targetConnectionId][groupKey].AddRange(result[groupKey]); } if (isActualRun) { if (!cachedDict.ContainsKey(nodeId)) { cachedDict[nodeId] = new List <string>(); } cachedDict[nodeId].AddRange(justCached); } }; try { if (isActualRun) { switch (nodeKind) { /* * Scripts */ case AssetBundleGraphSettings.NodeKind.FILTER_SCRIPT: { var scriptClassName = currentNodeData.scriptClassName; var executor = SystemDataUtility.CreateNodeOperationInstance <FilterBase>(scriptClassName, nodeId); executor.Run(nodeName, nodeId, firstConnectionIdFromThisNodeToChildNode, inputParentResults, alreadyCachedPaths, Output); break; } case AssetBundleGraphSettings.NodeKind.PREFABRICATOR_SCRIPT: { var scriptClassName = currentNodeData.scriptClassName; var executor = SystemDataUtility.CreateNodeOperationInstance <PrefabricatorBase>(scriptClassName, nodeId); executor.Run(nodeName, nodeId, firstConnectionIdFromThisNodeToChildNode, inputParentResults, alreadyCachedPaths, Output); break; } /* * GUIs */ case AssetBundleGraphSettings.NodeKind.LOADER_GUI: { var currentLoadFilePath = SystemDataUtility.GetCurrentPlatformValue(currentNodeData.loadFilePath); var executor = new IntegratedGUILoader(FileUtility.GetPathWithAssetsPath(currentLoadFilePath)); executor.Run(nodeName, nodeId, firstConnectionIdFromThisNodeToChildNode, inputParentResults, alreadyCachedPaths, Output); break; } case AssetBundleGraphSettings.NodeKind.FILTER_GUI: { /* * Filter requires "outputPoint ordered exist connection Id and Fake connection Id" for * exhausting assets by keyword and type correctly. * * outputPoint which has connection can through assets by keyword and keytype, * also outputPoint which doesn't have connection should take assets by keyword and keytype. */ var orderedConnectionIdsAndFakeConnectionIds = new string[orderedNodeOutputPointIds.Count]; for (var i = 0; i < orderedNodeOutputPointIds.Count; i++) { var orderedNodeOutputPointId = orderedNodeOutputPointIds[i]; foreach (var nonOrderedConnectionFromThisNodeToChildNode in nonOrderedConnectionsFromThisNodeToChildNode) { var connectionOutputPointId = nonOrderedConnectionFromThisNodeToChildNode.fromNodeOutputPointId; if (orderedNodeOutputPointId == connectionOutputPointId) { orderedConnectionIdsAndFakeConnectionIds[i] = nonOrderedConnectionFromThisNodeToChildNode.connectionId; break; } else { orderedConnectionIdsAndFakeConnectionIds[i] = AssetBundleGraphSettings.FILTER_FAKE_CONNECTION_ID; } } } var executor = new IntegratedGUIFilter(orderedConnectionIdsAndFakeConnectionIds, currentNodeData.containsKeywords, currentNodeData.containsKeytypes); executor.Run(nodeName, nodeId, string.Empty, inputParentResults, alreadyCachedPaths, Output); break; } case AssetBundleGraphSettings.NodeKind.IMPORTSETTING_GUI: { var executor = new IntegratedGUIImportSetting(); executor.Run(nodeName, nodeId, firstConnectionIdFromThisNodeToChildNode, inputParentResults, alreadyCachedPaths, Output); break; } case AssetBundleGraphSettings.NodeKind.MODIFIER_GUI: { var specificScriptClass = currentNodeData.scriptClassName; var executor = new IntegratedGUIModifier(specificScriptClass, SystemDataUtility.GetCurrentPlatformShortName()); executor.Run(nodeName, nodeId, firstConnectionIdFromThisNodeToChildNode, inputParentResults, alreadyCachedPaths, Output); break; } case AssetBundleGraphSettings.NodeKind.GROUPING_GUI: { var executor = new IntegratedGUIGrouping(SystemDataUtility.GetCurrentPlatformValue(currentNodeData.groupingKeyword)); executor.Run(nodeName, nodeId, firstConnectionIdFromThisNodeToChildNode, inputParentResults, alreadyCachedPaths, Output); break; } case AssetBundleGraphSettings.NodeKind.PREFABRICATOR_GUI: { var scriptClassName = currentNodeData.scriptClassName; if (string.IsNullOrEmpty(scriptClassName)) { Debug.LogError(nodeName + ": Classname is empty. Set valid classname. Configure valid script name from editor."); break; } var executor = SystemDataUtility.CreateNodeOperationInstance <PrefabricatorBase>(scriptClassName, nodeId); executor.Run(nodeName, nodeId, firstConnectionIdFromThisNodeToChildNode, inputParentResults, alreadyCachedPaths, Output); break; } case AssetBundleGraphSettings.NodeKind.BUNDLIZER_GUI: { /* * Bundlizer requires assetOutputConnectionId and additional resourceOutputConnectionId. * both-connected, or both-not-connected, or one of them is connected. 4 patterns exists. * * Bundler Node's outputPoint [0] is always the point for assetOutputConnectionId. * Bundler Node's outputPoint [1] is always the point for resourceOutputConnectionId. * * if one of these outputPoint don't have connection, use Fake connection id for correct output. * * * unorderedConnectionId \ * ----> orderedConnectionIdsAndFakeConnectionIds. * orderedOutputPointId / */ var orderedConnectionIdsAndFakeConnectionIds = new string[orderedNodeOutputPointIds.Count]; for (var i = 0; i < orderedNodeOutputPointIds.Count; i++) { var orderedNodeOutputPointId = orderedNodeOutputPointIds[i]; foreach (var nonOrderedConnectionFromThisNodeToChildNode in nonOrderedConnectionsFromThisNodeToChildNode) { var connectionOutputPointId = nonOrderedConnectionFromThisNodeToChildNode.fromNodeOutputPointId; if (orderedNodeOutputPointId == connectionOutputPointId) { orderedConnectionIdsAndFakeConnectionIds[i] = nonOrderedConnectionFromThisNodeToChildNode.connectionId; break; } else { orderedConnectionIdsAndFakeConnectionIds[i] = AssetBundleGraphSettings.BUNDLIZER_FAKE_CONNECTION_ID; } } } var bundleNameTemplate = SystemDataUtility.GetCurrentPlatformValue(currentNodeData.bundleNameTemplate); /* * TODO: variants needs to be execute Setup/Run as many times as its variants */ var executor = new IntegratedGUIBundlizer(bundleNameTemplate, orderedConnectionIdsAndFakeConnectionIds[0], currentNodeData.variants); executor.Run(nodeName, nodeId, string.Empty, inputParentResults, alreadyCachedPaths, Output); break; } case AssetBundleGraphSettings.NodeKind.BUNDLEBUILDER_GUI: { var bundleOptions = SystemDataUtility.GetCurrentPlatformValue(currentNodeData.enabledBundleOptions); var executor = new IntegratedGUIBundleBuilder(bundleOptions, allNodes.Select(nodeData => nodeData.nodeId).ToList()); executor.Run(nodeName, nodeId, firstConnectionIdFromThisNodeToChildNode, inputParentResults, alreadyCachedPaths, Output); break; } case AssetBundleGraphSettings.NodeKind.EXPORTER_GUI: { var exportTo = SystemDataUtility.GetCurrentPlatformValue(currentNodeData.exportFilePath); var executor = new IntegratedGUIExporter(FileUtility.GetPathWithProjectPath(exportTo)); executor.Run(nodeName, nodeId, firstConnectionIdFromThisNodeToChildNode, inputParentResults, alreadyCachedPaths, Output); break; } default: { Debug.LogError(nodeName + " is defined as unknown kind of node. value:" + nodeKind); break; } } } else { switch (nodeKind) { /* * Scripts */ case AssetBundleGraphSettings.NodeKind.FILTER_SCRIPT: { var scriptClassName = currentNodeData.scriptClassName; var executor = SystemDataUtility.CreateNodeOperationInstance <FilterBase>(scriptClassName, nodeId); executor.Setup(nodeName, nodeId, firstConnectionIdFromThisNodeToChildNode, inputParentResults, alreadyCachedPaths, Output); break; } case AssetBundleGraphSettings.NodeKind.PREFABRICATOR_SCRIPT: { var scriptClassName = currentNodeData.scriptClassName; var executor = SystemDataUtility.CreateNodeOperationInstance <PrefabricatorBase>(scriptClassName, nodeId); executor.Setup(nodeName, nodeId, firstConnectionIdFromThisNodeToChildNode, inputParentResults, alreadyCachedPaths, Output); break; } /* * GUIs */ case AssetBundleGraphSettings.NodeKind.LOADER_GUI: { var currentLoadFilePath = SystemDataUtility.GetCurrentPlatformValue(currentNodeData.loadFilePath); var executor = new IntegratedGUILoader(FileUtility.GetPathWithAssetsPath(currentLoadFilePath)); executor.Setup(nodeName, nodeId, firstConnectionIdFromThisNodeToChildNode, inputParentResults, alreadyCachedPaths, Output); break; } case AssetBundleGraphSettings.NodeKind.FILTER_GUI: { /* * Filter requires "outputPoint ordered exist connection Id and Fake connection Id" for * exhausting assets by keyword and type correctly. * * outputPoint which has connection can through assets by keyword and keytype, * also outputPoint which doesn't have connection should take assets by keyword and keytype. */ var orderedConnectionIdsAndFakeConnectionIds = new string[orderedNodeOutputPointIds.Count]; for (var i = 0; i < orderedNodeOutputPointIds.Count; i++) { var orderedNodeOutputPointId = orderedNodeOutputPointIds[i]; foreach (var nonOrderedConnectionFromThisNodeToChildNode in nonOrderedConnectionsFromThisNodeToChildNode) { var connectionOutputPointId = nonOrderedConnectionFromThisNodeToChildNode.fromNodeOutputPointId; if (orderedNodeOutputPointId == connectionOutputPointId) { orderedConnectionIdsAndFakeConnectionIds[i] = nonOrderedConnectionFromThisNodeToChildNode.connectionId; break; } else { orderedConnectionIdsAndFakeConnectionIds[i] = AssetBundleGraphSettings.FILTER_FAKE_CONNECTION_ID; } } } var executor = new IntegratedGUIFilter(orderedConnectionIdsAndFakeConnectionIds, currentNodeData.containsKeywords, currentNodeData.containsKeytypes); executor.Setup(nodeName, nodeId, string.Empty, inputParentResults, alreadyCachedPaths, Output); break; } case AssetBundleGraphSettings.NodeKind.IMPORTSETTING_GUI: { var executor = new IntegratedGUIImportSetting(); executor.Setup(nodeName, nodeId, firstConnectionIdFromThisNodeToChildNode, inputParentResults, alreadyCachedPaths, Output); break; } case AssetBundleGraphSettings.NodeKind.MODIFIER_GUI: { var specificScriptClass = currentNodeData.scriptClassName; var executor = new IntegratedGUIModifier(specificScriptClass, SystemDataUtility.GetCurrentPlatformShortName()); executor.Setup(nodeName, nodeId, firstConnectionIdFromThisNodeToChildNode, inputParentResults, alreadyCachedPaths, Output); break; } case AssetBundleGraphSettings.NodeKind.GROUPING_GUI: { var executor = new IntegratedGUIGrouping(SystemDataUtility.GetCurrentPlatformValue(currentNodeData.groupingKeyword)); executor.Setup(nodeName, nodeId, firstConnectionIdFromThisNodeToChildNode, inputParentResults, alreadyCachedPaths, Output); break; } case AssetBundleGraphSettings.NodeKind.PREFABRICATOR_GUI: { var scriptClassName = currentNodeData.scriptClassName; if (string.IsNullOrEmpty(scriptClassName)) { AssetBundleGraphEditorWindow.AddNodeException(new NodeException(nodeName + ": Classname is empty. Set valid classname.", nodeId)); break; } try { var executor = SystemDataUtility.CreateNodeOperationInstance <PrefabricatorBase>(scriptClassName, nodeId); executor.Setup(nodeName, nodeId, firstConnectionIdFromThisNodeToChildNode, inputParentResults, alreadyCachedPaths, Output); } catch (NodeException e) { AssetBundleGraphEditorWindow.AddNodeException(e); break; } break; } case AssetBundleGraphSettings.NodeKind.BUNDLIZER_GUI: { /* * Bundlizer requires assetOutputConnectionId and additional resourceOutputConnectionId. * both-connected, or both-not-connected, or one of them is connected. 4 patterns exists. * * Bundler Node's outputPoint [0] is always the point for assetOutputConnectionId. * Bundler Node's outputPoint [1] is always the point for resourceOutputConnectionId. * * if one of these outputPoint don't have connection, use Fake connection id for correct output. * * * unorderedConnectionId \ * ----> orderedConnectionIdsAndFakeConnectionIds. * orderedOutputPointId / */ var orderedConnectionIdsAndFakeConnectionIds = new string[orderedNodeOutputPointIds.Count]; for (var i = 0; i < orderedNodeOutputPointIds.Count; i++) { var orderedNodeOutputPointId = orderedNodeOutputPointIds[i]; foreach (var nonOrderedConnectionFromThisNodeToChildNode in nonOrderedConnectionsFromThisNodeToChildNode) { var connectionOutputPointId = nonOrderedConnectionFromThisNodeToChildNode.fromNodeOutputPointId; if (orderedNodeOutputPointId == connectionOutputPointId) { orderedConnectionIdsAndFakeConnectionIds[i] = nonOrderedConnectionFromThisNodeToChildNode.connectionId; break; } else { orderedConnectionIdsAndFakeConnectionIds[i] = AssetBundleGraphSettings.BUNDLIZER_FAKE_CONNECTION_ID; } } } var bundleNameTemplate = SystemDataUtility.GetCurrentPlatformValue(currentNodeData.bundleNameTemplate); /* * TODO: variants needs to be execute Setup/Run as many times as its variants */ var executor = new IntegratedGUIBundlizer(bundleNameTemplate, orderedConnectionIdsAndFakeConnectionIds[0], currentNodeData.variants); executor.Setup(nodeName, nodeId, string.Empty, inputParentResults, alreadyCachedPaths, Output); break; } case AssetBundleGraphSettings.NodeKind.BUNDLEBUILDER_GUI: { var bundleOptions = SystemDataUtility.GetCurrentPlatformValue(currentNodeData.enabledBundleOptions); var executor = new IntegratedGUIBundleBuilder(bundleOptions, allNodes.Select(nodeData => nodeData.nodeId).ToList()); executor.Setup(nodeName, nodeId, firstConnectionIdFromThisNodeToChildNode, inputParentResults, alreadyCachedPaths, Output); break; } case AssetBundleGraphSettings.NodeKind.EXPORTER_GUI: { var exportTo = SystemDataUtility.GetCurrentPlatformValue(currentNodeData.exportFilePath); var executor = new IntegratedGUIExporter(FileUtility.GetPathWithProjectPath(exportTo)); executor.Setup(nodeName, nodeId, firstConnectionIdFromThisNodeToChildNode, inputParentResults, alreadyCachedPaths, Output); break; } default: { Debug.LogError(nodeName + " is defined as unknown kind of node. value:" + nodeKind); break; } } } } catch (NodeException e) { AssetBundleGraphEditorWindow.AddNodeException(e); //Debug.LogError("error occured:\"" + e.reason + "\", please check information on node."); return; //throw new AssetBundleGraphException(nodeName + ": " + e.reason); } currentNodeData.Done(); if (updateHandler != null) { updateHandler(nodeId, 1f); } }