[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [35736] trunk/blender: Animation Tool: Propagate Pose

Joshua Leung aligorith at gmail.com
Thu Mar 24 04:02:36 CET 2011


Revision: 35736
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=35736
Author:   aligorith
Date:     2011-03-24 03:02:34 +0000 (Thu, 24 Mar 2011)
Log Message:
-----------
Animation Tool: Propagate Pose

This tool automates the process of copying a pose to successive
keyframes, making it easier for animators to go back and change the
pose for some controls which remain "static" for periods of time.
Previously, animators would need to do a "{Ctrl-Pageup Ctrl-V} *
number_of_static_keyframes" dance for each set of controls that this
happened on, which is not too good ergonomically speaking.

There are two modes exposed via the menu (Pose->Propagate):
- "Pose Propagate" - also known as the 'WHILE_HELD' mode, which
propagates to all keyframes that are holding the same value
- "To Next Keyframe" - which only propagates the pose to the closest
keyframe in the occurring after (but not including) the current frame

Additionally, there are a few other modes that can be used, though
they are less useful for direct use from the UI, though they can be
used via the PyAPI as need be.

---

Also, I did some cleanups in the "Pose" menu to bring it more into
line with the Object mode one. There are some more tweaks that could
still be done here, such as bringing the keyframing operator entries
under a submenu too (as in the Object mode version) to get the length
of this under control.

Modified Paths:
--------------
    trunk/blender/release/scripts/startup/bl_ui/space_view3d.py
    trunk/blender/source/blender/editors/animation/keyframes_draw.c
    trunk/blender/source/blender/editors/armature/armature_intern.h
    trunk/blender/source/blender/editors/armature/armature_ops.c
    trunk/blender/source/blender/editors/armature/poseSlide.c
    trunk/blender/source/blender/editors/armature/poseobject.c
    trunk/blender/source/blender/editors/include/ED_keyframes_draw.h

Modified: trunk/blender/release/scripts/startup/bl_ui/space_view3d.py
===================================================================
--- trunk/blender/release/scripts/startup/bl_ui/space_view3d.py	2011-03-24 00:14:49 UTC (rev 35735)
+++ trunk/blender/release/scripts/startup/bl_ui/space_view3d.py	2011-03-24 03:02:34 UTC (rev 35736)
@@ -177,11 +177,7 @@
         layout.operator("object.origin_set", text="Origin to Geometry").type = 'ORIGIN_GEOMETRY'
         layout.operator("object.origin_set", text="Origin to 3D Cursor").type = 'ORIGIN_CURSOR'
 
-        if context.mode == 'OBJECT':
-            layout.operator("object.align")
-            layout.operator("object.randomize_transform")
 
-
 class VIEW3D_MT_mirror(bpy.types.Menu):
     bl_label = "Mirror"
 
@@ -254,14 +250,6 @@
 
         layout.operator("uv.reset")
 
-        layout.separator()
-
-        # python scripts
-        layout.operator_context = 'INVOKE_REGION_WIN'
-        layout.operator("uv.smart_project")
-        layout.operator("uv.lightmap_pack")
-        layout.operator("uv.follow_active_quads")
-
 # ********** View menus **********
 
 
@@ -1172,33 +1160,33 @@
         layout.separator()
 
         layout.menu("VIEW3D_MT_transform")
-        layout.menu("VIEW3D_MT_snap")
 
         layout.menu("VIEW3D_MT_pose_transform")
+        layout.menu("VIEW3D_MT_pose_apply")	
+		
+        layout.menu("VIEW3D_MT_snap")
 
         layout.separator()
 
+        # TODO: make this an "Animation" menu like we have for object?
         layout.operator("anim.keyframe_insert_menu", text="Insert Keyframe...")
         layout.operator("anim.keyframe_delete_v3d", text="Delete Keyframe...")
         layout.operator("anim.keying_set_active_set", text="Change Keying Set...")
 
         layout.separator()
 
-        layout.operator("pose.relax")
+        layout.menu("VIEW3D_MT_pose_slide")
+        layout.menu("VIEW3D_MT_pose_propagate")
 
         layout.separator()
 
-        layout.menu("VIEW3D_MT_pose_apply")
-
-        layout.separator()
-
         layout.operator("pose.copy")
         layout.operator("pose.paste")
         layout.operator("pose.paste", text="Paste X-Flipped Pose").flipped = True
 
         layout.separator()
 
-        layout.menu("VIEW3D_MT_pose_pose")
+        layout.menu("VIEW3D_MT_pose_library")
         layout.menu("VIEW3D_MT_pose_motion")
         layout.menu("VIEW3D_MT_pose_group")
 
@@ -1246,7 +1234,28 @@
         layout.label(text="Origin")
 
 
-class VIEW3D_MT_pose_pose(bpy.types.Menu):
+class VIEW3D_MT_pose_slide(bpy.types.Menu):
+    bl_label = "In-Betweens"
+
+    def draw(self, context):
+        layout = self.layout
+
+        layout.operator("pose.push")
+        layout.operator("pose.relax")
+        layout.operator("pose.breakdown")
+
+
+class VIEW3D_MT_pose_propagate(bpy.types.Menu):
+    bl_label = "Propagate"
+
+    def draw(self, context):
+        layout = self.layout
+
+        layout.operator("pose.propagate")
+        layout.operator("pose.propagate", text="To Next Keyframe").mode = 'NEXT_KEY'
+
+
+class VIEW3D_MT_pose_library(bpy.types.Menu):
     bl_label = "Pose Library"
 
     def draw(self, context):
@@ -2313,3 +2322,14 @@
         if member:
             # Draw with no edit button
             rna_prop_ui.draw(self.layout, context, member, object, False)
+
+
+def register():
+    bpy.utils.register_module(__name__)
+
+
+def unregister():
+    bpy.utils.unregister_module(__name__)
+
+if __name__ == "__main__":
+    register()

Modified: trunk/blender/source/blender/editors/animation/keyframes_draw.c
===================================================================
--- trunk/blender/source/blender/editors/animation/keyframes_draw.c	2011-03-24 00:14:49 UTC (rev 35735)
+++ trunk/blender/source/blender/editors/animation/keyframes_draw.c	2011-03-24 03:02:34 UTC (rev 35736)
@@ -80,7 +80,7 @@
 /* ActKeyColumns (Keyframe Columns) ------------------------------------------ */
 
 /* Comparator callback used for ActKeyColumns and cframe float-value pointer */
-// NOTE: this is exported to other modules that use the ActKeyColumns for finding keyframes
+/* NOTE: this is exported to other modules that use the ActKeyColumns for finding keyframes */
 short compare_ak_cfraPtr (void *node, void *data)
 {
 	ActKeyColumn *ak= (ActKeyColumn *)node;
@@ -311,6 +311,23 @@
 
 /* ActKeyBlocks (Long Keyframes) ------------------------------------------ */
 
+/* Comparator callback used for ActKeyBlock and cframe float-value pointer */
+/* NOTE: this is exported to other modules that use the ActKeyBlocks for finding long-keyframes */
+short compare_ab_cfraPtr (void *node, void *data)
+{
+	ActKeyBlock *ab= (ActKeyBlock *)node;
+	float *cframe= data;
+	
+	if (*cframe < ab->start)
+		return -1;
+	else if (*cframe > ab->start)
+		return 1;
+	else
+		return 0;
+}
+
+/* --------------- */
+
 /* Create a ActKeyColumn for a pair of BezTriples */
 static ActKeyBlock *bezts_to_new_actkeyblock(BezTriple *prev, BezTriple *beztn)
 {

Modified: trunk/blender/source/blender/editors/armature/armature_intern.h
===================================================================
--- trunk/blender/source/blender/editors/armature/armature_intern.h	2011-03-24 00:14:49 UTC (rev 35735)
+++ trunk/blender/source/blender/editors/armature/armature_intern.h	2011-03-24 03:02:34 UTC (rev 35736)
@@ -200,6 +200,8 @@
 void POSE_OT_relax(struct wmOperatorType *ot);
 void POSE_OT_breakdown(struct wmOperatorType *ot);
 
+void POSE_OT_propagate(struct wmOperatorType *ot);
+
 /* ******************************************************* */
 /* editarmature.c */
 

Modified: trunk/blender/source/blender/editors/armature/armature_ops.c
===================================================================
--- trunk/blender/source/blender/editors/armature/armature_ops.c	2011-03-24 00:14:49 UTC (rev 35735)
+++ trunk/blender/source/blender/editors/armature/armature_ops.c	2011-03-24 03:02:34 UTC (rev 35736)
@@ -146,6 +146,8 @@
 	WM_operatortype_append(POSE_OT_armature_layers);
 	WM_operatortype_append(POSE_OT_bone_layers);
 	
+	WM_operatortype_append(POSE_OT_propagate);
+	
 	/* POSELIB */
 	WM_operatortype_append(POSELIB_OT_browse_interactive);
 	WM_operatortype_append(POSELIB_OT_apply_pose);

Modified: trunk/blender/source/blender/editors/armature/poseSlide.c
===================================================================
--- trunk/blender/source/blender/editors/armature/poseSlide.c	2011-03-24 00:14:49 UTC (rev 35735)
+++ trunk/blender/source/blender/editors/armature/poseSlide.c	2011-03-24 03:02:34 UTC (rev 35736)
@@ -61,8 +61,6 @@
 #include "WM_api.h"
 #include "WM_types.h"
 
-
-
 #include "ED_armature.h"
 #include "ED_keyframes_draw.h"
 #include "ED_screen.h"
@@ -77,7 +75,13 @@
  * for interactively controlling the spacing of poses, but also
  * for 'pushing' and/or 'relaxing' extremes as they see fit.
  *
- * B) Pose Sculpting
+ * B) Propagate
+ * This tool copies elements of the selected pose to successive
+ * keyframes, allowing the animator to go back and modify the poses
+ * for some "static" pose controls, without having to repeatedly
+ * doing a "next paste" dance.
+ *
+ * C) Pose Sculpting
  * This is yet to be implemented, but the idea here is to use
  * sculpting techniques to make it easier to pose rigs by allowing
  * rigs to be manipulated using a familiar paint-based interface. 
