Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 20 additions & 4 deletions NodeGraphQt/base/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,7 @@ def close(self):

def viewer(self):
"""
Returns the view interface used by the node graph.
Returns the internal view interface used by the node graph.

Warnings:
Methods in the ``NodeViewer`` are used internally
Expand Down Expand Up @@ -572,8 +572,17 @@ def set_grid_mode(self, mode=VIEWER_GRID_LINES):
"""
Set node graph grid mode.

Note:
By default grid mode is set to "VIEWER_GRID_LINES".

Node graph background types:

* :attr:`NodeGraphQt.constants.VIEWER_GRID_NONE`
* :attr:`NodeGraphQt.constants.VIEWER_GRID_DOTS`
* :attr:`NodeGraphQt.constants.VIEWER_GRID_LINES`

Args:
mode: VIEWER_GRID_LINES/VIEWER_GRID_DOTS/VIEWER_GRID_NONE.
mode (int): background styles.
"""
self.scene().grid_mode = mode
self._viewer.force_update()
Expand Down Expand Up @@ -734,8 +743,11 @@ def set_pipe_style(self, style=PIPE_LAYOUT_CURVED):
"""
Set node graph pipes to be drawn as straight, curved or angled.

.. image:: _images/pipe_layout_types.gif
:width: 80%

Note:
By default all pipes are set curved.
By default pipe layout is set to "PIPE_LAYOUT_CURVED".

Pipe Layout Styles:

Expand Down Expand Up @@ -1239,6 +1251,7 @@ def _deserialize(self, data, relative_pos=False, pos=None, set_parent=True):
Args:
data (dict): node data.
relative_pos (bool): position node relative to the cursor.
pos (tuple or list): custom x, y position.
set_parent (bool): set node parent to current node space.

Returns:
Expand Down Expand Up @@ -1280,7 +1293,10 @@ def _deserialize(self, data, relative_pos=False, pos=None, set_parent=True):
self.add_node(node, n_data.get('pos'), unique_name=set_parent)

if n_data.get('dynamic_port', None):
node.set_ports({'input_ports': n_data['input_ports'], 'output_ports': n_data['output_ports']})
node.set_ports({
'input_ports': n_data['input_ports'],
'output_ports': n_data['output_ports']
})

# build the connections.
for connection in data.get('connections', []):
Expand Down
3 changes: 3 additions & 0 deletions NodeGraphQt/base/port.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@ def connect_to(self, port=None):
if not port:
return

if self in port.connected_ports():
return

graph = self.node().graph
viewer = graph.viewer()

Expand Down
3 changes: 3 additions & 0 deletions NodeGraphQt/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,11 @@

# === NODE VIEWER ===

#: Style to render the node graph background with nothing.
VIEWER_GRID_NONE = 0
#: Style to render the node graph background with dots.
VIEWER_GRID_DOTS = 1
#: Style to render the node graph background with grid lines.
VIEWER_GRID_LINES = 2

VIEWER_BG_COLOR = (35, 35, 35)
Expand Down
3 changes: 2 additions & 1 deletion NodeGraphQt/widgets/node_publish_widget.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import os

from .properties import PropFileSavePath
from .. import QtWidgets
import os


class _element_widget(QtWidgets.QWidget):
Expand Down
37 changes: 36 additions & 1 deletion NodeGraphQt/widgets/viewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class NodeViewer(QtWidgets.QGraphicsView):
"""
The widget interface used for displaying the scene and nodes.
functions in this class are called by the
functions in this class should mainly be called by the
class:`NodeGraphQt.NodeGraph` class.
"""

Expand Down Expand Up @@ -665,6 +665,13 @@ def apply_live_connection(self, event):
self.end_live_connection()
return

# end connection if starting port is already connected.
if self._start_port.multi_connection and \
self._start_port in end_port.connected_ports:
self._detached_port = None
self.end_live_connection()
return

# register as disconnected if not acyclic.
if self.acyclic and not self.acyclic_check(self._start_port, end_port):
if self._detached_port:
Expand Down Expand Up @@ -814,6 +821,16 @@ def message_dialog(text, title='Node Graph'):
BaseDialog.message_dialog(text, title)

