diff --git a/Nodes/__pycache__/array_node.cpython-312.pyc b/Nodes/__pycache__/array_node.cpython-312.pyc index 62dd897..aaf81b7 100644 Binary files a/Nodes/__pycache__/array_node.cpython-312.pyc and b/Nodes/__pycache__/array_node.cpython-312.pyc differ diff --git a/Nodes/__pycache__/backdrop_node.cpython-312.pyc b/Nodes/__pycache__/backdrop_node.cpython-312.pyc deleted file mode 100644 index c344722..0000000 Binary files a/Nodes/__pycache__/backdrop_node.cpython-312.pyc and /dev/null differ diff --git a/Nodes/__pycache__/base_circle_node.cpython-312.pyc b/Nodes/__pycache__/base_circle_node.cpython-312.pyc deleted file mode 100644 index 571e8f6..0000000 Binary files a/Nodes/__pycache__/base_circle_node.cpython-312.pyc and /dev/null differ diff --git a/Nodes/__pycache__/base_node.cpython-312.pyc b/Nodes/__pycache__/base_node.cpython-312.pyc deleted file mode 100644 index 739b435..0000000 Binary files a/Nodes/__pycache__/base_node.cpython-312.pyc and /dev/null differ diff --git a/Nodes/__pycache__/character_status_node.cpython-312.pyc b/Nodes/__pycache__/character_status_node.cpython-312.pyc index 4ed2a54..02e454c 100644 Binary files a/Nodes/__pycache__/character_status_node.cpython-312.pyc and b/Nodes/__pycache__/character_status_node.cpython-312.pyc differ diff --git a/Nodes/__pycache__/data_node.cpython-312.pyc b/Nodes/__pycache__/data_node.cpython-312.pyc index 7536ed3..be9ba52 100644 Binary files a/Nodes/__pycache__/data_node.cpython-312.pyc and b/Nodes/__pycache__/data_node.cpython-312.pyc differ diff --git a/Nodes/__pycache__/group_node.cpython-312.pyc b/Nodes/__pycache__/group_node.cpython-312.pyc deleted file mode 100644 index 9381b3b..0000000 Binary files a/Nodes/__pycache__/group_node.cpython-312.pyc and /dev/null differ diff --git a/Nodes/__pycache__/math_operation_node.cpython-312.pyc b/Nodes/__pycache__/math_operation_node.cpython-312.pyc index 5a68825..75e12f5 100644 Binary files a/Nodes/__pycache__/math_operation_node.cpython-312.pyc and b/Nodes/__pycache__/math_operation_node.cpython-312.pyc differ diff --git a/Nodes/__pycache__/port_node.cpython-312.pyc b/Nodes/__pycache__/port_node.cpython-312.pyc deleted file mode 100644 index 0539463..0000000 Binary files a/Nodes/__pycache__/port_node.cpython-312.pyc and /dev/null differ diff --git a/Nodes/array_node.py b/Nodes/array_node.py index 9403b51..5a4a26a 100644 --- a/Nodes/array_node.py +++ b/Nodes/array_node.py @@ -1,4 +1,4 @@ -from NodeGraphQt import BaseNode +from OdenGraphQt import BaseNode class ArrayNode(BaseNode): """ @@ -11,8 +11,6 @@ class ArrayNode(BaseNode): __identifier__ = 'bunny-lab.io.array_node' NODE_NAME = 'Array' - - def __init__(self): super(ArrayNode, self).__init__() self.values = {} # Ensure values is a dictionary. diff --git a/Nodes/backdrop_node.py b/Nodes/backdrop_node.py deleted file mode 100644 index 88968cb..0000000 --- a/Nodes/backdrop_node.py +++ /dev/null @@ -1,184 +0,0 @@ -#!/usr/bin/env python3 -""" -Enhanced Backdrop Node (Inherited from BaseNode) - -Features: - - Inherits from `BaseNode` so it can be discovered in your node scanning. - - Custom context menu to rename (set title) or pick a new color. - - Forces geometry updates to reduce "ghosting" or partial redraws. -""" - -from Qt import QtWidgets, QtGui -from NodeGraphQt import BaseNode -from NodeGraphQt.constants import NodePropWidgetEnum -from NodeGraphQt.qgraphics.node_backdrop import BackdropNodeItem - - -class BackdropNode(BaseNode): - """ - Backdrop Node: - - Allows grouping or annotating other nodes by resizing a large rectangle. - - Provides a custom context menu for renaming and recoloring (via on_context_menu). - """ - - __identifier__ = 'bunny-lab.io.backdrop' - NODE_NAME = 'Backdrop' - - def __init__(self): - # Use BackdropNodeItem for the specialized QGraphicsItem. - super(BackdropNode, self).__init__(qgraphics_item=BackdropNodeItem) - - # Default color (teal). - self.model.color = (5, 129, 138, 255) - - # Multi-line text property for storing the backdrop text. - self.create_property( - 'backdrop_text', - '', - widget_type=NodePropWidgetEnum.QTEXT_EDIT.value, - tab='Backdrop' - ) - - # -------------------------------------------------------------------------- - # Resizing / Geometry - # -------------------------------------------------------------------------- - def on_backdrop_updated(self, update_prop, value=None): - """ - Triggered when the user resizes or double-clicks the backdrop sizer handle. - """ - if not self.graph: - return - - if update_prop == 'sizer_mouse_release': - # User finished dragging the resize handle - self.view.prepareGeometryChange() - self.graph.begin_undo(f'resized "{self.name()}"') - self.set_property('width', value['width']) - self.set_property('height', value['height']) - self.set_pos(*value['pos']) - self.graph.end_undo() - self.view.update() - - elif update_prop == 'sizer_double_clicked': - # User double-clicked the resize handle (auto-resize) - self.view.prepareGeometryChange() - self.graph.begin_undo(f'"{self.name()}" auto resize') - self.set_property('width', value['width']) - self.set_property('height', value['height']) - self.set_pos(*value['pos']) - self.graph.end_undo() - self.view.update() - - def auto_size(self): - """ - Auto-resize the backdrop to fit around intersecting nodes. - """ - if not self.graph: - return - self.view.prepareGeometryChange() - self.graph.begin_undo(f'"{self.name()}" auto resize') - size = self.view.calc_backdrop_size() - self.set_property('width', size['width']) - self.set_property('height', size['height']) - self.set_pos(*size['pos']) - self.graph.end_undo() - self.view.update() - - def wrap_nodes(self, nodes): - """ - Fit the backdrop around the specified nodes. - """ - if not self.graph or not nodes: - return - self.view.prepareGeometryChange() - self.graph.begin_undo(f'"{self.name()}" wrap nodes') - size = self.view.calc_backdrop_size([n.view for n in nodes]) - self.set_property('width', size['width']) - self.set_property('height', size['height']) - self.set_pos(*size['pos']) - self.graph.end_undo() - self.view.update() - - def nodes(self): - """ - Return a list of nodes wrapped by this backdrop. - """ - node_ids = [n.id for n in self.view.get_nodes()] - return [self.graph.get_node_by_id(nid) for nid in node_ids] - - def set_text(self, text=''): - """ - Set the multi-line text in the backdrop. - """ - self.set_property('backdrop_text', text) - - def text(self): - """ - Return the text content in the backdrop. - """ - return self.get_property('backdrop_text') - - def set_size(self, width, height): - """ - Manually set the backdrop size. - """ - if self.graph: - self.view.prepareGeometryChange() - self.graph.begin_undo('backdrop size') - self.set_property('width', width) - self.set_property('height', height) - self.graph.end_undo() - self.view.update() - else: - self.view.width, self.view.height = width, height - self.model.width, self.model.height = width, height - - def size(self): - """ - Return (width, height) of the backdrop. - """ - self.model.width = self.view.width - self.model.height = self.view.height - return self.model.width, self.model.height - - # No ports for a backdrop: - def inputs(self): - return - - def outputs(self): - return - - # -------------------------------------------------------------------------- - # Custom Context Menu - # -------------------------------------------------------------------------- - def on_context_menu(self, menu): - """ - Called manually by the node context menu callback in older NodeGraphQt versions. - """ - rename_action = menu.addAction("Set Title...") - rename_action.triggered.connect(self._change_title) - - color_action = menu.addAction("Set Color...") - color_action.triggered.connect(self._change_color) - - def _change_title(self): - """ - Prompt for a new backdrop title (header). - """ - new_title, ok = QtWidgets.QInputDialog.getText( - None, "Backdrop Title", "Enter new backdrop title:" - ) - if ok and new_title: - self.set_name(new_title) - - def _change_color(self): - """ - Prompt for a new backdrop color via QColorDialog. - """ - current_color = QtGui.QColor(*self.model.color) - color = QtWidgets.QColorDialog.getColor( - current_color, None, "Select Backdrop Color" - ) - if color.isValid(): - self.model.color = (color.red(), color.green(), color.blue(), color.alpha()) - self.view.update() diff --git a/Nodes/base_circle_node.py b/Nodes/base_circle_node.py deleted file mode 100644 index 790c8f6..0000000 --- a/Nodes/base_circle_node.py +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/python -from NodeGraphQt.nodes.base_node import BaseNode -from NodeGraphQt.qgraphics.node_circle import CircleNodeItem - - -class BaseNodeCircle(BaseNode): - """ - `Implemented in` ``v0.5.2`` - - The ``NodeGraphQt.BaseNodeCircle`` is pretty much the same class as the - :class:`NodeGraphQt.BaseNode` except with a different design. - - .. inheritance-diagram:: NodeGraphQt.BaseNodeCircle - - .. image:: ../_images/node_circle.png - :width: 250px - - example snippet: - - .. code-block:: python - :linenos: - - from NodeGraphQt import BaseNodeCircle - - class ExampleNode(BaseNodeCircle): - - # unique node identifier domain. - __identifier__ = 'io.jchanvfx.github' - - # initial default node name. - NODE_NAME = 'My Node' - - def __init__(self): - super(ExampleNode, self).__init__() - - # create an input port. - self.add_input('in') - - # create an output port. - self.add_output('out') - """ - - NODE_NAME = 'Circle Node' - - def __init__(self, qgraphics_item=None): - super(BaseNodeCircle, self).__init__(qgraphics_item or CircleNodeItem) \ No newline at end of file diff --git a/Nodes/base_node.py b/Nodes/base_node.py deleted file mode 100644 index 4212bb5..0000000 --- a/Nodes/base_node.py +++ /dev/null @@ -1,876 +0,0 @@ -#!/usr/bin/python -from collections import OrderedDict - -from NodeGraphQt.base.commands import NodeVisibleCmd, NodeWidgetVisibleCmd -from NodeGraphQt.base.node import NodeObject -from NodeGraphQt.base.port import Port -from NodeGraphQt.constants import NodePropWidgetEnum, PortTypeEnum -from NodeGraphQt.errors import ( - PortError, - PortRegistrationError, - NodeWidgetError -) -from NodeGraphQt.qgraphics.node_base import NodeItem -from NodeGraphQt.widgets.node_widgets import ( - NodeBaseWidget, - NodeCheckBox, - NodeComboBox, - NodeLineEdit -) - - -class BaseNode(NodeObject): - """ - The ``NodeGraphQt.BaseNode`` class is the base class for nodes that allows - port connections from one node to another. - - .. inheritance-diagram:: NodeGraphQt.BaseNode - - .. image:: ../_images/node.png - :width: 250px - - example snippet: - - .. code-block:: python - :linenos: - - from NodeGraphQt import BaseNode - - class ExampleNode(BaseNode): - - # unique node identifier domain. - __identifier__ = 'io.jchanvfx.github' - - # initial default node name. - NODE_NAME = 'My Node' - - def __init__(self): - super(ExampleNode, self).__init__() - - # create an input port. - self.add_input('in') - - # create an output port. - self.add_output('out') - """ - - NODE_NAME = 'Node' - - def __init__(self, qgraphics_item=None): - super(BaseNode, self).__init__(qgraphics_item or NodeItem) - self._inputs = [] - self._outputs = [] - - def update_model(self): - """ - Update the node model from view. - """ - for name, val in self.view.properties.items(): - if name in ['inputs', 'outputs']: - continue - self.model.set_property(name, val) - - for name, widget in self.view.widgets.items(): - self.model.set_property(name, widget.get_value()) - - def set_property(self, name, value, push_undo=True): - """ - Set the value on the node custom property. - - Args: - name (str): name of the property. - value (object): property data (python built in types). - push_undo (bool): register the command to the undo stack. (default: True) - """ - # prevent signals from causing a infinite loop. - if self.get_property(name) == value: - return - - if name == 'visible': - if self.graph: - undo_cmd = NodeVisibleCmd(self, value) - if push_undo: - self.graph.undo_stack().push(undo_cmd) - else: - undo_cmd.redo() - return - elif name == 'disabled': - # redraw the connected pipes in the scene. - ports = self.view.inputs + self.view.outputs - for port in ports: - for pipe in port.connected_pipes: - pipe.update() - super(BaseNode, self).set_property(name, value, push_undo) - - def set_layout_direction(self, value=0): - """ - Sets the node layout direction to either horizontal or vertical on - the current node only. - - `Implemented in` ``v0.3.0`` - - See Also: - :meth:`NodeGraph.set_layout_direction`, - :meth:`NodeObject.layout_direction` - - - Warnings: - This function does not register to the undo stack. - - Args: - value (int): layout direction mode. - """ - # base logic to update the model and view attributes only. - super(BaseNode, self).set_layout_direction(value) - # redraw the node. - self._view.draw_node() - - def set_icon(self, icon=None): - """ - Set the node icon. - - Args: - icon (str): path to the icon image. - """ - self.set_property('icon', icon) - - def icon(self): - """ - Node icon path. - - Returns: - str: icon image file path. - """ - return self.model.icon - - def widgets(self): - """ - Returns all embedded widgets from this node. - - See Also: - :meth:`BaseNode.get_widget` - - Returns: - dict: embedded node widgets. {``property_name``: ``node_widget``} - """ - return self.view.widgets - - def get_widget(self, name): - """ - Returns the embedded widget associated with the property name. - - See Also: - :meth:`BaseNode.add_combo_menu`, - :meth:`BaseNode.add_text_input`, - :meth:`BaseNode.add_checkbox`, - - Args: - name (str): node property name. - - Returns: - NodeBaseWidget: embedded node widget. - """ - return self.view.widgets.get(name) - - def add_custom_widget(self, widget, widget_type=None, tab=None): - """ - Add a custom node widget into the node. - - see example :ref:`Embedding Custom Widgets`. - - Note: - The ``value_changed`` signal from the added node widget is wired - up to the :meth:`NodeObject.set_property` function. - - Args: - widget (NodeBaseWidget): node widget class object. - widget_type: widget flag to display in the - :class:`NodeGraphQt.PropertiesBinWidget` - (default: :attr:`NodeGraphQt.constants.NodePropWidgetEnum.HIDDEN`). - tab (str): name of the widget tab to display in. - """ - if not isinstance(widget, NodeBaseWidget): - raise NodeWidgetError( - '\'widget\' must be an instance of a NodeBaseWidget') - - widget_type = widget_type or NodePropWidgetEnum.HIDDEN.value - self.create_property(widget.get_name(), - widget.get_value(), - widget_type=widget_type, - tab=tab) - widget.value_changed.connect(lambda k, v: self.set_property(k, v)) - widget._node = self - self.view.add_widget(widget) - #: redraw node to address calls outside the "__init__" func. - self.view.draw_node() - - #: HACK: calling the .parent() function here on the widget as it seems - # to address a seg fault issue when exiting the application. - widget.parent() - - def add_combo_menu(self, name, label='', items=None, tooltip=None, - tab=None): - """ - Creates a custom property with the :meth:`NodeObject.create_property` - function and embeds a :class:`PySide2.QtWidgets.QComboBox` widget - into the node. - - Note: - The ``value_changed`` signal from the added node widget is wired - up to the :meth:`NodeObject.set_property` function. - - Args: - name (str): name for the custom property. - label (str): label to be displayed. - items (list[str]): items to be added into the menu. - tooltip (str): widget tooltip. - tab (str): name of the widget tab to display in. - """ - self.create_property( - name, - value=items[0] if items else None, - items=items or [], - widget_type=NodePropWidgetEnum.QCOMBO_BOX.value, - widget_tooltip=tooltip, - tab=tab - ) - widget = NodeComboBox(self.view, name, label, items) - widget.setToolTip(tooltip or '') - widget.value_changed.connect(lambda k, v: self.set_property(k, v)) - self.view.add_widget(widget) - #: redraw node to address calls outside the "__init__" func. - self.view.draw_node() - - def add_text_input(self, name, label='', text='', placeholder_text='', - tooltip=None, tab=None): - """ - Creates a custom property with the :meth:`NodeObject.create_property` - function and embeds a :class:`PySide2.QtWidgets.QLineEdit` widget - into the node. - - Note: - The ``value_changed`` signal from the added node widget is wired - up to the :meth:`NodeObject.set_property` function. - - Args: - name (str): name for the custom property. - label (str): label to be displayed. - text (str): pre-filled text. - placeholder_text (str): placeholder text. - tooltip (str): widget tooltip. - tab (str): name of the widget tab to display in. - """ - self.create_property( - name, - value=text, - widget_type=NodePropWidgetEnum.QLINE_EDIT.value, - widget_tooltip=tooltip, - tab=tab - ) - widget = NodeLineEdit(self.view, name, label, text, placeholder_text) - widget.setToolTip(tooltip or '') - widget.value_changed.connect(lambda k, v: self.set_property(k, v)) - self.view.add_widget(widget) - #: redraw node to address calls outside the "__init__" func. - self.view.draw_node() - - def add_checkbox(self, name, label='', text='', state=False, tooltip=None, - tab=None): - """ - Creates a custom property with the :meth:`NodeObject.create_property` - function and embeds a :class:`PySide2.QtWidgets.QCheckBox` widget - into the node. - - Note: - The ``value_changed`` signal from the added node widget is wired - up to the :meth:`NodeObject.set_property` function. - - Args: - name (str): name for the custom property. - label (str): label to be displayed. - text (str): checkbox text. - state (bool): pre-check. - tooltip (str): widget tooltip. - tab (str): name of the widget tab to display in. - """ - self.create_property( - name, - value=state, - widget_type=NodePropWidgetEnum.QCHECK_BOX.value, - widget_tooltip=tooltip, - tab=tab - ) - widget = NodeCheckBox(self.view, name, label, text, state) - widget.setToolTip(tooltip or '') - widget.value_changed.connect(lambda k, v: self.set_property(k, v)) - self.view.add_widget(widget) - #: redraw node to address calls outside the "__init__" func. - self.view.draw_node() - - def hide_widget(self, name, push_undo=True): - """ - Hide an embedded node widget. - - Args: - name (str): node property name for the widget. - push_undo (bool): register the command to the undo stack. (default: True) - - See Also: - :meth:`BaseNode.add_custom_widget`, - :meth:`BaseNode.show_widget`, - :meth:`BaseNode.get_widget` - """ - if not self.view.has_widget(name): - return - undo_cmd = NodeWidgetVisibleCmd(self, name, visible=False) - if push_undo: - self.graph.undo_stack().push(undo_cmd) - else: - undo_cmd.redo() - - def show_widget(self, name, push_undo=True): - """ - Show an embedded node widget. - - Args: - name (str): node property name for the widget. - push_undo (bool): register the command to the undo stack. (default: True) - - See Also: - :meth:`BaseNode.add_custom_widget`, - :meth:`BaseNode.hide_widget`, - :meth:`BaseNode.get_widget` - """ - if not self.view.has_widget(name): - return - undo_cmd = NodeWidgetVisibleCmd(self, name, visible=True) - if push_undo: - self.graph.undo_stack().push(undo_cmd) - else: - undo_cmd.redo() - - def add_input(self, name='input', multi_input=False, display_name=True, - color=None, locked=False, painter_func=None): - """ - Add input :class:`Port` to node. - - Warnings: - Undo is NOT supported for this function. - - Args: - name (str): name for the input port. - multi_input (bool): allow port to have more than one connection. - display_name (bool): display the port name on the node. - color (tuple): initial port color (r, g, b) ``0-255``. - locked (bool): locked state see :meth:`Port.set_locked` - painter_func (function or None): custom function to override the drawing - of the port shape see example: :ref:`Creating Custom Shapes` - - Returns: - NodeGraphQt.Port: the created port object. - """ - if name in self.inputs().keys(): - raise PortRegistrationError( - 'port name "{}" already registered.'.format(name)) - - port_args = [name, multi_input, display_name, locked] - if painter_func and callable(painter_func): - port_args.append(painter_func) - view = self.view.add_input(*port_args) - - if color: - view.color = color - view.border_color = [min([255, max([0, i + 80])]) for i in color] - - port = Port(self, view) - port.model.type_ = PortTypeEnum.IN.value - port.model.name = name - port.model.display_name = display_name - port.model.multi_connection = multi_input - port.model.locked = locked - self._inputs.append(port) - self.model.inputs[port.name()] = port.model - return port - - def add_output(self, name='output', multi_output=True, display_name=True, - color=None, locked=False, painter_func=None): - """ - Add output :class:`Port` to node. - - Warnings: - Undo is NOT supported for this function. - - Args: - name (str): name for the output port. - multi_output (bool): allow port to have more than one connection. - display_name (bool): display the port name on the node. - color (tuple): initial port color (r, g, b) ``0-255``. - locked (bool): locked state see :meth:`Port.set_locked` - painter_func (function or None): custom function to override the drawing - of the port shape see example: :ref:`Creating Custom Shapes` - - Returns: - NodeGraphQt.Port: the created port object. - """ - if name in self.outputs().keys(): - raise PortRegistrationError( - 'port name "{}" already registered.'.format(name)) - - port_args = [name, multi_output, display_name, locked] - if painter_func and callable(painter_func): - port_args.append(painter_func) - view = self.view.add_output(*port_args) - - if color: - view.color = color - view.border_color = [min([255, max([0, i + 80])]) for i in color] - port = Port(self, view) - port.model.type_ = PortTypeEnum.OUT.value - port.model.name = name - port.model.display_name = display_name - port.model.multi_connection = multi_output - port.model.locked = locked - self._outputs.append(port) - self.model.outputs[port.name()] = port.model - return port - - def get_input(self, port): - """ - Get input port by the name or index. - - Args: - port (str or int): port name or index. - - Returns: - NodeGraphQt.Port: node port. - """ - if type(port) is int: - if port < len(self._inputs): - return self._inputs[port] - elif type(port) is str: - return self.inputs().get(port, None) - - def get_output(self, port): - """ - Get output port by the name or index. - - Args: - port (str or int): port name or index. - - Returns: - NodeGraphQt.Port: node port. - """ - if type(port) is int: - if port < len(self._outputs): - return self._outputs[port] - elif type(port) is str: - return self.outputs().get(port, None) - - def delete_input(self, port): - """ - Delete input port. - - Warnings: - Undo is NOT supported for this function. - - You can only delete ports if :meth:`BaseNode.port_deletion_allowed` - returns ``True`` otherwise a port error is raised see also - :meth:`BaseNode.set_port_deletion_allowed`. - - Args: - port (str or int): port name or index. - """ - if type(port) in [int, str]: - port = self.get_input(port) - if port is None: - return - if not self.port_deletion_allowed(): - raise PortError( - 'Port "{}" can\'t be deleted on this node because ' - '"ports_removable" is not enabled.'.format(port.name())) - if port.locked(): - raise PortError('Error: Can\'t delete a port that is locked!') - self._inputs.remove(port) - self._model.inputs.pop(port.name()) - self._view.delete_input(port.view) - port.model.node = None - self._view.draw_node() - - def delete_output(self, port): - """ - Delete output port. - - Warnings: - Undo is NOT supported for this function. - - You can only delete ports if :meth:`BaseNode.port_deletion_allowed` - returns ``True`` otherwise a port error is raised see also - :meth:`BaseNode.set_port_deletion_allowed`. - - Args: - port (str or int): port name or index. - """ - if type(port) in [int, str]: - port = self.get_output(port) - if port is None: - return - if not self.port_deletion_allowed(): - raise PortError( - 'Port "{}" can\'t be deleted on this node because ' - '"ports_removable" is not enabled.'.format(port.name())) - if port.locked(): - raise PortError('Error: Can\'t delete a port that is locked!') - self._outputs.remove(port) - self._model.outputs.pop(port.name()) - self._view.delete_output(port.view) - port.model.node = None - self._view.draw_node() - - def set_port_deletion_allowed(self, mode=False): - """ - Allow ports to be removable on this node. - - See Also: - :meth:`BaseNode.port_deletion_allowed` and - :meth:`BaseNode.set_ports` - - Args: - mode (bool): true to allow. - """ - self.model.port_deletion_allowed = mode - - def port_deletion_allowed(self): - """ - Return true if ports can be deleted on this node. - - See Also: - :meth:`BaseNode.set_port_deletion_allowed` - - Returns: - bool: true if ports can be deleted. - """ - return self.model.port_deletion_allowed - - def set_ports(self, port_data): - """ - Create node input and output ports from serialized port data. - - Warnings: - You can only use this function if the node has - :meth:`BaseNode.port_deletion_allowed` is `True` - see :meth:`BaseNode.set_port_deletion_allowed` - - Hint: - example snippet of port data. - - .. highlight:: python - .. code-block:: python - - { - 'input_ports': - [{ - 'name': 'input', - 'multi_connection': True, - 'display_name': 'Input', - 'locked': False - }], - 'output_ports': - [{ - 'name': 'output', - 'multi_connection': True, - 'display_name': 'Output', - 'locked': False - }] - } - - Args: - port_data(dict): port data. - """ - if not self.port_deletion_allowed(): - raise PortError( - 'Ports cannot be set on this node because ' - '"set_port_deletion_allowed" is not enabled on this node.') - - for port in self._inputs: - self._view.delete_input(port.view) - port.model.node = None - for port in self._outputs: - self._view.delete_output(port.view) - port.model.node = None - self._inputs = [] - self._outputs = [] - self._model.outputs = {} - self._model.inputs = {} - - [self.add_input(name=port['name'], - multi_input=port['multi_connection'], - display_name=port['display_name'], - locked=port.get('locked') or False) - for port in port_data['input_ports']] - [self.add_output(name=port['name'], - multi_output=port['multi_connection'], - display_name=port['display_name'], - locked=port.get('locked') or False) - for port in port_data['output_ports']] - self._view.draw_node() - - def inputs(self): - """ - Returns all the input ports from the node. - - Returns: - dict: {: } - """ - return {p.name(): p for p in self._inputs} - - def input_ports(self): - """ - Return all input ports. - - Returns: - list[NodeGraphQt.Port]: node input ports. - """ - return self._inputs - - def outputs(self): - """ - Returns all the output ports from the node. - - Returns: - dict: {: } - """ - return {p.name(): p for p in self._outputs} - - def output_ports(self): - """ - Return all output ports. - - Returns: - list[NodeGraphQt.Port]: node output ports. - """ - return self._outputs - - def input(self, index): - """ - Return the input port with the matching index. - - Args: - index (int): index of the input port. - - Returns: - NodeGraphQt.Port: port object. - """ - return self._inputs[index] - - def set_input(self, index, port): - """ - Creates a connection pipe to the targeted output :class:`Port`. - - Args: - index (int): index of the port. - port (NodeGraphQt.Port): port object. - """ - src_port = self.input(index) - src_port.connect_to(port) - - def output(self, index): - """ - Return the output port with the matching index. - - Args: - index (int): index of the output port. - - Returns: - NodeGraphQt.Port: port object. - """ - return self._outputs[index] - - def set_output(self, index, port): - """ - Creates a connection pipe to the targeted input :class:`Port`. - - Args: - index (int): index of the port. - port (NodeGraphQt.Port): port object. - """ - src_port = self.output(index) - src_port.connect_to(port) - - def connected_input_nodes(self): - """ - Returns all nodes connected from the input ports. - - Returns: - dict: {: } - """ - nodes = OrderedDict() - for p in self.input_ports(): - nodes[p] = [cp.node() for cp in p.connected_ports()] - return nodes - - def connected_output_nodes(self): - """ - Returns all nodes connected from the output ports. - - Returns: - dict: {: } - """ - nodes = OrderedDict() - for p in self.output_ports(): - nodes[p] = [cp.node() for cp in p.connected_ports()] - return nodes - - def add_accept_port_type(self, port, port_type_data): - """ - Add an accept constrain to a specified node port. - - Once a constraint has been added only ports of that type specified will - be allowed a pipe connection. - - port type data example - - .. highlight:: python - .. code-block:: python - - { - 'port_name': 'foo' - 'port_type': PortTypeEnum.IN.value - 'node_type': 'io.github.jchanvfx.NodeClass' - } - - See Also: - :meth:`NodeGraphQt.BaseNode.accepted_port_types` - - Args: - port (NodeGraphQt.Port): port to assign constrain to. - port_type_data (dict): port type data to accept a connection - """ - node_ports = self._inputs + self._outputs - if port not in node_ports: - raise PortError('Node does not contain port: "{}"'.format(port)) - - self._model.add_port_accept_connection_type( - port_name=port.name(), - port_type=port.type_(), - node_type=self.type_, - accept_pname=port_type_data['port_name'], - accept_ptype=port_type_data['port_type'], - accept_ntype=port_type_data['node_type'] - ) - - def accepted_port_types(self, port): - """ - Returns a dictionary of connection constrains of the port types - that allow for a pipe connection to this node. - - Args: - port (NodeGraphQt.Port): port object. - - Returns: - dict: {: {: []}} - """ - ports = self._inputs + self._outputs - if port not in ports: - raise PortError('Node does not contain port "{}"'.format(port)) - - accepted_types = self.graph.model.port_accept_connection_types( - node_type=self.type_, - port_type=port.type_(), - port_name=port.name() - ) - return accepted_types - - def add_reject_port_type(self, port, port_type_data): - """ - Add a reject constrain to a specified node port. - - Once a constraint has been added only ports of that type specified will - NOT be allowed a pipe connection. - - port type data example - - .. highlight:: python - .. code-block:: python - - { - 'port_name': 'foo' - 'port_type': PortTypeEnum.IN.value - 'node_type': 'io.github.jchanvfx.NodeClass' - } - - See Also: - :meth:`NodeGraphQt.Port.rejected_port_types` - - Args: - port (NodeGraphQt.Port): port to assign constrain to. - port_type_data (dict): port type data to reject a connection - """ - node_ports = self._inputs + self._outputs - if port not in node_ports: - raise PortError('Node does not contain port: "{}"'.format(port)) - - self._model.add_port_reject_connection_type( - port_name=port.name(), - port_type=port.type_(), - node_type=self.type_, - reject_pname=port_type_data['port_name'], - reject_ptype=port_type_data['port_type'], - reject_ntype=port_type_data['node_type'] - ) - - def rejected_port_types(self, port): - """ - Returns a dictionary of connection constrains of the port types - that are NOT allowed for a pipe connection to this node. - - Args: - port (NodeGraphQt.Port): port object. - - Returns: - dict: {: {: []}} - """ - ports = self._inputs + self._outputs - if port not in ports: - raise PortError('Node does not contain port "{}"'.format(port)) - - rejected_types = self.graph.model.port_reject_connection_types( - node_type=self.type_, - port_type=port.type_(), - port_name=port.name() - ) - return rejected_types - - def on_input_connected(self, in_port, out_port): - """ - Callback triggered when a new pipe connection is made. - - *The default of this function does nothing re-implement if you require - logic to run for this event.* - - Note: - to work with undo & redo for this method re-implement - :meth:`BaseNode.on_input_disconnected` with the reverse logic. - - Args: - in_port (NodeGraphQt.Port): source input port from this node. - out_port (NodeGraphQt.Port): output port that connected to this node. - """ - return - - def on_input_disconnected(self, in_port, out_port): - """ - Callback triggered when a pipe connection has been disconnected - from a INPUT port. - - *The default of this function does nothing re-implement if you require - logic to run for this event.* - - Note: - to work with undo & redo for this method re-implement - :meth:`BaseNode.on_input_connected` with the reverse logic. - - Args: - in_port (NodeGraphQt.Port): source input port from this node. - out_port (NodeGraphQt.Port): output port that was disconnected. - """ - return \ No newline at end of file diff --git a/Nodes/character_status_node.py b/Nodes/character_status_node.py index 5e12394..ab5e0fd 100644 --- a/Nodes/character_status_node.py +++ b/Nodes/character_status_node.py @@ -9,7 +9,7 @@ If the API call is successful, the node's title is set to "Character Status (API If the API is down or returns an error, the title is set to "Character Status (API Disconnected)". """ -from NodeGraphQt import BaseNode +from OdenGraphQt import BaseNode from Qt import QtCore, QtGui import requests import traceback @@ -151,3 +151,4 @@ class CharacterStatusNode(BaseNode): except Exception as e: print(f"[ERROR] Error while handling port {stat}: {e}") print("[ERROR] Stack Trace:\n", traceback.format_exc()) + diff --git a/Nodes/data_node.py b/Nodes/data_node.py index 7c89dc1..1b1304b 100644 --- a/Nodes/data_node.py +++ b/Nodes/data_node.py @@ -15,7 +15,7 @@ Behavior: - Displays the input value but does not transmit it further. """ -from NodeGraphQt import BaseNode +from OdenGraphQt import BaseNode class DataNode(BaseNode): __identifier__ = 'bunny-lab.io.data_node' @@ -121,3 +121,5 @@ class DataNode(BaseNode): connected_node = connected_port.node() if hasattr(connected_node, 'receive_data'): connected_node.receive_data(data, source_port_name) + + diff --git a/Nodes/group_node.py b/Nodes/group_node.py deleted file mode 100644 index f87fe32..0000000 --- a/Nodes/group_node.py +++ /dev/null @@ -1,176 +0,0 @@ -#!/usr/bin/python -from NodeGraphQt.nodes.base_node import BaseNode -from NodeGraphQt.nodes.port_node import PortInputNode, PortOutputNode -from NodeGraphQt.qgraphics.node_group import GroupNodeItem - - -class GroupNode(BaseNode): - """ - `Implemented in` ``v0.2.0`` - - The ``NodeGraphQt.GroupNode`` class extends from the :class:`NodeGraphQt.BaseNode` - class with the ability to nest other nodes inside of it. - - .. inheritance-diagram:: NodeGraphQt.GroupNode - - .. image:: ../_images/group_node.png - :width: 250px - - - - """ - - NODE_NAME = 'Group' - - def __init__(self, qgraphics_item=None): - super(GroupNode, self).__init__(qgraphics_item or GroupNodeItem) - self._input_port_nodes = {} - self._output_port_nodes = {} - - @property - def is_expanded(self): - """ - Returns if the group node is expanded or collapsed. - - Returns: - bool: true if the node is expanded. - """ - if not self.graph: - return False - return bool(self.id in self.graph.sub_graphs) - - def get_sub_graph(self): - """ - Returns the sub graph controller to the group node if initialized - or returns None. - - Returns: - SubGraph: sub graph controller. - """ - return self.graph.sub_graphs.get(self.id) - - def get_sub_graph_session(self): - """ - Returns the serialized sub graph session. - - Returns: - dict: serialized sub graph session. - """ - return self.model.subgraph_session - - def set_sub_graph_session(self, serialized_session): - """ - Sets the sub graph session data to the group node. - - Args: - serialized_session (dict): serialized session. - """ - serialized_session = serialized_session or {} - self.model.subgraph_session = serialized_session - - def expand(self): - """ - Expand the group node session. - - See Also: - :meth:`NodeGraph.expand_group_node`, - :meth:`SubGraph.expand_group_node`. - - Returns: - SubGraph: node graph used to manage the nodes expaneded session. - """ - sub_graph = self.graph.expand_group_node(self) - return sub_graph - - def collapse(self): - """ - Collapse the group node session it's expanded child sub graphs. - - See Also: - :meth:`NodeGraph.collapse_group_node`, - :meth:`SubGraph.collapse_group_node`. - """ - self.graph.collapse_group_node(self) - - def set_name(self, name=''): - super(GroupNode, self).set_name(name) - # update the tab bar and navigation labels. - sub_graph = self.get_sub_graph() - if sub_graph: - nav_widget = sub_graph.navigation_widget - nav_widget.update_label_item(self.name(), self.id) - - if sub_graph.parent_graph.is_root: - root_graph = sub_graph.parent_graph - tab_bar = root_graph.widget.tabBar() - for idx in range(tab_bar.count()): - if tab_bar.tabToolTip(idx) == self.id: - tab_bar.setTabText(idx, self.name()) - break - - def add_input(self, name='input', multi_input=False, display_name=True, - color=None, locked=False, painter_func=None): - port = super(GroupNode, self).add_input( - name=name, - multi_input=multi_input, - display_name=display_name, - color=color, - locked=locked, - painter_func=painter_func - ) - if self.is_expanded: - input_node = PortInputNode(parent_port=port) - input_node.NODE_NAME = port.name() - input_node.model.set_property('name', port.name()) - input_node.add_output(port.name()) - sub_graph = self.get_sub_graph() - sub_graph.add_node(input_node, selected=False, push_undo=False) - - return port - - def add_output(self, name='output', multi_output=True, display_name=True, - color=None, locked=False, painter_func=None): - port = super(GroupNode, self).add_output( - name=name, - multi_output=multi_output, - display_name=display_name, - color=color, - locked=locked, - painter_func=painter_func - ) - if self.is_expanded: - output_port = PortOutputNode(parent_port=port) - output_port.NODE_NAME = port.name() - output_port.model.set_property('name', port.name()) - output_port.add_input(port.name()) - sub_graph = self.get_sub_graph() - sub_graph.add_node(output_port, selected=False, push_undo=False) - - return port - - def delete_input(self, port): - if type(port) in [int, str]: - port = self.get_input(port) - if port is None: - return - - if self.is_expanded: - sub_graph = self.get_sub_graph() - port_node = sub_graph.get_node_by_port(port) - if port_node: - sub_graph.remove_node(port_node, push_undo=False) - - super(GroupNode, self).delete_input(port) - - def delete_output(self, port): - if type(port) in [int, str]: - port = self.get_output(port) - if port is None: - return - - if self.is_expanded: - sub_graph = self.get_sub_graph() - port_node = sub_graph.get_node_by_port(port) - if port_node: - sub_graph.remove_node(port_node, push_undo=False) - - super(GroupNode, self).delete_output(port) \ No newline at end of file diff --git a/Nodes/math_operation_node.py b/Nodes/math_operation_node.py index 2bf84e4..149b895 100644 --- a/Nodes/math_operation_node.py +++ b/Nodes/math_operation_node.py @@ -8,7 +8,7 @@ Math Operation Node: - Displays the computed result in a read-only text box labeled "Result". """ -from NodeGraphQt import BaseNode +from OdenGraphQt import BaseNode class MathOperationNode(BaseNode): __identifier__ = 'bunny-lab.io.math_node' @@ -119,3 +119,4 @@ class MathOperationNode(BaseNode): def receive_data(self, data, source_port_name=None): self.process_input() + diff --git a/Nodes/port_node.py b/Nodes/port_node.py deleted file mode 100644 index 6a71524..0000000 --- a/Nodes/port_node.py +++ /dev/null @@ -1,135 +0,0 @@ -#!/usr/bin/python -from NodeGraphQt.errors import PortRegistrationError -from NodeGraphQt.nodes.base_node import BaseNode -from NodeGraphQt.qgraphics.node_port_in import PortInputNodeItem -from NodeGraphQt.qgraphics.node_port_out import PortOutputNodeItem - - -class PortInputNode(BaseNode): - """ - The ``PortInputNode`` is the node that represents a input port from a - :class:`NodeGraphQt.GroupNode` when expanded in a - :class:`NodeGraphQt.SubGraph`. - - .. inheritance-diagram:: NodeGraphQt.nodes.port_node.PortInputNode - :parts: 1 - - .. image:: ../_images/port_in_node.png - :width: 150px - - - - """ - - NODE_NAME = 'InputPort' - - def __init__(self, qgraphics_item=None, parent_port=None): - super(PortInputNode, self).__init__(qgraphics_item or PortInputNodeItem) - self._parent_port = parent_port - - @property - def parent_port(self): - """ - The parent group node port representing this node. - - Returns: - NodeGraphQt.Port: port object. - """ - return self._parent_port - - def add_input(self, name='input', multi_input=False, display_name=True, - color=None, locked=False, painter_func=None): - """ - Warnings: - This is not available for the ``PortInputNode`` class. - """ - raise PortRegistrationError( - '"{}.add_input()" is not available for {}.' - .format(self.__class__.__name__, self) - ) - - def add_output(self, name='output', multi_output=True, display_name=True, - color=None, locked=False, painter_func=None): - """ - Warnings: - This function is called by :meth:`NodeGraphQt.SubGraph.expand_group_node` - and is not available for the ``PortInputNode`` class. - """ - if self._outputs: - raise PortRegistrationError( - '"{}.add_output()" only ONE output is allowed for this node.' - .format(self.__class__.__name__, self) - ) - super(PortInputNode, self).add_output( - name=name, - multi_output=multi_output, - display_name=False, - color=color, - locked=locked, - painter_func=None - ) - - -class PortOutputNode(BaseNode): - """ - The ``PortOutputNode`` is the node that represents a output port from a - :class:`NodeGraphQt.GroupNode` when expanded in a - :class:`NodeGraphQt.SubGraph`. - - .. inheritance-diagram:: NodeGraphQt.nodes.port_node.PortOutputNode - :parts: 1 - - .. image:: ../_images/port_out_node.png - :width: 150px - - - - """ - - NODE_NAME = 'OutputPort' - - def __init__(self, qgraphics_item=None, parent_port=None): - super(PortOutputNode, self).__init__( - qgraphics_item or PortOutputNodeItem - ) - self._parent_port = parent_port - - @property - def parent_port(self): - """ - The parent group node port representing this node. - - Returns: - NodeGraphQt.Port: port object. - """ - return self._parent_port - - def add_input(self, name='input', multi_input=False, display_name=True, - color=None, locked=False, painter_func=None): - """ - Warnings: - This function is called by :meth:`NodeGraphQt.SubGraph.expand_group_node` - and is not available for the ``PortOutputNode`` class. - """ - if self._inputs: - raise PortRegistrationError( - '"{}.add_input()" only ONE input is allowed for this node.' - .format(self.__class__.__name__, self) - ) - super(PortOutputNode, self).add_input( - name=name, - multi_input=multi_input, - display_name=False, - color=color, - locked=locked, - painter_func=None - ) - - def add_output(self, name='output', multi_output=True, display_name=True, - color=None, locked=False, painter_func=None): - """ - Warnings: - This is not available for the ``PortOutputNode`` class. - """ - raise PortRegistrationError( - '"{}.add_output()" is not available for {}.' - .format(self.__class__.__name__, self) - ) \ No newline at end of file diff --git a/borealis.py b/borealis.py index d9c4e3b..0b5c030 100644 --- a/borealis.py +++ b/borealis.py @@ -28,7 +28,7 @@ import pkgutil import importlib import inspect from Qt import QtWidgets, QtCore -from NodeGraphQt import NodeGraph, BaseNode +from OdenGraphQt import NodeGraph, BaseNode def import_nodes_from_folder(package_name): """ @@ -58,6 +58,7 @@ def make_node_command(graph, nt): return command if __name__ == '__main__': + app = QtWidgets.QApplication([]) # Create the NodeGraph controller. @@ -104,3 +105,4 @@ if __name__ == '__main__': timer.start(500) sys.exit(app.exec()) + diff --git a/debug_processed.png b/debug_processed.png index 6a2aa34..b905d3f 100644 Binary files a/debug_processed.png and b/debug_processed.png differ diff --git a/debug_screenshot.png b/debug_screenshot.png index b67056c..ad9b0a0 100644 Binary files a/debug_screenshot.png and b/debug_screenshot.png differ