|
1 | 1 | #!/usr/bin/python |
2 | 2 | # -*- coding: utf-8 -*- |
3 | | -import math |
4 | | -import inspect |
5 | | -from functools import partial |
6 | | - |
7 | | -# add basic math functions to math library |
8 | | -math.add = lambda x, y: x + y |
9 | | -math.sub = lambda x, y: x - y |
10 | | -math.mul = lambda x, y: x * y |
11 | | -math.div = lambda x, y: x / y |
12 | | - |
13 | | -# Transform float to functions |
14 | | -for constant in ['pi', 'e', 'tau', 'inf', 'nan']: |
15 | | - setattr(math, constant, partial(lambda x: x, getattr(math, constant))) |
16 | | - |
17 | | - |
| 3 | +import example_nodes as Nodes |
18 | 4 | from NodeGraphQt import (NodeGraph, |
19 | 5 | BaseNode, |
20 | 6 | setup_context_menu) |
21 | 7 | from NodeGraphQt import QtWidgets, QtCore, PropertiesBinWidget, NodeTreeWidget |
22 | 8 |
|
23 | 9 |
|
24 | | -class DataInputNode(BaseNode): |
25 | | - """ |
26 | | - Input node data. |
27 | | - """ |
28 | | - |
29 | | - __identifier__ = 'com.chantasticvfx' |
30 | | - NODE_NAME = 'Input Numbers' |
31 | | - |
32 | | - def __init__(self): |
33 | | - super(DataInputNode, self).__init__() |
34 | | - self.add_output('out') |
35 | | - self.add_text_input('out', 'Data Output', text='0.4', tab='widgets') |
36 | | - self.view.widgets['out'].value_changed.connect(self.update_streams) |
37 | | - |
38 | | - |
39 | | -class MathFunctionsNode(BaseNode): |
40 | | - """ |
41 | | - Math functions node. |
42 | | - """ |
43 | | - |
44 | | - # set a unique node identifier. |
45 | | - __identifier__ = 'com.chantasticvfx' |
46 | | - |
47 | | - # set the initial default node name. |
48 | | - NODE_NAME = 'Functions node' |
49 | | - |
50 | | - mathFuncs = [func for func in dir(math) if not func.startswith('_')] |
51 | | - |
52 | | - def __init__(self): |
53 | | - super(MathFunctionsNode, self).__init__() |
54 | | - self.set_color(25, 58, 51) |
55 | | - self.add_combo_menu('funcs', 'Functions', items=self.mathFuncs, |
56 | | - tab='widgets') |
57 | | - |
58 | | - # switch math function type |
59 | | - self.view.widgets['funcs'].value_changed.connect(self.addFunction) |
60 | | - self.view.widgets['funcs'].value_changed.connect(self.update_streams) |
61 | | - self.add_output('output') |
62 | | - self.create_property('output', None) |
63 | | - self.trigger_type = 'no_inPorts' |
64 | | - |
65 | | - self.view.widgets['funcs'].widget.setCurrentIndex(2) |
66 | | - |
67 | | - def addFunction(self, prop, func): |
68 | | - """ |
69 | | - Create inputs based on math functions arguments. |
70 | | - """ |
71 | | - self.func = getattr(math, func) |
72 | | - dataFunc = inspect.getfullargspec(self.func) |
73 | | - |
74 | | - for arg in dataFunc.args: |
75 | | - if not self.has_property(arg): |
76 | | - inPort = self.add_input(arg) |
77 | | - inPort.trigger = True |
78 | | - self.create_property(arg, None) |
79 | | - |
80 | | - for inPort in self._inputs: |
81 | | - if inPort.name() in dataFunc.args: |
82 | | - if not inPort.visible(): |
83 | | - inPort.set_visible(True) |
84 | | - else: |
85 | | - inPort.set_visible(False) |
86 | | - |
87 | | - def run(self): |
88 | | - """ |
89 | | - Evaluate all entries, pass them as arguments of the |
90 | | - chosen mathematical function. |
91 | | - """ |
92 | | - for to_port in self.input_ports(): |
93 | | - if to_port.visible() == False: |
94 | | - continue |
95 | | - from_ports = to_port.connected_ports() |
96 | | - if not from_ports: |
97 | | - raise Exception('Port %s not connected!' % to_port.name(), |
98 | | - to_port) |
99 | | - |
100 | | - for from_port in from_ports: |
101 | | - from_port.node().run() |
102 | | - data = from_port.node().get_property(from_port.name()) |
103 | | - self.set_property(to_port.name(), float(data)) |
104 | | - |
105 | | - try: |
106 | | - # Execute math function with arguments. |
107 | | - data = self.func(*[self.get_property(inport.name()) for inport in self._inputs if inport.visible()]) |
108 | | - |
109 | | - self.set_property('output', data) |
110 | | - except KeyError as error: |
111 | | - print("An input is missing! %s" % str(error)) |
112 | | - except TypeError as error: |
113 | | - print("Error evaluating function: %s" % str(error)) |
114 | | - |
115 | | - def on_input_connected(self, to_port, from_port): |
116 | | - """Override node callback method.""" |
117 | | - self.set_property(to_port.name(), from_port.node().run()) |
118 | | - self.update_streams() |
119 | | - |
120 | | - def on_input_disconnected(self, to_port, from_port): |
121 | | - """Override node callback method.""" |
122 | | - self.set_property('output', None) |
123 | | - self.update_streams() |
124 | | - |
125 | | - |
126 | | -class DataViewerNode(BaseNode): |
127 | | - __identifier__ = 'com.chantasticvfx' |
128 | | - NODE_NAME = 'Result View' |
129 | | - |
130 | | - def __init__(self): |
131 | | - super(DataViewerNode, self).__init__() |
132 | | - self.inPort = self.add_input('data') |
133 | | - self.add_text_input('data', 'Data Viewer', tab='widgets') |
134 | | - |
135 | | - def run(self): |
136 | | - """Evaluate input to show it.""" |
137 | | - for source in self.inPort.connected_ports(): |
138 | | - from_node = source.node() |
139 | | - try: |
140 | | - from_node.run() |
141 | | - except Exception as error: |
142 | | - print("%s no inputs connected: %s" % (from_node.name(), str(error))) |
143 | | - self.set_property('data', None) |
144 | | - return |
145 | | - value = from_node.get_property(source.name()) |
146 | | - self.set_property('data', str(value)) |
147 | | - |
148 | | - def on_input_connected(self, to_port, from_port): |
149 | | - """Override node callback method""" |
150 | | - self.run() |
151 | | - |
152 | | - def on_input_disconnected(self, to_port, from_port): |
153 | | - """Override node callback method""" |
154 | | - self.set_property('data', None) |
155 | | - |
156 | | - |
157 | 10 | if __name__ == '__main__': |
158 | 11 | app = QtWidgets.QApplication([]) |
159 | 12 |
|
@@ -187,38 +40,41 @@ def show_nodes_list(node): |
187 | 40 | graph.node_double_clicked.connect(show_nodes_list) |
188 | 41 |
|
189 | 42 | # registered nodes. |
190 | | - reg_nodes = [DataInputNode, DataViewerNode, MathFunctionsNode] |
| 43 | + reg_nodes = [ |
| 44 | + Nodes.__dict__[n] for n in Nodes.__dict__ |
| 45 | + if hasattr(Nodes.__dict__[n], 'NODE_NAME') |
| 46 | + ] |
191 | 47 |
|
192 | 48 | for n in reg_nodes: |
193 | 49 | graph.register_node(n) |
194 | 50 |
|
195 | | - mathNodeA = graph.create_node('com.chantasticvfx.MathFunctionsNode', |
| 51 | + mathNodeA = graph.create_node('Math.MathFunctionsNode', |
196 | 52 | name='Math Functions A', |
197 | 53 | color='#0a1e20', |
198 | 54 | text_color='#feab20', |
199 | 55 | pos=[-250, 70]) |
200 | 56 |
|
201 | | - mathNodeB = graph.create_node('com.chantasticvfx.MathFunctionsNode', |
| 57 | + mathNodeB = graph.create_node('Math.MathFunctionsNode', |
202 | 58 | name='Math Functions B', |
203 | 59 | color='#0a1e20', |
204 | 60 | text_color='#feab20', |
205 | 61 | pos=[-250, -70]) |
206 | 62 |
|
207 | | - mathNodeC = graph.create_node('com.chantasticvfx.MathFunctionsNode', |
208 | | - name='Math Functions C', |
209 | | - color='#0a1e20', |
210 | | - text_color='#feab20', |
211 | | - pos=[0, 0]) |
| 63 | + mathNodeC = graph.create_node('Math.MathFunctionsNode', |
| 64 | + name='Math Functions C', |
| 65 | + color='#0a1e20', |
| 66 | + text_color='#feab20', |
| 67 | + pos=[0, 0]) |
212 | 68 |
|
213 | | - inputANode = graph.create_node('com.chantasticvfx.DataInputNode', |
| 69 | + inputANode = graph.create_node('Inputs.DataInputNode', |
214 | 70 | name='Input A', |
215 | 71 | pos=[-500, -50]) |
216 | 72 |
|
217 | | - inputBNode = graph.create_node('com.chantasticvfx.DataInputNode', |
| 73 | + inputBNode = graph.create_node('Inputs.DataInputNode', |
218 | 74 | name='Input B', |
219 | 75 | pos=[-500, 50]) |
220 | 76 |
|
221 | | - outputNode = graph.create_node('com.chantasticvfx.DataViewerNode', |
| 77 | + outputNode = graph.create_node('Viewers.DataViewerNode', |
222 | 78 | name='Output', |
223 | 79 | pos=[250, 0]) |
224 | 80 |
|
|
0 commit comments