Browse Source

Ensure only valid responders can be graphed

Responder commands are serialized, so it is not possible to execute a
truly tree-shaped responder. Sigh.
pull/95/head
Adam Johnson 6 years ago
parent
commit
6e9e690d8a
Signed by: Hoikas
GPG Key ID: 0B6515D6FF6F271E
  1. 15
      korman/nodes/node_core.py
  2. 34
      korman/nodes/node_messages.py

15
korman/nodes/node_core.py

@ -196,6 +196,7 @@ class PlasmaNodeBase:
i = 0
while i < len(sockets):
socket = sockets[i]
node = socket.node
options = defs.get(socket.alias, None)
if options is None or socket.bl_idname != options["type"]:
@ -214,6 +215,20 @@ class PlasmaNodeBase:
allowed_sockets = options.get("valid_link_sockets", None)
allowed_nodes = options.get("valid_link_nodes", None)
# The socket may decide it doesn't want anyone linked to it.
can_link_attr = options.get("can_link", None)
if can_link_attr is not None:
can_link = getattr(node, can_link_attr)
socket.enabled = can_link
if not can_link:
for link in socket.links:
try:
self._tattle(socket, link, "(socket refused link)")
self.id_data.links.remove(link)
except RuntimeError:
# was already removed by someone else
pass
# Helpful default... If neither are set, require the link to be to the same socket type
if allowed_nodes is None and allowed_sockets is None:
allowed_sockets = frozenset((options["type"],))

34
korman/nodes/node_messages.py

@ -48,17 +48,51 @@ class PlasmaMessageNode(PlasmaNodeBase):
class PlasmaMessageWithCallbacksNode(PlasmaMessageNode):
output_sockets = OrderedDict([
("msgs", {
"can_link": "can_link_callback",
"text": "Send On Completion",
"type": "PlasmaMessageSocket",
"valid_link_sockets": "PlasmaMessageSocket",
}),
])
@property
def can_link_callback(self):
"""Determines if a callback message can be linked to this socket"""
# Node Graphs enable us to draw lots of fancy logic, unfortunately, not
# everything that can potentially be represented in a node tree can be
# exported to URU in a way that will actually work. Responder commands can
# wait on other responder commands, but the way they are executed in Plasma is
# serialized. It's really a list of commands that are executed until a wait
# is encountered. At that time, Plasma waits and resumes running the list when
# the wait callback is received.
# So what does this mean???
# It means that only one "branch" of message nodes can have waits.
def check_for_callbacks(parent_node, child_node):
for sibling_node in parent_node.find_outputs("msgs"):
if sibling_node == child_node:
continue
if getattr(sibling_node, "has_linked_callbacks", False):
return True
for grandparent_node in parent_node.find_inputs("sender"):
return check_for_callbacks(grandparent_node, parent_node)
return False
for sender_node in self.find_inputs("sender"):
if check_for_callbacks(sender_node, self):
return False
return True
@property
def has_callbacks(self):
"""This message has callbacks that can be waited on by a Responder"""
return True
@property
def has_linked_callbacks(self):
return self.find_output("msgs") is not None
class PlasmaAnimCmdMsgNode(idprops.IDPropMixin, PlasmaMessageWithCallbacksNode, bpy.types.Node):
bl_category = "MSG"
bl_idname = "PlasmaAnimCmdMsgNode"

Loading…
Cancel
Save