Пример #1
0
        //SL--
        public void InsetNodeBetweenConnect(FlowCanvas.BinderConnection connect, Vector2 insertPosition)
        {
            Port sp = connect.sourcePort;
            Port tp = connect.targetPort;

            if (sp.type == typeof(Flow))
            {
                var newNode = (FlowNode)AddNode(typeof(FlowCanvas.Nodes.Dummy), insertPosition);

                RemoveConnection(connect);

                FlowCanvas.BinderConnection.Create(sp, newNode.GetInputPort("In"));
                FlowCanvas.BinderConnection.Create(newNode.GetOutputPort("Out"), tp);
                newNode.GatherPorts();
            }
            else
            {
                var newNode = (FlowNode)AddNode(typeof(FlowCanvas.Nodes.ValuePoint <>), insertPosition);
                RemoveConnection(connect);
                var bc = FlowCanvas.BinderConnection.Create(sp, newNode.GetInputPort("In"));
                //newNode.GatherPorts();
                FlowCanvas.BinderConnection.Create(((FlowCanvas.FlowNode)(bc.targetNode)).GetOutputPort("Out"), tp);
                newNode.GatherPorts();
            }
        }
        ///----------------------------------------------------------------------------------------------

        ///Create a NEW BinderConnection object between two ports
        public static BinderConnection Create(Port source, Port target)
        {
            if (!CanBeBoundVerbosed(source, target, null, out string verbose))
            {
                ParadoxNotion.Services.Logger.LogWarning(verbose, LogTag.EDITOR, source.parent);
                return(null);
            }

            ParadoxNotion.Design.UndoUtility.RecordObject(source.parent.graph, "Connect Ports");

            BinderConnection binder = null;

            if (source is FlowOutput && target is FlowInput)
            {
                binder = new BinderConnection();
            }

            if (source is ValueOutput && target is ValueInput)
            {
                binder = (BinderConnection)System.Activator.CreateInstance(typeof(BinderConnection <>).RTMakeGenericType(new System.Type[] { target.type }));
            }

            if (binder != null)
            {
                binder.sourcePortID = source.ID;
                binder.targetPortID = target.ID;

                binder.SetSourceNode(source.parent);
                binder.SetTargetNode(target.parent);

                binder.sourcePort.connections++;
                binder.targetPort.connections++;

                binder.sourcePort.parent.OnPortConnected(binder.sourcePort, binder.targetPort);
                binder.targetPort.parent.OnPortConnected(binder.targetPort, binder.sourcePort);

                //for live editing
                if (Application.isPlaying)
                {
                    binder.Bind();
                }
            }

            ParadoxNotion.Design.UndoUtility.SetDirty(source.parent.graph);
            return(binder);
        }
        ///----------------------------------------------------------------------------------------------

        ///Create a NEW BinderConnection object between two ports
        public static BinderConnection Create(Port source, Port target)
        {
            var verbose = CanBeBoundVerbosed(source, target);

            if (verbose != null)
            {
                ParadoxNotion.Services.Logger.LogWarning(verbose, "Editor", source.parent);
                return(null);
            }

            source.parent.graph.RecordUndo("Connect Ports");

            BinderConnection binder = null;

            if (source is FlowOutput && target is FlowInput)
            {
                binder = new BinderConnection();
            }

            if (source is ValueOutput && target is ValueInput)
            {
                binder = (BinderConnection)System.Activator.CreateInstance(typeof(BinderConnection <>).RTMakeGenericType(new System.Type[] { target.type }));
            }

            if (binder != null)
            {
                binder.SetSourcePort(source, true);
                binder.SetTargetPort(target, true);

                //we call SetSource and SetTarget with 'isNew' flag, because we need call 'OnPort...' callbacks after both are set
                binder.sourcePort.connections++;
                binder.targetPort.connections++;
                binder.sourcePort.parent.OnPortConnected(binder.sourcePort, binder.targetPort);
                binder.targetPort.parent.OnPortConnected(binder.targetPort, binder.sourcePort);

                //for live editing
                if (Application.isPlaying)
                {
                    binder.Bind();
                }
            }

            return(binder);
        }
