diff --git a/korman/nodes/node_conditions.py b/korman/nodes/node_conditions.py index 21222dc..9031b2e 100644 --- a/korman/nodes/node_conditions.py +++ b/korman/nodes/node_conditions.py @@ -47,9 +47,9 @@ class PlasmaClickableNode(PlasmaNodeBase, bpy.types.Node): "text": "Avatar Facing Target", "type": "PlasmaFacingTargetSocket", }), - ("enable_callback", { - "text": "Local Reenable", - "type": "PlasmaRespCommandSocket", + ("message", { + "text": "Message", + "type": "PlasmaEnableMessageSocket", "spawn_empty": True, }), ]) @@ -348,6 +348,11 @@ class PlasmaVolumeSensorNode(PlasmaNodeBase, bpy.types.Node): "type": "PlasmaVolumeSettingsSocketIn", "valid_link_sockets": {"PlasmaVolumeSettingsSocketOut"}, }), + ("message", { + "text": "Message", + "type": "PlasmaEnableMessageSocket", + "spawn_empty": True, + }), ]) output_sockets = OrderedDict([ diff --git a/korman/nodes/node_core.py b/korman/nodes/node_core.py index 0c61a4f..5a6a4ea 100644 --- a/korman/nodes/node_core.py +++ b/korman/nodes/node_core.py @@ -240,6 +240,15 @@ class PlasmaNodeSocketBase: return bool(self.links) +class PlasmaNodeSocketInputGeneral(PlasmaNodeSocketBase, bpy.types.NodeSocket): + """A general input socket that will steal the output's color""" + def draw_color(self, context, node): + if self.is_linked: + return self.links[0].from_socket.draw_color(context, node) + else: + return (0.0, 0.0, 0.0, 0.0) + + class PlasmaNodeTree(bpy.types.NodeTree): bl_idname = "PlasmaNodeTree" bl_label = "Plasma" diff --git a/korman/nodes/node_messages.py b/korman/nodes/node_messages.py index fe3cdce..5b8a456 100644 --- a/korman/nodes/node_messages.py +++ b/korman/nodes/node_messages.py @@ -228,13 +228,19 @@ class PlasmaEnableMsgNode(PlasmaMessageNode, bpy.types.Node): bl_idname = "PlasmaEnableMsgNode" bl_label = "Enable/Disable" + output_sockets = OrderedDict([ + ("receivers", { + "text": "Send To", + "type": "PlasmaEnableMessageSocket", + "valid_link_sockets": {"PlasmaEnableMessageSocket", "PlasmaNodeSocketInputGeneral"}, + }), + ]) + cmd = EnumProperty(name="Command", description="How should we affect the object's state?", items=[("kDisable", "Disable", "Deactivate the object"), ("kEnable", "Enable", "Activate the object")], default="kEnable") - object_name = StringProperty(name="Object", - description="Object whose state we are changing") settings = EnumProperty(name="Affects", description="Which attributes should we change", items=[("kAudible", "Audio", "Sounds played by this object"), @@ -245,10 +251,13 @@ class PlasmaEnableMsgNode(PlasmaMessageNode, bpy.types.Node): def convert_message(self, exporter, so): msg = plEnableMsg() - target_bo = bpy.data.objects.get(self.object_name, None) - if target_bo is None: - self.raise_error("target object '{}' is invalid".format(self.object_name)) - msg.addReceiver(exporter.mgr.find_create_key(plSceneObject, bl=target_bo)) + for i in self.find_outputs("receivers"): + key = i.get_key(exporter, so) + if isinstance(key, tuple): + for j in key: + msg.addReceiver(j) + else: + msg.addReceiver(key) msg.setCmd(getattr(plEnableMsg, self.cmd), True) # If we have a full house, let's send it to all the SO's generic modifiers as by compressing @@ -263,11 +272,14 @@ class PlasmaEnableMsgNode(PlasmaMessageNode, bpy.types.Node): return msg def draw_buttons(self, context, layout): - layout.prop(self, "cmd") - layout.prop_search(self, "object_name", bpy.data, "objects") + layout.prop(self, "cmd", text="Cmd") layout.prop(self, "settings") +class PlasmaEnableMessageSocket(PlasmaNodeSocketBase, bpy.types.NodeSocket): + bl_color = (0.427, 0.196, 0.0, 1.0) + + class PlasmaExcludeRegionMsg(PlasmaMessageNode, bpy.types.Node): bl_category = "MSG" bl_idname = "PlasmaExcludeRegionMsg" @@ -376,6 +388,35 @@ class PlasmaOneShotCallbackSocket(PlasmaMessageSocketBase, bpy.types.NodeSocket) layout.prop(self, "marker") +class PlasmaSceneObjectMsgRcvrNode(PlasmaNodeBase, bpy.types.Node): + bl_category = "MSG" + bl_idname = "PlasmaSceneObjectMsgRcvrNode" + bl_label = "Send To Object" + bl_width_default = 190 + + input_sockets = OrderedDict([ + ("message", { + "text": "Message", + "type": "PlasmaNodeSocketInputGeneral", + "valid_link_sockets": {"PlasmaEnableMessageSocket"}, + "spawn_empty": True, + }), + ]) + + object_name = StringProperty(name="Object", + description="Object to send the message to") + + def draw_buttons(self, context, layout): + layout.prop_search(self, "object_name", bpy.data, "objects") + + def get_key(self, exporter, so): + bo = bpy.data.objects.get(self.object_name, None) + if bo is None: + self.raise_error("invalid object specified: '{}'".format(self.object_name)) + ref_so_key = exporter.mgr.find_create_key(plSceneObject, bl=bo) + return ref_so_key + + class PlasmaTimerCallbackMsgNode(PlasmaMessageNode, bpy.types.Node): bl_category = "MSG" bl_idname = "PlasmaTimerCallbackMsgNode" diff --git a/korman/nodes/node_responder.py b/korman/nodes/node_responder.py index 9cf60fc..ca16368 100644 --- a/korman/nodes/node_responder.py +++ b/korman/nodes/node_responder.py @@ -210,9 +210,6 @@ class PlasmaResponderCommandNode(PlasmaNodeBase, bpy.types.Node): ("whodoneit", { "text": "Condition", "type": "PlasmaRespCommandSocket", - # command sockets are on some unrelated outputs... - "valid_link_nodes": {"PlasmaResponderCommandNode", "PlasmaResponderStateNode"}, - "valid_link_sockets": {"PlasmaRespCommandSocket"}, }), ]) @@ -226,6 +223,10 @@ class PlasmaResponderCommandNode(PlasmaNodeBase, bpy.types.Node): "text": "Trigger", "type": "PlasmaRespCommandSocket", }), + ("reenable", { + "text": "Local Reenable", + "type": "PlasmaEnableMessageSocket", + }), ]) def convert_command(self, exporter, so, responder, commandMgr, waitOn=-1): @@ -249,31 +250,31 @@ class PlasmaResponderCommandNode(PlasmaNodeBase, bpy.types.Node): else: childWaitOn = waitOn command.msg = msg - - # If they linked us back to a condition or something that exports a LogicModifier, that - # means we need to reenable it here... NOTE: we can't filter by the node idname, sadly. - # NOTE: would be incredibly stupid to do this if we're not waiting on anything to complete - if childWaitOn != -1: - for child in self.find_outputs("trigger"): - key = child.get_key(exporter, so) - if key is None: - continue - logicmod = key.object - if not isinstance(logicmod, plLogicModifier): - continue - logicmod.setLogicFlag(plLogicModifier.kOneShot, True) - - # Yep, this is an entirely new ResponderCommand that sends a plEnableMsg - enableMsg = plEnableMsg() - enableMsg.addReceiver(key) - enableMsg.sender = responder.key - enableMsg.BCastFlags |= plMessage.kLocalPropagate - enableMsg.setCmd(plEnableMsg.kEnable, True) - logicCmdIdx, logicCmd = commandMgr.add_command(self, childWaitOn) - logicCmd.msg = enableMsg else: childWaitOn = waitOn + # If they linked us back to a condition or something that exports a LogicModifier, that + # means we need to reenable it here... NOTE: it would be incredibly stupid to do this + # if we're not waiting on anything to complete + if childWaitOn != -1: + for child in self.find_outputs("reenable"): + key = child.get_key(exporter, so) + if key is None: + continue + logicmod = key.object + if not isinstance(logicmod, plLogicModifier): + continue + logicmod.setLogicFlag(plLogicModifier.kOneShot, True) + + # Yep, this is an entirely new ResponderCommand that sends a plEnableMsg + enableMsg = plEnableMsg() + enableMsg.addReceiver(key) + enableMsg.sender = responder.key + enableMsg.BCastFlags |= plMessage.kLocalPropagate + enableMsg.setCmd(plEnableMsg.kEnable, True) + logicCmdIdx, logicCmd = commandMgr.add_command(self, childWaitOn) + logicCmd.msg = enableMsg + # Export any child commands for i in self.find_outputs("trigger", "PlasmaResponderCommandNode"): i.convert_command(exporter, so, responder, commandMgr, childWaitOn)