diff options
author | Joshua Leung <aligorith@gmail.com> | 2009-07-20 16:42:31 +0400 |
---|---|---|
committer | Joshua Leung <aligorith@gmail.com> | 2009-07-20 16:42:31 +0400 |
commit | cc69f1301387ea920a225b6eb49283e3c03e1b06 (patch) | |
tree | c37efd91a68d9ff93b8339690340ee11d013066d | |
parent | 8bf9a8cb1e18dc784835db5fd869ad14469053a5 (diff) |
2.5 - Constraints Editing + Keyframe Drawing Tweaks
Constraints:
* Adding constraints with targets should now work.
-- (When no target is provided, the code to create a new target is not yet in place again yet)
* Constraints can be added in Object and PoseModes again using the Ctrl-Shift-C hotkey.
* All constraints can now be cleared from the active Object or selected Bones using the Ctrl-Alt-C hotkey.
* Added warnings when adding constraints invalid for the current context, and removed the old add_constraint() function.
* Buttons window updates correctly after adding keyframes now
Keyframes Drawing:
* Removed un-necessary extra function-call for RB-Tree implementation, by inlining a special one-off case.
* Keyframe diamonds which are not within the viewable area are now not drawn (but filtering will still need to find them).
-rw-r--r-- | source/blender/blenlib/intern/DLRB_tree.c | 48 | ||||
-rw-r--r-- | source/blender/editors/animation/keyframes_draw.c | 28 | ||||
-rw-r--r-- | source/blender/editors/armature/armature_ops.c | 5 | ||||
-rw-r--r-- | source/blender/editors/object/editconstraint.c | 409 | ||||
-rw-r--r-- | source/blender/editors/object/object_intern.h | 2 | ||||
-rw-r--r-- | source/blender/editors/object/object_ops.c | 8 | ||||
-rw-r--r-- | source/blender/editors/space_buttons/space_buttons.c | 1 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_header.c | 2 |
8 files changed, 125 insertions, 378 deletions
diff --git a/source/blender/blenlib/intern/DLRB_tree.c b/source/blender/blenlib/intern/DLRB_tree.c index 766547cee05..af9774c6afd 100644 --- a/source/blender/blenlib/intern/DLRB_tree.c +++ b/source/blender/blenlib/intern/DLRB_tree.c @@ -161,7 +161,6 @@ static DLRBT_Node *get_uncle (DLRBT_Node *node) /* *********************************************** */ /* Tree Rotation Utilities */ -/* Left Rotation is only done for Right-Right Case, and Left-Right Case */ static void rotate_left (DLRBT_Tree *tree, DLRBT_Node *root) { DLRBT_Node **root_slot, *pivot; @@ -235,7 +234,6 @@ static void rotate_right (DLRBT_Tree *tree, DLRBT_Node *root) static void insert_check_1(DLRBT_Tree *tree, DLRBT_Node *node); static void insert_check_2(DLRBT_Tree *tree, DLRBT_Node *node); static void insert_check_3(DLRBT_Tree *tree, DLRBT_Node *node); -static void insert_check_4(DLRBT_Tree *tree, DLRBT_Node *node); /* ----- */ @@ -286,7 +284,7 @@ static void insert_check_2 (DLRBT_Tree *tree, DLRBT_Node *node) } } -/* W. 4) Perform rotation on sub-tree containing the 'new' node */ +/* W. 4+5) Perform rotation on sub-tree containing the 'new' node, then do any */ static void insert_check_3 (DLRBT_Tree *tree, DLRBT_Node *node) { DLRBT_Node *gp= get_grandparent(node); @@ -305,34 +303,30 @@ static void insert_check_3 (DLRBT_Tree *tree, DLRBT_Node *node) rotate_right(tree, node); node= node->right; } - // TODO: what about other cases? - /* fix old parent's color-tagging */ - insert_check_4(tree, node); + /* fix old parent's color-tagging, and perform rotation on the old parent in the + * opposite direction if needed for the current situation + * NOTE: in the code above, node pointer is changed to point to the old parent + */ + if (node) { + /* get 'new' grandparent (i.e. grandparent for old-parent (node)) */ + gp= get_grandparent(node); + + /* modify the coloring of the grandparent and parent so that they still satisfy the constraints */ + node->parent->tree_col= DLRBT_BLACK; + gp->tree_col= DLRBT_RED; + + /* if there are several nodes that all form a left chain, do a right rotation to correct this + * (or a rotation in the opposite direction if they all form a right chain) + */ + if ((node == node->parent->left) && (node->parent == gp->left)) + rotate_right(tree, gp); + else //if ((node == node->parent->right) && (node->parent == gp->right)) + rotate_left(tree, gp); + } } } -/* W. 5) Perform rotation in the opposite direction on the parent of the given node */ -static void insert_check_4 (DLRBT_Tree *tree, DLRBT_Node *node) -{ - DLRBT_Node *gp= get_grandparent(node); - - if (node == NULL) - return; - - /* modify the coloring of the grandparent and parent so that they still satisfy the constraints */ - node->parent->tree_col= DLRBT_BLACK; - gp->tree_col= DLRBT_RED; - - /* if there are several nodes that all form a left chain, do a right rotation to correct this - * (or a rotation in the opposite direction if they all form a right chain) - */ - if ((node == node->parent->left) && (node->parent == gp->left)) - rotate_right(tree, gp); - else /* ((node == node->parent->right) && (node->parent == gp->right)) */ - rotate_left(tree, gp); -} - /* ----- */ /* Balance the tree after the given element has been added to it diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c index 78ceb4a0149..2107e6e4252 100644 --- a/source/blender/editors/animation/keyframes_draw.c +++ b/source/blender/editors/animation/keyframes_draw.c @@ -445,28 +445,16 @@ static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, floa /* draw keys */ if (keys) { for (ak= keys->first; ak; ak= ak->next) { + /* optimisation: if keyframe doesn't appear within 5 units (screenspace) in visible area, don't draw + * - this might give some improvements, since we current have to flip between view/region matrices + */ + if (IN_RANGE_INCL(ak->cfra, v2d->cur.xmin, v2d->cur.xmax) == 0) + continue; + /* draw using OpenGL - uglier but faster */ - // NOTE: a previous version of this didn't work nice for some intel cards + // NOTE1: a previous version of this didn't work nice for some intel cards + // NOTE2: if we wanted to go back to icons, these are icon = (ak->sel & SELECT) ? ICON_SPACE2 : ICON_SPACE3; draw_keyframe_shape(ak->cfra, ypos, xscale, 5.0f, (ak->sel & SELECT), KEYFRAME_SHAPE_BOTH); - -#if 0 // OLD CODE - //int sc_x, sc_y; - - /* get co-ordinate to draw at */ - //gla2DDrawTranslatePt(di, ak->cfra, ypos, &sc_x, &sc_y); - - /* draw using icons - old way which is slower but more proven */ - //if (ak->sel & SELECT) UI_icon_draw_aspect((float)sc_x-7, (float)sc_y-6, ICON_SPACE2, 1.0f); - //else UI_icon_draw_aspect((float)sc_x-7, (float)sc_y-6, ICON_SPACE3, 1.0f); -#endif // OLD CODE -#if 0 // NEW NON-WORKING CODE - /* draw icon */ - // FIXME: this draws slightly wrong, as we need to apply some offset for icon, but that depends on scaling - // so for now disabled - //int icon = (ak->sel & SELECT) ? ICON_SPACE2 : ICON_SPACE3; - //UI_icon_draw_aspect(ak->cfra, ypos-6, icon, 1.0f); -#endif // NEW NON-WORKING CODE - } } diff --git a/source/blender/editors/armature/armature_ops.c b/source/blender/editors/armature/armature_ops.c index df32f452a38..a8a342451cc 100644 --- a/source/blender/editors/armature/armature_ops.c +++ b/source/blender/editors/armature/armature_ops.c @@ -251,6 +251,11 @@ 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); + // 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/object/editconstraint.c b/source/blender/editors/object/editconstraint.c index e3ec72b502c..b0890f5858d 100644 --- a/source/blender/editors/object/editconstraint.c +++ b/source/blender/editors/object/editconstraint.c @@ -77,9 +77,6 @@ #include "object_intern.h" /* XXX */ -static void BIF_undo_push() {} -static void error() {} -static int okee() {return 0;} static int pupmenu() {return 0;} /* -------------- Get Active Constraint Data ---------------------- */ @@ -273,255 +270,6 @@ static void set_constraint_nth_target (bConstraint *con, Object *target, char su } } -/* context: active object in posemode, active channel, optional selected channel */ -void add_constraint (Scene *scene, View3D *v3d, short only_IK) -{ - Object *ob= OBACT, *obsel=NULL; - bPoseChannel *pchanact=NULL, *pchansel=NULL; - bConstraint *con=NULL; - Base *base; - short nr; - - /* paranoia checks */ - if ((ob==NULL) || (ob==scene->obedit)) - return; - - if ((ob->pose) && (ob->flag & OB_POSEMODE)) { - bArmature *arm= ob->data; - - /* find active channel */ - pchanact= get_active_posechannel(ob); - if (pchanact==NULL) - return; - - /* find selected bone */ - for (pchansel=ob->pose->chanbase.first; pchansel; pchansel=pchansel->next) { - if (pchansel != pchanact) { - if (pchansel->bone->flag & BONE_SELECTED) { - if (pchansel->bone->layer & arm->layer) - break; - } - } - } - } - - /* find selected object */ - for (base= FIRSTBASE; base; base= base->next) { - if ((TESTBASE(v3d, base)) && (base->object!=ob)) - obsel= base->object; - } - - /* the only_IK caller has checked for posemode! */ - if (only_IK) { - for (con= pchanact->constraints.first; con; con= con->next) { - if (con->type==CONSTRAINT_TYPE_KINEMATIC) break; - } - if (con) { - error("Pose Channel already has IK"); - return; - } - - if (pchansel) - nr= pupmenu("Add IK Constraint%t|To Active Bone%x10"); - else if (obsel) - nr= pupmenu("Add IK Constraint%t|To Active Object%x10"); - else - nr= pupmenu("Add IK Constraint%t|To New Empty Object%x10|Without Target%x11"); - } - else { - if (pchanact) { - if (pchansel) - nr= pupmenu("Add Constraint to Active Bone%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Action%x16|Script%x18"); - else if ((obsel) && (obsel->type==OB_CURVE)) - nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6|Clamp To%x17|Stretch To%x7|%l|Action%x16|Script%x18"); - else if ((obsel) && (obsel->type==OB_MESH)) - nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Shrinkwrap%x22|Stretch To%x7|%l|Action%x16|Script%x18"); - else if (obsel) - nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Action%x16|Script%x18"); - else - nr= pupmenu("Add Constraint to New Empty Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Action%x16|Script%x18"); - } - else { - if ((obsel) && (obsel->type==OB_CURVE)) - nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6|Clamp To%x17|%l|Action%x16|Script%x18"); - else if ((obsel) && (obsel->type==OB_MESH)) - nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Shrinkwrap%x22|%l|Action%x16|Script%x18"); - else if (obsel) - nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|%l|Action%x16|Script%x18"); - else - nr= pupmenu("Add Constraint to New Empty Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|%l|Action%x16|Script%x18"); - } - } - - if (nr < 1) return; - - /* handle IK separate */ - if (nr==10 || nr==11) { - /* ik - prevent weird chains... */ - if (pchansel) { - bPoseChannel *pchan= pchanact; - while (pchan) { - if (pchan==pchansel) break; - pchan= pchan->parent; - } - if (pchan) { - error("IK root cannot be linked to IK tip"); - return; - } - - pchan= pchansel; - while (pchan) { - if (pchan==pchanact) break; - pchan= pchan->parent; - } - if (pchan) { - error("IK tip cannot be linked to IK root"); - return; - } - } - - con = add_new_constraint(CONSTRAINT_TYPE_KINEMATIC); - BLI_addtail(&pchanact->constraints, con); - unique_constraint_name(con, &pchanact->constraints); - pchanact->constflag |= PCHAN_HAS_IK; /* for draw, but also for detecting while pose solving */ - if (nr==11) - pchanact->constflag |= PCHAN_HAS_TARGET; - if (proxylocked_constraints_owner(ob, pchanact)) - con->flag |= CONSTRAINT_PROXY_LOCAL; - } - else { - /* normal constraints - add data */ - if (nr==1) con = add_new_constraint(CONSTRAINT_TYPE_LOCLIKE); - else if (nr==2) con = add_new_constraint(CONSTRAINT_TYPE_ROTLIKE); - else if (nr==3) con = add_new_constraint(CONSTRAINT_TYPE_TRACKTO); - else if (nr==4) con = add_new_constraint(CONSTRAINT_TYPE_MINMAX); - else if (nr==5) con = add_new_constraint(CONSTRAINT_TYPE_LOCKTRACK); - else if (nr==6) { - Curve *cu= obsel->data; - cu->flag |= CU_PATH; - con = add_new_constraint(CONSTRAINT_TYPE_FOLLOWPATH); - } - else if (nr==7) con = add_new_constraint(CONSTRAINT_TYPE_STRETCHTO); - else if (nr==8) con = add_new_constraint(CONSTRAINT_TYPE_SIZELIKE); - else if (nr==13) con = add_new_constraint(CONSTRAINT_TYPE_LOCLIMIT); - else if (nr==14) con = add_new_constraint(CONSTRAINT_TYPE_ROTLIMIT); - else if (nr==15) con = add_new_constraint(CONSTRAINT_TYPE_SIZELIMIT); - else if (nr==16) { - /* TODO: add a popup-menu to display list of available actions to use (like for pyconstraints) */ - con = add_new_constraint(CONSTRAINT_TYPE_ACTION); - } - else if (nr==17) { - Curve *cu= obsel->data; - cu->flag |= CU_PATH; - con = add_new_constraint(CONSTRAINT_TYPE_CLAMPTO); - } - else if (nr==18) { - char *menustr; - int scriptint= 0; -#ifndef DISABLE_PYTHON - /* popup a list of usable scripts */ - menustr = buildmenu_pyconstraints(NULL, &scriptint); - scriptint = pupmenu(menustr); - MEM_freeN(menustr); - - /* only add constraint if a script was chosen */ - if (scriptint) { - /* add constraint */ - con = add_new_constraint(CONSTRAINT_TYPE_PYTHON); - validate_pyconstraint_cb(con->data, &scriptint); - - /* make sure target allowance is set correctly */ - BPY_pyconstraint_update(ob, con); - } -#endif - } - else if (nr==19) { - con = add_new_constraint(CONSTRAINT_TYPE_CHILDOF); - - /* if this constraint is being added to a posechannel, make sure - * the constraint gets evaluated in pose-space - */ - if (pchanact) { - con->ownspace = CONSTRAINT_SPACE_POSE; - con->flag |= CONSTRAINT_SPACEONCE; - } - } - else if (nr==20) con = add_new_constraint(CONSTRAINT_TYPE_TRANSFORM); - else if (nr==21) con = add_new_constraint(CONSTRAINT_TYPE_DISTLIMIT); - else if (nr==22) con = add_new_constraint(CONSTRAINT_TYPE_SHRINKWRAP); - - if (con==NULL) return; /* paranoia */ - - if (pchanact) { - BLI_addtail(&pchanact->constraints, con); - unique_constraint_name(con, &pchanact->constraints); - pchanact->constflag |= PCHAN_HAS_CONST; /* for draw */ - if (proxylocked_constraints_owner(ob, pchanact)) - con->flag |= CONSTRAINT_PROXY_LOCAL; - } - else { - BLI_addtail(&ob->constraints, con); - unique_constraint_name(con, &ob->constraints); - if (proxylocked_constraints_owner(ob, NULL)) - con->flag |= CONSTRAINT_PROXY_LOCAL; - } - } - - /* set the target */ - if (pchansel) { - set_constraint_nth_target(con, ob, pchansel->name, 0); - } - else if (obsel) { - set_constraint_nth_target(con, obsel, "", 0); - } - else if (ELEM4(nr, 11, 13, 14, 15)==0) { /* add new empty as target */ - Base *base= BASACT, *newbase; - Object *obt; - - obt= add_object(scene, OB_EMPTY); - /* set layers OK */ - newbase= BASACT; - newbase->lay= base->lay; - obt->lay= newbase->lay; - - /* transform cent to global coords for loc */ - if (pchanact) { - if (only_IK) - VecMat4MulVecfl(obt->loc, ob->obmat, pchanact->pose_tail); - else - VecMat4MulVecfl(obt->loc, ob->obmat, pchanact->pose_head); - } - else - VECCOPY(obt->loc, ob->obmat[3]); - - set_constraint_nth_target(con, obt, "", 0); - - /* restore, add_object sets active */ - BASACT= base; - base->flag |= SELECT; - } - - /* active flag */ - con->flag |= CONSTRAINT_ACTIVE; - for (con= con->prev; con; con= con->prev) - con->flag &= ~CONSTRAINT_ACTIVE; - - DAG_scene_sort(scene); // sort order of objects - - if (pchanact) { - ob->pose->flag |= POSE_RECALC; // sort pose channels - DAG_object_flush_update(scene, ob, OB_RECALC_DATA); // and all its relations - } - else - DAG_object_flush_update(scene, ob, OB_RECALC_OB); // and all its relations - - if (only_IK) - BIF_undo_push("Add IK Constraint"); - else - BIF_undo_push("Add Constraint"); - -} - /* ------------- Constraint Sanity Testing ------------------- */ /* checks validity of object pointers, and NULLs, @@ -1177,14 +925,24 @@ static short get_new_constraint_target(bContext *C, int con_type, Object **tar_o } /* used by add constraint operators to add the constraint required */ -static int constraint_add_exec(bContext *C, wmOperator *op, ListBase *list) +static int constraint_add_exec(bContext *C, wmOperator *op, Object *ob, ListBase *list, int type, short setTarget) { Scene *scene= CTX_data_scene(C); - Object *ob = CTX_data_active_object(C); bPoseChannel *pchan= get_active_posechannel(ob); bConstraint *con; - int type= RNA_enum_get(op->ptr, "type"); - int setTarget= RNA_boolean_get(op->ptr, "set_targets"); + + /* check if constraint to be added is valid for the given constraints stack */ + if (type == CONSTRAINT_TYPE_NULL) { + return OPERATOR_CANCELLED; + } + if ( (type == CONSTRAINT_TYPE_RIGIDBODYJOINT) && (list != &ob->constraints) ) { + BKE_report(op->reports, RPT_ERROR, "Rigid Body Joint Constraint can only be added to Objects."); + return OPERATOR_CANCELLED; + } + if ( (type == CONSTRAINT_TYPE_KINEMATIC) && ((!pchan) || (list != &pchan->constraints)) ) { + BKE_report(op->reports, RPT_ERROR, "IK Constraint can only be added to Bones."); + return OPERATOR_CANCELLED; + } /* create a new constraint of the type requried, and add it to the active/given constraints list */ con = add_new_constraint(type); @@ -1295,103 +1053,64 @@ static int constraint_add_exec(bContext *C, wmOperator *op, ListBase *list) /* ------------------ */ -#if 0 // BUGGY -/* for object cosntraints, don't include NULL or IK for now */ -static int object_constraint_add_invoke(bContext *C, wmOperator *op, wmEvent *evt) -{ - EnumPropertyItem *item; - uiPopupMenu *pup; - uiLayout *layout; - int i, totitem; - - pup= uiPupMenuBegin(C, "Add Constraint", 0); - layout= uiPupMenuLayout(pup); - - /* loop over the constraint-types as defined in the enum - * - code below is based on the code used for WM_menu_invoke() - */ - totitem= sizeof(&constraint_type_items[0]) / sizeof(EnumPropertyItem); - item= constraint_type_items; - - for (i=0; i < totitem; i++) { - if (ELEM(item[i].value, CONSTRAINT_TYPE_NULL, CONSTRAINT_TYPE_KINEMATIC) == 0) { - if (item[i].identifier[0]) - uiItemEnumO(layout, (char*)item[i].name, item[i].icon, "OBJECT_OT_constraint_add", "type", item[i].value); - else - uiItemS(layout); - } - } - - uiPupMenuEnd(C, pup); -} -#endif // BUGGY - /* dummy operator callback */ static int object_constraint_add_exec(bContext *C, wmOperator *op) { ScrArea *sa= CTX_wm_area(C); Object *ob; + int type= RNA_enum_get(op->ptr, "type"); + short with_targets= 0; + /* get active object from context */ if (sa->spacetype == SPACE_BUTS) ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; else ob= CTX_data_active_object(C); - if (!ob) + if (!ob) { + BKE_report(op->reports, RPT_ERROR, "No active object to add constraint to."); return OPERATOR_CANCELLED; - - return constraint_add_exec(C, op, &ob->constraints); -} - -#if 0 // BUGGY -/* for bone constraints, don't include NULL for now */ -static int pose_constraint_add_invoke(bContext *C, wmOperator *op, wmEvent *evt) -{ - EnumPropertyItem *item; - uiPopupMenu *pup; - uiLayout *layout; - int i, totitem; - - pup= uiPupMenuBegin(C, "Add Constraint", 0); - layout= uiPupMenuLayout(pup); - - /* loop over the constraint-types as defined in the enum - * - code below is based on the code used for WM_menu_invoke() - */ - totitem= sizeof(&constraint_type_items[0]) / sizeof(EnumPropertyItem); - item= constraint_type_items; - - for (i=0; i < totitem; i++) { - // TODO: can add some other conditions here... - if (item[i].value != CONSTRAINT_TYPE_NULL) { - if (item[i].identifier[0]) - uiItemEnumO(layout, (char*)item[i].name, item[i].icon, "POSE_OT_constraint_add", "type", item[i].value); - else - uiItemS(layout); - } } - - uiPupMenuEnd(C, pup); + + /* hack: set constraint targets from selected objects in context is allowed when + * operator name included 'with_targets', since the menu doesn't allow multiple properties + */ + if (strstr(op->idname, "with_targets")) + with_targets= 1; + + return constraint_add_exec(C, op, ob, &ob->constraints, type, with_targets); } -#endif // BUGGY /* dummy operator callback */ static int pose_constraint_add_exec(bContext *C, wmOperator *op) { ScrArea *sa= CTX_wm_area(C); Object *ob; + int type= RNA_enum_get(op->ptr, "type"); + short with_targets= 0; + /* get active object from context */ if (sa->spacetype == SPACE_BUTS) ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; else ob= CTX_data_active_object(C); - if (!ob) + if (!ob) { + BKE_report(op->reports, RPT_ERROR, "No active object to add constraint to."); return OPERATOR_CANCELLED; + } + + /* hack: set constraint targets from selected objects in context is allowed when + * operator name included 'with_targets', since the menu doesn't allow multiple properties + */ + if (strstr(op->idname, "with_targets")) + with_targets= 1; - return constraint_add_exec(C, op, get_active_constraints(ob)); + return constraint_add_exec(C, op, ob, get_active_constraints(ob), type, with_targets); } +/* ------------------ */ + void OBJECT_OT_constraint_add(wmOperatorType *ot) { /* identifiers */ @@ -1400,7 +1119,26 @@ void OBJECT_OT_constraint_add(wmOperatorType *ot) ot->idname= "OBJECT_OT_constraint_add"; /* api callbacks */ - ot->invoke= WM_menu_invoke;//object_constraint_add_invoke; + ot->invoke= WM_menu_invoke; + ot->exec= object_constraint_add_exec; + ot->poll= ED_operator_object_active; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties */ + RNA_def_enum(ot->srna, "type", constraint_type_items, 0, "Type", ""); +} + +void OBJECT_OT_constraint_add_with_targets(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Add Constraint (with Targets)"; + ot->description = "Add a constraint to the active object, with target (where applicable) set to the selected Objects/Bones."; + ot->idname= "OBJECT_OT_constraint_add_with_targets"; + + /* api callbacks */ + ot->invoke= WM_menu_invoke; ot->exec= object_constraint_add_exec; ot->poll= ED_operator_object_active; @@ -1409,7 +1147,6 @@ void OBJECT_OT_constraint_add(wmOperatorType *ot) /* properties */ RNA_def_enum(ot->srna, "type", constraint_type_items, 0, "Type", ""); - RNA_def_boolean(ot->srna, "set_targets", 0, "Set Targets", "Set target info for new constraints from context."); } void POSE_OT_constraint_add(wmOperatorType *ot) @@ -1420,7 +1157,26 @@ void POSE_OT_constraint_add(wmOperatorType *ot) ot->idname= "POSE_OT_constraint_add"; /* api callbacks */ - ot->invoke= WM_menu_invoke; //pose_constraint_add_invoke; + ot->invoke= WM_menu_invoke; + ot->exec= pose_constraint_add_exec; + ot->poll= ED_operator_posemode; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties */ + RNA_def_enum(ot->srna, "type", constraint_type_items, 0, "Type", ""); +} + +void POSE_OT_constraint_add_with_targets(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Add Constraint (with Targets)"; + ot->description = "Add a constraint to the active bone, with target (where applicable) set to the selected Objects/Bones."; + ot->idname= "POSE_OT_constraint_add_with_targets"; + + /* api callbacks */ + ot->invoke= WM_menu_invoke; ot->exec= pose_constraint_add_exec; ot->poll= ED_operator_posemode; @@ -1429,6 +1185,5 @@ void POSE_OT_constraint_add(wmOperatorType *ot) /* properties */ RNA_def_enum(ot->srna, "type", constraint_type_items, 0, "Type", ""); - RNA_def_boolean(ot->srna, "set_targets", 0, "Set Targets", "Set target info for new constraints from context."); } diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index 99967858d8b..3feec87edca 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -102,7 +102,9 @@ void OBJECT_OT_modifier_mdef_bind(struct wmOperatorType *ot); /* editconstraint.c */ void OBJECT_OT_constraint_add(struct wmOperatorType *ot); +void OBJECT_OT_constraint_add_with_targets(struct wmOperatorType *ot); void POSE_OT_constraint_add(struct wmOperatorType *ot); +void POSE_OT_constraint_add_with_targets(struct wmOperatorType *ot); void OBJECT_OT_constraints_clear(struct wmOperatorType *ot); void POSE_OT_constraints_clear(struct wmOperatorType *ot); diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index 4bc60a6a91b..b8fb5f43ea4 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -112,7 +112,9 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_modifier_mdef_bind); WM_operatortype_append(OBJECT_OT_constraint_add); + WM_operatortype_append(OBJECT_OT_constraint_add_with_targets); WM_operatortype_append(POSE_OT_constraint_add); + WM_operatortype_append(POSE_OT_constraint_add_with_targets); WM_operatortype_append(OBJECT_OT_constraints_clear); WM_operatortype_append(POSE_OT_constraints_clear); WM_operatortype_append(CONSTRAINT_OT_delete); @@ -143,7 +145,7 @@ void ED_keymap_object(wmWindowManager *wm) /* Note: this keymap works disregarding mode */ WM_keymap_add_item(keymap, "OBJECT_OT_editmode_toggle", TABKEY, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "OBJECT_OT_center_set", CKEY, KM_PRESS, KM_ALT|KM_CTRL, 0); + WM_keymap_add_item(keymap, "OBJECT_OT_center_set", CKEY, KM_PRESS, KM_ALT|KM_SHIFT|KM_CTRL, 0); /* Note: this keymap gets disabled in non-objectmode, */ keymap= WM_keymap_listbase(wm, "Object Mode", 0, 0); @@ -158,8 +160,8 @@ void ED_keymap_object(wmWindowManager *wm) WM_keymap_verify_item(keymap, "OBJECT_OT_track_set", TKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_verify_item(keymap, "OBJECT_OT_track_clear", TKEY, KM_PRESS, KM_ALT, 0); - RNA_boolean_set(WM_keymap_verify_item(keymap, "OBJECT_OT_constraint_add", CKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "set_targets", 1); - WM_keymap_verify_item(keymap, "OBJECT_OT_constraints_clear", CKEY, KM_PRESS, /*KM_CTRL|*/KM_ALT, 0); + WM_keymap_verify_item(keymap, "OBJECT_OT_constraint_add_with_targets", CKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0); + WM_keymap_verify_item(keymap, "OBJECT_OT_constraints_clear", CKEY, KM_PRESS, KM_CTRL|KM_ALT, 0); WM_keymap_verify_item(keymap, "OBJECT_OT_location_clear", GKEY, KM_PRESS, KM_ALT, 0); WM_keymap_verify_item(keymap, "OBJECT_OT_rotation_clear", RKEY, KM_PRESS, KM_ALT, 0); diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c index 9345a24b198..4a741f85d85 100644 --- a/source/blender/editors/space_buttons/space_buttons.c +++ b/source/blender/editors/space_buttons/space_buttons.c @@ -326,6 +326,7 @@ static void buttons_area_listener(ScrArea *sa, wmNotifier *wmn) case ND_BONE_ACTIVE: case ND_BONE_SELECT: case ND_GEOM_SELECT: + case ND_CONSTRAINT: ED_area_tag_redraw(sa); break; case ND_SHADING: diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index 677d3c20de1..bdc6bdb5601 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -1993,7 +1993,7 @@ static void view3d_edit_object_trackmenu(bContext *C, uiLayout *layout, void *ar static void view3d_edit_object_constraintsmenu(bContext *C, uiLayout *layout, void *arg_unused) { - uiItemBooleanO(layout, NULL, 0, "OBJECT_OT_constraint_add", "set_targets", 1); // XXX it'd be better to have the version which sets links... + uiItemO(layout, NULL, 0, "OBJECT_OT_constraint_add_with_targets"); uiItemO(layout, NULL, 0, "OBJECT_OT_constraints_clear"); } |