public void OnGUI()
        {
            DrawGUIToolBar();

            using (new EditorGUILayout.HorizontalScope()) {
                DrawGUINodeGraph();
                if(showErrors) {
                    DrawGUINodeErrors();
                }
            }

            /*
                Event Handling:
                - Supporting dragging script into window to create node.
                - Context Menu
                - NodeGUI connection.
                - Command(Delete, Copy, etc...)
            */
            switch (Event.current.type) {
                // detect dragging script then change interface to "(+)" icon.
                case EventType.DragUpdated: {
                    var refs = DragAndDrop.objectReferences;

                    foreach (var refe in refs) {
                        if (refe.GetType() == typeof(UnityEditor.MonoScript)) {
                            Type scriptTypeInfo = ((MonoScript)refe).GetClass();
                            Type inheritedTypeInfo = GetDragAndDropAcceptableScriptType(scriptTypeInfo);

                            if (inheritedTypeInfo != null) {
                                // at least one asset is script. change interface.
                                DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
                                break;
                            }
                        }
                    }
                    break;
                }

                // script drop on editor.
                case EventType.DragPerform: {
                    var pathAndRefs = new Dictionary<string, object>();
                    for (var i = 0; i < DragAndDrop.paths.Length; i++) {
                        var path = DragAndDrop.paths[i];
                        var refe = DragAndDrop.objectReferences[i];
                        pathAndRefs[path] = refe;
                    }
                    var shouldSave = false;
                    foreach (var item in pathAndRefs) {
                        var refe = (MonoScript)item.Value;
                        if (refe.GetType() == typeof(UnityEditor.MonoScript)) {
                            Type scriptTypeInfo = refe.GetClass();
                            Type inheritedTypeInfo = GetDragAndDropAcceptableScriptType(scriptTypeInfo);

                            if (inheritedTypeInfo != null) {
                                var dropPos = Event.current.mousePosition;
                                var scriptName = refe.name;
                                var scriptClassName = scriptName;
                                AddNodeFromCode(scriptName, scriptClassName, inheritedTypeInfo, dropPos.x, dropPos.y);
                                shouldSave = true;
                            }
                        }
                    }

                    if (shouldSave) {
                        SaveGraphWithReload();
                    }
                    break;
                }

                // show context menu
                case EventType.ContextClick: {
                    var rightClickPos = Event.current.mousePosition;
                    var menu = new GenericMenu();
                    foreach (var menuItemStr in AssetBundleGraphSettings.GUI_Menu_Item_TargetGUINodeDict.Keys) {
                        var kind = AssetBundleGraphSettings.GUI_Menu_Item_TargetGUINodeDict[menuItemStr];
                        menu.AddItem(
                            new GUIContent(menuItemStr),
                            false,
                            () => {
                                AddNodeFromGUI(kind, rightClickPos.x, rightClickPos.y);
                                SaveGraphWithReload();
                                Repaint();
                            }
                        );
                    }
                    menu.ShowAsContext();
                    break;
                }

                /*
                    Handling mouseUp at empty space.
                */
                case EventType.MouseUp: {
                    modifyMode = ModifyMode.NONE;
                    HandleUtility.Repaint();

                    if (activeObject.idPosDict.ReadonlyDict().Any()) {
                        Undo.RecordObject(this, "Unselect");

                        foreach (var activeObjectId in activeObject.idPosDict.ReadonlyDict().Keys) {
                            // unselect all.
                            foreach (var node in nodes) {
                                if (activeObjectId == node.Id) {
                                    node.SetInactive();
                                }
                            }
                            foreach (var connection in connections) {
                                if (activeObjectId == connection.Id) {
                                    connection.SetInactive();
                                }
                            }
                        }

                        activeObject = RenewActiveObject(new List<string>());

                    }

                    // clear inspector
                    if( Selection.activeObject is NodeGUIInspectorHelper || Selection.activeObject is ConnectionGUIInspectorHelper) {
                        Selection.activeObject = null;
                    }

                    break;
                }

                /*
                    scale up or down by command & + or command & -.
                */
                case EventType.KeyDown: {
                    if (Event.current.command) {
                        if (Event.current.shift && Event.current.keyCode == KeyCode.Semicolon) {
                            NodeGUI.scaleFactor = NodeGUI.scaleFactor + 0.1f;
                            if (NodeGUI.scaleFactor < NodeGUI.SCALE_MIN) NodeGUI.scaleFactor = NodeGUI.SCALE_MIN;
                            if (NodeGUI.SCALE_MAX < NodeGUI.scaleFactor) NodeGUI.scaleFactor = NodeGUI.SCALE_MAX;
                            Event.current.Use();
                            break;
                        }

                        if (Event.current.keyCode == KeyCode.Minus) {
                            NodeGUI.scaleFactor = NodeGUI.scaleFactor - 0.1f;
                            if (NodeGUI.scaleFactor < NodeGUI.SCALE_MIN) NodeGUI.scaleFactor = NodeGUI.SCALE_MIN;
                            if (NodeGUI.SCALE_MAX < NodeGUI.scaleFactor) NodeGUI.scaleFactor = NodeGUI.SCALE_MAX;
                            Event.current.Use();
                            break;
                        }
                    }
                    break;
                }

                case EventType.ValidateCommand:
                {
                    switch (Event.current.commandName) {
                    // Delete active node or connection.
                    case "Delete": {
                            if (activeObject.idPosDict.ReadonlyDict().Any()) {
                                Event.current.Use();
                            }
                            break;
                        }

                    case "Copy": {
                            if (activeObject.idPosDict.ReadonlyDict().Any()) {
                                Event.current.Use();
                            }
                            break;
                        }

                    case "Cut": {
                            if (activeObject.idPosDict.ReadonlyDict().Any()) {
                                Event.current.Use();
                            }
                            break;
                        }

                    case "Paste": {
                            if(copyField.datas == null)  {
                                break;
                            }

                            if (copyField.datas.Any()) {
                                Event.current.Use();
                            }
                            break;
                        }

                    case "SelectAll": {
                            Event.current.Use();
                            break;
                        }
                    }
                    break;
                }

                case EventType.ExecuteCommand:
                {
                    switch (Event.current.commandName) {
                        // Delete active node or connection.
                        case "Delete": {

                            if (!activeObject.idPosDict.ReadonlyDict().Any()) break;
                            Undo.RecordObject(this, "Delete Selection");

                            foreach (var targetId in activeObject.idPosDict.ReadonlyDict().Keys) {
                                DeleteNode(targetId);
                                DeleteConnectionById(targetId);
                            }

                            SaveGraphWithReload();

                            activeObject = RenewActiveObject(new List<string>());
                            UpdateActivationOfObjects(activeObject);

                            Event.current.Use();
                            break;
                        }

                        case "Copy": {
                            if (!activeObject.idPosDict.ReadonlyDict().Any()) {
                                break;
                            }

                            Undo.RecordObject(this, "Copy Selection");

                            var targetNodeIds = activeObject.idPosDict.ReadonlyDict().Keys.ToList();
                            var targetNodeJsonRepresentations = JsonRepresentations(targetNodeIds);
                            copyField = new CopyField(targetNodeJsonRepresentations, CopyType.COPYTYPE_COPY);

                            Event.current.Use();
                            break;
                        }

                        case "Cut": {
                            if (!activeObject.idPosDict.ReadonlyDict().Any()) {
                                break;
                            }

                            Undo.RecordObject(this, "Cut Selection");
                            var targetNodeIds = activeObject.idPosDict.ReadonlyDict().Keys.ToList();
                            var targetNodeJsonRepresentations = JsonRepresentations(targetNodeIds);
                            copyField = new CopyField(targetNodeJsonRepresentations, CopyType.COPYTYPE_CUT);

                            foreach (var targetId in activeObject.idPosDict.ReadonlyDict().Keys) {
                                DeleteNode(targetId);
                                DeleteConnectionById(targetId);
                            }

                            SaveGraphWithReload();
                            InitializeGraph();

                            activeObject = RenewActiveObject(new List<string>());
                            UpdateActivationOfObjects(activeObject);

                            Event.current.Use();
                            break;
                        }

                        case "Paste": {

                            if(copyField.datas == null)  {
                                break;
                            }

                            var nodeNames = nodes.Select(node => node.Name).ToList();
                            var duplicatingData = new List<NodeGUI>();

                            if (copyField.datas.Any()) {
                                var pasteType = copyField.type;
                                foreach (var copyFieldData in copyField.datas) {
                                    var nodeJsonDict = AssetBundleGraph.Json.Deserialize(copyFieldData) as Dictionary<string, object>;
                                    var pastingNode = new NodeGUI(new NodeData(nodeJsonDict));
                                    var pastingNodeName = pastingNode.Name;

                                    var nameOverlapping = nodeNames.Where(name => name == pastingNodeName).ToList();

              									switch (pasteType) {
              										case CopyType.COPYTYPE_COPY: {
                                            if (2 <= nameOverlapping.Count) {
                                                continue;
                                            }
              											break;
              										}
              										case CopyType.COPYTYPE_CUT: {
                                            if (1 <= nameOverlapping.Count) {
                                                continue;
                                            }
              											break;
              										}
              									}

              									duplicatingData.Add(pastingNode);
                                }
                            }
                            // consume copyField
                            copyField.datas = null;

                            if (!duplicatingData.Any()) {
                                break;
                            }

                            Undo.RecordObject(this, "Paste");
                            foreach (var newNode in duplicatingData) {
                                DuplicateNode(newNode);
                            }

                            SaveGraphWithReload();
                            InitializeGraph();

                            Event.current.Use();
                            break;
                        }

                        case "SelectAll": {
                            Undo.RecordObject(this, "Select All Objects");

                            var nodeIds = nodes.Select(node => node.Id).ToList();
                            activeObject = RenewActiveObject(nodeIds);

                            // select all.
                            foreach (var node in nodes) {
                                node.SetActive();
                            }
                            foreach (var connection in connections) {
                                connection.SetActive();
                            }

                            Event.current.Use();
                            break;
                        }

                        default: {
                            break;
                        }
                    }
                    break;
                }
            }
        }
