Example #1
0
        public static PortView Create(
            Port port,
            Type type,
            IEdgeConnectorListener connectorListener
            )
        {
            if (type == null)
            {
                Debug.Log($"Port {port.name} has null type");
            }
            var view = new PortView(
                Orientation.Horizontal,
                port.isInput ? Direction.Input : Direction.Output,
                port.acceptsMultipleConnections ? Capacity.Multi : Capacity.Single,
                type
                )
            {
                m_EdgeConnector = new EdgeConnector <Edge>(connectorListener),
                portName        = port.name,
                target          = port
            };

            // Override default connector text with the human-readable port name
            // TODO: Apparently the edge connector (Edge.output.portName) is based on whatever
            // is in this label. So re-labeling it will inadvertedly change the port name.
            // (or it might be a two way binding). So natively, we won't be able to have multiple
            // ports with the same name.
            // view.m_ConnectorText.text = refPort.displayName;

            view.AddManipulator(view.m_EdgeConnector);
            return(view);
        }
Example #2
0
        protected virtual void AddInputPort(Port port)
        {
            var view = PortView.Create(port, port.type, m_ConnectorListener);

            // If we want to display an inline editable field as part
            // of the port, create a new PropertyField and bind it.
            if (port.fieldName != null)
            {
                var prop = m_SerializedNode.FindPropertyRelative(port.fieldName);
                if (prop != null)
                {
                    var field = new PropertyField(prop, " ");
                    field.Bind(m_SerializedNode.serializedObject);
                    field.RegisterCallback((FocusOutEvent e) => OnPropertyChange());

                    var container = new VisualElement();
                    container.AddToClassList("property-field-container");
                    container.Add(field);

                    view.SetEditorField(container);
                }
            }

            inputs.Add(view);
            inputContainer.Add(view);
        }
Example #3
0
        protected virtual void AddOutputPort(Port port)
        {
            var view = PortView.Create(port, ConnectorListener);

            Outputs.Add(view);
            outputContainer.Add(view);
        }
Example #4
0
        /// <summary>
        /// Create a new node from reflection data and insert into the Graph.
        /// </summary>
        internal void AddNodeFromSearch(Node node, Vector2 screenPosition, PortView connectedPort = null, bool registerUndo = true)
        {
            // Calculate where to place this node on the graph
            var windowRoot          = EditorWindow.rootVisualElement;
            var windowMousePosition = EditorWindow.rootVisualElement.ChangeCoordinatesTo(
                windowRoot.parent,
                screenPosition - EditorWindow.position.position
                );

            var graphMousePosition = contentViewContainer.WorldToLocal(windowMousePosition);

            // Track undo and add to the graph
            if (registerUndo)
            {
                Undo.RegisterCompleteObjectUndo(Graph, $"Add Node {node.Name}");
            }

            node.Position = graphMousePosition;

            Graph.AddNode(node);
            serializedGraph.Update();
            EditorUtility.SetDirty(Graph);

            // Add a node to the visual graph
            var editorType = NodeReflection.GetNodeEditorType(node.GetType());
            var element    = Activator.CreateInstance(editorType) as NodeView;

            element.Initialize(node, this, edgeConnectorListener);

            AddElement(element);

            // If there was a provided existing port to connect to, find the best
            // candidate port on the new node and connect.
            if (connectedPort != null)
            {
                var edge = new GraphViewEdge();

                if (connectedPort.direction == Direction.Input)
                {
                    edge.input  = connectedPort;
                    edge.output = element.GetCompatibleOutputPort(connectedPort);
                }
                else
                {
                    edge.output = connectedPort;
                    edge.input  = element.GetCompatibleInputPort(connectedPort);
                }

                AddEdge(edge, false);
            }

            Dirty(element);
        }
