From 0031950a746d6a1b632e6c57359432803e8871c9 Mon Sep 17 00:00:00 2001 From: Benjy Cook Date: Wed, 3 Aug 2011 18:17:33 +0000 Subject: Fixed issue with IK toggle buttons and added operators for the new limit rotation functions --- release/scripts/startup/ui_mocap.py | 53 ++++++++++++++++++++++++++++--------- 1 file changed, 41 insertions(+), 12 deletions(-) (limited to 'release/scripts/startup') diff --git a/release/scripts/startup/ui_mocap.py b/release/scripts/startup/ui_mocap.py index f31b580411a..ac063a3a0cc 100644 --- a/release/scripts/startup/ui_mocap.py +++ b/release/scripts/startup/ui_mocap.py @@ -52,11 +52,11 @@ class MocapConstraint(bpy.types.PropertyGroup): description="Other Constrained Bone (optional, depends on type)", update=setConstraint) s_frame = bpy.props.IntProperty(name="S", - default=bpy.context.scene.frame_start, + default=0, description="Start frame of Fix", update=setConstraint) e_frame = bpy.props.IntProperty(name="E", - default=bpy.context.scene.frame_end, + default=100, description="End frame of Fix", update=setConstraint) smooth_in = bpy.props.IntProperty(name="In", @@ -125,24 +125,33 @@ def toggleIKBone(self, context): if hasIKConstraint(parent_bone): break deformer_children = [child for child in parent_bone.children if child.bone.use_deform] - if len(deformer_children) > 1: - break + #~ if len(deformer_children) > 1: + #~ break ik.chain_count = chainLen for bone in self.parent_recursive: if bone.is_in_ik_chain: bone.IKRetarget = True else: print(self.name + " IK toggled OFF!") - cnstrn_bone = False + cnstrn_bones = [] + newChainLength = [] if hasIKConstraint(self): - cnstrn_bone = self + cnstrn_bones = [self] elif self.is_in_ik_chain: - cnstrn_bone = [child for child in self.children_recursive if hasIKConstraint(child)][0] - if cnstrn_bone: + cnstrn_bones = [child for child in self.children_recursive if hasIKConstraint(child)] + for cnstrn_bone in cnstrn_bones: + newChainLength.append(cnstrn_bone.parent_recursive.index(self) + 1) + if cnstrn_bones: # remove constraint, and update IK retarget for all parents of cnstrn_bone up to chain_len - ik = [constraint for constraint in cnstrn_bone.constraints if constraint.type == "IK"][0] - cnstrn_bone.constraints.remove(ik) - cnstrn_bone.IKRetarget = False + for i, cnstrn_bone in enumerate(cnstrn_bones): + print(cnstrn_bone.name) + if newChainLength: + ik = hasIKConstraint(cnstrn_bone) + ik.chain_count = newChainLength[i] + else: + ik = hasIKConstraint(cnstrn_bone) + cnstrn_bone.constraints.remove(ik) + cnstrn_bone.IKRetarget = False for bone in cnstrn_bone.parent_recursive: if not bone.is_in_ik_chain: bone.IKRetarget = False @@ -198,6 +207,7 @@ class MocapPanel(bpy.types.Panel): row2 = self.layout.row(align=True) row2.operator("mocap.looper", text='Loop animation') row2.operator("mocap.limitdof", text='Constrain Rig') + row2.operator("mocap.removelimitdof", text='Unconstrain Rig') self.layout.label("Retargeting") enduser_obj = bpy.context.active_object performer_obj = [obj for obj in bpy.context.selected_objects if obj != enduser_obj] @@ -414,11 +424,13 @@ class OBJECT_OT_DenoiseButton(bpy.types.Operator): class OBJECT_OT_LimitDOFButton(bpy.types.Operator): - '''UNIMPLEMENTED: Create limit constraints on the active armature from the selected armature's animation's range of motion''' + '''Create limit constraints on the active armature from the selected armature's animation's range of motion''' bl_idname = "mocap.limitdof" bl_label = "Analyzes animations Max/Min DOF and adds hard/soft constraints" def execute(self, context): + performer_obj = [obj for obj in context.selected_objects if obj != context.active_object][0] + mocap_tools.limit_dof(context, performer_obj, context.active_object) return {"FINISHED"} @classmethod @@ -432,6 +444,23 @@ class OBJECT_OT_LimitDOFButton(bpy.types.Operator): return False +class OBJECT_OT_RemoveLimitDOFButton(bpy.types.Operator): + '''Removes previously created limit constraints on the active armature''' + bl_idname = "mocap.removelimitdof" + bl_label = "Removes previously created limit constraints on the active armature" + + def execute(self, context): + mocap_tools.limit_dof_toggle_off(context, context.active_object) + return {"FINISHED"} + + @classmethod + def poll(cls, context): + activeIsArmature = False + if context.active_object: + activeIsArmature = isinstance(context.active_object.data, bpy.types.Armature) + return activeIsArmature + + class OBJECT_OT_RotateFixArmature(bpy.types.Operator): '''Realign the active armature's axis system to match Blender (Commonly needed after bvh import)''' bl_idname = "mocap.rotate_fix" -- cgit v1.2.3 From ecd4b869828bc5ed7e3d00ac8dc9e93832f2c156 Mon Sep 17 00:00:00 2001 From: Benjy Cook Date: Wed, 3 Aug 2011 22:26:59 +0000 Subject: Initial coding of path editing operator. Still needs some work, but all the basic functionality is there. Select a path and the stride bone (as active) and it will reparameterize the path to propel the armature forward in the same magnitude of the original --- release/scripts/startup/ui_mocap.py | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) (limited to 'release/scripts/startup') diff --git a/release/scripts/startup/ui_mocap.py b/release/scripts/startup/ui_mocap.py index ac063a3a0cc..03d173df7a6 100644 --- a/release/scripts/startup/ui_mocap.py +++ b/release/scripts/startup/ui_mocap.py @@ -304,6 +304,18 @@ class MocapConstraintsPanel(bpy.types.Panel): layout.separator() +class ExtraToolsPanel(bpy.types.Panel): + # Motion capture retargeting panel + bl_label = "Extra Mocap Tools" + bl_space_type = "PROPERTIES" + bl_region_type = "WINDOW" + bl_context = "object" + + def draw(self, context): + layout = self.layout + layout.operator('mocap.pathediting', text="Follow Path") + + class OBJECT_OT_RetargetButton(bpy.types.Operator): '''Retarget animation from selected armature to active armature ''' bl_idname = "mocap.retarget" @@ -383,7 +395,7 @@ class OBJECT_OT_ConvertSamplesButton(bpy.types.Operator): bl_label = "Converts samples / simplifies keyframes to beziers" def execute(self, context): - mocap_tools.fcurves_simplify() + mocap_tools.fcurves_simplify(context, context.active_object) return {"FINISHED"} @classmethod @@ -598,6 +610,25 @@ class OBJECT_OT_GuessHierachyMapping(bpy.types.Operator): return False +class OBJECT_OT_PathEditing(bpy.types.Operator): + '''Sets active object (stride object) to follow the selected curve''' + bl_idname = "mocap.pathediting" + bl_label = "Sets active object (stride object) to follow the selected curve" + + def execute(self, context): + path = [obj for obj in context.selected_objects if obj != context.active_object][0] + mocap_tools.path_editing(context, context.active_object, path) + return {"FINISHED"} + + @classmethod + def poll(cls, context): + if context.active_object: + selected_objs = [obj for obj in context.selected_objects if obj != context.active_object] + return selected_objs + else: + return False + + def register(): bpy.utils.register_module(__name__) -- cgit v1.2.3 From 9a9330d88c83b4c7ea76cd46a1fecd0c8e4e349e Mon Sep 17 00:00:00 2001 From: Benjy Cook Date: Fri, 5 Aug 2011 08:44:16 +0000 Subject: Post Retarget fixes - added an Update Constraints button, that recalculates all fixes. Useful for when the user makes some external change to the animation --- release/scripts/startup/ui_mocap.py | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) (limited to 'release/scripts/startup') diff --git a/release/scripts/startup/ui_mocap.py b/release/scripts/startup/ui_mocap.py index 03d173df7a6..8ef4c1e7591 100644 --- a/release/scripts/startup/ui_mocap.py +++ b/release/scripts/startup/ui_mocap.py @@ -264,9 +264,10 @@ class MocapConstraintsPanel(bpy.types.Panel): enduser_obj = context.active_object enduser_arm = enduser_obj.data layout.operator_menu_enum("mocap.addmocapfix", "type") + layout.operator("mocap.updateconstraints", text='Update Fixes') bakeRow = layout.row() - bakeRow.operator("mocap.bakeconstraints") - bakeRow.operator("mocap.unbakeconstraints") + bakeRow.operator("mocap.bakeconstraints", text='Bake Fixes') + bakeRow.operator("mocap.unbakeconstraints", text='Unbake Fixes') layout.separator() for i, m_constraint in enumerate(enduser_arm.mocap_constraints): box = layout.box() @@ -588,6 +589,21 @@ class OBJECT_OT_UnbakeMocapConstraints(bpy.types.Operator): return isinstance(context.active_object.data, bpy.types.Armature) +class OBJECT_OT_UpdateMocapConstraints(bpy.types.Operator): + '''Updates all post-retarget fixes - needed after changes to armature object or pose''' + bl_idname = "mocap.updateconstraints" + bl_label = "Updates all fixes to target armature - neccesary to take under consideration changes to armature object or pose" + + def execute(self, context): + updateConstraints(context.active_object, context) + return {"FINISHED"} + + @classmethod + def poll(cls, context): + if context.active_object: + return isinstance(context.active_object.data, bpy.types.Armature) + + class OBJECT_OT_GuessHierachyMapping(bpy.types.Operator): '''Attemps to auto figure out hierarchy mapping''' bl_idname = "mocap.guessmapping" @@ -623,7 +639,7 @@ class OBJECT_OT_PathEditing(bpy.types.Operator): @classmethod def poll(cls, context): if context.active_object: - selected_objs = [obj for obj in context.selected_objects if obj != context.active_object] + selected_objs = [obj for obj in context.selected_objects if obj != context.active_object and isinstance(obj.data, bpy.types.Curve)] return selected_objs else: return False -- cgit v1.2.3 From c334bf69a7282254bb80bb2896bd8716930a4adf Mon Sep 17 00:00:00 2001 From: Joerg Mueller Date: Sat, 6 Aug 2011 17:57:20 +0000 Subject: 3D Audio GSoC: Mixdown functionality. * Mixdown possible via libsndfile and ffmpeg! * Fixed some ffmpeg deprecation warnings * Mixdown UI only shows working Container, Codec and Format combinations! * Minor bugs and warnings fixed --- release/scripts/startup/bl_ui/properties_scene.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'release/scripts/startup') diff --git a/release/scripts/startup/bl_ui/properties_scene.py b/release/scripts/startup/bl_ui/properties_scene.py index a9310fcc532..c3784b9f692 100644 --- a/release/scripts/startup/bl_ui/properties_scene.py +++ b/release/scripts/startup/bl_ui/properties_scene.py @@ -70,6 +70,8 @@ class SCENE_PT_audio(SceneButtonsPanel, bpy.types.Panel): col.prop(rd, "ffmpeg_audio_channels", text="") col.prop(rd, "ffmpeg_audio_mixrate", text="Rate") + layout.operator("sound.mixdown") + class SCENE_PT_unit(SceneButtonsPanel, bpy.types.Panel): bl_label = "Units" -- cgit v1.2.3 From 022e815fbd6d81f9b1baa177cce1abf2f42bcb21 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sun, 7 Aug 2011 12:27:20 +0000 Subject: Sound clip NLA Strips for Nexyon These are basically just for specifying when a speaker should fire off it's soundclip, and as such, many NLA operations are irrelevant for it. They can only be specified on object-level for speaker objects. I've still got some UI tweaks I'll need to work on in order for these to be able to be added even when the speaker doesn't have any NLA tracks yet. (EDIT: while typing this, I had an idea for how to do this, but that'll be for next commit). In the mean time, you'll need to add a single keyframe for the object, snowflake that action and delete the NLA strip before you can start editing. --- release/scripts/startup/bl_ui/space_nla.py | 1 + 1 file changed, 1 insertion(+) (limited to 'release/scripts/startup') diff --git a/release/scripts/startup/bl_ui/space_nla.py b/release/scripts/startup/bl_ui/space_nla.py index 78489db6317..b6c2d078960 100644 --- a/release/scripts/startup/bl_ui/space_nla.py +++ b/release/scripts/startup/bl_ui/space_nla.py @@ -173,6 +173,7 @@ class NLA_MT_add(bpy.types.Menu): layout.column() layout.operator("nla.actionclip_add") layout.operator("nla.transition_add") + layout.operator("nla.soundclip_add") layout.separator() layout.operator("nla.meta_add") -- cgit v1.2.3 From 60eec89cda50360c8fc68f9d3d6dc18e5c6633b1 Mon Sep 17 00:00:00 2001 From: Benjy Cook Date: Mon, 8 Aug 2011 11:09:56 +0000 Subject: Created property systems for multiple retargets on a single armature, for this type of use and animation stitching. Also contains some placeholder UI and code for animation stitching. --- release/scripts/startup/ui_mocap.py | 69 +++++++++++++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 3 deletions(-) (limited to 'release/scripts/startup') diff --git a/release/scripts/startup/ui_mocap.py b/release/scripts/startup/ui_mocap.py index 8ef4c1e7591..3d034b0047a 100644 --- a/release/scripts/startup/ui_mocap.py +++ b/release/scripts/startup/ui_mocap.py @@ -110,6 +110,35 @@ bpy.utils.register_class(MocapConstraint) bpy.types.Armature.mocap_constraints = bpy.props.CollectionProperty(type=MocapConstraint) + +class AnimationStitchSettings(bpy.types.PropertyGroup): + first_action = bpy.props.StringProperty(name="Action 1", + description="First action in stitch") + second_action = bpy.props.StringProperty(name="Action 2", + description="Second action in stitch") + blend_frame = bpy.props.IntProperty(name="Stitch frame", + description="Frame to locate stitch on") + blend_amount = bpy.props.IntProperty(name="Blend amount", + description="Size of blending transitiion, on both sides of the stitch", + default=10) + +bpy.utils.register_class(AnimationStitchSettings) + + +class MocapNLATracks(bpy.types.PropertyGroup): + name = bpy.props.StringProperty() + active = bpy.props.BoolProperty() + base_track = bpy.props.StringProperty() + auto_fix_track = bpy.props.StringProperty() + manual_fix_track = bpy.props.StringProperty() + stride_action = bpy.props.StringProperty() + +bpy.utils.register_class(MocapNLATracks) + +bpy.types.Armature.stitch_settings = bpy.props.PointerProperty(type=AnimationStitchSettings) + +bpy.types.Armature.mocapNLATracks = bpy.props.CollectionProperty(type=MocapNLATracks) + #Update function for IK functionality. Is called when IK prop checkboxes are toggled. @@ -246,6 +275,7 @@ class MocapPanel(bpy.types.Panel): mapRow = self.layout.row() mapRow.operator("mocap.savemapping", text='Save mapping') mapRow.operator("mocap.loadmapping", text='Load mapping') + self.layout.prop(data=performer_obj.animation_data.action, property='name', text='Action Name') self.layout.operator("mocap.retarget", text='RETARGET!') @@ -315,6 +345,16 @@ class ExtraToolsPanel(bpy.types.Panel): def draw(self, context): layout = self.layout layout.operator('mocap.pathediting', text="Follow Path") + layout.label("Animation Stitching") + activeIsArmature = isinstance(context.active_object.data, bpy.types.Armature) + if activeIsArmature: + enduser_arm = context.active_object.data + settings = enduser_arm.stitch_settings + layout.prop_search(settings, "first_action", enduser_arm, "mocapNLATracks") + layout.prop_search(settings, "second_action", enduser_arm, "mocapNLATracks") + layout.prop(settings, "blend_frame") + layout.prop(settings, "blend_amount") + layout.operator('mocap.animstitch', text="Stitch Animations") class OBJECT_OT_RetargetButton(bpy.types.Operator): @@ -323,15 +363,18 @@ class OBJECT_OT_RetargetButton(bpy.types.Operator): bl_label = "Retargets active action from Performer to Enduser" def execute(self, context): + scene = context.scene + s_frame = scene.frame_start + e_frame = scene.frame_end enduser_obj = context.active_object performer_obj = [obj for obj in context.selected_objects if obj != enduser_obj] if enduser_obj is None or len(performer_obj) != 1: print("Need active and selected armatures") else: performer_obj = performer_obj[0] - scene = context.scene - s_frame = scene.frame_start - e_frame = scene.frame_end + s_frame, e_frame = performer_obj.animation_data.action.frame_range + s_frame = int(s_frame) + e_frame = int(e_frame) retarget.totalRetarget(performer_obj, enduser_obj, scene, s_frame, e_frame) return {"FINISHED"} @@ -645,6 +688,26 @@ class OBJECT_OT_PathEditing(bpy.types.Operator): return False +class OBJECT_OT_AnimationStitchingButton(bpy.types.Operator): + '''Stitches two defined animations into a single one via alignment of NLA Tracks''' + bl_idname = "mocap.animstitch" + bl_label = "Stitches two defined animations into a single one via alignment of NLA Tracks" + + def execute(self, context): + mocap_tools.anim_stitch(context, context.active_object) + return {"FINISHED"} + + @classmethod + def poll(cls, context): + activeIsArmature = False + if context.active_object: + activeIsArmature = isinstance(context.active_object.data, bpy.types.Armature) + if activeIsArmature: + stitch_settings = context.active_object.data.stitch_settings + return (stitch_settings.first_action and stitch_settings.second_action) + return False + + def register(): bpy.utils.register_module(__name__) -- cgit v1.2.3 From a672ab5e737202bede956a88357a96cf2728df15 Mon Sep 17 00:00:00 2001 From: Joerg Mueller Date: Tue, 9 Aug 2011 14:10:32 +0000 Subject: 3D Audio GSoC: Improved waveform drawing in the sequencer. * Drawing the waveform of a sequencer strip is now independent from whether the sound is cached or not. * Improved drawing of the waveform in the sequencer (especially speed!). * Making it possible to vertically zoom more in the sequencer to better see the waveform for lipsync. * Fixed a bug which crashed blender on loading a sound file via ffmpeg. --- release/scripts/startup/bl_ui/space_sequencer.py | 1 + 1 file changed, 1 insertion(+) (limited to 'release/scripts/startup') diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index 5320297dce2..19202088faf 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -638,6 +638,7 @@ class SEQUENCER_PT_sound(SequencerButtonsPanel, bpy.types.Panel): row.prop(strip.sound, "use_memory_cache") + layout.prop(strip, "waveform") layout.prop(strip, "volume") layout.prop(strip, "attenuation") layout.prop(strip, "pitch") -- cgit v1.2.3 From 8afad10f986f60e5ccfaed2798067ddcea9b5fcf Mon Sep 17 00:00:00 2001 From: Benjy Cook Date: Wed, 10 Aug 2011 18:40:14 +0000 Subject: Continued changes to storing of retargeted animation data, making it possible to easily switch between all retargeted clips, and stitch them with the future operator --- release/scripts/startup/ui_mocap.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'release/scripts/startup') diff --git a/release/scripts/startup/ui_mocap.py b/release/scripts/startup/ui_mocap.py index 3d034b0047a..01802893c4c 100644 --- a/release/scripts/startup/ui_mocap.py +++ b/release/scripts/startup/ui_mocap.py @@ -127,7 +127,6 @@ bpy.utils.register_class(AnimationStitchSettings) class MocapNLATracks(bpy.types.PropertyGroup): name = bpy.props.StringProperty() - active = bpy.props.BoolProperty() base_track = bpy.props.StringProperty() auto_fix_track = bpy.props.StringProperty() manual_fix_track = bpy.props.StringProperty() @@ -136,7 +135,7 @@ class MocapNLATracks(bpy.types.PropertyGroup): bpy.utils.register_class(MocapNLATracks) bpy.types.Armature.stitch_settings = bpy.props.PointerProperty(type=AnimationStitchSettings) - +bpy.types.Armature.active_mocap = bpy.props.StringProperty(update=retarget.NLASystemInitialize) bpy.types.Armature.mocapNLATracks = bpy.props.CollectionProperty(type=MocapNLATracks) #Update function for IK functionality. Is called when IK prop checkboxes are toggled. @@ -349,6 +348,8 @@ class ExtraToolsPanel(bpy.types.Panel): activeIsArmature = isinstance(context.active_object.data, bpy.types.Armature) if activeIsArmature: enduser_arm = context.active_object.data + layout.label("Retargeted Animations:") + layout.prop_search(enduser_arm, "active_mocap",enduser_arm, "mocapNLATracks") settings = enduser_arm.stitch_settings layout.prop_search(settings, "first_action", enduser_arm, "mocapNLATracks") layout.prop_search(settings, "second_action", enduser_arm, "mocapNLATracks") -- cgit v1.2.3 From fba1f50d0af22199f8d73aa6eb5e95e75c3f3d6a Mon Sep 17 00:00:00 2001 From: Benjy Cook Date: Wed, 10 Aug 2011 20:37:57 +0000 Subject: Mostly finished implementation of animation stitching, with lock bone functionality, allowing the user to choose a bone that maintains its position during the blend --- release/scripts/startup/ui_mocap.py | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'release/scripts/startup') diff --git a/release/scripts/startup/ui_mocap.py b/release/scripts/startup/ui_mocap.py index 01802893c4c..0788366547e 100644 --- a/release/scripts/startup/ui_mocap.py +++ b/release/scripts/startup/ui_mocap.py @@ -121,6 +121,12 @@ class AnimationStitchSettings(bpy.types.PropertyGroup): blend_amount = bpy.props.IntProperty(name="Blend amount", description="Size of blending transitiion, on both sides of the stitch", default=10) + second_offset = bpy.props.IntProperty(name="Second offset", + description="Frame offset for 2nd animation, where it should start", + default=10) + stick_bone = bpy.props.StringProperty(name="Stick Bone", + description="Bone to freeze during transition", + default="") bpy.utils.register_class(AnimationStitchSettings) @@ -355,6 +361,8 @@ class ExtraToolsPanel(bpy.types.Panel): layout.prop_search(settings, "second_action", enduser_arm, "mocapNLATracks") layout.prop(settings, "blend_frame") layout.prop(settings, "blend_amount") + layout.prop(settings, "second_offset") + layout.prop_search(settings, "stick_bone", context.active_object.pose, "bones") layout.operator('mocap.animstitch', text="Stitch Animations") -- cgit v1.2.3 From fee7337249342c3d5a332358883af9afe961f38d Mon Sep 17 00:00:00 2001 From: Joerg Mueller Date: Thu, 11 Aug 2011 11:41:24 +0000 Subject: 3D Audio GSoC: Adding a mono flag to mixdown non-mono sounds for 3D audio. * Added mono sound loading. * Bugfix: AUD_COMPARE_SPECS usage was wrong. * Bugfix: JOS resampler = instead of ==. * Bugfix: Change of a sound should apply settings in AUD_SequencerHandle. * Bugfix: Memory leak when canceling open sound operator. --- release/scripts/startup/bl_ui/properties_data_speaker.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'release/scripts/startup') diff --git a/release/scripts/startup/bl_ui/properties_data_speaker.py b/release/scripts/startup/bl_ui/properties_data_speaker.py index 45f2fa5d1f7..fe9f798af0c 100644 --- a/release/scripts/startup/bl_ui/properties_data_speaker.py +++ b/release/scripts/startup/bl_ui/properties_data_speaker.py @@ -63,7 +63,7 @@ class DATA_PT_speaker(DataButtonsPanel, bpy.types.Panel): split = layout.split(percentage=0.75) - split.template_ID(speaker, "sound", open="sound.open") + split.template_ID(speaker, "sound", open="sound.open_mono") split.prop(speaker, "muted") split = layout.split() -- cgit v1.2.3 From 87e9c0ffaa5f8f64ccdea5c2ce74dfbd0edf0e43 Mon Sep 17 00:00:00 2001 From: Benjy Cook Date: Thu, 11 Aug 2011 13:47:49 +0000 Subject: Advanced Retargeting option: If the end user armature is complex, on the level of Sintel/Mancandy rigs, the user is requested to mark Advanced Retargeting, and constraints will be semi automatically configured to retarget the animation and then Retargeting will bake and remove these constraints --- release/scripts/startup/ui_mocap.py | 51 +++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) (limited to 'release/scripts/startup') diff --git a/release/scripts/startup/ui_mocap.py b/release/scripts/startup/ui_mocap.py index 0788366547e..06d0bb0b415 100644 --- a/release/scripts/startup/ui_mocap.py +++ b/release/scripts/startup/ui_mocap.py @@ -140,9 +140,26 @@ class MocapNLATracks(bpy.types.PropertyGroup): bpy.utils.register_class(MocapNLATracks) + +def advancedRetargetToggle(self, context): + enduser_obj = context.active_object + performer_obj = [obj for obj in context.selected_objects if obj != enduser_obj] + if enduser_obj is None or len(performer_obj) != 1: + print("Need active and selected armatures") + return + else: + performer_obj = performer_obj[0] + if self.advancedRetarget: + retarget.preAdvancedRetargeting(performer_obj, enduser_obj) + else: + retarget.cleanTempConstraints(enduser_obj) + + + bpy.types.Armature.stitch_settings = bpy.props.PointerProperty(type=AnimationStitchSettings) bpy.types.Armature.active_mocap = bpy.props.StringProperty(update=retarget.NLASystemInitialize) bpy.types.Armature.mocapNLATracks = bpy.props.CollectionProperty(type=MocapNLATracks) +bpy.types.Armature.advancedRetarget = bpy.props.BoolProperty(default=False, update=advancedRetargetToggle) #Update function for IK functionality. Is called when IK prop checkboxes are toggled. @@ -189,7 +206,7 @@ def toggleIKBone(self, context): for bone in cnstrn_bone.parent_recursive: if not bone.is_in_ik_chain: bone.IKRetarget = False - + class MocapMapping(bpy.types.PropertyGroup): name = bpy.props.StringProperty() @@ -281,6 +298,7 @@ class MocapPanel(bpy.types.Panel): mapRow.operator("mocap.savemapping", text='Save mapping') mapRow.operator("mocap.loadmapping", text='Load mapping') self.layout.prop(data=performer_obj.animation_data.action, property='name', text='Action Name') + self.layout.prop(enduser_arm, "advancedRetarget", text='Advanced Retarget') self.layout.operator("mocap.retarget", text='RETARGET!') @@ -396,6 +414,35 @@ class OBJECT_OT_RetargetButton(bpy.types.Operator): return activeIsArmature and isinstance(performer_obj[0].data, bpy.types.Armature) else: return False + + + #~ class OBJECT_OT_AdvancedRetargetButton(bpy.types.Operator): + #~ '''Prepare for advanced retargeting ''' + #~ bl_idname = "mocap.preretarget" + #~ bl_label = "Prepares retarget of active action from Performer to Enduser" + + #~ def execute(self, context): + #~ scene = context.scene + #~ s_frame = scene.frame_start + #~ e_frame = scene.frame_end + #~ enduser_obj = context.active_object + #~ performer_obj = [obj for obj in context.selected_objects if obj != enduser_obj] + #~ if enduser_obj is None or len(performer_obj) != 1: + #~ print("Need active and selected armatures") + #~ else: + #~ performer_obj = performer_obj[0] + #~ retarget.preAdvancedRetargeting(performer_obj, enduser_obj) + #~ return {"FINISHED"} + + #~ @classmethod + #~ def poll(cls, context): + #~ if context.active_object: + #~ activeIsArmature = isinstance(context.active_object.data, bpy.types.Armature) + #~ performer_obj = [obj for obj in context.selected_objects if obj != context.active_object] + #~ if performer_obj: + #~ return activeIsArmature and isinstance(performer_obj[0].data, bpy.types.Armature) + #~ else: + #~ return False class OBJECT_OT_SaveMappingButton(bpy.types.Operator): @@ -715,7 +762,7 @@ class OBJECT_OT_AnimationStitchingButton(bpy.types.Operator): stitch_settings = context.active_object.data.stitch_settings return (stitch_settings.first_action and stitch_settings.second_action) return False - + def register(): bpy.utils.register_module(__name__) -- cgit v1.2.3 From 05b7ccb736b88b806d4df3c2f83aff9773756099 Mon Sep 17 00:00:00 2001 From: Benjy Cook Date: Thu, 11 Aug 2011 14:50:19 +0000 Subject: Optimizations following intensive profiling of retarget and other lengthy functions. Retargeting now takes ~30% less time --- release/scripts/startup/ui_mocap.py | 1 + 1 file changed, 1 insertion(+) (limited to 'release/scripts/startup') diff --git a/release/scripts/startup/ui_mocap.py b/release/scripts/startup/ui_mocap.py index 06d0bb0b415..dd5e6fa5d6d 100644 --- a/release/scripts/startup/ui_mocap.py +++ b/release/scripts/startup/ui_mocap.py @@ -25,6 +25,7 @@ from bpy import * import mocap_constraints import retarget import mocap_tools + ### reloads modules (for testing purposes only) from imp import reload reload(mocap_constraints) -- cgit v1.2.3 From f1a8c26aa3a8e3e3628d279ad32f3e1ea261a695 Mon Sep 17 00:00:00 2001 From: Benjy Cook Date: Thu, 11 Aug 2011 16:46:27 +0000 Subject: Additional work on animation stitching, now with auto-guess capability. Only a few bugs left, regarding animations translation --- release/scripts/startup/ui_mocap.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'release/scripts/startup') diff --git a/release/scripts/startup/ui_mocap.py b/release/scripts/startup/ui_mocap.py index dd5e6fa5d6d..19a96750e49 100644 --- a/release/scripts/startup/ui_mocap.py +++ b/release/scripts/startup/ui_mocap.py @@ -382,6 +382,7 @@ class ExtraToolsPanel(bpy.types.Panel): layout.prop(settings, "blend_amount") layout.prop(settings, "second_offset") layout.prop_search(settings, "stick_bone", context.active_object.pose, "bones") + layout.operator('mocap.animstitchguess', text="Guess Settings") layout.operator('mocap.animstitch', text="Stitch Animations") @@ -765,6 +766,25 @@ class OBJECT_OT_AnimationStitchingButton(bpy.types.Operator): return False +class OBJECT_OT_GuessAnimationStitchingButton(bpy.types.Operator): + '''Guesses the stitch frame and second offset for animation stitch''' + bl_idname = "mocap.animstitchguess" + bl_label = "Guesses the stitch frame and second offset for animation stitch" + + def execute(self, context): + mocap_tools.guess_anim_stitch(context, context.active_object) + return {"FINISHED"} + + @classmethod + def poll(cls, context): + activeIsArmature = False + if context.active_object: + activeIsArmature = isinstance(context.active_object.data, bpy.types.Armature) + if activeIsArmature: + stitch_settings = context.active_object.data.stitch_settings + return (stitch_settings.first_action and stitch_settings.second_action) + return False + def register(): bpy.utils.register_module(__name__) -- cgit v1.2.3 From 24b18fd154d17373525a12e0f9a58c78143262ee Mon Sep 17 00:00:00 2001 From: Benjy Cook Date: Fri, 12 Aug 2011 18:10:31 +0000 Subject: More work on Advanced Retargeting and some stride bone bugs --- release/scripts/startup/ui_mocap.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'release/scripts/startup') diff --git a/release/scripts/startup/ui_mocap.py b/release/scripts/startup/ui_mocap.py index 19a96750e49..82f76d66d1b 100644 --- a/release/scripts/startup/ui_mocap.py +++ b/release/scripts/startup/ui_mocap.py @@ -404,7 +404,11 @@ class OBJECT_OT_RetargetButton(bpy.types.Operator): s_frame, e_frame = performer_obj.animation_data.action.frame_range s_frame = int(s_frame) e_frame = int(e_frame) - retarget.totalRetarget(performer_obj, enduser_obj, scene, s_frame, e_frame) + if retarget.isRigAdvanced(enduser_obj) and not enduser_obj.data.advancedRetarget: + print("Recommended to use Advanced Retargeting method") + enduser_obj.data.advancedRetarget = True + else: + retarget.totalRetarget(performer_obj, enduser_obj, scene, s_frame, e_frame) return {"FINISHED"} @classmethod -- cgit v1.2.3 From c5ef9b62c1f7f407c42bb48fe3362fa6cf3cf101 Mon Sep 17 00:00:00 2001 From: Mitchell Stokes Date: Fri, 12 Aug 2011 20:53:29 +0000 Subject: BGE Animations: Adding an option to let users choose whether or not to lock animation updates to the framerate. If this option is enabled, animations are only updated at the same speed as the animation framerate. This can give a significant speed up in performance, but at the cost of smoothness in animations. I'm defaulting this behavior to off for now, which is the behavior seen in trunk. --- release/scripts/startup/bl_ui/properties_game.py | 1 + 1 file changed, 1 insertion(+) (limited to 'release/scripts/startup') diff --git a/release/scripts/startup/bl_ui/properties_game.py b/release/scripts/startup/bl_ui/properties_game.py index 58b2cacfbcc..dc397635452 100644 --- a/release/scripts/startup/bl_ui/properties_game.py +++ b/release/scripts/startup/bl_ui/properties_game.py @@ -342,6 +342,7 @@ class RENDER_PT_game_performance(RenderButtonsPanel, bpy.types.Panel): row = layout.row() row.prop(gs, "use_frame_rate") row.prop(gs, "use_display_lists") + row.prop(gs, "restrict_animation_updates") class RENDER_PT_game_display(RenderButtonsPanel, bpy.types.Panel): -- cgit v1.2.3 From aaeb498c26bf1241ab6f0b50976afdecd7636288 Mon Sep 17 00:00:00 2001 From: Benjy Cook Date: Sat, 13 Aug 2011 11:09:42 +0000 Subject: Added a small operator to ease mapping. When used, the hierarchy mapping field is filled with the currently selected (pose) bone. --- release/scripts/startup/ui_mocap.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'release/scripts/startup') diff --git a/release/scripts/startup/ui_mocap.py b/release/scripts/startup/ui_mocap.py index 82f76d66d1b..0820b6183f4 100644 --- a/release/scripts/startup/ui_mocap.py +++ b/release/scripts/startup/ui_mocap.py @@ -283,6 +283,7 @@ class MocapPanel(bpy.types.Panel): row.prop(data=bone, property='foot', text='', icon='POSE_DATA') row.label(bone.name) row.prop_search(bone, "map", enduser_arm, "bones") + row.operator("mocap.selectmap", text='', icon='CURSOR').perf_bone = bone.name label_mod = "FK" if bone.map: pose_bone = perf_pose_bones[bone.map] @@ -493,6 +494,37 @@ class OBJECT_OT_LoadMappingButton(bpy.types.Operator): return activeIsArmature and isinstance(performer_obj[0].data, bpy.types.Armature) else: return False + + +class OBJECT_OT_SelectMapBoneButton(bpy.types.Operator): + '''Select a bone for faster mapping''' + bl_idname = "mocap.selectmap" + bl_label = "Select a bone for faster mapping" + perf_bone = bpy.props.StringProperty() + + def execute(self, context): + enduser_obj = bpy.context.active_object + performer_obj = [obj for obj in bpy.context.selected_objects if obj != enduser_obj][0] + selectedBone = "" + for bone in enduser_obj.data.bones: + boneVis = bone.layers + for i in range(32): + if boneVis[i] and enduser_obj.data.layers[i]: + if bone.select: + selectedBone = bone.name + break + performer_obj.data.bones[self.perf_bone].map = selectedBone + return {"FINISHED"} + + @classmethod + def poll(cls, context): + if context.active_object: + activeIsArmature = isinstance(context.active_object.data, bpy.types.Armature) + performer_obj = [obj for obj in context.selected_objects if obj != context.active_object] + if performer_obj: + return activeIsArmature and isinstance(performer_obj[0].data, bpy.types.Armature) + else: + return False class OBJECT_OT_ConvertSamplesButton(bpy.types.Operator): -- cgit v1.2.3 From 2fef8f13f0189a8a748e6729081a4e5cb769314b Mon Sep 17 00:00:00 2001 From: Benjy Cook Date: Sat, 13 Aug 2011 18:46:34 +0000 Subject: Added argument to retargeting - step size. Allows retargeting every other 'step' frame, useful for previewing or faster retargeting. --- release/scripts/startup/ui_mocap.py | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'release/scripts/startup') diff --git a/release/scripts/startup/ui_mocap.py b/release/scripts/startup/ui_mocap.py index 0820b6183f4..9be26a3b2ff 100644 --- a/release/scripts/startup/ui_mocap.py +++ b/release/scripts/startup/ui_mocap.py @@ -161,6 +161,10 @@ bpy.types.Armature.stitch_settings = bpy.props.PointerProperty(type=AnimationSti bpy.types.Armature.active_mocap = bpy.props.StringProperty(update=retarget.NLASystemInitialize) bpy.types.Armature.mocapNLATracks = bpy.props.CollectionProperty(type=MocapNLATracks) bpy.types.Armature.advancedRetarget = bpy.props.BoolProperty(default=False, update=advancedRetargetToggle) +bpy.types.Armature.frameStep = smooth_out = bpy.props.IntProperty(name="Frame Skip", + default=1, + description="Amount of frames to skip - for previewing retargets quickly. 1 is fully sampled", + min=1) #Update function for IK functionality. Is called when IK prop checkboxes are toggled. @@ -301,6 +305,7 @@ class MocapPanel(bpy.types.Panel): mapRow.operator("mocap.loadmapping", text='Load mapping') self.layout.prop(data=performer_obj.animation_data.action, property='name', text='Action Name') self.layout.prop(enduser_arm, "advancedRetarget", text='Advanced Retarget') + self.layout.prop(enduser_arm, "frameStep") self.layout.operator("mocap.retarget", text='RETARGET!') -- cgit v1.2.3 From c8ae881b619ec2d2d05b3c55283ca1f4c69828ca Mon Sep 17 00:00:00 2001 From: Benjy Cook Date: Mon, 15 Aug 2011 10:18:02 +0000 Subject: Added option to each retargeted bone to fix twist issues caused by variable bone rolls and unknown axis differences. Also made retarget operator a single undo --- release/scripts/startup/ui_mocap.py | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'release/scripts/startup') diff --git a/release/scripts/startup/ui_mocap.py b/release/scripts/startup/ui_mocap.py index 9be26a3b2ff..23354f9d722 100644 --- a/release/scripts/startup/ui_mocap.py +++ b/release/scripts/startup/ui_mocap.py @@ -223,6 +223,9 @@ bpy.types.Bone.reverseMap = bpy.props.CollectionProperty(type=MocapMapping) bpy.types.Bone.foot = bpy.props.BoolProperty(name="Foot", description="Marks this bone as a 'foot', which determines retargeted animation's translation", default=False) +bpy.types.Bone.twistFix = bpy.props.BoolProperty(name="Twist Fix", + description="Fix Twist on this bone", + default=False) bpy.types.PoseBone.IKRetarget = bpy.props.BoolProperty(name="IK", description="Toggles IK Retargeting method for given bone", update=toggleIKBone, default=False) @@ -295,6 +298,7 @@ class MocapPanel(bpy.types.Panel): label_mod = "ik chain" if hasIKConstraint(pose_bone): label_mod = "ik end" + row.prop(data=bone, property='twistFix', text='', icon='RNA') row.prop(pose_bone, 'IKRetarget') row.label(label_mod) else: @@ -396,6 +400,7 @@ class OBJECT_OT_RetargetButton(bpy.types.Operator): '''Retarget animation from selected armature to active armature ''' bl_idname = "mocap.retarget" bl_label = "Retargets active action from Performer to Enduser" + bl_options = {'REGISTER', 'UNDO'} def execute(self, context): scene = context.scene -- cgit v1.2.3 From cbbbf31315bf57aed5ccfec02f29495b2e3767ec Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Mon, 15 Aug 2011 13:24:53 +0000 Subject: Restoring "Clear User Transforms" operator This can now be found as Pose -> Clear Transforms -> Reset Unkeyed, or via the operator search (known by its old name there) --- release/scripts/startup/bl_ui/space_view3d.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'release/scripts/startup') diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index c1973bc8555..c38bc0abc96 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -1262,11 +1262,15 @@ class VIEW3D_MT_pose_transform(bpy.types.Menu): layout.operator("pose.transforms_clear", text="All") + layout.separator() + layout.operator("pose.loc_clear", text="Location") layout.operator("pose.rot_clear", text="Rotation") layout.operator("pose.scale_clear", text="Scale") - layout.label(text="Origin") + layout.separator() + + layout.operator("pose.user_transforms_clear", text="Reset unkeyed") class VIEW3D_MT_pose_slide(bpy.types.Menu): -- cgit v1.2.3 From 87efb89901e36fbf72ed6f7ec0e6b6392946594f Mon Sep 17 00:00:00 2001 From: Joerg Mueller Date: Tue, 16 Aug 2011 14:43:04 +0000 Subject: Py fix for trunk to pepper merge. --- release/scripts/startup/bl_ui/properties_data_armature.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'release/scripts/startup') diff --git a/release/scripts/startup/bl_ui/properties_data_armature.py b/release/scripts/startup/bl_ui/properties_data_armature.py index cddf9fef0f2..9a76ed81530 100644 --- a/release/scripts/startup/bl_ui/properties_data_armature.py +++ b/release/scripts/startup/bl_ui/properties_data_armature.py @@ -18,7 +18,7 @@ # import bpy -from bpy.types import Panel +from bpy.types import Panel, Menu from rna_prop_ui import PropertyPanel -- cgit v1.2.3 From 78b147fbc20cc5cbd30057474686a5fb91124fab Mon Sep 17 00:00:00 2001 From: Benjy Cook Date: Wed, 17 Aug 2011 10:13:24 +0000 Subject: Commenting and pep8 compliance --- release/scripts/startup/ui_mocap.py | 86 ++++++++++++++++++++----------------- 1 file changed, 47 insertions(+), 39 deletions(-) (limited to 'release/scripts/startup') diff --git a/release/scripts/startup/ui_mocap.py b/release/scripts/startup/ui_mocap.py index 23354f9d722..3cb33776b0b 100644 --- a/release/scripts/startup/ui_mocap.py +++ b/release/scripts/startup/ui_mocap.py @@ -112,6 +112,7 @@ bpy.utils.register_class(MocapConstraint) bpy.types.Armature.mocap_constraints = bpy.props.CollectionProperty(type=MocapConstraint) +# Animation Stitch Settings, used for animation stitching of 2 retargeted animations. class AnimationStitchSettings(bpy.types.PropertyGroup): first_action = bpy.props.StringProperty(name="Action 1", description="First action in stitch") @@ -132,6 +133,7 @@ class AnimationStitchSettings(bpy.types.PropertyGroup): bpy.utils.register_class(AnimationStitchSettings) +# MocapNLA Tracks. Stores which tracks/actions are associated with each retargeted animation. class MocapNLATracks(bpy.types.PropertyGroup): name = bpy.props.StringProperty() base_track = bpy.props.StringProperty() @@ -141,7 +143,8 @@ class MocapNLATracks(bpy.types.PropertyGroup): bpy.utils.register_class(MocapNLATracks) - + +#Update function for Advanced Retarget boolean variable. def advancedRetargetToggle(self, context): enduser_obj = context.active_object performer_obj = [obj for obj in context.selected_objects if obj != enduser_obj] @@ -156,20 +159,23 @@ def advancedRetargetToggle(self, context): retarget.cleanTempConstraints(enduser_obj) - +#Animation Stitch Settings Property bpy.types.Armature.stitch_settings = bpy.props.PointerProperty(type=AnimationStitchSettings) -bpy.types.Armature.active_mocap = bpy.props.StringProperty(update=retarget.NLASystemInitialize) +#Current/Active retargeted animation on the armature +bpy.types.Armature.active_mocap = bpy.props.StringProperty(update=retarget.NLASystemInitialize) +#Collection of retargeted animations and their NLA Tracks on the armature bpy.types.Armature.mocapNLATracks = bpy.props.CollectionProperty(type=MocapNLATracks) +#Advanced retargeting boolean property bpy.types.Armature.advancedRetarget = bpy.props.BoolProperty(default=False, update=advancedRetargetToggle) +#frame step - frequency of frames to retarget. Skipping is useful for previewing, faster work etc. bpy.types.Armature.frameStep = smooth_out = bpy.props.IntProperty(name="Frame Skip", default=1, description="Amount of frames to skip - for previewing retargets quickly. 1 is fully sampled", min=1) -#Update function for IK functionality. Is called when IK prop checkboxes are toggled. - def toggleIKBone(self, context): + #Update function for IK functionality. Is called when IK prop checkboxes are toggled. if self.IKRetarget: if not self.is_in_ik_chain: print(self.name + " IK toggled ON!") @@ -211,21 +217,29 @@ def toggleIKBone(self, context): for bone in cnstrn_bone.parent_recursive: if not bone.is_in_ik_chain: bone.IKRetarget = False - + +#MocapMap class for storing mapping on enduser performer, +# where a bone may be linked to more than one on the performer class MocapMapping(bpy.types.PropertyGroup): name = bpy.props.StringProperty() bpy.utils.register_class(MocapMapping) +#string property for storing performer->enduser mapping bpy.types.Bone.map = bpy.props.StringProperty() +#Collection Property for storing enduser->performer mapping bpy.types.Bone.reverseMap = bpy.props.CollectionProperty(type=MocapMapping) +#Boolean property for storing foot bone toggle bpy.types.Bone.foot = bpy.props.BoolProperty(name="Foot", description="Marks this bone as a 'foot', which determines retargeted animation's translation", default=False) +#Boolean property for storing if this bone is twisted along the y axis, +# which can happen due to various sources of performers bpy.types.Bone.twistFix = bpy.props.BoolProperty(name="Twist Fix", description="Fix Twist on this bone", default=False) +#Boolean property for toggling ik retargeting for this bone bpy.types.PoseBone.IKRetarget = bpy.props.BoolProperty(name="IK", description="Toggles IK Retargeting method for given bone", update=toggleIKBone, default=False) @@ -384,7 +398,7 @@ class ExtraToolsPanel(bpy.types.Panel): if activeIsArmature: enduser_arm = context.active_object.data layout.label("Retargeted Animations:") - layout.prop_search(enduser_arm, "active_mocap",enduser_arm, "mocapNLATracks") + layout.prop_search(enduser_arm, "active_mocap", enduser_arm, "mocapNLATracks") settings = enduser_arm.stitch_settings layout.prop_search(settings, "first_action", enduser_arm, "mocapNLATracks") layout.prop_search(settings, "second_action", enduser_arm, "mocapNLATracks") @@ -397,6 +411,8 @@ class ExtraToolsPanel(bpy.types.Panel): class OBJECT_OT_RetargetButton(bpy.types.Operator): + #Retargeting operator. Assumes selected and active armatures, where the performer (the selected one) + # has an action for retargeting '''Retarget animation from selected armature to active armature ''' bl_idname = "mocap.retarget" bl_label = "Retargets active action from Performer to Enduser" @@ -428,41 +444,13 @@ class OBJECT_OT_RetargetButton(bpy.types.Operator): activeIsArmature = isinstance(context.active_object.data, bpy.types.Armature) performer_obj = [obj for obj in context.selected_objects if obj != context.active_object] if performer_obj: - return activeIsArmature and isinstance(performer_obj[0].data, bpy.types.Armature) + return activeIsArmature and isinstance(performer_obj[0].data, bpy.types.Armature) and performer_obj[0].animation_data else: return False - - - #~ class OBJECT_OT_AdvancedRetargetButton(bpy.types.Operator): - #~ '''Prepare for advanced retargeting ''' - #~ bl_idname = "mocap.preretarget" - #~ bl_label = "Prepares retarget of active action from Performer to Enduser" - - #~ def execute(self, context): - #~ scene = context.scene - #~ s_frame = scene.frame_start - #~ e_frame = scene.frame_end - #~ enduser_obj = context.active_object - #~ performer_obj = [obj for obj in context.selected_objects if obj != enduser_obj] - #~ if enduser_obj is None or len(performer_obj) != 1: - #~ print("Need active and selected armatures") - #~ else: - #~ performer_obj = performer_obj[0] - #~ retarget.preAdvancedRetargeting(performer_obj, enduser_obj) - #~ return {"FINISHED"} - - #~ @classmethod - #~ def poll(cls, context): - #~ if context.active_object: - #~ activeIsArmature = isinstance(context.active_object.data, bpy.types.Armature) - #~ performer_obj = [obj for obj in context.selected_objects if obj != context.active_object] - #~ if performer_obj: - #~ return activeIsArmature and isinstance(performer_obj[0].data, bpy.types.Armature) - #~ else: - #~ return False class OBJECT_OT_SaveMappingButton(bpy.types.Operator): + #Operator for saving mapping to enduser armature '''Save mapping to active armature (for future retargets) ''' bl_idname = "mocap.savemapping" bl_label = "Saves user generated mapping from Performer to Enduser" @@ -486,6 +474,7 @@ class OBJECT_OT_SaveMappingButton(bpy.types.Operator): class OBJECT_OT_LoadMappingButton(bpy.types.Operator): '''Load saved mapping from active armature''' + #Operator for loading mapping to enduser armature bl_idname = "mocap.loadmapping" bl_label = "Loads user generated mapping from Performer to Enduser" @@ -504,9 +493,10 @@ class OBJECT_OT_LoadMappingButton(bpy.types.Operator): return activeIsArmature and isinstance(performer_obj[0].data, bpy.types.Armature) else: return False - + class OBJECT_OT_SelectMapBoneButton(bpy.types.Operator): + #Operator for setting selected bone in enduser armature to the performer mapping '''Select a bone for faster mapping''' bl_idname = "mocap.selectmap" bl_label = "Select a bone for faster mapping" @@ -538,6 +528,7 @@ class OBJECT_OT_SelectMapBoneButton(bpy.types.Operator): class OBJECT_OT_ConvertSamplesButton(bpy.types.Operator): + #Operator to convert samples to beziers on the selected object '''Convert active armature's sampled keyframed to beziers''' bl_idname = "mocap.samples" bl_label = "Converts samples / simplifies keyframes to beziers" @@ -552,6 +543,7 @@ class OBJECT_OT_ConvertSamplesButton(bpy.types.Operator): class OBJECT_OT_LooperButton(bpy.types.Operator): + #Operator to trim fcurves which contain a few loops to a single one on the selected object '''Trim active armature's animation to a single cycle, given a cyclic animation (such as a walk cycle)''' bl_idname = "mocap.looper" bl_label = "loops animation / sampled mocap data" @@ -566,6 +558,7 @@ class OBJECT_OT_LooperButton(bpy.types.Operator): class OBJECT_OT_DenoiseButton(bpy.types.Operator): + #Operator to denoise impluse noise on the active object's fcurves '''Denoise active armature's animation. Good for dealing with 'bad' frames inherent in mocap animation''' bl_idname = "mocap.denoise" bl_label = "Denoises sampled mocap data " @@ -584,6 +577,7 @@ class OBJECT_OT_DenoiseButton(bpy.types.Operator): class OBJECT_OT_LimitDOFButton(bpy.types.Operator): + #Operator to analyze performer armature and apply rotation constraints on the enduser armature '''Create limit constraints on the active armature from the selected armature's animation's range of motion''' bl_idname = "mocap.limitdof" bl_label = "Analyzes animations Max/Min DOF and adds hard/soft constraints" @@ -605,6 +599,7 @@ class OBJECT_OT_LimitDOFButton(bpy.types.Operator): class OBJECT_OT_RemoveLimitDOFButton(bpy.types.Operator): + #Removes constraints created by above operator '''Removes previously created limit constraints on the active armature''' bl_idname = "mocap.removelimitdof" bl_label = "Removes previously created limit constraints on the active armature" @@ -622,6 +617,7 @@ class OBJECT_OT_RemoveLimitDOFButton(bpy.types.Operator): class OBJECT_OT_RotateFixArmature(bpy.types.Operator): + #Operator to fix common imported Mocap data issue of wrong axis system on active object '''Realign the active armature's axis system to match Blender (Commonly needed after bvh import)''' bl_idname = "mocap.rotate_fix" bl_label = "Rotates selected armature 90 degrees (fix for bvh import)" @@ -637,6 +633,7 @@ class OBJECT_OT_RotateFixArmature(bpy.types.Operator): class OBJECT_OT_ScaleFixArmature(bpy.types.Operator): + #Operator to scale down the selected armature to match the active one '''Rescale selected armature to match the active animation, for convienence''' bl_idname = "mocap.scale_fix" bl_label = "Scales performer armature to match target armature" @@ -659,6 +656,7 @@ class OBJECT_OT_ScaleFixArmature(bpy.types.Operator): class MOCAP_OT_AddMocapFix(bpy.types.Operator): + #Operator to add a post-retarget fix '''Add a post-retarget fix - useful for fixing certain artifacts following the retarget''' bl_idname = "mocap.addmocapfix" bl_label = "Add Mocap Fix to target armature" @@ -683,6 +681,7 @@ class MOCAP_OT_AddMocapFix(bpy.types.Operator): class OBJECT_OT_RemoveMocapConstraint(bpy.types.Operator): + #Operator to remove a post-retarget fix '''Remove this post-retarget fix''' bl_idname = "mocap.removeconstraint" bl_label = "Removes fixes from target armature" @@ -707,6 +706,7 @@ class OBJECT_OT_RemoveMocapConstraint(bpy.types.Operator): class OBJECT_OT_BakeMocapConstraints(bpy.types.Operator): + #Operator to bake all post-retarget fixes '''Bake all post-retarget fixes to the Retarget Fixes NLA Track''' bl_idname = "mocap.bakeconstraints" bl_label = "Bake all fixes to target armature" @@ -722,6 +722,7 @@ class OBJECT_OT_BakeMocapConstraints(bpy.types.Operator): class OBJECT_OT_UnbakeMocapConstraints(bpy.types.Operator): + #Operator to unbake all post-retarget fixes '''Unbake all post-retarget fixes - removes the baked data from the Retarget Fixes NLA Track''' bl_idname = "mocap.unbakeconstraints" bl_label = "Unbake all fixes to target armature" @@ -737,6 +738,8 @@ class OBJECT_OT_UnbakeMocapConstraints(bpy.types.Operator): class OBJECT_OT_UpdateMocapConstraints(bpy.types.Operator): + #Operator to update all post-retarget fixes, similar to update dependencies on drivers + #Needed because python properties lack certain callbacks and some fixes take a while to recalculate. '''Updates all post-retarget fixes - needed after changes to armature object or pose''' bl_idname = "mocap.updateconstraints" bl_label = "Updates all fixes to target armature - neccesary to take under consideration changes to armature object or pose" @@ -752,6 +755,7 @@ class OBJECT_OT_UpdateMocapConstraints(bpy.types.Operator): class OBJECT_OT_GuessHierachyMapping(bpy.types.Operator): + #Operator which calls heurisitic function to guess mapping between 2 armatures '''Attemps to auto figure out hierarchy mapping''' bl_idname = "mocap.guessmapping" bl_label = "Attemps to auto figure out hierarchy mapping" @@ -774,6 +778,7 @@ class OBJECT_OT_GuessHierachyMapping(bpy.types.Operator): class OBJECT_OT_PathEditing(bpy.types.Operator): + #Operator which calls path editing function, making active object follow the selected curve. '''Sets active object (stride object) to follow the selected curve''' bl_idname = "mocap.pathediting" bl_label = "Sets active object (stride object) to follow the selected curve" @@ -793,6 +798,7 @@ class OBJECT_OT_PathEditing(bpy.types.Operator): class OBJECT_OT_AnimationStitchingButton(bpy.types.Operator): + #Operator which calls stitching function, combining 2 animations onto the NLA. '''Stitches two defined animations into a single one via alignment of NLA Tracks''' bl_idname = "mocap.animstitch" bl_label = "Stitches two defined animations into a single one via alignment of NLA Tracks" @@ -810,9 +816,10 @@ class OBJECT_OT_AnimationStitchingButton(bpy.types.Operator): stitch_settings = context.active_object.data.stitch_settings return (stitch_settings.first_action and stitch_settings.second_action) return False - + class OBJECT_OT_GuessAnimationStitchingButton(bpy.types.Operator): + #Operator which calls stitching function heuristic, setting good values for above operator. '''Guesses the stitch frame and second offset for animation stitch''' bl_idname = "mocap.animstitchguess" bl_label = "Guesses the stitch frame and second offset for animation stitch" @@ -831,6 +838,7 @@ class OBJECT_OT_GuessAnimationStitchingButton(bpy.types.Operator): return (stitch_settings.first_action and stitch_settings.second_action) return False + def register(): bpy.utils.register_module(__name__) -- cgit v1.2.3 From 06ae5e48258dacc5598b23286d46891be32a08e5 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Mon, 22 Aug 2011 02:14:39 +0000 Subject: Reshuffling DopeSheet filter icons so that they appear more obviously related to each other --- release/scripts/startup/bl_ui/space_dopesheet.py | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'release/scripts/startup') diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py index cab58a3aadb..74ae427c5cf 100644 --- a/release/scripts/startup/bl_ui/space_dopesheet.py +++ b/release/scripts/startup/bl_ui/space_dopesheet.py @@ -35,7 +35,7 @@ def dopesheet_filter(layout, context, genericFiltersOnly=False): row.prop(dopesheet, "show_hidden", text="") if is_nla: - row.prop(dopesheet, "show_missing_nla", text="") + row.prop(dopesheet, "show_missing_nla", text="") if not genericFiltersOnly: if bpy.data.groups: @@ -50,21 +50,16 @@ def dopesheet_filter(layout, context, genericFiltersOnly=False): if dopesheet.show_only_matching_fcurves: row.prop(dopesheet, "filter_fcurve_name", text="") - row = layout.row() - row.prop(dopesheet, "show_datablock_filters", text="Filters", icon='DISCLOSURE_TRI_RIGHT') + row = layout.row(align=True) + row.prop(dopesheet, "show_datablock_filters", text="Filters") if (not genericFiltersOnly) and (dopesheet.show_datablock_filters): - # TODO: put a box around these? - subrow = row.row() - - row = subrow.row(align=True) - row.prop(dopesheet, "show_transforms", text="") - - row = subrow.row(align=True) row.prop(dopesheet, "show_scenes", text="") row.prop(dopesheet, "show_worlds", text="") row.prop(dopesheet, "show_nodes", text="") + row.prop(dopesheet, "show_transforms", text="") + if bpy.data.meshes: row.prop(dopesheet, "show_meshes", text="") if bpy.data.shape_keys: -- cgit v1.2.3 From a594196dc0cf0482aab7d16b4cfee1a7d3b8707d Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Mon, 22 Aug 2011 02:30:43 +0000 Subject: Bugfix: "Filters" toggle was being shown in Action Editor too, where it was irrelevant --- release/scripts/startup/bl_ui/space_dopesheet.py | 69 ++++++++++++------------ 1 file changed, 35 insertions(+), 34 deletions(-) (limited to 'release/scripts/startup') diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py index 74ae427c5cf..a2a51f9587f 100644 --- a/release/scripts/startup/bl_ui/space_dopesheet.py +++ b/release/scripts/startup/bl_ui/space_dopesheet.py @@ -50,40 +50,41 @@ def dopesheet_filter(layout, context, genericFiltersOnly=False): if dopesheet.show_only_matching_fcurves: row.prop(dopesheet, "filter_fcurve_name", text="") - row = layout.row(align=True) - row.prop(dopesheet, "show_datablock_filters", text="Filters") - - if (not genericFiltersOnly) and (dopesheet.show_datablock_filters): - row.prop(dopesheet, "show_scenes", text="") - row.prop(dopesheet, "show_worlds", text="") - row.prop(dopesheet, "show_nodes", text="") - - row.prop(dopesheet, "show_transforms", text="") - - if bpy.data.meshes: - row.prop(dopesheet, "show_meshes", text="") - if bpy.data.shape_keys: - row.prop(dopesheet, "show_shapekeys", text="") - if bpy.data.materials: - row.prop(dopesheet, "show_materials", text="") - if bpy.data.lamps: - row.prop(dopesheet, "show_lamps", text="") - if bpy.data.textures: - row.prop(dopesheet, "show_textures", text="") - if bpy.data.cameras: - row.prop(dopesheet, "show_cameras", text="") - if bpy.data.curves: - row.prop(dopesheet, "show_curves", text="") - if bpy.data.metaballs: - row.prop(dopesheet, "show_metaballs", text="") - if bpy.data.lattices: - row.prop(dopesheet, "show_lattices", text="") - if bpy.data.armatures: - row.prop(dopesheet, "show_armatures", text="") - if bpy.data.particles: - row.prop(dopesheet, "show_particles", text="") - if bpy.data.speakers: - row.prop(dopesheet, "show_speakers", text="") + if not genericFiltersOnly: + row = layout.row(align=True) + row.prop(dopesheet, "show_datablock_filters", text="Filters") + + if dopesheet.show_datablock_filters: + row.prop(dopesheet, "show_scenes", text="") + row.prop(dopesheet, "show_worlds", text="") + row.prop(dopesheet, "show_nodes", text="") + + row.prop(dopesheet, "show_transforms", text="") + + if bpy.data.meshes: + row.prop(dopesheet, "show_meshes", text="") + if bpy.data.shape_keys: + row.prop(dopesheet, "show_shapekeys", text="") + if bpy.data.materials: + row.prop(dopesheet, "show_materials", text="") + if bpy.data.lamps: + row.prop(dopesheet, "show_lamps", text="") + if bpy.data.textures: + row.prop(dopesheet, "show_textures", text="") + if bpy.data.cameras: + row.prop(dopesheet, "show_cameras", text="") + if bpy.data.curves: + row.prop(dopesheet, "show_curves", text="") + if bpy.data.metaballs: + row.prop(dopesheet, "show_metaballs", text="") + if bpy.data.lattices: + row.prop(dopesheet, "show_lattices", text="") + if bpy.data.armatures: + row.prop(dopesheet, "show_armatures", text="") + if bpy.data.particles: + row.prop(dopesheet, "show_particles", text="") + if bpy.data.speakers: + row.prop(dopesheet, "show_speakers", text="") ####################################### -- cgit v1.2.3 From a71c215f228173070d41faef1321db25b40d723e Mon Sep 17 00:00:00 2001 From: Joerg Mueller Date: Mon, 22 Aug 2011 18:59:56 +0000 Subject: 3D Audio GSoC: Final GSoC commit. * Bugfix: Negative frames crashed * Bugfix: JOS sample buffer size prediction error (wasted memory) * Optimisation: for JOS upsampling (around 12 % difference measured here) * Optimisation: Better filter for JOS resampling * Bugfix: Error in relative 3D audio code. * Removed Attenuation * Bugfix: Multiple scenes in BGE lead to errors, BGE audio now all relative, to support multiple scenes. --- release/scripts/startup/bl_ui/space_sequencer.py | 1 - 1 file changed, 1 deletion(-) (limited to 'release/scripts/startup') diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index f796ce8da5f..cebe78ff627 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -653,7 +653,6 @@ class SEQUENCER_PT_sound(SequencerButtonsPanel, Panel): layout.prop(strip, "waveform") layout.prop(strip, "volume") - layout.prop(strip, "attenuation") layout.prop(strip, "pitch") layout.prop(strip, "pan") -- cgit v1.2.3 From 9a9513a9f09f5524235e202a095b04863a07a52b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 23 Aug 2011 19:58:15 +0000 Subject: fix for 3 bugs in bone renaming - renaming a bone could crash if the area had to spaces in it (reported by Sebastian Koenig). - renaming bones wouldn't update inactive 3d views locked bone names. - selecting locked bones in the UI didnt work in editmode. --- release/scripts/startup/bl_ui/space_view3d.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'release/scripts/startup') diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index fa22e216ec9..dd705f76feb 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -2073,9 +2073,11 @@ class VIEW3D_PT_view3d_properties(Panel): col.prop(view, "lens") col.label(text="Lock to Object:") col.prop(view, "lock_object", text="") - if view.lock_object and view.lock_object.type == 'ARMATURE': - col.prop_search(view, "lock_bone", view.lock_object.data, "bones", text="") - elif not view.lock_object: + lock_object = view.lock_object + if lock_object: + if lock_object.type == 'ARMATURE': + col.prop_search(view, "lock_bone", lock_object.data, "edit_bones" if lock_object.mode == 'EDIT' else "bones", text="") + else: col.prop(view, "lock_cursor", text="Lock to Cursor") col = layout.column() -- cgit v1.2.3 From 752cb7485de8d06b261084eac3ab1c259a20ead3 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 27 Aug 2011 12:01:01 +0000 Subject: Do not show confirm message when creating text block from menu. --- release/scripts/startup/bl_ui/space_text.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'release/scripts/startup') diff --git a/release/scripts/startup/bl_ui/space_text.py b/release/scripts/startup/bl_ui/space_text.py index 300211a26bf..12e07c19ca1 100644 --- a/release/scripts/startup/bl_ui/space_text.py +++ b/release/scripts/startup/bl_ui/space_text.py @@ -172,7 +172,9 @@ class TEXT_MT_text(Menu): st = context.space_data text = st.text + layout.operator_context = 'EXEC_AREA' layout.operator("text.new") + layout.operator_context = 'INVOKE_AREA' layout.operator("text.open") if text: -- cgit v1.2.3 From b4b046995b21d59e315eb71ed08fc1ae066c891b Mon Sep 17 00:00:00 2001 From: Joerg Mueller Date: Sun, 28 Aug 2011 14:21:44 +0000 Subject: * Removing mocap GSoC (is an addon already). * Fixing ffmpeg-0.8 errors. * Fixing Ketsji paths. * Removing DoSound from BGE. * Fixing audio scene update to use only current scene objects. --- release/scripts/startup/ui_mocap.py | 850 ------------------------------------ 1 file changed, 850 deletions(-) delete mode 100644 release/scripts/startup/ui_mocap.py (limited to 'release/scripts/startup') diff --git a/release/scripts/startup/ui_mocap.py b/release/scripts/startup/ui_mocap.py deleted file mode 100644 index 3cb33776b0b..00000000000 --- a/release/scripts/startup/ui_mocap.py +++ /dev/null @@ -1,850 +0,0 @@ -# ##### BEGIN GPL LICENSE BLOCK ##### -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# ##### END GPL LICENSE BLOCK ##### - -# - -import bpy - -from bpy.props import * -from bpy import * -import mocap_constraints -import retarget -import mocap_tools - -### reloads modules (for testing purposes only) -from imp import reload -reload(mocap_constraints) -reload(retarget) -reload(mocap_tools) - -from mocap_constraints import * - -# MocapConstraint class -# Defines MocapConstraint datatype, used to add and configute mocap constraints -# Attached to Armature data - - -class MocapConstraint(bpy.types.PropertyGroup): - name = bpy.props.StringProperty(name="Name", - default="Mocap Fix", - description="Name of Mocap Fix", - update=setConstraint) - constrained_bone = bpy.props.StringProperty(name="Bone", - default="", - description="Constrained Bone", - update=updateConstraintBoneType) - constrained_boneB = bpy.props.StringProperty(name="Bone (2)", - default="", - description="Other Constrained Bone (optional, depends on type)", - update=setConstraint) - s_frame = bpy.props.IntProperty(name="S", - default=0, - description="Start frame of Fix", - update=setConstraint) - e_frame = bpy.props.IntProperty(name="E", - default=100, - description="End frame of Fix", - update=setConstraint) - smooth_in = bpy.props.IntProperty(name="In", - default=10, - description="Amount of frames to smooth in", - update=setConstraint, - min=0) - smooth_out = bpy.props.IntProperty(name="Out", - default=10, - description="Amount of frames to smooth out", - update=setConstraint, - min=0) - targetMesh = bpy.props.StringProperty(name="Mesh", - default="", - description="Target of Fix - Mesh (optional, depends on type)", - update=setConstraint) - active = bpy.props.BoolProperty(name="Active", - default=True, - description="Fix is active", - update=setConstraint) - show_expanded = bpy.props.BoolProperty(name="Show Expanded", - default=True, - description="Fix is fully shown") - targetPoint = bpy.props.FloatVectorProperty(name="Point", size=3, - subtype="XYZ", default=(0.0, 0.0, 0.0), - description="Target of Fix - Point", - update=setConstraint) - targetDist = bpy.props.FloatProperty(name="Offset", - default=0.0, - description="Distance and Floor Fixes - Desired offset", - update=setConstraint) - targetSpace = bpy.props.EnumProperty( - items=[("WORLD", "World Space", "Evaluate target in global space"), - ("LOCAL", "Object space", "Evaluate target in object space"), - ("constrained_boneB", "Other Bone Space", "Evaluate target in specified other bone space")], - name="Space", - description="In which space should Point type target be evaluated", - update=setConstraint) - type = bpy.props.EnumProperty(name="Type of constraint", - items=[("point", "Maintain Position", "Bone is at a specific point"), - ("freeze", "Maintain Position at frame", "Bone does not move from location specified in target frame"), - ("floor", "Stay above", "Bone does not cross specified mesh object eg floor"), - ("distance", "Maintain distance", "Target bones maintained specified distance")], - description="Type of Fix", - update=updateConstraintBoneType) - real_constraint = bpy.props.StringProperty() - real_constraint_bone = bpy.props.StringProperty() - - -bpy.utils.register_class(MocapConstraint) - -bpy.types.Armature.mocap_constraints = bpy.props.CollectionProperty(type=MocapConstraint) - - -# Animation Stitch Settings, used for animation stitching of 2 retargeted animations. -class AnimationStitchSettings(bpy.types.PropertyGroup): - first_action = bpy.props.StringProperty(name="Action 1", - description="First action in stitch") - second_action = bpy.props.StringProperty(name="Action 2", - description="Second action in stitch") - blend_frame = bpy.props.IntProperty(name="Stitch frame", - description="Frame to locate stitch on") - blend_amount = bpy.props.IntProperty(name="Blend amount", - description="Size of blending transitiion, on both sides of the stitch", - default=10) - second_offset = bpy.props.IntProperty(name="Second offset", - description="Frame offset for 2nd animation, where it should start", - default=10) - stick_bone = bpy.props.StringProperty(name="Stick Bone", - description="Bone to freeze during transition", - default="") - -bpy.utils.register_class(AnimationStitchSettings) - - -# MocapNLA Tracks. Stores which tracks/actions are associated with each retargeted animation. -class MocapNLATracks(bpy.types.PropertyGroup): - name = bpy.props.StringProperty() - base_track = bpy.props.StringProperty() - auto_fix_track = bpy.props.StringProperty() - manual_fix_track = bpy.props.StringProperty() - stride_action = bpy.props.StringProperty() - -bpy.utils.register_class(MocapNLATracks) - - -#Update function for Advanced Retarget boolean variable. -def advancedRetargetToggle(self, context): - enduser_obj = context.active_object - performer_obj = [obj for obj in context.selected_objects if obj != enduser_obj] - if enduser_obj is None or len(performer_obj) != 1: - print("Need active and selected armatures") - return - else: - performer_obj = performer_obj[0] - if self.advancedRetarget: - retarget.preAdvancedRetargeting(performer_obj, enduser_obj) - else: - retarget.cleanTempConstraints(enduser_obj) - - -#Animation Stitch Settings Property -bpy.types.Armature.stitch_settings = bpy.props.PointerProperty(type=AnimationStitchSettings) -#Current/Active retargeted animation on the armature -bpy.types.Armature.active_mocap = bpy.props.StringProperty(update=retarget.NLASystemInitialize) -#Collection of retargeted animations and their NLA Tracks on the armature -bpy.types.Armature.mocapNLATracks = bpy.props.CollectionProperty(type=MocapNLATracks) -#Advanced retargeting boolean property -bpy.types.Armature.advancedRetarget = bpy.props.BoolProperty(default=False, update=advancedRetargetToggle) -#frame step - frequency of frames to retarget. Skipping is useful for previewing, faster work etc. -bpy.types.Armature.frameStep = smooth_out = bpy.props.IntProperty(name="Frame Skip", - default=1, - description="Amount of frames to skip - for previewing retargets quickly. 1 is fully sampled", - min=1) - - -def toggleIKBone(self, context): - #Update function for IK functionality. Is called when IK prop checkboxes are toggled. - if self.IKRetarget: - if not self.is_in_ik_chain: - print(self.name + " IK toggled ON!") - ik = self.constraints.new('IK') - #ik the whole chain up to the root, excluding - chainLen = 0 - for parent_bone in self.parent_recursive: - chainLen += 1 - if hasIKConstraint(parent_bone): - break - deformer_children = [child for child in parent_bone.children if child.bone.use_deform] - #~ if len(deformer_children) > 1: - #~ break - ik.chain_count = chainLen - for bone in self.parent_recursive: - if bone.is_in_ik_chain: - bone.IKRetarget = True - else: - print(self.name + " IK toggled OFF!") - cnstrn_bones = [] - newChainLength = [] - if hasIKConstraint(self): - cnstrn_bones = [self] - elif self.is_in_ik_chain: - cnstrn_bones = [child for child in self.children_recursive if hasIKConstraint(child)] - for cnstrn_bone in cnstrn_bones: - newChainLength.append(cnstrn_bone.parent_recursive.index(self) + 1) - if cnstrn_bones: - # remove constraint, and update IK retarget for all parents of cnstrn_bone up to chain_len - for i, cnstrn_bone in enumerate(cnstrn_bones): - print(cnstrn_bone.name) - if newChainLength: - ik = hasIKConstraint(cnstrn_bone) - ik.chain_count = newChainLength[i] - else: - ik = hasIKConstraint(cnstrn_bone) - cnstrn_bone.constraints.remove(ik) - cnstrn_bone.IKRetarget = False - for bone in cnstrn_bone.parent_recursive: - if not bone.is_in_ik_chain: - bone.IKRetarget = False - - -#MocapMap class for storing mapping on enduser performer, -# where a bone may be linked to more than one on the performer -class MocapMapping(bpy.types.PropertyGroup): - name = bpy.props.StringProperty() - -bpy.utils.register_class(MocapMapping) - -#string property for storing performer->enduser mapping -bpy.types.Bone.map = bpy.props.StringProperty() -#Collection Property for storing enduser->performer mapping -bpy.types.Bone.reverseMap = bpy.props.CollectionProperty(type=MocapMapping) -#Boolean property for storing foot bone toggle -bpy.types.Bone.foot = bpy.props.BoolProperty(name="Foot", - description="Marks this bone as a 'foot', which determines retargeted animation's translation", - default=False) -#Boolean property for storing if this bone is twisted along the y axis, -# which can happen due to various sources of performers -bpy.types.Bone.twistFix = bpy.props.BoolProperty(name="Twist Fix", - description="Fix Twist on this bone", - default=False) -#Boolean property for toggling ik retargeting for this bone -bpy.types.PoseBone.IKRetarget = bpy.props.BoolProperty(name="IK", - description="Toggles IK Retargeting method for given bone", - update=toggleIKBone, default=False) - - -def updateIKRetarget(): - # ensures that Blender constraints and IK properties are in sync - # currently runs when module is loaded, should run when scene is loaded - # or user adds a constraint to armature. Will be corrected in the future, - # once python callbacks are implemented - for obj in bpy.data.objects: - if obj.pose: - bones = obj.pose.bones - for pose_bone in bones: - if pose_bone.is_in_ik_chain or hasIKConstraint(pose_bone): - pose_bone.IKRetarget = True - else: - pose_bone.IKRetarget = False - -updateIKRetarget() - - -class MocapPanel(bpy.types.Panel): - # Motion capture retargeting panel - bl_label = "Mocap tools" - bl_space_type = "PROPERTIES" - bl_region_type = "WINDOW" - bl_context = "object" - - def draw(self, context): - self.layout.label("Preprocessing") - row = self.layout.row(align=True) - row.alignment = 'EXPAND' - row.operator("mocap.samples", text='Samples to Beziers') - row.operator("mocap.denoise", text='Clean noise') - row.operator("mocap.rotate_fix", text='Fix BVH Axis Orientation') - row.operator("mocap.scale_fix", text='Auto scale Performer') - row2 = self.layout.row(align=True) - row2.operator("mocap.looper", text='Loop animation') - row2.operator("mocap.limitdof", text='Constrain Rig') - row2.operator("mocap.removelimitdof", text='Unconstrain Rig') - self.layout.label("Retargeting") - enduser_obj = bpy.context.active_object - performer_obj = [obj for obj in bpy.context.selected_objects if obj != enduser_obj] - if enduser_obj is None or len(performer_obj) != 1: - self.layout.label("Select performer rig and target rig (as active)") - else: - self.layout.operator("mocap.guessmapping", text="Guess Hiearchy Mapping") - row3 = self.layout.row(align=True) - column1 = row3.column(align=True) - column1.label("Performer Rig") - column2 = row3.column(align=True) - column2.label("Enduser Rig") - performer_obj = performer_obj[0] - if performer_obj.data and enduser_obj.data: - if performer_obj.data.name in bpy.data.armatures and enduser_obj.data.name in bpy.data.armatures: - perf = performer_obj.data - enduser_arm = enduser_obj.data - perf_pose_bones = enduser_obj.pose.bones - for bone in perf.bones: - row = self.layout.row() - row.prop(data=bone, property='foot', text='', icon='POSE_DATA') - row.label(bone.name) - row.prop_search(bone, "map", enduser_arm, "bones") - row.operator("mocap.selectmap", text='', icon='CURSOR').perf_bone = bone.name - label_mod = "FK" - if bone.map: - pose_bone = perf_pose_bones[bone.map] - if pose_bone.is_in_ik_chain: - label_mod = "ik chain" - if hasIKConstraint(pose_bone): - label_mod = "ik end" - row.prop(data=bone, property='twistFix', text='', icon='RNA') - row.prop(pose_bone, 'IKRetarget') - row.label(label_mod) - else: - row.label(" ") - row.label(" ") - mapRow = self.layout.row() - mapRow.operator("mocap.savemapping", text='Save mapping') - mapRow.operator("mocap.loadmapping", text='Load mapping') - self.layout.prop(data=performer_obj.animation_data.action, property='name', text='Action Name') - self.layout.prop(enduser_arm, "advancedRetarget", text='Advanced Retarget') - self.layout.prop(enduser_arm, "frameStep") - self.layout.operator("mocap.retarget", text='RETARGET!') - - -class MocapConstraintsPanel(bpy.types.Panel): - #Motion capture constraints panel - bl_label = "Mocap Fixes" - bl_space_type = "PROPERTIES" - bl_region_type = "WINDOW" - bl_context = "object" - - def draw(self, context): - layout = self.layout - if context.active_object: - if context.active_object.data: - if context.active_object.data.name in bpy.data.armatures: - enduser_obj = context.active_object - enduser_arm = enduser_obj.data - layout.operator_menu_enum("mocap.addmocapfix", "type") - layout.operator("mocap.updateconstraints", text='Update Fixes') - bakeRow = layout.row() - bakeRow.operator("mocap.bakeconstraints", text='Bake Fixes') - bakeRow.operator("mocap.unbakeconstraints", text='Unbake Fixes') - layout.separator() - for i, m_constraint in enumerate(enduser_arm.mocap_constraints): - box = layout.box() - headerRow = box.row() - headerRow.prop(m_constraint, 'show_expanded', text='', icon='TRIA_DOWN' if m_constraint.show_expanded else 'TRIA_RIGHT', emboss=False) - headerRow.prop(m_constraint, 'type', text='') - headerRow.prop(m_constraint, 'name', text='') - headerRow.prop(m_constraint, 'active', icon='MUTE_IPO_ON' if not m_constraint.active else'MUTE_IPO_OFF', text='', emboss=False) - headerRow.operator("mocap.removeconstraint", text="", icon='X', emboss=False).constraint = i - if m_constraint.show_expanded: - box.separator() - box.prop_search(m_constraint, 'constrained_bone', enduser_obj.pose, "bones", icon='BONE_DATA') - if m_constraint.type == "distance" or m_constraint.type == "point": - box.prop_search(m_constraint, 'constrained_boneB', enduser_obj.pose, "bones", icon='CONSTRAINT_BONE') - frameRow = box.row() - frameRow.label("Frame Range:") - frameRow.prop(m_constraint, 's_frame') - frameRow.prop(m_constraint, 'e_frame') - smoothRow = box.row() - smoothRow.label("Smoothing:") - smoothRow.prop(m_constraint, 'smooth_in') - smoothRow.prop(m_constraint, 'smooth_out') - targetRow = box.row() - targetLabelCol = targetRow.column() - targetLabelCol.label("Target settings:") - targetPropCol = targetRow.column() - if m_constraint.type == "floor": - targetPropCol.prop_search(m_constraint, 'targetMesh', bpy.data, "objects") - if m_constraint.type == "point" or m_constraint.type == "freeze": - box.prop(m_constraint, 'targetSpace') - if m_constraint.type == "point": - targetPropCol.prop(m_constraint, 'targetPoint') - if m_constraint.type == "distance" or m_constraint.type == "floor": - targetPropCol.prop(m_constraint, 'targetDist') - layout.separator() - - -class ExtraToolsPanel(bpy.types.Panel): - # Motion capture retargeting panel - bl_label = "Extra Mocap Tools" - bl_space_type = "PROPERTIES" - bl_region_type = "WINDOW" - bl_context = "object" - - def draw(self, context): - layout = self.layout - layout.operator('mocap.pathediting', text="Follow Path") - layout.label("Animation Stitching") - activeIsArmature = isinstance(context.active_object.data, bpy.types.Armature) - if activeIsArmature: - enduser_arm = context.active_object.data - layout.label("Retargeted Animations:") - layout.prop_search(enduser_arm, "active_mocap", enduser_arm, "mocapNLATracks") - settings = enduser_arm.stitch_settings - layout.prop_search(settings, "first_action", enduser_arm, "mocapNLATracks") - layout.prop_search(settings, "second_action", enduser_arm, "mocapNLATracks") - layout.prop(settings, "blend_frame") - layout.prop(settings, "blend_amount") - layout.prop(settings, "second_offset") - layout.prop_search(settings, "stick_bone", context.active_object.pose, "bones") - layout.operator('mocap.animstitchguess', text="Guess Settings") - layout.operator('mocap.animstitch', text="Stitch Animations") - - -class OBJECT_OT_RetargetButton(bpy.types.Operator): - #Retargeting operator. Assumes selected and active armatures, where the performer (the selected one) - # has an action for retargeting - '''Retarget animation from selected armature to active armature ''' - bl_idname = "mocap.retarget" - bl_label = "Retargets active action from Performer to Enduser" - bl_options = {'REGISTER', 'UNDO'} - - def execute(self, context): - scene = context.scene - s_frame = scene.frame_start - e_frame = scene.frame_end - enduser_obj = context.active_object - performer_obj = [obj for obj in context.selected_objects if obj != enduser_obj] - if enduser_obj is None or len(performer_obj) != 1: - print("Need active and selected armatures") - else: - performer_obj = performer_obj[0] - s_frame, e_frame = performer_obj.animation_data.action.frame_range - s_frame = int(s_frame) - e_frame = int(e_frame) - if retarget.isRigAdvanced(enduser_obj) and not enduser_obj.data.advancedRetarget: - print("Recommended to use Advanced Retargeting method") - enduser_obj.data.advancedRetarget = True - else: - retarget.totalRetarget(performer_obj, enduser_obj, scene, s_frame, e_frame) - return {"FINISHED"} - - @classmethod - def poll(cls, context): - if context.active_object: - activeIsArmature = isinstance(context.active_object.data, bpy.types.Armature) - performer_obj = [obj for obj in context.selected_objects if obj != context.active_object] - if performer_obj: - return activeIsArmature and isinstance(performer_obj[0].data, bpy.types.Armature) and performer_obj[0].animation_data - else: - return False - - -class OBJECT_OT_SaveMappingButton(bpy.types.Operator): - #Operator for saving mapping to enduser armature - '''Save mapping to active armature (for future retargets) ''' - bl_idname = "mocap.savemapping" - bl_label = "Saves user generated mapping from Performer to Enduser" - - def execute(self, context): - enduser_obj = bpy.context.active_object - performer_obj = [obj for obj in bpy.context.selected_objects if obj != enduser_obj][0] - retarget.createDictionary(performer_obj.data, enduser_obj.data) - return {"FINISHED"} - - @classmethod - def poll(cls, context): - if context.active_object: - activeIsArmature = isinstance(context.active_object.data, bpy.types.Armature) - performer_obj = [obj for obj in context.selected_objects if obj != context.active_object] - if performer_obj: - return activeIsArmature and isinstance(performer_obj[0].data, bpy.types.Armature) - else: - return False - - -class OBJECT_OT_LoadMappingButton(bpy.types.Operator): - '''Load saved mapping from active armature''' - #Operator for loading mapping to enduser armature - bl_idname = "mocap.loadmapping" - bl_label = "Loads user generated mapping from Performer to Enduser" - - def execute(self, context): - enduser_obj = bpy.context.active_object - performer_obj = [obj for obj in bpy.context.selected_objects if obj != enduser_obj][0] - retarget.loadMapping(performer_obj.data, enduser_obj.data) - return {"FINISHED"} - - @classmethod - def poll(cls, context): - if context.active_object: - activeIsArmature = isinstance(context.active_object.data, bpy.types.Armature) - performer_obj = [obj for obj in context.selected_objects if obj != context.active_object] - if performer_obj: - return activeIsArmature and isinstance(performer_obj[0].data, bpy.types.Armature) - else: - return False - - -class OBJECT_OT_SelectMapBoneButton(bpy.types.Operator): - #Operator for setting selected bone in enduser armature to the performer mapping - '''Select a bone for faster mapping''' - bl_idname = "mocap.selectmap" - bl_label = "Select a bone for faster mapping" - perf_bone = bpy.props.StringProperty() - - def execute(self, context): - enduser_obj = bpy.context.active_object - performer_obj = [obj for obj in bpy.context.selected_objects if obj != enduser_obj][0] - selectedBone = "" - for bone in enduser_obj.data.bones: - boneVis = bone.layers - for i in range(32): - if boneVis[i] and enduser_obj.data.layers[i]: - if bone.select: - selectedBone = bone.name - break - performer_obj.data.bones[self.perf_bone].map = selectedBone - return {"FINISHED"} - - @classmethod - def poll(cls, context): - if context.active_object: - activeIsArmature = isinstance(context.active_object.data, bpy.types.Armature) - performer_obj = [obj for obj in context.selected_objects if obj != context.active_object] - if performer_obj: - return activeIsArmature and isinstance(performer_obj[0].data, bpy.types.Armature) - else: - return False - - -class OBJECT_OT_ConvertSamplesButton(bpy.types.Operator): - #Operator to convert samples to beziers on the selected object - '''Convert active armature's sampled keyframed to beziers''' - bl_idname = "mocap.samples" - bl_label = "Converts samples / simplifies keyframes to beziers" - - def execute(self, context): - mocap_tools.fcurves_simplify(context, context.active_object) - return {"FINISHED"} - - @classmethod - def poll(cls, context): - return context.active_object.animation_data - - -class OBJECT_OT_LooperButton(bpy.types.Operator): - #Operator to trim fcurves which contain a few loops to a single one on the selected object - '''Trim active armature's animation to a single cycle, given a cyclic animation (such as a walk cycle)''' - bl_idname = "mocap.looper" - bl_label = "loops animation / sampled mocap data" - - def execute(self, context): - mocap_tools.autoloop_anim() - return {"FINISHED"} - - @classmethod - def poll(cls, context): - return context.active_object.animation_data - - -class OBJECT_OT_DenoiseButton(bpy.types.Operator): - #Operator to denoise impluse noise on the active object's fcurves - '''Denoise active armature's animation. Good for dealing with 'bad' frames inherent in mocap animation''' - bl_idname = "mocap.denoise" - bl_label = "Denoises sampled mocap data " - - def execute(self, context): - mocap_tools.denoise_median() - return {"FINISHED"} - - @classmethod - def poll(cls, context): - return context.active_object - - @classmethod - def poll(cls, context): - return context.active_object.animation_data - - -class OBJECT_OT_LimitDOFButton(bpy.types.Operator): - #Operator to analyze performer armature and apply rotation constraints on the enduser armature - '''Create limit constraints on the active armature from the selected armature's animation's range of motion''' - bl_idname = "mocap.limitdof" - bl_label = "Analyzes animations Max/Min DOF and adds hard/soft constraints" - - def execute(self, context): - performer_obj = [obj for obj in context.selected_objects if obj != context.active_object][0] - mocap_tools.limit_dof(context, performer_obj, context.active_object) - return {"FINISHED"} - - @classmethod - def poll(cls, context): - if context.active_object: - activeIsArmature = isinstance(context.active_object.data, bpy.types.Armature) - performer_obj = [obj for obj in context.selected_objects if obj != context.active_object] - if performer_obj: - return activeIsArmature and isinstance(performer_obj[0].data, bpy.types.Armature) - else: - return False - - -class OBJECT_OT_RemoveLimitDOFButton(bpy.types.Operator): - #Removes constraints created by above operator - '''Removes previously created limit constraints on the active armature''' - bl_idname = "mocap.removelimitdof" - bl_label = "Removes previously created limit constraints on the active armature" - - def execute(self, context): - mocap_tools.limit_dof_toggle_off(context, context.active_object) - return {"FINISHED"} - - @classmethod - def poll(cls, context): - activeIsArmature = False - if context.active_object: - activeIsArmature = isinstance(context.active_object.data, bpy.types.Armature) - return activeIsArmature - - -class OBJECT_OT_RotateFixArmature(bpy.types.Operator): - #Operator to fix common imported Mocap data issue of wrong axis system on active object - '''Realign the active armature's axis system to match Blender (Commonly needed after bvh import)''' - bl_idname = "mocap.rotate_fix" - bl_label = "Rotates selected armature 90 degrees (fix for bvh import)" - - def execute(self, context): - mocap_tools.rotate_fix_armature(context.active_object.data) - return {"FINISHED"} - - @classmethod - def poll(cls, context): - if context.active_object: - return isinstance(context.active_object.data, bpy.types.Armature) - - -class OBJECT_OT_ScaleFixArmature(bpy.types.Operator): - #Operator to scale down the selected armature to match the active one - '''Rescale selected armature to match the active animation, for convienence''' - bl_idname = "mocap.scale_fix" - bl_label = "Scales performer armature to match target armature" - - def execute(self, context): - enduser_obj = bpy.context.active_object - performer_obj = [obj for obj in bpy.context.selected_objects if obj != enduser_obj][0] - mocap_tools.scale_fix_armature(performer_obj, enduser_obj) - return {"FINISHED"} - - @classmethod - def poll(cls, context): - if context.active_object: - activeIsArmature = isinstance(context.active_object.data, bpy.types.Armature) - performer_obj = [obj for obj in context.selected_objects if obj != context.active_object] - if performer_obj: - return activeIsArmature and isinstance(performer_obj[0].data, bpy.types.Armature) - else: - return False - - -class MOCAP_OT_AddMocapFix(bpy.types.Operator): - #Operator to add a post-retarget fix - '''Add a post-retarget fix - useful for fixing certain artifacts following the retarget''' - bl_idname = "mocap.addmocapfix" - bl_label = "Add Mocap Fix to target armature" - type = bpy.props.EnumProperty(name="Type of Fix", - items=[("point", "Maintain Position", "Bone is at a specific point"), - ("freeze", "Maintain Position at frame", "Bone does not move from location specified in target frame"), - ("floor", "Stay above", "Bone does not cross specified mesh object eg floor"), - ("distance", "Maintain distance", "Target bones maintained specified distance")], - description="Type of fix") - - def execute(self, context): - enduser_obj = bpy.context.active_object - enduser_arm = enduser_obj.data - new_mcon = enduser_arm.mocap_constraints.add() - new_mcon.type = self.type - return {"FINISHED"} - - @classmethod - def poll(cls, context): - if context.active_object: - return isinstance(context.active_object.data, bpy.types.Armature) - - -class OBJECT_OT_RemoveMocapConstraint(bpy.types.Operator): - #Operator to remove a post-retarget fix - '''Remove this post-retarget fix''' - bl_idname = "mocap.removeconstraint" - bl_label = "Removes fixes from target armature" - constraint = bpy.props.IntProperty() - - def execute(self, context): - enduser_obj = bpy.context.active_object - enduser_arm = enduser_obj.data - m_constraints = enduser_arm.mocap_constraints - m_constraint = m_constraints[self.constraint] - if m_constraint.real_constraint: - bone = enduser_obj.pose.bones[m_constraint.real_constraint_bone] - cons_obj = getConsObj(bone) - removeConstraint(m_constraint, cons_obj) - m_constraints.remove(self.constraint) - return {"FINISHED"} - - @classmethod - def poll(cls, context): - if context.active_object: - return isinstance(context.active_object.data, bpy.types.Armature) - - -class OBJECT_OT_BakeMocapConstraints(bpy.types.Operator): - #Operator to bake all post-retarget fixes - '''Bake all post-retarget fixes to the Retarget Fixes NLA Track''' - bl_idname = "mocap.bakeconstraints" - bl_label = "Bake all fixes to target armature" - - def execute(self, context): - bakeConstraints(context) - return {"FINISHED"} - - @classmethod - def poll(cls, context): - if context.active_object: - return isinstance(context.active_object.data, bpy.types.Armature) - - -class OBJECT_OT_UnbakeMocapConstraints(bpy.types.Operator): - #Operator to unbake all post-retarget fixes - '''Unbake all post-retarget fixes - removes the baked data from the Retarget Fixes NLA Track''' - bl_idname = "mocap.unbakeconstraints" - bl_label = "Unbake all fixes to target armature" - - def execute(self, context): - unbakeConstraints(context) - return {"FINISHED"} - - @classmethod - def poll(cls, context): - if context.active_object: - return isinstance(context.active_object.data, bpy.types.Armature) - - -class OBJECT_OT_UpdateMocapConstraints(bpy.types.Operator): - #Operator to update all post-retarget fixes, similar to update dependencies on drivers - #Needed because python properties lack certain callbacks and some fixes take a while to recalculate. - '''Updates all post-retarget fixes - needed after changes to armature object or pose''' - bl_idname = "mocap.updateconstraints" - bl_label = "Updates all fixes to target armature - neccesary to take under consideration changes to armature object or pose" - - def execute(self, context): - updateConstraints(context.active_object, context) - return {"FINISHED"} - - @classmethod - def poll(cls, context): - if context.active_object: - return isinstance(context.active_object.data, bpy.types.Armature) - - -class OBJECT_OT_GuessHierachyMapping(bpy.types.Operator): - #Operator which calls heurisitic function to guess mapping between 2 armatures - '''Attemps to auto figure out hierarchy mapping''' - bl_idname = "mocap.guessmapping" - bl_label = "Attemps to auto figure out hierarchy mapping" - - def execute(self, context): - enduser_obj = bpy.context.active_object - performer_obj = [obj for obj in bpy.context.selected_objects if obj != enduser_obj][0] - mocap_tools.guessMapping(performer_obj, enduser_obj) - return {"FINISHED"} - - @classmethod - def poll(cls, context): - if context.active_object: - activeIsArmature = isinstance(context.active_object.data, bpy.types.Armature) - performer_obj = [obj for obj in context.selected_objects if obj != context.active_object] - if performer_obj: - return activeIsArmature and isinstance(performer_obj[0].data, bpy.types.Armature) - else: - return False - - -class OBJECT_OT_PathEditing(bpy.types.Operator): - #Operator which calls path editing function, making active object follow the selected curve. - '''Sets active object (stride object) to follow the selected curve''' - bl_idname = "mocap.pathediting" - bl_label = "Sets active object (stride object) to follow the selected curve" - - def execute(self, context): - path = [obj for obj in context.selected_objects if obj != context.active_object][0] - mocap_tools.path_editing(context, context.active_object, path) - return {"FINISHED"} - - @classmethod - def poll(cls, context): - if context.active_object: - selected_objs = [obj for obj in context.selected_objects if obj != context.active_object and isinstance(obj.data, bpy.types.Curve)] - return selected_objs - else: - return False - - -class OBJECT_OT_AnimationStitchingButton(bpy.types.Operator): - #Operator which calls stitching function, combining 2 animations onto the NLA. - '''Stitches two defined animations into a single one via alignment of NLA Tracks''' - bl_idname = "mocap.animstitch" - bl_label = "Stitches two defined animations into a single one via alignment of NLA Tracks" - - def execute(self, context): - mocap_tools.anim_stitch(context, context.active_object) - return {"FINISHED"} - - @classmethod - def poll(cls, context): - activeIsArmature = False - if context.active_object: - activeIsArmature = isinstance(context.active_object.data, bpy.types.Armature) - if activeIsArmature: - stitch_settings = context.active_object.data.stitch_settings - return (stitch_settings.first_action and stitch_settings.second_action) - return False - - -class OBJECT_OT_GuessAnimationStitchingButton(bpy.types.Operator): - #Operator which calls stitching function heuristic, setting good values for above operator. - '''Guesses the stitch frame and second offset for animation stitch''' - bl_idname = "mocap.animstitchguess" - bl_label = "Guesses the stitch frame and second offset for animation stitch" - - def execute(self, context): - mocap_tools.guess_anim_stitch(context, context.active_object) - return {"FINISHED"} - - @classmethod - def poll(cls, context): - activeIsArmature = False - if context.active_object: - activeIsArmature = isinstance(context.active_object.data, bpy.types.Armature) - if activeIsArmature: - stitch_settings = context.active_object.data.stitch_settings - return (stitch_settings.first_action and stitch_settings.second_action) - return False - - -def register(): - bpy.utils.register_module(__name__) - - -def unregister(): - bpy.utils.unregister_module(__name__) - -if __name__ == "__main__": - register() -- cgit v1.2.3 From c07bd1439a3f026b8603c52662c3e7ccc364321a Mon Sep 17 00:00:00 2001 From: Peter Schlaile Date: Sun, 28 Aug 2011 14:46:03 +0000 Subject: == Sequencer == This patch adds: * support for proxy building again (missing feature from Blender 2.49) additionally to the way, Blender 2.49 worked, you can select several strips at once and make Blender build proxies in the background (using the job system) Also a new thing: movie proxies are now build into AVI files, and the proxy system is moved into ImBuf-library, so that other parts of blender can also benefit from it. * Timecode support: to fix seeking issues with files, that have a) varying frame rates b) very large GOP lengths c) are broken inbetween d) use different time code tracks the proxy builder can now also build timecode indices, which are used (optionally) for seeking. For the first time, it is possible, to do frame exact seeking on all file types. * Support for different video-streams in one video file (can be selected in sequencer, other parts of blender can also use it, but UI has to be added accordingly) * IMPORTANT: this patch *requires* ffmpeg 0.7 or newer, since older versions don't support the pkt_pts field, that is essential for building timecode indices. Windows and Mac libs are already updated, Linux-users have to build their own ffmpeg verions until distros keep up. --- release/scripts/startup/bl_ui/space_sequencer.py | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'release/scripts/startup') diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index 84cc365425e..1902e9345d6 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -60,6 +60,7 @@ class SEQUENCER_HT_header(Header): layout.separator() layout.operator("sequencer.refresh_all") + layout.template_running_jobs() elif st.view_type == 'SEQUENCER_PREVIEW': layout.separator() layout.operator("sequencer.refresh_all") @@ -241,6 +242,7 @@ class SEQUENCER_MT_strip(Menu): layout.operator("sequencer.images_separate") layout.operator("sequencer.offset_clear") layout.operator("sequencer.deinterlace_selected_movies") + layout.operator("sequencer.rebuild_proxy") layout.separator() layout.operator("sequencer.duplicate") @@ -578,6 +580,7 @@ class SEQUENCER_PT_input(SequencerButtonsPanel, Panel): col = split.column() col.prop(strip, "filepath", text="") col.prop(strip, "mpeg_preseek", text="MPEG Preseek") + col.prop(strip, "streamindex", text="Stream Index") # TODO, sound??? # end drawing filename @@ -746,7 +749,7 @@ class SEQUENCER_PT_filter(SequencerButtonsPanel, Panel): class SEQUENCER_PT_proxy(SequencerButtonsPanel, Panel): - bl_label = "Proxy" + bl_label = "Proxy / Timecode" @classmethod def poll(cls, context): @@ -772,12 +775,29 @@ class SEQUENCER_PT_proxy(SequencerButtonsPanel, Panel): flow = layout.column_flow() flow.prop(strip, "use_proxy_custom_directory") flow.prop(strip, "use_proxy_custom_file") - if strip.proxy: # TODO - need to add this somehow + if strip.proxy: if strip.use_proxy_custom_directory and not strip.use_proxy_custom_file: flow.prop(strip.proxy, "directory") if strip.use_proxy_custom_file: flow.prop(strip.proxy, "filepath") + row = layout.row() + row.prop(strip.proxy, "build_25") + row.prop(strip.proxy, "build_50") + row.prop(strip.proxy, "build_75") + row.prop(strip.proxy, "build_100") + + col = layout.column() + col.label(text="Build JPEG quality") + col.prop(strip.proxy, "quality") + + if strip.type == "MOVIE": + col = layout.column() + col.label(text="Use timecode index:") + + col.prop(strip.proxy, "timecode") + + class SEQUENCER_PT_preview(SequencerButtonsPanel_Output, Panel): bl_label = "Scene Preview/Render" -- cgit v1.2.3 From 5bac37f6d4d2e8d584ae0ec6bafd2808c47fbb25 Mon Sep 17 00:00:00 2001 From: Joerg Mueller Date: Mon, 29 Aug 2011 15:01:55 +0000 Subject: * Reverting Titlecard commit r37537 * Reverting update recent files commit r37155 * Turning reference counts into unsigned ints * Minor things --- release/scripts/startup/bl_ui/space_sequencer.py | 14 +++----------- release/scripts/startup/bl_ui/space_userpref.py | 1 - 2 files changed, 3 insertions(+), 12 deletions(-) (limited to 'release/scripts/startup') diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index cebe78ff627..168a025c407 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -225,7 +225,6 @@ class SEQUENCER_MT_add_effect(Menu): layout.operator("sequencer.effect_strip_add", text="Speed Control").type = 'SPEED' layout.operator("sequencer.effect_strip_add", text="Multicam Selector").type = 'MULTICAM' layout.operator("sequencer.effect_strip_add", text="Adjustment Layer").type = 'ADJUSTMENT' - layout.operator("sequencer.effect_strip_add", text="Title Card").type = 'TITLE_CARD' class SEQUENCER_MT_strip(Menu): @@ -407,7 +406,7 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel): 'CROSS', 'GAMMA_CROSS', 'MULTIPLY', 'OVER_DROP', 'PLUGIN', 'WIPE', 'GLOW', 'TRANSFORM', 'COLOR', 'SPEED', - 'MULTICAM', 'ADJUSTMENT', 'TITLE_CARD'} + 'MULTICAM', 'ADJUSTMENT'} def draw(self, context): layout = self.layout @@ -475,11 +474,6 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel): row.label("Cut To") for i in range(1, strip.channel): row.operator("sequencer.cut_multicam", text=str(i)).camera = i - elif strip.type == "TITLE_CARD": - layout.prop(strip, "title") - layout.prop(strip, "subtitle") - layout.prop(strip, "color_foreground") - layout.prop(strip, "color_background") col = layout.column(align=True) if strip.type == 'SPEED': @@ -551,8 +545,7 @@ class SEQUENCER_PT_input(SequencerButtonsPanel, Panel): 'CROSS', 'GAMMA_CROSS', 'MULTIPLY', 'OVER_DROP', 'PLUGIN', 'WIPE', 'GLOW', 'TRANSFORM', 'COLOR', - 'MULTICAM', 'SPEED', 'ADJUSTMENT', - 'TITLE_CARD'} + 'MULTICAM', 'SPEED', 'ADJUSTMENT'} def draw(self, context): layout = self.layout @@ -713,8 +706,7 @@ class SEQUENCER_PT_filter(SequencerButtonsPanel, Panel): 'CROSS', 'GAMMA_CROSS', 'MULTIPLY', 'OVER_DROP', 'PLUGIN', 'WIPE', 'GLOW', 'TRANSFORM', 'COLOR', - 'MULTICAM', 'SPEED', 'ADJUSTMENT', - 'TITLE_CARD'} + 'MULTICAM', 'SPEED', 'ADJUSTMENT'} def draw(self, context): layout = self.layout diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index 79565030e56..13edc3471d2 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -746,7 +746,6 @@ class USERPREF_PT_file(Panel): col.prop(paths, "save_version") col.prop(paths, "recent_files") - col.prop(paths, "use_update_recent_files_on_load") col.prop(paths, "use_save_preview_images") col.label(text="Auto Save:") col.prop(paths, "use_auto_save_temporary_files") -- cgit v1.2.3 From d049a722fea3d150fbfad06ffdbbb5c150717134 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 30 Aug 2011 04:13:48 +0000 Subject: fix [#28413] bpy.ops.nla.bake can't bake from frame 0 --- release/scripts/startup/bl_operators/nla.py | 33 ++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 10 deletions(-) (limited to 'release/scripts/startup') diff --git a/release/scripts/startup/bl_operators/nla.py b/release/scripts/startup/bl_operators/nla.py index 714b889da26..cf595b1adf4 100644 --- a/release/scripts/startup/bl_operators/nla.py +++ b/release/scripts/startup/bl_operators/nla.py @@ -200,19 +200,32 @@ class BakeAction(Operator): bl_label = "Bake Action" bl_options = {'REGISTER', 'UNDO'} - frame_start = IntProperty(name="Start Frame", + frame_start = IntProperty( + name="Start Frame", description="Start frame for baking", - default=1, min=1, max=300000) - frame_end = IntProperty(name="End Frame", + min=0, max=300000, + default=1, + ) + frame_end = IntProperty( + name="End Frame", description="End frame for baking", - default=250, min=1, max=300000) - step = IntProperty(name="Frame Step", + min=1, max=300000, + default=250, + ) + step = IntProperty( + name="Frame Step", description="Frame Step", - default=1, min=1, max=120) - only_selected = BoolProperty(name="Only Selected", - default=True) - clear_consraints = BoolProperty(name="Clear Constraints", - default=False) + min=1, max=120, + default=1, + ) + only_selected = BoolProperty( + name="Only Selected", + default=True, + ) + clear_consraints = BoolProperty( + name="Clear Constraints", + default=False, + ) bake_types = EnumProperty( name="Bake Data", options={'ENUM_FLAG'}, -- cgit v1.2.3 From 6c9ee34dd8acba35808847d3669798c6d3459b9c Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Tue, 30 Aug 2011 10:44:02 +0000 Subject: 2.5 UI Files: * Code cleanup after Pepper merge. --- release/scripts/startup/bl_ui/properties_data_armature.py | 3 +-- release/scripts/startup/bl_ui/properties_data_speaker.py | 8 ++------ release/scripts/startup/bl_ui/properties_object_constraint.py | 5 +---- release/scripts/startup/bl_ui/properties_render.py | 9 +++------ release/scripts/startup/bl_ui/properties_scene.py | 2 -- 5 files changed, 7 insertions(+), 20 deletions(-) (limited to 'release/scripts/startup') diff --git a/release/scripts/startup/bl_ui/properties_data_armature.py b/release/scripts/startup/bl_ui/properties_data_armature.py index 9a76ed81530..b2c09469067 100644 --- a/release/scripts/startup/bl_ui/properties_data_armature.py +++ b/release/scripts/startup/bl_ui/properties_data_armature.py @@ -72,8 +72,7 @@ class DATA_PT_skeleton(ArmatureButtonsPanel, Panel): flow.prop(arm, "use_deform_preserve_volume", text="Quaternion") if context.scene.render.engine == "BLENDER_GAME": - col = layout.column() - col.prop(arm, "vert_deformer") + layout.row().prop(arm, "vert_deformer", expand=True, text="") class DATA_PT_display(ArmatureButtonsPanel, Panel): bl_label = "Display" diff --git a/release/scripts/startup/bl_ui/properties_data_speaker.py b/release/scripts/startup/bl_ui/properties_data_speaker.py index fe9f798af0c..657c0fe652a 100644 --- a/release/scripts/startup/bl_ui/properties_data_speaker.py +++ b/release/scripts/startup/bl_ui/properties_data_speaker.py @@ -66,10 +66,7 @@ class DATA_PT_speaker(DataButtonsPanel, bpy.types.Panel): split.template_ID(speaker, "sound", open="sound.open_mono") split.prop(speaker, "muted") - split = layout.split() - - row = split.row() - + row = layout.row() row.prop(speaker, "volume") row.prop(speaker, "pitch") @@ -84,15 +81,14 @@ class DATA_PT_distance(DataButtonsPanel, bpy.types.Panel): speaker = context.speaker split = layout.split() + col = split.column() - col.label("Volume:") col.prop(speaker, "volume_min", text="Minimum") col.prop(speaker, "volume_max", text="Maximum") col.prop(speaker, "attenuation") col = split.column() - col.label("Distance:") col.prop(speaker, "distance_max", text="Maximum") col.prop(speaker, "distance_reference", text="Reference") diff --git a/release/scripts/startup/bl_ui/properties_object_constraint.py b/release/scripts/startup/bl_ui/properties_object_constraint.py index c74a0000499..ba237e74fb7 100644 --- a/release/scripts/startup/bl_ui/properties_object_constraint.py +++ b/release/scripts/startup/bl_ui/properties_object_constraint.py @@ -235,7 +235,6 @@ class ConstraintButtonsPanel(): row.label() def LIMIT_ROTATION(self, context, layout, con): - split = layout.split() col = split.column(align=True) @@ -259,9 +258,7 @@ class ConstraintButtonsPanel(): sub.prop(con, "min_z", text="Min") sub.prop(con, "max_z", text="Max") - row = layout.row() - row.prop(con, "use_transform_limit") - row.label() + layout.prop(con, "use_transform_limit") row = layout.row() row.label(text="Convert:") diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py index c906013e094..395cfc6934e 100644 --- a/release/scripts/startup/bl_ui/properties_render.py +++ b/release/scripts/startup/bl_ui/properties_render.py @@ -592,12 +592,9 @@ class RENDER_PT_encoding(RenderButtonsPanel, Panel): if rd.ffmpeg_format not in {'MP3'}: layout.prop(rd, "ffmpeg_audio_codec", text="Audio Codec") - split = layout.split() - - col = split.column() - col.prop(rd, "ffmpeg_audio_bitrate") - col = split.column() - col.prop(rd, "ffmpeg_audio_volume", slider=True) + row = layout.row() + row.prop(rd, "ffmpeg_audio_bitrate") + row.prop(rd, "ffmpeg_audio_volume", slider=True) class RENDER_PT_bake(RenderButtonsPanel, Panel): diff --git a/release/scripts/startup/bl_ui/properties_scene.py b/release/scripts/startup/bl_ui/properties_scene.py index fd7fc8ed462..66f967bb6e1 100644 --- a/release/scripts/startup/bl_ui/properties_scene.py +++ b/release/scripts/startup/bl_ui/properties_scene.py @@ -59,14 +59,12 @@ class SCENE_PT_audio(SceneButtonsPanel, Panel): split = layout.split() col = split.column() - col.label("Listener:") col.prop(scene, "audio_distance_model", text="") col.prop(scene, "audio_doppler_speed", text="Speed") col.prop(scene, "audio_doppler_factor", text="Doppler") col = split.column() - col.label("Format:") col.prop(rd, "ffmpeg_audio_channels", text="") col.prop(rd, "ffmpeg_audio_mixrate", text="Rate") -- cgit v1.2.3 From b20c9b0ba368d5685d3c996572780befe852b889 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 30 Aug 2011 10:49:58 +0000 Subject: minor edits, pep8 - also correct float -> double promotion for blf. --- release/scripts/startup/bl_operators/nla.py | 4 +-- release/scripts/startup/bl_operators/object.py | 27 ++++++++++-------- .../startup/bl_ui/properties_data_armature.py | 1 + .../startup/bl_ui/properties_object_constraint.py | 1 - .../scripts/startup/bl_ui/properties_texture.py | 8 +++--- release/scripts/startup/bl_ui/space_dopesheet.py | 2 +- release/scripts/startup/bl_ui/space_nla.py | 4 +-- release/scripts/startup/bl_ui/space_sequencer.py | 1 - release/scripts/startup/bl_ui/space_view3d.py | 5 ++-- release/scripts/startup/keyingsets_builtins.py | 33 +++++++++++----------- 10 files changed, 45 insertions(+), 41 deletions(-) (limited to 'release/scripts/startup') diff --git a/release/scripts/startup/bl_operators/nla.py b/release/scripts/startup/bl_operators/nla.py index 085cd75f9f9..c764f7d62f1 100644 --- a/release/scripts/startup/bl_operators/nla.py +++ b/release/scripts/startup/bl_operators/nla.py @@ -269,10 +269,8 @@ class BakeAction(Operator): wm = context.window_manager return wm.invoke_props_dialog(self) -################################# - -class ClearUselessActions(bpy.types.Operator): +class ClearUselessActions(Operator): '''Mark actions with no F-Curves for deletion after save+reload of file preserving "action libraries"''' bl_idname = "anim.clear_useless_actions" bl_label = "Clear Useless Actions" diff --git a/release/scripts/startup/bl_operators/object.py b/release/scripts/startup/bl_operators/object.py index 88f863b8e55..6c9f27afaa5 100644 --- a/release/scripts/startup/bl_operators/object.py +++ b/release/scripts/startup/bl_operators/object.py @@ -686,26 +686,30 @@ class ClearAllRestrictRender(Operator): obj.hide_render = False return {'FINISHED'} -class TransformsToDeltasAnim(bpy.types.Operator): + +class TransformsToDeltasAnim(Operator): '''Convert object animation for normal transforms to delta transforms''' bl_idname = "object.anim_transforms_to_deltas" bl_label = "Animated Transforms to Deltas" bl_options = {'REGISTER', 'UNDO'} - + @classmethod def poll(cls, context): obs = context.selected_editable_objects return (obs is not None) - + def execute(self, context): for obj in context.selected_editable_objects: # get animation data adt = obj.animation_data if (adt is None) or (adt.action is None): - self.report({'WARNING'}, "No animation data to convert on object: " + obj.name) + self.report({'WARNING'}, + "No animation data to convert on object: %r" % + obj.name) continue - - # if F-Curve uses standard transform path, just append "delta_" to this path + + # if F-Curve uses standard transform path + # just append "delta_" to this path for fcu in adt.action.fcurves: if fcu.data_path == "location": fcu.data_path = "delta_location" @@ -716,13 +720,14 @@ class TransformsToDeltasAnim(bpy.types.Operator): elif fcu.data_path == "rotation_quaternion": fcu.data_path = "delta_rotation_quaternion" obj.rotation_quaternion.identity() - #elif fcu.data_path == "rotation_axis_angle": # XXX: currently not implemented - # fcu.data_path = "delta_rotation_axis_angle" + # XXX: currently not implemented + # elif fcu.data_path == "rotation_axis_angle": + # fcu.data_path = "delta_rotation_axis_angle" elif fcu.data_path == "scale": fcu.data_path = "delta_scale" - obj.scale = (1, 1, 1) - + obj.scale = 1.0, 1.0, 1.0 + # hack: force animsys flush by changing frame, so that deltas get run context.scene.frame_set(context.scene.frame_current) - + return {'FINISHED'} diff --git a/release/scripts/startup/bl_ui/properties_data_armature.py b/release/scripts/startup/bl_ui/properties_data_armature.py index b2c09469067..3d1903f4cbc 100644 --- a/release/scripts/startup/bl_ui/properties_data_armature.py +++ b/release/scripts/startup/bl_ui/properties_data_armature.py @@ -74,6 +74,7 @@ class DATA_PT_skeleton(ArmatureButtonsPanel, Panel): if context.scene.render.engine == "BLENDER_GAME": layout.row().prop(arm, "vert_deformer", expand=True, text="") + class DATA_PT_display(ArmatureButtonsPanel, Panel): bl_label = "Display" diff --git a/release/scripts/startup/bl_ui/properties_object_constraint.py b/release/scripts/startup/bl_ui/properties_object_constraint.py index ba237e74fb7..05fac2026a0 100644 --- a/release/scripts/startup/bl_ui/properties_object_constraint.py +++ b/release/scripts/startup/bl_ui/properties_object_constraint.py @@ -478,7 +478,6 @@ class ConstraintButtonsPanel(): row.prop(con, "use_transform_limit") row.label() - def STRETCH_TO(self, context, layout, con): self.target_template(layout, con) diff --git a/release/scripts/startup/bl_ui/properties_texture.py b/release/scripts/startup/bl_ui/properties_texture.py index 0172fbcbadd..34f5a948ee7 100644 --- a/release/scripts/startup/bl_ui/properties_texture.py +++ b/release/scripts/startup/bl_ui/properties_texture.py @@ -414,7 +414,7 @@ class TEXTURE_PT_image_sampling(TextureTypePanel, Panel): row = col.row() row.active = tex.use_normal_map row.prop(slot, "normal_map_space", text="") - + row = col.row() row.active = not tex.use_normal_map row.prop(tex, "use_derivative_map") @@ -1029,14 +1029,14 @@ class TEXTURE_PT_influence(TextureSlotPanel, Panel): # only show bump settings if activated but not for normalmap images row = layout.row() - + sub = row.row() sub.active = (tex.use_map_normal or tex.use_map_warp) and not (tex.texture.type == 'IMAGE' and (tex.texture.use_normal_map or tex.texture.use_derivative_map)) sub.prop(tex, "bump_method", text="Method") - # the space setting is supported for: derivmaps + bumpmaps (DEFAULT,BEST_QUALITY), not for normalmaps + # the space setting is supported for: derivmaps + bumpmaps (DEFAULT,BEST_QUALITY), not for normalmaps sub = row.row() - sub.active = (tex.use_map_normal or tex.use_map_warp) and not (tex.texture.type == 'IMAGE' and tex.texture.use_normal_map) and ((tex.bump_method in {'BUMP_DEFAULT', 'BUMP_BEST_QUALITY'}) or (tex.texture.type == 'IMAGE' and tex.texture.use_derivative_map)) + sub.active = (tex.use_map_normal or tex.use_map_warp) and not (tex.texture.type == 'IMAGE' and tex.texture.use_normal_map) and ((tex.bump_method in {'BUMP_DEFAULT', 'BUMP_BEST_QUALITY'}) or (tex.texture.type == 'IMAGE' and tex.texture.use_derivative_map)) sub.prop(tex, "bump_objectspace", text="Space") diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py index 5ed79f45fbc..90dcc99e6d7 100644 --- a/release/scripts/startup/bl_ui/space_dopesheet.py +++ b/release/scripts/startup/bl_ui/space_dopesheet.py @@ -36,7 +36,7 @@ def dopesheet_filter(layout, context, genericFiltersOnly=False): if is_nla: row.prop(dopesheet, "show_missing_nla", text="") - + if not genericFiltersOnly: if bpy.data.groups: row = layout.row(align=True) diff --git a/release/scripts/startup/bl_ui/space_nla.py b/release/scripts/startup/bl_ui/space_nla.py index 1d4b7c6828f..ffead81c507 100644 --- a/release/scripts/startup/bl_ui/space_nla.py +++ b/release/scripts/startup/bl_ui/space_nla.py @@ -69,11 +69,11 @@ class NLA_MT_view(Menu): layout.separator() layout.operator("anim.previewrange_set") layout.operator("anim.previewrange_clear") - + layout.separator() layout.operator("nla.view_all") layout.operator("nla.view_selected") - + layout.separator() layout.operator("screen.area_dupli") layout.operator("screen.screen_full_area") diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index 8592cc2fcc0..36f606da635 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -804,7 +804,6 @@ class SEQUENCER_PT_proxy(SequencerButtonsPanel, Panel): col.prop(strip.proxy, "timecode") - class SEQUENCER_PT_preview(SequencerButtonsPanel_Output, Panel): bl_label = "Scene Preview/Render" bl_space_type = 'SEQUENCE_EDITOR' diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 64cbc4c3d98..9f96df1eb66 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -179,9 +179,9 @@ class VIEW3D_MT_transform(Menu): layout.operator("object.randomize_transform") layout.operator("object.align") - + layout.separator() - + layout.operator("object.anim_transforms_to_deltas") @@ -1273,6 +1273,7 @@ class VIEW3D_MT_pose_transform(Menu): layout.operator("pose.user_transforms_clear", text="Reset unkeyed") + class VIEW3D_MT_pose_slide(Menu): bl_label = "In-Betweens" diff --git a/release/scripts/startup/keyingsets_builtins.py b/release/scripts/startup/keyingsets_builtins.py index dcc1afed74b..6b12c95e072 100644 --- a/release/scripts/startup/keyingsets_builtins.py +++ b/release/scripts/startup/keyingsets_builtins.py @@ -32,13 +32,14 @@ in lost (i.e. unkeyed) animation. import bpy import keyingsets_utils +from bpy.types import KeyingSetInfo ############################### # Built-In KeyingSets # Location -class BUILTIN_KSI_Location(bpy.types.KeyingSetInfo): +class BUILTIN_KSI_Location(KeyingSetInfo): bl_label = "Location" # poll - use predefined callback for selected bones/objects @@ -52,7 +53,7 @@ class BUILTIN_KSI_Location(bpy.types.KeyingSetInfo): # Rotation -class BUILTIN_KSI_Rotation(bpy.types.KeyingSetInfo): +class BUILTIN_KSI_Rotation(KeyingSetInfo): bl_label = "Rotation" # poll - use predefined callback for selected bones/objects @@ -66,7 +67,7 @@ class BUILTIN_KSI_Rotation(bpy.types.KeyingSetInfo): # Scale -class BUILTIN_KSI_Scaling(bpy.types.KeyingSetInfo): +class BUILTIN_KSI_Scaling(KeyingSetInfo): bl_label = "Scaling" # poll - use predefined callback for selected bones/objects @@ -82,7 +83,7 @@ class BUILTIN_KSI_Scaling(bpy.types.KeyingSetInfo): # LocRot -class BUILTIN_KSI_LocRot(bpy.types.KeyingSetInfo): +class BUILTIN_KSI_LocRot(KeyingSetInfo): bl_label = "LocRot" # poll - use predefined callback for selected bones/objects @@ -100,7 +101,7 @@ class BUILTIN_KSI_LocRot(bpy.types.KeyingSetInfo): # LocScale -class BUILTIN_KSI_LocScale(bpy.types.KeyingSetInfo): +class BUILTIN_KSI_LocScale(KeyingSetInfo): bl_label = "LocScale" # poll - use predefined callback for selected bones/objects @@ -118,7 +119,7 @@ class BUILTIN_KSI_LocScale(bpy.types.KeyingSetInfo): # LocRotScale -class BUILTIN_KSI_LocRotScale(bpy.types.KeyingSetInfo): +class BUILTIN_KSI_LocRotScale(KeyingSetInfo): bl_label = "LocRotScale" # poll - use predefined callback for selected bones/objects @@ -138,7 +139,7 @@ class BUILTIN_KSI_LocRotScale(bpy.types.KeyingSetInfo): # RotScale -class BUILTIN_KSI_RotScale(bpy.types.KeyingSetInfo): +class BUILTIN_KSI_RotScale(KeyingSetInfo): bl_label = "RotScale" # poll - use predefined callback for selected bones/objects @@ -158,7 +159,7 @@ class BUILTIN_KSI_RotScale(bpy.types.KeyingSetInfo): # Location -class BUILTIN_KSI_VisualLoc(bpy.types.KeyingSetInfo): +class BUILTIN_KSI_VisualLoc(KeyingSetInfo): bl_label = "Visual Location" bl_options = {'INSERTKEY_VISUAL'} @@ -174,7 +175,7 @@ class BUILTIN_KSI_VisualLoc(bpy.types.KeyingSetInfo): # Rotation -class BUILTIN_KSI_VisualRot(bpy.types.KeyingSetInfo): +class BUILTIN_KSI_VisualRot(KeyingSetInfo): bl_label = "Visual Rotation" bl_options = {'INSERTKEY_VISUAL'} @@ -190,7 +191,7 @@ class BUILTIN_KSI_VisualRot(bpy.types.KeyingSetInfo): # VisualLocRot -class BUILTIN_KSI_VisualLocRot(bpy.types.KeyingSetInfo): +class BUILTIN_KSI_VisualLocRot(KeyingSetInfo): bl_label = "Visual LocRot" bl_options = {'INSERTKEY_VISUAL'} @@ -212,7 +213,7 @@ class BUILTIN_KSI_VisualLocRot(bpy.types.KeyingSetInfo): # Available -class BUILTIN_KSI_Available(bpy.types.KeyingSetInfo): +class BUILTIN_KSI_Available(KeyingSetInfo): bl_label = "Available" # poll - selected objects or selected object with animation data @@ -234,7 +235,7 @@ class BUILTIN_KSI_Available(bpy.types.KeyingSetInfo): # All properties that are likely to get animated in a character rig -class BUILTIN_KSI_WholeCharacter(bpy.types.KeyingSetInfo): +class BUILTIN_KSI_WholeCharacter(KeyingSetInfo): bl_label = "Whole Character" # these prefixes should be avoided, as they are not really bones @@ -265,7 +266,7 @@ class BUILTIN_KSI_WholeCharacter(bpy.types.KeyingSetInfo): # loc, rot, scale - only include unlocked ones ksi.doLoc(ks, bone) - if bone.rotation_mode in ('QUATERNION', 'AXIS_ANGLE'): + if bone.rotation_mode in {'QUATERNION', 'AXIS_ANGLE'}: ksi.doRot4d(ks, bone) else: ksi.doRot3d(ks, bone) @@ -365,7 +366,7 @@ class BUILTIN_KSI_WholeCharacter(bpy.types.KeyingSetInfo): # Delta Location -class BUILTIN_KSI_DeltaLocation(bpy.types.KeyingSetInfo): +class BUILTIN_KSI_DeltaLocation(KeyingSetInfo): bl_label = "Delta Location" # poll - selected objects only (and only if active object in object mode) @@ -390,7 +391,7 @@ class BUILTIN_KSI_DeltaLocation(bpy.types.KeyingSetInfo): # Delta Rotation -class BUILTIN_KSI_DeltaRotation(bpy.types.KeyingSetInfo): +class BUILTIN_KSI_DeltaRotation(KeyingSetInfo): bl_label = "Delta Rotation" # poll - selected objects only (and only if active object in object mode) @@ -423,7 +424,7 @@ class BUILTIN_KSI_DeltaRotation(bpy.types.KeyingSetInfo): # Delta Scale -class BUILTIN_KSI_DeltaScale(bpy.types.KeyingSetInfo): +class BUILTIN_KSI_DeltaScale(KeyingSetInfo): bl_label = "Delta Scale" # poll - selected objects only (and only if active object in object mode) -- cgit v1.2.3 From 047e8224b14aa7836db3b067824258e49e8602db Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Tue, 30 Aug 2011 11:31:48 +0000 Subject: Fix for my last commit. --- release/scripts/startup/bl_ui/properties_data_armature.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'release/scripts/startup') diff --git a/release/scripts/startup/bl_ui/properties_data_armature.py b/release/scripts/startup/bl_ui/properties_data_armature.py index 3d1903f4cbc..e17064178b8 100644 --- a/release/scripts/startup/bl_ui/properties_data_armature.py +++ b/release/scripts/startup/bl_ui/properties_data_armature.py @@ -72,8 +72,7 @@ class DATA_PT_skeleton(ArmatureButtonsPanel, Panel): flow.prop(arm, "use_deform_preserve_volume", text="Quaternion") if context.scene.render.engine == "BLENDER_GAME": - layout.row().prop(arm, "vert_deformer", expand=True, text="") - + layout.row().prop(arm, "vert_deformer", expand=True) class DATA_PT_display(ArmatureButtonsPanel, Panel): bl_label = "Display" -- cgit v1.2.3 From 0de9af375b5a437ab50d1d1725195ddaa35607c9 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Tue, 30 Aug 2011 12:45:56 +0000 Subject: 2.5 Game UI: *Fix for clutter after pepper merge, 3 booleans in one row, is 1 too much here ;-) --- release/scripts/startup/bl_ui/properties_game.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'release/scripts/startup') diff --git a/release/scripts/startup/bl_ui/properties_game.py b/release/scripts/startup/bl_ui/properties_game.py index e3c576e7093..161e4b10cff 100644 --- a/release/scripts/startup/bl_ui/properties_game.py +++ b/release/scripts/startup/bl_ui/properties_game.py @@ -340,10 +340,12 @@ class RENDER_PT_game_performance(RenderButtonsPanel, Panel): layout = self.layout gs = context.scene.game_settings - row = layout.row() + col = layout.column() + row = col.row() row.prop(gs, "use_frame_rate") row.prop(gs, "use_display_lists") - row.prop(gs, "restrict_animation_updates") + + col.prop(gs, "restrict_animation_updates") class RENDER_PT_game_display(RenderButtonsPanel, Panel): -- cgit v1.2.3 From f940e5fdd91ef02a454cd6a509f76953a77754dd Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 1 Sep 2011 10:56:16 +0000 Subject: Feature Request #28449: Pose Library poses can be renamed from Properties Editor --- release/scripts/startup/bl_ui/properties_data_armature.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'release/scripts/startup') diff --git a/release/scripts/startup/bl_ui/properties_data_armature.py b/release/scripts/startup/bl_ui/properties_data_armature.py index e17064178b8..463ba84470f 100644 --- a/release/scripts/startup/bl_ui/properties_data_armature.py +++ b/release/scripts/startup/bl_ui/properties_data_armature.py @@ -185,9 +185,13 @@ class DATA_PT_pose_library(ArmatureButtonsPanel, Panel): layout.template_ID(ob, "pose_library", new="poselib.new", unlink="poselib.unlink") if poselib: + + # list of poses in pose library row = layout.row() row.template_list(poselib, "pose_markers", poselib.pose_markers, "active_index", rows=5) - + + # column of operators for active pose + # - goes beside list col = row.column(align=True) col.active = (poselib.library is None) @@ -202,8 +206,12 @@ class DATA_PT_pose_library(ArmatureButtonsPanel, Panel): if pose_marker_active is not None: col.operator("poselib.pose_remove", icon='ZOOMOUT', text="").pose = pose_marker_active.name col.operator("poselib.apply_pose", icon='ZOOM_SELECTED', text="").pose_index = poselib.pose_markers.active_index - - layout.operator("poselib.action_sanitise") + + col.operator("poselib.action_sanitise", icon='HELP', text="") # XXX: put in menu? + + # properties for active marker + if pose_marker_active is not None: + layout.prop(pose_marker_active, "name") # TODO: this panel will soon be depreceated too -- cgit v1.2.3