@@ -854,3 +858,340 @@
 }
 
 /* **************************************************** */
+/* B) Pose Propagate */
+
+/* "termination conditions" - i.e. when we stop */
+typedef enum ePosePropagate_Termination {
+		/* stop when we run out of keyframes */
+	POSE_PROPAGATE_LAST_KEY	= 0,
+		/* stop after the next keyframe */
+	POSE_PROPAGATE_NEXT_KEY,
+		/* stop after the specified frame */
+	POSE_PROPAGATE_BEFORE_FRAME,
+		/* stop after */
+	POSE_PROPAGATE_SMART_HOLDS
+} ePosePropagate_Termination;
+
+/* --------------------------------- */
+
+/* helper for pose_propagate_get_boneHoldEndFrame() 
+ * Checks if ActKeyBlock should exist...
+ */
+// TODO: move to keyframes drawing API...
+static short actkeyblock_is_valid (ActKeyBlock *ab, DLRBT_Tree *keys)
+{
+	ActKeyColumn *ak;
+	short startCurves, endCurves, totCurves;
+	
+	/* check that block is valid */
+	if (ab == NULL)
+		return 0;
+	
+	/* find out how many curves occur at each keyframe */
+	ak= (ActKeyColumn *)BLI_dlrbTree_search_exact(keys, compare_ak_cfraPtr, &ab->start);
+	startCurves = (ak)? ak->totcurve: 0;
+	
+	ak= (ActKeyColumn *)BLI_dlrbTree_search_exact(keys, compare_ak_cfraPtr, &ab->end);
+	endCurves = (ak)? ak->totcurve: 0;
+	
+	/* only draw keyblock if it appears in at all of the keyframes at lowest end */
+	if (!startCurves && !endCurves) 
+		return 0;
+	
+	totCurves = (startCurves>endCurves)? endCurves: startCurves;
+	return (ab->totcurve >= totCurves);
+}
+
+/* get frame on which the "hold" for the bone ends 
+ * XXX: this may not really work that well if a bone moves on some channels and not others
+ * 		if this happens to be a major issue, scrap this, and just make this happen 
+ *		independently per F-Curve
+ */
+static float pose_propagate_get_boneHoldEndFrame (Object *ob, tPChanFCurveLink *pfl, float startFrame)
+{
+	DLRBT_Tree keys, blocks;
+	ActKeyBlock *ab;
+	
+	AnimData *adt= ob->adt;
+	LinkData *ld;
+	float endFrame = startFrame;
+	
+	/* set up optimised data-structures for searching for relevant keyframes + holds */
+	BLI_dlrbTree_init(&keys);
+	BLI_dlrbTree_init(&blocks);
+	
+	for (ld = pfl->fcurves.first; ld; ld = ld->next) {
+		FCurve *fcu = (FCurve *)ld->data;
+		fcurve_to_keylist(adt, fcu, &keys, &blocks);
+	}
+	
+	BLI_dlrbTree_linkedlist_sync(&keys);
+	BLI_dlrbTree_linkedlist_sync(&blocks);
+	
+	/* find the long keyframe (i.e. hold), and hence obtain the endFrame value 
+	 *	- the best case would be one that starts on the frame itself
+	 */
+	ab = (ActKeyBlock *)BLI_dlrbTree_search_exact(&blocks, compare_ab_cfraPtr, &startFrame);
+	
+	if (actkeyblock_is_valid(ab, &keys) == 0) {
+		/* There are only two cases for no-exact match:
+		 * 	1) the current frame is just before another key but not on a key itself
+		 * 	2) the current frame is on a key, but that key doesn't link to the next
+		 *
+		 * If we've got the first case, then we can search for another block, 
+		 * otherwise forget it, as we'd be overwriting some valid data.
+		 */
+		if (BLI_dlrbTree_search_exact(&keys, compare_ak_cfraPtr, &startFrame) == NULL) {
+			/* we've got case 1, so try the one after */

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list