Example #5
0
        /// <summary>
        /// Return true if this port can be connected with an edge to the given port
        /// </summary>
        public bool IsCompatibleWith(PortView other)
        {
            if (other.node == node || other.direction == direction)
            {
                return(false);
            }

            // TODO: Loop detection to ensure nobody is making a cycle
            // (for certain use cases, that is)

            // Check for type cast support in the direction of output port -> input port
            return((other.direction == Direction.Input && portType.IsCastableTo(other.portType, true)) ||
                   (other.direction == Direction.Output && other.portType.IsCastableTo(portType, true)));
        }
        public static PortView Create(Port port, IEdgeConnectorListener connectorListener)
        {
            Direction direction = port.Direction == PortDirection.Input ? Direction.Input : Direction.Output;
            Capacity  capacity  = port.Capacity == PortCapacity.Multiple ? Capacity.Multi : Capacity.Single;

            var view = new PortView(Orientation.Horizontal, direction, capacity, port.Type)
            {
                m_EdgeConnector = new EdgeConnector <Edge>(connectorListener),
                portName        = port.Name,
                Target          = port
            };

            view.AddManipulator(view.m_EdgeConnector);
            return(view);
        }
Example #7
0
        protected virtual void AddInputPort(Port port)
        {
            var view = PortView.Create(port, ConnectorListener);

            // If we're exposing a control element via reflection: include it in the view
            var reflection = NodeReflection.GetNodeType(Target.GetType());
            var element    = reflection.GetPortByName(port.Name)?.GetControlElement(this);

            if (element != null)
            {
                var container = new VisualElement();
                container.AddToClassList("property-field-container");
                container.Add(element);

                view.SetEditorField(container);
            }

            Inputs.Add(view);
            inputContainer.Add(view);
        }
Example #8
0
 public PortView GetCompatibleOutputPort(PortView input)
 {
     return(Outputs.Find((port) => port.IsCompatibleWith(input)));
 }
Example #9
0
 public PortView GetCompatibleInputPort(PortView output)
 {
     return(Inputs.Find((port) => port.IsCompatibleWith(output)));
 }
Example #10
0
 public void OpenSearch(Vector2 screenPosition, PortView connectedPort = null)
 {
     searchWindow.SourcePort = connectedPort;
     GraphViewSearchWindow.Open(new SearchWindowContext(screenPosition), searchWindow);
 }
Example #11
0
 public void OpenSearch(Vector2 screenPosition, PortView connectedPort = null)
 {
     m_SearchProvider.sourcePort = connectedPort;
     SearchWindow.Open(new SearchWindowContext(screenPosition), m_SearchProvider);
 }
Example #12
0
        /// <summary>
        /// Create a new node from reflection data and insert into the Graph.
        /// </summary>
        internal void AddNodeFromReflectionData(
            NodeReflectionData data,
            Vector2 screenPosition,
            PortView connectedPort = null
            )
        {
            // Calculate where to place this node on the graph
            var windowRoot          = m_EditorWindow.rootVisualElement;
            var windowMousePosition = m_EditorWindow.rootVisualElement.ChangeCoordinatesTo(
                windowRoot.parent,
                screenPosition - m_EditorWindow.position.position
                );

            var graphMousePosition = contentViewContainer.WorldToLocal(windowMousePosition);

            // Create a new node instance and set initial data (ports, etc)
            Undo.RegisterCompleteObjectUndo(m_Graph, $"Add Node {data.name}");

            Debug.Log($"+node {data.name}");

            var node = data.CreateInstance();

            node.graphPosition = graphMousePosition;

            m_Graph.AddNode(node);
            m_SerializedGraph.Update();
            EditorUtility.SetDirty(m_Graph);

            var serializedNodesArr = m_SerializedGraph.FindProperty("nodes");

            var nodeIdx        = m_Graph.nodes.IndexOf(node);
            var serializedNode = serializedNodesArr.GetArrayElementAtIndex(nodeIdx);

            // Add a node to the visual graph
            var editorType = NodeReflection.GetNodeEditorType(data.type);
            var element    = Activator.CreateInstance(editorType) as NodeView;

            element.Initialize(node, serializedNode, m_EdgeListener);

            AddElement(element);

            // If there was a provided existing port to connect to, find the best
            // candidate port on the new node and connect.
            if (connectedPort != null)
            {
                var edge = new Edge();

                if (connectedPort.direction == Direction.Input)
                {
                    edge.input  = connectedPort;
                    edge.output = element.GetCompatibleOutputPort(connectedPort);
                }
                else
                {
                    edge.output = connectedPort;
                    edge.input  = element.GetCompatibleInputPort(connectedPort);
                }

                AddEdge(edge, false);
            }

            Dirty(element);
        }