def load_dialog(self, current_dir=None, ext=None):
"""
Prompt node viewer file load dialog widget.
Args:
current_dir (str): directory path starting point. (optional)
ext (str): custom file extension filter type. (optional)
Returns:
str: selected file path.
"""
ext = '*{} '.format(ext) if ext else ''
ext_filter = ';;'.join([
'Node Graph ({}*json)'.format(ext), 'All Files (*)'
Expand All @@ -824,6 +841,16 @@ def load_dialog(self, current_dir=None, ext=None):
return file

def save_dialog(self, current_dir=None, ext=None):
"""
Prompt node viewer file save dialog widget.
Args:
current_dir (str): directory path starting point. (optional)
ext (str): custom file extension filter type. (optional)
Returns:
str: selected file path.
"""
ext_label = '*{} '.format(ext) if ext else ''
ext_type = '.{}'.format(ext) if ext else '.json'
ext_map = {'Node Graph ({}*json)'.format(ext_label): ext_type,
Expand Down Expand Up @@ -924,6 +951,14 @@ def remove_node(node):
node.delete()

def move_nodes(self, nodes, pos=None, offset=None):
"""
Globally move specified nodes.
Args:
nodes (list[AbstractNodeItem]): node items.
pos (tuple or list): custom x, y position.
offset (tuple or list): x, y position offset.
"""
group = self.scene().createItemGroup(nodes)
group_rect = group.boundingRect()
if pos:
Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,11 @@ applications that supports PySide2.
<img src="/docs/_images/prop_bin.png" width="600" title="Properties Bin">

#### Vertical Layout
<img src="/docs/_images/vertical_layout.png" width="600" title="Vertical Layout">
<img src="/docs/_images/vertical_layout.png" width="400" title="Vertical Layout">

#### Pipe Layout

<img src="/docs/_images/pipe_layout_types.gif" width="600" title="Pipe Layout">

#### Example

Expand Down
Binary file modified docs/_images/menu_hotkeys.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/_images/pipe_layout_menu.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/_images/pipe_layout_types.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'NodeGraphQT.tex', 'NodeGraphQt Documentation',
'Johnny Chan', 'manual'),
author, 'manual'),
]


Expand Down
2 changes: 2 additions & 0 deletions docs/examples/ex_node.rst
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ To you update the widget you can call the :meth:`NodeGraphQt.NodeObject.set_prop
- ``QCheckBox``: :meth:`NodeGraphQt.BaseNode.add_checkbox`
- ``QLineEdit``: :meth:`NodeGraphQt.BaseNode.add_text_input`

See: :ref:`Node Widgets` for more node widget types.


Connecting Nodes
****************
Expand Down
35 changes: 35 additions & 0 deletions docs/examples/ex_pipe.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
Pipe Examples
#############

Example Pipe Layouts
********************

.. image:: ../_images/pipe_layout_types.gif
:width: 650px

The :class:`NodeGraphQt.NodeGraph` class has 3 different pipe layout styles as
shown above this can be set easily with the :meth:`NodeGraphQt.NodeGraph.set_pipe_style`
function.

Here's a super simple example snippet for setting the pipe layout style to be angled.

.. code-block:: python
:linenos:

from NodeGraphQt import NodeGraph
from NodeGraphQt.constants import PIPE_LAYOUT_ANGLE

graph = NodeGraph()
graph.set_pipe_style(PIPE_LAYOUT_ANGLE)

Constants variables for the 3 different pipe layout styles:

- ``Curved``: :attr:`NodeGraphQt.constants.PIPE_LAYOUT_CURVED`
- ``Straight``: :attr:`NodeGraphQt.constants.PIPE_LAYOUT_STRAIGHT`
- ``Angle``: :attr:`NodeGraphQt.constants.PIPE_LAYOUT_ANGLE`

Note: if you've set up your node graph with the ``NodeGraphQt.setup_context_menu``
is a convenience function then you'll already have the actions to set the pipe
layout under "Edit>Pipe".

.. image:: ../_images/pipe_layout_menu.png
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@ GitHub Project: https://github.com/jchanvfx/NodeGraphQt
examples/ex_overview
examples/ex_node
examples/ex_port
examples/ex_pipe
examples/ex_menu
25 changes: 23 additions & 2 deletions docs/node_widgets.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ NodeBaseWidget
:members:
:exclude-members: node, setToolTip, type_, value, widget

NodeCheckBox
************

.. autoclass:: NodeGraphQt.widgets.node_widgets.NodeCheckBox
:members:
:exclude-members: widget, type_

NodeComboBox
************

Expand All @@ -25,9 +32,23 @@ NodeLineEdit
:members:
:exclude-members: widget, type_

NodeCheckBox
NodeFilePath
************

.. autoclass:: NodeGraphQt.widgets.node_widgets.NodeCheckBox
.. autoclass:: NodeGraphQt.widgets.node_widgets.NodeFilePath
:members:
:exclude-members: widget, type_

NodeFloatEdit
*************

.. autoclass:: NodeGraphQt.widgets.node_widgets.NodeFloatEdit
:members:
:exclude-members: widget, type_

NodeIntEdit
***********

.. autoclass:: NodeGraphQt.widgets.node_widgets.NodeIntEdit
:members:
:exclude-members: widget, type_