From 1844fc7057fcc342c4bc9f4e1385bc97a2bd33e6 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 24 Jul 2009 12:27:42 +0000 Subject: 2.5 - Restored Bone Paths Operators * 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 | 3 + source/blender/editors/armature/armature_ops.c | 3 + source/blender/editors/armature/poseobject.c | 265 +++++++++++++++------ source/blender/editors/space_view3d/drawarmature.c | 6 +- .../blender/editors/space_view3d/view3d_header.c | 34 +-- 5 files changed, 204 insertions(+), 107 deletions(-) (limited to 'source') diff --git a/source/blender/editors/armature/armature_intern.h b/source/blender/editors/armature/armature_intern.h index 7b3f9a020e3..c37f6803d58 100644 --- a/source/blender/editors/armature/armature_intern.h +++ b/source/blender/editors/armature/armature_intern.h @@ -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); diff --git a/source/blender/editors/armature/armature_ops.c b/source/blender/editors/armature/armature_ops.c index 5de40ecc54f..5495147acb0 100644 --- a/source/blender/editors/armature/armature_ops.c +++ b/source/blender/editors/armature/armature_ops.c @@ -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); diff --git a/source/blender/editors/armature/poseobject.c b/source/blender/editors/armature/poseobject.c index 9814a056b70..d0bc36b5f09 100644 --- a/source/blender/editors/armature/poseobject.c +++ b/source/blender/editors/armature/poseobject.c @@ -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) diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c index b698b404825..5a9790390b7 100644 --- a/source/blender/editors/space_view3d/drawarmature.c +++ b/source/blender/editors/space_view3d/drawarmature.c @@ -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); } } diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index f2a386c81ba..b5c1e8bb9f6 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -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); -- cgit v1.2.3