Skip to content

Commit 58beae7

Browse files
committed
Added optional inputs that are only required to be set prior to node execution if they are connected to another node.
The Node base class has now an optional TRIGGER input that can be used to add execution dependencies to nodes. This should recduce the excessive need for WaitAll nodes and allows to use nodes with nothing but manually set inputs to be executed at the appropriate time. TRIGGER inputs can be shown/hidden by right-clicking on a node in the editor.
1 parent e725159 commit 58beae7

3 files changed

Lines changed: 70 additions & 10 deletions

File tree

bin/pairs.ppy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
[[0, {"class": "ForEachAtomPair", "position": [5, -73], "inputs": [["Start", "Atom", null, ""], ["Control", "object", null, ""]], "outputs": [["Final", "object", null, ""], ["Atom1", "Atom", null, ""], ["Atom2", "Atom", null, ""]], "outputConnections": {"Atom2": ["3:IAtom"], "Atom1": ["2:IAtom"], "Final": ["10:ITrigger"]}, "inputConnections": {"Start": "1:OAtoms", "Control": "9:OTrigger"}}], [1, {"class": "ReadAtoms", "position": [-163, -103], "inputs": [["FileName", "str", "test.cif", "test.cif"]], "outputs": [["Atoms", "Atom", null, ""]], "outputConnections": {"Atoms": ["0:IStart"]}, "inputConnections": {}}], [2, {"class": "BreakAtom", "position": [235, -218], "inputs": [["Atom", "Atom", null, ""]], "outputs": [["Name", "str", null, ""], ["Element", "str", null, ""], ["frac", "float", null, ""], ["cart", "float", null, ""], ["ADP", "float", null, ""], ["ADP_Flag", "str", null, ""], ["Cell", "float", null, ""]], "outputConnections": {"Element": [], "Name": ["7:IStr1"], "ADP": [], "frac": [], "cart": ["6:IPosition1"], "ADP_Flag": [], "Cell": []}, "inputConnections": {"Atom": "0:OAtom1"}}], [3, {"class": "BreakAtom", "position": [289, 66], "inputs": [["Atom", "Atom", null, ""]], "outputs": [["Name", "str", null, ""], ["Element", "str", null, ""], ["frac", "float", null, ""], ["cart", "float", null, ""], ["ADP", "float", null, ""], ["ADP_Flag", "str", null, ""], ["Cell", "float", null, ""]], "outputConnections": {"Element": [], "Name": ["8:IStr2"], "ADP": [], "frac": [], "cart": ["6:IPosition2"], "ADP_Flag": [], "Cell": []}, "inputConnections": {"Atom": "0:OAtom2"}}], [6, {"class": "Distance", "position": [606, -49], "inputs": [["Position1", "float", null, ""], ["Position2", "float", null, ""]], "outputs": [["Distance", "float", null, ""]], "outputConnections": {"Distance": ["9:IValue"]}, "inputConnections": {"Position2": "3:Ocart", "Position1": "2:Ocart"}}], [7, {"class": "Join", "position": [501, -195], "inputs": [["Str1", "str", null, ""], ["Str2", "str", " -- ", " -- "]], "outputs": [["Joined", "str", null, ""]], "outputConnections": {"Joined": ["8:IStr1"]}, "inputConnections": {"Str1": "2:OName"}}], [8, {"class": "Join", "position": [771, -80], "inputs": [["Str1", "str", null, ""], ["Str2", "str", null, ""]], "outputs": [["Joined", "str", null, ""]], "outputConnections": {"Joined": ["9:IName"]}, "inputConnections": {"Str1": "7:OJoined", "Str2": "3:OName"}}], [9, {"class": "SetValue", "position": [939, 50], "inputs": [["Name", "str", null, ""], ["Value", "object", null, ""]], "outputs": [["Trigger", "object", null, ""]], "outputConnections": {"Trigger": ["0:IControl"]}, "inputConnections": {"Value": "6:ODistance", "Name": "8:OJoined"}}], [10, {"class": "ShowValues", "position": [175, 324], "inputs": [["Trigger", "object", null, ""]], "outputs": [["Output", "object", null, ""]], "outputConnections": {"Output": []}, "inputConnections": {"Trigger": "0:OFinal"}}]]
1+
[[0, {"outputs": [["Final", "object", null, ""], ["Atom1", "Atom", null, ""], ["Atom2", "Atom", null, ""]], "class": "ForEachAtomPair", "inputs": [["TRIGGER", "object", "", ""], ["Start", "Atom", null, ""], ["Control", "object", null, ""]], "outputConnections": {"Final": ["8:ITRIGGER"], "Atom1": ["2:IAtom"], "Atom2": ["3:IAtom"]}, "inputConnections": {"Control": "7:OTrigger", "Start": "1:OAtoms"}, "position": [5, -73]}], [1, {"outputs": [["Atoms", "Atom", null, ""]], "class": "ReadAtoms", "inputs": [["TRIGGER", "object", "", ""], ["FileName", "str", "test.cif", "test.cif"]], "outputConnections": {"Atoms": ["0:IStart"]}, "inputConnections": {}, "position": [-163, -103]}], [2, {"outputs": [["Name", "str", null, ""], ["Element", "str", null, ""], ["frac", "float", null, ""], ["cart", "float", null, ""], ["ADP", "float", null, ""], ["ADP_Flag", "str", null, ""], ["Cell", "float", null, ""]], "class": "BreakAtom", "inputs": [["TRIGGER", "object", "", ""], ["Atom", "Atom", null, ""]], "outputConnections": {"cart": ["4:IPosition1"], "Cell": [], "ADP_Flag": [], "Element": [], "frac": [], "Name": ["5:IStr1"], "ADP": []}, "inputConnections": {"Atom": "0:OAtom1"}, "position": [235, -218]}], [3, {"outputs": [["Name", "str", null, ""], ["Element", "str", null, ""], ["frac", "float", null, ""], ["cart", "float", null, ""], ["ADP", "float", null, ""], ["ADP_Flag", "str", null, ""], ["Cell", "float", null, ""]], "class": "BreakAtom", "inputs": [["TRIGGER", "object", "", ""], ["Atom", "Atom", null, ""]], "outputConnections": {"cart": ["4:IPosition2"], "Cell": [], "ADP_Flag": [], "Element": [], "frac": [], "Name": ["6:IStr2"], "ADP": []}, "inputConnections": {"Atom": "0:OAtom2"}, "position": [289, 66]}], [4, {"outputs": [["Distance", "float", null, ""]], "class": "Distance", "inputs": [["TRIGGER", "object", "", ""], ["Position1", "float", null, ""], ["Position2", "float", null, ""]], "outputConnections": {"Distance": ["7:IValue"]}, "inputConnections": {"Position2": "3:Ocart", "Position1": "2:Ocart"}, "position": [606, -49]}], [5, {"outputs": [["Joined", "str", null, ""]], "class": "Join", "inputs": [["TRIGGER", "object", "", ""], ["Str1", "str", null, ""], ["Str2", "str", " -- ", " -- "]], "outputConnections": {"Joined": ["6:IStr1"]}, "inputConnections": {"Str1": "2:OName"}, "position": [501, -195]}], [6, {"outputs": [["Joined", "str", null, ""]], "class": "Join", "inputs": [["TRIGGER", "object", "", ""], ["Str1", "str", null, ""], ["Str2", "str", null, ""]], "outputConnections": {"Joined": ["7:IName"]}, "inputConnections": {"Str2": "3:OName", "Str1": "5:OJoined"}, "position": [771, -80]}], [7, {"outputs": [["Trigger", "object", null, ""]], "class": "SetValue", "inputs": [["TRIGGER", "object", "", ""], ["Name", "str", null, ""], ["Value", "object", null, ""]], "outputConnections": {"Trigger": ["0:IControl"]}, "inputConnections": {"Value": "4:ODistance", "Name": "6:OJoined"}, "position": [939, 50]}], [8, {"outputs": [["Output", "object", null, ""]], "class": "ShowValues", "inputs": [["TRIGGER", "object", null, ""]], "outputConnections": {"Output": []}, "inputConnections": {"TRIGGER": "0:OFinal"}, "position": [124, 344]}]]

