[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [23359] trunk/blender/source/blender/ editors: 2.5 - Pose Relax/Push improvements

Joshua Leung aligorith at gmail.com
Sun Sep 20 07:05:17 CEST 2009


Revision: 23359
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=23359
Author:   aligorith
Date:     2009-09-20 07:05:16 +0200 (Sun, 20 Sep 2009)

Log Message:
-----------
2.5 - Pose Relax/Push improvements

* Relax and Push are now interactive. Moving the mouse left<->right decreases/increases (respectively) the number of times the pose is relaxed or pushed. The sensitivity on this could be tweaked as necessary.

* Cancelling these 'pose sliding' tools now correctly restores the initial pose
* Autokeyframing is now only done when the operator is confirmed.

--

Also, made 'View persp/ortho' <-> 'View Persp/Ortho' to be more in line with other operator names, but to also make it easier to read.

Modified Paths:
--------------
    trunk/blender/source/blender/editors/armature/poseSlide.c
    trunk/blender/source/blender/editors/space_view3d/view3d_edit.c

Modified: trunk/blender/source/blender/editors/armature/poseSlide.c
===================================================================
--- trunk/blender/source/blender/editors/armature/poseSlide.c	2009-09-20 01:36:11 UTC (rev 23358)
+++ trunk/blender/source/blender/editors/armature/poseSlide.c	2009-09-20 05:05:16 UTC (rev 23359)
@@ -135,7 +135,13 @@
 	
 	ListBase fcurves;		/* F-Curves for this PoseChannel */
 	bPoseChannel *pchan;	/* Pose Channel which data is attached to */
+	
 	char *pchan_path;		/* RNA Path to this Pose Channel (needs to be freed when we're done) */
+	
+	float oldloc[3];		/* transform values at start of operator (to be restored before each modal step) */
+	float oldrot[3];
+	float oldscale[3];
+	float oldquat[4];
 } tPChanFCurveLink;
 
 /* ------------------------------------ */
@@ -202,6 +208,12 @@
 				pchan->flag |= POSE_ROT;
 			if (transFlags & ACT_TRANS_SCALE)
 				pchan->flag |= POSE_SIZE;
+				
+			/* store current transforms */
+			VECCOPY(pfl->oldloc, pchan->loc);
+			VECCOPY(pfl->oldrot, pchan->eul);
+			VECCOPY(pfl->oldscale, pchan->size);
+			QUATCOPY(pfl->oldquat, pchan->quat);
 		}
 	}
 	CTX_DATA_END;
@@ -261,6 +273,23 @@
 
 /* ------------------------------------ */
 
+/* helper for apply() / reset() - refresh the data */
+static void pose_slide_refresh (bContext *C, tPoseSlideOp *pso)
+{
+	/* old optimize trick... this enforces to bypass the depgraph 
+	 *	- note: code copied from transform_generics.c -> recalcData()
+	 */
+	// FIXME: shouldn't this use the builtin stuff?
+	if ((pso->arm->flag & ARM_DELAYDEFORM)==0)
+		DAG_id_flush_update(&pso->ob->id, OB_RECALC_DATA);  /* sets recalc flags */
+	else
+		where_is_pose(pso->scene, pso->ob);
+	
+	/* note, notifier might evolve */
+	WM_event_add_notifier(C, NC_OBJECT|ND_POSE, pso->ob);
+	WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);	
+}
+
 /* helper for apply() callabcks - find the next F-Curve with matching path... */
 static LinkData *find_next_fcurve_link (ListBase *fcuLinks, LinkData *prev, char *path)
 {
@@ -330,22 +359,45 @@
 			w2 = (w2/wtot);
 		}
 		
