public static INodeOperation CreateOperation(SaveData saveData, NodeData currentNodeData, Action<NodeException> errorHandler)
        {
            INodeOperation executor = null;

            try {
                switch (currentNodeData.Kind) {
                case NodeKind.LOADER_GUI: {
                        executor = new IntegratedGUILoader();
                        break;
                    }
                case NodeKind.FILTER_GUI: {
                        // Filter requires multiple output connections
                        var connectionsToChild = saveData.Connections.FindAll(c => c.FromNodeId == currentNodeData.Id);
                        executor = new IntegratedGUIFilter(connectionsToChild);
                        break;
                    }

                case NodeKind.IMPORTSETTING_GUI: {
                        executor = new IntegratedGUIImportSetting();
                        break;
                    }
                case NodeKind.MODIFIER_GUI: {
                        executor = new IntegratedGUIModifier();
                        break;
                    }
                case NodeKind.GROUPING_GUI: {
                        executor = new IntegratedGUIGrouping();
                        break;
                    }
                case NodeKind.PREFABBUILDER_GUI: {
                        executor = new IntegratedPrefabBuilder();
                        break;
                    }

                case NodeKind.BUNDLECONFIG_GUI: {
                        executor = new IntegratedGUIBundleConfigurator();
                        break;
                    }

                case NodeKind.BUNDLEBUILDER_GUI: {
                        executor = new IntegratedGUIBundleBuilder();
                        break;
                    }

                case NodeKind.EXPORTER_GUI: {
                        executor = new IntegratedGUIExporter();
                        break;
                    }

                default: {
                        Debug.LogError(currentNodeData.Name + " is defined as unknown kind of node. value:" + currentNodeData.Kind);
                        break;
                    }
                }
            } catch (NodeException e) {
                errorHandler(e);
            }

            return executor;
        }
Ejemplo n.º 2
0
        private void DoInspectorImportSettingGUI(NodeGUI node)
        {
            EditorGUILayout.HelpBox("ImportSetting: Force apply import settings to given assets.", MessageType.Info);
            UpdateNodeName(node);

            GUILayout.Space(10f);

            if (packageEditMode)
            {
                EditorGUI.BeginDisabledGroup(true);
            }

            /*
             *      importer node has no platform key.
             *      platform key is contained by Unity's importer inspector itself.
             */
            using (new EditorGUILayout.VerticalScope(GUI.skin.box)) {
                var nodeId = node.nodeId;

                var samplingPath = FileUtility.PathCombine(AssetBundleGraphSettings.IMPORTER_SETTINGS_PLACE, nodeId);

                IntegratedGUIImportSetting.ValidateImportSample(samplingPath,
                                                                (string noFolderFound) => {
                    EditorGUILayout.LabelField("Sampling Asset", "No sample asset found. please Reload first.");
                },
                                                                (string noFilesFound) => {
                    EditorGUILayout.LabelField("Sampling Asset", "No sample asset found. please Reload first.");
                },
                                                                (string samplingAssetPath) => {
                    EditorGUILayout.LabelField("Sampling Asset Path", samplingAssetPath);
                    if (GUILayout.Button("Setup Import Setting"))
                    {
                        var obj = AssetDatabase.LoadAssetAtPath <UnityEngine.Object>(samplingAssetPath);
                        Selection.activeObject = obj;
                    }
                    if (GUILayout.Button("Reset Import Setting"))
                    {
                        // delete all import setting files.
                        FileUtility.RemakeDirectory(samplingPath);
                        node.Save();
                    }
                },
                                                                (string tooManyFilesFoundMessage) => {
                    if (GUILayout.Button("Reset Import Setting"))
                    {
                        // delete all import setting files.
                        FileUtility.RemakeDirectory(samplingPath);
                        node.Save();
                    }
                }
                                                                );
            }

            if (packageEditMode)
            {
                EditorGUI.EndDisabledGroup();
            }
            UpdateDeleteSetting(node);
        }
        private void DoInspectorImportSettingGUI(NodeGUI node)
        {
            EditorGUILayout.HelpBox("ImportSetting: Force apply import settings to given assets.", MessageType.Info);
            UpdateNodeName(node);

            GUILayout.Space(10f);

            /*
             *      importer node has no platform key.
             *      platform key is contained by Unity's importer inspector itself.
             */
            using (new EditorGUILayout.VerticalScope(GUI.skin.box)) {
                Type incomingType = FindIncomingAssetType(node.Data.InputPoints[0]);
                IntegratedGUIImportSetting.ConfigStatus status =
                    IntegratedGUIImportSetting.GetConfigStatus(node.Data);

                if (incomingType == null)
                {
                    // try to retrieve incoming type from configuration
                    if (status == IntegratedGUIImportSetting.ConfigStatus.GoodSampleFound)
                    {
                        incomingType = IntegratedGUIImportSetting.GetReferenceAssetImporter(node.Data).GetType();
                    }
                    else
                    {
                        EditorGUILayout.HelpBox("ImportSetting needs a single type of incoming assets.", MessageType.Info);
                        return;
                    }
                }

                switch (status)
                {
                case IntegratedGUIImportSetting.ConfigStatus.NoSampleFound:
                    // IntegratedGUIImportSetting.Setup() must run to grab another sample to configure.
                    EditorGUILayout.HelpBox("Press Refresh to configure.", MessageType.Info);
                    break;

                case IntegratedGUIImportSetting.ConfigStatus.GoodSampleFound:
                    if (GUILayout.Button("Configure Import Setting"))
                    {
                        Selection.activeObject = IntegratedGUIImportSetting.GetReferenceAssetImporter(node.Data);
                    }
                    if (GUILayout.Button("Reset Import Setting"))
                    {
                        IntegratedGUIImportSetting.ResetConfig(node.Data);
                    }
                    break;

                case IntegratedGUIImportSetting.ConfigStatus.TooManySamplesFound:
                    if (GUILayout.Button("Reset Import Setting"))
                    {
                        IntegratedGUIImportSetting.ResetConfig(node.Data);
                    }
                    break;
                }
            }
        }
        private INodeOperation CreateOperation(NodeData currentNodeData)
        {
            INodeOperation executor = null;

            try {
                switch (currentNodeData.Kind)
                {
                case NodeKind.LOADER_GUI: {
                    executor = new IntegratedGUILoader();
                    break;
                }

                case NodeKind.FILTER_GUI: {
                    executor = new IntegratedGUIFilter();
                    break;
                }

                case NodeKind.IMPORTSETTING_GUI: {
                    executor = new IntegratedGUIImportSetting();
                    break;
                }

                case NodeKind.MODIFIER_GUI: {
                    executor = new IntegratedGUIModifier();
                    break;
                }

                case NodeKind.GROUPING_GUI: {
                    executor = new IntegratedGUIGrouping();
                    break;
                }

                case NodeKind.PREFABBUILDER_GUI: {
                    executor = new IntegratedPrefabBuilder();
                    break;
                }

                case NodeKind.BUNDLECONFIG_GUI: {
                    executor = new IntegratedGUIBundleConfigurator();
                    break;
                }

                case NodeKind.BUNDLEBUILDER_GUI: {
                    executor = new IntegratedGUIBundleBuilder();
                    break;
                }

                case NodeKind.EXPORTER_GUI: {
                    executor = new IntegratedGUIExporter();
                    break;
                }

                default: {
                    LogUtility.Logger.LogError(LogUtility.kTag, currentNodeData.Name + " is defined as unknown kind of node. value:" + currentNodeData.Kind);
                    break;
                }
                }
            } catch (NodeException e) {
                m_nodeExceptions.Add(e);
            }

            return(executor);
        }
