diff options
author | Joshua Leung <aligorith@gmail.com> | 2011-02-16 09:18:20 +0300 |
---|---|---|
committer | Joshua Leung <aligorith@gmail.com> | 2011-02-16 09:18:20 +0300 |
commit | 437bdbc96cd80dadb8517ae94dd5e9f5e3e4bf70 (patch) | |
tree | 0e7ceeb988d6f4311900ff3427fdcac4fa642bb2 /source | |
parent | 7748860aeb6dc653f529fbe1c030df3674c9fac4 (diff) |
PoseLib Bugfixes, Cleanups, and Missing Operators
* All the various index-related issues should finally be sorted now.
It seems you cannot just partially implement some of these active
index getter/setters...
* Standardised the call used by PoseLib operators to get the Object
from which they get the active PoseLib data from
* PoseLib operators which require some existing data to work now use a
poll() which checks for this
* Added back the operator used to make standard actions into ones
usable by PoseLib
* Added a dummy operator for the apply active pose button which really
just calls the same backend functions as "Browse Interactive", but
which has a nicer frontend (naming + description) for the purpose of
being used in this way
* Also, removed some useless code from here
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/editors/armature/armature_intern.h | 1 | ||||
-rw-r--r-- | source/blender/editors/armature/armature_ops.c | 1 | ||||
-rw-r--r-- | source/blender/editors/armature/poselib.c | 287 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_action.c | 38 |
4 files changed, 177 insertions, 150 deletions
diff --git a/source/blender/editors/armature/armature_intern.h b/source/blender/editors/armature/armature_intern.h index 580579990bd..acddb29138b 100644 --- a/source/blender/editors/armature/armature_intern.h +++ b/source/blender/editors/armature/armature_intern.h @@ -179,6 +179,7 @@ void POSELIB_OT_pose_remove(struct wmOperatorType *ot); void POSELIB_OT_pose_rename(struct wmOperatorType *ot); void POSELIB_OT_browse_interactive(struct wmOperatorType *ot); +void POSELIB_OT_apply_pose(struct wmOperatorType *ot); /* ******************************************************* */ /* Pose Sliding Tools */ diff --git a/source/blender/editors/armature/armature_ops.c b/source/blender/editors/armature/armature_ops.c index 37978244b15..494f7a0041d 100644 --- a/source/blender/editors/armature/armature_ops.c +++ b/source/blender/editors/armature/armature_ops.c @@ -142,6 +142,7 @@ void ED_operatortypes_armature(void) /* POSELIB */ WM_operatortype_append(POSELIB_OT_browse_interactive); + WM_operatortype_append(POSELIB_OT_apply_pose); WM_operatortype_append(POSELIB_OT_pose_add); WM_operatortype_append(POSELIB_OT_pose_remove); diff --git a/source/blender/editors/armature/poselib.c b/source/blender/editors/armature/poselib.c index b160ad9b661..7e27cfbe0e1 100644 --- a/source/blender/editors/armature/poselib.c +++ b/source/blender/editors/armature/poselib.c @@ -97,36 +97,6 @@ static void action_set_activemarker(void *UNUSED(a), void *UNUSED(b), void *UNUS */ /* ************************************************************* */ -/* gets list of poses in poselib as a string usable for pupmenu() */ -static char *poselib_build_poses_menu (bAction *act, char title[]) -{ - DynStr *pupds= BLI_dynstr_new(); - TimeMarker *marker; - char *str; - char buf[64]; - int i; - - /* add title first */ - sprintf(buf, "%s%%t|", title); - BLI_dynstr_append(pupds, buf); - - /* loop through markers, adding them */ - for (marker=act->markers.first, i=1; marker; marker=marker->next, i++) { - BLI_dynstr_append(pupds, marker->name); - - sprintf(buf, "%%x%d", i); - BLI_dynstr_append(pupds, buf); - - if (marker->next) - BLI_dynstr_append(pupds, "|"); - } - - /* convert to normal MEM_malloc'd string */ - str= BLI_dynstr_get_cstring(pupds); - BLI_dynstr_free(pupds); - - return str; -} /* gets the first available frame in poselib to store a pose on * - frames start from 1, and a pose should occur on every frame... 0 is error! @@ -170,7 +140,25 @@ static TimeMarker *poselib_get_active_pose (bAction *act) return NULL; } -/* ************************************************************* */ +/* Get object that Pose Lib should be found on */ +static Object *get_poselib_object (bContext *C) +{ + ScrArea *sa = CTX_wm_area(C); + + if (sa->spacetype == SPACE_BUTS) + return CTX_data_pointer_get_type(C, "object", &RNA_Object).data; + else + return ED_object_pose_armature(CTX_data_active_object(C)); +} + +/* Poll callback for operators that require existing PoseLib data (with poses) to work */ +static int has_poselib_pose_data_poll (bContext *C) +{ + Object *ob = get_poselib_object(C); + return (ob && ob->poselib); +} + +/* ----------------------------------- */ /* Initialise a new poselib (whether it is needed or not) */ static bAction *poselib_init_new (Object *ob) @@ -198,83 +186,13 @@ static bAction *poselib_validate (Object *ob) return ob->poselib; } - -/* This tool automagically generates/validates poselib data so that it corresponds to the data - * in the action. This is for use in making existing actions usable as poselibs. - */ -// TODO: operatorfy me! -static void poselib_validate_act (bAction *act) -{ - DLRBT_Tree keys = {NULL, NULL}; - ActKeyColumn *ak; - TimeMarker *marker, *markern; - - /* validate action and poselib */ - if (act == NULL) { - //error("No Action to validate"); - return; - } - - /* determine which frames have keys */ - BLI_dlrbTree_init(&keys); - action_to_keylist(NULL, act, &keys, NULL); - BLI_dlrbTree_linkedlist_sync(&keys); - - /* for each key, make sure there is a correspnding pose */ - for (ak= keys.first; ak; ak= ak->next) { - /* check if any pose matches this */ - // TODO: don't go looking through the list like this every time... - for (marker= act->markers.first; marker; marker= marker->next) { - if (IS_EQ(marker->frame, ak->cfra)) { - marker->flag = -1; - break; - } - } - - /* add new if none found */ - if (marker == NULL) { - /* add pose to poselib */ - marker= MEM_callocN(sizeof(TimeMarker), "ActionMarker"); - - BLI_strncpy(marker->name, "Pose", sizeof(marker->name)); - - marker->frame= (int)ak->cfra; - marker->flag= -1; - - BLI_addtail(&act->markers, marker); - } - } - - /* remove all untagged poses (unused), and remove all tags */ - for (marker= act->markers.first; marker; marker= markern) { - markern= marker->next; - - if (marker->flag != -1) - BLI_freelinkN(&act->markers, marker); - else - marker->flag = 0; - } - - /* free temp memory */ - BLI_freelistN((ListBase *)&keys); - - //BIF_undo_push("PoseLib Validate Action"); -} - /* ************************************************************* */ /* Pose Lib UI Operators */ static int poselib_new_exec (bContext *C, wmOperator *op) { - ScrArea *sa = CTX_wm_area(C); - Object *ob; + Object *ob = get_poselib_object(C); - /* get object to add Pose Lib to */ - if (sa->spacetype == SPACE_BUTS) - ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; - else - ob= ED_object_pose_armature(CTX_data_active_object(C)); - /* sanity checks */ if (ob == NULL) return OPERATOR_CANCELLED; @@ -305,33 +223,10 @@ void POSELIB_OT_new (wmOperatorType *ot) /* ------------------------------------------------ */ -static int poselib_unlink_poll (bContext *C) -{ - /* object must exist, and so must a poselib */ - ScrArea *sa = CTX_wm_area(C); - Object *ob; - - /* get object to add Pose Lib to */ - if (sa->spacetype == SPACE_BUTS) - ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; - else - ob= ED_object_pose_armature(CTX_data_active_object(C)); - - /* sanity checks */ - return (ob && ob->poselib); -} - static int poselib_unlink_exec (bContext *C, wmOperator *op) { - ScrArea *sa = CTX_wm_area(C); - Object *ob; + Object *ob = get_poselib_object(C); - /* get object to add Pose Lib to */ - if (sa->spacetype == SPACE_BUTS) - ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; - else - ob= ED_object_pose_armature(CTX_data_active_object(C)); - /* sanity checks */ if (ELEM(NULL, ob, ob->poselib)) return OPERATOR_CANCELLED; @@ -355,7 +250,7 @@ void POSELIB_OT_unlink (wmOperatorType *ot) /* callbacks */ ot->exec = poselib_unlink_exec; - ot->poll= poselib_unlink_poll; + ot->poll= has_poselib_pose_data_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -364,9 +259,89 @@ void POSELIB_OT_unlink (wmOperatorType *ot) /* ************************************************************* */ /* Pose Editing Operators */ +/* This tool automagically generates/validates poselib data so that it corresponds to the data + * in the action. This is for use in making existing actions usable as poselibs. + */ +static int poselib_sanitise_exec (bContext *C, wmOperator *op) +{ + Object *ob = get_poselib_object(C); + bAction *act = (ob)? ob->poselib : NULL; + DLRBT_Tree keys; + ActKeyColumn *ak; + TimeMarker *marker, *markern; + + /* validate action */ + if (act == NULL) { + BKE_report(op->reports, RPT_WARNING, "No Action to validate"); + return OPERATOR_CANCELLED; + } + + /* determine which frames have keys */ + BLI_dlrbTree_init(&keys); + action_to_keylist(NULL, act, &keys, NULL); + BLI_dlrbTree_linkedlist_sync(&keys); + + /* for each key, make sure there is a corresponding pose */ + for (ak= keys.first; ak; ak= ak->next) { + /* check if any pose matches this */ + // TODO: don't go looking through the list like this every time... + for (marker= act->markers.first; marker; marker= marker->next) { + if (IS_EQ(marker->frame, ak->cfra)) { + marker->flag = -1; + break; + } + } + + /* add new if none found */ + if (marker == NULL) { + /* add pose to poselib */ + marker= MEM_callocN(sizeof(TimeMarker), "ActionMarker"); + + BLI_strncpy(marker->name, "Pose", sizeof(marker->name)); + + marker->frame= (int)ak->cfra; + marker->flag= -1; + + BLI_addtail(&act->markers, marker); + } + } + + /* remove all untagged poses (unused), and remove all tags */ + for (marker= act->markers.first; marker; marker= markern) { + markern= marker->next; + + if (marker->flag != -1) + BLI_freelinkN(&act->markers, marker); + else + marker->flag = 0; + } + + /* free temp memory */ + BLI_dlrbTree_free(&keys); + + return OPERATOR_FINISHED; +} + +void POSELIB_OT_action_sanitise (wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Sanitise Pose Library Action"; + ot->idname = "POSELIB_OT_action_sanitise"; + ot->description = "Make action suitable for use as a Pose Library"; + + /* callbacks */ + ot->exec = poselib_sanitise_exec; + ot->poll = has_poselib_pose_data_poll; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +/* ------------------------------------------ */ + static void poselib_add_menu_invoke__replacemenu (bContext *C, uiLayout *layout, void *UNUSED(arg)) { - Object *ob= ED_object_pose_armature(CTX_data_active_object(C)); + Object *ob= get_poselib_object(C); bAction *act= ob->poselib; TimeMarker *marker; @@ -389,14 +364,13 @@ static void poselib_add_menu_invoke__replacemenu (bContext *C, uiLayout *layout, static int poselib_add_menu_invoke (bContext *C, wmOperator *op, wmEvent *UNUSED(evt)) { Scene *scene= CTX_data_scene(C); - Object *ob= ED_object_pose_armature(CTX_data_active_object(C)); - bArmature *arm= (ob) ? ob->data : NULL; + Object *ob= get_poselib_object(C); bPose *pose= (ob) ? ob->pose : NULL; uiPopupMenu *pup; uiLayout *layout; /* sanity check */ - if (ELEM3(NULL, ob, arm, pose)) + if (ELEM(NULL, ob, pose)) return OPERATOR_CANCELLED; /* start building */ @@ -425,9 +399,8 @@ static int poselib_add_menu_invoke (bContext *C, wmOperator *op, wmEvent *UNUSED static int poselib_add_exec (bContext *C, wmOperator *op) { - Object *ob= ED_object_pose_armature(CTX_data_active_object(C)); + Object *ob= get_poselib_object(C); bAction *act = poselib_validate(ob); - bArmature *arm= (ob) ? ob->data : NULL; bPose *pose= (ob) ? ob->pose : NULL; TimeMarker *marker; KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "Whole Character"); /* this includes custom props :)*/ @@ -435,7 +408,7 @@ static int poselib_add_exec (bContext *C, wmOperator *op) char name[64]; /* sanity check (invoke should have checked this anyway) */ - if (ELEM3(NULL, ob, arm, pose)) + if (ELEM(NULL, ob, pose)) return OPERATOR_CANCELLED; /* get name to give to pose */ @@ -469,7 +442,7 @@ static int poselib_add_exec (bContext *C, wmOperator *op) ANIM_apply_keyingset(C, NULL, act, ks, MODIFYKEY_MODE_INSERT, (float)frame); /* store new 'active' pose number */ - act->active_marker= BLI_countlist(&act->markers) - 1; + act->active_marker= BLI_countlist(&act->markers); /* done */ return OPERATOR_FINISHED; @@ -499,14 +472,14 @@ void POSELIB_OT_pose_add (wmOperatorType *ot) static EnumPropertyItem *poselib_stored_pose_itemf(bContext *C, PointerRNA *UNUSED(ptr), int *free) { - Object *ob= ED_object_pose_armature(CTX_data_active_object(C)); + Object *ob= get_poselib_object(C); bAction *act= (ob) ? ob->poselib : NULL; TimeMarker *marker; EnumPropertyItem *item= NULL, item_tmp= {0}; int totitem= 0; int i= 0; - if (C==NULL) { + if (C == NULL) { return DummyRNA_DEFAULT_items; } @@ -529,7 +502,7 @@ static EnumPropertyItem *poselib_stored_pose_itemf(bContext *C, PointerRNA *UNUS static int poselib_remove_exec (bContext *C, wmOperator *op) { - Object *ob= ED_object_pose_armature(CTX_data_active_object(C)); + Object *ob= get_poselib_object(C); bAction *act= (ob) ? ob->poselib : NULL; TimeMarker *marker; FCurve *fcu; @@ -585,20 +558,20 @@ void POSELIB_OT_pose_remove (wmOperatorType *ot) /* api callbacks */ ot->invoke= WM_menu_invoke; ot->exec= poselib_remove_exec; - ot->poll= ED_operator_posemode; + ot->poll= has_poselib_pose_data_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; /* properties */ prop= RNA_def_enum(ot->srna, "pose", DummyRNA_DEFAULT_items, 0, "Pose", "The pose to remove"); - RNA_def_enum_funcs(prop, poselib_stored_pose_itemf); + RNA_def_enum_funcs(prop, poselib_stored_pose_itemf); ot->prop= prop; } static int poselib_rename_invoke (bContext *C, wmOperator *op, wmEvent *evt) { - Object *ob= ED_object_pose_armature(CTX_data_active_object(C)); + Object *ob= get_poselib_object(C); bAction *act= (ob) ? ob->poselib : NULL; TimeMarker *marker; @@ -665,20 +638,21 @@ void POSELIB_OT_pose_rename (wmOperatorType *ot) /* identifiers */ ot->name= "PoseLib Rename Pose"; ot->idname= "POSELIB_OT_pose_rename"; - ot->description= "Rename nth pose from the active Pose Library"; + ot->description= "Rename specified pose from the active Pose Library"; /* api callbacks */ ot->invoke= poselib_rename_invoke; ot->exec= poselib_rename_exec; - ot->poll= ED_operator_posemode; + ot->poll= has_poselib_pose_data_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; /* properties */ + /* NOTE: name not pose is the operator's "main" property, so that it will get activated in the popup for easy renaming */ + ot->prop= RNA_def_string(ot->srna, "name", "RenamedPose", 64, "New Pose Name", "New name for pose"); prop= RNA_def_enum(ot->srna, "pose", prop_poses_dummy_types, 0, "Pose", "The pose to rename"); RNA_def_enum_funcs(prop, poselib_stored_pose_itemf); - RNA_def_string(ot->srna, "name", "RenamedPose", 64, "New Pose Name", "New name for pose"); } /* ************************************************************* */ @@ -1361,7 +1335,7 @@ static int poselib_preview_handle_event (bContext *UNUSED(C), wmOperator *op, wm static void poselib_preview_init_data (bContext *C, wmOperator *op) { tPoseLib_PreviewData *pld; - Object *ob= ED_object_pose_armature(CTX_data_active_object(C)); + Object *ob= get_poselib_object(C); int pose_index = RNA_int_get(op->ptr, "pose_index"); /* set up preview state info */ @@ -1593,12 +1567,12 @@ void POSELIB_OT_browse_interactive (wmOperatorType *ot) ot->idname= "POSELIB_OT_browse_interactive"; ot->description= "Interactively browse poses in 3D-View"; - /* api callbacks */ + /* callbacks */ ot->invoke= poselib_preview_invoke; ot->modal= poselib_preview_modal; ot->cancel= poselib_preview_cancel; ot->exec= poselib_preview_exec; - ot->poll= ED_operator_posemode; + ot->poll= has_poselib_pose_data_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING; @@ -1611,3 +1585,22 @@ void POSELIB_OT_browse_interactive (wmOperatorType *ot) /* not used yet */ /* RNA_def_float_factor(ot->srna, "blend_factor", 1.0f, 0.0f, 1.0f, "Blend Factor", "Amount that the pose is applied on top of the existing poses", 0.0f, 1.0f); */ } + +void POSELIB_OT_apply_pose (wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Apply Pose Library Pose"; + ot->idname = "POSELIB_OT_apply_pose"; + ot->description = "Apply specified Pose Library pose to the rig"; + + /* callbacks */ + ot->exec= poselib_preview_exec; + ot->poll= has_poselib_pose_data_poll; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties */ + // TODO: make the pose_index into a proper enum instead of a cryptic int... + ot->prop= RNA_def_int(ot->srna, "pose_index", -1, -2, INT_MAX, "Pose", "Index of the pose to apply (-2 for no change to pose, -1 for poselib active pose)", 0, INT_MAX); +} diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c index 6cfd122d08e..954fe5f851a 100644 --- a/source/blender/makesrna/intern/rna_action.c +++ b/source/blender/makesrna/intern/rna_action.c @@ -141,7 +141,7 @@ static TimeMarker *rna_Action_pose_markers_new(bAction *act, ReportList *reports static void rna_Action_pose_markers_remove(bAction *act, ReportList *reports, TimeMarker *marker) { if (!BLI_remlink_safe(&act->markers, marker)) { - BKE_reportf(reports, RPT_ERROR, "TimelineMarker '%s' not found in action '%s'", marker->name, act->id.name+2); + BKE_reportf(reports, RPT_ERROR, "TimelineMarker '%s' not found in Action '%s'", marker->name, act->id.name+2); return; } @@ -149,15 +149,41 @@ static void rna_Action_pose_markers_remove(bAction *act, ReportList *reports, Ti MEM_freeN(marker); } +static PointerRNA rna_Action_active_pose_marker_get(PointerRNA *ptr) +{ + bAction *act= (bAction*)ptr->data; + return rna_pointer_inherit_refine(ptr, &RNA_TimelineMarker, BLI_findlink(&act->markers, act->active_marker-1)); +} + +static void rna_Action_active_pose_marker_set(PointerRNA *ptr, PointerRNA value) +{ + bAction *act= (bAction*)ptr->data; + act->active_marker= BLI_findindex(&act->markers, value.data) + 1; +} + +static int rna_Action_active_pose_marker_index_get(PointerRNA *ptr) +{ + bAction *act= (bAction*)ptr->data; + return MAX2(act->active_marker-1, 0); +} + +static void rna_Action_active_pose_marker_index_set(PointerRNA *ptr, int value) +{ + bAction *act= (bAction*)ptr->data; + act->active_marker= value+1; +} + static void rna_Action_active_pose_marker_index_range(PointerRNA *ptr, int *min, int *max) { - bAction *act= (bAction *)ptr->data; + bAction *act= (bAction*)ptr->data; *min= 0; *max= BLI_countlist(&act->markers)-1; *max= MAX2(0, *max); } + + static void rna_Action_frame_range_get(PointerRNA *ptr,float *values) { calc_action_range(ptr->id.data, values, values+1, 1); @@ -456,9 +482,15 @@ static void rna_def_action_pose_markers(BlenderRNA *brna, PropertyRNA *cprop) parm= RNA_def_pointer(func, "marker", "TimelineMarker", "", "Timeline marker to remove."); RNA_def_property_flag(parm, PROP_REQUIRED|PROP_NEVER_NULL); + prop= RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "TimelineMarker"); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_pointer_funcs(prop, "rna_Action_active_pose_marker_get", "rna_Action_active_pose_marker_set", NULL, NULL); + RNA_def_property_ui_text(prop, "Active Pose Marker", "Active pose marker for this Action"); + prop= RNA_def_property(srna, "active_index", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "active_marker"); - RNA_def_property_int_funcs(prop, NULL, NULL, "rna_Action_active_pose_marker_index_range"); + RNA_def_property_int_funcs(prop, "rna_Action_active_pose_marker_index_get", "rna_Action_active_pose_marker_index_set", "rna_Action_active_pose_marker_index_range"); RNA_def_property_ui_text(prop, "Active Pose Marker Index", "Index of active pose marker"); } |