4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21 * All rights reserved.
23 * The Original Code is: all of this file.
25 * Contributor(s): Joshua Leung
27 * ***** END GPL LICENSE BLOCK *****
33 #include "MEM_guardedalloc.h"
35 #include "BLI_blenlib.h"
36 #include "BLI_arithb.h"
37 #include "BLI_dynstr.h"
39 #include "DNA_action_types.h"
40 #include "DNA_armature_types.h"
41 #include "DNA_constraint_types.h"
42 #include "DNA_curve_types.h"
43 #include "DNA_object_types.h"
44 #include "DNA_scene_types.h"
45 #include "DNA_screen_types.h"
46 #include "DNA_text_types.h"
47 #include "DNA_view3d_types.h"
49 #include "BKE_action.h"
50 #include "BKE_armature.h"
51 #include "BKE_constraint.h"
52 #include "BKE_depsgraph.h"
53 #include "BKE_global.h"
56 #include "BKE_object.h"
57 #include "BKE_utildefines.h"
59 #include "BIF_editaction.h"
60 #include "BIF_editarmature.h"
61 #include "BIF_editconstraint.h"
62 #include "BIF_poseobject.h"
63 #include "BIF_interface.h"
64 #include "BIF_screen.h"
65 #include "BIF_space.h"
66 #include "BIF_toolbox.h"
68 #ifndef DISABLE_PYTHON
69 #include "BPY_extern.h"
76 /* -------------- Get Active Constraint Data ---------------------- */
78 ListBase *get_active_constraint_channels (Object *ob, int forcevalid)
85 /* See if we are a bone constraint */
86 if (ob->flag & OB_POSEMODE) {
87 bActionChannel *achan;
90 pchan = get_active_posechannel(ob);
92 /* Make sure we have an action */
93 if (ob->action == NULL) {
97 ob->action= add_empty_action("Action");
100 /* Make sure we have an actionchannel */
101 achan = get_action_channel(ob->action, pchan->name);
106 achan = MEM_callocN (sizeof(bActionChannel), "ActionChannel");
108 strcpy(achan->name, pchan->name);
109 sprintf(ipstr, "%s.%s", ob->action->id.name+2, achan->name);
111 achan->ipo= add_ipo(ipstr, ID_AC);
113 BLI_addtail(&ob->action->chanbase, achan);
116 return &achan->constraintChannels;
121 /* else we return object constraints */
123 if (ob->ipoflag & OB_ACTION_OB) {
124 bActionChannel *achan = get_action_channel(ob->action, "Object");
126 return &achan->constraintChannels;
131 return &ob->constraintChannels;
136 /* if object in posemode, active bone constraints, else object constraints */
137 ListBase *get_active_constraints (Object *ob)
142 if (ob->flag & OB_POSEMODE) {
145 pchan = get_active_posechannel(ob);
147 return &pchan->constraints;
150 return &ob->constraints;
155 /* single constraint */
156 bConstraint *get_active_constraint (Object *ob)
158 ListBase *lb= get_active_constraints(ob);
163 for (con= lb->first; con; con=con->next) {
164 if (con->flag & CONSTRAINT_ACTIVE)
172 /* single channel, for ipo */
173 bConstraintChannel *get_active_constraint_channel (Object *ob)
176 bConstraintChannel *chan;
178 if (ob->flag & OB_POSEMODE) {
182 pchan = get_active_posechannel(ob);
184 for (con= pchan->constraints.first; con; con= con->next) {
185 if (con->flag & CONSTRAINT_ACTIVE)
190 bActionChannel *achan = get_action_channel(ob->action, pchan->name);
192 for (chan= achan->constraintChannels.first; chan; chan= chan->next) {
193 if (!strcmp(chan->name, con->name))
203 for (con= ob->constraints.first; con; con= con->next) {
204 if (con->flag & CONSTRAINT_ACTIVE)
209 ListBase *lb= get_active_constraint_channels(ob, 0);
212 for (chan= lb->first; chan; chan= chan->next) {
213 if (!strcmp(chan->name, con->name))
225 /* -------------- Constraint Management (Add New, Remove, Rename) -------------------- */
227 /* Creates a new constraint, initialises its data, and returns it */
228 bConstraint *add_new_constraint (short type)
231 bConstraintTypeInfo *cti;
233 con = MEM_callocN(sizeof(bConstraint), "Constraint");
235 /* Set up a generic constraint datablock */
237 con->flag |= CONSTRAINT_EXPAND;
239 strcpy(con->name, "Const");
241 /* Load the data for it */
242 cti = constraint_get_typeinfo(con);
244 con->data = MEM_callocN(cti->size, cti->structName);
246 /* only constraints that change any settings need this */
248 cti->new_data(con->data);
254 /* Adds the given constraint to the Object-level set of constraints for the given Object */
255 void add_constraint_to_object (bConstraint *con, Object *ob)
258 list = &ob->constraints;
261 unique_constraint_name(con, list);
262 BLI_addtail(list, con);
264 if (proxylocked_constraints_owner(ob, NULL))
265 con->flag |= CONSTRAINT_PROXY_LOCAL;
267 con->flag |= CONSTRAINT_ACTIVE;
268 for (con= con->prev; con; con= con->prev)
269 con->flag &= ~CONSTRAINT_ACTIVE;
273 /* helper function for add_constriant - sets the last target for the active constraint */
274 static void set_constraint_nth_target (bConstraint *con, Object *target, char subtarget[], int index)
276 bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
277 ListBase targets = {NULL, NULL};
278 bConstraintTarget *ct;
281 if (cti && cti->get_constraint_targets) {
282 cti->get_constraint_targets(con, &targets);
283 num_targets= BLI_countlist(&targets);
286 if (abs(index) < num_targets)
287 index= num_targets - abs(index);
289 index= num_targets - 1;
291 else if (index >= num_targets) {
292 index= num_targets - 1;
295 for (ct=targets.first, i=0; ct; ct= ct->next, i++) {
298 strcpy(ct->subtarget, subtarget);
303 if (cti->flush_constraint_targets)
304 cti->flush_constraint_targets(con, &targets, 0);
308 /* context: active object in posemode, active channel, optional selected channel */
309 void add_constraint (short only_IK)
311 Object *ob= OBACT, *obsel=NULL;
312 bPoseChannel *pchanact=NULL, *pchansel=NULL;
313 bConstraint *con=NULL;
317 /* paranoia checks */
318 if ((ob==NULL) || (ob==G.obedit))
321 if ((ob->pose) && (ob->flag & OB_POSEMODE)) {
322 bArmature *arm= ob->data;
324 /* find active channel */
325 pchanact= get_active_posechannel(ob);
329 /* find selected bone */
330 for (pchansel=ob->pose->chanbase.first; pchansel; pchansel=pchansel->next) {
331 if (pchansel != pchanact) {
332 if (pchansel->bone->flag & BONE_SELECTED) {
333 if (pchansel->bone->layer & arm->layer)
340 /* find selected object */
341 for (base= FIRSTBASE; base; base= base->next) {
342 if ((TESTBASE(base)) && (base->object!=ob))
346 /* the only_IK caller has checked for posemode! */
348 for (con= pchanact->constraints.first; con; con= con->next) {
349 if (con->type==CONSTRAINT_TYPE_KINEMATIC) break;
352 error("Pose Channel already has IK");
357 nr= pupmenu("Add IK Constraint%t|To Active Bone%x10");
359 nr= pupmenu("Add IK Constraint%t|To Active Object%x10");
361 nr= pupmenu("Add IK Constraint%t|To New Empty Object%x10|Without Target%x11");
366 nr= pupmenu("Add Constraint to Active Bone%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Action%x16|Script%x18");
367 else if ((obsel) && (obsel->type==OB_CURVE))
368 nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6|Clamp To%x17|Stretch To%x7|%l|Action%x16|Script%x18");
370 nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Action%x16|Script%x18");
372 nr= pupmenu("Add Constraint to New Empty Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Action%x16|Script%x18");
375 if ((obsel) && (obsel->type==OB_CURVE))
376 nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6|Clamp To%x17|%l|Action%x16|Script%x18");
378 nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|%l|Action%x16|Script%x18");
380 nr= pupmenu("Add Constraint to New Empty Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|%l|Action%x16|Script%x18");
386 /* handle IK separate */
387 if (nr==10 || nr==11) {
388 /* ik - prevent weird chains... */
390 bPoseChannel *pchan= pchanact;
392 if (pchan==pchansel) break;
393 pchan= pchan->parent;
396 error("IK root cannot be linked to IK tip");
402 if (pchan==pchanact) break;
403 pchan= pchan->parent;
406 error("IK tip cannot be linked to IK root");
411 con = add_new_constraint(CONSTRAINT_TYPE_KINEMATIC);
412 BLI_addtail(&pchanact->constraints, con);
413 unique_constraint_name(con, &pchanact->constraints);
414 pchanact->constflag |= PCHAN_HAS_IK; /* for draw, but also for detecting while pose solving */
416 pchanact->constflag |= PCHAN_HAS_TARGET;
417 if (proxylocked_constraints_owner(ob, pchanact))
418 con->flag |= CONSTRAINT_PROXY_LOCAL;
421 /* normal constraints - add data */
422 if (nr==1) con = add_new_constraint(CONSTRAINT_TYPE_LOCLIKE);
423 else if (nr==2) con = add_new_constraint(CONSTRAINT_TYPE_ROTLIKE);
424 else if (nr==3) con = add_new_constraint(CONSTRAINT_TYPE_TRACKTO);
425 else if (nr==4) con = add_new_constraint(CONSTRAINT_TYPE_MINMAX);
426 else if (nr==5) con = add_new_constraint(CONSTRAINT_TYPE_LOCKTRACK);
428 Curve *cu= obsel->data;
430 con = add_new_constraint(CONSTRAINT_TYPE_FOLLOWPATH);
432 else if (nr==7) con = add_new_constraint(CONSTRAINT_TYPE_STRETCHTO);
433 else if (nr==8) con = add_new_constraint(CONSTRAINT_TYPE_SIZELIKE);
434 else if (nr==13) con = add_new_constraint(CONSTRAINT_TYPE_LOCLIMIT);
435 else if (nr==14) con = add_new_constraint(CONSTRAINT_TYPE_ROTLIMIT);
436 else if (nr==15) con = add_new_constraint(CONSTRAINT_TYPE_SIZELIMIT);
438 /* TODO: add a popup-menu to display list of available actions to use (like for pyconstraints) */
439 con = add_new_constraint(CONSTRAINT_TYPE_ACTION);
442 Curve *cu= obsel->data;
444 con = add_new_constraint(CONSTRAINT_TYPE_CLAMPTO);
449 #ifndef DISABLE_PYTHON
450 /* popup a list of usable scripts */
451 menustr = buildmenu_pyconstraints(NULL, &scriptint);
452 scriptint = pupmenu(menustr);
455 /* only add constraint if a script was chosen */
458 con = add_new_constraint(CONSTRAINT_TYPE_PYTHON);
459 validate_pyconstraint_cb(con->data, &scriptint);
461 /* make sure target allowance is set correctly */
462 BPY_pyconstraint_update(ob, con);
467 con = add_new_constraint(CONSTRAINT_TYPE_CHILDOF);
469 /* if this constraint is being added to a posechannel, make sure
470 * the constraint gets evaluated in pose-space
473 con->ownspace = CONSTRAINT_SPACE_POSE;
474 con->flag |= CONSTRAINT_SPACEONCE;
477 else if (nr==20) con = add_new_constraint(CONSTRAINT_TYPE_TRANSFORM);
478 else if (nr==21) con = add_new_constraint(CONSTRAINT_TYPE_DISTLIMIT);
480 if (con==NULL) return; /* paranoia */
483 BLI_addtail(&pchanact->constraints, con);
484 unique_constraint_name(con, &pchanact->constraints);
485 pchanact->constflag |= PCHAN_HAS_CONST; /* for draw */
486 if (proxylocked_constraints_owner(ob, pchanact))
487 con->flag |= CONSTRAINT_PROXY_LOCAL;
490 BLI_addtail(&ob->constraints, con);
491 unique_constraint_name(con, &ob->constraints);
492 if (proxylocked_constraints_owner(ob, NULL))
493 con->flag |= CONSTRAINT_PROXY_LOCAL;
499 set_constraint_nth_target(con, ob, pchansel->name, 0);
502 set_constraint_nth_target(con, obsel, "", 0);
504 else if (ELEM4(nr, 11, 13, 14, 15)==0) { /* add new empty as target */
505 Base *base= BASACT, *newbase;
508 obt= add_object(OB_EMPTY);
511 newbase->lay= base->lay;
512 obt->lay= newbase->lay;
514 /* transform cent to global coords for loc */
517 VecMat4MulVecfl(obt->loc, ob->obmat, pchanact->pose_tail);
519 VecMat4MulVecfl(obt->loc, ob->obmat, pchanact->pose_head);
522 VECCOPY(obt->loc, ob->obmat[3]);
524 set_constraint_nth_target(con, obt, "", 0);
526 /* restore, add_object sets active */
528 base->flag |= SELECT;
532 con->flag |= CONSTRAINT_ACTIVE;
533 for (con= con->prev; con; con= con->prev)
534 con->flag &= ~CONSTRAINT_ACTIVE;
536 DAG_scene_sort(G.scene); // sort order of objects
539 ob->pose->flag |= POSE_RECALC; // sort pose channels
540 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); // and all its relations
543 DAG_object_flush_update(G.scene, ob, OB_RECALC_OB); // and all its relations
545 allqueue(REDRAWVIEW3D, 0);
546 allqueue(REDRAWBUTSOBJECT, 0);
547 allqueue(REDRAWBUTSEDIT, 0);
548 allqueue(REDRAWOOPS, 0);
551 BIF_undo_push("Add IK Constraint");
553 BIF_undo_push("Add Constraint");
557 /* Remove all constraints from the active object */
558 void ob_clear_constraints (void)
562 /* paranoia checks */
563 if ((ob==NULL) || (ob==G.obedit) || (ob->flag & OB_POSEMODE))
566 /* get user permission */
567 if (okee("Clear Constraints")==0)
571 free_constraints(&ob->constraints);
574 DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
576 allqueue(REDRAWVIEW3D, 0);
577 allqueue(REDRAWBUTSOBJECT, 0);
578 allqueue(REDRAWOOPS, 0);
580 BIF_undo_push("Clear Constraint(s)");
583 /* Rename the given constraint
584 * - con already has the new name
586 void rename_constraint (Object *ob, bConstraint *con, char *oldname)
589 bConstraintChannel *conchan;
590 ListBase *conlist= NULL;
594 /* get context by searching for con (primitive...) */
595 for (tcon= ob->constraints.first; tcon; tcon= tcon->next) {
601 conlist= &ob->constraints;
608 for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
609 for (tcon= pchan->constraints.first; tcon; tcon= tcon->next) {
618 conlist= &pchan->constraints;
619 channame= pchan->name;
624 printf("rename constraint failed\n"); /* should not happen in UI */
628 /* first make sure it's a unique name within context */
629 unique_constraint_name (con, conlist);
633 for (conchan= ob->constraintChannels.first; conchan; conchan= conchan->next) {
634 if ( strcmp(oldname, conchan->name)==0 )
635 BLI_strncpy(conchan->name, con->name, sizeof(conchan->name));
641 bActionChannel *achan= get_action_channel(ob->action, channame);
643 conchan= get_constraint_channel(&achan->constraintChannels, oldname);
645 BLI_strncpy(conchan->name, con->name, sizeof(conchan->name));
651 /* ------------- Constraint Sanity Testing ------------------- */
653 /* checks validity of object pointers, and NULLs,
654 * if Bone doesnt exist it sets the CONSTRAINT_DISABLE flag
656 static void test_constraints (Object *owner, const char substring[])
659 ListBase *conlist= NULL;
662 if (owner==NULL) return;
665 if (strlen(substring)) {
666 switch (owner->type) {
668 type = CONSTRAINT_OBTYPE_BONE;
671 type = CONSTRAINT_OBTYPE_OBJECT;
676 type = CONSTRAINT_OBTYPE_OBJECT;
678 /* Get the constraint list for this object */
680 case CONSTRAINT_OBTYPE_OBJECT:
681 conlist = &owner->constraints;
683 case CONSTRAINT_OBTYPE_BONE:
688 bone = get_named_bone( ((bArmature *)owner->data), substring );
689 chan = get_pose_channel(owner->pose, substring);
691 conlist = &chan->constraints;
697 /* Check all constraints - is constraint valid? */
699 for (curcon = conlist->first; curcon; curcon=curcon->next) {
700 bConstraintTypeInfo *cti= constraint_get_typeinfo(curcon);
701 ListBase targets = {NULL, NULL};
702 bConstraintTarget *ct;
704 /* clear disabled-flag first */
705 curcon->flag &= ~CONSTRAINT_DISABLE;
707 #ifndef DISABLE_PYTHON
708 /* Check specialised data (settings) for constraints that need this */
709 if (curcon->type == CONSTRAINT_TYPE_PYTHON) {
710 bPythonConstraint *data = curcon->data;
712 /* is there are valid script? */
713 if (data->text == NULL) {
714 curcon->flag |= CONSTRAINT_DISABLE;
716 else if (BPY_is_pyconstraint(data->text)==0) {
717 curcon->flag |= CONSTRAINT_DISABLE;
719 /* does the constraint require target input... also validates targets */
720 BPY_pyconstraint_update(owner, curcon);
722 /* targets have already been checked for this */
727 if (curcon->type == CONSTRAINT_TYPE_KINEMATIC) {
728 bKinematicConstraint *data = curcon->data;
730 /* bad: we need a separate set of checks here as poletarget is
731 * optional... otherwise poletarget must exist too or else
732 * the constraint is deemed invalid
734 if (exist_object(data->tar) == 0) {
736 curcon->flag |= CONSTRAINT_DISABLE;
738 else if (data->tar == owner) {
739 if (!get_named_bone(get_armature(owner), data->subtarget)) {
740 curcon->flag |= CONSTRAINT_DISABLE;
745 if (exist_object(data->poletar) == 0) {
746 data->poletar = NULL;
747 curcon->flag |= CONSTRAINT_DISABLE;
749 else if (data->poletar == owner) {
750 if (!get_named_bone(get_armature(owner), data->polesubtarget)) {
751 curcon->flag |= CONSTRAINT_DISABLE;
756 /* targets have already been checked for this */
759 else if (curcon->type == CONSTRAINT_TYPE_ACTION) {
760 bActionConstraint *data = curcon->data;
762 /* validate action */
763 if (data->act == NULL)
764 curcon->flag |= CONSTRAINT_DISABLE;
766 else if (curcon->type == CONSTRAINT_TYPE_FOLLOWPATH) {
767 bFollowPathConstraint *data = curcon->data;
769 /* don't allow track/up axes to be the same */
770 if (data->upflag==data->trackflag)
771 curcon->flag |= CONSTRAINT_DISABLE;
772 if (data->upflag+3==data->trackflag)
773 curcon->flag |= CONSTRAINT_DISABLE;
775 else if (curcon->type == CONSTRAINT_TYPE_TRACKTO) {
776 bTrackToConstraint *data = curcon->data;
778 /* don't allow track/up axes to be the same */
779 if (data->reserved2==data->reserved1)
780 curcon->flag |= CONSTRAINT_DISABLE;
781 if (data->reserved2+3==data->reserved1)
782 curcon->flag |= CONSTRAINT_DISABLE;
784 else if (curcon->type == CONSTRAINT_TYPE_LOCKTRACK) {
785 bLockTrackConstraint *data = curcon->data;
787 if (data->lockflag==data->trackflag)
788 curcon->flag |= CONSTRAINT_DISABLE;
789 if (data->lockflag+3==data->trackflag)
790 curcon->flag |= CONSTRAINT_DISABLE;
793 /* Check targets for constraints */
794 if (cti && cti->get_constraint_targets) {
795 cti->get_constraint_targets(curcon, &targets);
797 /* disable and clear constraints targets that are incorrect */
798 for (ct= targets.first; ct; ct= ct->next) {
799 /* general validity checks (for those constraints that need this) */
800 if (exist_object(ct->tar) == 0) {
802 curcon->flag |= CONSTRAINT_DISABLE;
804 else if (ct->tar == owner) {
805 if (!get_named_bone(get_armature(owner), ct->subtarget)) {
806 curcon->flag |= CONSTRAINT_DISABLE;
810 /* target checks for specific constraints */
811 if (ELEM(curcon->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO)) {
813 if (ct->tar->type != OB_CURVE) {
815 curcon->flag |= CONSTRAINT_DISABLE;
818 Curve *cu= ct->tar->data;
820 /* auto-set 'Path' setting on curve so this works */
827 /* free any temporary targets */
828 if (cti->flush_constraint_targets)
829 cti->flush_constraint_targets(curcon, &targets, 0);
835 static void test_bonelist_constraints (Object *owner, ListBase *list)
839 for (bone = list->first; bone; bone = bone->next) {
840 test_constraints(owner, bone->name);
841 test_bonelist_constraints(owner, &bone->childbase);
845 void object_test_constraints (Object *owner)
847 test_constraints(owner, "");
849 if (owner->type==OB_ARMATURE) {
850 bArmature *arm= get_armature(owner);
853 test_bonelist_constraints(owner, &arm->bonebase);
857 /* ********************** CONSTRAINT-SPECIFIC STUFF ********************* */
858 /* ------------- PyConstraints ------------------ */
860 /* this callback sets the text-file to be used for selected menu item */
861 void validate_pyconstraint_cb (void *arg1, void *arg2)
863 bPythonConstraint *data = arg1;
865 int index = *((int *)arg2);
868 /* exception for no script */
870 /* innovative use of a for...loop to search */
871 for (text=G.main->text.first, i=1; text && index!=i; i++, text=text->id.next);
876 #ifndef DISABLE_PYTHON
877 /* this returns a string for the list of usable pyconstraint script names */
878 char *buildmenu_pyconstraints (Text *con_text, int *pyconindex)
880 DynStr *pupds= BLI_dynstr_new();
886 /* add title first */
887 sprintf(buf, "Scripts: %%t|[None]%%x0|");
888 BLI_dynstr_append(pupds, buf);
890 /* init active-index first */
891 if (con_text == NULL)
894 /* loop through markers, adding them */
895 for (text=G.main->text.first, i=1; text; i++, text=text->id.next) {
896 /* this is important to ensure that right script is shown as active */
897 if (text == con_text) *pyconindex = i;
899 /* only include valid pyconstraint scripts */
900 if (BPY_is_pyconstraint(text)) {
901 BLI_dynstr_append(pupds, text->id.name+2);
903 sprintf(buf, "%%x%d", i);
904 BLI_dynstr_append(pupds, buf);
907 BLI_dynstr_append(pupds, "|");
911 /* convert to normal MEM_malloc'd string */
912 str= BLI_dynstr_get_cstring(pupds);
913 BLI_dynstr_free(pupds);
917 #endif /* DISABLE_PYTHON */
919 /* this callback gets called when the 'refresh' button of a pyconstraint gets pressed */
920 void update_pyconstraint_cb (void *arg1, void *arg2)
922 Object *owner= (Object *)arg1;
923 bConstraint *con= (bConstraint *)arg2;
924 #ifndef DISABLE_PYTHON
926 BPY_pyconstraint_update(owner, con);
930 /* ------------- Child-Of Constraint ------------------ */
932 /* ChildOf Constraint - set inverse callback */
933 void childof_const_setinv (void *conv, void *unused)
935 bConstraint *con= (bConstraint *)conv;
936 bChildOfConstraint *data= (bChildOfConstraint *)con->data;
938 bPoseChannel *pchan= NULL;
940 /* try to find a pose channel */
942 pchan= get_active_posechannel(ob);
944 /* calculate/set inverse matrix */
946 float pmat[4][4], cinf;
947 float imat[4][4], tmat[4][4];
949 /* make copy of pchan's original pose-mat (for use later) */
950 Mat4CpyMat4(pmat, pchan->pose_mat);
952 /* disable constraint for pose to be solved without it */
956 /* solve pose without constraint */
959 /* determine effect of constraint by removing the newly calculated
960 * pchan->pose_mat from the original pchan->pose_mat, thus determining
961 * the effect of the constraint
963 Mat4Invert(imat, pchan->pose_mat);
964 Mat4MulMat4(tmat, imat, pmat);
965 Mat4Invert(data->invmat, tmat);
967 /* recalculate pose with new inv-mat */
972 /* use what_does_parent to find inverse - just like for normal parenting.
973 * NOTE: what_does_parent uses a static workob defined in object.c
975 what_does_parent(ob);
976 Mat4Invert(data->invmat, workob.obmat);
979 Mat4One(data->invmat);
982 /* ChildOf Constraint - clear inverse callback */
983 void childof_const_clearinv (void *conv, void *unused)
985 bConstraint *con= (bConstraint *)conv;
986 bChildOfConstraint *data= (bChildOfConstraint *)con->data;
988 /* simply clear the matrix */
989 Mat4One(data->invmat);