Ejemplo n.º 5
0
        public static INodeOperation CreateOperation(SaveData saveData, NodeData currentNodeData)
        {
            INodeOperation executor = null;

            try {
                switch (currentNodeData.Kind)
                {
                case NodeKind.LOADER_GUI: {
                    executor = new IntegratedGUILoader();
                    break;
                }

                case NodeKind.FILTER_GUI: {
                    // Filter requires multiple output connections
                    var connectionsToChild = saveData.Connections.FindAll(c => c.FromNodeId == currentNodeData.Id);
                    executor = new IntegratedGUIFilter(connectionsToChild);
                    break;
                }

                case NodeKind.IMPORTSETTING_GUI: {
                    executor = new IntegratedGUIImportSetting();
                    break;
                }

                case NodeKind.MODIFIER_GUI: {
                    executor = new IntegratedGUIModifier();
                    break;
                }

                case NodeKind.GROUPING_GUI: {
                    executor = new IntegratedGUIGrouping();
                    break;
                }

                case NodeKind.PREFABBUILDER_GUI: {
                    executor = new IntegratedPrefabBuilder();
                    break;
                }

                case NodeKind.BUNDLECONFIG_GUI: {
                    executor = new IntegratedGUIBundleConfigurator();
                    break;
                }

                case NodeKind.BUNDLEBUILDER_GUI: {
                    executor = new IntegratedGUIBundleBuilder();
                    break;
                }

                case NodeKind.EXPORTER_GUI: {
                    executor = new IntegratedGUIExporter();
                    break;
                }

                default: {
                    Debug.LogError(currentNodeData.Name + " is defined as unknown kind of node. value:" + currentNodeData.Kind);
                    break;
                }
                }
            } catch (NodeException e) {
                AssetBundleGraphEditorWindow.AddNodeException(e);
                //Debug.LogError("error occured:\"" + e.reason + "\", please check information on node.");
                //throw new AssetBundleGraphException(node.Name + ": " + e.reason);
            }

            return(executor);
        }
        /**
         *      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);
            }
        }
        public static INodeOperation CreateOperation(SaveData saveData, NodeData currentNodeData, Action <NodeException> errorHandler)
        {
            INodeOperation executor = null;

            try {
                switch (currentNodeData.Kind)
                {
                case NodeKind.LOADER_GUI: {
                    executor = new IntegratedGUILoader();
                    break;
                }

                case NodeKind.FILTER_GUI: {
                    // Filter requires multiple output connections
                    var connectionsToChild = saveData.Connections.FindAll(c => c.FromNodeId == currentNodeData.Id);
                    executor = new IntegratedGUIFilter(connectionsToChild);
                    break;
                }

                case NodeKind.IMPORTSETTING_GUI: {
                    executor = new IntegratedGUIImportSetting();
                    break;
                }

                case NodeKind.MODIFIER_GUI: {
                    executor = new IntegratedGUIModifier();
                    break;
                }

                case NodeKind.GROUPING_GUI: {
                    executor = new IntegratedGUIGrouping();
                    break;
                }

                case NodeKind.PREFABBUILDER_GUI: {
                    executor = new IntegratedPrefabBuilder();
                    break;
                }

                case NodeKind.BUNDLECONFIG_GUI: {
                    executor = new IntegratedGUIBundleConfigurator();
                    break;
                }

                case NodeKind.BUNDLEBUILDER_GUI: {
                    executor = new IntegratedGUIBundleBuilder();
                    break;
                }

                case NodeKind.EXPORTER_GUI: {
                    executor = new IntegratedGUIExporter();
                    break;
                }

                default: {
                    Debug.LogError(currentNodeData.Name + " is defined as unknown kind of node. value:" + currentNodeData.Kind);
                    break;
                }
                }
            } catch (NodeException e) {
                errorHandler(e);
            }

            return(executor);
        }