Пример #4
0
        //...
        static void FinalizeConnection(Port sourcePort, FlowNode targetNode)
        {
            if (sourcePort == null || targetNode == null)
            {
                return;
            }

            Port source = null;
            Port target = null;

            if (sourcePort is ValueOutput || sourcePort is FlowOutput)
            {
                source = sourcePort;
                target = targetNode.GetFirstInputOfType(sourcePort.type);
            }
            else
            {
                source = targetNode.GetFirstOutputOfType(sourcePort.type);
                target = sourcePort;
            }

            BinderConnection.Create(source, target);
        }
        ///----------------------------------------------------------------------------------------------
        ///----------------------------------------------------------------------------------------------

        ///Convert nodes to macro (with a bit of hocus pocus)
        public static void ConvertNodesToMacro(List <Node> originalNodes)
        {
            if (originalNodes == null || originalNodes.Count == 0)
            {
                return;
            }

            if (!UnityEditor.EditorUtility.DisplayDialog("Convert to Macro", "This will create a new Macro out of the nodes.\nPlease note that since Macros are assets, Scene Object references will not be saved.\nThe Macro can NOT be unpacked later on.\nContinue?", "Yes", "No!"))
            {
                return;
            }

            //create asset
            var newMacro = EditorUtils.CreateAsset <Macro>();

            if (newMacro == null)
            {
                return;
            }

            //undo
            var graph = (FlowScriptBase)originalNodes[0].graph;

            graph.RecordUndo("Convert To Macro");

            //clone nodes
            var cloned = Graph.CloneNodes(originalNodes, newMacro, -newMacro.translation);

            //clear initial "example" ports
            newMacro.inputDefinitions.Clear();
            newMacro.outputDefinitions.Clear();

            //cache used ports
            var inputMergeMapSource = new Dictionary <Port, Port>();
            var inputMergeMapTarget = new Dictionary <Port, Port>();

            var outputMergeMapTarget = new Dictionary <Port, Port>();
            var outputMergeMapSource = new Dictionary <Port, Port>();


            //relink copied nodes to inside macro entry/exit
            for (var i = 0; i < originalNodes.Count; i++)
            {
                var originalNode = originalNodes[i];
                //create macro entry node port definitions and link those to input ports of cloned nodes inside
                foreach (var originalInputConnection in originalNode.inConnections.OfType <BinderConnection>())
                {
                    //only do stuff if link source node is not part of the clones
                    if (originalNodes.Contains(originalInputConnection.sourceNode))
                    {
                        continue;
                    }
                    Port defSourcePort = null;
                    //merge same input ports and same target ports
                    if (!inputMergeMapSource.TryGetValue(originalInputConnection.sourcePort, out defSourcePort))
                    {
                        if (!inputMergeMapTarget.TryGetValue(originalInputConnection.targetPort, out defSourcePort))
                        {
                            //remark: we use sourcePort.type instead of target port type, so that connections remain assignable
                            var def = new DynamicPortDefinition(originalInputConnection.targetPort.name, originalInputConnection.sourcePort.type);
                            defSourcePort = newMacro.AddInputDefinition(def);
                            inputMergeMapTarget[originalInputConnection.targetPort] = defSourcePort;
                        }
                        inputMergeMapSource[originalInputConnection.sourcePort] = defSourcePort;
                    }

                    if (defSourcePort.CanAcceptConnections())                      //check this for case of merged FlowPorts
                    {
                        var targetPort = (cloned[i] as FlowNode).GetInputPort(originalInputConnection.targetPortID);
                        BinderConnection.Create(defSourcePort, targetPort);
                    }
                }

                //create macro exit node port definitions and link those to output ports of cloned nodes inside
                foreach (var originalOutputConnection in originalNode.outConnections.OfType <BinderConnection>())
                {
                    //only do stuff if link target node is not part of the clones
                    if (originalNodes.Contains(originalOutputConnection.targetNode))
                    {
                        continue;
                    }
                    Port defTargetPort = null;
                    //merge same input ports and same target ports
                    if (!outputMergeMapTarget.TryGetValue(originalOutputConnection.targetPort, out defTargetPort))
                    {
                        if (!outputMergeMapSource.TryGetValue(originalOutputConnection.sourcePort, out defTargetPort))
                        {
                            var def = new DynamicPortDefinition(originalOutputConnection.sourcePort.name, originalOutputConnection.sourcePort.type);
                            defTargetPort = newMacro.AddOutputDefinition(def);
                            outputMergeMapSource[originalOutputConnection.sourcePort] = defTargetPort;
                        }
                        outputMergeMapTarget[originalOutputConnection.targetPort] = defTargetPort;
                    }

                    if (defTargetPort.CanAcceptConnections())                      //check this for case of merged ValuePorts
                    {
                        var sourcePort = (cloned[i] as FlowNode).GetOutputPort(originalOutputConnection.sourcePortID);
                        BinderConnection.Create(sourcePort, defTargetPort);
                    }
                }
            }

            //Delete originals
            var originalBounds = RectUtils.GetBoundRect(originalNodes.Select(n => n.rect).ToArray());

            foreach (var node in originalNodes.ToArray())
            {
                graph.RemoveNode(node, false);
            }

            //Create MacroWrapper. Relink macro wrapper to outside nodes
            var wrapperPos = originalBounds.center;

            wrapperPos.x = (int)wrapperPos.x;
            wrapperPos.y = (int)wrapperPos.y;
            var wrapper = graph.AddMacroNode(newMacro, wrapperPos, null, null);

            wrapper.GatherPorts();
            foreach (var pair in inputMergeMapSource)
            {
                var source = pair.Key;
                var target = wrapper.GetInputPort(pair.Value.ID);
                BinderConnection.Create(source, target);
            }
            foreach (var pair in outputMergeMapTarget)
            {
                var source = wrapper.GetOutputPort(pair.Value.ID);
                var target = pair.Key;
                BinderConnection.Create(source, target);
            }

            //organize a bit
            var clonedBounds = RectUtils.GetBoundRect(cloned.Select(n => n.rect).ToArray());

            newMacro.entry.position = new Vector2((int)(clonedBounds.xMin - 300), (int)clonedBounds.yMin);
            newMacro.exit.position  = new Vector2((int)(clonedBounds.xMax + 300), (int)clonedBounds.yMin);
            newMacro.translation    = -newMacro.entry.position + new Vector2(300, 300);
            //

            //validate and save
            newMacro.Validate();
            UnityEditor.AssetDatabase.SaveAssets();
        }
