From 35d07d3645f67afce54d4458d423f8790c236121 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Sat, 16 Jun 2018 22:07:24 -0400 Subject: [PATCH] Deprecate Responder Command nodes This commit removes the ability for Responder State nodes to specify Responder Command nodes. Now, Responder State nodes reference Message nodes directly. Messages that support sending callbacks can now reference other messages as linked outputs. Note that old node trees are currently broken and will need to be reworked by hand. TODO is to automatically upgrade those old command based node trees. Also, LOGICWIZ code using command nodes needs to be updated. --- korman/nodes/node_messages.py | 35 ++++++++++++++++----------- korman/nodes/node_responder.py | 44 ++++++++++++++++++++++++++++++---- 2 files changed, 60 insertions(+), 19 deletions(-) diff --git a/korman/nodes/node_messages.py b/korman/nodes/node_messages.py index af8b19a..2762c9c 100644 --- a/korman/nodes/node_messages.py +++ b/korman/nodes/node_messages.py @@ -34,17 +34,32 @@ class PlasmaMessageNode(PlasmaNodeBase): ("sender", { "text": "Sender", "type": "PlasmaMessageSocket", + "valid_link_sockets": "PlasmaMessageSocket", "spawn_empty": True, }), ]) @property def has_callbacks(self): - """This message has callbacks that can be waited on by a Responder""" + """This message does not have callbacks that can be waited on by a Responder""" return False -class PlasmaAnimCmdMsgNode(idprops.IDPropMixin, PlasmaMessageNode, bpy.types.Node): +class PlasmaMessageWithCallbacksNode(PlasmaMessageNode): + output_sockets = OrderedDict([ + ("msgs", { + "text": "Send On Completion", + "type": "PlasmaMessageSocket", + "valid_link_sockets": "PlasmaMessageSocket", + }), + ]) + + @property + def has_callbacks(self): + """This message has callbacks that can be waited on by a Responder""" + return True + +class PlasmaAnimCmdMsgNode(idprops.IDPropMixin, PlasmaMessageWithCallbacksNode, bpy.types.Node): bl_category = "MSG" bl_idname = "PlasmaAnimCmdMsgNode" bl_label = "Animation Command" @@ -407,7 +422,7 @@ class PlasmaLinkToAgeMsg(PlasmaMessageNode, bpy.types.Node): layout.prop(self, "spawn_point") -class PlasmaOneShotMsgNode(idprops.IDPropObjectMixin, PlasmaMessageNode, bpy.types.Node): +class PlasmaOneShotMsgNode(idprops.IDPropObjectMixin, PlasmaMessageWithCallbacksNode, bpy.types.Node): bl_category = "MSG" bl_idname = "PlasmaOneShotMsgNode" bl_label = "One Shot" @@ -426,7 +441,7 @@ class PlasmaOneShotMsgNode(idprops.IDPropObjectMixin, PlasmaMessageNode, bpy.typ animation = StringProperty(name="Animation", description="Name of the animation the avatar should execute") marker = StringProperty(name="Marker", - description="Name of the marker specifying when to notify the Responder") + description="Name of the marker specifying when to notify the Responder") drivable = BoolProperty(name="Drivable", description="Player retains control of the avatar during the OneShot", default=False) @@ -523,7 +538,7 @@ class PlasmaSceneObjectMsgRcvrNode(idprops.IDPropObjectMixin, PlasmaNodeBase, bp return {"target_object": "object_name"} -class PlasmaSoundMsgNode(idprops.IDPropObjectMixin, PlasmaMessageNode, bpy.types.Node): +class PlasmaSoundMsgNode(idprops.IDPropObjectMixin, PlasmaMessageWithCallbacksNode, bpy.types.Node): bl_category = "MSG" bl_idname = "PlasmaSoundMsgNode" bl_label = "Sound" @@ -646,16 +661,12 @@ class PlasmaSoundMsgNode(idprops.IDPropObjectMixin, PlasmaMessageNode, bpy.types layout.prop(self, "looping") layout.prop(self, "volume") - @property - def has_callbacks(self): - return True - @classmethod def _idprop_mapping(cls): return {"emitter_object": "object_name"} -class PlasmaTimerCallbackMsgNode(PlasmaMessageNode, bpy.types.Node): +class PlasmaTimerCallbackMsgNode(PlasmaMessageWithCallbacksNode, bpy.types.Node): bl_category = "MSG" bl_idname = "PlasmaTimerCallbackMsgNode" bl_label = "Timed Callback" @@ -677,10 +688,6 @@ class PlasmaTimerCallbackMsgNode(PlasmaMessageNode, bpy.types.Node): msg.time = self.delay return msg - @property - def has_callbacks(self): - return True - class PlasmaFootstepSoundMsgNode(PlasmaMessageNode, bpy.types.Node): bl_category = "MSG" diff --git a/korman/nodes/node_responder.py b/korman/nodes/node_responder.py index 166e242..646a6c8 100644 --- a/korman/nodes/node_responder.py +++ b/korman/nodes/node_responder.py @@ -126,9 +126,10 @@ class PlasmaResponderStateNode(PlasmaNodeBase, bpy.types.Node): ]) output_sockets = OrderedDict([ - ("cmds", { - "text": "Commands", - "type": "PlasmaRespCommandSocket", + ("msgs", { + "text": "Send Message", + "type": "PlasmaMessageSocket", + "valid_link_sockets": "PlasmaMessageSocket", }), ("gotostate", { "link_limit": 1, @@ -182,12 +183,44 @@ class PlasmaResponderStateNode(PlasmaNodeBase, bpy.types.Node): # Convert the commands commands = CommandMgr() - for i in self.find_outputs("cmds", "PlasmaResponderCommandNode"): + for i in self.find_outputs("msgs"): # slight optimization--commands attached to states can't wait on other commands # namely because it's impossible to wait on a command that doesn't exist... - i.convert_command(exporter, so, stateMgr.responder, commands) + self._generate_command(exporter, so, stateMgr.responder, commands, i) commands.save(state) + def _generate_command(self, exporter, so, responder, commandMgr, msgNode, waitOn=-1): + def prepare_message(exporter, so, responder, commandMgr, waitOn, msg): + idx, command = commandMgr.add_command(self, waitOn) + if msg.sender is None: + msg.sender = responder.key + msg.BCastFlags |= plMessage.kLocalPropagate + command.msg = msg + return (idx, command) + + # HACK: Some message nodes may need to sneakily send multiple messages. So, convert_message + # is therefore now a generator. We will ASSume that the first message generated is the + # primary msg that we should use for callbacks, if applicable + if inspect.isgeneratorfunction(msgNode.convert_message): + messages = tuple(msgNode.convert_message(exporter, so)) + msg = messages[0] + for i in messages[1:]: + prepare_message(exporter, so, responder, commandMgr, waitOn, i) + else: + msg = msgNode.convert_message(exporter, so) + idx, command = prepare_message(exporter, so, responder, commandMgr, waitOn, msg) + + # If the callback message node is not properly set up for event callbacks, we don't want to + if msgNode.has_callbacks and msgNode.find_output("msgs"): + childWaitOn = commandMgr.add_wait(idx) + msgNode.convert_callback_message(exporter, so, msg, responder.key, childWaitOn) + else: + childWaitOn = waitOn + + # Export any linked callback messages + for i in msgNode.find_outputs("msgs"): + self._generate_command(exporter, so, responder, commandMgr, i, childWaitOn) + def update(self): super().update() @@ -231,6 +264,7 @@ class PlasmaResponderCommandNode(PlasmaNodeBase, bpy.types.Node): ]) def convert_command(self, exporter, so, responder, commandMgr, waitOn=-1): + raise RuntimeError() def prepare_message(exporter, so, responder, commandMgr, waitOn, msg): idx, command = commandMgr.add_command(self, waitOn) if msg.sender is None: