2.5 - Yet another round of bugfixes
authorJoshua Leung <aligorith@gmail.com>
Sun, 20 Sep 2009 12:54:30 +0000 (12:54 +0000)
committerJoshua Leung <aligorith@gmail.com>
Sun, 20 Sep 2009 12:54:30 +0000 (12:54 +0000)
* Copy Rotation constraint "should" work ok for custom rotation orders now. It now converts both rotations to the form used by the owner. So far, this doesn't seem to have broken any of the test rigs in my test-suite, though new specimens for the hall of flakiness are always welcome.

* Fixed many RNA wrapping bugs for Armature data.
- Fixed a few wrong tooltips
- Made proper refreshes for restpose/posed, etc.

* Started converting special quaternion interpolation for Pose Sliding tools (push/relax/breakdown), though this doesn't seem to be working correctly yet.
-->> Help to get these working right is welcome :)

source/blender/blenkernel/intern/constraint.c
source/blender/editors/armature/poseSlide.c
source/blender/makesrna/intern/rna_armature.c

index 748208d6c0bfd410f3d3f701e8d0a44c8e0594cc..e49bda0fdd2ac6417ae7d96bdd6c83d39a0daf7b 100644 (file)
@@ -1588,7 +1588,8 @@ static void rotlike_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *ta
                VECCOPY(loc, cob->matrix[3]);
                Mat4ToSize(cob->matrix, size);
                
-               Mat4ToEulO(ct->matrix, eul, ct->rotOrder);
+               /* to allow compatible rotations, must get both rotations in the order of the owner... */
+               Mat4ToEulO(ct->matrix, eul, cob->rotOrder);
                Mat4ToEulO(cob->matrix, obeul, cob->rotOrder);
                
                if ((data->flag & ROTLIKE_X)==0)
index 02c23f01f1e88e41bae3b49d8bd2a568ce672b0c..353503967ec42c28fd8e16ef935c45d0f72b74cb 100644 (file)
@@ -410,30 +410,82 @@ static void pose_slide_apply_vec3 (tPoseSlideOp *pso, tPChanFCurveLink *pfl, flo
 /* helper for apply() - perform sliding for quaternion rotations (using quat blending) */
 static void pose_slide_apply_quat (tPoseSlideOp *pso, tPChanFCurveLink *pfl)
 {
-       // TODO: this is quite evil stuff...
-#if 0 // XXX port...
-       /* get 2 quats */
-       quat_prev[0] = eval_icu(icu_w, frame_prev);
-       quat_prev[1] = eval_icu(icu_x, frame_prev);
-       quat_prev[2] = eval_icu(icu_y, frame_prev);
-       quat_prev[3] = eval_icu(icu_z, frame_prev);
-       
-       quat_next[0] = eval_icu(icu_w, frame_next);
-       quat_next[1] = eval_icu(icu_x, frame_next);
-       quat_next[2] = eval_icu(icu_y, frame_next);
-       quat_next[3] = eval_icu(icu_z, frame_next);
-       
-#if 0
-       /* apply the setting, completely smooth */
-       QuatInterpol(pchan->quat, quat_prev, quat_next, (framef-frame_prev) / (frame_next-frame_prev) );
-#else
-       /* tricky interpolation */
-       QuatInterpol(quat_interp, quat_prev, quat_next, (framef-frame_prev) / (frame_next-frame_prev) );
-       QUATCOPY(quat_orig, pchan->quat);
-       QuatInterpol(pchan->quat, quat_orig, quat_interp, 1.0f/6.0f);
-       /* done */
-#endif
-#endif
+       FCurve *fcu_w=NULL, *fcu_x=NULL, *fcu_y=NULL, *fcu_z=NULL;
+       bPoseChannel *pchan= pfl->pchan;
+       LinkData *ld=NULL;
+       char *path=NULL;
+       float cframe;
+       
+       /* get the path to use - this should be quaternion rotations only (needs care) */
+       path= BLI_sprintfN("%s.%s", pfl->pchan_path, "rotation");
+       
+       /* get the current frame number */
+       cframe= (float)pso->cframe;
+       
+       /* using this path, find each matching F-Curve for the variables we're interested in */
+       while ( (ld= find_next_fcurve_link(&pfl->fcurves, ld, path)) ) {
+               FCurve *fcu= (FCurve *)ld->data;
+               
+               /* assign this F-Curve to one of the relevant pointers... */
+               switch (fcu->array_index) {
+                       case 3: /* z */
+                               fcu_z= fcu;
+                               break;
+                       case 2: /* y */
+                               fcu_y= fcu;
+                               break;
+                       case 1: /* x */
+                               fcu_x= fcu;
+                               break;
+                       case 0: /* w */
+                               fcu_w= fcu;
+                               break;
+               }
+       }
+       
+       /* only if all channels exist, proceed */
+       if (fcu_w && fcu_x && fcu_y && fcu_z) {
+               float quat_prev[4], quat_next[4];
+               
+               /* get 2 quats */
+               quat_prev[0] = evaluate_fcurve(fcu_w, pso->prevFrame);
+               quat_prev[1] = evaluate_fcurve(fcu_x, pso->prevFrame);
+               quat_prev[2] = evaluate_fcurve(fcu_y, pso->prevFrame);
+               quat_prev[3] = evaluate_fcurve(fcu_z, pso->prevFrame);
+               
+               quat_next[0] = evaluate_fcurve(fcu_w, pso->nextFrame);
+               quat_next[1] = evaluate_fcurve(fcu_x, pso->nextFrame);
+               quat_next[2] = evaluate_fcurve(fcu_y, pso->nextFrame);
+               quat_next[3] = evaluate_fcurve(fcu_z, pso->nextFrame);
+               
+               /* perform blending */
+               if (pso->mode == POSESLIDE_BREAKDOWN) {
+                       /* just perform the interpol between quat_prev and quat_next using pso->percentage as a guide */
+                       QuatInterpol(pchan->quat, quat_prev, quat_next, pso->percentage);
+               }
+               else {
+                       float quat_interp[4], quat_orig[4];
+                       int iters= (int)ceil(10.0f*pso->percentage); // TODO: maybe a sensitivity ctrl on top of this is needed
+                       
+                       /* perform this blending several times until a satisfactory result is reached */
+                       while (iters-- > 0) {
+                               /* calculate the interpolation between the endpoints */
+                               QuatInterpol(quat_interp, quat_prev, quat_next, (cframe-pso->prevFrame) / (pso->nextFrame-pso->prevFrame) );
+                               
+                               /* make a copy of the original rotation */
+                               QUATCOPY(quat_orig, pchan->quat);
+                               
+                               /* tricky interpolations - mode-dependent blending between original and new */
+                               if (pso->mode == POSESLIDE_RELAX) // xxx this was the original code, so should work fine
+                                       QuatInterpol(pchan->quat, quat_orig, quat_interp, 1.0f/6.0f);
+                               else // I'm just guessing here...
+                                       QuatInterpol(pchan->quat, quat_orig, quat_interp, 6.0f/5.0f);
+                       }
+               }
+       }
+       
+       /* free the path now */
+       MEM_freeN(path);
 }
 
 /* apply() - perform the pose sliding based on weighting various poses */
index a1bcbe57bd53dd0116ea7d1cfcbc3b504a13d17c..d06c8ccee03543b14e1b38afa6afda630ab37b1f 100644 (file)
@@ -52,6 +52,7 @@ static void rna_Armature_update_data(bContext *C, PointerRNA *ptr)
 
        DAG_id_flush_update(id, OB_RECALC_DATA);
        WM_event_add_notifier(C, NC_GEOM|ND_DATA, id);
+       //WM_event_add_notifier(C, NC_OBJECT|ND_POSE, NULL);
 }
 
 static void rna_Armature_redraw_data(bContext *C, PointerRNA *ptr)
