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