-		/* depending on the mode, */
+		/* depending on the mode, calculate the new value
+		 *	- in all of these, the start+end values are multiplied by w2 and w1 (respectively),
+		 *	  since multiplication in another order would decrease the value the current frame is closer to
+		 */
 		switch (pso->mode) {
 			case POSESLIDE_PUSH: /* make the current pose more pronounced */
-				// TODO: this is not interactively modifiable!
-				vec[ch]= ( -((sVal * w2) + (eVal * w1)) + (vec[ch] * 6.0f) ) / 5.0f;
+			{
+				/* perform a weighted average here, favouring the middle pose 
+				 *	- numerator should be larger than denominator to 'expand' the result
+				 *	- perform this weighting a number of times given by the percentage...
+				 */
+				int iters= (int)ceil(10.0f*pso->percentage); // TODO: maybe a sensitivity ctrl on top of this is needed
+				
+				while (iters-- > 0) {
+					vec[ch]= ( -((sVal * w2) + (eVal * w1)) + (vec[ch] * 6.0f) ) / 5.0f; 
+				}
+			}
 				break;
 				
 			case POSESLIDE_RELAX: /* make the current pose more like its surrounding ones */
-				/* apply the value with a hard coded 6th */
-				// TODO: this is not interactively modifiable!
-				vec[ch]= ( ((sVal * w2) + (eVal * w1)) + (vec[ch] * 5.0f) ) / 6.0f;
+			{
+				/* perform a weighted average here, favouring the middle pose 
+				 *	- numerator should be smaller than denominator to 'relax' the result
+				 *	- perform this weighting a number of times given by the percentage...
+				 */
+				int iters= (int)ceil(10.0f*pso->percentage); // TODO: maybe a sensitivity ctrl on top of this is needed
+				
+				while (iters-- > 0) {
+					vec[ch]= ( ((sVal * w2) + (eVal * w1)) + (vec[ch] * 5.0f) ) / 6.0f;
+				}
+			}
 				break;
 				
 			case POSESLIDE_BREAKDOWN: /* make the current pose slide around between the endpoints */
+			{
 				/* perform simple linear interpolation - coefficient for start must come from pso->percentage... */
+				// TODO: make this use some kind of spline interpolation instead?
 				vec[ch]= ((sVal * w2) + (eVal * w1));
+			}
 				break;
 		}
 		
@@ -384,26 +436,6 @@
 #endif
 }
 
-/* helper for apply() - perform autokeyframing */
-static void pose_slide_autoKeyframe (bContext *C, tPoseSlideOp *pso, bPoseChannel *pchan, KeyingSet *ks)
-{
-	/* insert keyframes as necessary if autokeyframing */
-	if (autokeyframe_cfra_can_key(pso->scene, &pso->ob->id)) {
-		bCommonKeySrc cks;
-		ListBase dsources = {&cks, &cks};
-		
-		/* init common-key-source for use by KeyingSets */
-		memset(&cks, 0, sizeof(bCommonKeySrc));
-		cks.id= &pso->ob->id;
-		
-		/* init cks for this PoseChannel, then use the relative KeyingSets to keyframe it */
-		cks.pchan= pchan;
-		
-		/* insert keyframes */
-		modify_keyframes(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)pso->cframe);
-	}
-}
-
 /* apply() - perform the pose sliding based on weighting various poses */
 static void pose_slide_apply (bContext *C, wmOperator *op, tPoseSlideOp *pso)
 {
@@ -428,15 +460,11 @@
 		if (pchan->flag & POSE_LOC) {
 			/* calculate these for the 'location' vector, and use location curves */
 			pose_slide_apply_vec3(pso, pfl, pchan->loc, "location");
-			/* insert keyframes if needed */
-			pose_slide_autoKeyframe(C, pso, pchan, pso->ks_loc);
 		}
 		
 		if (pchan->flag & POSE_SIZE) {
 			/* calculate these for the 'scale' vector, and use scale curves */
 			pose_slide_apply_vec3(pso, pfl, pchan->size, "scale");
-			/* insert keyframes if needed */
-			pose_slide_autoKeyframe(C, pso, pchan, pso->ks_scale);
 		}
 		
 		if (pchan->flag & POSE_ROT) {
@@ -452,24 +480,58 @@
 				/* quaternions - use quaternion blending */
 				pose_slide_apply_quat(pso, pfl);
 			}
+		}
+	}
+	
+	/* depsgraph updates + redraws */
+	pose_slide_refresh(C, pso);
+}
+
+/* perform autokeyframing after changes were made + confirmed */
+static void pose_slide_autoKeyframe (bContext *C, tPoseSlideOp *pso)
+{
+	/* insert keyframes as necessary if autokeyframing */
+	if (autokeyframe_cfra_can_key(pso->scene, &pso->ob->id)) {
+		bCommonKeySrc cks;
+		ListBase dsources = {&cks, &cks};
+		tPChanFCurveLink *pfl;
+		
+		/* init common-key-source for use by KeyingSets */
+		memset(&cks, 0, sizeof(bCommonKeySrc));
+		cks.id= &pso->ob->id;
+		
+		/* iterate over each pose-channel affected, applying the changes */
+		for (pfl= pso->pfLinks.first; pfl; pfl= pfl->next) {
+			bPoseChannel *pchan= pfl->pchan;
+			/* init cks for this PoseChannel, then use the relative KeyingSets to keyframe it */
+			cks.pchan= pchan;
 			
-			/* insert keyframes if needed */
-			pose_slide_autoKeyframe(C, pso, pchan, pso->ks_rot);
+			/* insert keyframes */
+			if (pchan->flag & POSE_LOC)
+				modify_keyframes(C, &dsources, NULL, pso->ks_loc, MODIFYKEY_MODE_INSERT, (float)pso->cframe);
+			if (pchan->flag & POSE_ROT)
+				modify_keyframes(C, &dsources, NULL, pso->ks_rot, MODIFYKEY_MODE_INSERT, (float)pso->cframe);
+			if (pchan->flag & POSE_SIZE)
+				modify_keyframes(C, &dsources, NULL, pso->ks_scale, MODIFYKEY_MODE_INSERT, (float)pso->cframe);
 		}
 	}
+}
+
+/* reset changes made to current pose */
+static void pose_slide_reset (bContext *C, tPoseSlideOp *pso)
+{
+	tPChanFCurveLink *pfl;
 	
-	/* old optimize trick... this enforces to bypass the depgraph 
-	 *	- note: code copied from transform_generics.c -> recalcData()
-	 */
-	// FIXME: shouldn't this use the builtin stuff?
-	if ((pso->arm->flag & ARM_DELAYDEFORM)==0)
-		DAG_id_flush_update(&pso->ob->id, OB_RECALC_DATA);  /* sets recalc flags */
-	else
-		where_is_pose(pso->scene, pso->ob);
-	
-	/* note, notifier might evolve */
-	WM_event_add_notifier(C, NC_OBJECT|ND_POSE, pso->ob);
-	WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
+	/* iterate over each pose-channel affected, restoring all channels to their original values */
+	for (pfl= pso->pfLinks.first; pfl; pfl= pfl->next) {
+		bPoseChannel *pchan= pfl->pchan;
+		
+		/* just copy all the values over regardless of whether they changed or not */
+		VECCOPY(pchan->loc, pfl->oldloc);
+		VECCOPY(pchan->eul, pfl->oldrot);
+		VECCOPY(pchan->size, pfl->oldscale);
+		QUATCOPY(pchan->quat, pfl->oldquat);
+	}
 }
 
 /* ------------------------------------ */