@@ -577,7 +578,7 @@ static void rna_def_armature(BlenderRNA *brna)
        RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
        RNA_def_property_enum_items(prop, prop_pose_position_items);
        RNA_def_property_ui_text(prop, "Pose Position", "Show armature in binding pose or final posed state.");
-       RNA_def_property_update(prop, 0, "rna_Armature_redraw_data");
+       RNA_def_property_update(prop, 0, "rna_Armature_update_data");
        
        prop= RNA_def_property(srna, "drawtype", PROP_ENUM, PROP_NONE);
        RNA_def_property_enum_items(prop, prop_drawtype_items);
@@ -593,7 +594,7 @@ static void rna_def_armature(BlenderRNA *brna)
        prop= RNA_def_property(srna, "paths_type", PROP_ENUM, PROP_NONE);
        RNA_def_property_enum_bitflag_sdna(prop, NULL, "pathflag");
        RNA_def_property_enum_items(prop, prop_paths_type_items);
-       RNA_def_property_ui_text(prop, "Paths Type", "Mapping type to use for this image in the game engine.");
+       RNA_def_property_ui_text(prop, "Paths Type", "Type of range to show for Bone Paths");
        RNA_def_property_update(prop, 0, "rna_Armature_redraw_data");
        
        prop= RNA_def_property(srna, "paths_location", PROP_ENUM, PROP_NONE);
@@ -609,7 +610,7 @@ static void rna_def_armature(BlenderRNA *brna)
        RNA_def_property_array(prop, 16);
        RNA_def_property_ui_text(prop, "Visible Layers", "Armature layer visibility.");
        RNA_def_property_boolean_funcs(prop, NULL, "rna_Armature_layer_set");
-       RNA_def_property_update(prop, NC_OBJECT|ND_POSE, NULL);
+       RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Armature_redraw_data");
        RNA_def_property_flag(prop, PROP_LIB_EXCEPTION);
        
                /* layer protection */
@@ -658,8 +659,8 @@ static void rna_def_armature(BlenderRNA *brna)
        RNA_def_property_update(prop, 0, "rna_Armature_redraw_data");
        
        prop= RNA_def_property(srna, "ghost_only_selected", PROP_BOOLEAN, PROP_NONE);
-       RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", ARM_GHOST_ONLYSEL);
-       RNA_def_property_ui_text(prop, "Draw Ghosts on Selected Keyframes Only", "");
+       RNA_def_property_boolean_sdna(prop, NULL, "flag", ARM_GHOST_ONLYSEL);
+       RNA_def_property_ui_text(prop, "Draw Ghosts on Selected Bones Only", "");
        RNA_def_property_update(prop, 0, "rna_Armature_redraw_data");
        
                /* deformflag */
@@ -705,7 +706,6 @@ static void rna_def_armature(BlenderRNA *brna)
        RNA_def_property_update(prop, 0, "rna_Armature_redraw_data");
        
        
-       
        /* Number fields */
                /* ghost/onionskining settings */
        prop= RNA_def_property(srna, "ghost_step", PROP_INT, PROP_NONE);