|
1 | 1 | #!/usr/bin/python |
2 | 2 | # -*- coding: utf-8 -*- |
3 | | -import inspect |
4 | | -import math |
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 | +from example_nodes import 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 | | -def update_streams(node, *args): |
25 | | - """ |
26 | | - Update all nodes joined by pipes |
27 | | - """ |
28 | | - nodes = [] |
29 | | - trash = [] |
30 | | - |
31 | | - for port, nodeList in node.connected_output_nodes().items(): |
32 | | - nodes.extend(nodeList) |
33 | | - |
34 | | - while nodes: |
35 | | - node = nodes.pop() |
36 | | - if node not in trash: |
37 | | - trash.append(node) |
38 | | - |
39 | | - for port, nodeList in node.connected_output_nodes().items(): |
40 | | - nodes.extend(nodeList) |
41 | | - |
42 | | - if not nodes: |
43 | | - try: |
44 | | - node.run() |
45 | | - except Exception as error: |
46 | | - print("Error Update Streams: %s" % str(error)) |
47 | | - |
48 | | - |
49 | | -class DataInputNode(BaseNode): |
50 | | - """ |
51 | | - Input node data. |
52 | | - """ |
53 | | - |
54 | | - __identifier__ = 'com.chantasticvfx' |
55 | | - NODE_NAME = 'Input Numbers' |
56 | | - |
57 | | - def __init__(self): |
58 | | - super(DataInputNode, self).__init__() |
59 | | - self.output = self.add_output('out') |
60 | | - self.add_text_input('out', 'Data Input', text='0.4', tab='widgets') |
61 | | - self.view.widgets['out'].value_changed.connect(partial(update_streams, self)) |
62 | | - |
63 | | - def run(self): |
64 | | - return |
65 | | - |
66 | | - |
67 | | -class MathFunctionsNode(BaseNode): |
68 | | - """ |
69 | | - Math functions node. |
70 | | - """ |
71 | | - |
72 | | - # set a unique node identifier. |
73 | | - __identifier__ = 'com.chantasticvfx' |
74 | | - |
75 | | - # set the initial default node name. |
76 | | - NODE_NAME = 'Functions node' |
77 | | - |
78 | | - mathFuncs = [func for func in dir(math) if not func.startswith('_')] |
79 | | - |
80 | | - def __init__(self): |
81 | | - super(MathFunctionsNode, self).__init__() |
82 | | - self.set_color(25, 58, 51) |
83 | | - self.add_combo_menu('functions', 'Functions', items=self.mathFuncs, |
84 | | - tab='widgets') |
85 | | - |
86 | | - # switch math function type |
87 | | - self.view.widgets['functions'].value_changed.connect(self.addFunction) |
88 | | - update = partial(update_streams, self) |
89 | | - self.view.widgets['functions'].value_changed.connect(update) |
90 | | - self.output = self.add_output('output') |
91 | | - self.create_property(self.output.name(), None) |
92 | | - self.trigger_type = 'no_inPorts' |
93 | | - |
94 | | - self.view.widgets['functions'].widget.setCurrentIndex(2) |
95 | | - |
96 | | - def addFunction(self, prop, func): |
97 | | - """ |
98 | | - Create inputs based on math functions arguments. |
99 | | - """ |
100 | | - self.func = getattr(math, func) |
101 | | - dataFunc = inspect.getfullargspec(self.func) |
102 | | - |
103 | | - for arg in dataFunc.args: |
104 | | - if not self.has_property(arg): |
105 | | - inPort = self.add_input(arg) |
106 | | - inPort.trigger = True |
107 | | - self.create_property(arg, None) |
108 | | - |
109 | | - for inPort in self._inputs: |
110 | | - if inPort.name() in dataFunc.args: |
111 | | - if not inPort.visible(): |
112 | | - inPort.set_visible(True) |
113 | | - else: |
114 | | - inPort.set_visible(False) |
115 | | - |
116 | | - def run(self): |
117 | | - """ |
118 | | - Evaluate all entries, pass them as arguments of the |
119 | | - chosen mathematical function. |
120 | | - """ |
121 | | - for to_port in self.input_ports(): |
122 | | - if to_port.visible() == False: |
123 | | - continue |
124 | | - from_ports = to_port.connected_ports() |
125 | | - if not from_ports: |
126 | | - raise Exception('Port %s not connected!' % to_port.name(), |
127 | | - to_port) |
128 | | - |
129 | | - for from_port in from_ports: |
130 | | - from_port.node().run() |
131 | | - data = from_port.node().get_property(from_port.name()) |
132 | | - self.set_property(to_port.name(), float(data)) |
133 | | - |
134 | | - try: |
135 | | - # Execute math function with arguments. |
136 | | - output = self.func(*[self.get_property(inport.name()) for inport in self._inputs if inport.visible()]) |
137 | | - |
138 | | - self.set_property('output', output) |
139 | | - except KeyError as error: |
140 | | - print("An input is missing! %s" % str(error)) |
141 | | - except TypeError as error: |
142 | | - print("Error evaluating function: %s" % str(error)) |
143 | | - |
144 | | - def on_input_connected(self, to_port, from_port): |
145 | | - """Override node callback method.""" |
146 | | - self.set_property(to_port.name(), from_port.node().run()) |
147 | | - update_streams(self) |
148 | | - |
149 | | - def on_input_disconnected(self, to_port, from_port): |
150 | | - """Override node callback method.""" |
151 | | - self.set_property('output', None) |
152 | | - update_streams(self) |
153 | | - |
154 | | - |
155 | | -class DataViewerNode(BaseNode): |
156 | | - __identifier__ = 'com.chantasticvfx' |
157 | | - NODE_NAME = 'Result View' |
158 | | - |
159 | | - def __init__(self): |
160 | | - super(DataViewerNode, self).__init__() |
161 | | - self.input = self.add_input('in data') |
162 | | - self.add_text_input('data', 'Data Viewer', tab='widgets') |
163 | | - |
164 | | - def run(self): |
165 | | - """Evaluate input to show it.""" |
166 | | - for source in self.input.connected_ports(): |
167 | | - from_node = source.node() |
168 | | - try: |
169 | | - from_node.run() |
170 | | - except Exception as error: |
171 | | - print("%s no inputs connected: %s" % (from_node.name(), str(error))) |
172 | | - self.set_property('data', None) |
173 | | - return |
174 | | - value = from_node.get_property(source.name()) |
175 | | - self.set_property('data', str(value)) |
176 | | - |
177 | | - def on_input_connected(self, to_port, from_port): |
178 | | - """Override node callback method""" |
179 | | - self.run() |
180 | | - |
181 | | - def on_input_disconnected(self, to_port, from_port): |
182 | | - """Override node callback method""" |
183 | | - self.set_property('data', None) |
184 | | - |
185 | | - |
186 | 10 | if __name__ == '__main__': |
187 | 11 | app = QtWidgets.QApplication([]) |
188 | 12 |
|
@@ -216,38 +40,36 @@ def show_nodes_list(node): |
216 | 40 | graph.node_double_clicked.connect(show_nodes_list) |
217 | 41 |
|
218 | 42 | # registered nodes. |
219 | | - reg_nodes = [DataInputNode, DataViewerNode, MathFunctionsNode] |
220 | | - |
221 | | - for n in reg_nodes: |
| 43 | + for n in Nodes: |
222 | 44 | graph.register_node(n) |
223 | 45 |
|
224 | | - mathNodeA = graph.create_node('com.chantasticvfx.MathFunctionsNode', |
| 46 | + mathNodeA = graph.create_node('Math.MathFunctionsNode', |
225 | 47 | name='Math Functions A', |
226 | 48 | color='#0a1e20', |
227 | 49 | text_color='#feab20', |
228 | 50 | pos=[-250, 70]) |
229 | 51 |
|
230 | | - mathNodeB = graph.create_node('com.chantasticvfx.MathFunctionsNode', |
| 52 | + mathNodeB = graph.create_node('Math.MathFunctionsNode', |
231 | 53 | name='Math Functions B', |
232 | 54 | color='#0a1e20', |
233 | 55 | text_color='#feab20', |
234 | 56 | pos=[-250, -70]) |
235 | 57 |
|
236 | | - mathNodeC = graph.create_node('com.chantasticvfx.MathFunctionsNode', |
237 | | - name='Math Functions C', |
238 | | - color='#0a1e20', |
239 | | - text_color='#feab20', |
240 | | - pos=[0, 0]) |
| 58 | + mathNodeC = graph.create_node('Math.MathFunctionsNode', |
| 59 | + name='Math Functions C', |
| 60 | + color='#0a1e20', |
| 61 | + text_color='#feab20', |
| 62 | + pos=[0, 0]) |
241 | 63 |
|
242 | | - inputANode = graph.create_node('com.chantasticvfx.DataInputNode', |
| 64 | + inputANode = graph.create_node('Inputs.DataInputNode', |
243 | 65 | name='Input A', |
244 | 66 | pos=[-500, -50]) |
245 | 67 |
|
246 | | - inputBNode = graph.create_node('com.chantasticvfx.DataInputNode', |
| 68 | + inputBNode = graph.create_node('Inputs.DataInputNode', |
247 | 69 | name='Input B', |
248 | 70 | pos=[-500, 50]) |
249 | 71 |
|
250 | | - outputNode = graph.create_node('com.chantasticvfx.DataViewerNode', |
| 72 | + outputNode = graph.create_node('Viewers.DataViewerNode', |
251 | 73 | name='Output', |
252 | 74 | pos=[250, 0]) |
253 | 75 |
|
|
0 commit comments