Пример #6
0
        ///Create a NEW binding connection object between two ports
        public static BinderConnection Create(Port source, Port target)
        {
            if (source == null || target == null)
            {
                return(null);
            }

            if (source == target)
            {
                return(null);
            }

            if (!source.CanAcceptConnections())
            {
                ParadoxNotion.Services.Logger.LogWarning("Source port can accept no more connections.", "Editor", source.parent);
                return(null);
            }

            if (!target.CanAcceptConnections())
            {
                ParadoxNotion.Services.Logger.LogWarning("Target port can accept no more connections.", "Editor", source.parent);
                return(null);
            }

            if (source.parent == target.parent)
            {
                ParadoxNotion.Services.Logger.LogWarning("Can't connect ports on the same parent node.", "Editor", source.parent);
                return(null);
            }

            if (source is FlowOutput && !(target is FlowInput))
            {
                ParadoxNotion.Services.Logger.LogWarning("Flow ports can only be connected to other Flow ports.", "Editor", source.parent);
                return(null);
            }

            if ((source is FlowInput && target is FlowInput) || (source is ValueInput && target is ValueInput))
            {
                ParadoxNotion.Services.Logger.LogWarning("Can't connect input to input.", "Editor", source.parent);
                return(null);
            }

            if ((source is FlowOutput && target is FlowOutput) || (source is ValueOutput && target is ValueOutput))
            {
                ParadoxNotion.Services.Logger.LogWarning("Can't connect output to output.", "Editor", source.parent);
                return(null);
            }

            if (!TypeConverter.HasConvertion(source.type, target.type))
            {
                ParadoxNotion.Services.Logger.LogWarning(string.Format("Can't connect ports. Type '{0}' is not assignable from Type '{1}' and there exists no automatic conversion for those types.", target.type.FriendlyName(), source.type.FriendlyName()), "Editor", source.parent);
                return(null);
            }


                        #if UNITY_EDITOR
            UnityEditor.Undo.RecordObject(source.parent.graph, "Connect Ports");
                        #endif

            BinderConnection binder = null;
            if (source is FlowOutput && target is FlowInput)
            {
                binder = new BinderConnection();
            }

            if (source is ValueOutput && target is ValueInput)
            {
                binder = (BinderConnection)System.Activator.CreateInstance(typeof(BinderConnection <>).RTMakeGenericType(new System.Type[] { target.type }));
            }

            if (binder != null)
            {
                binder.OnCreate(source, target);
            }
            return(binder);
        }
        ///Return whether or not source can connect to target. The return is a string with the reason why NOT, null if possible.
        ///Providing an existing ref connection, will bypass source/target validation respectively if that connection is already connected to that source/target port.
        public static string CanBeBoundVerbosed(Port source, Port target, BinderConnection refConnection = null)
        {
            if (source == null || target == null)
            {
                return("A port is null.");
            }

            if (source == target)
            {
                // return "Can't connect port to itself.";
                return(string.Empty);
            }

            if (source.parent == target.parent)
            {
                return("Can't connect ports on the same node.");
            }

            if (source.parent == target.parent)
            {
                return("Can't connect ports on the same parent node.");
            }

            if (source.IsInputPort() && target.IsInputPort())
            {
                return("Can't connect input to input.");
            }

            if (source.IsOutputPort() && target.IsOutputPort())
            {
                return("Can't connect output to output.");
            }

            if (source.IsFlowPort() != target.IsFlowPort())
            {
                return("Flow ports can only be connected to other Flow ports.");
            }

            if (refConnection == null || refConnection.sourcePort != source)
            {
                if (!source.CanAcceptConnections())
                {
                    return("Source port can accept no more out connections.");
                }
            }

            if (refConnection == null || refConnection.targetPort != target)
            {
                if (!target.CanAcceptConnections())
                {
                    return("Target port can accept no more in connections.");
                }
            }

            if (!TypeConverter.HasConvertion(source.type, target.type))
            {
                return(string.Format("Can't connect ports. Type '{0}' is not assignable from Type '{1}' and there exists no automatic conversion for those types.", target.type.FriendlyName(), source.type.FriendlyName()));
            }

            return(null);
        }
 ///Return whether or not source can connect to target.
 public static bool CanBeBound(Port source, Port target, BinderConnection refConnection = null)
 {
     return(CanBeBoundVerbosed(source, target, refConnection) == null);
 }
