From 1b5b229a334ca06adc054c7cfd1dc1e43af603b8 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Wed, 10 Jun 2015 18:22:37 -0400 Subject: [PATCH] Export Region Sensors --- korman/nodes/__init__.py | 1 - korman/nodes/node_conditions.py | 82 ++++++++++++++++++++++++++- korman/nodes/node_responder.py | 10 +++- korman/properties/modifiers/base.py | 2 +- korman/properties/modifiers/region.py | 12 ++-- 5 files changed, 94 insertions(+), 13 deletions(-) diff --git a/korman/nodes/__init__.py b/korman/nodes/__init__.py index 869f1b0..d34b022 100644 --- a/korman/nodes/__init__.py +++ b/korman/nodes/__init__.py @@ -21,7 +21,6 @@ import nodeitems_utils # Put all Korman node modules here... from .node_conditions import * from .node_core import * -from .node_logic import * from .node_messages import * from .node_responder import * diff --git a/korman/nodes/node_conditions.py b/korman/nodes/node_conditions.py index 1ac9574..6aad214 100644 --- a/korman/nodes/node_conditions.py +++ b/korman/nodes/node_conditions.py @@ -15,6 +15,7 @@ import bpy from bpy.props import * +from PyHSPlasma import * from .node_core import PlasmaNodeBase, PlasmaNodeSocketBase from ..properties.modifiers.physics import bounds_types @@ -31,6 +32,7 @@ class PlasmaVolumeReportNode(PlasmaNodeBase, bpy.types.Node): report_when = EnumProperty(name="When", description="When the region should trigger", items=[("each", "Each Event", "The region will trigger on every enter/exit"), + ("first", "First Event", "The region will trigger on the first event only"), ("count", "Population", "When the region has a certain number of objects inside it")]) threshold = IntProperty(name="Threshold", description="How many objects should be in the region for it to trigger", @@ -77,9 +79,87 @@ class PlasmaVolumeSensorNode(PlasmaNodeBase, bpy.types.Node): layout.prop(self, "report_on") # Okay, if they changed the name of the ObData, that's THEIR problem... - layout.prop_search(self, "region", bpy.data, "meshes", icon="MESH_DATA") + layout.prop_search(self, "region", bpy.data, "objects", icon="MESH_DATA") layout.prop(self, "bounds") + def export(self, exporter, tree, bo, so): + interface = exporter.mgr.add_object(plInterfaceInfoModifier, name=self.create_key_name(tree), so=so) + + # Region Enters + enter_simple = self.find_input_socket("enter").allow + enter_settings = self.find_input("enter", "PlasmaVolumeReportNode") + if enter_simple or enter_settings is not None: + key = self._export_volume_event(exporter, tree, bo, so, plVolumeSensorConditionalObject.kTypeEnter, enter_settings) + interface.addIntfKey(key) + + # Region Exits + exit_simple = self.find_input_socket("exit").allow + exit_settings = self.find_input("exit", "PlasmaVolumeReportNode") + if exit_simple or exit_settings is not None: + key = self._export_volume_event(exporter, tree, bo, so, plVolumeSensorConditionalObject.kTypeExit, exit_settings) + interface.addIntfKey(key) + + # Don't forget to export the physical object itself! + # [trollface.jpg] + simIface, physical = exporter.physics.generate_physical(bo, so, "{}_VolumeSensor".format(bo.name)) + phys_bo = bpy.data.objects[self.region] + exporter.physics.export(phys_bo, physical, self.bounds) + + physical.memberGroup = plSimDefs.kGroupDetector + if "avatar" in self.report_on: + physical.reportGroup |= 1 << plSimDefs.kGroupAvatar + if "dynamics" in self.report_on: + physical.reportGroup |= 1 << plSimDefs.kGroupDynamic + + def _export_volume_event(self, exporter, tree, bo, so, event, settings): + if event == plVolumeSensorConditionalObject.kTypeEnter: + suffix = "Enter" + else: + suffix = "Exit" + + theName = "{}_{}_{}".format(tree.name, self.name, suffix) + print(" [LogicModifier '{}']".format(theName)) + logicKey = exporter.mgr.find_create_key(plLogicModifier, name=theName, so=so) + logicmod = logicKey.object + logicmod.setLogicFlag(plLogicModifier.kMultiTrigger, True) + + # LogicMod notification... This is one of the cases where the linked node needs to match + # exactly one key... + notify = plNotifyMsg() + notify.BCastFlags = (plMessage.kNetPropagate | plMessage.kLocalPropagate) + for i in self.find_outputs("satisfies"): + key = i.get_key(exporter, tree, so) + if key is None: + print(" WARNING: '{}' Node '{}' doesn't expose a key. It won't be triggered!".format(i.bl_idname, i.name)) + else: + notify.addReceiver(key) + logicmod.notify = notify + + # Now, the detector objects + print(" [ObjectInVolumeDetector '{}']".format(theName)) + detKey = exporter.mgr.find_create_key(plObjectInVolumeDetector, name=theName, so=so) + det = detKey.object + + print(" [VolumeSensorConditionalObject '{}']".format(theName)) + volKey = exporter.mgr.find_create_key(plVolumeSensorConditionalObject, name=theName, so=so) + volsens = volKey.object + + volsens.type = event + if settings is not None: + if settings.report_when == "first": + volsens.first = True + elif settings.report_when == "threshold": + volsens.trigNum = settings.threshold + + # There appears to be a mandatory order for these keys... + det.addReceiver(volKey) + det.addReceiver(logicKey) + + # End mandatory order + logicmod.addCondition(volKey) + return logicKey + + class PlasmaVolumeSettingsSocket(PlasmaNodeSocketBase): bl_color = (43.1, 24.7, 0.0, 1.0) diff --git a/korman/nodes/node_responder.py b/korman/nodes/node_responder.py index ca71fe2..70162a6 100644 --- a/korman/nodes/node_responder.py +++ b/korman/nodes/node_responder.py @@ -20,15 +20,18 @@ import uuid from .node_core import * -class PlasmaResponderNode(PlasmaNodeBase, bpy.types.Node): +class PlasmaResponderNode(PlasmaNodeVariableInput, bpy.types.Node): bl_category = "LOGIC" bl_idname = "PlasmaResponderNode" bl_label = "Responder" def init(self, context): - self.inputs.new("PlasmaRespTriggerSocket", "Trigger", "whodoneit") + self.inputs.new("PlasmaConditionSocket", "Condition", "condition") self.outputs.new("PlasmaRespStateSocket", "States", "states") + def draw_buttons(self, context, layout): + self.ensure_sockets("PlasmaConditionSocket", "Condition", "condition") + def get_key(self, exporter, tree, so): return exporter.mgr.find_create_key(plResponderModifier, name=self.create_key_name(tree), so=so) @@ -74,13 +77,14 @@ class PlasmaResponderStateNode(PlasmaNodeVariableInput, bpy.types.Node): default=False) def init(self, context): + self.inputs.new("PlasmaRespStateSocket", "Condition", "condition") self.outputs.new("PlasmaRespCommandSocket", "Commands", "cmds") self.outputs.new("PlasmaRespStateSocket", "Trigger", "gotostate").link_limit = 1 def draw_buttons(self, context, layout): # This actually draws nothing, but it makes sure we have at least one empty input slot # We need this because it's possible that multiple OTHER states can call us - self.ensure_sockets("PlasmaRespStateSocket", "Condition") + self.ensure_sockets("PlasmaRespStateSocket", "Condition", "condition") # Now draw a prop layout.prop(self, "default_state") diff --git a/korman/properties/modifiers/base.py b/korman/properties/modifiers/base.py index 3432682..7f15211 100644 --- a/korman/properties/modifiers/base.py +++ b/korman/properties/modifiers/base.py @@ -54,7 +54,7 @@ class PlasmaModifierProperties(bpy.types.PropertyGroup): class PlasmaModifierLogicWiz: @property def node_tree(self): - name = "LOGICWIZ_{}".format(self.display_name) + name = self.display_name try: return bpy.data.node_groups[name] except LookupError: diff --git a/korman/properties/modifiers/region.py b/korman/properties/modifiers/region.py index 407d454..89c96f3 100644 --- a/korman/properties/modifiers/region.py +++ b/korman/properties/modifiers/region.py @@ -88,20 +88,18 @@ class PlasmaFootstepRegion(PlasmaModifierProperties, PlasmaModifierLogicWiz): # Region Sensor volsens = nodes.new("PlasmaVolumeSensorNode") - volsens.region = bo.data.name + volsens.name = "RegionSensor" + volsens.region = bo.name volsens.bounds = self.bounds volsens.find_input_socket("enter").allow = True volsens.find_input_socket("exit").allow = True - # LogicMod - logicmod = nodes.new("PlasmaLogicTriggerNode") - logicmod.link_input(tree, volsens, "satisfies", "condition") - # Responder respmod = nodes.new("PlasmaResponderNode") - respmod.link_input(tree, logicmod, "trigger", "whodoneit") + respmod.name = "Resp" + respmod.link_input(tree, volsens, "satisfies", "condition") respstate = nodes.new("PlasmaResponderStateNode") - respstate.link_input(tree, respmod, "states", respstate.inputs.new("PlasmaRespStateSocket", "Responder")) + respstate.link_input(tree, respmod, "states", "condition") respstate.default_state = True respcmd = nodes.new("PlasmaResponderCommandNode") respcmd.link_input(tree, respstate, "cmds", "whodoneit")