Browse Source

Add an animation group modifier

Now, an object can be a "master" animation object controlling many
animated objects when you address it with the Animation Command logic
node.

This also includes a fix for a bug that would potentially break an
animation if it were addressed by an Animation Command node.
pull/10/head
Adam Johnson 10 years ago
parent
commit
2b8c16da1b
  1. 9
      korman/nodes/node_messages.py
  2. 59
      korman/properties/modifiers/anim.py
  3. 22
      korman/ui/modifiers/anim.py

9
korman/nodes/node_messages.py

@ -168,6 +168,15 @@ class PlasmaAnimCmdMsgNode(PlasmaMessageNode, bpy.types.Node):
anim = obj.plasma_modifiers.animation anim = obj.plasma_modifiers.animation
if not anim.enabled: if not anim.enabled:
self.raise_error("invalid animation", tree) self.raise_error("invalid animation", tree)
group = obj.plasma_modifiers.animation_group
if group.enabled:
# we might be controlling more than one animation. isn't that cute?
# https://www.youtube.com/watch?v=hspNaoxzNbs
# (but obviously this is not wrong...)
target = exporter.mgr.find_create_key(plMsgForwarder, bl=obj, name=group.display_name)
else:
# remember, the AGModifier MUST exist first... so just in case...
exporter.mgr.find_create_key(plAGModifier, bl=obj, name=anim.display_name)
target = exporter.mgr.find_create_key(plAGMasterMod, bl=obj, name=anim.display_name) target = exporter.mgr.find_create_key(plAGMasterMod, bl=obj, name=anim.display_name)
else: else:
material = bpy.data.materials.get(self.material_name, None) material = bpy.data.materials.get(self.material_name, None)

59
korman/properties/modifiers/anim.py

@ -122,7 +122,7 @@ class PlasmaAnimationModifier(PlasmaModifierProperties):
channel.affine = affine channel.affine = affine
# We need both an AGModifier and an AGMasterMod # We need both an AGModifier and an AGMasterMod
# TODO: grouped animations (eg one door, two objects) # NOTE: mandatory order--otherwise the animation will not work in game!
agmod = exporter.mgr.find_create_object(plAGModifier, so=so, name=self.display_name) agmod = exporter.mgr.find_create_object(plAGModifier, so=so, name=self.display_name)
agmod.channelName = bo.name agmod.channelName = bo.name
agmaster = exporter.mgr.find_create_object(plAGMasterMod, so=so, name=self.display_name) agmaster = exporter.mgr.find_create_object(plAGMasterMod, so=so, name=self.display_name)
@ -142,6 +142,63 @@ class PlasmaAnimationModifier(PlasmaModifierProperties):
phys.mass = 1.0 phys.mass = 1.0
class AnimGroupObject(bpy.types.PropertyGroup):
object_name = StringProperty(name="Child",
description="Object whose action is a child animation")
class PlasmaAnimationGroupModifier(PlasmaModifierProperties):
pl_id = "animation_group"
pl_depends = {"animation"}
bl_category = "Animation"
bl_label = "Group"
bl_description = "Defines related animations"
bl_icon = "GROUP"
children = CollectionProperty(name="Child Animations",
description="Animations that will execute the same commands as this one",
type=AnimGroupObject)
active_child_index = IntProperty(options={"HIDDEN"})
def created(self, obj):
self.display_name = "{}_AnimGroup".format(obj.name)
def export(self, exporter, bo, so):
action = _get_blender_action(bo)
key_name = bo.plasma_modifiers.animation.display_name
# See above... AGModifier must always be inited first...
agmod = exporter.mgr.find_create_object(plAGModifier, so=so, name=key_name)
# The message forwarder is the guy that makes sure that everybody knows WTF is going on
msgfwd = exporter.mgr.find_create_object(plMsgForwarder, so=so, name=self.display_name)
# Now, this is da swhiz...
agmaster = exporter.mgr.find_create_object(plAGMasterMod, so=so, name=key_name)
agmaster.msgForwarder = msgfwd.key
agmaster.isGrouped, agmaster.isGroupMaster = True, True
for i in self.children:
child_bo = bpy.data.objects.get(i.object_name, None)
if child_bo is None:
msg = "Animation Group '{}' specifies an invalid object '{}'. Ignoring..."
exporter.report.warn(msg.format(self.display_name, i.object_name), ident=2)
continue
if child_bo.animation_data is None or child_bo.animation_data.action is None:
msg = "Animation Group '{}' specifies an object '{}' with no valid animation data. Ignoring..."
exporter.report.warn(msg.format(self.display_name, i.object_name), indent=2)
continue
child_animation = child_bo.plasma_modifiers.animation
if not child_animation.enabled:
msg = "Animation Group '{}' specifies an object '{}' with no Plasma Animation modifier. Ignoring..."
exporter.report.warn(msg.format(self.display_name, i.object_name), indent=2)
continue
child_agmod = exporter.mgr.find_create_key(plAGModifier, bl=child_bo, name=child_animation.display_name)
child_agmaster = exporter.mgr.find_create_key(plAGMasterMod, bl=child_bo, name=child_animation.display_name)
msgfwd.addForwardKey(child_agmaster)
msgfwd.addForwardKey(agmaster.key)
class LoopMarker(bpy.types.PropertyGroup): class LoopMarker(bpy.types.PropertyGroup):
loop_name = StringProperty(name="Loop Name", loop_name = StringProperty(name="Loop Name",
description="Name of this loop") description="Name of this loop")

22
korman/ui/modifiers/anim.py

@ -39,6 +39,28 @@ def animation(modifier, layout, context):
col.prop_search(modifier, "loop_end", action, "pose_markers", icon="PMARKER") col.prop_search(modifier, "loop_end", action, "pose_markers", icon="PMARKER")
class GroupListUI(bpy.types.UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_property, index=0, flt_flag=0):
layout.prop_search(item, "object_name", bpy.data, "objects", icon="ACTION")
def animation_group(modifier, layout, context):
if not _check_for_anim(layout, context):
return
row = layout.row()
row.template_list("GroupListUI", "children", modifier, "children", modifier, "active_child_index",
rows=3, maxrows=4)
col = row.column(align=True)
op = col.operator("object.plasma_modifier_collection_add", icon="ZOOMIN", text="")
op.modifier = modifier.pl_id
op.collection = "children"
op = col.operator("object.plasma_modifier_collection_remove", icon="ZOOMOUT", text="")
op.modifier = modifier.pl_id
op.collection = "children"
op.index = modifier.active_child_index
class LoopListUI(bpy.types.UIList): class LoopListUI(bpy.types.UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_property, index=0, flt_flag=0): def draw_item(self, context, layout, data, item, icon, active_data, active_property, index=0, flt_flag=0):
layout.prop(item, "loop_name", emboss=False, text="", icon="PMARKER_ACT") layout.prop(item, "loop_name", emboss=False, text="", icon="PMARKER_ACT")

Loading…
Cancel
Save