Пример #9
0
        //Seal it...
        sealed protected override void DrawNodeConnections(Rect drawCanvas, bool fullDrawPass, Vector2 canvasMousePos, float zoomFactor)
        {
            var e = Event.current;

            //Port container graphics
            if (fullDrawPass || drawCanvas.Overlaps(rect))
            {
                GUI.Box(new Rect(rect.x - 8, rect.y + 2, 10, rect.height), string.Empty, CanvasStyles.nodePortContainer);
                GUI.Box(new Rect(rect.xMax - 2, rect.y + 2, 10, rect.height), string.Empty, CanvasStyles.nodePortContainer);
            }
            ///

            if (fullDrawPass || drawCanvas.Overlaps(rect))
            {
                var portRect = new Rect(0, 0, 10, 10);

                //INPUT Ports
                if (orderedInputs != null)
                {
                    Port instancePort = null;
                    for (var i = 0; i < orderedInputs.Length; i++)
                    {
                        var port       = orderedInputs[i];
                        var canConnect = true;
                        if (clickedPort != null)
                        {
                            if ((port == clickedPort) ||
                                (clickedPort.parent == port.parent) ||
                                (clickedPort.IsInputPort()) ||
                                (port.isConnected && port is ValueInput) ||
                                (!TypeConverter.HasConvertion(clickedPort.type, port.type)))
                            {
                                canConnect = false;
                            }
                        }

                        port.pos        = new Vector2(rect.x - 5, rect.y + port.posOffsetY);
                        portRect.width  = port.isConnected? 12:10;
                        portRect.height = portRect.width;
                        portRect.center = port.pos;

                        //first gameobject or component port is considered to be the 'instance' port by convention
                        if (port == firstValuePort)
                        {
                            if (port.IsUnitySceneObject())
                            {
                                instancePort = port;
                            }
                        }

                        //Port graphic
                        if (clickedPort != null && !canConnect && clickedPort != port)
                        {
                            GUI.color = new Color(1, 1, 1, 0.3f);
                        }
                        GUI.Box(portRect, string.Empty, port.isConnected? CanvasStyles.nodePortConnected : CanvasStyles.nodePortEmpty);
                        GUI.color = Color.white;

                        //Tooltip
                        if (portRect.Contains(e.mousePosition))
                        {
                            var labelString = (canConnect || port.isConnected || port == clickedPort)? port.type.FriendlyName() : "Can't Connect Here";
                            var size        = CanvasStyles.box.CalcSize(new GUIContent(labelString));
                            var rect        = new Rect(0, 0, size.x + 10, size.y + 5);
                            rect.x = portRect.x - size.x - 10;
                            rect.y = portRect.y - size.y / 2;
                            GUI.Box(rect, labelString, CanvasStyles.box);

                            //Or value
                        }
                        else
                        {
                            if (port is ValueInput && !port.isConnected)
                            {
                                //Only these types are shown their value
                                if (port.type.IsValueType || port.type == typeof(Type) || port.type == typeof(string) || port.IsUnityObject())
                                {
                                    var    value       = (port as ValueInput).serializedValue;
                                    string labelString = null;
                                    if (!(port as ValueInput).isDefaultValue)
                                    {
                                        if (value is UnityEngine.Object && value as UnityEngine.Object != null)
                                        {
                                            labelString = string.Format("<b><color=#66ff33>{0}</color></b>", (value as UnityEngine.Object).name);
                                        }
                                        else
                                        {
                                            labelString = value.ToStringAdvanced();
                                        }
                                    }
                                    else if (port == instancePort)
                                    {
                                        var exists = true;
                                        if (graphAgent != null && typeof(Component).IsAssignableFrom(port.type))
                                        {
                                            exists = graphAgent.GetComponent(port.type) != null;
                                        }
                                        var color = exists? "66ff33" : "ff3300";
                                        labelString = string.Format("<color=#{0}><b>♟ <i>Self</i></b></color>", color);
                                    }
                                    else
                                    {
                                        GUI.color   = new Color(1, 1, 1, 0.15f);
                                        labelString = value.ToStringAdvanced();
                                    }
                                    var size = CanvasStyles.label.CalcSize(new GUIContent(labelString));
                                    var rect = new Rect(0, 0, size.x, size.y);
                                    rect.x = portRect.x - size.x - 5;
                                    rect.y = portRect.y - size.y * 0.3f;                                     //*0.3? something's wrong here. FIX
                                    GUI.Label(rect, labelString, CanvasStyles.label);
                                    GUI.color = Color.white;
                                }
                            }
                        }

                        if (GraphEditorUtility.allowClick)
                        {
                            //Right click removes connections
                            if (port.isConnected && e.type == EventType.ContextClick && portRect.Contains(e.mousePosition))
                            {
                                foreach (var c in GetInPortConnections(port))
                                {
                                    graph.RemoveConnection(c);
                                }
                                e.Use();
                                return;
                            }

                            //Click initialize new drag & drop connection
                            if (e.type == EventType.MouseDown && e.button == 0 && portRect.Contains(e.mousePosition))
                            {
                                if (port.CanAcceptConnections())
                                {
                                    dragDropMisses = 0;
                                    clickedPort    = port;
                                    e.Use();
                                }
                            }

                            //Drop on creates connection
                            if (e.type == EventType.MouseUp && e.button == 0 && clickedPort != null)
                            {
                                if (portRect.Contains(e.mousePosition) && port.CanAcceptConnections())
                                {
                                    BinderConnection.Create(clickedPort, port);
                                    clickedPort = null;
                                    e.Use();
                                }
                            }
                        }
                    }
                }

                //OUTPUT Ports
                if (orderedOutputs != null)
                {
                    for (var i = 0; i < orderedOutputs.Length; i++)
                    {
                        var port       = orderedOutputs[i];
                        var canConnect = true;
                        if (clickedPort != null)
                        {
                            if ((port == clickedPort) ||
                                (clickedPort.parent == port.parent) ||
                                (clickedPort.IsOutputPort()) ||
                                (port.isConnected && port is FlowOutput) ||
                                (!TypeConverter.HasConvertion(port.type, clickedPort.type)))
                            {
                                canConnect = false;
                            }
                        }

                        port.pos        = new Vector2(rect.xMax + 5, rect.y + port.posOffsetY);
                        portRect.width  = port.isConnected? 12:10;
                        portRect.height = portRect.width;
                        portRect.center = port.pos;

                        //Port graphic
                        if (clickedPort != null && !canConnect && clickedPort != port)
                        {
                            GUI.color = new Color(1, 1, 1, 0.3f);
                        }
                        GUI.Box(portRect, string.Empty, port.isConnected? CanvasStyles.nodePortConnected : CanvasStyles.nodePortEmpty);
                        GUI.color = Color.white;

                        //Tooltip
                        if (portRect.Contains(e.mousePosition))
                        {
                            var labelString = (canConnect || port.isConnected || port == clickedPort)? port.type.FriendlyName() : "Can't Connect Here";
                            var size        = CanvasStyles.box.CalcSize(new GUIContent(labelString));
                            var rect        = new Rect(0, 0, size.x + 10, size.y + 5);
                            rect.x = portRect.x + 15;
                            rect.y = portRect.y - portRect.height / 2;
                            GUI.Box(rect, labelString, CanvasStyles.box);
                        }

                        if (GraphEditorUtility.allowClick)
                        {
                            //Right click removes connections
                            if (e.type == EventType.ContextClick && portRect.Contains(e.mousePosition))
                            {
                                foreach (var c in GetOutPortConnections(port))
                                {
                                    graph.RemoveConnection(c);
                                }
                                e.Use();
                                return;
                            }

                            //Click initialize new drag & drop connection
                            if (e.type == EventType.MouseDown && e.button == 0 && portRect.Contains(e.mousePosition))
                            {
                                if (port.CanAcceptConnections())
                                {
                                    dragDropMisses = 0;
                                    clickedPort    = port;
                                    e.Use();
                                }
                            }

                            //Drop on creates connection
                            if (e.type == EventType.MouseUp && e.button == 0 && clickedPort != null)
                            {
                                if (portRect.Contains(e.mousePosition) && port.CanAcceptConnections())
                                {
                                    BinderConnection.Create(port, clickedPort);
                                    clickedPort = null;
                                    e.Use();
                                }
                            }
                        }
                    }
                }
            }

            ///ACCEPT CONNECTION
            if (clickedPort != null && e.type == EventType.MouseUp)
            {
                ///ON NODE
                if (rect.Contains(e.mousePosition))
                {
                    var cachePort = clickedPort;
                    var menu      = new GenericMenu();
                    if (cachePort is ValueOutput || cachePort is FlowOutput)
                    {
                        if (orderedInputs != null)
                        {
                            foreach (var _port in orderedInputs.Where(p => p.CanAcceptConnections() && TypeConverter.HasConvertion(cachePort.type, p.type)))
                            {
                                var port = _port;
                                menu.AddItem(new GUIContent(string.Format("To: '{0}'", port.name)), false, () => { BinderConnection.Create(cachePort, port); });
                            }
                        }
                    }
                    else
                    {
                        if (orderedOutputs != null)
                        {
                            foreach (var _port in orderedOutputs.Where(p => p.CanAcceptConnections() && TypeConverter.HasConvertion(p.type, cachePort.type)))
                            {
                                var port = _port;
                                menu.AddItem(new GUIContent(string.Format("From: '{0}'", port.name)), false, () => { BinderConnection.Create(port, cachePort); });
                            }
                        }
                    }

                    //append menu items
                    menu = OnDragAndDropPortContextMenu(menu, cachePort);

                    //if there is only 1 option, just do it
                    if (menu.GetItemCount() == 1)
                    {
                        EditorUtils.GetMenuItems(menu)[0].func();
                    }
                    else
                    {
                        GraphEditorUtility.PostGUI += () => { menu.ShowAsContext(); };
                    }

                    clickedPort = null;
                    e.Use();
                    ///

                    ///ON CANVAS
                }
                else
                {
                    dragDropMisses++;
                    if (dragDropMisses == graph.allNodes.Count && clickedPort != null)
                    {
                        var cachePort = clickedPort;
                        clickedPort = null;
                        DoContextPortConnectionMenu(cachePort, e.mousePosition, zoomFactor);
                        e.Use();
                    }
                }
            }

            //Temp connection line when linking
            if (clickedPort != null && clickedPort.parent == this)
            {
                var from  = clickedPort.pos;
                var to    = e.mousePosition;
                var xDiff = (from.x - to.x) * 0.8f;
                xDiff = to.x > from.x? xDiff : -xDiff;
                var tangA = clickedPort is FlowInput || clickedPort is ValueInput? new Vector2(xDiff, 0) : new Vector2(-xDiff, 0);
                var tangB = tangA * -1;
                Handles.DrawBezier(from, to, from + tangA, to + tangB, new Color(0.5f, 0.5f, 0.8f, 0.8f), null, 3);
            }

            //Actualy draw the existing connections
            for (var i = 0; i < outConnections.Count; i++)
            {
                var binder = outConnections[i] as BinderConnection;
                if (binder != null)                  //for in case it's MissingConnection
                {
                    var sourcePort = binder.sourcePort;
                    var targetPort = binder.targetPort;
                    if (sourcePort != null && targetPort != null)
                    {
                        if (fullDrawPass || drawCanvas.Overlaps(RectUtils.GetBoundRect(sourcePort.pos, targetPort.pos)))
                        {
                            binder.DrawConnectionGUI(sourcePort.pos, targetPort.pos);
                        }
                    }
                }
            }
        }
