From 6dcab85c1dc261d308a9e2c5685e4b700003cc9e Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Tue, 14 Jul 2015 23:02:12 -0400 Subject: [PATCH] Allow Advanced Logic to reference specific Nodes This allows us to ensure that a given NodeTree is only ever exported once. A node reference acts as a way to attach a plMultiModifier to a plSceneObject without using those terms. Things will work just fine if the node reference isn't used, so as long as the entire tree is only used once. Future work: ensuring the whole logic tree is only ever exported once. --- korman/exporter/convert.py | 15 ++++++++++++++- korman/properties/modifiers/logic.py | 21 +++++++++++++++++++-- korman/ui/modifiers/logic.py | 12 +++++++++--- 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/korman/exporter/convert.py b/korman/exporter/convert.py index 6f43726..6795be9 100644 --- a/korman/exporter/convert.py +++ b/korman/exporter/convert.py @@ -33,6 +33,8 @@ class Exporter: self._op = op # Blender export operator self._objects = [] self.actors = set() + self.node_trees_exported = set() + self.want_node_trees = {} @property def age_name(self): @@ -66,7 +68,10 @@ class Exporter: # Step 3: Export all the things! self._export_scene_objects() - # Step 3.1: Now that all Plasma Objects (save Mipmaps) are exported, we do any post + # Step 3.1: Ensure referenced logic node trees are exported + self._export_referenced_node_trees() + + # Step 3.2: Now that all Plasma Objects (save Mipmaps) are exported, we do any post # processing that needs to inspect those objects self._post_process_scene_objects() @@ -212,6 +217,14 @@ class Exporter: else: print(" No material(s) on the ObData, so no drawables") + def _export_referenced_node_trees(self): + print("\nChecking Logic Trees...") + need_to_export = ((name, bo, so) for name, (bo, so) in self.want_node_trees.items() + if name not in self.node_trees_exported) + for tree, bo, so in need_to_export: + print(" NodeTree '{}'".format(tree)) + bpy.data.node_groups[tree].export(self, bo, so) + def _harvest_actors(self): for bl_obj in self._objects: for mod in bl_obj.plasma_modifiers.modifiers: diff --git a/korman/properties/modifiers/logic.py b/korman/properties/modifiers/logic.py index 4d1e1a0..fcba3c7 100644 --- a/korman/properties/modifiers/logic.py +++ b/korman/properties/modifiers/logic.py @@ -33,13 +33,16 @@ class PlasmaVersionedNodeTree(bpy.types.PropertyGroup): default=set(list(zip(*game_versions))[0])) node_tree_name = StringProperty(name="Node Tree", description="Node Tree to export") + node_name = StringProperty(name="Node Ref", + description="Attach a reference to this node") @property def node_tree(self): try: return bpy.data.node_groups[self.node_tree_name] except KeyError: - raise ExportError("Node Tree {} does not exist!".format(self.node_tree_name)) + raise ExportError("Node Tree '{}' does not exist!".format(self.node_tree_name)) + class PlasmaAdvancedLogic(PlasmaModifierProperties): pl_id = "advanced_logic" @@ -60,7 +63,20 @@ class PlasmaAdvancedLogic(PlasmaModifierProperties): for i in self.logic_groups: our_versions = [globals()[j] for j in i.version] if version in our_versions: - i.node_tree.export(exporter, bo, so) + # If node_name is defined, then we're only adding a reference. We will make sure that + # the entire node tree is exported once before the post_export step, however. + if i.node_name: + exporter.want_node_trees[i.node_tree_name] = (bo, so) + node = i.node_tree.nodes.get(i.node_name, None) + if node is None: + raise ExportError("Node '{}' does not exist in '{}'".format(i.node_name, i.node_tree_name)) + # We are going to assume get_key will do the adding correctly. Single modifiers + # should fetch the appropriate SceneObject before doing anything, so this will + # be a no-op in that case. Multi modifiers should accept any SceneObject, however + node.get_key(exporter, so) + else: + exporter.node_trees_exported.add(i.node_tree_name) + i.node_tree.export(exporter, bo, so) def harvest_actors(self): actors = set() @@ -88,6 +104,7 @@ class PlasmaSpawnPoint(PlasmaModifierProperties): def requires_actor(self): return True + class PlasmaMaintainersMarker(PlasmaModifierProperties): pl_id = "maintainersmarker" diff --git a/korman/ui/modifiers/logic.py b/korman/ui/modifiers/logic.py index 70f53f9..9dc27f1 100644 --- a/korman/ui/modifiers/logic.py +++ b/korman/ui/modifiers/logic.py @@ -19,6 +19,7 @@ class LogicListUI(bpy.types.UIList): def draw_item(self, context, layout, data, item, icon, active_data, active_property, index=0, flt_flag=0): layout.prop(item, "name", emboss=False, text="", icon="NODETREE") + def advanced_logic(modifier, layout, context): row = layout.row() row.template_list("LogicListUI", "logic_groups", modifier, "logic_groups", modifier, "active_group_index", @@ -37,9 +38,14 @@ def advanced_logic(modifier, layout, context): # Modify the loop points if modifier.logic_groups: logic = modifier.logic_groups[modifier.active_group_index] - row = layout.row() - row.prop_menu_enum(logic, "version") - row.prop_search(logic, "node_tree_name", bpy.data, "node_groups", icon="NODETREE", text="") + layout.row().prop_menu_enum(logic, "version") + layout.prop_search(logic, "node_tree_name", bpy.data, "node_groups", icon="NODETREE") + try: + layout.prop_search(logic, "node_name", logic.node_tree, "nodes", icon="NODE") + except: + row = layout.row() + row.enabled = False + row.prop(logic, "node_name", icon="NODE") def spawnpoint(modifier, layout, context): layout.label(text="Avatar faces negative Y.")