Example #13
0
        private VisualElement AddItem(string property_path, int index)
        {
            var port_name = $"{this.list_name}[{index}]";
            var port      = parent_node.GetPort(port_name);
            var prop      = m_SerializedList.GetArrayElementAtIndex(index);

            if (port == null)
            {
                Debug.Log("Added port!");
                port = new Port {
                    name    = port_name,
                    isInput = false,
                    acceptsMultipleConnections = false,
                    type      = list_type,
                    fieldName = prop.propertyPath
                };
                parent_node.AddPort(port);
                m_SerializedList.serializedObject.Update();
            }
            var view = PortView.Create(port, port.type, m_ConnectorListener);

            view.hideEditorFieldOnConnection = false;

            var field = new PropertyField(prop, "");

            field.Bind(m_SerializedList.serializedObject);
            field.RegisterCallback((FocusOutEvent e) => m_OnPropertyChange());

            var container = new VisualElement();

            container.AddToClassList("property-field-container");
            container.style.flexDirection = FlexDirection.Row;
            var remove_button = new Button(() => {
                m_UpdateBinding();
                m_SerializedList.DeleteArrayElementAtIndex(index);
                m_SerializedList.serializedObject.ApplyModifiedProperties();
                m_UpdateBinding();
                int new_size    = m_SerializedList.arraySize;
                var canvas      = GetFirstAncestorOfType <CanvasView>();
                var connections = new List <Edge>(items[index].connections);
                foreach (var connection in connections)
                {
                    canvas.RemoveEdge(connection, false);
                }
                for (int i = index; i < new_size; i++)
                {
                    connections = new List <Edge>(items[i + 1].connections);
                    foreach (Edge connection in connections)
                    {
                        var connect_to = connection.input;
                        canvas.RemoveEdge(connection, false);
                        if (connect_to != null)
                        {
                            canvas.AddEdge(new Edge {
                                input  = connect_to,
                                output = items[i]
                            }, false);
                        }
                    }
                }
                canvas.DirtyAll();
                // Remove the last port from the list!
                parent_node.RemovePort(parent_node.GetPort($"{list_name}[{new_size}]"));
                m_SerializedList.serializedObject.Update();
                m_UpdateBinding();
                m_OnPropertyChange();
            });

            remove_button.text                          = "-";
            remove_button.style.color                   = new StyleColor(UnityEngine.Color.white);
            remove_button.style.backgroundColor         = new StyleColor(UnityEngine.Color.red);
            remove_button.style.marginBottom            = new StyleLength(0.0);
            remove_button.style.marginLeft              = new StyleLength(0.0);
            remove_button.style.marginTop               = new StyleLength(0.0);
            remove_button.style.marginRight             = new StyleLength(0.0);
            remove_button.style.borderBottomLeftRadius  = new StyleLength(0.0);
            remove_button.style.borderTopLeftRadius     = new StyleLength(0.0);
            remove_button.style.borderTopRightRadius    = new StyleLength(0.0);
            remove_button.style.borderBottomRightRadius = new StyleLength(0.0);
            container.Add(remove_button);
            container.Add(field);
            field.style.flexGrow = new StyleFloat(1.0f);

            view.SetEditorField(container);

            this.items.Add(view);
            Add(view);
            m_OnPropertyChange();
            return(view);
        }