From 08eac0c3675ff4baff4ad3d0aae4d5ab10a8a133 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 9 Jul 2014 10:27:31 +0200 Subject: [PATCH] Add bone_groups.new() and bone_groups.remove() methods to RNA. To do so, matching BKE 'API' was also refactored a bit: * Get Pose data instead of Object, as parameter; * Removed some sanity checks not needed at such a low level (callers are supposed to do that); * You can now remove an arbitrary bone group, not only the active one. Based on patch by pkrime (Paolo Acampora), with own edits. Reviewers: #python, pkrime, aligorith Reviewed By: aligorith Differential Revision: https://developer.blender.org/D522 --- source/blender/blenkernel/BKE_action.h | 8 ++- source/blender/blenkernel/intern/action.c | 76 +++++++++++--------- source/blender/editors/armature/pose_group.c | 14 ++-- source/blender/makesrna/intern/rna_pose.c | 45 +++++++++++- 4 files changed, 99 insertions(+), 44 deletions(-) diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index 517c0f7d58b..57ba6fd55ca 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -180,10 +180,12 @@ void framechange_poses_clear_unkeyed(void); /* Bone Groups API --------------------- */ /* Adds a new bone-group */ -void BKE_pose_add_group(struct Object *ob); +struct bActionGroup *BKE_pose_add_group(struct bPose *pose, const char *name); -/* Remove the active bone-group */ -void BKE_pose_remove_group(struct Object *ob); +/* Remove a bone-group */ +void BKE_pose_remove_group(struct bPose *pose, struct bActionGroup *grp, const int index); +/* Remove the matching bone-group from its index */ +void BKE_pose_remove_group_index(struct bPose *pose, const int index); /* Assorted Evaluation ----------------- */ diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 3219219bee5..8f1382dacc3 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -952,52 +952,52 @@ void framechange_poses_clear_unkeyed(void) /* ************************** Bone Groups ************************** */ -/* Adds a new bone-group */ -void BKE_pose_add_group(Object *ob) +/* Adds a new bone-group (name may be NULL) */ +bActionGroup *BKE_pose_add_group(bPose *pose, const char *name) { - bPose *pose = (ob) ? ob->pose : NULL; bActionGroup *grp; - if (ELEM(NULL, ob, ob->pose)) - return; + if (!name) { + name = DATA_("Group"); + } grp = MEM_callocN(sizeof(bActionGroup), "PoseGroup"); - BLI_strncpy(grp->name, DATA_("Group"), sizeof(grp->name)); + BLI_strncpy(grp->name, name, sizeof(grp->name)); BLI_addtail(&pose->agroups, grp); - BLI_uniquename(&pose->agroups, grp, DATA_("Group"), '.', offsetof(bActionGroup, name), sizeof(grp->name)); + BLI_uniquename(&pose->agroups, grp, name, '.', offsetof(bActionGroup, name), sizeof(grp->name)); pose->active_group = BLI_countlist(&pose->agroups); + + return grp; } -/* Remove the active bone-group */ -void BKE_pose_remove_group(Object *ob) +/* Remove the given bone-group (expects 'virtual' index (+1 one, used by active_group etc.)) + * index might be invalid ( < 1), in which case it will be find from grp. */ +void BKE_pose_remove_group(bPose *pose, bActionGroup *grp, const int index) { - bPose *pose = (ob) ? ob->pose : NULL; - bActionGroup *grp = NULL; bPoseChannel *pchan; + int idx = index; - /* sanity checks */ - if (ELEM(NULL, ob, pose)) - return; - if (pose->active_group <= 0) - return; + if (idx < 1) { + idx = BLI_findindex(&pose->agroups, grp) + 1; + } - /* get group to remove */ - grp = BLI_findlink(&pose->agroups, pose->active_group - 1); - if (grp) { - /* adjust group references (the trouble of using indices!): - * - firstly, make sure nothing references it - * - also, make sure that those after this item get corrected - */ - for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) { - if (pchan->agrp_index == pose->active_group) - pchan->agrp_index = 0; - else if (pchan->agrp_index > pose->active_group) - pchan->agrp_index--; - } - - /* now, remove it from the pose */ - BLI_freelinkN(&pose->agroups, grp); + BLI_assert(idx > 0); + + /* adjust group references (the trouble of using indices!): + * - firstly, make sure nothing references it + * - also, make sure that those after this item get corrected + */ + for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) { + if (pchan->agrp_index == idx) + pchan->agrp_index = 0; + else if (pchan->agrp_index > idx) + pchan->agrp_index--; + } + + /* now, remove it from the pose */ + BLI_freelinkN(&pose->agroups, grp); + if (pose->active_group >= idx) { pose->active_group--; if (pose->active_group < 0 || BLI_listbase_is_empty(&pose->agroups)) { pose->active_group = 0; @@ -1005,6 +1005,18 @@ void BKE_pose_remove_group(Object *ob) } } +/* Remove the indexed bone-group (expects 'virtual' index (+1 one, used by active_group etc.)) */ +void BKE_pose_remove_group_index(bPose *pose, const int index) +{ + bActionGroup *grp = NULL; + + /* get group to remove */ + grp = BLI_findlink(&pose->agroups, index - 1); + if (grp) { + BKE_pose_remove_group(pose, grp, index); + } +} + /* ************** F-Curve Utilities for Actions ****************** */ /* Check if the given action has any keyframes */ diff --git a/source/blender/editors/armature/pose_group.c b/source/blender/editors/armature/pose_group.c index 376c1bc0838..50d9d300d15 100644 --- a/source/blender/editors/armature/pose_group.c +++ b/source/blender/editors/armature/pose_group.c @@ -62,12 +62,12 @@ static int pose_group_add_exec(bContext *C, wmOperator *UNUSED(op)) { Object *ob = ED_pose_object_from_context(C); - /* only continue if there's an object */ - if (ob == NULL) + /* only continue if there's an object and pose */ + if (ELEM(NULL, ob, ob->pose)) return OPERATOR_CANCELLED; /* for now, just call the API function for this */ - BKE_pose_add_group(ob); + BKE_pose_add_group(ob->pose, NULL); /* notifiers for updates */ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob); @@ -95,12 +95,12 @@ static int pose_group_remove_exec(bContext *C, wmOperator *UNUSED(op)) { Object *ob = ED_pose_object_from_context(C); - /* only continue if there's an object */ - if (ob == NULL) + /* only continue if there's an object and pose */ + if (ELEM(NULL, ob, ob->pose)) return OPERATOR_CANCELLED; /* for now, just call the API function for this */ - BKE_pose_remove_group(ob); + BKE_pose_remove_group_index(ob->pose, ob->pose->active_group); /* notifiers for updates */ WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob); @@ -189,7 +189,7 @@ static int pose_group_assign_exec(bContext *C, wmOperator *op) */ pose->active_group = RNA_int_get(op->ptr, "type"); if (pose->active_group == 0) - BKE_pose_add_group(ob); + BKE_pose_add_group(ob->pose, NULL); /* add selected bones to group then */ CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones) diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c index 18e4ac6b004..9f05d61eeff 100644 --- a/source/blender/makesrna/intern/rna_pose.c +++ b/source/blender/makesrna/intern/rna_pose.c @@ -140,7 +140,32 @@ static char *rna_PoseBone_path(PointerRNA *ptr) return BLI_sprintfN("pose.bones[\"%s\"]", name_esc); } +/* Bone groups only. */ + +static bActionGroup *rna_bone_group_new(ID *id, bPose *pose, const char *name) +{ + bActionGroup *grp = BKE_pose_add_group(pose, name); + WM_main_add_notifier(NC_OBJECT | ND_POSE | NA_ADDED, id); + return grp; +} + +static void rna_bone_group_remove(ID *id, bPose *pose, ReportList *reports, PointerRNA *grp_ptr) +{ + bActionGroup *grp = grp_ptr->data; + const int grp_idx = BLI_findindex(&pose->agroups, grp); + + if (grp_idx == -1) { + BKE_reportf(reports, RPT_ERROR, "Bone group '%s' not found in this object", grp->name); + return; + } + + BKE_pose_remove_group(pose, grp, grp_idx + 1); + WM_main_add_notifier(NC_OBJECT | ND_POSE | NA_REMOVED, id); +} + + /* shared for actions groups and bone groups */ + void rna_ActionGroup_colorset_set(PointerRNA *ptr, int value) { bActionGroup *grp = ptr->data; @@ -1241,14 +1266,30 @@ static void rna_def_bone_groups(BlenderRNA *brna, PropertyRNA *cprop) StructRNA *srna; PropertyRNA *prop; -/* FunctionRNA *func; */ -/* PropertyRNA *parm; */ + FunctionRNA *func; + PropertyRNA *parm; RNA_def_property_srna(cprop, "BoneGroups"); srna = RNA_def_struct(brna, "BoneGroups", NULL); RNA_def_struct_sdna(srna, "bPose"); RNA_def_struct_ui_text(srna, "Bone Groups", "Collection of bone groups"); + func = RNA_def_function(srna, "new", "rna_bone_group_new"); + RNA_def_function_ui_description(func, "Add a new bone group to the object"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID); /* ID needed for refresh */ + RNA_def_string(func, "name", "Group", MAX_NAME, "", "Name of the new group"); + /* return type */ + parm = RNA_def_pointer(func, "group", "BoneGroup", "", "New bone group"); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "remove", "rna_bone_group_remove"); + RNA_def_function_ui_description(func, "Remove a bone group from this object"); + RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID); /* ID needed for refresh */ + /* bone group to remove */ + parm = RNA_def_pointer(func, "group", "BoneGroup", "", "Removed bone group"); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); + prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "BoneGroup"); RNA_def_property_flag(prop, PROP_EDITABLE);