diff options
author | Joseph Eagar <joeedh@gmail.com> | 2009-07-22 06:57:40 +0400 |
---|---|---|
committer | Joseph Eagar <joeedh@gmail.com> | 2009-07-22 06:57:40 +0400 |
commit | 69327f2ebd6dab06b3f75911ef7a28fd562994be (patch) | |
tree | 18b8df7d8ac4106f85cb4a907f5edc566f453b7f /source/blender/editors/armature | |
parent | eecc3f51d4632aa028f6a4d550d43b6804db4aaa (diff) | |
parent | d44d7e220dfbf7b0575ec93f1bb18777f4277eef (diff) |
merge with trunk at r21785, and also fixed stupid ngon normals bug
Diffstat (limited to 'source/blender/editors/armature')
-rw-r--r-- | source/blender/editors/armature/armature_intern.h | 24 | ||||
-rw-r--r-- | source/blender/editors/armature/armature_ops.c | 24 | ||||
-rw-r--r-- | source/blender/editors/armature/editarmature.c | 14 | ||||
-rw-r--r-- | source/blender/editors/armature/editarmature_retarget.c | 8 | ||||
-rw-r--r-- | source/blender/editors/armature/editarmature_sketch.c | 191 | ||||
-rw-r--r-- | source/blender/editors/armature/poselib.c | 7 | ||||
-rw-r--r-- | source/blender/editors/armature/poseobject.c | 650 |
7 files changed, 552 insertions, 366 deletions
diff --git a/source/blender/editors/armature/armature_intern.h b/source/blender/editors/armature/armature_intern.h index d5ad63ca21b..7b3f9a020e3 100644 --- a/source/blender/editors/armature/armature_intern.h +++ b/source/blender/editors/armature/armature_intern.h @@ -33,28 +33,40 @@ 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_copy(struct wmOperatorType *ot); +void POSE_OT_paste(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 +74,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 +92,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 df32f452a38..bf4ec09f3fb 100644 --- a/source/blender/editors/armature/armature_ops.c +++ b/source/blender/editors/armature/armature_ops.c @@ -147,6 +147,9 @@ void ED_operatortypes_armature(void) WM_operatortype_append(POSE_OT_loc_clear); WM_operatortype_append(POSE_OT_scale_clear); + WM_operatortype_append(POSE_OT_copy); + WM_operatortype_append(POSE_OT_paste); + WM_operatortype_append(POSE_OT_select_all_toggle); WM_operatortype_append(POSE_OT_select_inverse); @@ -155,6 +158,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); @@ -225,13 +234,19 @@ void ED_keymap_armature(wmWindowManager *wm) WM_keymap_add_item(keymap, "POSE_OT_hide", HKEY, KM_PRESS, 0, 0); kmi= WM_keymap_add_item(keymap, "POSE_OT_hide", HKEY, KM_PRESS, KM_SHIFT, 0); - RNA_boolean_set(kmi->ptr, "unselected", 1); + RNA_boolean_set(kmi->ptr, "unselected", 1); WM_keymap_add_item(keymap, "POSE_OT_reveal", HKEY, KM_PRESS, KM_ALT, 0); /*clear pose*/ WM_keymap_add_item(keymap, "POSE_OT_rot_clear", RKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "POSE_OT_loc_clear", GKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "POSE_OT_scale_clear", SKEY, KM_PRESS, KM_ALT, 0); + // for now, we include hotkeys for copy/paste + WM_keymap_add_item(keymap, "POSE_OT_copy", CKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "POSE_OT_paste", VKEY, KM_PRESS, KM_CTRL, 0); + kmi= WM_keymap_add_item(keymap, "POSE_OT_paste", VKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0); + RNA_boolean_set(kmi->ptr, "flipped", 1); + WM_keymap_add_item(keymap, "POSE_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "POSE_OT_select_inverse", IKEY, KM_PRESS, KM_CTRL, 0); @@ -251,6 +266,13 @@ void ED_keymap_armature(wmWindowManager *wm) WM_keymap_add_item(keymap, "POSE_OT_select_linked", LKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "POSE_OT_constraint_add_with_targets", CKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0); + WM_keymap_add_item(keymap, "POSE_OT_constraints_clear", CKEY, KM_PRESS, KM_CTRL|KM_ALT, 0); + 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 d00f4c770d1..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) { @@ -5095,9 +5093,9 @@ static void constraint_bone_name_fix(Object *ob, ListBase *conlist, char *oldnam /* called by UI for renaming a bone */ /* warning: make sure the original bone was not renamed yet! */ /* seems messy, but thats what you get with not using pointers but channel names :) */ -void armature_bone_rename(Object *ob, char *oldnamep, char *newnamep) +void ED_armature_bone_rename(bArmature *arm, char *oldnamep, char *newnamep) { - bArmature *arm= ob->data; + Object *ob; char newname[MAXBONENAME]; char oldname[MAXBONENAME]; @@ -5242,7 +5240,7 @@ void armature_flip_names(Scene *scene) if (ebone->flag & BONE_SELECTED) { BLI_strncpy(newname, ebone->name, sizeof(newname)); bone_flip_name(newname, 1); // 1 = do strip off number extensions - armature_bone_rename(obedit, ebone->name, newname); + ED_armature_bone_rename(arm, ebone->name, newname); } } } @@ -5263,7 +5261,7 @@ void armature_autoside_names(Scene *scene, short axis) if (ebone->flag & BONE_SELECTED) { BLI_strncpy(newname, ebone->name, sizeof(newname)); bone_autoside_name(newname, 1, axis, ebone->head[axis], ebone->tail[axis]); - armature_bone_rename(obedit, ebone->name, newname); + ED_armature_bone_rename(arm, ebone->name, newname); } } } diff --git a/source/blender/editors/armature/editarmature_retarget.c b/source/blender/editors/armature/editarmature_retarget.c index 6f5692dbf4c..a1ce256a1af 100644 --- a/source/blender/editors/armature/editarmature_retarget.c +++ b/source/blender/editors/armature/editarmature_retarget.c @@ -2139,15 +2139,15 @@ static MemoNode * solveJoints(MemoNode *table, BArcIterator *iter, float **vec_c MemoNode *min_node = NULL; float *vec0 = vec_cache[previous]; float *vec1 = vec_cache[current]; - float min_weight; - int min_next; + float min_weight= 0.0f; + int min_next= 0; int next; for (next = current + 1; next <= nb_positions - (joints_left - 1); next++) { MemoNode *next_node; float *vec2 = vec_cache[next]; - float weight = 0; + float weight = 0.0f; /* ADD WEIGHT OF PREVIOUS - CURRENT - NEXT triple */ weight = calcCostAngleLengthDistance(iter, vec_cache, edge, vec0, vec1, vec2, current, next, angle_weight, length_weight, distance_weight); @@ -2824,7 +2824,7 @@ void BIF_retargetArmature(bContext *C) ReebGraph *reebg; double start_time, end_time; double gstart_time, gend_time; - double reeb_time, rig_time, retarget_time, total_time; + double reeb_time, rig_time=0.0, retarget_time=0.0, total_time; gstart_time = start_time = PIL_check_seconds_timer(); diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c index af1ed3e2746..974eeb91a68 100644 --- a/source/blender/editors/armature/editarmature_sketch.c +++ b/source/blender/editors/armature/editarmature_sketch.c @@ -186,7 +186,6 @@ typedef struct SK_GestureAction { GestureApplyFct apply; } SK_GestureAction; -SK_Sketch *GLOBAL_sketch = NULL; SK_Point boneSnap; int LAST_SNAP_POINT_VALID = 0; float LAST_SNAP_POINT[3]; @@ -217,6 +216,8 @@ void sk_applyReverseGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch); int sk_detectConvertGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch); void sk_applyConvertGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch); +SK_Sketch* contextSketch(const bContext *c, int create); +SK_Sketch* viewcontextSketch(ViewContext *vc, int create); void sk_resetOverdraw(SK_Sketch *sketch); int sk_hasOverdraw(SK_Sketch *sketch, SK_Stroke *stk); @@ -381,7 +382,7 @@ int BIF_nbJointsTemplate(const bContext *C) char * BIF_nameBoneTemplate(const bContext *C) { ToolSettings *ts = CTX_data_tool_settings(C); - SK_Sketch *stk = GLOBAL_sketch; + SK_Sketch *stk = contextSketch(C, 1); RigGraph *rg; int index = 0; @@ -1592,6 +1593,7 @@ int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, SK_Strok float p[3]; float size = 0; + BLI_freelistN(&sketch->depth_peels); sketch->depth_peels.first = sketch->depth_peels.last = NULL; peelObjectsContext(C, &sketch->depth_peels, dd->mval); @@ -3023,9 +3025,10 @@ int BDR_drawSketchNames(ViewContext *vc) { if (ValidSketchViewContext(vc)) { - if (GLOBAL_sketch != NULL) + SK_Sketch *sketch = viewcontextSketch(vc, 0); + if (sketch) { - sk_drawSketch(vc->scene, vc->v3d, GLOBAL_sketch, 1); + sk_drawSketch(vc->scene, vc->v3d, sketch, 1); return 1; } } @@ -3037,18 +3040,20 @@ void BDR_drawSketch(const bContext *C) { if (ED_operator_sketch_mode(C)) { - if (GLOBAL_sketch != NULL) + SK_Sketch *sketch = contextSketch(C, 0); + if (sketch) { - sk_drawSketch(CTX_data_scene(C), CTX_wm_view3d(C), GLOBAL_sketch, 0); + sk_drawSketch(CTX_data_scene(C), CTX_wm_view3d(C), sketch, 0); } } } static int sketch_delete(bContext *C, wmOperator *op, wmEvent *event) { - if (GLOBAL_sketch != NULL) + SK_Sketch *sketch = contextSketch(C, 0); + if (sketch) { - sk_deleteSelectedStrokes(GLOBAL_sketch); + sk_deleteSelectedStrokes(sketch); // allqueue(REDRAWVIEW3D, 0); } return OPERATOR_FINISHED; @@ -3056,9 +3061,10 @@ static int sketch_delete(bContext *C, wmOperator *op, wmEvent *event) void BIF_sk_selectStroke(bContext *C, short mval[2], short extend) { - if (GLOBAL_sketch != NULL) + SK_Sketch *sketch = contextSketch(C, 0); + if (sketch) { - sk_selectStroke(C, GLOBAL_sketch, mval, extend); + sk_selectStroke(C, sketch, mval, extend); } } @@ -3066,9 +3072,10 @@ void BIF_convertSketch(bContext *C) { if (ED_operator_sketch_full_mode(C)) { - if (GLOBAL_sketch != NULL) + SK_Sketch *sketch = contextSketch(C, 0); + if (sketch) { - sk_convert(C, GLOBAL_sketch); + sk_convert(C, sketch); // BIF_undo_push("Convert Sketch"); // allqueue(REDRAWVIEW3D, 0); // allqueue(REDRAWBUTSEDIT, 0); @@ -3080,42 +3087,86 @@ void BIF_deleteSketch(bContext *C) { if (ED_operator_sketch_full_mode(C)) { - if (GLOBAL_sketch != NULL) + SK_Sketch *sketch = contextSketch(C, 0); + if (sketch) { - sk_deleteSelectedStrokes(GLOBAL_sketch); + sk_deleteSelectedStrokes(sketch); // BIF_undo_push("Convert Sketch"); // allqueue(REDRAWVIEW3D, 0); } } } -//void BIF_selectAllSketch(bContext *C, int mode) -//{ -// if (BIF_validSketchMode(C)) -// { -// if (GLOBAL_sketch != NULL) -// { -// sk_selectAllSketch(GLOBAL_sketch, mode); -//// XXX -//// allqueue(REDRAWVIEW3D, 0); -// } -// } -//} +#if 0 +void BIF_selectAllSketch(bContext *C, int mode) +{ + if (BIF_validSketchMode(C)) + { + SK_Sketch *sketch = contextSketch(C, 0); + if (sketch) + { + sk_selectAllSketch(sketch, mode); +// XXX +// allqueue(REDRAWVIEW3D, 0); + } + } +} +#endif -void BIF_freeSketch(bContext *C) +void ED_freeSketch(SK_Sketch *sketch) { - if (GLOBAL_sketch != NULL) + sk_freeSketch(sketch); +} + +SK_Sketch* ED_createSketch() +{ + return sk_createSketch(); +} + +SK_Sketch* contextSketch(const bContext *C, int create) +{ + Object *obedit = CTX_data_edit_object(C); + SK_Sketch *sketch = NULL; + + if (obedit && obedit->type == OB_ARMATURE) { - sk_freeSketch(GLOBAL_sketch); - GLOBAL_sketch = NULL; + bArmature *arm = obedit->data; + + if (arm->sketch == NULL && create) + { + arm->sketch = sk_createSketch(); + } + sketch = arm->sketch; } + + return sketch; +} + +SK_Sketch* viewcontextSketch(ViewContext *vc, int create) +{ + Object *obedit = vc->obedit; + SK_Sketch *sketch = NULL; + + if (obedit && obedit->type == OB_ARMATURE) + { + bArmature *arm = obedit->data; + + if (arm->sketch == NULL && create) + { + arm->sketch = sk_createSketch(); + } + sketch = arm->sketch; + } + + return sketch; } static int sketch_cancel(bContext *C, wmOperator *op, wmEvent *event) { - if (GLOBAL_sketch != NULL) + SK_Sketch *sketch = contextSketch(C, 0); + if (sketch != NULL) { - sk_cancelStroke(GLOBAL_sketch); + sk_cancelStroke(sketch); ED_area_tag_redraw(CTX_wm_area(C)); return OPERATOR_FINISHED; } @@ -3124,9 +3175,10 @@ static int sketch_cancel(bContext *C, wmOperator *op, wmEvent *event) static int sketch_finish(bContext *C, wmOperator *op, wmEvent *event) { - if (GLOBAL_sketch != NULL) + SK_Sketch *sketch = contextSketch(C, 0); + if (sketch != NULL) { - if (sk_finish_stroke(C, GLOBAL_sketch)) + if (sk_finish_stroke(C, sketch)) { ED_area_tag_redraw(CTX_wm_area(C)); return OPERATOR_FINISHED; @@ -3137,10 +3189,11 @@ static int sketch_finish(bContext *C, wmOperator *op, wmEvent *event) static int sketch_select(bContext *C, wmOperator *op, wmEvent *event) { - if (GLOBAL_sketch != NULL) + SK_Sketch *sketch = contextSketch(C, 0); + if (sketch) { short extend = 0; - sk_selectStroke(C, GLOBAL_sketch, event->mval, extend); + sk_selectStroke(C, sketch, event->mval, extend); ED_area_tag_redraw(CTX_wm_area(C)); } @@ -3149,7 +3202,8 @@ static int sketch_select(bContext *C, wmOperator *op, wmEvent *event) static int sketch_draw_stroke_cancel(bContext *C, wmOperator *op) { - sk_cancelStroke(GLOBAL_sketch); + SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */ + sk_cancelStroke(sketch); MEM_freeN(op->customdata); return OPERATOR_CANCELLED; } @@ -3158,18 +3212,14 @@ static int sketch_draw_stroke(bContext *C, wmOperator *op, wmEvent *event) { short snap = RNA_boolean_get(op->ptr, "snap"); SK_DrawData *dd; - - if (GLOBAL_sketch == NULL) - { - GLOBAL_sketch = sk_createSketch(); - } + SK_Sketch *sketch = contextSketch(C, 1); op->customdata = dd = MEM_callocN(sizeof("SK_DrawData"), "SketchDrawData"); sk_initDrawData(dd, event->mval); - sk_start_draw_stroke(GLOBAL_sketch); + sk_start_draw_stroke(sketch); - sk_draw_stroke(C, GLOBAL_sketch, GLOBAL_sketch->active_stroke, dd, snap); + sk_draw_stroke(C, sketch, sketch->active_stroke, dd, snap); WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); @@ -3178,7 +3228,8 @@ static int sketch_draw_stroke(bContext *C, wmOperator *op, wmEvent *event) static int sketch_draw_gesture_cancel(bContext *C, wmOperator *op) { - sk_cancelStroke(GLOBAL_sketch); + SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */ + sk_cancelStroke(sketch); MEM_freeN(op->customdata); return OPERATOR_CANCELLED; } @@ -3187,17 +3238,14 @@ static int sketch_draw_gesture(bContext *C, wmOperator *op, wmEvent *event) { short snap = RNA_boolean_get(op->ptr, "snap"); SK_DrawData *dd; - - if (GLOBAL_sketch == NULL) - { - GLOBAL_sketch = sk_createSketch(); - } + SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */ + sk_cancelStroke(sketch); op->customdata = dd = MEM_callocN(sizeof("SK_DrawData"), "SketchDrawData"); sk_initDrawData(dd, event->mval); - sk_start_draw_gesture(GLOBAL_sketch); - sk_draw_stroke(C, GLOBAL_sketch, GLOBAL_sketch->gesture, dd, snap); + sk_start_draw_gesture(sketch); + sk_draw_stroke(C, sketch, sketch->gesture, dd, snap); WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); @@ -3208,6 +3256,7 @@ static int sketch_draw_modal(bContext *C, wmOperator *op, wmEvent *event, short { short snap = RNA_boolean_get(op->ptr, "snap"); SK_DrawData *dd = op->customdata; + SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */ int retval = OPERATOR_RUNNING_MODAL; switch (event->type) @@ -3220,7 +3269,7 @@ static int sketch_draw_modal(bContext *C, wmOperator *op, wmEvent *event, short case MOUSEMOVE: dd->mval[0] = event->mval[0]; dd->mval[1] = event->mval[1]; - sk_draw_stroke(C, GLOBAL_sketch, stk, dd, snap); + sk_draw_stroke(C, sketch, stk, dd, snap); ED_area_tag_redraw(CTX_wm_area(C)); break; case ESCKEY: @@ -3235,7 +3284,7 @@ static int sketch_draw_modal(bContext *C, wmOperator *op, wmEvent *event, short { sk_endContinuousStroke(stk); sk_filterLastContinuousStroke(stk); - sk_updateNextPoint(GLOBAL_sketch, stk); + sk_updateNextPoint(sketch, stk); ED_area_tag_redraw(CTX_wm_area(C)); MEM_freeN(op->customdata); retval = OPERATOR_FINISHED; @@ -3248,11 +3297,11 @@ static int sketch_draw_modal(bContext *C, wmOperator *op, wmEvent *event, short if (stk->nb_points > 1) { /* apply gesture here */ - sk_applyGesture(C, GLOBAL_sketch); + sk_applyGesture(C, sketch); } sk_freeStroke(stk); - GLOBAL_sketch->gesture = NULL; + sketch->gesture = NULL; ED_area_tag_redraw(CTX_wm_area(C)); MEM_freeN(op->customdata); @@ -3267,21 +3316,23 @@ static int sketch_draw_modal(bContext *C, wmOperator *op, wmEvent *event, short static int sketch_draw_stroke_modal(bContext *C, wmOperator *op, wmEvent *event) { - return sketch_draw_modal(C, op, event, 0, GLOBAL_sketch->active_stroke); + SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */ + return sketch_draw_modal(C, op, event, 0, sketch->active_stroke); } static int sketch_draw_gesture_modal(bContext *C, wmOperator *op, wmEvent *event) { - return sketch_draw_modal(C, op, event, 1, GLOBAL_sketch->gesture); + SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */ + return sketch_draw_modal(C, op, event, 1, sketch->gesture); } static int sketch_draw_preview(bContext *C, wmOperator *op, wmEvent *event) { short snap = RNA_boolean_get(op->ptr, "snap"); + SK_Sketch *sketch = contextSketch(C, 0); - if (GLOBAL_sketch != NULL) + if (sketch) { - SK_Sketch *sketch = GLOBAL_sketch; SK_DrawData dd; sk_initDrawData(&dd, event->mval); @@ -3296,14 +3347,12 @@ static int sketch_draw_preview(bContext *C, wmOperator *op, wmEvent *event) int ED_operator_sketch_mode_active_stroke(bContext *C) { - Object *obedit = CTX_data_edit_object(C); ToolSettings *ts = CTX_data_tool_settings(C); + SK_Sketch *sketch = contextSketch(C, 0); - if (obedit && - obedit->type == OB_ARMATURE && - ts->bone_sketching & BONE_SKETCHING && - GLOBAL_sketch != NULL && - GLOBAL_sketch->active_stroke != NULL) + if (ts->bone_sketching & BONE_SKETCHING && + sketch != NULL && + sketch->active_stroke != NULL) { return 1; } @@ -3315,15 +3364,13 @@ int ED_operator_sketch_mode_active_stroke(bContext *C) int ED_operator_sketch_mode_gesture(bContext *C) { - Object *obedit = CTX_data_edit_object(C); ToolSettings *ts = CTX_data_tool_settings(C); + SK_Sketch *sketch = contextSketch(C, 0); - if (obedit && - obedit->type == OB_ARMATURE && - ts->bone_sketching & BONE_SKETCHING && + if (ts->bone_sketching & BONE_SKETCHING && (ts->bone_sketching & BONE_SKETCHING_QUICK) == 0 && - GLOBAL_sketch != NULL && - GLOBAL_sketch->active_stroke == NULL) + sketch != NULL && + sketch->active_stroke == NULL) { return 1; } diff --git a/source/blender/editors/armature/poselib.c b/source/blender/editors/armature/poselib.c index 93611a30bd8..ef2e5188487 100644 --- a/source/blender/editors/armature/poselib.c +++ b/source/blender/editors/armature/poselib.c @@ -37,6 +37,7 @@ #include "BLI_arithb.h" #include "BLI_blenlib.h" #include "BLI_dynstr.h" +#include "BLI_dlrbTree.h" #include "DNA_listBase.h" #include "DNA_anim_types.h" @@ -216,7 +217,7 @@ bAction *poselib_validate (Object *ob) // TODO: operatorfy me! void poselib_validate_act (bAction *act) { - ListBase keys = {NULL, NULL}; + DLRBT_Tree keys = {NULL, NULL}; ActKeyColumn *ak; TimeMarker *marker, *markern; @@ -227,7 +228,9 @@ void poselib_validate_act (bAction *act) } /* 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) { @@ -267,7 +270,7 @@ void poselib_validate_act (bAction *act) } /* free temp memory */ - BLI_freelistN(&keys); + BLI_freelistN((ListBase *)&keys); BIF_undo_push("PoseLib Validate Action"); } diff --git a/source/blender/editors/armature/poseobject.c b/source/blender/editors/armature/poseobject.c index 2913d1d13d9..9814a056b70 100644 --- a/source/blender/editors/armature/poseobject.c +++ b/source/blender/editors/armature/poseobject.c @@ -63,6 +63,7 @@ #include "BKE_modifier.h" #include "BKE_object.h" #include "BKE_utildefines.h" +#include "BKE_report.h" #include "BIF_gl.h" @@ -81,17 +82,17 @@ #include "ED_transform.h" /* for autokey TFM_TRANSLATION, etc */ #include "ED_view3d.h" +#include "UI_interface.h" + #include "armature_intern.h" /* ************* XXX *************** */ static int movetolayer_short_buts() {return 1;} -static int okee() {return 0;} static int pupmenu() {return 0;} static void waitcursor() {}; static void error() {}; static void BIF_undo_push() {} static void countall() {} -static void add_constraint() {} static void autokeyframe_pose_cb_func() {} /* ************* XXX *************** */ @@ -399,7 +400,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 @@ -587,92 +588,6 @@ void POSE_OT_select_hierarchy(wmOperatorType *ot) } -void pose_add_IK(Scene *scene) -{ - Object *obedit= scene->obedit; // XXX context - Object *ob= OBACT; - - /* paranoia checks */ - if(!ob && !ob->pose) return; - if(ob==obedit || (ob->flag & OB_POSEMODE)==0) return; - - add_constraint(1); /* 1 means only IK */ -} - -/* context: all selected channels */ -void pose_clear_IK(Scene *scene) -{ - Object *obedit= scene->obedit; // XXX context - Object *ob= OBACT; - bArmature *arm= ob->data; - bPoseChannel *pchan; - bConstraint *con; - bConstraint *next; - - /* paranoia checks */ - if(!ob && !ob->pose) return; - if(ob==obedit || (ob->flag & OB_POSEMODE)==0) return; - - if(pose_has_protected_selected(ob, 0, 1)) - return; - - if(okee("Remove IK constraint(s)")==0) return; - - for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { - if(arm->layer & pchan->bone->layer) { - if(pchan->bone->flag & (BONE_ACTIVE|BONE_SELECTED)) { - - for(con= pchan->constraints.first; con; con= next) { - next= con->next; - if(con->type==CONSTRAINT_TYPE_KINEMATIC) { - BLI_remlink(&pchan->constraints, con); - free_constraint_data(con); - MEM_freeN(con); - } - } - pchan->constflag &= ~(PCHAN_HAS_IK|PCHAN_HAS_TARGET); - } - } - } - - DAG_object_flush_update(scene, ob, OB_RECALC_DATA); // and all its relations - - BIF_undo_push("Remove IK constraint(s)"); -} - -void pose_clear_constraints(Scene *scene) -{ - Object *obedit= scene->obedit; // XXX context - Object *ob= OBACT; - bArmature *arm= ob->data; - bPoseChannel *pchan; - - /* paranoia checks */ - if(!ob && !ob->pose) return; - if(ob==obedit || (ob->flag & OB_POSEMODE)==0) return; - - if(pose_has_protected_selected(ob, 0, 1)) - return; - - if(okee("Remove Constraints")==0) return; - - /* find active */ - for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { - if(arm->layer & pchan->bone->layer) { - if(pchan->bone->flag & (BONE_ACTIVE|BONE_SELECTED)) { - free_constraints(&pchan->constraints); - pchan->constflag= 0; - } - } - } - - DAG_object_flush_update(scene, ob, OB_RECALC_DATA); // and all its relations - - BIF_undo_push("Remove Constraint(s)"); - -} - - void pose_copy_menu(Scene *scene) { Object *obedit= scene->obedit; // XXX context @@ -865,81 +780,132 @@ void pose_copy_menu(Scene *scene) /* ******************** copy/paste pose ********************** */ -static bPose *g_posebuf=NULL; +/* Global copy/paste buffer for pose - cleared on start/end session + before every copy operation */ +static bPose *g_posebuf = NULL; void free_posebuf(void) { if (g_posebuf) { - // was copied without constraints - BLI_freelistN (&g_posebuf->chanbase); - MEM_freeN (g_posebuf); + /* was copied without constraints */ + BLI_freelistN(&g_posebuf->chanbase); + MEM_freeN(g_posebuf); } + g_posebuf=NULL; } -void copy_posebuf (Scene *scene) -{ - Object *ob= OBACT; +/* ---- */ - if (!ob || !ob->pose){ - error ("No Pose"); - return; +static int pose_copy_exec (bContext *C, wmOperator *op) +{ + Object *ob= CTX_data_active_object(C); + + /* sanity checking */ + if ELEM(NULL, ob, ob->pose) { + BKE_report(op->reports, RPT_ERROR, "No Pose to Copy"); + return OPERATOR_CANCELLED; } + /* free existing pose buffer */ free_posebuf(); - set_pose_keys(ob); // sets chan->flag to POSE_KEY if bone selected + /* sets chan->flag to POSE_KEY if bone selected, then copy those bones to the buffer */ + set_pose_keys(ob); copy_pose(&g_posebuf, ob->pose, 0); + + + return OPERATOR_FINISHED; +} +void POSE_OT_copy (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Copy Pose"; + ot->idname= "POSE_OT_copy"; + ot->description= "Copies the current pose of the selected bones to copy/paste buffer."; + + /* api callbacks */ + ot->exec= pose_copy_exec; + ot->poll= ED_operator_posemode; + + /* flag */ + ot->flag= OPTYPE_REGISTER; } -void paste_posebuf (Scene *scene, int flip) +/* ---- */ + +static int pose_paste_exec (bContext *C, wmOperator *op) { - Object *ob= OBACT; + Scene *scene= CTX_data_scene(C); + Object *ob= CTX_data_active_object(C); bPoseChannel *chan, *pchan; - float eul[4]; char name[32]; + int flip= RNA_boolean_get(op->ptr, "flipped"); - if (!ob || !ob->pose) - return; + /* sanity checks */ + if ELEM(NULL, ob, ob->pose) + return OPERATOR_CANCELLED; - if (!g_posebuf){ - error ("Copy buffer is empty"); - return; + if (g_posebuf == NULL) { + BKE_report(op->reports, RPT_ERROR, "Copy buffer is empty"); + return OPERATOR_CANCELLED; } - /* - // disabled until protected bones in proxies follow the rules everywhere else! - if(pose_has_protected_selected(ob, 1, 1)) - return; - */ - - /* Safely merge all of the channels in this pose into - any existing pose */ - for (chan=g_posebuf->chanbase.first; chan; chan=chan->next) { + /* Safely merge all of the channels in the buffer pose into any existing pose */ + for (chan= g_posebuf->chanbase.first; chan; chan=chan->next) { if (chan->flag & POSE_KEY) { + /* get the name - if flipping, we must flip this first */ BLI_strncpy(name, chan->name, sizeof(name)); if (flip) - bone_flip_name (name, 0); // 0 = don't strip off number extensions + bone_flip_name(name, 0); /* 0 = don't strip off number extensions */ /* only copy when channel exists, poses are not meant to add random channels to anymore */ pchan= get_pose_channel(ob->pose, name); if (pchan) { - /* only loc rot size */ - /* only copies transform info for the pose */ + /* only loc rot size + * - only copies transform info for the pose + */ VECCOPY(pchan->loc, chan->loc); VECCOPY(pchan->size, chan->size); - QUATCOPY(pchan->quat, chan->quat); pchan->flag= chan->flag; + /* check if rotation modes are compatible (i.e. do they need any conversions) */ + if (pchan->rotmode == chan->rotmode) { + /* copy the type of rotation in use */ + if (pchan->rotmode) { + VECCOPY(pchan->eul, chan->eul); + } + else { + QUATCOPY(pchan->quat, chan->quat); + } + } + else if (pchan->rotmode) { + /* quat to euler */ + QuatToEul(chan->quat, pchan->eul); + } + else { + /* euler to quat */ + EulToQuat(chan->eul, pchan->quat); + } + + /* paste flipped pose? */ if (flip) { pchan->loc[0]*= -1; - QuatToEul(pchan->quat, eul); - eul[1]*= -1; - eul[2]*= -1; - EulToQuat(eul, pchan->quat); + /* has to be done as eulers... */ + if (pchan->rotmode) { + pchan->eul[1] *= -1; + pchan->eul[2] *= -1; + } + else { + float eul[3]; + + QuatToEul(pchan->quat, eul); + eul[1]*= -1; + eul[2]*= -1; + EulToQuat(eul, pchan->quat); + } } #if 0 // XXX old animation system @@ -947,6 +913,7 @@ void paste_posebuf (Scene *scene, int flip) ID *id= &ob->id; /* Set keys on pose */ + // TODO: make these use keyingsets.... if (chan->flag & POSE_ROT) { insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X, 0); insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y, 0); @@ -989,8 +956,29 @@ void paste_posebuf (Scene *scene, int flip) where_is_pose(scene, ob); ob->recalc= 0; } + + /* notifiers for updates */ + WM_event_add_notifier(C, NC_OBJECT|ND_POSE|ND_TRANSFORM, ob); - BIF_undo_push("Paste Action Pose"); + return OPERATOR_FINISHED; +} + +void POSE_OT_paste (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Paste Pose"; + ot->idname= "POSE_OT_paste"; + ot->description= "Pastes the stored pose on to the current pose."; + + /* api callbacks */ + ot->exec= pose_paste_exec; + ot->poll= ED_operator_posemode; + + /* flag */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties */ + RNA_def_boolean(ot->srna, "flipped", 0, "Flipped on X-Axis", ""); } /* ********************************************** */ @@ -1020,216 +1008,320 @@ 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; + + /* for now, just call the API function for this */ + pose_add_group(ob); - 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); + /* notifiers for updates */ + WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob); - pose->active_group= BLI_countlist(&pose->agroups); + 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."; - BIF_undo_push("Add 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); + + /* only continue if there's an object, and a pose there too */ + if (ELEM(NULL, ob, ob->pose)) + return OPERATOR_CANCELLED; + pose= ob->pose; - /* 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); + /* 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); + } - if (grp->next) - BLI_dynstr_append(pupds, "|"); + /* 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); + + 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(C, op); } - - /* 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; + ScrArea *sa= CTX_wm_area(C); + Object *ob; + bArmature *arm; + bPose *pose; bPoseChannel *pchan; - char *menustr; - int nr; 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; + arm= ob->data; + pose= ob->pose; + + /* set the active group number to the one from operator props + * - if 0 after this, make a new group... + */ + pose->active_group= RNA_int_get(op->ptr, "type"); + if (pose->active_group == 0) + pose_add_group(ob); /* add selected bones to group then */ + // NOTE: unfortunately, we cannot use the context-iterators here, since they might not be defined... + // CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pchans) 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; + /* ensure that PoseChannel is on visible layer and is not hidden in PoseMode */ + // NOTE: sync this view3d_context() in space_view3d.c + if ((pchan->bone) && (arm->layer & pchan->bone->layer) && !(pchan->bone->flag & BONE_HIDDEN_P)) { + if (pchan->bone->flag & (BONE_SELECTED|BONE_ACTIVE)) { + pchan->agrp_index= pose->active_group; + done= 1; + } } } + /* 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; + /* 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; + bArmature *arm; + bPose *pose; bPoseChannel *pchan; 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); + + /* only continue if there's an object, and a pose there too */ + if (ELEM(NULL, ob, ob->pose)) + return OPERATOR_CANCELLED; + pose= ob->pose; + arm= ob->data; - /* remove selected bones from their groups */ + /* add selected bones to ungroup then */ + // NOTE: unfortunately, we cannot use the context-iterators here, since they might not be defined... + // CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pchans) 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; + /* ensure that PoseChannel is on visible layer and is not hidden in PoseMode */ + // NOTE: sync this view3d_context() in space_view3d.c + if ((pchan->bone) && (arm->layer & pchan->bone->layer) && !(pchan->bone->flag & BONE_HIDDEN_P)) { + if (pchan->bone->flag & (BONE_SELECTED|BONE_ACTIVE)) { + if (pchan->agrp_index) { + pchan->agrp_index= 0; + done= 1; + } } } } + /* 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; } -/* Ctrl-G in 3D-View while in PoseMode */ -void pgroup_operation_with_menu (Scene *scene) +void POSE_OT_group_unassign (wmOperatorType *ot) { - Object *ob= OBACT; - bArmature *arm= (ob) ? ob->data : NULL; - bPose *pose= (ob) ? ob->pose : NULL; - bPoseChannel *pchan= NULL; - int mode; + /* identifiers */ + ot->name= "Remove Selected from Bone Groups"; + ot->idname= "POSE_OT_group_unassign"; + ot->description= "Add selected bones from all bone groups"; - /* sanity checks */ - if (ELEM3(NULL, ob, pose, arm)) - return; + /* api callbacks */ + ot->exec= pose_group_unassign_exec; + ot->poll= ED_operator_posemode; - /* check that something is selected */ - for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) { - if ((pchan->bone->flag & BONE_SELECTED) && (pchan->bone->layer & arm->layer)) - break; - } - if (pchan == NULL) - return; + /* 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 (pchan) - mode= pupmenu("Bone Groups%t|Add Selected to Active Group%x1|Add Selected to Group%x2|%|Remove Selected From Groups%x3|Remove Active Group%x4"); - else - mode= pupmenu("Bone Groups%t|Add New Group%x5|Remove Active Group%x4"); + 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"); - /* handle mode */ - switch (mode) { - case 1: - pose_assign_to_posegroup(scene, 1); - break; - case 2: - pose_assign_to_posegroup(scene, 0); - break; - case 5: - pose_add_posegroup(scene); - break; - case 3: - pose_remove_from_posegroups(scene); - break; - case 4: - pose_remove_posegroup(scene); - break; + 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; } /* ********************************************** */ @@ -1346,7 +1438,7 @@ void pose_flip_names(Scene *scene) if(pchan->bone->flag & (BONE_ACTIVE|BONE_SELECTED)) { BLI_strncpy(newname, pchan->name, sizeof(newname)); bone_flip_name(newname, 1); // 1 = do strip off number extensions - armature_bone_rename(ob, pchan->name, newname); + ED_armature_bone_rename(arm, pchan->name, newname); } } } @@ -1375,7 +1467,7 @@ void pose_autoside_names(Scene *scene, short axis) if(pchan->bone->flag & (BONE_ACTIVE|BONE_SELECTED)) { BLI_strncpy(newname, pchan->name, sizeof(newname)); bone_autoside_name(newname, 1, axis, pchan->bone->head[axis], pchan->bone->tail[axis]); - armature_bone_rename(ob, pchan->name, newname); + ED_armature_bone_rename(arm, pchan->name, newname); } } } |