Node
Nodes carry the sockets, the title and the content widget of a graph element.
nodeeditor.node_node ¶
A module containing NodeEditor's class for representing Node.
Node ¶
Bases: QObject, Serializable
Class representing Node in the Scene.
title
property
writable
¶
Title shown in the scene
:getter: return current Node title
:setter: sets Node title and passes it to Graphics Node class
:type: str
setNodeLabel ¶
Set the floating single-line label above the node.
:param text: label text; empty string hides the label :param store_history: store undo history entry (skip during load/deserialize)
setNodeLabelVisible ¶
Show or hide the floating label of this Node.
The label stays hidden while it carries no text.
:param visible: True shows the label, False hides it
:type visible: bool
isNodeLabelVisible ¶
Is the floating label of this Node currently visible?
:return: True if the label is visible
:rtype: bool
setNodeLabelOffset ¶
Set the gap between the top of this Node and the bottom of its floating label.
:param offset: gap in pixels
:type offset: float
setPos ¶
Sets position of the Graphics Node
:param x: X Scene position
:param y: Y Scene position
getSocketShapeName ¶
Name of the shape used by a socket of socket_type on this node.
The side's own map is consulted first, then its '*' wildcard
entry, and the circle is the last resort. Types that are not mapped
keep the classic circle.
:param socket_type: the socket's type, as passed to initSockets
:param is_input: True for an input socket
:return: the registered shape name
:rtype: str
Example::
class MyNode(Node):
def initSettings(self):
super().initSettings()
self.input_socket_shapes = {1: 'chevron'}
self.output_socket_shapes = {'*': 'triangle'}
initSockets ¶
Create sockets for inputs and outputs
:param inputs: list of Socket Types (int)
:type inputs: list
:param outputs: list of Socket Types (int)
:type outputs: list
:param input_text: list of Socket Types (int)
:type input_text: list
:param output_text: list of Socket Types (int)
:type output_text: list
:param reset: if True destroys and removes old Sockets
:type reset: bool
onEdgeConnectionChanged ¶
Event handling that any connection (Edge) has changed. Currently not used...
:param new_edge: reference to the changed :class:~nodeeditor.node_edge.Edge
:type new_edge: :class:~nodeeditor.node_edge.Edge
onInputChanged ¶
Event handling when Node's input Edge has changed. We auto-mark this Node to be Dirty with all it's
descendants
:param socket: reference to the changed :class:~nodeeditor.node_socket.Socket
:type socket: :class:~nodeeditor.node_socket.Socket
onDeserialized ¶
Event manually called when this node was deserialized. Currently called when node is deserialized from scene
Passing data containing the data which have been deserialized
doSelect ¶
Shortcut method for selecting/deselecting the Node
:param new_state: True if you want to select the Node. False if you want to deselect the Node
:type new_state: bool
hasConnectedEdge ¶
Returns True if edge is connected to any :class:~nodeeditor.node_socket.Socket of this Node
getSocketPosition ¶
Get the relative x, y position of a :class:~nodeeditor.node_socket.Socket. This is used for placing
the Graphics Sockets on Graphics Node.
:param index: Order number of the Socket. (0, 1, 2, ...)
:type index: int
:param position: Socket Position Constant describing where the Socket is located. See :ref:socket-position-constants
:type position: int
:param num_out_of: Total number of Sockets on this Socket Position
:type num_out_of: int
:return: Position of described Socket on the Node
:rtype: x, y
getSocketScenePosition ¶
Get absolute Socket position in the Scene
:param socket: Socket which position we want to know
:return: (x, y) Socket's scene position
updateConnectedEdges ¶
Recalculate (Refresh) positions of all connected Edges. Used for updating Graphics Edges
isDirty ¶
Is this node marked as Dirty
:return: True if Node is marked as Dirty
:rtype: bool
markDirty ¶
Mark this Node as Dirty. See :ref:evaluation for more
:param new_value: True if this Node should be Dirty. False if you want to un-dirty this Node
:type new_value: bool
onMarkedDirty ¶
Called when this Node has been marked as Dirty. This method is supposed to be overridden
markChildrenDirty ¶
Mark all first level children of this Node to be Dirty. Not this Node it self. Not other descendants
:param new_value: True if children should be Dirty. False if you want to un-dirty children
:type new_value: bool
markDescendantsDirty ¶
Mark all children and descendants of this Node to be Dirty. Not this Node it self
The traversal is iterative and keeps a visited set, so a graph with a cycle terminates instead of exhausting the interpreter's recursion limit, and a node reachable through several paths is visited once rather than once per path.
:param new_value: True if children and descendants should be Dirty. False if you want to un-dirty children and descendants
:type new_value: bool
isInvalid ¶
Is this node marked as Invalid?
:return: True if Node is marked as Invalid
:rtype: bool
markInvalid ¶
Mark this Node as Invalid. See :ref:evaluation for more
:param new_value: True if this Node should be Invalid. False if you want to make this Node valid
:type new_value: bool
onMarkedInvalid ¶
Called when this Node has been marked as Invalid. This method is supposed to be overridden
markChildrenInvalid ¶
Mark all first level children of this Node to be Invalid. Not this Node it self. Not other descendants
:param new_value: True if children should be Invalid. False if you want to make children valid
:type new_value: bool
markDescendantsInvalid ¶
Mark all children and descendants of this Node to be Invalid. Not this Node it self
The traversal is iterative and keeps a visited set, so a graph with a cycle terminates instead of exhausting the interpreter's recursion limit, and a node reachable through several paths is visited once rather than once per path.
:param new_value: True if children and descendants should be Invalid. False if you want to make children and descendants valid
:type new_value: bool
eval ¶
Evaluate this Node. This is supposed to be overridden. See :ref:evaluation for more
getChildrenNodes ¶
Retreive all first-level children connected to this Node Outputs
:return: list of Nodes connected to this Node from all Outputs
:rtype: List[:class:~nodeeditor.node_node.Node]
getInput ¶
Get the first Node connected to the Input specified by index
:param index: Order number of the Input Socket
:type index: int
:return: :class:~nodeeditor.node_node.Node which is connected to the specified Input or None if
there is no connection or the index is out of range
:rtype: :class:~nodeeditor.node_node.Node or None
getInputWithSocket ¶
Get the first Node connected to the Input specified by index and the connection Socket
:param index: Order number of the Input Socket
:type index: int
:return: Tuple containing :class:~nodeeditor.node_node.Node and :class:~nodeeditor.node_socket.Socket which
is connected to the specified Input or None if there is no connection or the index is out of range
:rtype: (:class:~nodeeditor.node_node.Node, :class:~nodeeditor.node_socket.Socket)
getInputWithSocketIndex ¶
Get the first Node connected to the Input specified by index and the connection Socket
:param index: Order number of the Input Socket
:type index: int
:return: Tuple containing :class:~nodeeditor.node_node.Node and :class:~nodeeditor.node_socket.Socket which
is connected to the specified Input or None if there is no connection or the index is out of range
:rtype: (:class:~nodeeditor.node_node.Node, int)
getInputs ¶
Get all Nodes connected to the Input specified by index
:param index: Order number of the Input Socket
:type index: int
:return: all :class:~nodeeditor.node_node.Node instances which are connected to the
specified Input or [] if there is no connection or the index is out of range
:rtype: List[:class:~nodeeditor.node_node.Node]
getOutputs ¶
Get all Nodes connected to the Output specified by index
:param index: Order number of the Output Socket
:type index: int
:return: all :class:~nodeeditor.node_node.Node instances which are connected to the
specified Output or [] if there is no connection or the index is out of range
:rtype: List[:class:~nodeeditor.node_node.Node]
serialize ¶
Serialize this Node into an OrderedDict for storing in memory or on disk.
:return: data serialized in OrderedDict
:rtype: OrderedDict
deserialize ¶
Deserialize this Node from a dict of serialized data.
Sockets missing in the data are created, sockets already present are reused.
:param data: Dictionary containing serialized data
:type data: dict
:param hashmap: Helper dictionary containing references (by id == key) to existing objects
:type hashmap: dict
:param restore_id: True if we are creating new Sockets. False is useful when loading existing
Sockets of which we want to keep the existing object's id.
:type restore_id: bool
:return: True if deserialization was successful, otherwise False
:rtype: bool
nodeeditor.node_multi_input_node ¶
A module containing the MultiInputNode class: a :class:~nodeeditor.node_node.Node
whose input :class:~nodeeditor.node_socket.Socket accepts any number of
:class:~nodeeditor.node_edge.Edge (s) and reads them in an explicit,
persisted order.
MultiInputNode ¶
Bases: Node
Base class for nodes reading an arbitrary number of inputs in order.
Subclass it, declare the sockets you need and read them with
:meth:getOrderedSources / :meth:getOrderedValues::
class Sum(MultiInputNode, CalcNode):
def evalImplementation(self):
return [sum(self.getOrderedValues())]
By default every input socket accepts multiple Edges
(:attr:multi_input_all_inputs). Set :attr:multi_input_socket and
:attr:multi_input_all_inputs = False to make only one socket do so.
The order is, by default, the order the Edges were connected in. It can
be changed at any time from code (:meth:setEdgeOrder, :meth:moveEdgeTo,
:meth:swapEdges) and is saved to / loaded from the graph file.
This class deliberately does not define __init__, so it can be mixed
into an existing node hierarchy without changing its constructor chain.
:Instance Attributes:
- **multi_input_socket** - index of the input `Socket` which accepts
many `Edges` when :attr:`multi_input_all_inputs` is ``False``
- **multi_input_all_inputs** - ``True`` to let every input `Socket`
accept multiple `Edges`
initSockets ¶
Create sockets for inputs and outputs, keeping only
:attr:multi_input_socket multi-edged if :attr:multi_input_all_inputs
is False
getMultiSocket ¶
Get the input :class:~nodeeditor.node_socket.Socket which accepts many Edges.
:param index: index of the input Socket or None to use
:attr:multi_input_socket
:type index: int or None
:return: the ordered input Socket or None if the node has no such socket
:rtype: :class:~nodeeditor.node_socket.Socket or None
compactEdgeOrder ¶
Renumber the input Edges to a gap free 0..n-1 sequence.
Called automatically on every connection change, so it is only needed
after assigning :attr:~nodeeditor.node_edge.Edge.input_index directly.
:param index: index of the input Socket or None to use
:attr:multi_input_socket
:type index: int or None
:return: True if anything actually changed
:rtype: bool
getOrderedEdges ¶
Get the connected Edges of the ordered input Socket in read order.
:param index: index of the input Socket or None to use
:attr:multi_input_socket
:type index: int or None
:return: Edges ordered by :attr:~nodeeditor.node_edge.Edge.input_index
:rtype: List[:class:~nodeeditor.node_edge.Edge]
getOrderedSources ¶
Get the (node, socket) pairs feeding the ordered input Socket.
One entry per connected Edge, in read order, so a source connected
twice appears twice.
:param index: index of the input Socket or None to use
:attr:multi_input_socket
:type index: int or None
:return: source Node and its Socket per read position
:rtype: List[Tuple[:class:~nodeeditor.node_node.Node, :class:~nodeeditor.node_socket.Socket]]
getOrderedValues ¶
Evaluate every source of the ordered input Socket in read order.
The returned list always has one entry per connected Edge; a source
which fails to evaluate contributes None instead of raising, so
len(getOrderedValues()) always equals the number of connections.
:param index: index of the input Socket or None to use
:attr:multi_input_socket
:type index: int or None
:return: evaluated value per read position
:rtype: list
getOrderedNodes ¶
Get the source :class:~nodeeditor.node_node.Node (s) of the ordered
input Socket in read order.
:param index: index of the input Socket or None to use
:attr:multi_input_socket
:type index: int or None
:return: source Nodes, one per read position
:rtype: List[:class:~nodeeditor.node_node.Node]
describeInputOrder ¶
Human readable one-line-per-position description of the input order.
Handy for tooltips and for logging what the node currently sees::
0: Input
1: Add
:param index: index of the input Socket or None to use
:attr:multi_input_socket
:type index: int or None
:return: description of the current read order
:rtype: str
orderLabel
staticmethod
¶
Display label for read position position (0-based).
:param position: 0-based read position
:type position: int
:return: "#1" for position 0, "#2" for position 1, and so on
:rtype: str
updateInputOrderLabels ¶
Write :meth:orderLabel onto every Edge of the ordered input
Socket. No-op when :attr:show_input_order_labels is False.
Called automatically after every connection change and reorder, so
you only need it when toggling :attr:show_input_order_labels on
for a node that already has connections.
:param index: index of the input Socket or None to use
:attr:multi_input_socket
:type index: int or None
setEdgeOrder ¶
Set the read order of the connected Edges of the ordered input Socket.
edges may be a partial list; edges missing from it are appended
afterwards keeping their relative order.
:param edges: Edges of this node's ordered input Socket, first read
position first
:type edges: List[:class:~nodeeditor.node_edge.Edge]
:param index: index of the input Socket or None to use
:attr:multi_input_socket
:type index: int or None
:return: True if the order changed
:rtype: bool
setEdgeOrderByNodes ¶
Set the read order from a list of source :class:~nodeeditor.node_node.Node (s).
Each node moves to the first read position that is not already taken by an earlier entry, so listing the same node twice moves it to position 0 and pushes the rest down.
:param nodes: source Nodes, first read position first
:type nodes: List[:class:~nodeeditor.node_node.Node]
:param index: index of the input Socket or None to use
:attr:multi_input_socket
:type index: int or None
:return: True if the order changed
:rtype: bool
moveEdgeTo ¶
Move a connected Edge to read position position.
:param edge: :class:~nodeeditor.node_edge.Edge connected to this node
:type edge: :class:~nodeeditor.node_edge.Edge
:param position: target read position
:type position: int
:param index: index of the input Socket or None to use
:attr:multi_input_socket
:type index: int or None
:return: True if the order changed
:rtype: bool
moveEdgeBy ¶
Shift a connected Edge by offset read positions.
Clamped at both ends, so offset=-1 on the first input is a no-op.
:param edge: :class:~nodeeditor.node_edge.Edge connected to this node
:type edge: :class:~nodeeditor.node_edge.Edge
:param offset: how many positions to move, negative moves earlier
:type offset: int
:param index: index of the input Socket or None to use
:attr:multi_input_socket
:type index: int or None
:return: True if the order changed
:rtype: bool
swapEdges ¶
Swap the read positions of two Edges connected to this node.
:param edge_a: first :class:~nodeeditor.node_edge.Edge to swap
:type edge_a: :class:~nodeeditor.node_edge.Edge
:param edge_b: second :class:~nodeeditor.node_edge.Edge to swap
:type edge_b: :class:~nodeeditor.node_edge.Edge
:param index: index of the input Socket or None to use
:attr:multi_input_socket
:type index: int or None
:return: True if the order changed
:rtype: bool
reverseEdgeOrder ¶
Reverse the read order of the connected Edges.
:param index: index of the input Socket or None to use
:attr:multi_input_socket
:type index: int or None
:return: True if the order changed
:rtype: bool
onEdgeConnectionChanged ¶
Keep the read order gap free after any connection change.
This is the single hook every connection path already goes through
(EdgeDragging, EdgeRerouting, Edge.remove), so
:attr:~nodeeditor.node_edge.Edge.input_index stays a contiguous
0..n-1 sequence and the #N labels (see
:attr:show_input_order_labels) stay in sync. An Edge that just
detached from our ordered socket gets its managed #N label
cleared. onInputChanged is intentionally not overridden
so existing subclass chains keep working.