Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Leung <aligorith@gmail.com>2009-07-21 14:18:08 +0400
committerJoshua Leung <aligorith@gmail.com>2009-07-21 14:18:08 +0400
commit6d074526f24320eb23be6ad14fd372a2f9c70b89 (patch)
treebfdd6138ce9b24dc8d234b8472f558e2878c5586
parent8c9ade81e8a916521fbfb110aade7627131f3610 (diff)
2.5 - Restoring Bone Groups
* Added Bone Groups UI to 'Armature' context buttons for now. Later, it may be more convenient to have these with bones instead? * Added operators for the operations that can be performed on these groups. Moved the core adding/removing functions to blenkernel so that they can be used elsewhere in future if need be. * Properly wrapped bone groups in RNA. Copied the way that Vertex Groups are wrapped, since they share some similarities. Setting colours for bone groups still needs more work though.
-rw-r--r--release/ui/buttons_data_armature.py33
-rw-r--r--source/blender/blenkernel/BKE_action.h37
-rw-r--r--source/blender/blenkernel/intern/action.c58
-rw-r--r--source/blender/editors/armature/armature_intern.h21
-rw-r--r--source/blender/editors/armature/armature_ops.c8
-rw-r--r--source/blender/editors/armature/editarmature.c6
-rw-r--r--source/blender/editors/armature/poseobject.c371
-rw-r--r--source/blender/editors/space_view3d/view3d_header.c45
-rw-r--r--source/blender/makesrna/RNA_access.h1
-rw-r--r--source/blender/makesrna/intern/rna_pose.c137
10 files changed, 529 insertions, 188 deletions
diff --git a/release/ui/buttons_data_armature.py b/release/ui/buttons_data_armature.py
index 94fda908e56..8eb7ba59c70 100644
--- a/release/ui/buttons_data_armature.py
+++ b/release/ui/buttons_data_armature.py
@@ -79,6 +79,38 @@ class DATA_PT_display(DataButtonsPanel):
sub.itemR(arm, "draw_group_colors", text="Colors")
sub.itemR(arm, "delay_deform", text="Delay Refresh")
+class DATA_PT_bone_groups(DataButtonsPanel):
+ __idname__ = "DATA_PT_bone_groups"
+ __label__ = "Bone Groups"
+
+ def poll(self, context):
+ return (context.object and context.object.type=='ARMATURE' and context.object.pose)
+
+ def draw(self, context):
+ layout = self.layout
+ ob = context.object
+ pose= ob.pose
+
+ row = layout.row()
+
+ row.template_list(pose, "bone_groups", pose, "active_bone_group_index")
+
+ col = row.column(align=True)
+ col.itemO("pose.group_add", icon="ICON_ZOOMIN", text="")
+ col.itemO("pose.group_remove", icon="ICON_ZOOMOUT", text="")
+
+ group = pose.active_bone_group
+ if group:
+ row = layout.row()
+ row.itemR(group, "name")
+
+ row = layout.row(align=True)
+
+ row.itemO("pose.group_assign", text="Assign")
+ row.itemO("pose.group_remove", text="Remove") #row.itemO("pose.bone_group_remove_from", text="Remove")
+ #row.itemO("object.bone_group_select", text="Select")
+ #row.itemO("object.bone_group_deselect", text="Deselect")
+
class DATA_PT_paths(DataButtonsPanel):
__idname__ = "DATA_PT_paths"
__label__ = "Paths"
@@ -136,5 +168,6 @@ class DATA_PT_ghost(DataButtonsPanel):
bpy.types.register(DATA_PT_context_arm)
bpy.types.register(DATA_PT_skeleton)
bpy.types.register(DATA_PT_display)
+bpy.types.register(DATA_PT_bone_groups)
bpy.types.register(DATA_PT_paths)
bpy.types.register(DATA_PT_ghost)
diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h
index 0c9bba5e413..d35acb5447a 100644
--- a/source/blender/blenkernel/BKE_action.h
+++ b/source/blender/blenkernel/BKE_action.h
@@ -1,6 +1,6 @@
/* BKE_action.h May 2001
*
- * Blender kernel action functionality
+ * Blender kernel action and pose functionality
*
* Reevan McKay
*
@@ -26,7 +26,7 @@
* All rights reserved.
*
* Contributor(s): Full recode, Ton Roosendaal, Crete 2005
- * Full recode, Joshua Leung, 2009
+ * Full recode, Joshua Leung, 2009
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -103,8 +103,7 @@ void free_pose(struct bPose *pose);
* Allocate a new pose on the heap, and copy the src pose and it's channels
* into the new pose. *dst is set to the newly allocated structure, and assumed to be NULL.
*/
-void copy_pose(struct bPose **dst, struct bPose *src,
- int copyconstraints);
+void copy_pose(struct bPose **dst, struct bPose *src, int copyconstraints);
@@ -112,9 +111,8 @@ void copy_pose(struct bPose **dst, struct bPose *src,
* Return a pointer to the pose channel of the given name
* from this pose.
*/
-struct bPoseChannel *get_pose_channel(const struct bPose *pose,
- const char *name);
-
+struct bPoseChannel *get_pose_channel(const struct bPose *pose, const char *name);
+
/**
* Return a pointer to the active pose channel from this Object.
* (Note: Object, not bPose is used here, as we need layer info from Armature)
@@ -126,8 +124,9 @@ struct bPoseChannel *get_active_posechannel(struct Object *ob);
* already exists in this pose - if not a new one is
* allocated and initialized.
*/
-struct bPoseChannel *verify_pose_channel(struct bPose* pose,
- const char* name);
+struct bPoseChannel *verify_pose_channel(struct bPose* pose, const char* name);
+
+
/* sets constraint flags */
void update_pose_constraint_flags(struct bPose *pose);
@@ -136,18 +135,30 @@ void update_pose_constraint_flags(struct bPose *pose);
// XXX to be depreceated for a more general solution in animsys...
void framechange_poses_clear_unkeyed(void);
+/* Bone Groups API --------------------- */
+
+/* Adds a new bone-group */
+void pose_add_group(struct Object *ob);
+
+/* Remove the active bone-group */
+void pose_remove_group(struct Object *ob);
+
+/* Assorted Evaluation ----------------- */
+
/* Used for the Action Constraint */
void what_does_obaction(struct Scene *scene, struct Object *ob, struct Object *workob, struct bPose *pose, struct bAction *act, char groupname[], float cframe);
-/* exported for game engine */
-void game_blend_poses(struct bPose *dst, struct bPose *src, float srcweight/*, short mode*/); /* was blend_poses */
-void extract_pose_from_pose(struct bPose *pose, const struct bPose *src);
-
/* for proxy */
void copy_pose_result(struct bPose *to, struct bPose *from);
/* clear all transforms */
void rest_pose(struct bPose *pose);
+/* Game Engine ------------------------- */
+
+/* exported for game engine */
+void game_blend_poses(struct bPose *dst, struct bPose *src, float srcweight/*, short mode*/); /* was blend_poses */
+void extract_pose_from_pose(struct bPose *pose, const struct bPose *src);
+
/* functions used by the game engine */
void game_copy_pose(struct bPose **dst, struct bPose *src);
void game_free_pose(struct bPose *pose);
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index 96896509f60..f4d4eb1cc9c 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -21,6 +21,7 @@
* All rights reserved.
*
* Contributor(s): Full recode, Ton Roosendaal, Crete 2005
+ * Full recode, Joshua Leung, 2009
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -31,7 +32,8 @@
#include <string.h>
#include <math.h>
-#include <stdlib.h> /* for NULL */
+#include <stdlib.h>
+#include <stddef.h>
#include "MEM_guardedalloc.h"
@@ -68,8 +70,6 @@
#include "RNA_access.h"
#include "RNA_types.h"
-//XXX #include "nla.h"
-
/* *********************** NOTE ON POSE AND ACTION **********************
- Pose is the local (object level) component of armature. The current
@@ -765,7 +765,57 @@ void framechange_poses_clear_unkeyed(void)
}
}
-/* ************************ END Pose channels *************** */
+/* ************************** Bone Groups ************************** */
+
+/* Adds a new bone-group */
+void pose_add_group (Object *ob)
+{
+ bPose *pose= (ob) ? ob->pose : NULL;
+ bActionGroup *grp;
+
+ if (ELEM(NULL, ob, ob->pose))
+ return;
+
+ grp= MEM_callocN(sizeof(bActionGroup), "PoseGroup");
+ strcpy(grp->name, "Group");
+ BLI_addtail(&pose->agroups, grp);
+ BLI_uniquename(&pose->agroups, grp, "Group", '.', offsetof(bActionGroup, name), 32);
+
+ pose->active_group= BLI_countlist(&pose->agroups);
+}
+
+/* Remove the active bone-group */
+void pose_remove_group (Object *ob)
+{
+ bPose *pose= (ob) ? ob->pose : NULL;
+ bActionGroup *grp = NULL;
+ bPoseChannel *pchan;
+
+ /* sanity checks */
+ if (ELEM(NULL, ob, pose))
+ return;
+ if (pose->active_group <= 0)
+ return;
+
+ /* 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);
+ pose->active_group= 0;
+ }
+}
/* ************** time ****************** */
diff --git a/source/blender/editors/armature/armature_intern.h b/source/blender/editors/armature/armature_intern.h
index d5ad63ca21b..9ea7b1174a5 100644
--- a/source/blender/editors/armature/armature_intern.h
+++ b/source/blender/editors/armature/armature_intern.h
@@ -33,28 +33,37 @@ struct wmOperatorType;
/* editarmature.c operators */
void ARMATURE_OT_bone_primitive_add(struct wmOperatorType *ot);
+
void ARMATURE_OT_bones_align(struct wmOperatorType *ot);
void ARMATURE_OT_calculate_roll(struct wmOperatorType *ot);
void ARMATURE_OT_switch_direction(struct wmOperatorType *ot);
+
void ARMATURE_OT_subdivs(struct wmOperatorType *ot);
void ARMATURE_OT_subdivide_simple(struct wmOperatorType *ot);
void ARMATURE_OT_subdivide_multi(struct wmOperatorType *ot);
+
void ARMATURE_OT_parent_set(struct wmOperatorType *ot);
void ARMATURE_OT_parent_clear(struct wmOperatorType *ot);
+
void ARMATURE_OT_select_all_toggle(struct wmOperatorType *ot);
void ARMATURE_OT_select_inverse(struct wmOperatorType *ot);
void ARMATURE_OT_select_hierarchy(struct wmOperatorType *ot);
void ARMATURE_OT_select_linked(struct wmOperatorType *ot);
+
void ARMATURE_OT_delete(struct wmOperatorType *ot);
void ARMATURE_OT_duplicate_selected(struct wmOperatorType *ot);
void ARMATURE_OT_extrude(struct wmOperatorType *ot);
void ARMATURE_OT_click_extrude(struct wmOperatorType *ot);
+/* ******************************************************* */
+/* Pose-Mode Operators */
void POSE_OT_hide(struct wmOperatorType *ot);
void POSE_OT_reveal(struct wmOperatorType *ot);
+
void POSE_OT_rot_clear(struct wmOperatorType *ot);
void POSE_OT_loc_clear(struct wmOperatorType *ot);
void POSE_OT_scale_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);
@@ -62,6 +71,16 @@ void POSE_OT_select_hierarchy(struct wmOperatorType *ot);
void POSE_OT_select_linked(struct wmOperatorType *ot);
void POSE_OT_select_constraint_target(struct wmOperatorType *ot);
+void POSE_OT_groups_menu(struct wmOperatorType *ot);
+void POSE_OT_group_add(struct wmOperatorType *ot);
+void POSE_OT_group_remove(struct wmOperatorType *ot);
+void POSE_OT_group_remove(struct wmOperatorType *ot);
+void POSE_OT_group_assign(struct wmOperatorType *ot);
+void POSE_OT_group_unassign(struct wmOperatorType *ot);
+
+/* ******************************************************* */
+/* Etch-A-Ton */
+
void SKETCH_OT_gesture(struct wmOperatorType *ot);
void SKETCH_OT_delete(struct wmOperatorType *ot);
void SKETCH_OT_draw_stroke(struct wmOperatorType *ot);
@@ -70,12 +89,14 @@ void SKETCH_OT_finish_stroke(struct wmOperatorType *ot);
void SKETCH_OT_cancel_stroke(struct wmOperatorType *ot);
void SKETCH_OT_select(struct wmOperatorType *ot);
+/* ******************************************************* */
/* PoseLib */
void POSELIB_OT_pose_add(struct wmOperatorType *ot);
void POSELIB_OT_pose_remove(struct wmOperatorType *ot);
void POSELIB_OT_pose_rename(struct wmOperatorType *ot);
void POSELIB_OT_browse_interactive(struct wmOperatorType *ot);
+/* ******************************************************* */
/* editarmature.c */
struct bArmature;
struct EditBone;
diff --git a/source/blender/editors/armature/armature_ops.c b/source/blender/editors/armature/armature_ops.c
index ed98f70818e..84bddbf0725 100644
--- a/source/blender/editors/armature/armature_ops.c
+++ b/source/blender/editors/armature/armature_ops.c
@@ -155,6 +155,12 @@ void ED_operatortypes_armature(void)
WM_operatortype_append(POSE_OT_select_linked);
WM_operatortype_append(POSE_OT_select_constraint_target);
+ WM_operatortype_append(POSE_OT_groups_menu);
+ WM_operatortype_append(POSE_OT_group_add);
+ WM_operatortype_append(POSE_OT_group_remove);
+ WM_operatortype_append(POSE_OT_group_assign);
+ WM_operatortype_append(POSE_OT_group_unassign);
+
/* POSELIB */
WM_operatortype_append(POSELIB_OT_browse_interactive);
@@ -256,6 +262,8 @@ void ED_keymap_armature(wmWindowManager *wm)
WM_keymap_add_item(keymap, "POSE_OT_ik_add", IKEY, KM_PRESS, /*KM_CTRL|*/KM_SHIFT, 0);
WM_keymap_add_item(keymap, "POSE_OT_ik_clear", IKEY, KM_PRESS, KM_CTRL|KM_ALT, 0);
+ WM_keymap_add_item(keymap, "POSE_OT_groups_menu", GKEY, KM_PRESS, KM_CTRL, 0);
+
// XXX this should probably be in screen instead... here for testing purposes in the meantime... - Aligorith
WM_keymap_verify_item(keymap, "ANIM_OT_insert_keyframe_menu", IKEY, KM_PRESS, 0, 0);
WM_keymap_verify_item(keymap, "ANIM_OT_delete_keyframe_old", IKEY, KM_PRESS, KM_ALT, 0);
diff --git a/source/blender/editors/armature/editarmature.c b/source/blender/editors/armature/editarmature.c
index 49f13d99af9..68d8ffbc11d 100644
--- a/source/blender/editors/armature/editarmature.c
+++ b/source/blender/editors/armature/editarmature.c
@@ -1598,10 +1598,8 @@ static int armature_delete_selected_exec(bContext *C, wmOperator *op)
/* cancel if nothing selected */
if (CTX_DATA_COUNT(C, selected_bones) == 0)
- return OPERATOR_CANCELLED;
-
- /* if (okee("Erase selected bone(s)")==0) return; */
-
+ return OPERATOR_CANCELLED;
+
/* Select mirrored bones */
if (arm->flag & ARM_MIRROR_EDIT) {
for (curBone=arm->edbo->first; curBone; curBone=curBone->next) {
diff --git a/source/blender/editors/armature/poseobject.c b/source/blender/editors/armature/poseobject.c
index 16a9efc9023..d753cf39f69 100644
--- a/source/blender/editors/armature/poseobject.c
+++ b/source/blender/editors/armature/poseobject.c
@@ -81,6 +81,8 @@
#include "ED_transform.h" /* for autokey TFM_TRANSLATION, etc */
#include "ED_view3d.h"
+#include "UI_interface.h"
+
#include "armature_intern.h"
/* ************* XXX *************** */
@@ -397,7 +399,7 @@ void pose_clear_paths(Object *ob)
}
-
+// XXX this function is to be removed when the other stuff is recoded
void pose_select_constraint_target(Scene *scene)
{
Object *obedit= scene->obedit; // XXX context
@@ -932,171 +934,301 @@ void pose_adds_vgroups(Scene *scene, Object *meshobj, int heatweights)
/* ********************************************** */
-/* adds a new pose-group */
-void pose_add_posegroup (Scene *scene)
+
+static int pose_group_add_exec (bContext *C, wmOperator *op)
{
- Object *ob= OBACT;
- bPose *pose= (ob) ? ob->pose : NULL;
- bActionGroup *grp;
+ ScrArea *sa= CTX_wm_area(C);
+ Object *ob;
- if (ELEM(NULL, ob, ob->pose))
- 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 (ob == NULL)
+ return OPERATOR_CANCELLED;
- grp= MEM_callocN(sizeof(bActionGroup), "PoseGroup");
- strcpy(grp->name, "Group");
- BLI_addtail(&pose->agroups, grp);
- BLI_uniquename(&pose->agroups, grp, "Group", '.', offsetof(bActionGroup, name), 32);
+ /* for now, just call the API function for this */
+ pose_add_group(ob);
- pose->active_group= BLI_countlist(&pose->agroups);
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
- BIF_undo_push("Add Bone Group");
+ return OPERATOR_FINISHED;
+}
+
+void POSE_OT_group_add (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Bone Group";
+ ot->idname= "POSE_OT_group_add";
+ ot->description= "Add a new bone group.";
+
+ /* api callbacks */
+ ot->exec= pose_group_add_exec;
+ ot->poll= ED_operator_posemode;
+ /* flags */
+ ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
}
-/* Remove the active bone-group */
-void pose_remove_posegroup (Scene *scene)
+
+static int pose_group_remove_exec (bContext *C, wmOperator *op)
{
- Object *ob= OBACT;
- bPose *pose= (ob) ? ob->pose : NULL;
- bActionGroup *grp = NULL;
- bPoseChannel *pchan;
+ ScrArea *sa= CTX_wm_area(C);
+ Object *ob;
- /* sanity checks */
- if (ELEM(NULL, ob, pose))
- return;
- if (pose->active_group <= 0)
- 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);
- /* 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);
- pose->active_group= 0;
-
- BIF_undo_push("Remove Bone Group");
- }
+ /* only continue if there's an object */
+ if (ob == NULL)
+ return OPERATOR_CANCELLED;
+ /* for now, just call the API function for this */
+ pose_remove_group(ob);
+
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
+
+ return OPERATOR_FINISHED;
}
-char *build_posegroups_menustr (bPose *pose, short for_pupmenu)
+void POSE_OT_group_remove (wmOperatorType *ot)
{
- DynStr *pupds= BLI_dynstr_new();
+ /* identifiers */
+ ot->name= "Remove Bone Group";
+ ot->idname= "POSE_OT_group_remove";
+ ot->description= "Removes the active bone group.";
+
+ /* api callbacks */
+ ot->exec= pose_group_remove_exec;
+ ot->poll= ED_operator_posemode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ------------ */
+
+/* invoke callback which presents a list of bone-groups for the user to choose from */
+static int pose_groups_menu_invoke (bContext *C, wmOperator *op, wmEvent *evt)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ Object *ob;
+ bPose *pose;
+
+ uiPopupMenu *pup;
+ uiLayout *layout;
bActionGroup *grp;
- char *str;
- char buf[16];
int i;
- /* add title first (and the "none" entry) */
- BLI_dynstr_append(pupds, "Bone Group%t|");
- if (for_pupmenu)
- BLI_dynstr_append(pupds, "Add New%x0|");
+ /* 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
- BLI_dynstr_append(pupds, "BG: [None]%x0|");
+ ob= CTX_data_active_object(C);
- /* loop through groups, adding them */
- for (grp= pose->agroups.first, i=1; grp; grp=grp->next, i++) {
- if (for_pupmenu == 0)
- BLI_dynstr_append(pupds, "BG: ");
- BLI_dynstr_append(pupds, grp->name);
+ /* only continue if there's an object, and a pose there too */
+ if (ELEM(NULL, ob, ob->pose))
+ return OPERATOR_CANCELLED;
+ pose= ob->pose;
+
+ /* if there's no active group (or active is invalid), create a new menu to find it */
+ if (pose->active_group <= 0) {
+ /* create a new menu, and start populating it with group names */
+ pup= uiPupMenuBegin(C, op->type->name, 0);
+ layout= uiPupMenuLayout(pup);
- sprintf(buf, "%%x%d", i);
- BLI_dynstr_append(pupds, buf);
+ /* special entry - allow to create new group, then use that
+ * (not to be used for removing though)
+ */
+ if (strstr(op->idname, "assign")) {
+ uiItemIntO(layout, "New Group", 0, op->idname, "type", 0);
+ uiItemS(layout);
+ }
+
+ /* add entries for each group */
+ for (grp= pose->agroups.first, i=1; grp; grp=grp->next, i++)
+ uiItemIntO(layout, grp->name, 0, op->idname, "type", i);
+
+ /* finish building the menu, and process it (should result in calling self again) */
+ uiPupMenuEnd(C, pup);
- if (grp->next)
- BLI_dynstr_append(pupds, "|");
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ /* just use the active group index, and call the exec callback for the calling operator */
+ RNA_int_set(op->ptr, "type", pose->active_group);
+ return op->type->exec;
}
-
- /* convert to normal MEM_malloc'd string */
- str= BLI_dynstr_get_cstring(pupds);
- BLI_dynstr_free(pupds);
-
- return str;
}
/* Assign selected pchans to the bone group that the user selects */
-void pose_assign_to_posegroup (Scene *scene, short active)
+static int pose_group_assign_exec (bContext *C, wmOperator *op)
{
- Object *ob= OBACT;
- bArmature *arm= (ob) ? ob->data : NULL;
- bPose *pose= (ob) ? ob->pose : NULL;
- bPoseChannel *pchan;
- char *menustr;
- int nr;
+ ScrArea *sa= CTX_wm_area(C);
+ Object *ob;
+ bPose *pose;
short done= 0;
- /* sanity checks */
- if (ELEM3(NULL, ob, pose, arm))
- return;
-
- /* get group to affect */
- if ((active==0) || (pose->active_group <= 0)) {
- menustr= build_posegroups_menustr(pose, 1);
- nr= 0; // XXX pupmenu_col(menustr, 20);
- MEM_freeN(menustr);
-
- if (nr < 0)
- return;
- else if (nr == 0) {
- /* add new - note: this does an undo push and sets active group */
- pose_add_posegroup(scene);
- }
- else
- pose->active_group= nr;
- }
+ /* 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, and a pose there too */
+ if (ELEM(NULL, ob, ob->pose))
+ return OPERATOR_CANCELLED;
+ pose= ob->pose;
+
+ /* set the active group number to the one from operator props */
+ pose->active_group= RNA_int_get(op->ptr, "type");
/* add selected bones to group then */
- for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) {
- if ((pchan->bone->flag & BONE_SELECTED) && (pchan->bone->layer & arm->layer)) {
- pchan->agrp_index= pose->active_group;
- done= 1;
- }
+ CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pchans)
+ {
+ pchan->agrp_index= pose->active_group;
+ done= 1;
}
+ CTX_DATA_END;
+
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
+ /* report done status */
if (done)
- BIF_undo_push("Add Bones To Group");
-
+ return OPERATOR_FINISHED;
+ else
+ return OPERATOR_CANCELLED;
}
-/* Remove selected pchans from their bone groups */
-void pose_remove_from_posegroups (Scene *scene)
+void POSE_OT_group_assign (wmOperatorType *ot)
{
- Object *ob= OBACT;
- bArmature *arm= (ob) ? ob->data : NULL;
- bPose *pose= (ob) ? ob->pose : NULL;
- bPoseChannel *pchan;
+ /* identifiers */
+ ot->name= "Add Selected to Bone Group";
+ ot->idname= "POSE_OT_group_assign";
+ ot->description= "Add selected bones to the chosen bone group.";
+
+ /* api callbacks */
+ ot->invoke= pose_groups_menu_invoke;
+ ot->exec= pose_group_assign_exec;
+ ot->poll= ED_operator_posemode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_int(ot->srna, "type", 0, 0, 10, "Bone Group Index", "", 0, INT_MAX);
+}
+
+
+static int pose_group_unassign_exec (bContext *C, wmOperator *op)
+{
+ ScrArea *sa= CTX_wm_area(C);
+ Object *ob;
+ bPose *pose;
short done= 0;
- /* sanity checks */
- if (ELEM3(NULL, ob, pose, arm))
- 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);
- /* remove selected bones from their groups */
- for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) {
- if ((pchan->bone->flag & BONE_SELECTED) && (pchan->bone->layer & arm->layer)) {
- if (pchan->agrp_index) {
- pchan->agrp_index= 0;
- done= 1;
- }
+ /* only continue if there's an object, and a pose there too */
+ if (ELEM(NULL, ob, ob->pose))
+ return OPERATOR_CANCELLED;
+ pose= ob->pose;
+
+ /* add selected bones to ungroup then */
+ CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pchans)
+ {
+ if (pchan->agrp_index) {
+ pchan->agrp_index= 0;
+ done= 1;
}
}
+ CTX_DATA_END;
+
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
+ /* report done status */
if (done)
- BIF_undo_push("Remove Bones From Groups");
+ return OPERATOR_FINISHED;
+ else
+ return OPERATOR_CANCELLED;
+}
+
+void POSE_OT_group_unassign (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Remove Selected from Bone Groups";
+ ot->idname= "POSE_OT_group_unassign";
+ ot->description= "Add selected bones from all bone groups";
+
+ /* api callbacks */
+ ot->exec= pose_group_unassign_exec;
+ ot->poll= ED_operator_posemode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ----------------- */
+
+static int pose_groupOps_menu_invoke (bContext *C, wmOperator *op, wmEvent *evt)
+{
+ Object *ob= CTX_data_active_object(C);
+ uiPopupMenu *pup= uiPupMenuBegin(C, op->type->name, 0);
+ uiLayout *layout= uiPupMenuLayout(pup);
+
+ /* sanity check - must have object with pose */
+ if ELEM(NULL, ob, ob->pose)
+ return OPERATOR_CANCELLED;
+
+ /* get mode of action */
+ if (CTX_DATA_COUNT(C, selected_pchans)) {
+ /* if selected bone(s), include options to add/remove to active group */
+ uiItemO(layout, "Add Selected to Active Group", 0, "POSE_OT_group_assign");
+ uiItemS(layout);
+
+ uiItemO(layout, "Remove Selected from All Groups", 0, "POSE_OT_group_unassign");
+ uiItemO(layout, "Remove Active Group", 0, "POSE_OT_group_remove");
+ }
+ else {
+ /* no selected bones - so just options for groups management */
+ uiItemO(layout, "Add New Group", 0, "POSE_OT_group_add");
+ uiItemO(layout, "Remove Active Group", 0, "POSE_OT_group_remove");
+ }
+
+ return OPERATOR_CANCELLED;
+}
+
+void POSE_OT_groups_menu (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Bone Group Tools";
+ ot->idname= "POSE_OT_groups_menu";
+ ot->description= "Menu displaying available tools for Bone Groups.";
+
+ /* api callbacks (only invoke needed) */
+ ot->invoke= pose_groupOps_menu_invoke;
+ ot->poll= ED_operator_posemode;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER;
}
+#if 0
/* Ctrl-G in 3D-View while in PoseMode */
void pgroup_operation_with_menu (Scene *scene)
{
@@ -1143,6 +1275,7 @@ void pgroup_operation_with_menu (Scene *scene)
break;
}
}
+#endif
/* ********************************************** */
diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c
index 1047e8ee7e5..edffa39cb8c 100644
--- a/source/blender/editors/space_view3d/view3d_header.c
+++ b/source/blender/editors/space_view3d/view3d_header.c
@@ -3040,47 +3040,18 @@ static void view3d_pose_armature_constraintsmenu(bContext *C, uiLayout *layout,
uiItemO(layout, NULL, 0, "POSE_OT_constraints_clear");
}
-#if 0
-static void do_view3d_pose_armature_groupmenu(bContext *C, void *arg, int event)
-{
- switch (event) {
- case 1:
- pose_assign_to_posegroup(1);
- break;
- case 2:
- pose_assign_to_posegroup(0);
- break;
- case 3:
- pose_add_posegroup();
- break;
- case 4:
- pose_remove_from_posegroups();
- break;
- case 5:
- pose_remove_posegroup();
- break;
- }
-}
-
-static uiBlock *view3d_pose_armature_groupmenu(bContext *C, ARegion *ar, void *arg_unused)
+static void view3d_pose_armature_groupmenu(bContext *C, uiLayout *layout, void *arg_unused)
{
- uiBlock *block;
- short yco = 20, menuwidth = 120;
+ uiItemO(layout, "Add Selected to Active Group", 0, "POSE_OT_group_assign");
+ //uiItemO(layout, "Add Selected to Group", 0, "POSE_OT_group_assign");
- block= uiBeginBlock(C, ar, "view3d_pose_armature_groupmenu", UI_EMBOSSP);
- uiBlockSetButmFunc(block, do_view3d_pose_armature_groupmenu, NULL);
+ uiItemO(layout, "Add New Group", 0, "POSE_OT_group_add");
- uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Add Selected to Active Group|Ctrl G", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
- uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Add Selected to Group|Ctrl G", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
- uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Add New Group|Ctrl G", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, "");
- uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Remove from All Groups|Ctrl G", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
- uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Remove Active Group|Ctrl G", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 5, "");
-
- uiBlockSetDirection(block, UI_RIGHT);
- uiTextBoundsBlock(block, 60);
- return block;
+ uiItemO(layout, "Remove from All Groups", 0, "POSE_OT_group_unassign");
+ 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) {
@@ -3214,7 +3185,7 @@ static void view3d_pose_armaturemenu(bContext *C, uiLayout *layout, void *arg_un
uiItemMenuF(layout, "Pose Library", 0, view3d_pose_armature_poselibmenu);
//uiItemMenuF(layout, "Motion Paths", 0, view3d_pose_armature_motionpathsmenu);
- //uiItemMenuF(layout, "Bone Groups", 0, view3d_pose_armature_groupmenu);
+ uiItemMenuF(layout, "Bone Groups", 0, view3d_pose_armature_groupmenu);
uiItemS(layout);
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index f3c2e95451d..33bf1147748 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -63,6 +63,7 @@ extern StructRNA RNA_BezierCurvePoint;
extern StructRNA RNA_BlendTexture;
extern StructRNA RNA_BlenderRNA;
extern StructRNA RNA_Bone;
+extern StructRNA RNA_BoneGroup;
extern StructRNA RNA_BooleanModifier;
extern StructRNA RNA_BooleanProperty;
extern StructRNA RNA_Brush;
diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c
index c7ee7887aff..e15310a02bf 100644
--- a/source/blender/makesrna/intern/rna_pose.c
+++ b/source/blender/makesrna/intern/rna_pose.c
@@ -107,11 +107,106 @@ static int rna_PoseChannel_has_ik_get(PointerRNA *ptr)
return ED_pose_channel_in_IK_chain(ob, pchan);
}
+static PointerRNA rna_Pose_active_bone_group_get(PointerRNA *ptr)
+{
+ bPose *pose= (bPose*)ptr->data;
+ return rna_pointer_inherit_refine(ptr, &RNA_BoneGroup, BLI_findlink(&pose->agroups, pose->active_group-1));
+}
+
+static int rna_Pose_active_bone_group_index_get(PointerRNA *ptr)
+{
+ bPose *pose= (bPose*)ptr->data;
+ return MAX2(pose->active_group-1, 0);
+}
+
+static void rna_Pose_active_bone_group_index_set(PointerRNA *ptr, int value)
+{
+ bPose *pose= (bPose*)ptr->data;
+ pose->active_group= value+1;
+}
+
+static void rna_Pose_active_bone_group_index_range(PointerRNA *ptr, int *min, int *max)
+{
+ bPose *pose= (bPose*)ptr->data;
+
+ *min= 0;
+ *max= BLI_countlist(&pose->agroups)-1;
+ *max= MAX2(0, *max);
+}
+
+void rna_pose_bgroup_name_index_get(PointerRNA *ptr, char *value, int index)
+{
+ bPose *pose= (bPose*)ptr->data;
+ bActionGroup *grp;
+
+ grp= BLI_findlink(&pose->agroups, index-1);
+
+ if(grp) BLI_strncpy(value, grp->name, sizeof(grp->name));
+ else BLI_strncpy(value, "", sizeof(grp->name)); // XXX if invalid pointer, won't this crash?
+}
+
+int rna_pose_bgroup_name_index_length(PointerRNA *ptr, int index)
+{
+ bPose *pose= (bPose*)ptr->data;
+ bActionGroup *grp;
+
+ grp= BLI_findlink(&pose->agroups, index-1);
+ return (grp)? strlen(grp->name): 0;
+}
+
+void rna_pose_bgroup_name_index_set(PointerRNA *ptr, const char *value, short *index)
+{
+ bPose *pose= (bPose*)ptr->data;
+ bActionGroup *grp;
+ int a;
+
+ for (a=1, grp=pose->agroups.first; grp; grp=grp->next, a++) {
+ if (strcmp(grp->name, value) == 0) {
+ *index= a;
+ return;
+ }
+ }
+
+ *index= 0;
+}
+
+void rna_pose_pgroup_name_set(PointerRNA *ptr, const char *value, char *result, int maxlen)
+{
+ bPose *pose= (bPose*)ptr->data;
+ bActionGroup *grp;
+
+ for (grp= pose->agroups.first; grp; grp= grp->next) {
+ if (strcmp(grp->name, value) == 0) {
+ BLI_strncpy(result, value, maxlen);
+ return;
+ }
+ }
+
+ BLI_strncpy(result, "", maxlen);
+}
+
#else
-/* users shouldn't be editing pose channel data directly -- better to set ipos and let blender calc pose_channel stuff */
-/* it's going to be weird for users to find IK flags and other such here, instead of in bone where they would expect them
- -- is there any way to put a doc in bone, pointing them here? */
+static void rna_def_bone_group(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna= RNA_def_struct(brna, "BoneGroup", NULL);
+ RNA_def_struct_sdna(srna, "bActionGroup");
+ RNA_def_struct_ui_text(srna, "Bone Group", "Groups of Pose Channels (Bones).");
+
+ prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Name", "");
+ RNA_def_struct_name_property(srna, prop);
+
+ // TODO: add some runtime-collections stuff to access grouped bones
+
+ // FIXME: this needs more work - probably a custom template?
+ prop= RNA_def_property(srna, "custom_color", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "customCol");
+ RNA_def_property_ui_text(prop, "Custom Color", "Index of custom color set.");
+}
static void rna_def_pose_channel(BlenderRNA *brna)
{
@@ -341,27 +436,47 @@ static void rna_def_pose_channel(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Lock Scale", "Lock editing of scale in the interface.");
}
-void RNA_def_pose(BlenderRNA *brna)
+static void rna_def_pose(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
-
- rna_def_pose_channel(brna);
-
+
+ /* struct definition */
srna= RNA_def_struct(brna, "Pose", NULL);
RNA_def_struct_sdna(srna, "bPose");
RNA_def_struct_ui_text(srna, "Pose", "A collection of pose channels, including settings for animating bones.");
+ /* pose channels */
prop= RNA_def_property(srna, "pose_channels", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "chanbase", NULL);
RNA_def_property_struct_type(prop, "PoseChannel");
RNA_def_property_ui_text(prop, "Pose Channels", "Individual pose channels for the armature.");
- /* commented for now... missing info... */
- /*prop= RNA_def_property(srna, "action_groups", PROP_COLLECTION, PROP_NONE);
+ /* bone groups */
+ prop= RNA_def_property(srna, "bone_groups", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "agroups", NULL);
- RNA_def_property_struct_type(prop, "ActionGroup");
- RNA_def_property_ui_text(prop, "Action Groups", "Groups of bones.");*/
+ RNA_def_property_struct_type(prop, "BoneGroup");
+ RNA_def_property_ui_text(prop, "Bone Groups", "Groups of the bones.");
+
+ prop= RNA_def_property(srna, "active_bone_group", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "BoneGroup");
+ RNA_def_property_pointer_funcs(prop, "rna_Pose_active_bone_group_get", "rna_Pose_active_bone_group_set", NULL);
+ RNA_def_property_ui_text(prop, "Active Bone Group", "Bone groups of the pose.");
+ RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_update");
+
+ prop= RNA_def_property(srna, "active_bone_group_index", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "active_group");
+ RNA_def_property_int_funcs(prop, "rna_Pose_active_bone_group_index_get", "rna_Pose_active_bone_group_index_set", "rna_Pose_active_bone_group_index_range");
+ RNA_def_property_ui_text(prop, "Active Bone Group Index", "Active index in bone groups array.");
+ RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Pose_update");
+}
+
+void RNA_def_pose(BlenderRNA *brna)
+{
+ rna_def_pose(brna);
+ rna_def_pose_channel(brna);
+
+ rna_def_bone_group(brna);
}
#endif