Пример #10
0
        ///Create a NEW binding connection object between two ports
        public static BinderConnection Create(Port source, Port target)
        {
            if (source == null || target == null)
            {
                Debug.LogError("Source Port or Target Port is null when making a new Binder Connection");
                return(null);
            }

            if (!source.CanAcceptConnections())
            {
                Debug.LogWarning("Source port can accept no more connections");
                return(null);
            }

            if (!target.CanAcceptConnections())
            {
                Debug.LogWarning("Target port can accept no more connections");
                return(null);
            }

            if (source.parent == target.parent)
            {
                Debug.LogWarning("Can't connect ports on the same parent node");
                return(null);
            }


            if (source is FlowOutput && !(target is FlowInput))
            {
                Debug.LogWarning("Flow ports can only be connected to other Flow ports");
                return(null);
            }

            if ((source is FlowInput && target is FlowInput) || (source is ValueInput && target is ValueInput))
            {
                Debug.LogWarning("Can't connect input to input");
                return(null);
            }

            if ((source is FlowOutput && target is FlowOutput) || (source is ValueOutput && target is ValueOutput))
            {
                Debug.LogWarning("Can't connect output to output");
                return(null);
            }

            if (!TypeConverter.HasConvertion(source.type, target.type))
            {
                Debug.LogWarning(string.Format("Can't connect ports. Type '{0}' is not assignable from Type '{1}' and there exists no internal convertion for those types.", target.type.FriendlyName(), source.type.FriendlyName()));
                return(null);
            }


                        #if UNITY_EDITOR
            UnityEditor.Undo.RecordObject(source.parent.graph, "Connect Ports");
                        #endif


            if (source is FlowOutput && target is FlowInput)
            {
                var flowBind = new BinderConnection();
                flowBind.OnCreate(source, target);
                return(flowBind);
            }

            if (source is ValueOutput && target is ValueInput)
            {
                var valueBind = (BinderConnection)System.Activator.CreateInstance(typeof(BinderConnection <>).RTMakeGenericType(new System.Type[] { target.type }));
                valueBind.OnCreate(source, target);
                return(valueBind);
            }

            return(null);
        }
 ///Return whether or not source can connect to target. The return is a string with the reason why NOT, null if possible.
 ///Providing an existing ref connection, will bypass source/target validation respectively if that connection is already connected to that source/target port.
 public static bool CanBeBoundVerbosed(Port source, Port target, BinderConnection refConnection, out string verbose)
 {
     verbose = CanBeBoundVerbosed_Internal(source, target, refConnection);
     return(verbose == null);
 }
        ///----------------------------------------------------------------------------------------------

        ///Return whether or not source can connect to target.
        public static bool CanBeBound(Port source, Port target, BinderConnection refConnection)
        {
            return(CanBeBoundVerbosed(source, target, refConnection, out string v));
        }