private void HandleGraphGUIEvents()
        {
            //mouse drag event handling.
            switch (Event.current.type) {
            // draw line while dragging.
            case EventType.MouseDrag: {
                    switch (modifyMode) {
                    case ModifyMode.NONE: {
                            switch (Event.current.button) {
                            case 0:{// left click
                                    if (Event.current.command) {
                                        scalePoint = new ScalePoint(Event.current.mousePosition, NodeGUI.scaleFactor, 0);
                                        modifyMode = ModifyMode.SCALING;
                                        break;
                                    }

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

                            if (!direction) distance = -distance;

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

                            if (NodeGUI.scaleFactor < NodeGUI.SCALE_MIN) NodeGUI.scaleFactor = NodeGUI.SCALE_MIN;
                            if (NodeGUI.SCALE_MAX < NodeGUI.scaleFactor) NodeGUI.scaleFactor = NodeGUI.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.SELECTING: {
                            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 * NodeGUI.scaleFactor;
                                nodeRect.y = nodeRect.y * NodeGUI.scaleFactor;
                                nodeRect.width = nodeRect.width * NodeGUI.scaleFactor;
                                nodeRect.height = nodeRect.height * NodeGUI.scaleFactor;
                                // get containd nodes,
                                if (nodeRect.Overlaps(selectedRect)) {
                                    activeObjectIds.Add(node.Id);
                                }
                            }

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

                            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.NONE;

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

                    case ModifyMode.SCALING: {
                            modifyMode = ModifyMode.NONE;
                            break;
                        }
                    }
                    break;
                }
            }
        }
Beispiel #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;
                }
            }
        }