From b605a11eb53c62e218d4926fc7327194a6eb64b0 Mon Sep 17 00:00:00 2001 From: Leandro Inocencio Date: Tue, 28 Jan 2020 11:11:29 -0500 Subject: [PATCH 01/10] Load example from .nodes (.json) --- example.nodes | 352 ++++++++++++++++++++++++++++++++++++++++++ example_math_nodes.py | 34 +--- 2 files changed, 354 insertions(+), 32 deletions(-) create mode 100644 example.nodes diff --git a/example.nodes b/example.nodes new file mode 100644 index 00000000..2e7dcb67 --- /dev/null +++ b/example.nodes @@ -0,0 +1,352 @@ +{ + "nodes":{ + "0x150ad608":{ + "type_":"Math.MathFunctionsNode", + "icon":null, + "name":"Math Functions A", + "color":[ + 10, + 30, + 32 + ], + "border_color":[ + 74, + 84, + 85, + 255 + ], + "text_color":[ + 254, + 171, + 32 + ], + "disabled":false, + "selected":true, + "width":186.0, + "height":103.0, + "pos":[ + -247.0, + 103.0 + ], + "custom":{ + "funcs":"mul", + "output":8.0, + "x":3.2, + "y":2.5 + } + }, + "0x161e21c8":{ + "type_":"Math.MathFunctionsNode", + "icon":null, + "name":"Math Functions B", + "color":[ + 10, + 30, + 32 + ], + "border_color":[ + 74, + 84, + 85, + 255 + ], + "text_color":[ + 254, + 171, + 32 + ], + "disabled":false, + "selected":true, + "width":185.0, + "height":103.0, + "pos":[ + -256.0, + -188.0 + ], + "custom":{ + "funcs":"add", + "output":66.1415926535898, + "x":63.0, + "y":3.141592653589793 + } + }, + "0x161e2b48":{ + "type_":"Math.MathFunctionsNode", + "icon":null, + "name":"Math Functions C", + "color":[ + 10, + 30, + 32 + ], + "border_color":[ + 74, + 84, + 85, + 255 + ], + "text_color":[ + 254, + 171, + 32 + ], + "disabled":false, + "selected":true, + "width":186.0, + "height":103.0, + "pos":[ + 10.0, + -56.0 + ], + "custom":{ + "funcs":"add", + "output":74.1415926535898, + "x":66.1415926535898, + "y":8.0 + } + }, + "0x161e8508":{ + "type_":"Inputs.DataInputNode", + "icon":null, + "name":"Input A", + "color":[ + 13, + 18, + 23, + 255 + ], + "border_color":[ + 74, + 84, + 85, + 255 + ], + "text_color":[ + 255, + 255, + 255, + 180 + ], + "disabled":false, + "selected":true, + "width":173.0, + "height":91.0, + "pos":[ + -500.0, + 44.0 + ], + "custom":{ + "out":"3.2" + } + }, + "0x161e8d48":{ + "type_":"Inputs.DataInputNode", + "icon":null, + "name":"Input B", + "color":[ + 13, + 18, + 23, + 255 + ], + "border_color":[ + 74, + 84, + 85, + 255 + ], + "text_color":[ + 255, + 255, + 255, + 180 + ], + "disabled":false, + "selected":true, + "width":173.0, + "height":91.0, + "pos":[ + -502.0, + 190.0 + ], + "custom":{ + "out":"2.5" + } + }, + "0x161ed4c8":{ + "type_":"Viewers.DataViewerNode", + "icon":null, + "name":"Output", + "color":[ + 13, + 18, + 23, + 255 + ], + "border_color":[ + 74, + 84, + 85, + 255 + ], + "text_color":[ + 255, + 255, + 255, + 180 + ], + "disabled":false, + "selected":true, + "width":170, + "height":91.0, + "pos":[ + 290.0, + -136.0 + ], + "custom":{ + "data":"74.1415926535898" + } + }, + "0x161f41c8":{ + "type_":"Inputs.TickTimeNode", + "icon":null, + "name":"Tick Time", + "color":[ + 13, + 18, + 23, + 255 + ], + "border_color":[ + 74, + 84, + 85, + 255 + ], + "text_color":[ + 255, + 255, + 255, + 180 + ], + "disabled":false, + "selected":true, + "width":173.0, + "height":91.0, + "pos":[ + -514.0, + -246.0 + ], + "custom":{ + "out":"63" + } + }, + "0x1750b048":{ + "type_":"Math.MathFunctionsNode", + "icon":null, + "name":"Math Functions C 1", + "color":[ + 10, + 30, + 32 + ], + "border_color":[ + 74, + 84, + 85, + 255 + ], + "text_color":[ + 254, + 171, + 32 + ], + "disabled":false, + "selected":true, + "width":185.66666666666669, + "height":103.0, + "pos":[ + -528.8333333333335, + -110.5 + ], + "custom":{ + "funcs":"pi", + "output":3.141592653589793, + "x":86.2, + "y":5.7 + } + } + }, + "connections":[ + { + "in":[ + "0x150ad608", + "x" + ], + "out":[ + "0x161e8508", + "out" + ] + }, + { + "in":[ + "0x150ad608", + "y" + ], + "out":[ + "0x161e8d48", + "out" + ] + }, + { + "out":[ + "0x150ad608", + "output" + ], + "in":[ + "0x161e2b48", + "y" + ] + }, + { + "in":[ + "0x161e21c8", + "x" + ], + "out":[ + "0x161f41c8", + "out" + ] + }, + { + "in":[ + "0x161e21c8", + "y" + ], + "out":[ + "0x1750b048", + "output" + ] + }, + { + "out":[ + "0x161e21c8", + "output" + ], + "in":[ + "0x161e2b48", + "x" + ] + }, + { + "out":[ + "0x161e2b48", + "output" + ], + "in":[ + "0x161ed4c8", + "data" + ] + } + ] +} \ No newline at end of file diff --git a/example_math_nodes.py b/example_math_nodes.py index efb23ac2..c6206380 100644 --- a/example_math_nodes.py +++ b/example_math_nodes.py @@ -40,37 +40,7 @@ def show_nodes_list(node): graph.node_double_clicked.connect(show_nodes_list) # registered nodes. - for n in Nodes: - graph.register_node(n) - - mathNodeA = graph.create_node('Math.MathFunctionsNode', - name='Math Functions A', - color='#0a1e20', - text_color='#feab20', - pos=[-250, 70]) - - mathNodeB = graph.create_node('Math.MathFunctionsNode', - name='Math Functions B', - color='#0a1e20', - text_color='#feab20', - pos=[-250, -70]) - - mathNodeC = graph.create_node('Math.MathFunctionsNode', - name='Math Functions C', - color='#0a1e20', - text_color='#feab20', - pos=[0, 0]) - - inputANode = graph.create_node('Inputs.DataInputNode', - name='Input A', - pos=[-500, -50]) - - inputBNode = graph.create_node('Inputs.DataInputNode', - name='Input B', - pos=[-500, 50]) - - outputNode = graph.create_node('Viewers.DataViewerNode', - name='Output', - pos=[250, 0]) + [graph.register_node(n) for n in Nodes] + graph.load_session('example.nodes') app.exec_() From 292564ffc112cd2b50fdb8044d4587b77e984ac4 Mon Sep 17 00:00:00 2001 From: Leandro Inocencio Date: Tue, 28 Jan 2020 11:12:13 -0500 Subject: [PATCH 02/10] cleanup --- example_nodes/input_nodes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example_nodes/input_nodes.py b/example_nodes/input_nodes.py index b1a4c733..87c97022 100644 --- a/example_nodes/input_nodes.py +++ b/example_nodes/input_nodes.py @@ -27,7 +27,7 @@ class TickTimeNode(BaseNode): def __init__(self): super(TickTimeNode, self).__init__() self.add_output('out') - self.add_text_input('out', 'Data Input', text='0', tab='widgets') + self.add_text_input('out', 'Ticks', text='0', tab='widgets') self.view.widgets['out'].value_changed.connect(self.update_streams) self.timer = QtCore.QTimer() From 176fb59a5e603cc86820671e37ad84e6c5b82ebd Mon Sep 17 00:00:00 2001 From: Leandro Inocencio Date: Tue, 28 Jan 2020 12:45:38 -0500 Subject: [PATCH 03/10] add ObjectWrapper Node --- example_nodes/util_nodes.py | 130 ++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 example_nodes/util_nodes.py diff --git a/example_nodes/util_nodes.py b/example_nodes/util_nodes.py new file mode 100644 index 00000000..9ff490b5 --- /dev/null +++ b/example_nodes/util_nodes.py @@ -0,0 +1,130 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +import inspect +from NodeGraphQt import BaseNode + + +class ObjectWrapperNode(BaseNode): + """ + Take an object from the input port and wrappe it. + """ + + # set a unique node identifier. + __identifier__ = 'Util' + + # set the initial default node name. + NODE_NAME = 'Object Wrapper' + + def __init__(self): + super(ObjectWrapperNode, self).__init__() + self.selfPort = self.add_input('self') + self.create_property('self', None) + + def buildNode(self): + obj = self.get_property('self') + if obj: + self.set_name(obj.__class__.__name__.capitalize()) + else: + self.set_name('Object Wrapper (None)') + + # switch math function type + if 'methods' not in self.view.widgets: + self.add_combo_menu('methods', + 'Methods', + items=dir(obj), + tab='widgets') + + self.view.widgets['methods'].value_changed.connect( + self.addFunction) + self.view.widgets['methods'].value_changed.connect( + self.update_streams) + self.add_output('output') + self.create_property('output', None) + else: + comboBox = self.view.widgets['methods'].widget + comboBox.clear() + comboBox.addItems(dir(obj)) + + def addFunction(self, prop, func): + """ + Create inputs based on math functions arguments. + """ + self.funcName = func + obj = self.get_property('self') + func = getattr(obj, self.funcName) + dataFunc = inspect.signature(func) + + for arg in dataFunc.args: + if not self.has_property(arg): + inPort = self.add_input(arg) + self.create_property(arg, None) + + for inPort in self._inputs: + if inPort.name() in dataFunc.args: + if not inPort.visible(): + inPort.set_visible(True) + else: + inPort.set_visible(False) + + def getSelf(self): + for from_port in self.selfPort.connected_ports(): + return from_port.node().get_property(from_port.name()) + + def run(self): + """ + Evaluate all entries, pass them as arguments of the + chosen mathematical function. + """ + obj = self.getSelf() + if not obj: + return + + for to_port in self.input_ports(): + if to_port.visible() == False: + continue + + from_ports = to_port.connected_ports() + if not from_ports: + raise Exception('Port %s not connected!' % to_port.name(), + to_port) + + for from_port in from_ports: + if from_port.name() == 'self': + obj = from_port.node().get_property(from_port.name()) + continue + from_port.node().run() + data = from_port.node().get_property(from_port.name()) + self.set_property(to_port.name(), data) + + self.func = getattr(obj, self.funcName) + + try: + # Execute math function with arguments. + data = self.func(*[ + self.get_property(inport.name()) for inport in self._inputs + if inport.visible() and inport.name() != 'self' + ]) + + self.set_property('output', data) + except KeyError as error: + print("An input is missing! %s" % str(error)) + except TypeError as error: + print("Error evaluating function: %s" % str(error)) + + def on_input_connected(self, to_port, from_port): + """Override node callback method.""" + from_port.node().run() + outValue = from_port.node().get_property(from_port.name()) + self.set_property(to_port.name(), outValue) + + if to_port.name() == 'self': + self.buildNode() + self.update_streams() + + def on_input_disconnected(self, to_port, from_port): + """Override node callback method.""" + self.set_property('self', None) + self.set_property('output', None) + comboBox = self.view.widgets['methods'].widget + comboBox.clear() + self.update_streams() From a940e98a568b95debfa36f0b098f405f8e08cf08 Mon Sep 17 00:00:00 2001 From: Leandro Inocencio Date: Wed, 29 Jan 2020 12:46:11 -0500 Subject: [PATCH 04/10] We cannot inspect the buildin functions, but we can wrap them. --- example_nodes/math_node.py | 13 +------- example_nodes/wrappers/__init__.py | 0 example_nodes/wrappers/math.py | 53 ++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 12 deletions(-) create mode 100644 example_nodes/wrappers/__init__.py create mode 100644 example_nodes/wrappers/math.py diff --git a/example_nodes/math_node.py b/example_nodes/math_node.py index 65969ec2..22e867a3 100644 --- a/example_nodes/math_node.py +++ b/example_nodes/math_node.py @@ -1,19 +1,8 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -import math +import example_nodes.wrappers.math as math import inspect from functools import partial - -# add basic math functions to math library -math.add = lambda x, y: x + y -math.sub = lambda x, y: x - y -math.mul = lambda x, y: x * y -math.div = lambda x, y: x / y - -# Transform float to functions -for constant in ['pi', 'e', 'tau', 'inf', 'nan']: - setattr(math, constant, partial(lambda x: x, getattr(math, constant))) - from NodeGraphQt import BaseNode diff --git a/example_nodes/wrappers/__init__.py b/example_nodes/wrappers/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/example_nodes/wrappers/math.py b/example_nodes/wrappers/math.py new file mode 100644 index 00000000..d2dd475a --- /dev/null +++ b/example_nodes/wrappers/math.py @@ -0,0 +1,53 @@ +from math import * + +_pi = pi +_e = e +_tau = tau +_inf = inf +_nan = nan + +# add contants as functions + + +def pi(): + print('pi', _pi) + return _pi + + +def e(): + print('e', _e) + return _e + + +def tau(): + print('tau', _tau) + return _tau + + +def inf(): + print('inf', _inf) + return _inf + + +def nan(): + print('nan', _nan) + return _nan + + +# add basic math functions to math library + + +def add(x, y): + return x + y + + +def sub(x, y): + return x - y + + +def mul(x, y): + return x * y + + +def div(x, y): + return x / y From fb4921675cc2602bd74db0d0cfa51d1333d62bd4 Mon Sep 17 00:00:00 2001 From: Leandro Inocencio Date: Wed, 29 Jan 2020 19:10:52 -0500 Subject: [PATCH 05/10] add logic node If --- example.nodes | 256 +++++++++++++++-------------------- example_nodes/input_nodes.py | 19 +++ example_nodes/logic_nodes.py | 42 ++++++ 3 files changed, 167 insertions(+), 150 deletions(-) create mode 100644 example_nodes/logic_nodes.py diff --git a/example.nodes b/example.nodes index 2e7dcb67..d8cb3bd9 100644 --- a/example.nodes +++ b/example.nodes @@ -1,49 +1,15 @@ { "nodes":{ - "0x150ad608":{ - "type_":"Math.MathFunctionsNode", + "0x1508f548":{ + "type_":"Inputs.DataInputNode", "icon":null, - "name":"Math Functions A", + "name":"Input A", "color":[ - 10, - 30, - 32 - ], - "border_color":[ - 74, - 84, - 85, + 13, + 18, + 23, 255 ], - "text_color":[ - 254, - 171, - 32 - ], - "disabled":false, - "selected":true, - "width":186.0, - "height":103.0, - "pos":[ - -247.0, - 103.0 - ], - "custom":{ - "funcs":"mul", - "output":8.0, - "x":3.2, - "y":2.5 - } - }, - "0x161e21c8":{ - "type_":"Math.MathFunctionsNode", - "icon":null, - "name":"Math Functions B", - "color":[ - 10, - 30, - 32 - ], "border_color":[ 74, 84, @@ -51,33 +17,32 @@ 255 ], "text_color":[ - 254, - 171, - 32 + 255, + 255, + 255, + 180 ], "disabled":false, "selected":true, - "width":185.0, - "height":103.0, + "width":173.0, + "height":91.0, "pos":[ - -256.0, - -188.0 + -417.0, + -160.0 ], "custom":{ - "funcs":"add", - "output":66.1415926535898, - "x":63.0, - "y":3.141592653589793 + "out":"Hola" } }, - "0x161e2b48":{ - "type_":"Math.MathFunctionsNode", + "0x160ea048":{ + "type_":"Inputs.DataInputNode", "icon":null, - "name":"Math Functions C", + "name":"Input B", "color":[ - 10, - 30, - 32 + 13, + 18, + 23, + 255 ], "border_color":[ 74, @@ -86,29 +51,27 @@ 255 ], "text_color":[ - 254, - 171, - 32 + 255, + 255, + 255, + 180 ], "disabled":false, "selected":true, - "width":186.0, - "height":103.0, + "width":173.0, + "height":91.0, "pos":[ - 10.0, - -56.0 + -390.0, + -23.0 ], "custom":{ - "funcs":"add", - "output":74.1415926535898, - "x":66.1415926535898, - "y":8.0 + "out":"Chau" } }, - "0x161e8508":{ - "type_":"Inputs.DataInputNode", + "0x160ea748":{ + "type_":"Viewers.DataViewerNode", "icon":null, - "name":"Input A", + "name":"Output", "color":[ 13, 18, @@ -129,20 +92,20 @@ ], "disabled":false, "selected":true, - "width":173.0, + "width":170, "height":91.0, "pos":[ - -500.0, - 44.0 + 186.0, + -231.0 ], "custom":{ - "out":"3.2" + "data":"Hola" } }, - "0x161e8d48":{ - "type_":"Inputs.DataInputNode", + "0x160f3688":{ + "type_":"Logics.ifNode", "icon":null, - "name":"Input B", + "name":"If", "color":[ 13, 18, @@ -163,24 +126,25 @@ ], "disabled":false, "selected":true, - "width":173.0, - "height":91.0, + "width":170, + "height":108.0, "pos":[ - -502.0, - 190.0 + -75.0, + -178.0 ], "custom":{ - "out":"2.5" + "condition":0.0, + "out":"Hola" } }, - "0x161ed4c8":{ - "type_":"Viewers.DataViewerNode", + "0x160fad08":{ + "type_":"Math.MathFunctionsNode", "icon":null, - "name":"Output", + "name":"Math Functions", "color":[ - 13, - 18, - 23, + 25, + 58, + 51, 255 ], "border_color":[ @@ -197,17 +161,20 @@ ], "disabled":false, "selected":true, - "width":170, - "height":91.0, + "width":181.0, + "height":103.0, "pos":[ - 290.0, - -136.0 + -411.0, + -319.0 ], "custom":{ - "data":"74.1415926535898" + "funcs":"fmod", + "output":1.0, + "x":219.0, + "y":2.0 } }, - "0x161f41c8":{ + "0x17678bc8":{ "type_":"Inputs.TickTimeNode", "icon":null, "name":"Tick Time", @@ -234,21 +201,22 @@ "width":173.0, "height":91.0, "pos":[ - -514.0, - -246.0 + -678.0, + -393.0 ], "custom":{ - "out":"63" + "out":"219" } }, - "0x1750b048":{ - "type_":"Math.MathFunctionsNode", + "0x1768efc8":{ + "type_":"Inputs.DataInputNode", "icon":null, - "name":"Math Functions C 1", + "name":"Basic Input", "color":[ - 10, - 30, - 32 + 13, + 18, + 23, + 255 ], "border_color":[ 74, @@ -257,95 +225,83 @@ 255 ], "text_color":[ - 254, - 171, - 32 + 255, + 255, + 255, + 180 ], "disabled":false, "selected":true, - "width":185.66666666666669, - "height":103.0, + "width":173.0, + "height":91.0, "pos":[ - -528.8333333333335, - -110.5 + -678.0, + -207.0 ], "custom":{ - "funcs":"pi", - "output":3.141592653589793, - "x":86.2, - "y":5.7 + "out":"2" } } }, "connections":[ { - "in":[ - "0x150ad608", - "x" - ], "out":[ - "0x161e8508", + "0x1508f548", "out" - ] - }, - { - "in":[ - "0x150ad608", - "y" ], - "out":[ - "0x161e8d48", - "out" + "in":[ + "0x160f3688", + "then" ] }, { "out":[ - "0x150ad608", - "output" + "0x160ea048", + "out" ], "in":[ - "0x161e2b48", - "y" + "0x160f3688", + "else" ] }, { "in":[ - "0x161e21c8", - "x" + "0x160ea748", + "data" ], "out":[ - "0x161f41c8", + "0x160f3688", "out" ] }, { "in":[ - "0x161e21c8", - "y" + "0x160f3688", + "condition" ], "out":[ - "0x1750b048", + "0x160fad08", "output" ] }, { - "out":[ - "0x161e21c8", - "output" - ], "in":[ - "0x161e2b48", + "0x160fad08", "x" + ], + "out":[ + "0x17678bc8", + "out" ] }, { - "out":[ - "0x161e2b48", - "output" - ], "in":[ - "0x161ed4c8", - "data" + "0x160fad08", + "y" + ], + "out":[ + "0x1768efc8", + "out" ] } ] diff --git a/example_nodes/input_nodes.py b/example_nodes/input_nodes.py index 87c97022..1bc7cf53 100644 --- a/example_nodes/input_nodes.py +++ b/example_nodes/input_nodes.py @@ -66,3 +66,22 @@ def run(self): else: print('No existe %s' % path) self.set_property('output', '') + + +class BoolInputNode(BaseNode): + """ + Input Bool data. + """ + + __identifier__ = 'Inputs' + NODE_NAME = 'Bool' + + def __init__(self): + super(BoolInputNode, self).__init__() + self.add_output('out') + self.create_property('out', None) + self.add_combo_menu('combo', 'Bool value', items=['True', 'False'], tab='widgets') + self.view.widgets['combo'].value_changed.connect(self.update_streams) + + def run(self): + self.set_property('out', eval(self.get_property('combo'))) \ No newline at end of file diff --git a/example_nodes/logic_nodes.py b/example_nodes/logic_nodes.py new file mode 100644 index 00000000..af4cf433 --- /dev/null +++ b/example_nodes/logic_nodes.py @@ -0,0 +1,42 @@ +from NodeGraphQt import BaseNode, QtCore + + +class ifNode(BaseNode): + """ + if node. + """ + + __identifier__ = 'Logics' + NODE_NAME = 'If' + + def __init__(self): + super(ifNode, self).__init__() + self.condition = self.add_input('condition') + self.create_property('condition', None) + self._then = self.add_input('then') + self._else = self.add_input('else') + self.add_output('out') + self.create_property('out', None) + + def run(self): + for port in self.condition.connected_ports(): + port.node().run() + if port.node().get_property(port.name()): + result = self._then + else: + result = self._else + + for port in result.connected_ports(): + port.node().run() + self.set_property('out', port.node().get_property(port.name())) + break + + def on_input_connected(self, to_port, from_port): + """Override node callback method.""" + from_port.node().run() + self.set_property(to_port.name(), from_port.node().get_property(from_port.name())) + self.update_streams() + + def on_input_disconnected(self, to_port, from_port): + """Override node callback method.""" + self.set_property('out', None) From c8acea3b3980de2a242af9f2aad17328c57cdccf Mon Sep 17 00:00:00 2001 From: Leandro Inocencio Date: Wed, 29 Jan 2020 19:13:13 -0500 Subject: [PATCH 06/10] cleanup --- example_nodes/logic_nodes.py | 1 - 1 file changed, 1 deletion(-) diff --git a/example_nodes/logic_nodes.py b/example_nodes/logic_nodes.py index af4cf433..d7340927 100644 --- a/example_nodes/logic_nodes.py +++ b/example_nodes/logic_nodes.py @@ -12,7 +12,6 @@ class ifNode(BaseNode): def __init__(self): super(ifNode, self).__init__() self.condition = self.add_input('condition') - self.create_property('condition', None) self._then = self.add_input('then') self._else = self.add_input('else') self.add_output('out') From c72c08c85d5b7e8a97f00c254af2074eb8c77d4d Mon Sep 17 00:00:00 2001 From: Leandro Inocencio Date: Wed, 29 Jan 2020 19:45:46 -0500 Subject: [PATCH 07/10] evaluate multi streams --- NodeGraphQt/base/node.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NodeGraphQt/base/node.py b/NodeGraphQt/base/node.py index fb6975ec..6e999b12 100644 --- a/NodeGraphQt/base/node.py +++ b/NodeGraphQt/base/node.py @@ -795,7 +795,7 @@ def update_streams(self, *args): for port, nodeList in node.connected_output_nodes().items(): nodes.extend(nodeList) - if not nodes: + if not node.connected_output_nodes(): try: node.run() except Exception as error: From 1191a5719946b3f064597963d8a2b5fb9a529e88 Mon Sep 17 00:00:00 2001 From: Leandro Inocencio Date: Wed, 29 Jan 2020 20:15:13 -0500 Subject: [PATCH 08/10] add boolean logics node --- example.nodes | 211 +++++++---------------------------- example_nodes/logic_nodes.py | 72 +++++++++++- 2 files changed, 109 insertions(+), 174 deletions(-) diff --git a/example.nodes b/example.nodes index d8cb3bd9..104ba0b8 100644 --- a/example.nodes +++ b/example.nodes @@ -1,74 +1,6 @@ { "nodes":{ - "0x1508f548":{ - "type_":"Inputs.DataInputNode", - "icon":null, - "name":"Input A", - "color":[ - 13, - 18, - 23, - 255 - ], - "border_color":[ - 74, - 84, - 85, - 255 - ], - "text_color":[ - 255, - 255, - 255, - 180 - ], - "disabled":false, - "selected":true, - "width":173.0, - "height":91.0, - "pos":[ - -417.0, - -160.0 - ], - "custom":{ - "out":"Hola" - } - }, - "0x160ea048":{ - "type_":"Inputs.DataInputNode", - "icon":null, - "name":"Input B", - "color":[ - 13, - 18, - 23, - 255 - ], - "border_color":[ - 74, - 84, - 85, - 255 - ], - "text_color":[ - 255, - 255, - 255, - 180 - ], - "disabled":false, - "selected":true, - "width":173.0, - "height":91.0, - "pos":[ - -390.0, - -23.0 - ], - "custom":{ - "out":"Chau" - } - }, - "0x160ea748":{ + "0x15095e08":{ "type_":"Viewers.DataViewerNode", "icon":null, "name":"Output", @@ -95,17 +27,17 @@ "width":170, "height":91.0, "pos":[ - 186.0, - -231.0 + 149.0, + -146.0 ], "custom":{ - "data":"Hola" + "data":"" } }, - "0x160f3688":{ - "type_":"Logics.ifNode", + "0x15126848":{ + "type_":"Inputs.BoolInputNode", "icon":null, - "name":"If", + "name":"Bool", "color":[ 13, 18, @@ -127,57 +59,20 @@ "disabled":false, "selected":true, "width":170, - "height":108.0, - "pos":[ - -75.0, - -178.0 - ], - "custom":{ - "condition":0.0, - "out":"Hola" - } - }, - "0x160fad08":{ - "type_":"Math.MathFunctionsNode", - "icon":null, - "name":"Math Functions", - "color":[ - 25, - 58, - 51, - 255 - ], - "border_color":[ - 74, - 84, - 85, - 255 - ], - "text_color":[ - 255, - 255, - 255, - 180 - ], - "disabled":false, - "selected":true, - "width":181.0, "height":103.0, "pos":[ - -411.0, - -319.0 + -413.0, + -212.0 ], "custom":{ - "funcs":"fmod", - "output":1.0, - "x":219.0, - "y":2.0 + "out":true, + "combo":"True" } }, - "0x17678bc8":{ - "type_":"Inputs.TickTimeNode", + "0x15140308":{ + "type_":"Logics.BooleanNode", "icon":null, - "name":"Tick Time", + "name":"Boolean", "color":[ 13, 18, @@ -198,20 +93,21 @@ ], "disabled":false, "selected":true, - "width":173.0, - "height":91.0, + "width":170, + "height":103.0, "pos":[ - -678.0, - -393.0 + -143.0, + -149.0 ], "custom":{ - "out":"219" + "out":null, + "funcs":"and" } }, - "0x1768efc8":{ - "type_":"Inputs.DataInputNode", + "0x1514a4c8":{ + "type_":"Inputs.BoolInputNode", "icon":null, - "name":"Basic Input", + "name":"Bool 1", "color":[ 13, 18, @@ -232,75 +128,46 @@ ], "disabled":false, "selected":true, - "width":173.0, - "height":91.0, + "width":170, + "height":103.0, "pos":[ - -678.0, - -207.0 + -411.25, + -61.5 ], "custom":{ - "out":"2" + "out":true, + "combo":"True" } } }, "connections":[ - { - "out":[ - "0x1508f548", - "out" - ], - "in":[ - "0x160f3688", - "then" - ] - }, - { - "out":[ - "0x160ea048", - "out" - ], - "in":[ - "0x160f3688", - "else" - ] - }, { "in":[ - "0x160ea748", + "0x15095e08", "data" ], "out":[ - "0x160f3688", + "0x15140308", "out" ] }, { - "in":[ - "0x160f3688", - "condition" - ], "out":[ - "0x160fad08", - "output" - ] - }, - { - "in":[ - "0x160fad08", - "x" - ], - "out":[ - "0x17678bc8", + "0x15126848", "out" + ], + "in":[ + "0x15140308", + "a" ] }, { "in":[ - "0x160fad08", - "y" + "0x15140308", + "b" ], "out":[ - "0x1768efc8", + "0x1514a4c8", "out" ] } diff --git a/example_nodes/logic_nodes.py b/example_nodes/logic_nodes.py index d7340927..5715ffdb 100644 --- a/example_nodes/logic_nodes.py +++ b/example_nodes/logic_nodes.py @@ -1,7 +1,7 @@ from NodeGraphQt import BaseNode, QtCore -class ifNode(BaseNode): +class IfNode(BaseNode): """ if node. """ @@ -10,7 +10,7 @@ class ifNode(BaseNode): NODE_NAME = 'If' def __init__(self): - super(ifNode, self).__init__() + super(IfNode, self).__init__() self.condition = self.add_input('condition') self._then = self.add_input('then') self._else = self.add_input('else') @@ -39,3 +39,71 @@ def on_input_connected(self, to_port, from_port): def on_input_disconnected(self, to_port, from_port): """Override node callback method.""" self.set_property('out', None) + + +class BooleanNode(BaseNode): + """ + Boolean Logic funtions node. + """ + + __identifier__ = 'Logics' + + NODE_NAME = 'Boolean' + + logics = {'and': 'a and b', + 'or': 'a or b', + 'xor': '(not a and b) or (a and not b)', + 'not': 'not a'} + + def __init__(self): + super(BooleanNode, self).__init__() + self.a = self.add_input('a') + self.b = self.add_input('b') + self.add_output('out') + self.create_property('out', None) + self.add_combo_menu('funcs', + 'Functions', + items=list(self.logics.keys()), + tab='widgets') + self.func = logics['and'] + # switch math function type + self.view.widgets['funcs'].value_changed.connect(self.addFunction) + self.view.widgets['funcs'].value_changed.connect(self.update_streams) + + def addFunction(self, prop, func): + """ + Create inputs based on math functions arguments. + """ + self.func = logics[func] + if self.b.visible() and not 'b' in self.func: + self.b.set_visible(False) + elif not self.b.visible(): + self.b.set_visible(True) + + def run(self): + a = None + b = None + + for port in self.a.connected_ports(): + port.node().run() + a = port.node().get_property(port.name()) + + for port in self.b.connected_ports(): + port.node().run() + b = port.node().get_property(port.name()) + + if a is None or (b is None and 'b' in self.func): + raise Exception("No inputs!") + + self.set_property('out', eval(self.func)) + + def on_input_connected(self, to_port, from_port): + """Override node callback method.""" + from_port.node().run() + result = from_port.node().get_property(from_port.name()) + self.set_property(to_port.name(), result) + self.update_streams() + + def on_input_disconnected(self, to_port, from_port): + """Override node callback method.""" + self.set_property('out', None) From 43073838b598d2f2640ddacb8ed3607c16fe11fe Mon Sep 17 00:00:00 2001 From: Leandro Inocencio Date: Wed, 29 Jan 2020 20:18:52 -0500 Subject: [PATCH 09/10] fix --- example_nodes/logic_nodes.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/example_nodes/logic_nodes.py b/example_nodes/logic_nodes.py index 5715ffdb..6ea49a30 100644 --- a/example_nodes/logic_nodes.py +++ b/example_nodes/logic_nodes.py @@ -65,7 +65,8 @@ def __init__(self): 'Functions', items=list(self.logics.keys()), tab='widgets') - self.func = logics['and'] + + self.func = self.logics['and'] # switch math function type self.view.widgets['funcs'].value_changed.connect(self.addFunction) self.view.widgets['funcs'].value_changed.connect(self.update_streams) @@ -74,7 +75,7 @@ def addFunction(self, prop, func): """ Create inputs based on math functions arguments. """ - self.func = logics[func] + self.func = self.logics[func] if self.b.visible() and not 'b' in self.func: self.b.set_visible(False) elif not self.b.visible(): From 22f68d33534683c380a36afb0c81a6be28de0e77 Mon Sep 17 00:00:00 2001 From: Leandro Inocencio Date: Thu, 30 Jan 2020 16:20:38 -0500 Subject: [PATCH 10/10] add wrappers for build-in modules --- example_auto_nodes/module_nodes.py | 34 ++--- example_auto_nodes/wrappers/__init__.py | 0 example_auto_nodes/wrappers/dict.py | 45 +++++++ example_auto_nodes/wrappers/list.py | 52 +++++++ example_auto_nodes/wrappers/math.py | 52 +++++++ example_auto_nodes/wrappers/str.py | 171 ++++++++++++++++++++++++ example_auto_nodes/wrappers/tuple.py | 11 ++ 7 files changed, 342 insertions(+), 23 deletions(-) create mode 100644 example_auto_nodes/wrappers/__init__.py create mode 100644 example_auto_nodes/wrappers/dict.py create mode 100644 example_auto_nodes/wrappers/list.py create mode 100644 example_auto_nodes/wrappers/math.py create mode 100644 example_auto_nodes/wrappers/str.py create mode 100644 example_auto_nodes/wrappers/tuple.py diff --git a/example_auto_nodes/module_nodes.py b/example_auto_nodes/module_nodes.py index 7531db13..915266a6 100644 --- a/example_auto_nodes/module_nodes.py +++ b/example_auto_nodes/module_nodes.py @@ -2,7 +2,6 @@ get_functions_from_module, get_functions_from_type) -import math import os import sys import random @@ -10,19 +9,11 @@ import numpydoc.docscrape import inspect -# add basic math functions to math library -math.add = lambda x, y: x + y -math.sub = lambda x, y: x - y -math.mul = lambda x, y: x * y -math.div = lambda x, y: x / y - - -def get_value(self,index): - return self[index] - - -def get_item(self,index): - return self.items()[index] +import example_auto_nodes.wrappers.math as _math +import example_auto_nodes.wrappers.list as _list +import example_auto_nodes.wrappers.dict as _dict +import example_auto_nodes.wrappers.str as _str +import example_auto_nodes.wrappers.tuple as _tuple class MathModuleNode(ModuleNode): @@ -36,7 +27,7 @@ class MathModuleNode(ModuleNode): # set the initial default node name. NODE_NAME = 'math module' - module_functions = get_functions_from_type(math) + module_functions = get_functions_from_type(_math) def __init__(self): super(MathModuleNode, self).__init__(float, float) @@ -162,8 +153,8 @@ class StringFunctionsNode(ModuleNode): # set the initial default node name. NODE_NAME = 'String Functions' - module_functions = get_functions_from_type(str) - module_functions["get value"] = get_value + module_functions = get_functions_from_type(_str) + def __init__(self): super(StringFunctionsNode, self).__init__() @@ -180,8 +171,7 @@ class ListFunctionsNode(ModuleNode): # set the initial default node name. NODE_NAME = 'List Functions' - module_functions = get_functions_from_type(list) - module_functions["get value"] = get_value + module_functions = get_functions_from_type(_list) def __init__(self): super(ListFunctionsNode, self).__init__() @@ -198,8 +188,7 @@ class DictFunctionsNode(ModuleNode): # set the initial default node name. NODE_NAME = 'Dict Functions' - module_functions = get_functions_from_type(list) - module_functions["get item"] = get_item + module_functions = get_functions_from_type(_dict) def __init__(self): super(DictFunctionsNode, self).__init__() @@ -216,8 +205,7 @@ class TupleFunctionsNode(ModuleNode): # set the initial default node name. NODE_NAME = 'Tuple Functions' - module_functions = get_functions_from_type(tuple) - module_functions["get value"] = get_value + module_functions = get_functions_from_type(_tuple) def __init__(self): super(TupleFunctionsNode, self).__init__() diff --git a/example_auto_nodes/wrappers/__init__.py b/example_auto_nodes/wrappers/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/example_auto_nodes/wrappers/dict.py b/example_auto_nodes/wrappers/dict.py new file mode 100644 index 00000000..5775e3fa --- /dev/null +++ b/example_auto_nodes/wrappers/dict.py @@ -0,0 +1,45 @@ +def clear(self): + self.clear() + return self + + +def copy(self): + return self.copy() + + +def fromkeys(self, iterable, value=None): + return self.fromkeys(iterable, value) + + +def get(self, key, default=None): + return self.get(key, default) + + +def items(self): + return list(self.items()) + + +def keys(self): + return list(self.keys()) + + +def pop(self, index): + return self.pop(index) + + +def popitem(self): + return self.popitem() + + +def setdefault(self, key, default=None): + self.setdefault(key, default) + return self + + +def update(self, e): + self.update(e) + return self + + +def values(self): + return list(self.values()) diff --git a/example_auto_nodes/wrappers/list.py b/example_auto_nodes/wrappers/list.py new file mode 100644 index 00000000..50a8daae --- /dev/null +++ b/example_auto_nodes/wrappers/list.py @@ -0,0 +1,52 @@ +def append(self, object): + self.append(object) + return self + + +def clear(self): + self.clear() + return self + + +def copy(self): + return self.copy() + + +def count(self, value): + return self.count(value) + + +def extend(self, iterable): + self.extend(iterable) + return self + +def index(self, value): + return self.index(value) + + +def insert(self, index, obj): + self.insert(index, obj) + return self + + +def pop(self, index=-1): + return self.pop(index) + + +def remove(self, value): + return self.remove(value) + + +def reverse(self): + self.reverse() + return self + + +def sort(self): + self.sort() + return self + + +# custom functions +def get(self, index): + return self.__getitem__(index) diff --git a/example_auto_nodes/wrappers/math.py b/example_auto_nodes/wrappers/math.py new file mode 100644 index 00000000..c0e4cc66 --- /dev/null +++ b/example_auto_nodes/wrappers/math.py @@ -0,0 +1,52 @@ +from math import * + +_pi = pi +_e = e +_tau = tau +_inf = inf +_nan = nan + + +# add contants as functions + +def pi(): + print('pi', _pi) + return _pi + + +def e(): + print('e', _e) + return _e + + +def tau(): + print('tau', _tau) + return _tau + + +def inf(): + print('inf', _inf) + return _inf + + +def nan(): + print('nan', _nan) + return _nan + + +# add basic math functions to math library + +def add(x, y): + return x + y + + +def sub(x, y): + return x - y + + +def mul(x, y): + return x * y + + +def div(x, y): + return x / y diff --git a/example_auto_nodes/wrappers/str.py b/example_auto_nodes/wrappers/str.py new file mode 100644 index 00000000..8c23726d --- /dev/null +++ b/example_auto_nodes/wrappers/str.py @@ -0,0 +1,171 @@ + +def capitalize(self): + return self.capitalize() + + +def casefold(self): + return self.casefold() + + +def center(self, width, fillchar=" "): + return self.center(width, fillchar) + + +def count(self, sub, start=0, end=-1): + return self.count(sub, start, end) + + +def encode(self, encoding, errors): + return self.encode(encoding, errors) + + +def endswith(self, suffix, start=0, end=-1): + return self.endswith(suffix, start, end) + + +def expandtabs(self, tabsize=8): + return self.expandtabs(tabsize) + + +def find(self, sub, start=0, end=-1): + return self.find(sub, start, end) + + +def format(self, *args, **kwargs): + return self.format(*args, **kwargs) + + +def index(self, sub, start=0, end=-1): + return self.index(sub, start, end) + + +def isalnum(self): + return self.isalnum() + + +def isalpha(self): + return self.isalpha() + + +def isascii(self): + return self.isascii() + + +def isdecimal(self): + return self.isdecimal() + + +def isdigit(self): + return self.isdigit() + + +def isidentifier(self): + return self.isidentifier() + + +def islower(self): + return self.islower() + + +def isnumeric(self): + return self.isnumeric() + + +def isprintable(self): + return self.isprintable() + + +def isspace(self): + return self.isspace() + + +def istitle(self): + return self.istitle() + + +def isupper(self): + return self.isupper() + + +def join(self, iterable): + return self.join(iterable) + + +def ljust(self, width, fillchar=" "): + return self.ljust(width, fillchar) + + +def lower(self): + return self.lower() + + +def lstrip(self, chars=" "): + return self.lstrip(chars) + + +def partition(self, sep): + return self.partition(sep) + + +def replace(self, old, new, count=-1): + return self.replace(old, new, count) + + +def rfind(self, sub, start=0, end=-1): + return self.rfind(sub, start, end) + + +def rindex(self, sub, start=0, end=-1): + return self.rindex(sub, start, end) + + +def rjust(self, width, fillchar=" "): + return self.rjust(width, fillchar) + + +def rpartition(self, sep): + return self.rpartition(sep) + + +def rsplit(self, sep, maxsplit=-1): + return self.rsplit(sep, maxsplit) + + +def rstrip(self, chars=" "): + return self.rstrip(chars) + + +def split(self, sep, maxsplit=-1): + return self.split(sep, maxsplit) + + +def splitlines(self, keepends): + return self.splitlines(keepends) + + +def startswith(self, prefix, start=0, end=-1): + return self.startswith(prefix, start, end) + + +def strip(self, chars=" "): + return self.strip(chars) + + +def swapcase(self): + return self.swapcase() + + +def title(self): + return self.title() + + +def translate(self, table): + return self.translate(table) + + +def upper(self): + return self.upper() + + +def zfill(self, width): + return self.zfill(width) diff --git a/example_auto_nodes/wrappers/tuple.py b/example_auto_nodes/wrappers/tuple.py new file mode 100644 index 00000000..1a8af60c --- /dev/null +++ b/example_auto_nodes/wrappers/tuple.py @@ -0,0 +1,11 @@ +def count(self, value): + return self.count(value) + + +def index(self, value): + return self.index(value) + + +# custom functions +def get(self, index): + return self.__getitem__(index)