floppy/node.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,11 @@ class Info(object):
4242
"""
4343
Class for handling all information related to both inputs and outputs.
4444
"""
45-
def __init__(self, name, varType, hints=None, default='', select=None, owner=False, list=False):
45+
def __init__(self, name, varType, hints=None, default='', select=None, owner=False, list=False, optional=False):
4646
self.name = name
4747
self.connected = False
4848
self.varType = varType
49+
self.optional = optional
4950
if not hints:
5051
self.hints = [varType.__name__]
5152
else:
@@ -186,13 +187,15 @@ def addInput(name: str,
186187
hints=None,
187188
default='',
188189
select=None,
189-
list=False):
190+
list=False,
191+
optional=False):
190192
MetaNode.inputs.append({'name': name,
191193
'varType': varType,
192194
'hints': hints,
193195
'default': default,
194196
'select': select,
195-
'list': list})
197+
'list': list,
198+
'optional': optional})
196199

197200
def addOutput(name: str,
198201
varType: object,
@@ -249,6 +252,7 @@ class MyNode(Node):
249252
To access the value of an input during the Node's 'run' method or 'check' method use
250253
'myNodeInstance._myStringInput'. An 'InputNotAvailable' Exception is raised is the input is not set yet.
251254
"""
255+
Input('TRIGGER', object, optional=True)
252256
Tag('Node')
253257

254258
def __init__(self, nodeID, graph):
@@ -358,7 +362,8 @@ def check(self) -> bool:
358362
return self.notify()
359363
for inp in self.inputs.values():
360364
if not inp.isAvailable():
361-
# print(self, inp.default)
365+
if inp.optional and not inp.connected:
366+
continue
362367
# print(' {}: Prerequisites not met.'.format(str(self)))
363368
return False
364369
# print(' {}: ready.'.format(str(self)))
@@ -1004,7 +1009,7 @@ def report(self):
10041009

10051010

10061011
class GetValue(Node):
1007-
Input('Trigger', object)
1012+
# Input('Trigger', object)
10081013
Input('Name', str)
10091014
Output('Value', object)
10101015

@@ -1032,7 +1037,7 @@ def run(self):
10321037

10331038

10341039
class ShowValues(Node):
1035-
Input('Trigger', object)
1040+
# Input('Trigger', object)
10361041
Output('Output', object)
10371042

10381043
def __init__(self, *args, **kwargs):

floppy/painter.py

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,9 @@ def __init__(self, parent=None):
5959
self.drawItems = []
6060
self.drawItemsOfNode = {}
6161
self.watchingItems = set()
62-
62+
self.triggers = set()
6363
self.contextSensitive = True
64+
self.rightClickedNode = None
6465

6566
self.mouseDownPos = None
6667
self.dialog = None
@@ -69,6 +70,7 @@ def __init__(self, parent=None):
6970

7071
def reset(self):
7172
self.nodes = []
73+
self.triggers = set()
7274
self.graph = None
7375
self.shiftDown = False
7476
self.looseConnection = None
@@ -77,6 +79,7 @@ def reset(self):
7779
self.drawItems = []
7880
self.drawItemsOfNode = {}
7981
self.watchingItems = set()
82+
self.rightClickedNode = None
8083

8184
self.contextSensitive = True
8285

@@ -134,7 +137,21 @@ def mousePressEvent(self, event):
134137
self.dialog = None
135138
self.mouseDownPos = event.pos()
136139
if event.button() == Qt.RightButton:
137-
self.drag = event.pos()
140+
self.rightClickedNode = None
141+
for nodePoints in self.nodePoints:
142+
x1 = nodePoints[0].x()
143+
x2 = nodePoints[1].x() #+ x1
144+
y1 = nodePoints[0].y()
145+
y2 = nodePoints[1].y() #+ y1
146+
xx = event.pos()
147+
yy = xx.y()
148+
xx = xx.x()
149+
if x1 < xx < x2 and y1 < yy < y2:
150+
self.rightClickedNode = nodePoints[-1]
151+
break
152+
if not self.rightClickedNode:
153+
self.drag = event.pos()
154+
138155
if event.button() == Qt.LeftButton:
139156
for item in self.watchingItems:
140157
item.watchDown(event.pos())
@@ -252,6 +269,23 @@ def mouseMoveEvent(self, event):
252269
def getSelectedNode(self):
253270
return self.clickedNode
254271

272+
def contextMenuEvent(self, event):
273+
node = self.rightClickedNode
274+
if not node:
275+
return None
276+
menu = QMenu(self)
277+
if not node in self.triggers:
278+
triggerAction = menu.addAction('Add Trigger')
279+
action = menu.exec_(self.mapToGlobal(event.pos()))
280+
if action == triggerAction:
281+
self.triggers.add(node)
282+
else:
283+
triggerAction = menu.addAction('Remove Trigger')
284+
action = menu.exec_(self.mapToGlobal(event.pos()))
285+
if action == triggerAction:
286+
self.triggers.discard(node)
287+
return None
288+
255289
def paintEvent(self, event):
256290
# before = time.time()
257291
self.inputPinPositions = []
@@ -323,12 +357,21 @@ def paintEvent(self, event):
323357
pen.setColor(QColor(150, 150, 150))
324358
painter.setFont(QFont('Helvetica', NODETITLEFONTSIZE))
325359
painter.setPen(pen)
326-
painter.drawText(x, y, w, h, Qt.AlignHCenter, node.__class__.__name__)
360+
painter.drawText(x, y+3, w, h, Qt.AlignHCenter, node.__class__.__name__)
327361
painter.setBrush(QColor(40, 40, 40))
328362
drawOffset = 25
329363
# for i, inputPin in enumerate(node.inputPins.values()):
330364
for i, drawItem in enumerate(self.drawItemsOfNode[node]['inp']):
331365
inputPin = drawItem.data
366+
if inputPin.name == 'TRIGGER':
367+
if not node in self.triggers and not inputPin.info.connected:
368+
drawItem.update(x, y+drawOffset+8, w, h, painter.transform())
369+
drawItem.deactivate()
370+
drawOffset += (8 + PINSIZE)
371+
continue
372+
else:
373+
self.triggers.add(node)
374+
drawItem.activeate()
332375
# pen.setColor(QColor(255, 190, 0))
333376
try:
334377
pen.setColor(Painter2D.PINCOLORS[inputPin.info.varType])
@@ -549,6 +592,9 @@ def registerNode(self, node, position, silent=False):
549592
self.drawItems.append(s)
550593
self.drawItemsOfNode[node]['out'].append(s)
551594
for inp in node.inputPins.values():
595+
# print(inp.name)
596+
# if inp.name == 'TRIGGER':# and inp.connected:
597+
# self.triggers.add(node)
552598
if inp.info.select:
553599
s = Selector(node, inp, self)
554600
elif inp.info.name == 'Control':
@@ -943,6 +989,13 @@ def __init__(self, parent, data, painter):
943989
self.h = 0
944990
self.parent = parent
945991
self.data = data
992+
self.active = True
993+
994+
def deactivate(self):
995+
self.active = False
996+
997+
def activeate(self):
998+
self.active = True
946999

9471000
def update(self, x, y, w, h, transform):
9481001
self.transform = transform
@@ -975,6 +1028,8 @@ def setState(self, state):
9751028
self.state = state
9761029

9771030
def collide(self, pos):
1031+
if not self.active:
1032+
return False
9781033
if self._x < pos.x() < self._xx and self._y < pos.y() < self._yy:
9791034
return True
9801035

0 commit comments

Comments
 (0)