示例#2
0
        public void OnGUI()
        {
            using (new EditorGUILayout.HorizontalScope(GUI.skin.box)) {
                if (GUILayout.Button(reloadButtonTexture, GUILayout.Height(18))) {
                    Setup();
                }

                if (GUILayout.Button("Build (active build target is " + EditorUserBuildSettings.activeBuildTarget + ")", GUILayout.Height(18))) {
                    Run();
                }
            }

            /*
                scroll view.
            */
            // var scaledScrollPos = Node.ScaleEffect(scrollPos);
            scrollPos = EditorGUILayout.BeginScrollView(scrollPos);
            // scrollPos = scrollPos + (movedScrollPos - scaledScrollPos);
            {

                // draw node window x N.
                {
                    BeginWindows();

                    nodes.ForEach(node => node.DrawNode());

                    EndWindows();
                }

                // draw connection input point marks.
                foreach (var node in nodes) {
                    node.DrawConnectionInputPointMark(currentEventSource, modifyMode == ModifyMode.CONNECT_STARTED);
                }

                // draw connections.
                foreach (var con in connections) {
                    if (connectionThroughputs.ContainsKey(con.connectionId)) {
                        var throughputListDict = connectionThroughputs[con.connectionId];
                        con.DrawConnection(nodes, throughputListDict);
                    } else {
                        con.DrawConnection(nodes, new Dictionary<string, List<ThroughputAsset>>());
                    }
                }

                // draw connection output point marks.
                foreach (var node in nodes) {
                    node.DrawConnectionOutputPointMark(currentEventSource, modifyMode == ModifyMode.CONNECT_STARTED, Event.current);
                }

                /*
                    draw connecting line if modifing connection.
                */
                switch (modifyMode) {
                    case ModifyMode.CONNECT_STARTED: {
                        // from start node to mouse.
                        DrawStraightLineFromCurrentEventSourcePointTo(Event.current.mousePosition, currentEventSource);

                        break;
                    }
                    case ModifyMode.CONNECT_ENDED: {
                        // do nothing
                        break;
                    }
                    case ModifyMode.SELECTION_STARTED: {
                        GUI.DrawTexture(new Rect(selection.x, selection.y, Event.current.mousePosition.x - selection.x, Event.current.mousePosition.y - selection.y), selectionTex);
                        break;
                    }
                }

                /*
                    mouse drag event handling.
                */
                switch (Event.current.type) {

                    // draw line while dragging.
                    case EventType.MouseDrag: {
                        switch (modifyMode) {
                            case ModifyMode.CONNECT_ENDED: {
                                switch (Event.current.button) {
                                    case 0:{// left click
                                        if (Event.current.command) {
                                            scalePoint = new ScalePoint(Event.current.mousePosition, Node.scaleFactor, 0);
                                            modifyMode = ModifyMode.SCALING_STARTED;
                                            break;
                                        }

                                        selection = new AssetBundleGraphSelection(Event.current.mousePosition);
                                        modifyMode = ModifyMode.SELECTION_STARTED;
                                        break;
                                    }
                                    case 2:{// middle click.
                                        scalePoint = new ScalePoint(Event.current.mousePosition, Node.scaleFactor, 0);
                                        modifyMode = ModifyMode.SCALING_STARTED;
                                        break;
                                    }
                                }
                                break;
                            }
                            case ModifyMode.SELECTION_STARTED: {
                                // do nothing.
                                break;
                            }
                            case ModifyMode.SCALING_STARTED: {
                                var baseDistance = (int)Vector2.Distance(Event.current.mousePosition, new Vector2(scalePoint.x, scalePoint.y));
                                var distance = baseDistance / Node.SCALE_WIDTH;
                                var direction = (0 < Event.current.mousePosition.y - scalePoint.y);

                                if (!direction) distance = -distance;

                                // var before = Node.scaleFactor;
                                Node.scaleFactor = scalePoint.startScale + (distance * Node.SCALE_RATIO);

                                if (Node.scaleFactor < Node.SCALE_MIN) Node.scaleFactor = Node.SCALE_MIN;
                                if (Node.SCALE_MAX < Node.scaleFactor) Node.scaleFactor = Node.SCALE_MAX;
                                break;
                            }
                        }

                        HandleUtility.Repaint();
                        Event.current.Use();
                        break;
                    }
                }

                /*
                    mouse up event handling.
                    use rawType for detect for detectiong mouse-up which raises outside of window.
                */
                switch (Event.current.rawType) {
                    case EventType.MouseUp: {
                        switch (modifyMode) {
                            /*
                                select contained nodes & connections.
                            */
                            case ModifyMode.SELECTION_STARTED: {
                                var x = 0f;
                                var y = 0f;
                                var width = 0f;
                                var height = 0f;

                                if (Event.current.mousePosition.x < selection.x) {
                                    x = Event.current.mousePosition.x;
                                    width = selection.x - Event.current.mousePosition.x;
                                }
                                if (selection.x < Event.current.mousePosition.x) {
                                    x = selection.x;
                                    width = Event.current.mousePosition.x - selection.x;
                                }

                                if (Event.current.mousePosition.y < selection.y) {
                                    y = Event.current.mousePosition.y;
                                    height = selection.y - Event.current.mousePosition.y;
                                }
                                if (selection.y < Event.current.mousePosition.y) {
                                    y = selection.y;
                                    height = Event.current.mousePosition.y - selection.y;
                                }

                                var activeObjectIds = new List<string>();

                                var selectedRect = new Rect(x, y, width, height);

                                foreach (var node in nodes) {
                                    var nodeRect = new Rect(node.GetRect());
                                    nodeRect.x = nodeRect.x * Node.scaleFactor;
                                    nodeRect.y = nodeRect.y * Node.scaleFactor;
                                    nodeRect.width = nodeRect.width * Node.scaleFactor;
                                    nodeRect.height = nodeRect.height * Node.scaleFactor;
                                    // get containd nodes,
                                    if (nodeRect.Overlaps(selectedRect)) {
                                        activeObjectIds.Add(node.nodeId);
                                    }
                                }

                                foreach (var connection in connections) {
                                    // get contained connection badge.
                                    if (connection.GetRect().Overlaps(selectedRect)) {
                                        activeObjectIds.Add(connection.connectionId);
                                    }
                                }

                                if (Event.current.shift) {
                                    // add current active object ids to new list.
                                    foreach (var alreadySelectedObjectId in activeObject.idPosDict.ReadonlyDict().Keys) {
                                        if (!activeObjectIds.Contains(alreadySelectedObjectId)) activeObjectIds.Add(alreadySelectedObjectId);
                                    }
                                } else {
                                    // do nothing, means cancel selections if nodes are not contained by selection.
                                }

                                Undo.RecordObject(this, "Select Objects");

                                activeObject = RenewActiveObject(activeObjectIds);
                                UpdateActivationOfObjects(activeObject);

                                selection = new AssetBundleGraphSelection(Vector2.zero);
                                modifyMode = ModifyMode.CONNECT_ENDED;

                                HandleUtility.Repaint();
                                Event.current.Use();
                                break;
                            }

                            case ModifyMode.SCALING_STARTED: {
                                modifyMode = ModifyMode.CONNECT_ENDED;
                                break;
                            }
                        }
                        break;
                    }
                }

                // set rect for scroll.
                if (nodes.Any()) {
                    GUILayoutUtility.GetRect(new GUIContent(string.Empty), GUIStyle.none, GUILayout.Width(spacerRectRightBottom.x), GUILayout.Height(spacerRectRightBottom.y));
                }
            }
            EditorGUILayout.EndScrollView();

            /*
                detect
                    dragging some script into window.
                    right click.
                    connection end mouse up.
                    command(Delete, Copy, and more)
            */
            switch (Event.current.type) {
                // detect dragging script then change interface to "(+)" icon.
                case EventType.DragUpdated: {
                    var refs = DragAndDrop.objectReferences;

                    foreach (var refe in refs) {
                        if (refe.GetType() == typeof(UnityEditor.MonoScript)) {
                            var type = ((MonoScript)refe).GetClass();

                            var inherited = IsAcceptableScriptType(type);

                            if (inherited != null) {
                                // at least one asset is script. change interface.
                                DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
                                break;
                            }
                        }
                    }
                    break;
                }

                // script drop on editor.
                case EventType.DragPerform: {
                    var pathAndRefs = new Dictionary<string, object>();
                    for (var i = 0; i < DragAndDrop.paths.Length; i++) {
                        var path = DragAndDrop.paths[i];
                        var refe = DragAndDrop.objectReferences[i];
                        pathAndRefs[path] = refe;
                    }
                    var shouldSave = false;
                    foreach (var item in pathAndRefs) {
                        var path = item.Key;
                        var refe = (MonoScript)item.Value;
                        if (refe.GetType() == typeof(UnityEditor.MonoScript)) {
                            var type = refe.GetClass();
                            var inherited = IsAcceptableScriptType(type);

                            if (inherited != null) {
                                var dropPos = Event.current.mousePosition;
                                var scriptName = refe.name;
                                var scriptType = scriptName;// name = type.
                                var scriptPath = path;
                                AddNodeFromCode(scriptName, scriptType, scriptPath, inherited, Guid.NewGuid().ToString(), dropPos.x, dropPos.y);
                                shouldSave = true;
                            }
                        }
                    }

                    if (shouldSave) SaveGraphWithReload();
                    break;
                }

                // show context menu
                case EventType.ContextClick: {
                    var rightClickPos = Event.current.mousePosition;
                    var menu = new GenericMenu();
                    foreach (var menuItemStr in AssetBundleGraphSettings.GUI_Menu_Item_TargetGUINodeDict.Keys) {
                        var targetGUINodeNameStr = AssetBundleGraphSettings.GUI_Menu_Item_TargetGUINodeDict[menuItemStr];
                        menu.AddItem(
                            new GUIContent(menuItemStr),
                            false,
                            () => {
                                AddNodeFromGUI(string.Empty, targetGUINodeNameStr, Guid.NewGuid().ToString(), rightClickPos.x, rightClickPos.y);
                                SaveGraphWithReload();
                                Repaint();
                            }
                        );
                    }
                    menu.ShowAsContext();
                    break;
                }

                /*
                    handling mouse up
                         -> drag released -> release modifyMode.
                */
                case EventType.MouseUp: {
                    modifyMode = ModifyMode.CONNECT_ENDED;
                    HandleUtility.Repaint();

                    if (activeObject.idPosDict.ReadonlyDict().Any()) {
                        Undo.RecordObject(this, "Unselect");

                        foreach (var activeObjectId in activeObject.idPosDict.ReadonlyDict().Keys) {
                            // unselect all.
                            foreach (var node in nodes) {
                                if (activeObjectId == node.nodeId) node.SetInactive();
                            }
                            foreach (var connection in connections) {
                                if (activeObjectId == connection.connectionId) connection.SetInactive();
                            }
                        }

                        activeObject = RenewActiveObject(new List<string>());
                    }

                    break;
                }

                /*
                    scale up or down by command & + or command & -.
                */
                case EventType.KeyDown: {
                    if (Event.current.command) {
                        if (Event.current.shift && Event.current.keyCode == KeyCode.Semicolon) {
                            Node.scaleFactor = Node.scaleFactor + 0.1f;
                            if (Node.scaleFactor < Node.SCALE_MIN) Node.scaleFactor = Node.SCALE_MIN;
                            if (Node.SCALE_MAX < Node.scaleFactor) Node.scaleFactor = Node.SCALE_MAX;
                            Event.current.Use();
                            break;
                        }

                        if (Event.current.keyCode == KeyCode.Minus) {
                            Node.scaleFactor = Node.scaleFactor - 0.1f;
                            if (Node.scaleFactor < Node.SCALE_MIN) Node.scaleFactor = Node.SCALE_MIN;
                            if (Node.SCALE_MAX < Node.scaleFactor) Node.scaleFactor = Node.SCALE_MAX;
                            Event.current.Use();
                            break;
                        }
                    }
                    break;
                }

                case EventType.ValidateCommand: {
                    switch (Event.current.commandName) {
                        // Delete active node or connection.
                        case "Delete": {

                            if (!activeObject.idPosDict.ReadonlyDict().Any()) break;
                            Undo.RecordObject(this, "Delete Selection");

                            foreach (var targetId in activeObject.idPosDict.ReadonlyDict().Keys) {
                                DeleteNode(targetId);
                                DeleteConnectionById(targetId);
                            }

                            SaveGraphWithReload();
                            InitializeGraph();

                            activeObject = RenewActiveObject(new List<string>());
                            UpdateActivationOfObjects(activeObject);

                            Event.current.Use();
                            break;
                        }

                        case "Copy": {
                            if (!activeObject.idPosDict.ReadonlyDict().Any()) {
                                break;
                            }

                            Undo.RecordObject(this, "Copy Selection");

                            var targetNodeIds = activeObject.idPosDict.ReadonlyDict().Keys.ToList();
                            var targetNodeJsonRepresentations = JsonRepresentations(targetNodeIds);
                            copyField = new CopyField(targetNodeJsonRepresentations, CopyType.COPYTYPE_COPY);

                            Event.current.Use();
                            break;
                        }

                        case "Cut": {
                            if (!activeObject.idPosDict.ReadonlyDict().Any()) {
                                break;
                            }

                            Undo.RecordObject(this, "Cut Selection");
                            var targetNodeIds = activeObject.idPosDict.ReadonlyDict().Keys.ToList();
                            var targetNodeJsonRepresentations = JsonRepresentations(targetNodeIds);
                            copyField = new CopyField(targetNodeJsonRepresentations, CopyType.COPYTYPE_CUT);

                            foreach (var targetId in activeObject.idPosDict.ReadonlyDict().Keys) {
                                DeleteNode(targetId);
                                DeleteConnectionById(targetId);
                            }

                            SaveGraphWithReload();
                            InitializeGraph();

                            activeObject = RenewActiveObject(new List<string>());
                            UpdateActivationOfObjects(activeObject);

                            Event.current.Use();
                            break;
                        }

                        case "Paste": {
                            var nodeNames = nodes.Select(node => node.name).ToList();
                            var duplicatingData = new List<Node>();

                            if (copyField.datas.Any()) {
                                var pasteType = copyField.type;
                                foreach (var copyFieldData in copyField.datas) {
                                    var nodeJsonDict = Json.Deserialize(copyFieldData) as Dictionary<string, object>;
                                    var pastingNode = NodeFromJsonDict(nodes.Count, nodeJsonDict);
                                    var pastingNodeName = pastingNode.name;

                                    var nameOverlapping = nodeNames.Where(name => name == pastingNodeName).ToList();

              									switch (pasteType) {
              										case CopyType.COPYTYPE_COPY: {
              											if (2 <= nameOverlapping.Count) continue;
              											break;
              										}
              										case CopyType.COPYTYPE_CUT: {
              											if (1 <= nameOverlapping.Count) continue;
              											break;
              										}
              									}

              									duplicatingData.Add(pastingNode);
                                }
                            }

                            if (!duplicatingData.Any()) break;

                            Undo.RecordObject(this, "Paste");
                            foreach (var newNode in duplicatingData) {
                                DuplicateNode(newNode);
                            }

                            SaveGraphWithReload();
                            InitializeGraph();

                            Event.current.Use();
                            break;
                        }

                        case "SelectAll": {
                            Undo.RecordObject(this, "Select All Objects");

                            var nodeIds = nodes.Select(node => node.nodeId).ToList();
                            activeObject = RenewActiveObject(nodeIds);

                            // select all.
                            foreach (var node in nodes) {
                                node.SetActive();
                            }
                            foreach (var connection in connections) {
                                connection.SetActive();
                            }

                            Event.current.Use();
                            break;
                        }

                        default: {
                            break;
                        }
                    }
                    break;
                }
            }
        }