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;
        }
Example #2
0
        public void DeleteCurrentPackagePlatformKey(string platformPackageKey)
        {
            switch (this.kind)
            {
            case AssetBundleGraphSettings.NodeKind.LOADER_GUI: {
                loadPath.Remove(platformPackageKey);
                break;
            }

            case AssetBundleGraphSettings.NodeKind.IMPORTSETTING_GUI: {
                importerPackages.Remove(platformPackageKey);
                break;
            }

            case AssetBundleGraphSettings.NodeKind.MODIFIER_GUI: {
                IntegratedGUIModifier.DeletePlatformData(nodeId, platformPackageKey);
                break;
            }

            case AssetBundleGraphSettings.NodeKind.GROUPING_GUI: {
                groupingKeyword.Remove(platformPackageKey);
                break;
            }

            case AssetBundleGraphSettings.NodeKind.BUNDLIZER_GUI: {
                bundleNameTemplate.Remove(platformPackageKey);
                break;
            }

            case AssetBundleGraphSettings.NodeKind.BUNDLEBUILDER_GUI: {
                enabledBundleOptions.Remove(platformPackageKey);
                break;
            }

            case AssetBundleGraphSettings.NodeKind.EXPORTER_GUI: {
                exportTo.Remove(platformPackageKey);
                break;
            }

            default: {
                Debug.LogError(this.name + " is defined as unknown kind of node. value:" + this.kind);
                break;
            }
            }
        }