@@ -538,24 +600,19 @@
 		return OPERATOR_CANCELLED;
 	}
 	
-	// FIXME: for now, just do modal for breakdowns... 
-	if (pso->mode == POSESLIDE_BREAKDOWN) {	
-		/* initial apply for operator... */
-		pose_slide_apply(C, op, pso);
-		
-		/* set cursor to indicate modal */
-		WM_cursor_modal(win, BC_EW_SCROLLCURSOR);
-		
-		/* add a modal handler for this operator */
-		WM_event_add_modal_handler(C, op);
-		return OPERATOR_RUNNING_MODAL;
-	}
-	else {
-		/* temp static operator code... until a way to include percentage in the formulation comes up */
-		pose_slide_apply(C, op, pso);
-		pose_slide_exit(C, op);
-		return OPERATOR_FINISHED;
-	}
+	/* initial apply for operator... */
+	// TODO: need to calculate percentage for initial round too...
+	pose_slide_apply(C, op, pso);
+	
+	/* depsgraph updates + redraws */
+	pose_slide_refresh(C, pso);
+	
+	/* set cursor to indicate modal */
+	WM_cursor_modal(win, BC_EW_SCROLLCURSOR);
+	
+	/* add a modal handler for this operator */
+	WM_event_add_modal_handler(C, op);
+	return OPERATOR_RUNNING_MODAL;
 }
 
 /* common code for modal() */
@@ -566,15 +623,36 @@
 	
 	switch (evt->type) {
 		case LEFTMOUSE:	/* confirm */
+		{
+			/* return to normal cursor */
 			WM_cursor_restore(win);
+			
+			/* insert keyframes as required... */
+			pose_slide_autoKeyframe(C, pso);
 			pose_slide_exit(C, op);
+			
+			/* done! */
 			return OPERATOR_FINISHED;
+		}
 		
 		case ESCKEY:	/* cancel */
 		case RIGHTMOUSE: 
+		{
+			/* return to normal cursor */
 			WM_cursor_restore(win);
+			
+			/* reset transforms back to original state */
+			pose_slide_reset(C, pso);
+			
+			/* depsgraph updates + redraws */
+			pose_slide_refresh(C, pso);
+			
+			/* clean up temp data */
 			pose_slide_exit(C, op);
+			
+			/* cancelled! */
 			return OPERATOR_CANCELLED;
+		}
 			
 		case MOUSEMOVE: /* calculate new position */
 		{
@@ -584,6 +662,9 @@
 			pso->percentage= (evt->x - pso->ar->winrct.xmin) / ((float)pso->ar->winx);
 			RNA_float_set(op->ptr, "percentage", pso->percentage);
 			
+			/* reset transforms (to avoid accumulation errors) */
+			pose_slide_reset(C, pso);
+			
 			/* apply... */
 			pose_slide_apply(C, op, pso);
 		}
@@ -608,6 +689,9 @@
 	/* settings should have been set up ok for applying, so just apply! */

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list