From 484b16925ab383868967309d112126bcb5cf6a40 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Thu, 8 Jun 2017 22:08:23 -0400 Subject: [PATCH] Convert the rest of the message nodes to ID props --- korman/exporter/material.py | 19 +++--- korman/nodes/node_messages.py | 120 ++++++++++++++++++++++------------ 2 files changed, 87 insertions(+), 52 deletions(-) diff --git a/korman/exporter/material.py b/korman/exporter/material.py index eb817b1..6b64622 100644 --- a/korman/exporter/material.py +++ b/korman/exporter/material.py @@ -357,8 +357,9 @@ class MaterialConverter: return None fcurves = [] + texture = tex_slot.texture mat_action = harvest_fcurves(bm, fcurves, "texture_slots[{}]".format(idx)) - tex_action = harvest_fcurves(tex_slot.texture, fcurves) + tex_action = harvest_fcurves(texture, fcurves) if not fcurves: return base_layer @@ -370,7 +371,7 @@ class MaterialConverter: if ctrl is not None: if layer_animation is None: name = "{}_LayerAnim".format(base_layer.key.name) - layer_animation = self.get_texture_animation_key(bo, bm, tex_slot=tex_slot).object + layer_animation = self.get_texture_animation_key(bo, bm, texture).object setattr(layer_animation, attr, ctrl) # Alrighty, if we exported any controllers, layer_animation is a plLayerAnimation. We need to do @@ -695,19 +696,15 @@ class MaterialConverter: def get_bump_layer(self, bo): return self._bump_mats.get(bo, None) - def get_texture_animation_key(self, bo, bm, tex_name=None, tex_slot=None): + def get_texture_animation_key(self, bo, bm, texture): """Finds or creates the appropriate key for sending messages to an animated Texture""" - assert tex_name or tex_slot - if tex_slot is None: - tex_slot = bm.texture_slots.get(tex_name, None) - if tex_slot is None: - raise ExportError("Material '{}' does not contain Texture '{}'".format(bm.name, tex_name)) - if tex_name is None: - tex_name = tex_slot.name + tex_name = texture.name + if not tex_name in bm.texture_slots: + raise ExportError("Texture '{}' not used in Material '{}'".format(bm.name, tex_name)) name = "{}_{}_LayerAnim".format(bm.name, tex_name) - layer = tex_slot.texture.plasma_layer + layer = texture.plasma_layer pClass = plLayerSDLAnimation if layer.anim_sdl_var else plLayerAnimation return self._mgr.find_create_key(pClass, bl=bo, name=name) diff --git a/korman/nodes/node_messages.py b/korman/nodes/node_messages.py index 1308c1d..af8b19a 100644 --- a/korman/nodes/node_messages.py +++ b/korman/nodes/node_messages.py @@ -44,7 +44,7 @@ class PlasmaMessageNode(PlasmaNodeBase): return False -class PlasmaAnimCmdMsgNode(PlasmaMessageNode, bpy.types.Node): +class PlasmaAnimCmdMsgNode(idprops.IDPropMixin, PlasmaMessageNode, bpy.types.Node): bl_category = "MSG" bl_idname = "PlasmaAnimCmdMsgNode" bl_label = "Animation Command" @@ -55,12 +55,32 @@ class PlasmaAnimCmdMsgNode(PlasmaMessageNode, bpy.types.Node): items=[("OBJECT", "Object", "Mesh Action"), ("TEXTURE", "Texture", "Texture Action")], default="OBJECT") - object_name = StringProperty(name="Object", - description="Target object name") - material_name = StringProperty(name="Material", - description="Target material name") - texture_name = StringProperty(name="Texture", - description="Target texture slot name") + + def _poll_material_textures(self, value): + if self.target_object is None: + return False + if self.target_material is None: + return False + return value.name in self.target_material.texture_slots + + def _poll_mesh_materials(self, value): + if self.target_object is None: + return False + if self.target_object.type != "MESH": + return False + return value.name in self.target_object.data.materials + + target_object = PointerProperty(name="Object", + description="Target object", + type=bpy.types.Object) + target_material = PointerProperty(name="Material", + description="Target material", + type=bpy.types.Material, + poll=_poll_mesh_materials) + target_texture = PointerProperty(name="Texture", + description="Target texture", + type=bpy.types.Texture, + poll=_poll_material_textures) go_to = EnumProperty(name="Go To", description="Where should the animation start?", @@ -122,19 +142,16 @@ class PlasmaAnimCmdMsgNode(PlasmaMessageNode, bpy.types.Node): def draw_buttons(self, context, layout): layout.prop(self, "anim_type") - layout.prop_search(self, "object_name", bpy.data, "objects") + layout.prop(self, "target_object") if self.anim_type != "OBJECT": - bo = bpy.data.objects.get(self.object_name) - if bo is None or not hasattr(bo.data, "materials"): - layout.label("Invalid Object", icon="ERROR") - else: - layout.prop_search(self, "material_name", bo.data, "materials") - material = bpy.data.materials.get(self.material_name, None) - if material is None: - layout.label("Invalid Material", icon="ERROR") - else: - layout.prop_search(self, "texture_name", material, "texture_slots") + col = layout.column() + col.enabled = self.target_object is not None + col.prop(self, "target_material") + + col = layout.column() + col.enabled = self.target_object is not None and self.target_material is not None + col.prop(self, "target_texture") layout.prop(self, "go_to") layout.prop(self, "action") @@ -150,8 +167,7 @@ class PlasmaAnimCmdMsgNode(PlasmaMessageNode, bpy.types.Node): if self.anim_type != "OBJECT": loops = None else: - obj = bpy.data.objects.get(self.object_name, None) - loops = None if obj is None else obj.plasma_modifiers.animation_loop + loops = None if self.target_object is None else self.target_object.plasma_modifiers.animation_loop if loops is not None and loops.enabled: layout.prop_search(self, "loop_name", loops, "loops", icon="PMARKER_ACT") else: @@ -171,9 +187,9 @@ class PlasmaAnimCmdMsgNode(PlasmaMessageNode, bpy.types.Node): msg = plAnimCmdMsg() # We're either sending this off to an AGMasterMod or a LayerAnim - obj = bpy.data.objects.get(self.object_name, None) + obj = self.target_object if obj is None: - self.raise_error("invalid object: '{}'".format(self.object_name)) + self.raise_error("target object must be specified") if self.anim_type == "OBJECT": if not obj.plasma_object.has_animation_data: self.raise_error("invalid animation") @@ -186,10 +202,13 @@ class PlasmaAnimCmdMsgNode(PlasmaMessageNode, bpy.types.Node): else: _agmod_trash, target = exporter.animation.get_anigraph_keys(obj) else: - material = bpy.data.materials.get(self.material_name, None) + material = self.target_material if material is None: - self.raise_error("invalid material: '{}'".format(self.material_name)) - target = exporter.mesh.material.get_texture_animation_key(obj, material, self.texture_name) + self.raise_error("target material must be specified") + texture = self.target_texture + if texture is None: + self.raise_error("target texture must be specified") + target = exporter.mesh.material.get_texture_animation_key(obj, material, texture) if target is None: raise RuntimeError() @@ -225,6 +244,17 @@ class PlasmaAnimCmdMsgNode(PlasmaMessageNode, bpy.types.Node): def has_callbacks(self): return self.event != "NONE" + @classmethod + def _idprop_mapping(cls): + return {"target_object": "object_name", + "target_material": "material_name", + "target_texture": "texture_name"} + + def _idprop_sources(self): + return {"object_name": bpy.data.objects, + "material_name": bpy.data.materials, + "texture_name": bpy.data.textures} + class PlasmaEnableMsgNode(PlasmaMessageNode, bpy.types.Node): bl_category = "MSG" @@ -377,14 +407,15 @@ class PlasmaLinkToAgeMsg(PlasmaMessageNode, bpy.types.Node): layout.prop(self, "spawn_point") -class PlasmaOneShotMsgNode(PlasmaMessageNode, bpy.types.Node): +class PlasmaOneShotMsgNode(idprops.IDPropObjectMixin, PlasmaMessageNode, bpy.types.Node): bl_category = "MSG" bl_idname = "PlasmaOneShotMsgNode" bl_label = "One Shot" bl_width_default = 210 - pos = StringProperty(name="Position", - description="Object defining the OneShot position") + pos_object = PointerProperty(name="Position", + description="Object defining the OneShot position", + type=bpy.types.Object) seek = EnumProperty(name="Seek", description="How the avatar should approach the OneShot position", items=[("SMART", "Smart Seek", "Let the engine figure out the best path"), @@ -417,7 +448,7 @@ class PlasmaOneShotMsgNode(PlasmaMessageNode, bpy.types.Node): row = layout.row() row.prop(self, "drivable") row.prop(self, "reversable") - layout.prop_search(self, "pos", bpy.data, "objects", icon="EMPTY_DATA") + layout.prop(self, "pos_object", icon="EMPTY_DATA") layout.prop(self, "seek") def export(self, exporter, bo, so): @@ -431,22 +462,24 @@ class PlasmaOneShotMsgNode(PlasmaMessageNode, bpy.types.Node): def get_key(self, exporter, so): name = self.key_name - if self.pos: - bo = bpy.data.objects.get(self.pos, None) - if bo is None: - raise ExportError("Node '{}' in '{}' specifies an invalid Position Empty".format(self.name, self.id_data.name)) - pos_so = exporter.mgr.find_create_object(plSceneObject, bl=bo) + if self.pos_object is not None: + pos_so = exporter.mgr.find_create_object(plSceneObject, bl=self.pos_object) return exporter.mgr.find_create_key(plOneShotMod, name=name, so=pos_so) else: return exporter.mgr.find_create_key(plOneShotMod, name=name, so=so) def harvest_actors(self): - return (self.pos,) + if self.pos_object: + return (self.pos_object.name,) @property def has_callbacks(self): return bool(self.marker) + @classmethod + def _idprop_mapping(cls): + return {"pos_object": "pos"} + class PlasmaOneShotCallbackSocket(PlasmaMessageSocketBase, bpy.types.NodeSocket): marker = StringProperty(name="Marker", @@ -456,7 +489,7 @@ class PlasmaOneShotCallbackSocket(PlasmaMessageSocketBase, bpy.types.NodeSocket) layout.prop(self, "marker") -class PlasmaSceneObjectMsgRcvrNode(PlasmaNodeBase, bpy.types.Node): +class PlasmaSceneObjectMsgRcvrNode(idprops.IDPropObjectMixin, PlasmaNodeBase, bpy.types.Node): bl_category = "MSG" bl_idname = "PlasmaSceneObjectMsgRcvrNode" bl_label = "Send To Object" @@ -471,19 +504,24 @@ class PlasmaSceneObjectMsgRcvrNode(PlasmaNodeBase, bpy.types.Node): }), ]) - object_name = StringProperty(name="Object", - description="Object to send the message to") + target_object = PointerProperty(name="Object", + description="Object to send the message to", + type=bpy.types.Object) def draw_buttons(self, context, layout): - layout.prop_search(self, "object_name", bpy.data, "objects") + layout.prop(self, "target_object") def get_key(self, exporter, so): - bo = bpy.data.objects.get(self.object_name, None) + bo = self.target_object if bo is None: - self.raise_error("invalid object specified: '{}'".format(self.object_name)) + self.raise_error("target object must be specified") ref_so_key = exporter.mgr.find_create_key(plSceneObject, bl=bo) return ref_so_key + @classmethod + def _idprop_mapping(cls): + return {"target_object": "object_name"} + class PlasmaSoundMsgNode(idprops.IDPropObjectMixin, PlasmaMessageNode, bpy.types.Node): bl_category = "MSG"