From b09d51a8c240fcb5e19471c8090c11d64e2dc342 Mon Sep 17 00:00:00 2001 From: ArnoChenFx Date: Sat, 8 Feb 2020 13:57:12 +0800 Subject: [PATCH 1/6] add NODE_PROP_FILE file ext filter --- NodeGraphQt/base/model.py | 7 ++++++- NodeGraphQt/base/node.py | 22 ++++++++++++++++------ NodeGraphQt/widgets/properties.py | 8 +++++++- 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/NodeGraphQt/base/model.py b/NodeGraphQt/base/model.py index 3af31ee8..eb0d4f86 100644 --- a/NodeGraphQt/base/model.py +++ b/NodeGraphQt/base/model.py @@ -92,7 +92,7 @@ def __init__(self): } def add_property(self, name, value, items=None, range=None, - widget_type=NODE_PROP, tab='Properties'): + widget_type=NODE_PROP, tab='Properties', ext=None): """ add custom property. @@ -103,6 +103,7 @@ def add_property(self, name, value, items=None, range=None, range (tuple)): min, max values used by NODE_PROP_SLIDER. widget_type (int): widget type flag. tab (str): widget tab name. + ext (str) file ext for NODE_PROP_FILE """ tab = tab or 'Properties' @@ -122,6 +123,8 @@ def add_property(self, name, value, items=None, range=None, self._TEMP_property_attrs[name]['items'] = items if range: self._TEMP_property_attrs[name]['range'] = range + if ext: + self._TEMP_property_attrs[name]['ext'] = ext else: attrs = {self.type_: {name: { 'widget_type': widget_type, @@ -131,6 +134,8 @@ def add_property(self, name, value, items=None, range=None, attrs[self.type_][name]['items'] = items if range: attrs[self.type_][name]['range'] = range + if ext: + attrs[self.type_][name]['ext'] = ext self._graph_model.set_node_common_properties(attrs) def set_property(self, name, value): diff --git a/NodeGraphQt/base/node.py b/NodeGraphQt/base/node.py index 55c6fe5a..d7c6cbc2 100644 --- a/NodeGraphQt/base/node.py +++ b/NodeGraphQt/base/node.py @@ -234,7 +234,7 @@ def set_selected(self, selected=True): self.set_property('selected', selected) def create_property(self, name, value, items=None, range=None, - widget_type=NODE_PROP, tab=None): + widget_type=NODE_PROP, tab=None, ext=None): """ Creates a custom property to the node. @@ -247,7 +247,13 @@ def create_property(self, name, value, items=None, range=None, - :attr:`NodeGraphQt.constants.NODE_PROP_QCHECKBOX` - :attr:`NodeGraphQt.constants.NODE_PROP_QSPINBOX` - :attr:`NodeGraphQt.constants.NODE_PROP_COLORPICKER` - - :attr:`NodeGraphQt.constants.NODE_PROP_SLIDER` + - :attr:`NodeGraphQt.constants.NODE_PROP_FILE` + - :attr:`NodeGraphQt.constants.NODE_PROP_VECTOR2` + - :attr:`NodeGraphQt.constants.NODE_PROP_VECTOR3` + - :attr:`NodeGraphQt.constants.NODE_PROP_VECTOR4` + - :attr:`NodeGraphQt.constants.NODE_PROP_FLOAT` + - :attr:`NodeGraphQt.constants.NODE_PROP_INT` + - :attr:`NodeGraphQt.constants.NODE_PROP_BUTTON` See Also: :class:`NodeGraphQt.PropertiesBinWidget` @@ -259,8 +265,9 @@ def create_property(self, name, value, items=None, range=None, range (tuple)): ``(min, max)`` values used by ``NODE_PROP_SLIDER`` widget_type (int): widget flag to display in the ``PropertiesBinWidget`` tab (str): name of the widget tab to display in the properties bin. + ext (str): file ext of ``NODE_PROP_FILE`` """ - self.model.add_property(name, value, items, range, widget_type, tab) + self.model.add_property(name, value, items, range, widget_type, tab, ext) def properties(self): """ @@ -557,9 +564,12 @@ def add_file_input(self, name, label='', text='', tab=None, ext="*"): tab (str): name of the widget tab to display in. ext (str): file ext """ - self.create_property( - name, text, widget_type=NODE_PROP_FILE, tab=tab) - widget = NodeFilePath(self.view, name, label, text,ext) + self.model.add_property(name, text, None, None, NODE_PROP_FILE, tab, ext) + # use create_property will cause strange error + # self.create_property( + # name, text, widget_type=NODE_PROP_FILE, tab=tab, ext=None) + + widget = NodeFilePath(self.view, name, label, text, ext) widget.value_changed.connect(lambda k, v: self.set_property(k, v)) self.view.add_widget(widget) diff --git a/NodeGraphQt/widgets/properties.py b/NodeGraphQt/widgets/properties.py index 588c10e1..d66d44c6 100644 --- a/NodeGraphQt/widgets/properties.py +++ b/NodeGraphQt/widgets/properties.py @@ -310,9 +310,13 @@ def __init__(self, parent=None): self._ledit.setStyleSheet("QLineEdit{border:1px solid}") _button.setStyleSheet("QPushButton{border:1px solid}") + self._ext = "*" + + def set_ext(self, ext): + self._ext = ext def _on_select_file(self): - file_path = file_dialog.getOpenFileName(self) + file_path = file_dialog.getOpenFileName(self, ext_filter=self._ext) file = file_path[0] or None if file: self.set_value(file) @@ -868,6 +872,8 @@ def _read_node(self, node): prop_range = common_props[prop_name]['range'] widget.set_min(prop_range[0]) widget.set_max(prop_range[1]) + if 'ext' in common_props[prop_name].keys(): + widget.set_ext(common_props[prop_name]['ext']) prop_window.add_widget(prop_name, widget, value, prop_name.replace('_', ' ')) From 7f6702ae4354fd4a7403d453c9a6df7c82cdd779 Mon Sep 17 00:00:00 2001 From: ArnoChenFx Date: Sun, 9 Feb 2020 18:07:23 +0800 Subject: [PATCH 2/6] set messagebox stylesheet --- NodeGraphQt/widgets/file_dialog.py | 8 ++++++++ NodeGraphQt/widgets/stylesheet.py | 28 ++++++++++++++++++++++++++++ NodeGraphQt/widgets/viewer.py | 9 +++------ 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/NodeGraphQt/widgets/file_dialog.py b/NodeGraphQt/widgets/file_dialog.py index f8480f20..e3fea479 100644 --- a/NodeGraphQt/widgets/file_dialog.py +++ b/NodeGraphQt/widgets/file_dialog.py @@ -1,4 +1,5 @@ from NodeGraphQt import QtWidgets +from NodeGraphQt.widgets.stylesheet import STYLE_MESSAGEBOX import os current_dir = os.path.expanduser('~') @@ -40,3 +41,10 @@ def getOpenFileName(parent=None, title="Open File", file_dir=None, ext_filter="* return file_dlg +def messageBox(text, title , buttons): + msg = QtWidgets.QMessageBox() + msg.setStyleSheet(STYLE_MESSAGEBOX) + msg.setWindowTitle(title) + msg.setInformativeText(text) + msg.setStandardButtons(buttons) + return msg.exec_() \ No newline at end of file diff --git a/NodeGraphQt/widgets/stylesheet.py b/NodeGraphQt/widgets/stylesheet.py index 9e95ea78..8efa21b0 100644 --- a/NodeGraphQt/widgets/stylesheet.py +++ b/NodeGraphQt/widgets/stylesheet.py @@ -193,3 +193,31 @@ background-color: transparent; } ''' + +STYLE_MESSAGEBOX = ''' +QLabel{ + min-width:500 px; + font-size: 18px; + background-color: transparent; + color: rgb(200 ,200, 200); +} +QPushButton{ + width:100px; + font-size: 18px; + background-color: transparent; + color: rgb(200 ,200, 200); + border-width: 1px; + border-color: rgb(40,40,40); +} +QPushButton::pressed { + border-style: inset; +} +QPushButton::hover { + background-color: rgb(65, 65, 65); + border-color: rgb(10,80,230); +} +QMessageBox{ + background-color: rgb(55, 55, 55); + color: rgb(200 ,200, 200); +} +''' \ No newline at end of file diff --git a/NodeGraphQt/widgets/viewer.py b/NodeGraphQt/widgets/viewer.py index 0725f222..e8921b9a 100644 --- a/NodeGraphQt/widgets/viewer.py +++ b/NodeGraphQt/widgets/viewer.py @@ -14,7 +14,7 @@ from NodeGraphQt.widgets.actions import BaseMenu from NodeGraphQt.widgets.scene import NodeScene from NodeGraphQt.widgets.tab_search import TabSearchWidget, TabSearchMenuWidget -from NodeGraphQt.widgets.file_dialog import file_dialog +from NodeGraphQt.widgets.file_dialog import file_dialog, messageBox ZOOM_MIN = -0.95 ZOOM_MAX = 2.0 @@ -714,14 +714,11 @@ def context_menus(self): 'nodes': self._ctx_node_menu} def question_dialog(self, text, title='Node Graph'): - dlg = QtWidgets.QMessageBox.question( - self, title, text, - QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No) + dlg = messageBox(text, title, QtWidgets.QMessageBox.Yes|QtWidgets.QMessageBox.No) return dlg == QtWidgets.QMessageBox.Yes def message_dialog(self, text, title='Node Graph'): - QtWidgets.QMessageBox.information( - self, title, text, QtWidgets.QMessageBox.Ok) + messageBox(text, title, QtWidgets.QMessageBox.Ok) def load_dialog(self, current_dir=None, ext=None): ext = '*{} '.format(ext) if ext else '' From 08691167ed7fd22c3b37dddb5170ffd90c56775b Mon Sep 17 00:00:00 2001 From: ArnoChenFx Date: Sun, 9 Feb 2020 19:12:06 +0800 Subject: [PATCH 3/6] upgrade tab search --- NodeGraphQt/base/graph.py | 14 +++++++------- NodeGraphQt/widgets/viewer.py | 11 +++++++---- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/NodeGraphQt/base/graph.py b/NodeGraphQt/base/graph.py index c296eee2..484ab296 100644 --- a/NodeGraphQt/base/graph.py +++ b/NodeGraphQt/base/graph.py @@ -5,7 +5,7 @@ import re import copy -from NodeGraphQt import QtCore, QtWidgets +from NodeGraphQt import QtCore, QtWidgets, QtGui from NodeGraphQt.base.commands import (NodeAddedCmd, NodeRemovedCmd, NodeMovedCmd, @@ -105,10 +105,9 @@ def __init__(self, parent=None): self._node_factory = NodeFactory() self._undo_stack = QtWidgets.QUndoStack(self) - tab = QtWidgets.QAction('Search Nodes', self) - tab.setShortcut('tab') - tab.triggered.connect(self._toggle_tab_search) - self._viewer.addAction(tab) + tab = QtWidgets.QShortcut(QtGui.QKeySequence(QtCore.Qt.Key_Tab), self._viewer) + tab.activated.connect(self._toggle_tab_search) + self._viewer.need_show_tab_search.connect(self._toggle_tab_search) self._wire_signals() @@ -164,8 +163,9 @@ def _toggle_tab_search(self): """ toggle the tab search widget. """ - self._viewer.tab_search_set_nodes(self._node_factory.names) - self._viewer.tab_search_toggle() + if self._viewer.underMouse(): + self._viewer.tab_search_set_nodes(self._node_factory.names) + self._viewer.tab_search_toggle() def _on_property_bin_changed(self, node_id, prop_name, prop_value): """ diff --git a/NodeGraphQt/widgets/viewer.py b/NodeGraphQt/widgets/viewer.py index e8921b9a..7d8a689a 100644 --- a/NodeGraphQt/widgets/viewer.py +++ b/NodeGraphQt/widgets/viewer.py @@ -33,6 +33,7 @@ class NodeViewer(QtWidgets.QGraphicsView): connection_sliced = QtCore.Signal(list) connection_changed = QtCore.Signal(list, list) insert_node = QtCore.Signal(object, str, dict) + need_show_tab_search = QtCore.Signal() # pass through signals node_selected = QtCore.Signal(str) @@ -207,10 +208,13 @@ def contextMenuEvent(self, event): action.node_id = node.id ctx_menu = ctx_menu or self._ctx_menu - if ctx_menu.isEnabled(): - ctx_menu.exec_(event.globalPos()) + if len(ctx_menu.actions()) > 0: + if ctx_menu.isEnabled(): + ctx_menu.exec_(event.globalPos()) + else: + return super(NodeViewer, self).contextMenuEvent(event) else: - return super(NodeViewer, self).contextMenuEvent(event) + self.need_show_tab_search.emit() def mousePressEvent(self, event): if event.button() == QtCore.Qt.LeftButton: @@ -286,7 +290,6 @@ def mouseReleaseEvent(self, event): elif event.button() == QtCore.Qt.MiddleButton: self.MMB_state = False - # hide pipe slicer. if self._SLICER_PIPE.isVisible(): self._on_pipes_sliced(self._SLICER_PIPE.path()) From 953a61e50092c28df3bcf834f2cc8a061612b1b8 Mon Sep 17 00:00:00 2001 From: ArnoChenFx Date: Mon, 10 Feb 2020 00:45:27 +0800 Subject: [PATCH 4/6] small fix --- NodeGraphQt/base/graph.py | 3 +-- NodeGraphQt/base/node.py | 3 +++ NodeGraphQt/widgets/properties.py | 6 +++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/NodeGraphQt/base/graph.py b/NodeGraphQt/base/graph.py index 484ab296..182378f1 100644 --- a/NodeGraphQt/base/graph.py +++ b/NodeGraphQt/base/graph.py @@ -687,8 +687,7 @@ def create_node(self, node_type, name=None, selected=True, color=None, NodeCls = self._node_factory.create_node_instance(node_type) if NodeCls: node = NodeCls() - - node._graph = self + node.set_graph(self) node.model._graph_model = self.model wid_types = node.model.__dict__.pop('_TEMP_property_widget_types') diff --git a/NodeGraphQt/base/node.py b/NodeGraphQt/base/node.py index d7c6cbc2..7cedb3eb 100644 --- a/NodeGraphQt/base/node.py +++ b/NodeGraphQt/base/node.py @@ -125,6 +125,9 @@ def model(self): """ return self._model + def set_graph(self, graph): + self._graph = graph + def set_model(self, model): """ Set the node model. diff --git a/NodeGraphQt/widgets/properties.py b/NodeGraphQt/widgets/properties.py index d66d44c6..dc05f3a1 100644 --- a/NodeGraphQt/widgets/properties.py +++ b/NodeGraphQt/widgets/properties.py @@ -402,7 +402,7 @@ def __init__(self, parent=None): self._step = 1 self._speed = 0.1 - self.textChanged.connect(self._on_text_changed) + self.editingFinished.connect(self._on_text_changed) self.menu = _valueMenu() self.menu.mouseMove.connect(self.mouseMoveEvent) @@ -413,7 +413,7 @@ def __init__(self, parent=None): self.set_data_type(float) - def _on_text_changed(self, value): + def _on_text_changed(self): self.valueChanged.emit(self.value()) def _reset(self): @@ -429,6 +429,7 @@ def mouseMoveEvent(self, event): delta = event.x() - self.pre_x value = self.pre_val + int(delta*self._speed) * self._step self.setValue(value) + self._on_text_changed() super(_valueEdit,self).mouseMoveEvent(event) @@ -543,7 +544,6 @@ def _set_slider_value(self,value): elif value > _max and self._slider.value() != _max: self._slider.setValue(_max) - def set_min(self, value=0): self._slider.setMinimum(int(value*self._mul)) From 4f6e39237df1f003a7a319ce98a12c4b4fdef7a8 Mon Sep 17 00:00:00 2001 From: ArnoChenFx Date: Mon, 10 Feb 2020 21:22:53 +0800 Subject: [PATCH 5/6] fix slider eidt bug --- NodeGraphQt/widgets/properties.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/NodeGraphQt/widgets/properties.py b/NodeGraphQt/widgets/properties.py index dc05f3a1..4d5c8102 100644 --- a/NodeGraphQt/widgets/properties.py +++ b/NodeGraphQt/widgets/properties.py @@ -518,18 +518,19 @@ def __init__(self, parent=None): self.set_data_type(float) self._lock = False - def _on_edit_changed(self,value): + def _on_edit_changed(self, value): self._set_slider_value(value) self.valueChanged.emit(self._edit.value()) - def _on_slider_changed(self,value): + def _on_slider_changed(self, value): if self._lock: self._lock = False return value = value / float(self._mul) self._edit.setValue(value) + self._on_edit_changed(value) - def _set_slider_value(self,value): + def _set_slider_value(self, value): value = int(value * self._mul) if value == self._slider.value(): @@ -567,6 +568,7 @@ def value(self): def setValue(self,value): self._edit.setValue(value) + self._on_edit_changed(value) class _doubleSpinBox(QtWidgets.QDoubleSpinBox): From 0aed7c6284c1c50f212694a6f2181d1e9c2de8dd Mon Sep 17 00:00:00 2001 From: Leandro Inocencio Date: Tue, 11 Feb 2020 12:45:12 -0500 Subject: [PATCH 6/6] Generate color based on strings, cryptomatte style --- example_auto_nodes/node_base/auto_node.py | 33 ++++++++++++++--------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/example_auto_nodes/node_base/auto_node.py b/example_auto_nodes/node_base/auto_node.py index fc6b5159..9a128270 100644 --- a/example_auto_nodes/node_base/auto_node.py +++ b/example_auto_nodes/node_base/auto_node.py @@ -2,19 +2,27 @@ from NodeGraphQt.base.port import Port from NodeGraphQt.constants import NODE_PROP from NodeGraphQt import QtCore -import random +import hashlib import copy import time -def rand_color(seed_type): - seed = id(seed_type) - random.seed(seed + 10) - r = random.randint(50, 200) - random.seed(seed + 5) - g = random.randint(50, 200) - random.seed(seed + 3421) - b = random.randint(50, 200) - return (r, g, b, 255) + +# Generate random color based on strings +class CryptoColors(object): + def __init__(self): + self.colors = {} + + def get(self, text, Min=50, Max=200): + if text in self.colors: + return self.colors[text] + h = hashlib.sha256(text.encode('utf-8')).hexdigest() + d = int('0xFFFFFFFFFFFFFFFF', 0) + r = int(Min + (int("0x" + h[:16], 0) / d) * (Max - Min)) + g = int(Min + (int("0x" + h[16:32], 0) / d) * (Max - Min)) + b = int(Min + (int("0x" + h[32:48], 0) / d) * (Max - Min)) + a = int(Min + (int("0x" + h[48:], 0) / d) * (Max - Min)) + self.colors[text] = (r, g, b, 255) + return self.colors[text] class AutoNode(BaseNode,QtCore.QObject): @@ -29,6 +37,7 @@ def __init__(self, defaultInputType=None, defaultOutputType=None): self.matchTypes = [[float, int]] self.errorColor = (200, 50, 50) self.stopCookColor = (200, 200, 200) + self._cryptoColors = CryptoColors() self.defaultColor = self.get_property("color") self.defaultValue = None @@ -186,8 +195,8 @@ def set_port_type(self, port, value_type): else: current_port.DataType = value_type - current_port.border_color = rand_color(value_type) - current_port.color = rand_color(value_type) + current_port.border_color = self._cryptoColors.get(str(value_type)) + current_port.color = self._cryptoColors.get(str(value_type)) conn_type = 'multi' if current_port.multi_connection() else 'single' data_type_name = value_type.__name__ if value_type else "all" current_port.view.setToolTip('{}: {} ({}) '.format(current_port.name(), data_type_name, conn_type))