2.5 - Restored Bone Paths Operators
authorJoshua Leung <aligorith@gmail.com>
Fri, 24 Jul 2009 12:27:42 +0000 (12:27 +0000)
committerJoshua Leung <aligorith@gmail.com>
Fri, 24 Jul 2009 12:27:42 +0000 (12:27 +0000)
* A number-counter cursor is now used while sampling the curve
* Fixed some of the drawing errors with the paths. Unfortunately, when the armature is rotated, the path text is drawn in the wrong places still...

source/blender/editors/armature/armature_intern.h
source/blender/editors/armature/armature_ops.c
source/blender/editors/armature/poseobject.c
source/blender/editors/space_view3d/drawarmature.c
source/blender/editors/space_view3d/view3d_header.c

index 7b3f9a020e3626544d0f5db9f7bf9a28c50f6b82..c37f6803d5811b39da1d392f745d58a89ab94f2b 100644 (file)
@@ -67,6 +67,9 @@ void POSE_OT_scale_clear(struct wmOperatorType *ot);
 void POSE_OT_copy(struct wmOperatorType *ot);
 void POSE_OT_paste(struct wmOperatorType *ot);
 
+void POSE_OT_paths_calculate(struct wmOperatorType *ot);
+void POSE_OT_paths_clear(struct wmOperatorType *ot);
+
 void POSE_OT_select_all_toggle(struct wmOperatorType *ot);
 void POSE_OT_select_inverse(struct wmOperatorType *ot);
 void POSE_OT_select_parent(struct wmOperatorType *ot);
index 5de40ecc54fc3f5d3c4c06931f747e2010e702f0..5495147acb00b8c783bfbc03296a49ea16cab6de 100644 (file)
@@ -150,6 +150,9 @@ void ED_operatortypes_armature(void)
        WM_operatortype_append(POSE_OT_copy);
        WM_operatortype_append(POSE_OT_paste);
        
+       WM_operatortype_append(POSE_OT_paths_calculate);
+       WM_operatortype_append(POSE_OT_paths_clear);
+       
        WM_operatortype_append(POSE_OT_select_all_toggle);
        WM_operatortype_append(POSE_OT_select_inverse);
 
index 9814a056b703d9f0ff787276967a39425bc13bb6..d0bc36b5f09b84f5429da6a9300765694d10f1da 100644 (file)
@@ -21,6 +21,7 @@
  * All rights reserved.
  *
  * Contributor(s): Ton Roosendaal, Blender Foundation '05, full recode.
+ *                              Joshua Leung
  *
  * ***** END GPL LICENSE BLOCK *****
  * support for animation modes - Reevan McKay
@@ -50,6 +51,7 @@
 #include "DNA_view3d_types.h"
 #include "DNA_userdef_types.h"
 
+#include "BKE_animsys.h"
 #include "BKE_action.h"
 #include "BKE_armature.h"
 #include "BKE_blender.h"
@@ -89,7 +91,6 @@
 /* ************* XXX *************** */
 static int movetolayer_short_buts() {return 1;}
 static int pupmenu() {return 0;}
-static void waitcursor() {};
 static void error() {};
 static void BIF_undo_push() {}
 static void countall() {}
@@ -201,10 +202,12 @@ int ED_pose_channel_in_IK_chain(Object *ob, bPoseChannel *pchan)
 
 /* ********************************************** */
 
-/* For the object with pose/action: create path curves for selected bones 
- * This recalculates the WHOLE path within the pchan->pathsf and pchan->pathef range
+/* For the object with pose/action: update paths for those that have got them
+ * This should selectively update paths that exist...
+ *
+ * To be called from various tools that do incremental updates 
  */