Example #3
0
        private void DoInspectorModifierGUI(NodeGUI node)
        {
            EditorGUILayout.HelpBox("Modifier: Force apply asset settings to given assets.", MessageType.Info);
            UpdateNodeName(node);

            GUILayout.Space(10f);

            var currentModifierTargetType = IntegratedGUIModifier.ModifierOperationTargetTypeName(node.nodeId);

            using (new EditorGUILayout.VerticalScope(GUI.skin.box)) {
                // show incoming type of Assets and reset interface.
                {
                    var isOperationDataExist = false;
                    IntegratedGUIModifier.ValidateModifiyOperationData(
                        node.nodeId,
                        node.currentPlatform,
                        () => {
                        GUILayout.Label("No modifier data found, please Reload first.");
                    },
                        () => {
                        isOperationDataExist = true;
                    }
                        );

                    if (!isOperationDataExist)
                    {
                        return;
                    }

                    using (new EditorGUILayout.HorizontalScope()) {
                        GUILayout.Label("Target Type:");
                        GUILayout.Label(currentModifierTargetType);
                    }

                    /*
                     *      reset whole platform's data for this modifier.
                     */
                    if (GUILayout.Button("Reset Modifier"))
                    {
                        var modifierFolderPath = FileUtility.PathCombine(AssetBundleGraphSettings.MODIFIER_OPERATOR_DATAS_PLACE, node.nodeId);
                        FileUtility.RemakeDirectory(modifierFolderPath);
                        node.Save();
                        modifierOperatorInstance = null;
                        return;
                    }
                }

                GUILayout.Space(10f);

                var usingScriptMode = !string.IsNullOrEmpty(node.scriptClassName);

                // use modifier script manually.
                {
                    GUIStyle s = new GUIStyle("TextFieldDropDownText");

                    /*
                     *      check prefabricator script-type string.
                     */
                    if (string.IsNullOrEmpty(node.scriptClassName))
                    {
                        s.fontStyle = FontStyle.Bold;
                        s.fontSize  = 12;
                    }
                    else
                    {
                        var loadedType = System.Reflection.Assembly.GetExecutingAssembly().CreateInstance(node.scriptClassName);

                        if (loadedType == null)
                        {
                            s.fontStyle = FontStyle.Bold;
                            s.fontSize  = 12;
                        }
                    }

                    var before = !string.IsNullOrEmpty(node.scriptClassName);
                    usingScriptMode = EditorGUILayout.ToggleLeft("Use ModifierOperator Script", !string.IsNullOrEmpty(node.scriptClassName));

                    // detect mode changed.
                    if (before != usingScriptMode)
                    {
                        // checked. initialize value of scriptClassName.
                        if (usingScriptMode)
                        {
                            node.BeforeSave();
                            node.scriptClassName = "MyModifier";
                            node.Save();
                        }

                        // unchecked.
                        if (!usingScriptMode)
                        {
                            node.BeforeSave();
                            node.scriptClassName = string.Empty;
                            node.Save();
                        }
                    }

                    if (!usingScriptMode)
                    {
                        EditorGUI.BeginDisabledGroup(true);
                    }
                    GUILayout.Label("ここをドロップダウンにする。2");
                    var newScriptClass = EditorGUILayout.TextField("Classname", node.scriptClassName, s);
                    if (newScriptClass != node.scriptClassName)
                    {
                        node.BeforeSave();
                        node.scriptClassName = newScriptClass;
                        node.Save();
                    }
                    if (!usingScriptMode)
                    {
                        EditorGUI.EndDisabledGroup();
                    }
                }

                GUILayout.Space(10f);

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

                // show for each platform tab.

                var currentPlatform = node.currentPlatform;
                node.currentPlatform = UpdateCurrentPlatform(node.currentPlatform);

                /*
                 *      if platform tab is changed, renew modifierOperatorInstance for that tab.
                 */
                if (currentPlatform != node.currentPlatform)
                {
                    modifierOperatorInstance = null;
                }

                /*
                 *      reload modifierOperator instance from saved modifierOperator data.
                 */
                if (modifierOperatorInstance == null)
                {
                    var modifierOperatorDataPath = IntegratedGUIModifier.ModifierDataPathForeachPlatform(node.nodeId, node.currentPlatform);

                    // choose default modifierOperatorData if platform specified file is not exist.
                    if (!File.Exists(modifierOperatorDataPath))
                    {
                        modifierOperatorDataPath = IntegratedGUIModifier.ModifierDataPathForDefaultPlatform(node.nodeId);
                    }

                    var loadedModifierOperatorDataStr = string.Empty;
                    using (var sr = new StreamReader(modifierOperatorDataPath)) {
                        loadedModifierOperatorDataStr = sr.ReadToEnd();
                    }

                    var modifierOperatorType = TypeUtility.SupportedModifierOperatorDefinition[currentModifierTargetType];

                    /*
                     *      create instance from saved modifierOperator data.
                     */
                    modifierOperatorInstance = typeof(NodeGUIEditor)
                                               .GetMethod("FromJson")
                                               .MakeGenericMethod(modifierOperatorType) // set desired generic type here.
                                               .Invoke(this, new object[] { loadedModifierOperatorDataStr }) as ModifierOperators.OperatorBase;
                }

                /*
                 *      Show ModifierOperator Inspector.
                 */
                if (modifierOperatorInstance != null)
                {
                    Action changed = () => {
                        var data       = JsonUtility.ToJson(modifierOperatorInstance);
                        var prettified = AssetBundleGraphEditorWindow.PrettifyJson(data);

                        var modifierOperatorDataPath = IntegratedGUIModifier.ModifierDataPathForeachPlatform(node.nodeId, node.currentPlatform);

                        using (var sw = new StreamWriter(modifierOperatorDataPath)) {
                            sw.Write(prettified);
                        }

                        // reflect change of data.
                        AssetDatabase.Refresh();

                        modifierOperatorInstance = null;
                    };

                    GUILayout.Space(10f);

                    modifierOperatorInstance.DrawInspector(changed);
                }

                var deleted = UpdateDeleteSetting(node);
                if (deleted)
                {
                    // source platform depended data is deleted. reload instance for reloading instance from data.
                    modifierOperatorInstance = null;
                }

                if (usingScriptMode)
                {
                    EditorGUI.EndDisabledGroup();
                }
            }
        }
