Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Leung <aligorith@gmail.com>2009-09-20 09:05:16 +0400
committerJoshua Leung <aligorith@gmail.com>2009-09-20 09:05:16 +0400
commit22995e9c459ad8dc7acbde15db94b2013def78f8 (patch)
tree4e8c87e05876507ab979392f771e80892e9de441 /source/blender/editors/armature
parentf4b9ec0e37d636c974f4ea24c90d288015df7d24 (diff)
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.
Diffstat (limited to 'source/blender/editors/armature')
-rw-r--r--source/blender/editors/armature/poseSlide.c220
1 files changed, 152 insertions, 68 deletions
diff --git a/source/blender/editors/armature/poseSlide.c b/source/blender/editors/armature/poseSlide.c
index eb290b1f83c..02c23f01f1e 100644
--- a/source/blender/editors/armature/poseSlide.c
+++ b/source/blender/editors/armature/poseSlide.c
@@ -135,7 +135,13 @@ typedef struct tPChanFCurveLink {
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 @@ static int pose_slide_init (bContext *C, wmOperator *op, short mode)
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 @@ static void pose_slide_exit (bContext *C, wmOperator *op)
/* ------------------------------------ */
+/* 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 @@ static void pose_slide_apply_vec3 (tPoseSlideOp *pso, tPChanFCurveLink *pfl, flo
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 @@ static void pose_slide_apply_quat (tPoseSlideOp *pso, tPChanFCurveLink *pfl)
#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 @@ static void pose_slide_apply (bContext *C, wmOperator *op, tPoseSlideOp *pso)
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 @@ static void pose_slide_apply (bContext *C, wmOperator *op, tPoseSlideOp *pso)
/* quaternions - use quaternion blending */
pose_slide_apply_quat(pso, pfl);
}
-
- /* insert keyframes if needed */
- pose_slide_autoKeyframe(C, pso, pchan, pso->ks_rot);
}
}
- /* 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);
+ /* 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 (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;
- /* 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 @@ static int pose_slide_invoke_common (bContext *C, wmOperator *op, tPoseSlideOp *
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 @@ static int pose_slide_modal (bContext *C, wmOperator *op, wmEvent *evt)
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 @@ static int pose_slide_modal (bContext *C, wmOperator *op, wmEvent *evt)
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 @@ static int pose_slide_exec_common (bContext *C, wmOperator *op, tPoseSlideOp *ps
/* settings should have been set up ok for applying, so just apply! */
pose_slide_apply(C, op, pso);
+ /* insert keyframes if needed */
+ pose_slide_autoKeyframe(C, pso);
+
/* cleanup and done */
pose_slide_exit(C, op);
@@ -668,12 +752,12 @@ void POSE_OT_push (wmOperatorType *ot)
/* callbacks */
ot->exec= pose_slide_push_exec;
ot->invoke= pose_slide_push_invoke;
- //ot->modal= pose_slide_modal;
- //ot->cancel= pose_slide_cancel;
+ ot->modal= pose_slide_modal;
+ ot->cancel= pose_slide_cancel;
ot->poll= ED_operator_posemode;
/* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;//|OPTYPE_BLOCKING;
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
/* Properties */
pose_slide_opdef_properties(ot);
@@ -725,12 +809,12 @@ void POSE_OT_relax (wmOperatorType *ot)
/* callbacks */
ot->exec= pose_slide_relax_exec;
ot->invoke= pose_slide_relax_invoke;
- //ot->modal= pose_slide_modal;
- //ot->cancel= pose_slide_cancel;
+ ot->modal= pose_slide_modal;
+ ot->cancel= pose_slide_cancel;
ot->poll= ED_operator_posemode;
/* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;//|OPTYPE_BLOCKING;
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
/* Properties */
pose_slide_opdef_properties(ot);