-void pose_calculate_path(bContext *C, Scene *scene, Object *ob)
+void ED_pose_recalculate_paths(bContext *C, Scene *scene, Object *ob)
 {
        bArmature *arm;
        bPoseChannel *pchan;
@@ -213,29 +216,28 @@ void pose_calculate_path(bContext *C, Scene *scene, Object *ob)
        int cfra;
        int sfra, efra;
        
-       if (ob==NULL || ob->pose==NULL)
+       /* sanity checks */
+       if ELEM(NULL, ob, ob->pose)
                return;
        arm= ob->data;
        
-       /* version patch for older files here (do_versions patch too complicated) */
-       if ((arm->pathsf == 0) || (arm->pathef == 0)) {
-               arm->pathsf = SFRA;
-               arm->pathef = EFRA;
-       }
-       if (arm->pathsize == 0) {
-               arm->pathsize = 1;
-       }
-       
        /* set frame values */
-       cfra= CFRA;
-       sfra = arm->pathsf;
-       efra = arm->pathef;
-       if (efra <= sfra) {
-               error("Can't calculate paths when pathlen <= 0");
-               return;
+       cfra = CFRA;
+       sfra = efra = cfra; 
+       for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+               if ((pchan->bone) && (arm->layer & pchan->bone->layer)) {
+                       if (pchan->path) {
+                               /* if the pathsf and pathef aren't initialised, abort! */
+                               if (ELEM(0, pchan->pathsf, pchan->pathef))      
+                                       return;
+                               
+                               /* try to increase area to do (only as much as needed) */
+                               sfra= MIN2(sfra, pchan->pathsf);
+                               efra= MAX2(efra, pchan->pathef);
+                       }
+               }
        }
-       
-       waitcursor(1);
+       if (efra <= sfra) return;
        
        /* hack: for unsaved files, set OB_RECALC so that paths can get calculated */
        if ((ob->recalc & OB_RECALC)==0) {
@@ -245,35 +247,30 @@ void pose_calculate_path(bContext *C, Scene *scene, Object *ob)
        else
                ED_anim_object_flush_update(C, ob);
        
-       
-       /* malloc the path blocks */
-       for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
-               if ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED)) {
-                       if (arm->layer & pchan->bone->layer) {
-                               pchan->pathlen= efra-sfra+1;
-                               pchan->pathsf= sfra;
-                               pchan->pathef= efra+1;
-                               if (pchan->path)
-                                       MEM_freeN(pchan->path);
-                               pchan->path= MEM_callocN(3*pchan->pathlen*sizeof(float), "pchan path");
-                       }
-               }
-       }
-       
+       /* calculate path over requested range */
        for (CFRA=sfra; CFRA<=efra; CFRA++) {
                /* do all updates */
                for (base= FIRSTBASE; base; base= base->next) {
                        if (base->object->recalc) {
                                int temp= base->object->recalc;
+                               
+                               if (base->object->adt)
+                                       BKE_animsys_evaluate_animdata(&base->object->id, base->object->adt, (float)CFRA, ADT_RECALC_ALL);
+                               
+                               /* update object */
                                object_handle_update(scene, base->object);
                                base->object->recalc= temp;
                        }
                }
                
                for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
-                       if ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED)) {
-                               if (arm->layer & pchan->bone->layer) {
-                                       if (pchan->path) {
+                       if ((pchan->bone) && (arm->layer & pchan->bone->layer)) {
+                               if (pchan->path) {
+                                       /* only update if:
+                                        *      - in range of this pchan's existing path
+                                        *      - ... insert evil filtering/optimising conditions here...
+                                        */
+                                       if (IN_RANGE(CFRA, pchan->pathsf, pchan->pathef)) {
                                                fp= pchan->path+3*(CFRA-sfra);
                                                
                                                if (arm->pathflag & ARM_PATH_HEADS) { 
@@ -290,16 +287,35 @@ void pose_calculate_path(bContext *C, Scene *scene, Object *ob)
                }
        }
        
-       waitcursor(0);
-       
+       /* reset flags */
        CFRA= cfra;
+       ob->pose->flag &= ~POSE_RECALCPATHS;
+       
+       /* flush one final time - to restore to the original state */
+       for (base= FIRSTBASE; base; base= base->next) {
+               if (base->object->recalc) {
+                       int temp= base->object->recalc;
+                       
+                       if (base->object->adt)
+                               BKE_animsys_evaluate_animdata(&base->object->id, base->object->adt, (float)CFRA, ADT_RECALC_ALL);
+                       
+                       object_handle_update(scene, base->object);
+                       base->object->recalc= temp;
+               }
+       }
 }
 
-/* For the object with pose/action: update paths for those that have got them
- * This should selectively update paths that exist...
+/* --------- */
+
+/* For the object with pose/action: create path curves for selected bones 
+ * This recalculates the WHOLE path within the pchan->pathsf and pchan->pathef range
  */
-void pose_recalculate_paths(bContext *C, Scene *scene, Object *ob)
+static int pose_calculate_paths_exec (bContext *C, wmOperator *op)
 {
+       wmWindow *win= CTX_wm_window(C);
+       ScrArea *sa= CTX_wm_area(C);
+       Scene *scene= CTX_data_scene(C);
+       Object *ob;
        bArmature *arm;
        bPoseChannel *pchan;
        Base *base;
@@ -307,29 +323,35 @@ void pose_recalculate_paths(bContext *C, Scene *scene, Object *ob)
        int cfra;
        int sfra, efra;
        
-       if (ob==NULL || ob->pose==NULL)
-               return;
+       /* since this call may also be used from the buttons window, we need to check for where to get the object */
+       if (sa->spacetype == SPACE_BUTS) 
+               ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
+       else
+               ob= CTX_data_active_object(C);
+               
+       /* only continue if there's an object */
+       if ELEM(NULL, ob, ob->pose)
+               return OPERATOR_CANCELLED;
        arm= ob->data;
        
-       /* set frame values */
-       cfra = CFRA;
-       sfra = efra = cfra; 
-       for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
-               if ((pchan->bone) && (arm->layer & pchan->bone->layer)) {
-                       if (pchan->path) {
-                               /* if the pathsf and pathef aren't initialised, abort! */
-                               if (ELEM(0, pchan->pathsf, pchan->pathef))      
-                                       return;
-                               
-                               /* try to increase area to do (only as much as needed) */
-                               sfra= MIN2(sfra, pchan->pathsf);
-                               efra= MAX2(efra, pchan->pathef);
-                       }
-               }
+       /* version patch for older files here (do_versions patch too complicated) */
+       if ((arm->pathsf == 0) || (arm->pathef == 0)) {
+               arm->pathsf = SFRA;
+               arm->pathef = EFRA;
        }
-       if (efra <= sfra) return;
+       if (arm->pathsize == 0) {
+               arm->pathsize = 1;
+       }
+       
+       /* get frame values to use */
+       cfra= CFRA;
+       sfra = arm->pathsf;
+       efra = arm->pathef;
        
-       waitcursor(1);
+       if (efra <= sfra) {
+               BKE_report(op->reports, RPT_ERROR, "Can't calculate paths when pathlen <= 0");
+               return OPERATOR_CANCELLED;
+       }
        
        /* hack: for unsaved files, set OB_RECALC so that paths can get calculated */
        if ((ob->recalc & OB_RECALC)==0) {
@@ -339,24 +361,42 @@ void pose_recalculate_paths(bContext *C, Scene *scene, Object *ob)
        else
                ED_anim_object_flush_update(C, ob);
        
+       /* alloc the path cache arrays */
+       for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+               if ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED)) {
+                       if (arm->layer & pchan->bone->layer) {
+                               pchan->pathlen= efra-sfra+1;
+                               pchan->pathsf= sfra;
+                               pchan->pathef= efra+1;
+                               if (pchan->path)
+                                       MEM_freeN(pchan->path);
+                               pchan->path= MEM_callocN(3*pchan->pathlen*sizeof(float), "pchan path");
+                       }
+               }
+       }
+       
+       /* step through frame range sampling the values */
        for (CFRA=sfra; CFRA<=efra; CFRA++) {
+               /* for each frame we calculate, update time-cursor... (may be too slow) */
+               WM_timecursor(win, CFRA);
+               
                /* do all updates */
                for (base= FIRSTBASE; base; base= base->next) {
                        if (base->object->recalc) {
                                int temp= base->object->recalc;
+                               
+                               if (base->object->adt)
+                                       BKE_animsys_evaluate_animdata(&base->object->id, base->object->adt, (float)CFRA, ADT_RECALC_ALL);
+                               
                                object_handle_update(scene, base->object);
                                base->object->recalc= temp;
                        }
                }
                
                for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
-                       if ((pchan->bone) && (arm->layer & pchan->bone->layer)) {
-                               if (pchan->path) {
-                                       /* only update if:
-                                        *      - in range of this pchan's existing path
-                                        *      - ... insert evil filtering/optimising conditions here...
-                                        */
-                                       if (IN_RANGE(CFRA, pchan->pathsf, pchan->pathef)) {
+                       if ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED)) {
+                               if (arm->layer & pchan->bone->layer) {
+                                       if (pchan->path) {
                                                fp= pchan->path+3*(CFRA-sfra);
                                                
                                                if (arm->pathflag & ARM_PATH_HEADS) { 
@@ -373,18 +413,55 @@ void pose_recalculate_paths(bContext *C, Scene *scene, Object *ob)
                }
        }
        
-       waitcursor(0);
+       /* restore original cursor */
+       WM_cursor_restore(win);
        
+       /* reset current frame, and clear flags */
        CFRA= cfra;
        ob->pose->flag &= ~POSE_RECALCPATHS;
+       
+       /* flush one final time - to restore to the original state */
+       for (base= FIRSTBASE; base; base= base->next) {
+               if (base->object->recalc) {
+                       int temp= base->object->recalc;
+                       
+                       if (base->object->adt)
+                               BKE_animsys_evaluate_animdata(&base->object->id, base->object->adt, (float)CFRA, ADT_RECALC_ALL);
+                       
+                       object_handle_update(scene, base->object);
+                       base->object->recalc= temp;
+               }
+       }
+       
+       /* notifiers for updates */
+       WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
+       
+       return OPERATOR_FINISHED; 
+}
+
+void POSE_OT_paths_calculate (wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Calculate Bone Paths";
+       ot->idname= "POSE_OT_paths_calculate";
+       ot->description= "Calculate paths for the selected bones.";
+       
+       /* api callbacks */
+       ot->exec= pose_calculate_paths_exec;
+       ot->poll= ED_operator_posemode;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
+/* --------- */
+
 /* for the object with pose/action: clear path curves for selected bones only */
-void pose_clear_paths(Object *ob)
+void ED_pose_clear_paths(Object *ob)
 {
        bPoseChannel *pchan;
        
-       if (ob==NULL || ob->pose==NULL)
+       if ELEM(NULL, ob, ob->pose)
                return;
        
        /* free the path blocks */
@@ -396,9 +473,49 @@ void pose_clear_paths(Object *ob)
                        }
                }
        }
+}
+
+/* operator callback for this */
+static int pose_clear_paths_exec (bContext *C, wmOperator *op)
+{
+       ScrArea *sa= CTX_wm_area(C);
+       Object *ob;
        
+       /* since this call may also be used from the buttons window, we need to check for where to get the object */
+       if (sa->spacetype == SPACE_BUTS) 
+               ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
+       else
+               ob= CTX_data_active_object(C);
+               
+       /* only continue if there's an object */
+       if ELEM(NULL, ob, ob->pose)
+               return OPERATOR_CANCELLED;
+       
+       /* for now, just call the API function for this (which is shared with backend functions) */
+       ED_pose_clear_paths(ob);
+       
+       /* notifiers for updates */
+       WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
+       
+       return OPERATOR_FINISHED; 
+}
+
+void POSE_OT_paths_clear (wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Clear Bone Paths";
+       ot->idname= "POSE_OT_paths_clear";
+       ot->description= "Clear path caches for selected bones.";
+       
+       /* api callbacks */
+       ot->exec= pose_clear_paths_exec;
+       ot->poll= ED_operator_posemode;
+       
+       /* flags */
+       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
+/* ******************* Select Constraint Target Operator ************* */
 
 // XXX this function is to be removed when the other stuff is recoded
 void pose_select_constraint_target(Scene *scene)
index b698b404825d733d2dbb35f6849c7a4a1bbffdd6..5a9790390b78b1bf3c3b96918d4b291e1b2279d4 100644 (file)
@@ -2154,12 +2154,12 @@ static void draw_pose_paths(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec
                                                
                                                /* only draw framenum if several consecutive highlighted points don't occur on same point */
                                                if (a == 0) {
-                                                       sprintf(str, "  %d\n", (a+sfra));
+                                                       sprintf(str, "%d", (a+sfra));
                                                        view3d_object_text_draw_add(fp[0], fp[1], fp[2], str, 0);
                                                }
                                                else if ((a > stepsize) && (a < len-stepsize)) { 
                                                        if ((VecEqual(fp, fp-(stepsize*3))==0) || (VecEqual(fp, fp+(stepsize*3))==0)) {
-                                                               sprintf(str, "  %d\n", (a+sfra));
+                                                               sprintf(str, "%d", (a+sfra));
                                                                view3d_object_text_draw_add(fp[0], fp[1], fp[2], str, 0);
                                                        }
                                                }
@@ -2201,7 +2201,7 @@ static void draw_pose_paths(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec
                                                                if (ak->cfra == (a+sfra)) {
                                                                        char str[32];
                                                                        
-                                                                       sprintf(str, "  %d\n", (a+sfra));
+                                                                       sprintf(str, "%d", (a+sfra));
                                                                        view3d_object_text_draw_add(fp[0], fp[1], fp[2], str, 0);
                                                                }
                                                        }
index f2a386c81baccad08106bf79fd9c0f9d4c38d9a9..b5c1e8bb9f6a593ff79a834b1bb5bdb4a144250e 100644 (file)
@@ -3051,37 +3051,11 @@ static void view3d_pose_armature_groupmenu(bContext *C, uiLayout *layout, void *
        uiItemO(layout, "Remove Active Group", 0, "POSE_OT_group_remove");
 }
 
-#if 0
-static void do_view3d_pose_armature_motionpathsmenu(bContext *C, void *arg, int event)
-{
-       switch(event) {
-                
-       case 1:
-               pose_calculate_path(OBACT);
-               break;
-       case 2:
-               pose_clear_paths(OBACT);
-               break;
-       }
-}
-
-
-static uiBlock *view3d_pose_armature_motionpathsmenu(bContext *C, ARegion *ar, void *arg_unused)
+static void view3d_pose_armature_motionpathsmenu(bContext *C, uiLayout *layout, void *arg_unused)
 {
-       uiBlock *block;
-       short yco = 20, menuwidth = 120;
-
-       block= uiBeginBlock(C, ar, "view3d_pose_armature_motionpathsmenu", UI_EMBOSSP);
-       uiBlockSetButmFunc(block, do_view3d_pose_armature_motionpathsmenu, NULL);
-       
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Calculate Paths|W",                      0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
-       uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear All Paths|W",                      0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
-       
-       uiBlockSetDirection(block, UI_RIGHT);
-       uiTextBoundsBlock(block, 60);
-       return block;
+       uiItemO(layout, NULL, 0, "POSE_OT_paths_calculate");
+       uiItemO(layout, NULL, 0, "POSE_OT_paths_clear");
 }
-#endif
 
 static void view3d_pose_armature_poselibmenu(bContext *C, uiLayout *layout, void *arg_unused)
 {
@@ -3184,7 +3158,7 @@ static void view3d_pose_armaturemenu(bContext *C, uiLayout *layout, void *arg_un
        uiItemS(layout);
 
        uiItemMenuF(layout, "Pose Library", 0, view3d_pose_armature_poselibmenu);
-       //uiItemMenuF(layout, "Motion Paths", 0, view3d_pose_armature_motionpathsmenu);
+       uiItemMenuF(layout, "Motion Paths", 0, view3d_pose_armature_motionpathsmenu);
        uiItemMenuF(layout, "Bone Groups", 0, view3d_pose_armature_groupmenu);
        
        uiItemS(layout);