|
Blender
V2.59
|
00001 /* 00002 * $Id: object_constraint.c 36473 2011-05-04 05:52:14Z campbellbarton $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00021 * All rights reserved. 00022 * 00023 * The Original Code is: all of this file. 00024 * 00025 * Contributor(s): Joshua Leung, Blender Foundation 00026 * 00027 * ***** END GPL LICENSE BLOCK ***** 00028 */ 00029 00035 #include <stdio.h> 00036 #include <string.h> 00037 00038 #include "MEM_guardedalloc.h" 00039 00040 #include "BLI_blenlib.h" 00041 #include "BLI_math.h" 00042 #include "BLI_dynstr.h" 00043 #include "BLI_utildefines.h" 00044 00045 #include "DNA_constraint_types.h" 00046 #include "DNA_curve_types.h" 00047 #include "DNA_scene_types.h" 00048 #include "DNA_text_types.h" 00049 #include "DNA_object_types.h" 00050 00051 #include "BKE_action.h" 00052 #include "BKE_armature.h" 00053 #include "BKE_constraint.h" 00054 #include "BKE_context.h" 00055 #include "BKE_depsgraph.h" 00056 #include "BKE_global.h" 00057 #include "BKE_main.h" 00058 #include "BKE_object.h" 00059 #include "BKE_report.h" 00060 #include "BIK_api.h" 00061 00062 #ifdef WITH_PYTHON 00063 #include "BPY_extern.h" 00064 #endif 00065 00066 #include "WM_api.h" 00067 #include "WM_types.h" 00068 00069 #include "RNA_access.h" 00070 #include "RNA_define.h" 00071 #include "RNA_enum_types.h" 00072 00073 #include "ED_object.h" 00074 #include "ED_armature.h" 00075 #include "ED_screen.h" 00076 00077 #include "UI_interface.h" 00078 #include "UI_resources.h" 00079 00080 #include "object_intern.h" 00081 00082 /* -------------- Get Active Constraint Data ---------------------- */ 00083 00084 /* if object in posemode, active bone constraints, else object constraints */ 00085 ListBase *get_active_constraints (Object *ob) 00086 { 00087 if (ob == NULL) 00088 return NULL; 00089 00090 if (ob->mode & OB_MODE_POSE) { 00091 bPoseChannel *pchan; 00092 00093 pchan = get_active_posechannel(ob); 00094 if (pchan) 00095 return &pchan->constraints; 00096 } 00097 else 00098 return &ob->constraints; 00099 00100 return NULL; 00101 } 00102 00103 /* Find the list that a given constraint belongs to, and/or also get the posechannel this is from (if applicable) */ 00104 ListBase *get_constraint_lb (Object *ob, bConstraint *con, bPoseChannel **pchan_r) 00105 { 00106 if (pchan_r) 00107 *pchan_r= NULL; 00108 00109 if (ELEM(NULL, ob, con)) 00110 return NULL; 00111 00112 /* try object constraints first */ 00113 if ((BLI_findindex(&ob->constraints, con) != -1)) { 00114 return &ob->constraints; 00115 } 00116 00117 /* if armature, try pose bones too */ 00118 if (ob->pose) { 00119 bPoseChannel *pchan; 00120 00121 /* try each bone in order 00122 * NOTE: it's not possible to directly look up the active bone yet, so this will have to do 00123 */ 00124 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { 00125 if ((BLI_findindex(&pchan->constraints, con) != -1)) { 00126 00127 if (pchan_r) 00128 *pchan_r= pchan; 00129 00130 return &pchan->constraints; 00131 } 00132 } 00133 } 00134 00135 /* done */ 00136 return NULL; 00137 } 00138 00139 /* single constraint */ 00140 bConstraint *get_active_constraint (Object *ob) 00141 { 00142 return constraints_get_active(get_active_constraints(ob)); 00143 } 00144 00145 /* -------------- Constraint Management (Add New, Remove, Rename) -------------------- */ 00146 /* ------------- PyConstraints ------------------ */ 00147 00148 /* this callback sets the text-file to be used for selected menu item */ 00149 static void validate_pyconstraint_cb (void *arg1, void *arg2) 00150 { 00151 bPythonConstraint *data = arg1; 00152 Text *text= NULL; 00153 int index = *((int *)arg2); 00154 int i; 00155 00156 /* exception for no script */ 00157 if (index) { 00158 /* innovative use of a for...loop to search */ 00159 for (text=G.main->text.first, i=1; text && index!=i; i++, text=text->id.next); 00160 } 00161 data->text = text; 00162 } 00163 00164 #ifdef WITH_PYTHON 00165 /* this returns a string for the list of usable pyconstraint script names */ 00166 static char *buildmenu_pyconstraints (Text *con_text, int *pyconindex) 00167 { 00168 DynStr *pupds= BLI_dynstr_new(); 00169 Text *text; 00170 char *str; 00171 char buf[64]; 00172 int i; 00173 00174 /* add title first */ 00175 sprintf(buf, "Scripts: %%t|[None]%%x0|"); 00176 BLI_dynstr_append(pupds, buf); 00177 00178 /* init active-index first */ 00179 if (con_text == NULL) 00180 *pyconindex= 0; 00181 00182 /* loop through markers, adding them */ 00183 for (text=G.main->text.first, i=1; text; i++, text=text->id.next) { 00184 /* this is important to ensure that right script is shown as active */ 00185 if (text == con_text) *pyconindex = i; 00186 00187 /* only include valid pyconstraint scripts */ 00188 if (BPY_is_pyconstraint(text)) { 00189 BLI_dynstr_append(pupds, text->id.name+2); 00190 00191 sprintf(buf, "%%x%d", i); 00192 BLI_dynstr_append(pupds, buf); 00193 00194 if (text->id.next) 00195 BLI_dynstr_append(pupds, "|"); 00196 } 00197 } 00198 00199 /* convert to normal MEM_malloc'd string */ 00200 str= BLI_dynstr_get_cstring(pupds); 00201 BLI_dynstr_free(pupds); 00202 00203 return str; 00204 } 00205 #endif /* WITH_PYTHON */ 00206 00207 #if 0 // UNUSED, until pyconstraints are added back. 00208 /* this callback gets called when the 'refresh' button of a pyconstraint gets pressed */ 00209 static void update_pyconstraint_cb (void *arg1, void *arg2) 00210 { 00211 #ifndef WITH_PYTHON 00212 (void)arg1; /* unused */ 00213 (void)arg2; /* unused */ 00214 #else 00215 Object *owner= (Object *)arg1; 00216 bConstraint *con= (bConstraint *)arg2; 00217 if (owner && con) 00218 BPY_pyconstraint_update(owner, con); 00219 #endif 00220 } 00221 #endif // UNUSED 00222 00223 /* helper function for add_constriant - sets the last target for the active constraint */ 00224 static void set_constraint_nth_target (bConstraint *con, Object *target, const char subtarget[], int index) 00225 { 00226 bConstraintTypeInfo *cti= constraint_get_typeinfo(con); 00227 ListBase targets = {NULL, NULL}; 00228 bConstraintTarget *ct; 00229 int num_targets, i; 00230 00231 if (cti && cti->get_constraint_targets) { 00232 cti->get_constraint_targets(con, &targets); 00233 num_targets= BLI_countlist(&targets); 00234 00235 if (index < 0) { 00236 if (abs(index) < num_targets) 00237 index= num_targets - abs(index); 00238 else 00239 index= num_targets - 1; 00240 } 00241 else if (index >= num_targets) { 00242 index= num_targets - 1; 00243 } 00244 00245 for (ct=targets.first, i=0; ct; ct= ct->next, i++) { 00246 if (i == index) { 00247 ct->tar= target; 00248 strcpy(ct->subtarget, subtarget); 00249 break; 00250 } 00251 } 00252 00253 if (cti->flush_constraint_targets) 00254 cti->flush_constraint_targets(con, &targets, 0); 00255 } 00256 } 00257 00258 /* ------------- Constraint Sanity Testing ------------------- */ 00259 00260 /* checks validity of object pointers, and NULLs, 00261 * if Bone doesnt exist it sets the CONSTRAINT_DISABLE flag. 00262 */ 00263 static void test_constraints (Object *owner, bPoseChannel *pchan) 00264 { 00265 bConstraint *curcon; 00266 ListBase *conlist= NULL; 00267 int type; 00268 00269 if (owner==NULL) return; 00270 00271 /* Check parents */ 00272 if (pchan) { 00273 switch (owner->type) { 00274 case OB_ARMATURE: 00275 type = CONSTRAINT_OBTYPE_BONE; 00276 break; 00277 default: 00278 type = CONSTRAINT_OBTYPE_OBJECT; 00279 break; 00280 } 00281 } 00282 else 00283 type = CONSTRAINT_OBTYPE_OBJECT; 00284 00285 /* Get the constraint list for this object */ 00286 switch (type) { 00287 case CONSTRAINT_OBTYPE_OBJECT: 00288 conlist = &owner->constraints; 00289 break; 00290 case CONSTRAINT_OBTYPE_BONE: 00291 conlist = &pchan->constraints; 00292 break; 00293 } 00294 00295 /* Check all constraints - is constraint valid? */ 00296 if (conlist) { 00297 for (curcon = conlist->first; curcon; curcon=curcon->next) { 00298 bConstraintTypeInfo *cti= constraint_get_typeinfo(curcon); 00299 ListBase targets = {NULL, NULL}; 00300 bConstraintTarget *ct; 00301 00302 /* clear disabled-flag first */ 00303 curcon->flag &= ~CONSTRAINT_DISABLE; 00304 00305 if (curcon->type == CONSTRAINT_TYPE_KINEMATIC) { 00306 bKinematicConstraint *data = curcon->data; 00307 00308 /* bad: we need a separate set of checks here as poletarget is 00309 * optional... otherwise poletarget must exist too or else 00310 * the constraint is deemed invalid 00311 */ 00312 /* default IK check ... */ 00313 if (exist_object(data->tar) == 0) { 00314 data->tar = NULL; 00315 curcon->flag |= CONSTRAINT_DISABLE; 00316 } 00317 else if (data->tar == owner) { 00318 if (!get_named_bone(get_armature(owner), data->subtarget)) { 00319 curcon->flag |= CONSTRAINT_DISABLE; 00320 } 00321 } 00322 00323 if (data->poletar) { 00324 if (exist_object(data->poletar) == 0) { 00325 data->poletar = NULL; 00326 curcon->flag |= CONSTRAINT_DISABLE; 00327 } 00328 else if (data->poletar == owner) { 00329 if (!get_named_bone(get_armature(owner), data->polesubtarget)) { 00330 curcon->flag |= CONSTRAINT_DISABLE; 00331 } 00332 } 00333 } 00334 /* ... can be overwritten here */ 00335 BIK_test_constraint(owner, curcon); 00336 /* targets have already been checked for this */ 00337 continue; 00338 } 00339 else if (curcon->type == CONSTRAINT_TYPE_PIVOT) { 00340 bPivotConstraint *data = curcon->data; 00341 00342 /* target doesn't have to exist, but if it is non-null, it must exist! */ 00343 if (data->tar && exist_object(data->tar)==0) { 00344 data->tar = NULL; 00345 curcon->flag |= CONSTRAINT_DISABLE; 00346 } 00347 else if (data->tar == owner) { 00348 if (!get_named_bone(get_armature(owner), data->subtarget)) { 00349 curcon->flag |= CONSTRAINT_DISABLE; 00350 } 00351 } 00352 00353 /* targets have already been checked for this */ 00354 continue; 00355 } 00356 else if (curcon->type == CONSTRAINT_TYPE_ACTION) { 00357 bActionConstraint *data = curcon->data; 00358 00359 /* validate action */ 00360 if (data->act == NULL) 00361 curcon->flag |= CONSTRAINT_DISABLE; 00362 } 00363 else if (curcon->type == CONSTRAINT_TYPE_FOLLOWPATH) { 00364 bFollowPathConstraint *data = curcon->data; 00365 00366 /* don't allow track/up axes to be the same */ 00367 if (data->upflag==data->trackflag) 00368 curcon->flag |= CONSTRAINT_DISABLE; 00369 if (data->upflag+3==data->trackflag) 00370 curcon->flag |= CONSTRAINT_DISABLE; 00371 } 00372 else if (curcon->type == CONSTRAINT_TYPE_TRACKTO) { 00373 bTrackToConstraint *data = curcon->data; 00374 00375 /* don't allow track/up axes to be the same */ 00376 if (data->reserved2==data->reserved1) 00377 curcon->flag |= CONSTRAINT_DISABLE; 00378 if (data->reserved2+3==data->reserved1) 00379 curcon->flag |= CONSTRAINT_DISABLE; 00380 } 00381 else if (curcon->type == CONSTRAINT_TYPE_LOCKTRACK) { 00382 bLockTrackConstraint *data = curcon->data; 00383 00384 if (data->lockflag==data->trackflag) 00385 curcon->flag |= CONSTRAINT_DISABLE; 00386 if (data->lockflag+3==data->trackflag) 00387 curcon->flag |= CONSTRAINT_DISABLE; 00388 } 00389 else if (curcon->type == CONSTRAINT_TYPE_SPLINEIK) { 00390 bSplineIKConstraint *data = curcon->data; 00391 00392 /* if the number of points does not match the amount required by the chain length, 00393 * free the points array and request a rebind... 00394 */ 00395 if ((data->points == NULL) || (data->numpoints != data->chainlen+1)) 00396 { 00397 /* free the points array */ 00398 if (data->points) { 00399 MEM_freeN(data->points); 00400 data->points = NULL; 00401 } 00402 00403 /* clear the bound flag, forcing a rebind next time this is evaluated */ 00404 data->flag &= ~CONSTRAINT_SPLINEIK_BOUND; 00405 } 00406 } 00407 00408 /* Check targets for constraints */ 00409 if (cti && cti->get_constraint_targets) { 00410 cti->get_constraint_targets(curcon, &targets); 00411 00412 /* disable and clear constraints targets that are incorrect */ 00413 for (ct= targets.first; ct; ct= ct->next) { 00414 /* general validity checks (for those constraints that need this) */ 00415 if (exist_object(ct->tar) == 0) { 00416 /* object doesn't exist, but constraint requires target */ 00417 ct->tar = NULL; 00418 curcon->flag |= CONSTRAINT_DISABLE; 00419 } 00420 else if (ct->tar == owner) { 00421 if (type == CONSTRAINT_OBTYPE_BONE) { 00422 if (!get_named_bone(get_armature(owner), ct->subtarget)) { 00423 /* bone must exist in armature... */ 00424 // TODO: clear subtarget? 00425 curcon->flag |= CONSTRAINT_DISABLE; 00426 } 00427 else if (strcmp(pchan->name, ct->subtarget) == 0) { 00428 /* cannot target self */ 00429 ct->subtarget[0] = '\0'; 00430 curcon->flag |= CONSTRAINT_DISABLE; 00431 } 00432 } 00433 else { 00434 /* cannot use self as target */ 00435 ct->tar = NULL; 00436 curcon->flag |= CONSTRAINT_DISABLE; 00437 } 00438 } 00439 00440 /* target checks for specific constraints */ 00441 if (ELEM3(curcon->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO, CONSTRAINT_TYPE_SPLINEIK)) { 00442 if (ct->tar) { 00443 if (ct->tar->type != OB_CURVE) { 00444 ct->tar= NULL; 00445 curcon->flag |= CONSTRAINT_DISABLE; 00446 } 00447 else { 00448 Curve *cu= ct->tar->data; 00449 00450 /* auto-set 'Path' setting on curve so this works */ 00451 cu->flag |= CU_PATH; 00452 } 00453 } 00454 } 00455 } 00456 00457 /* free any temporary targets */ 00458 if (cti->flush_constraint_targets) 00459 cti->flush_constraint_targets(curcon, &targets, 0); 00460 } 00461 } 00462 } 00463 } 00464 00465 void object_test_constraints (Object *owner) 00466 { 00467 if (owner->constraints.first) 00468 test_constraints(owner, NULL); 00469 00470 if (owner->type==OB_ARMATURE && owner->pose) { 00471 bPoseChannel *pchan; 00472 00473 for (pchan= owner->pose->chanbase.first; pchan; pchan= pchan->next) { 00474 if (pchan->constraints.first) 00475 test_constraints(owner, pchan); 00476 } 00477 } 00478 } 00479 00480 00481 /************************ generic functions for operators using constraint names and data context *********************/ 00482 00483 #define EDIT_CONSTRAINT_OWNER_OBJECT 0 00484 #define EDIT_CONSTRAINT_OWNER_BONE 1 00485 00486 static EnumPropertyItem constraint_owner_items[] = { 00487 {EDIT_CONSTRAINT_OWNER_OBJECT, "OBJECT", 0, "Object", "Edit a constraint on the active object"}, 00488 {EDIT_CONSTRAINT_OWNER_BONE, "BONE", 0, "Bone", "Edit a constraint on the active bone"}, 00489 {0, NULL, 0, NULL, NULL}}; 00490 00491 00492 static int edit_constraint_poll_generic(bContext *C, StructRNA *rna_type) 00493 { 00494 PointerRNA ptr= CTX_data_pointer_get_type(C, "constraint", rna_type); 00495 Object *ob= (ptr.id.data) ? ptr.id.data : ED_object_active_context(C); 00496 00497 if (!ob || ob->id.lib) return 0; 00498 if (ptr.id.data && ((ID*)ptr.id.data)->lib) return 0; 00499 00500 return 1; 00501 } 00502 00503 static int edit_constraint_poll(bContext *C) 00504 { 00505 return edit_constraint_poll_generic(C, &RNA_Constraint); 00506 } 00507 00508 static void edit_constraint_properties(wmOperatorType *ot) 00509 { 00510 RNA_def_string(ot->srna, "constraint", "", 32, "Constraint", "Name of the constraint to edit"); 00511 RNA_def_enum(ot->srna, "owner", constraint_owner_items, 0, "Owner", "The owner of this constraint"); 00512 } 00513 00514 static int edit_constraint_invoke_properties(bContext *C, wmOperator *op) 00515 { 00516 PointerRNA ptr= CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint); 00517 Object *ob= (ptr.id.data)?ptr.id.data:ED_object_active_context(C); 00518 bConstraint *con; 00519 ListBase *list; 00520 00521 if (RNA_property_is_set(op->ptr, "constraint") && RNA_property_is_set(op->ptr, "owner")) 00522 return 1; 00523 00524 if (ptr.data) { 00525 con = ptr.data; 00526 RNA_string_set(op->ptr, "constraint", con->name); 00527 00528 list = get_constraint_lb(ob, con, NULL); 00529 00530 if (&ob->constraints == list) 00531 RNA_enum_set(op->ptr, "owner", EDIT_CONSTRAINT_OWNER_OBJECT); 00532 else 00533 RNA_enum_set(op->ptr, "owner", EDIT_CONSTRAINT_OWNER_BONE); 00534 00535 return 1; 00536 } 00537 00538 return 0; 00539 } 00540 00541 static bConstraint *edit_constraint_property_get(wmOperator *op, Object *ob, int type) 00542 { 00543 char constraint_name[32]; 00544 int owner = RNA_enum_get(op->ptr, "owner"); 00545 bConstraint *con; 00546 ListBase *list=NULL; 00547 00548 RNA_string_get(op->ptr, "constraint", constraint_name); 00549 00550 if (owner == EDIT_CONSTRAINT_OWNER_OBJECT) { 00551 list = &ob->constraints; 00552 } 00553 else if (owner == EDIT_CONSTRAINT_OWNER_BONE) { 00554 bPoseChannel *pchan= get_active_posechannel(ob); 00555 if (pchan) 00556 list = &pchan->constraints; 00557 else { 00558 //if (G.f & G_DEBUG) 00559 //printf("edit_constraint_property_get: No active bone for object '%s'\n", (ob)? ob->id.name+2 : "<None>"); 00560 return NULL; 00561 } 00562 } 00563 else { 00564 //if (G.f & G_DEBUG) 00565 //printf("edit_constraint_property_get: defaulting to getting list in the standard way\n"); 00566 list = get_active_constraints(ob); 00567 } 00568 00569 con = constraints_findByName(list, constraint_name); 00570 printf("constraint found = %p, %s\n", (void *)con, (con)?con->name:"<Not found>"); 00571 00572 if (con && (type != 0) && (con->type != type)) 00573 con = NULL; 00574 00575 return con; 00576 } 00577 00578 /* ********************** CONSTRAINT-SPECIFIC STUFF ********************* */ 00579 00580 /* ---------- Distance-Dependent Constraints ---------- */ 00581 /* StretchTo, Limit Distance */ 00582 00583 static int stretchto_reset_exec (bContext *C, wmOperator *op) 00584 { 00585 Object *ob = ED_object_active_context(C); 00586 bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_STRETCHTO); 00587 bStretchToConstraint *data= (con) ? (bStretchToConstraint *)con->data : NULL; 00588 00589 /* despite 3 layers of checks, we may still not be able to find a constraint */ 00590 if (data == NULL) 00591 return OPERATOR_CANCELLED; 00592 00593 /* just set original length to 0.0, which will cause a reset on next recalc */ 00594 data->orglength = 0.0f; 00595 ED_object_constraint_update(ob); 00596 00597 WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT, NULL); 00598 return OPERATOR_FINISHED; 00599 } 00600 00601 static int stretchto_reset_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) 00602 { 00603 if (edit_constraint_invoke_properties(C, op)) 00604 return stretchto_reset_exec(C, op); 00605 else 00606 return OPERATOR_CANCELLED; 00607 } 00608 00609 void CONSTRAINT_OT_stretchto_reset (wmOperatorType *ot) 00610 { 00611 /* identifiers */ 00612 ot->name= "Reset Original Length"; 00613 ot->idname= "CONSTRAINT_OT_stretchto_reset"; 00614 ot->description= "Reset original length of bone for Stretch To Constraint"; 00615 00616 ot->exec= stretchto_reset_exec; 00617 ot->invoke= stretchto_reset_invoke; 00618 ot->poll= edit_constraint_poll; 00619 00620 /* flags */ 00621 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00622 edit_constraint_properties(ot); 00623 } 00624 00625 00626 static int limitdistance_reset_exec (bContext *C, wmOperator *op) 00627 { 00628 Object *ob = ED_object_active_context(C); 00629 bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_DISTLIMIT); 00630 bDistLimitConstraint *data= (con) ? (bDistLimitConstraint *)con->data : NULL; 00631 00632 /* despite 3 layers of checks, we may still not be able to find a constraint */ 00633 if (data == NULL) 00634 return OPERATOR_CANCELLED; 00635 00636 /* just set original length to 0.0, which will cause a reset on next recalc */ 00637 data->dist = 0.0f; 00638 ED_object_constraint_update(ob); 00639 00640 WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT, NULL); 00641 return OPERATOR_FINISHED; 00642 } 00643 00644 static int limitdistance_reset_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) 00645 { 00646 if (edit_constraint_invoke_properties(C, op)) 00647 return limitdistance_reset_exec(C, op); 00648 else 00649 return OPERATOR_CANCELLED; 00650 } 00651 00652 void CONSTRAINT_OT_limitdistance_reset (wmOperatorType *ot) 00653 { 00654 /* identifiers */ 00655 ot->name= "Reset Distance"; 00656 ot->idname= "CONSTRAINT_OT_limitdistance_reset"; 00657 ot->description= "Reset limiting distance for Limit Distance Constraint"; 00658 00659 ot->exec= limitdistance_reset_exec; 00660 ot->invoke= limitdistance_reset_invoke; 00661 ot->poll= edit_constraint_poll; 00662 00663 /* flags */ 00664 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00665 edit_constraint_properties(ot); 00666 } 00667 00668 /* ------------- Child-Of Constraint ------------------ */ 00669 00670 /* ChildOf Constraint - set inverse callback */ 00671 static int childof_set_inverse_exec (bContext *C, wmOperator *op) 00672 { 00673 Scene *scene= CTX_data_scene(C); 00674 Object *ob = ED_object_active_context(C); 00675 bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_CHILDOF); 00676 bChildOfConstraint *data= (con) ? (bChildOfConstraint *)con->data : NULL; 00677 bPoseChannel *pchan= NULL; 00678 00679 /* despite 3 layers of checks, we may still not be able to find a constraint */ 00680 if (data == NULL) { 00681 printf("DEBUG: Child-Of Set Inverse - object = '%s'\n", (ob)? ob->id.name+2 : "<None>"); 00682 BKE_report(op->reports, RPT_ERROR, "Couldn't find constraint data for Child-Of Set Inverse"); 00683 return OPERATOR_CANCELLED; 00684 } 00685 00686 /* try to find a pose channel */ 00687 // TODO: get from context instead? 00688 if (ob && ob->pose) 00689 pchan= get_active_posechannel(ob); 00690 00691 /* calculate/set inverse matrix */ 00692 if (pchan) { 00693 float pmat[4][4], cinf; 00694 float imat[4][4], tmat[4][4]; 00695 00696 /* make copy of pchan's original pose-mat (for use later) */ 00697 copy_m4_m4(pmat, pchan->pose_mat); 00698 00699 /* disable constraint for pose to be solved without it */ 00700 cinf= con->enforce; 00701 con->enforce= 0.0f; 00702 00703 /* solve pose without constraint */ 00704 where_is_pose(scene, ob); 00705 00706 /* determine effect of constraint by removing the newly calculated 00707 * pchan->pose_mat from the original pchan->pose_mat, thus determining 00708 * the effect of the constraint 00709 */ 00710 invert_m4_m4(imat, pchan->pose_mat); 00711 mul_m4_m4m4(tmat, imat, pmat); 00712 invert_m4_m4(data->invmat, tmat); 00713 00714 /* recalculate pose with new inv-mat */ 00715 con->enforce= cinf; 00716 where_is_pose(scene, ob); 00717 } 00718 else if (ob) { 00719 Object workob; 00720 /* use what_does_parent to find inverse - just like for normal parenting. 00721 * NOTE: what_does_parent uses a static workob defined in object.c 00722 */ 00723 what_does_parent(scene, ob, &workob); 00724 invert_m4_m4(data->invmat, workob.obmat); 00725 } 00726 else 00727 unit_m4(data->invmat); 00728 00729 WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT, ob); 00730 00731 return OPERATOR_FINISHED; 00732 } 00733 00734 static int childof_set_inverse_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) 00735 { 00736 if (edit_constraint_invoke_properties(C, op)) 00737 return childof_set_inverse_exec(C, op); 00738 else 00739 return OPERATOR_CANCELLED; 00740 } 00741 00742 void CONSTRAINT_OT_childof_set_inverse (wmOperatorType *ot) 00743 { 00744 /* identifiers */ 00745 ot->name= "Set Inverse"; 00746 ot->idname= "CONSTRAINT_OT_childof_set_inverse"; 00747 ot->description= "Set inverse correction for ChildOf constraint"; 00748 00749 ot->exec= childof_set_inverse_exec; 00750 ot->invoke= childof_set_inverse_invoke; 00751 ot->poll= edit_constraint_poll; 00752 00753 /* flags */ 00754 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00755 edit_constraint_properties(ot); 00756 } 00757 00758 /* ChildOf Constraint - clear inverse callback */ 00759 static int childof_clear_inverse_exec (bContext *C, wmOperator *op) 00760 { 00761 Object *ob = ED_object_active_context(C); 00762 bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_CHILDOF); 00763 bChildOfConstraint *data= (con) ? (bChildOfConstraint *)con->data : NULL; 00764 00765 if(data==NULL) { 00766 BKE_report(op->reports, RPT_ERROR, "Childof constraint not found."); 00767 return OPERATOR_CANCELLED; 00768 } 00769 00770 /* simply clear the matrix */ 00771 unit_m4(data->invmat); 00772 00773 WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT, ob); 00774 00775 return OPERATOR_FINISHED; 00776 } 00777 00778 static int childof_clear_inverse_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) 00779 { 00780 if (edit_constraint_invoke_properties(C, op)) 00781 return childof_clear_inverse_exec(C, op); 00782 else 00783 return OPERATOR_CANCELLED; 00784 } 00785 00786 void CONSTRAINT_OT_childof_clear_inverse (wmOperatorType *ot) 00787 { 00788 /* identifiers */ 00789 ot->name= "Clear Inverse"; 00790 ot->idname= "CONSTRAINT_OT_childof_clear_inverse"; 00791 ot->description= "Clear inverse correction for ChildOf constraint"; 00792 00793 ot->exec= childof_clear_inverse_exec; 00794 ot->invoke= childof_clear_inverse_invoke; 00795 ot->poll= edit_constraint_poll; 00796 00797 /* flags */ 00798 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00799 edit_constraint_properties(ot); 00800 } 00801 00802 /***************************** BUTTONS ****************************/ 00803 00804 void ED_object_constraint_set_active(Object *ob, bConstraint *con) 00805 { 00806 ListBase *lb = get_constraint_lb(ob, con, NULL); 00807 00808 /* lets be nice and escape if its active already */ 00809 // NOTE: this assumes that the stack doesn't have other active ones set... 00810 if ((lb && con) && (con->flag & CONSTRAINT_ACTIVE)) 00811 return; 00812 00813 constraints_set_active(lb, con); 00814 } 00815 00816 void ED_object_constraint_update(Object *ob) 00817 { 00818 00819 if(ob->pose) update_pose_constraint_flags(ob->pose); 00820 00821 object_test_constraints(ob); 00822 00823 if(ob->type==OB_ARMATURE) DAG_id_tag_update(&ob->id, OB_RECALC_DATA|OB_RECALC_OB); 00824 else DAG_id_tag_update(&ob->id, OB_RECALC_OB); 00825 } 00826 00827 void ED_object_constraint_dependency_update(Main *bmain, Scene *scene, Object *ob) 00828 { 00829 ED_object_constraint_update(ob); 00830 00831 if(ob->pose) ob->pose->flag |= POSE_RECALC; // checks & sorts pose channels 00832 DAG_scene_sort(bmain, scene); 00833 } 00834 00835 static int constraint_poll(bContext *C) 00836 { 00837 PointerRNA ptr= CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint); 00838 return (ptr.id.data && ptr.data); 00839 } 00840 00841 static int constraint_delete_exec (bContext *C, wmOperator *UNUSED(op)) 00842 { 00843 PointerRNA ptr= CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint); 00844 Object *ob= ptr.id.data; 00845 bConstraint *con= ptr.data; 00846 ListBase *lb = get_constraint_lb(ob, con, NULL); 00847 const short is_ik= ELEM(con->type, CONSTRAINT_TYPE_KINEMATIC, CONSTRAINT_TYPE_SPLINEIK); 00848 00849 /* free the constraint */ 00850 if (remove_constraint(lb, con)) { 00851 /* there's no active constraint now, so make sure this is the case */ 00852 constraints_set_active(lb, NULL); 00853 00854 ED_object_constraint_update(ob); /* needed to set the flags on posebones correctly */ 00855 00856 /* ITASC needs to be rebuilt once a constraint is removed [#26920] */ 00857 if(is_ik) { 00858 BIK_clear_data(ob->pose); 00859 } 00860 00861 /* notifiers */ 00862 WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT|NA_REMOVED, ob); 00863 00864 return OPERATOR_FINISHED; 00865 } 00866 else { 00867 /* couldn't remove due to some invalid data */ 00868 return OPERATOR_CANCELLED; 00869 } 00870 } 00871 00872 void CONSTRAINT_OT_delete (wmOperatorType *ot) 00873 { 00874 /* identifiers */ 00875 ot->name= "Delete Constraint"; 00876 ot->idname= "CONSTRAINT_OT_delete"; 00877 ot->description= "Remove constraint from constraint stack"; 00878 00879 /* callbacks */ 00880 ot->exec= constraint_delete_exec; 00881 ot->poll= constraint_poll; 00882 00883 /* flags */ 00884 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00885 } 00886 00887 static int constraint_move_down_exec (bContext *C, wmOperator *op) 00888 { 00889 Object *ob = ED_object_active_context(C); 00890 bConstraint *con = edit_constraint_property_get(op, ob, 0); 00891 00892 if (con && con->next) { 00893 ListBase *conlist= get_constraint_lb(ob, con, NULL); 00894 bConstraint *nextCon= con->next; 00895 00896 /* insert the nominated constraint after the one that used to be after it */ 00897 BLI_remlink(conlist, con); 00898 BLI_insertlinkafter(conlist, nextCon, con); 00899 00900 WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT, ob); 00901 00902 return OPERATOR_FINISHED; 00903 } 00904 00905 return OPERATOR_CANCELLED; 00906 } 00907 00908 static int constraint_move_down_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) 00909 { 00910 if (edit_constraint_invoke_properties(C, op)) 00911 return constraint_move_down_exec(C, op); 00912 else 00913 return OPERATOR_CANCELLED; 00914 } 00915 00916 00917 void CONSTRAINT_OT_move_down (wmOperatorType *ot) 00918 { 00919 /* identifiers */ 00920 ot->name= "Move Constraint Down"; 00921 ot->idname= "CONSTRAINT_OT_move_down"; 00922 ot->description= "Move constraint down in constraint stack"; 00923 00924 /* callbacks */ 00925 ot->exec= constraint_move_down_exec; 00926 ot->invoke= constraint_move_down_invoke; 00927 ot->poll= edit_constraint_poll; 00928 00929 /* flags */ 00930 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00931 edit_constraint_properties(ot); 00932 } 00933 00934 00935 static int constraint_move_up_exec (bContext *C, wmOperator *op) 00936 { 00937 Object *ob = ED_object_active_context(C); 00938 bConstraint *con = edit_constraint_property_get(op, ob, 0); 00939 00940 if (con && con->prev) { 00941 ListBase *conlist= get_constraint_lb(ob, con, NULL); 00942 bConstraint *prevCon= con->prev; 00943 00944 /* insert the nominated constraint before the one that used to be before it */ 00945 BLI_remlink(conlist, con); 00946 BLI_insertlinkbefore(conlist, prevCon, con); 00947 00948 WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT, ob); 00949 00950 return OPERATOR_FINISHED; 00951 } 00952 00953 return OPERATOR_CANCELLED; 00954 } 00955 00956 static int constraint_move_up_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) 00957 { 00958 if (edit_constraint_invoke_properties(C, op)) 00959 return constraint_move_up_exec(C, op); 00960 else 00961 return OPERATOR_CANCELLED; 00962 } 00963 00964 void CONSTRAINT_OT_move_up (wmOperatorType *ot) 00965 { 00966 /* identifiers */ 00967 ot->name= "Move Constraint Up"; 00968 ot->idname= "CONSTRAINT_OT_move_up"; 00969 ot->description= "Move constraint up in constraint stack"; 00970 00971 /* callbacks */ 00972 ot->exec= constraint_move_up_exec; 00973 ot->invoke= constraint_move_up_invoke; 00974 ot->poll= edit_constraint_poll; 00975 00976 /* flags */ 00977 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 00978 edit_constraint_properties(ot); 00979 } 00980 00981 /***************************** OPERATORS ****************************/ 00982 00983 /************************ remove constraint operators *********************/ 00984 00985 static int pose_constraints_clear_exec(bContext *C, wmOperator *UNUSED(op)) 00986 { 00987 Main *bmain= CTX_data_main(C); 00988 Scene *scene= CTX_data_scene(C); 00989 Object *ob= ED_object_pose_armature(CTX_data_active_object(C)); 00990 00991 /* free constraints for all selected bones */ 00992 CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pose_bones) 00993 { 00994 free_constraints(&pchan->constraints); 00995 pchan->constflag &= ~(PCHAN_HAS_IK|PCHAN_HAS_SPLINEIK|PCHAN_HAS_CONST); 00996 } 00997 CTX_DATA_END; 00998 00999 /* force depsgraph to get recalculated since relationships removed */ 01000 DAG_scene_sort(bmain, scene); /* sort order of objects */ 01001 01002 /* note, calling BIK_clear_data() isnt needed here */ 01003 01004 /* do updates */ 01005 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 01006 WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT, ob); 01007 01008 return OPERATOR_FINISHED; 01009 } 01010 01011 void POSE_OT_constraints_clear(wmOperatorType *ot) 01012 { 01013 /* identifiers */ 01014 ot->name = "Clear Pose Constraints"; 01015 ot->idname= "POSE_OT_constraints_clear"; 01016 ot->description= "Clear all the constraints for the selected bones"; 01017 01018 /* callbacks */ 01019 ot->exec= pose_constraints_clear_exec; 01020 ot->poll= ED_operator_posemode; // XXX - do we want to ensure there are selected bones too? 01021 } 01022 01023 01024 static int object_constraints_clear_exec(bContext *C, wmOperator *UNUSED(op)) 01025 { 01026 Main *bmain= CTX_data_main(C); 01027 Scene *scene= CTX_data_scene(C); 01028 01029 /* do freeing */ 01030 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) 01031 { 01032 free_constraints(&ob->constraints); 01033 DAG_id_tag_update(&ob->id, OB_RECALC_OB); 01034 } 01035 CTX_DATA_END; 01036 01037 /* force depsgraph to get recalculated since relationships removed */ 01038 DAG_scene_sort(bmain, scene); /* sort order of objects */ 01039 01040 /* do updates */ 01041 WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT, NULL); 01042 01043 return OPERATOR_FINISHED; 01044 } 01045 01046 void OBJECT_OT_constraints_clear(wmOperatorType *ot) 01047 { 01048 /* identifiers */ 01049 ot->name = "Clear Object Constraints"; 01050 ot->idname= "OBJECT_OT_constraints_clear"; 01051 ot->description= "Clear all the constraints for the active Object only"; 01052 01053 /* callbacks */ 01054 ot->exec= object_constraints_clear_exec; 01055 ot->poll= ED_operator_object_active_editable; 01056 } 01057 01058 /************************ copy all constraints operators *********************/ 01059 01060 static int pose_constraint_copy_exec(bContext *C, wmOperator *op) 01061 { 01062 Main *bmain= CTX_data_main(C); 01063 Scene *scene = CTX_data_scene(C); 01064 bPoseChannel *pchan = CTX_data_active_pose_bone(C); 01065 01066 /* don't do anything if bone doesn't exist or doesn't have any constraints */ 01067 if (ELEM(NULL, pchan, pchan->constraints.first)) { 01068 BKE_report(op->reports, RPT_ERROR, "No active bone with constraints for copying"); 01069 return OPERATOR_CANCELLED; 01070 } 01071 01072 /* copy all constraints from active posebone to all selected posebones */ 01073 CTX_DATA_BEGIN(C, bPoseChannel*, chan, selected_pose_bones) 01074 { 01075 /* if we're not handling the object we're copying from, copy all constraints over */ 01076 if (pchan != chan) { 01077 copy_constraints(&chan->constraints, &pchan->constraints, TRUE); 01078 /* update flags (need to add here, not just copy) */ 01079 chan->constflag |= pchan->constflag; 01080 } 01081 } 01082 CTX_DATA_END; 01083 01084 /* force depsgraph to get recalculated since new relationships added */ 01085 DAG_scene_sort(bmain, scene); /* sort order of objects/bones */ 01086 01087 WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT, NULL); 01088 01089 return OPERATOR_FINISHED; 01090 } 01091 01092 void POSE_OT_constraints_copy(wmOperatorType *ot) 01093 { 01094 /* identifiers */ 01095 ot->name= "Copy Constraints to Selected"; 01096 ot->idname= "POSE_OT_constraints_copy"; 01097 ot->description = "Copy constraints to other selected bones."; 01098 01099 /* api callbacks */ 01100 ot->exec= pose_constraint_copy_exec; 01101 ot->poll= ED_operator_posemode; 01102 01103 /* flags */ 01104 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01105 } 01106 01107 static int object_constraint_copy_exec(bContext *C, wmOperator *UNUSED(op)) 01108 { 01109 Main *bmain= CTX_data_main(C); 01110 Scene *scene = CTX_data_scene(C); 01111 Object *obact = ED_object_active_context(C); 01112 01113 /* copy all constraints from active object to all selected objects */ 01114 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) 01115 { 01116 /* if we're not handling the object we're copying from, copy all constraints over */ 01117 if (obact != ob) 01118 copy_constraints(&ob->constraints, &obact->constraints, TRUE); 01119 } 01120 CTX_DATA_END; 01121 01122 /* force depsgraph to get recalculated since new relationships added */ 01123 DAG_scene_sort(bmain, scene); /* sort order of objects */ 01124 01125 return OPERATOR_FINISHED; 01126 } 01127 01128 void OBJECT_OT_constraints_copy(wmOperatorType *ot) 01129 { 01130 /* identifiers */ 01131 ot->name= "Copy Constraints to Selected"; 01132 ot->idname= "OBJECT_OT_constraints_copy"; 01133 ot->description = "Copy constraints to other selected objects."; 01134 01135 /* api callbacks */ 01136 ot->exec= object_constraint_copy_exec; 01137 ot->poll= ED_operator_object_active_editable; 01138 01139 /* flags */ 01140 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01141 } 01142 01143 /************************ add constraint operators *********************/ 01144 01145 /* get the Object and/or PoseChannel to use as target */ 01146 static short get_new_constraint_target(bContext *C, int con_type, Object **tar_ob, bPoseChannel **tar_pchan, short add) 01147 { 01148 Object *obact= ED_object_active_context(C); 01149 bPoseChannel *pchanact= get_active_posechannel(obact); 01150 short only_curve= 0, only_mesh= 0, only_ob= 0; 01151 short found= 0; 01152 01153 /* clear tar_ob and tar_pchan fields before use 01154 * - assume for now that both always exist... 01155 */ 01156 *tar_ob= NULL; 01157 *tar_pchan= NULL; 01158 01159 /* check if constraint type doesn't requires a target 01160 * - if so, no need to get any targets 01161 */ 01162 switch (con_type) { 01163 /* no-target constraints --------------------------- */ 01164 /* null constraint - shouldn't even be added! */ 01165 case CONSTRAINT_TYPE_NULL: 01166 /* limit constraints - no targets needed */ 01167 case CONSTRAINT_TYPE_LOCLIMIT: 01168 case CONSTRAINT_TYPE_ROTLIMIT: 01169 case CONSTRAINT_TYPE_SIZELIMIT: 01170 case CONSTRAINT_TYPE_SAMEVOL: 01171 return 0; 01172 01173 /* restricted target-type constraints -------------- */ 01174 /* NOTE: for these, we cannot try to add a target object if no valid ones are found, since that doesn't work */ 01175 /* curve-based constraints - set the only_curve and only_ob flags */ 01176 case CONSTRAINT_TYPE_CLAMPTO: 01177 case CONSTRAINT_TYPE_FOLLOWPATH: 01178 case CONSTRAINT_TYPE_SPLINEIK: 01179 only_curve= 1; 01180 only_ob= 1; 01181 add= 0; 01182 break; 01183 01184 /* mesh only? */ 01185 case CONSTRAINT_TYPE_SHRINKWRAP: 01186 only_mesh= 1; 01187 only_ob= 1; 01188 add= 0; 01189 break; 01190 01191 /* object only - add here is ok? */ 01192 case CONSTRAINT_TYPE_RIGIDBODYJOINT: 01193 only_ob= 1; 01194 break; 01195 } 01196 01197 /* if the active Object is Armature, and we can search for bones, do so... */ 01198 if ((obact->type == OB_ARMATURE) && (only_ob == 0)) { 01199 /* search in list of selected Pose-Channels for target */ 01200 CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pose_bones) 01201 { 01202 /* just use the first one that we encounter, as long as it is not the active one */ 01203 if (pchan != pchanact) { 01204 *tar_ob= obact; 01205 *tar_pchan= pchan; 01206 found= 1; 01207 01208 break; 01209 } 01210 } 01211 CTX_DATA_END; 01212 } 01213 01214 /* if not yet found, try selected Objects... */ 01215 if (found == 0) { 01216 /* search in selected objects context */ 01217 CTX_DATA_BEGIN(C, Object*, ob, selected_objects) 01218 { 01219 /* just use the first object we encounter (that isn't the active object) 01220 * and which fulfills the criteria for the object-target that we've got 01221 */ 01222 if ( (ob != obact) && 01223 ((!only_curve) || (ob->type == OB_CURVE)) && 01224 ((!only_mesh) || (ob->type == OB_MESH)) ) 01225 { 01226 /* set target */ 01227 *tar_ob= ob; 01228 found= 1; 01229 01230 /* perform some special operations on the target */ 01231 if (only_curve) { 01232 /* Curve-Path option must be enabled for follow-path constraints to be able to work */ 01233 Curve *cu= (Curve *)ob->data; 01234 cu->flag |= CU_PATH; 01235 } 01236 01237 break; 01238 } 01239 } 01240 CTX_DATA_END; 01241 } 01242 01243 /* if still not found, add a new empty to act as a target (if allowed) */ 01244 if ((found == 0) && (add)) { 01245 Scene *scene= CTX_data_scene(C); 01246 Base *base= BASACT, *newbase=NULL; 01247 Object *obt; 01248 01249 /* add new target object */ 01250 obt= add_object(scene, OB_EMPTY); 01251 01252 /* set layers OK */ 01253 newbase= BASACT; 01254 newbase->lay= base->lay; 01255 obt->lay= newbase->lay; 01256 01257 /* transform cent to global coords for loc */ 01258 if (pchanact) { 01259 /* since by default, IK targets the tip of the last bone, use the tip of the active PoseChannel 01260 * if adding a target for an IK Constraint 01261 */ 01262 if (con_type == CONSTRAINT_TYPE_KINEMATIC) 01263 mul_v3_m4v3(obt->loc, obact->obmat, pchanact->pose_tail); 01264 else 01265 mul_v3_m4v3(obt->loc, obact->obmat, pchanact->pose_head); 01266 } 01267 else 01268 VECCOPY(obt->loc, obact->obmat[3]); 01269 01270 /* restore, add_object sets active */ 01271 BASACT= base; 01272 base->flag |= SELECT; 01273 01274 /* make our new target the new object */ 01275 *tar_ob= obt; 01276 found= 1; 01277 } 01278 01279 /* return whether there's any target */ 01280 return found; 01281 } 01282 01283 /* used by add constraint operators to add the constraint required */ 01284 static int constraint_add_exec(bContext *C, wmOperator *op, Object *ob, ListBase *list, int type, short setTarget) 01285 { 01286 Main *bmain= CTX_data_main(C); 01287 Scene *scene= CTX_data_scene(C); 01288 bPoseChannel *pchan; 01289 bConstraint *con; 01290 01291 if (list == &ob->constraints) { 01292 pchan= NULL; 01293 } 01294 else { 01295 pchan= get_active_posechannel(ob); 01296 01297 /* ensure not to confuse object/pose adding */ 01298 if (pchan == NULL) { 01299 BKE_report(op->reports, RPT_ERROR, "No active pose bone to add a constraint to."); 01300 return OPERATOR_CANCELLED; 01301 } 01302 } 01303 /* check if constraint to be added is valid for the given constraints stack */ 01304 if (type == CONSTRAINT_TYPE_NULL) { 01305 return OPERATOR_CANCELLED; 01306 } 01307 if ( (type == CONSTRAINT_TYPE_RIGIDBODYJOINT) && (list != &ob->constraints) ) { 01308 BKE_report(op->reports, RPT_ERROR, "Rigid Body Joint Constraint can only be added to Objects."); 01309 return OPERATOR_CANCELLED; 01310 } 01311 if ( (type == CONSTRAINT_TYPE_KINEMATIC) && ((!pchan) || (list != &pchan->constraints)) ) { 01312 BKE_report(op->reports, RPT_ERROR, "IK Constraint can only be added to Bones."); 01313 return OPERATOR_CANCELLED; 01314 } 01315 if ( (type == CONSTRAINT_TYPE_SPLINEIK) && ((!pchan) || (list != &pchan->constraints)) ) { 01316 BKE_report(op->reports, RPT_ERROR, "Spline IK Constraint can only be added to Bones."); 01317 return OPERATOR_CANCELLED; 01318 } 01319 01320 /* create a new constraint of the type requried, and add it to the active/given constraints list */ 01321 if (pchan) 01322 con = add_pose_constraint(ob, pchan, NULL, type); 01323 else 01324 con = add_ob_constraint(ob, NULL, type); 01325 01326 /* get the first selected object/bone, and make that the target 01327 * - apart from the buttons-window add buttons, we shouldn't add in this way 01328 */ 01329 if (setTarget) { 01330 Object *tar_ob= NULL; 01331 bPoseChannel *tar_pchan= NULL; 01332 01333 /* get the target objects, adding them as need be */ 01334 if (get_new_constraint_target(C, type, &tar_ob, &tar_pchan, 1)) { 01335 /* method of setting target depends on the type of target we've got 01336 * - by default, just set the first target (distinction here is only for multiple-targetted constraints) 01337 */ 01338 if (tar_pchan) 01339 set_constraint_nth_target(con, tar_ob, tar_pchan->name, 0); 01340 else 01341 set_constraint_nth_target(con, tar_ob, "", 0); 01342 } 01343 } 01344 01345 /* do type-specific tweaking to the constraint settings */ 01346 switch (type) { 01347 case CONSTRAINT_TYPE_PYTHON: // FIXME: this code is not really valid anymore 01348 { 01349 #ifdef WITH_PYTHON 01350 char *menustr; 01351 int scriptint= 0; 01352 /* popup a list of usable scripts */ 01353 menustr = buildmenu_pyconstraints(NULL, &scriptint); 01354 // XXX scriptint = pupmenu(menustr); 01355 MEM_freeN(menustr); 01356 01357 /* only add constraint if a script was chosen */ 01358 if (scriptint) { 01359 /* add constraint */ 01360 validate_pyconstraint_cb(con->data, &scriptint); 01361 01362 /* make sure target allowance is set correctly */ 01363 BPY_pyconstraint_update(ob, con); 01364 } 01365 #endif 01366 } 01367 default: 01368 break; 01369 } 01370 01371 /* make sure all settings are valid - similar to above checks, but sometimes can be wrong */ 01372 object_test_constraints(ob); 01373 01374 if (pchan) 01375 update_pose_constraint_flags(ob->pose); 01376 01377 01378 /* force depsgraph to get recalculated since new relationships added */ 01379 DAG_scene_sort(bmain, scene); /* sort order of objects */ 01380 01381 if ((ob->type==OB_ARMATURE) && (pchan)) { 01382 ob->pose->flag |= POSE_RECALC; /* sort pose channels */ 01383 DAG_id_tag_update(&ob->id, OB_RECALC_DATA|OB_RECALC_OB); 01384 } 01385 else 01386 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 01387 01388 /* notifiers for updates */ 01389 WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT|NA_ADDED, ob); 01390 01391 return OPERATOR_FINISHED; 01392 } 01393 01394 /* ------------------ */ 01395 01396 /* dummy operator callback */ 01397 static int object_constraint_add_exec(bContext *C, wmOperator *op) 01398 { 01399 Object *ob=ED_object_active_context(C); 01400 int type= RNA_enum_get(op->ptr, "type"); 01401 short with_targets= 0; 01402 01403 if (!ob) { 01404 BKE_report(op->reports, RPT_ERROR, "No active object to add constraint to."); 01405 return OPERATOR_CANCELLED; 01406 } 01407 01408 /* hack: set constraint targets from selected objects in context is allowed when 01409 * operator name included 'with_targets', since the menu doesn't allow multiple properties 01410 */ 01411 if (strstr(op->idname, "with_targets")) 01412 with_targets= 1; 01413 01414 return constraint_add_exec(C, op, ob, &ob->constraints, type, with_targets); 01415 } 01416 01417 /* dummy operator callback */ 01418 static int pose_constraint_add_exec(bContext *C, wmOperator *op) 01419 { 01420 Object *ob= ED_object_pose_armature(ED_object_active_context(C)); 01421 int type= RNA_enum_get(op->ptr, "type"); 01422 short with_targets= 0; 01423 01424 if (!ob) { 01425 BKE_report(op->reports, RPT_ERROR, "No active object to add constraint to."); 01426 return OPERATOR_CANCELLED; 01427 } 01428 01429 /* hack: set constraint targets from selected objects in context is allowed when 01430 * operator name included 'with_targets', since the menu doesn't allow multiple properties 01431 */ 01432 if (strstr(op->idname, "with_targets")) 01433 with_targets= 1; 01434 01435 return constraint_add_exec(C, op, ob, get_active_constraints(ob), type, with_targets); 01436 } 01437 01438 /* ------------------ */ 01439 01440 void OBJECT_OT_constraint_add(wmOperatorType *ot) 01441 { 01442 /* identifiers */ 01443 ot->name= "Add Constraint"; 01444 ot->description = "Add a constraint to the active object"; 01445 ot->idname= "OBJECT_OT_constraint_add"; 01446 01447 /* api callbacks */ 01448 ot->invoke= WM_menu_invoke; 01449 ot->exec= object_constraint_add_exec; 01450 ot->poll= ED_operator_object_active_editable; 01451 01452 /* flags */ 01453 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01454 01455 /* properties */ 01456 ot->prop= RNA_def_enum(ot->srna, "type", constraint_type_items, 0, "Type", ""); 01457 } 01458 01459 void OBJECT_OT_constraint_add_with_targets(wmOperatorType *ot) 01460 { 01461 /* identifiers */ 01462 ot->name= "Add Constraint (with Targets)"; 01463 ot->description = "Add a constraint to the active object, with target (where applicable) set to the selected Objects/Bones"; 01464 ot->idname= "OBJECT_OT_constraint_add_with_targets"; 01465 01466 /* api callbacks */ 01467 ot->invoke= WM_menu_invoke; 01468 ot->exec= object_constraint_add_exec; 01469 ot->poll= ED_operator_object_active_editable; 01470 01471 /* flags */ 01472 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01473 01474 /* properties */ 01475 ot->prop= RNA_def_enum(ot->srna, "type", constraint_type_items, 0, "Type", ""); 01476 } 01477 01478 void POSE_OT_constraint_add(wmOperatorType *ot) 01479 { 01480 /* identifiers */ 01481 ot->name= "Add Constraint"; 01482 ot->description = "Add a constraint to the active bone"; 01483 ot->idname= "POSE_OT_constraint_add"; 01484 01485 /* api callbacks */ 01486 ot->invoke= WM_menu_invoke; 01487 ot->exec= pose_constraint_add_exec; 01488 ot->poll= ED_operator_posemode; 01489 01490 /* flags */ 01491 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01492 01493 /* properties */ 01494 ot->prop= RNA_def_enum(ot->srna, "type", constraint_type_items, 0, "Type", ""); 01495 } 01496 01497 void POSE_OT_constraint_add_with_targets(wmOperatorType *ot) 01498 { 01499 /* identifiers */ 01500 ot->name= "Add Constraint (with Targets)"; 01501 ot->description = "Add a constraint to the active bone, with target (where applicable) set to the selected Objects/Bones"; 01502 ot->idname= "POSE_OT_constraint_add_with_targets"; 01503 01504 /* api callbacks */ 01505 ot->invoke= WM_menu_invoke; 01506 ot->exec= pose_constraint_add_exec; 01507 ot->poll= ED_operator_posemode; 01508 01509 /* flags */ 01510 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01511 01512 /* properties */ 01513 ot->prop= RNA_def_enum(ot->srna, "type", constraint_type_items, 0, "Type", ""); 01514 } 01515 01516 /************************ IK Constraint operators *********************/ 01517 /* NOTE: only for Pose-Channels */ 01518 // TODO: should these be here, or back in editors/armature/poseobject.c again? 01519 01520 /* present menu with options + validation for targets to use */ 01521 static int pose_ik_add_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(evt)) 01522 { 01523 Object *ob= ED_object_pose_armature(CTX_data_active_object(C)); 01524 bPoseChannel *pchan= get_active_posechannel(ob); 01525 bConstraint *con= NULL; 01526 01527 uiPopupMenu *pup; 01528 uiLayout *layout; 01529 Object *tar_ob= NULL; 01530 bPoseChannel *tar_pchan= NULL; 01531 01532 /* must have active bone */ 01533 if (ELEM(NULL, ob, pchan)) { 01534 BKE_report(op->reports, RPT_ERROR, "Must have active bone to add IK Constraint to."); 01535 return OPERATOR_CANCELLED; 01536 } 01537 01538 /* bone must not have any constraints already */ 01539 for (con= pchan->constraints.first; con; con= con->next) { 01540 if (con->type==CONSTRAINT_TYPE_KINEMATIC) break; 01541 } 01542 if (con) { 01543 BKE_report(op->reports, RPT_ERROR, "Bone already has IK Constraint."); 01544 return OPERATOR_CANCELLED; 01545 } 01546 01547 /* prepare popup menu to choose targetting options */ 01548 pup= uiPupMenuBegin(C, "Add IK", ICON_NONE); 01549 layout= uiPupMenuLayout(pup); 01550 01551 /* the type of targets we'll set determines the menu entries to show... */ 01552 if (get_new_constraint_target(C, CONSTRAINT_TYPE_KINEMATIC, &tar_ob, &tar_pchan, 0)) { 01553 /* bone target, or object target? 01554 * - the only thing that matters is that we want a target... 01555 */ 01556 if (tar_pchan) 01557 uiItemBooleanO(layout, "To Active Bone", ICON_NONE, "POSE_OT_ik_add", "with_targets", 1); 01558 else 01559 uiItemBooleanO(layout, "To Active Object", ICON_NONE, "POSE_OT_ik_add", "with_targets", 1); 01560 } 01561 else { 01562 /* we have a choice of adding to a new empty, or not setting any target (targetless IK) */ 01563 uiItemBooleanO(layout, "To New Empty Object", ICON_NONE, "POSE_OT_ik_add", "with_targets", 1); 01564 uiItemBooleanO(layout, "Without Targets", ICON_NONE, "POSE_OT_ik_add", "with_targets", 0); 01565 } 01566 01567 /* finish building the menu, and process it (should result in calling self again) */ 01568 uiPupMenuEnd(C, pup); 01569 01570 return OPERATOR_CANCELLED; 01571 } 01572 01573 /* call constraint_add_exec() to add the IK constraint */ 01574 static int pose_ik_add_exec(bContext *C, wmOperator *op) 01575 { 01576 Object *ob= CTX_data_active_object(C); 01577 int with_targets= RNA_boolean_get(op->ptr, "with_targets"); 01578 01579 /* add the constraint - all necessary checks should have been done by the invoke() callback already... */ 01580 return constraint_add_exec(C, op, ob, get_active_constraints(ob), CONSTRAINT_TYPE_KINEMATIC, with_targets); 01581 } 01582 01583 void POSE_OT_ik_add(wmOperatorType *ot) 01584 { 01585 /* identifiers */ 01586 ot->name= "Add IK to Bone"; 01587 ot->description= "Add IK Constraint to the active Bone"; 01588 ot->idname= "POSE_OT_ik_add"; 01589 01590 /* api callbacks */ 01591 ot->invoke= pose_ik_add_invoke; 01592 ot->exec= pose_ik_add_exec; 01593 ot->poll= ED_operator_posemode; 01594 01595 /* flags */ 01596 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01597 01598 /* properties */ 01599 RNA_def_boolean(ot->srna, "with_targets", 1, "With Targets", "Assign IK Constraint with targets derived from the select bones/objects"); 01600 } 01601 01602 /* ------------------ */ 01603 01604 /* remove IK constraints from selected bones */ 01605 static int pose_ik_clear_exec(bContext *C, wmOperator *UNUSED(op)) 01606 { 01607 Object *ob= ED_object_pose_armature(CTX_data_active_object(C)); 01608 01609 /* only remove IK Constraints */ 01610 CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pose_bones) 01611 { 01612 bConstraint *con, *next; 01613 01614 // TODO: should we be checking if these contraints were local before we try and remove them? 01615 for (con= pchan->constraints.first; con; con= next) { 01616 next= con->next; 01617 if (con->type==CONSTRAINT_TYPE_KINEMATIC) { 01618 remove_constraint(&pchan->constraints, con); 01619 } 01620 } 01621 pchan->constflag &= ~(PCHAN_HAS_IK|PCHAN_HAS_TARGET); 01622 } 01623 CTX_DATA_END; 01624 01625 /* refresh depsgraph */ 01626 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 01627 01628 /* note, notifier might evolve */ 01629 WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT|NA_REMOVED, ob); 01630 01631 return OPERATOR_FINISHED; 01632 } 01633 01634 void POSE_OT_ik_clear(wmOperatorType *ot) 01635 { 01636 /* identifiers */ 01637 ot->name= "Remove IK"; 01638 ot->description= "Remove all IK Constraints from selected bones"; 01639 ot->idname= "POSE_OT_ik_clear"; 01640 01641 /* api callbacks */ 01642 ot->exec= pose_ik_clear_exec; 01643 ot->poll= ED_operator_posemode; 01644 01645 /* flags */ 01646 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 01647 } 01648