Example #4
0
        private void DoInspectorModifierGUI(Node node)
        {
            EditorGUILayout.HelpBox("Modifier: Force apply asset settings to given assets.", MessageType.Info);
            UpdateNodeName(node);

            GUILayout.Space(10f);

            var currentModifierTargetType = IntegratedGUIModifier.ModifierOperationTargetTypeName(node.nodeId);

            using (new EditorGUILayout.VerticalScope(GUI.skin.box)) {
                var isOperationDataExist = false;
                IntegratedGUIModifier.ValidateModifiyOperationData(
                    node.nodeId,
                    node.currentPlatform,
                    () => {
                    GUILayout.Label("No modifier data found, please Reload first.");
                },
                    () => {
                    isOperationDataExist = true;
                }
                    );

                if (!isOperationDataExist)
                {
                    return;
                }

                using (new EditorGUILayout.HorizontalScope()) {
                    GUILayout.Label("Target Type:");
                    GUILayout.Label(currentModifierTargetType);
                }

                /*
                 *      reset whole platform's data for this modifier.
                 */
                if (GUILayout.Button("Reset Modifier"))
                {
                    var modifierFolderPath = FileController.PathCombine(AssetBundleGraphSettings.MODIFIER_OPERATOR_DATAS_PLACE, node.nodeId);
                    FileController.RemakeDirectory(modifierFolderPath);
                    node.Save();
                    modifierOperatorInstance = null;
                    return;
                }
            }

            var currentPlatform = node.currentPlatform;

            node.currentPlatform = UpdateCurrentPlatform(node.currentPlatform);

            /*
             *      if platform tab is changed, renew modifierOperatorInstance for that tab.
             */
            if (currentPlatform != node.currentPlatform)
            {
                modifierOperatorInstance = null;
            }

            /*
             *      reload modifierOperator instance from saved modifierOperator data.
             */
            if (modifierOperatorInstance == null)
            {
                var modifierOperatorDataPath = IntegratedGUIModifier.ModifierDataPathForeachPlatform(node.nodeId, node.currentPlatform);

                // choose default modifierOperatorData if platform specified file is not exist.
                if (!File.Exists(modifierOperatorDataPath))
                {
                    modifierOperatorDataPath = IntegratedGUIModifier.ModifierDataPathForDefaultPlatform(node.nodeId);
                }

                var loadedModifierOperatorDataStr = string.Empty;
                using (var sr = new StreamReader(modifierOperatorDataPath)) {
                    loadedModifierOperatorDataStr = sr.ReadToEnd();
                }

                var modifierOperatorType = TypeBinder.SupportedModifierOperatorDefinition[currentModifierTargetType];

                /*
                 *      create instance from saved modifierOperator data.
                 */
                modifierOperatorInstance = typeof(NodeEditor)
                                           .GetMethod("FromJson")
                                           .MakeGenericMethod(modifierOperatorType)// set desired generic type here.
                                           .Invoke(this, new object[] { loadedModifierOperatorDataStr }) as ModifierOperators.OperatorBase;
            }

            /*
             *      Show ModifierOperator Inspector.
             */
            if (modifierOperatorInstance != null)
            {
                Action changed = () => {
                    var data       = JsonUtility.ToJson(modifierOperatorInstance);
                    var prettified = AssetBundleGraph.PrettifyJson(data);

                    var modifierOperatorDataPath = IntegratedGUIModifier.ModifierDataPathForeachPlatform(node.nodeId, node.currentPlatform);

                    using (var sw = new StreamWriter(modifierOperatorDataPath)) {
                        sw.Write(prettified);
                    }

                    // reflect change of data.
                    AssetDatabase.Refresh();

                    modifierOperatorInstance = null;
                };

                GUILayout.Space(10f);

                modifierOperatorInstance.DrawInspector(changed);
            }

            var deleted = UpdateDeleteSetting(node);

            if (deleted)
            {
                // source platform depended data is deleted. reload instance for reloading instance from data.
                modifierOperatorInstance = null;
            }
        }
        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);
        }
Example #6
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);
        }