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 #include "BPY_extern.h"
74 /* -------------- Get Active Constraint Data ---------------------- */
76 ListBase *get_active_constraint_channels (Object *ob, int forcevalid)
83 /* See if we are a bone constraint */
84 if (ob->flag & OB_POSEMODE) {
85 bActionChannel *achan;
88 pchan = get_active_posechannel(ob);
90 /* Make sure we have an action */
91 if (ob->action == NULL) {
95 ob->action= add_empty_action("Action");
98 /* Make sure we have an actionchannel */
99 achan = get_action_channel(ob->action, pchan->name);
104 achan = MEM_callocN (sizeof(bActionChannel), "ActionChannel");
106 strcpy(achan->name, pchan->name);
107 sprintf(ipstr, "%s.%s", ob->action->id.name+2, achan->name);
109 achan->ipo= add_ipo(ipstr, ID_AC);
111 BLI_addtail(&ob->action->chanbase, achan);
114 return &achan->constraintChannels;
119 /* else we return object constraints */
121 if (ob->ipoflag & OB_ACTION_OB) {
122 bActionChannel *achan = get_action_channel(ob->action, "Object");
124 return &achan->constraintChannels;
129 return &ob->constraintChannels;
134 /* if object in posemode, active bone constraints, else object constraints */
135 ListBase *get_active_constraints (Object *ob)
140 if (ob->flag & OB_POSEMODE) {
143 pchan = get_active_posechannel(ob);
145 return &pchan->constraints;
148 return &ob->constraints;
153 /* single constraint */
154 bConstraint *get_active_constraint (Object *ob)
156 ListBase *lb= get_active_constraints(ob);
161 for (con= lb->first; con; con=con->next) {
162 if (con->flag & CONSTRAINT_ACTIVE)
170 /* single channel, for ipo */
171 bConstraintChannel *get_active_constraint_channel (Object *ob)
174 bConstraintChannel *chan;
176 if (ob->flag & OB_POSEMODE) {
180 pchan = get_active_posechannel(ob);
182 for (con= pchan->constraints.first; con; con= con->next) {
183 if (con->flag & CONSTRAINT_ACTIVE)
188 bActionChannel *achan = get_action_channel(ob->action, pchan->name);
190 for (chan= achan->constraintChannels.first; chan; chan= chan->next) {
191 if (!strcmp(chan->name, con->name))
201 for (con= ob->constraints.first; con; con= con->next) {
202 if (con->flag & CONSTRAINT_ACTIVE)
207 ListBase *lb= get_active_constraint_channels(ob, 0);
210 for (chan= lb->first; chan; chan= chan->next) {
211 if (!strcmp(chan->name, con->name))
223 /* -------------- Constraint Management (Add New, Remove, Rename) -------------------- */
225 /* Creates a new constraint, initialises its data, and returns it */
226 bConstraint *add_new_constraint (short type)
229 bConstraintTypeInfo *cti;
231 con = MEM_callocN(sizeof(bConstraint), "Constraint");
233 /* Set up a generic constraint datablock */
235 con->flag |= CONSTRAINT_EXPAND;
237 strcpy(con->name, "Const");
239 /* Load the data for it */
240 cti = constraint_get_typeinfo(con);
242 con->data = MEM_callocN(cti->size, cti->structName);
244 /* only constraints that change any settings need this */
246 cti->new_data(con->data);
252 /* Adds the given constraint to the Object-level set of constraints for the given Object */
253 void add_constraint_to_object (bConstraint *con, Object *ob)
256 list = &ob->constraints;
259 unique_constraint_name(con, list);
260 BLI_addtail(list, con);
262 if (proxylocked_constraints_owner(ob, NULL))
263 con->flag |= CONSTRAINT_PROXY_LOCAL;
265 con->flag |= CONSTRAINT_ACTIVE;
266 for (con= con->prev; con; con= con->prev)
267 con->flag &= ~CONSTRAINT_ACTIVE;
271 /* helper function for add_constriant - sets the last target for the active constraint */
272 static void set_constraint_nth_target (bConstraint *con, Object *target, char subtarget[], int index)
274 bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
275 ListBase targets = {NULL, NULL};
276 bConstraintTarget *ct;
279 if (cti && cti->get_constraint_targets) {
280 cti->get_constraint_targets(con, &targets);
281 num_targets= BLI_countlist(&targets);
284 if (abs(index) < num_targets)
285 index= num_targets - abs(index);
287 index= num_targets - 1;
289 else if (index >= num_targets) {
290 index= num_targets - 1;
293 for (ct=targets.first, i=0; ct; ct= ct->next, i++) {
296 strcpy(ct->subtarget, subtarget);
301 if (cti->flush_constraint_targets)
302 cti->flush_constraint_targets(con, &targets, 0);
306 /* context: active object in posemode, active channel, optional selected channel */
307 void add_constraint (short only_IK)
309 Object *ob= OBACT, *obsel=NULL;
310 bPoseChannel *pchanact=NULL, *pchansel=NULL;
311 bConstraint *con=NULL;
315 /* paranoia checks */
316 if ((ob==NULL) || (ob==G.obedit))
319 if ((ob->pose) && (ob->flag & OB_POSEMODE)) {
320 bArmature *arm= ob->data;
322 /* find active channel */
323 pchanact= get_active_posechannel(ob);
327 /* find selected bone */
328 for (pchansel=ob->pose->chanbase.first; pchansel; pchansel=pchansel->next) {
329 if (pchansel != pchanact) {
330 if (pchansel->bone->flag & BONE_SELECTED) {
331 if (pchansel->bone->layer & arm->layer)
338 /* find selected object */
339 for (base= FIRSTBASE; base; base= base->next) {
340 if ((TESTBASE(base)) && (base->object!=ob))
344 /* the only_IK caller has checked for posemode! */
346 for (con= pchanact->constraints.first; con; con= con->next) {
347 if (con->type==CONSTRAINT_TYPE_KINEMATIC) break;
350 error("Pose Channel already has IK");
355 nr= pupmenu("Add IK Constraint%t|To Active Bone%x10");
357 nr= pupmenu("Add IK Constraint%t|To Active Object%x10");
359 nr= pupmenu("Add IK Constraint%t|To New Empty Object%x10|Without Target%x11");
364 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");
365 else if ((obsel) && (obsel->type==OB_CURVE))
366 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");
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|Stretch To%x7|%l|Action%x16|Script%x18");
370 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");
373 if ((obsel) && (obsel->type==OB_CURVE))
374 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");
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|%l|Action%x16|Script%x18");
378 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");
384 /* handle IK separate */
385 if (nr==10 || nr==11) {
386 /* ik - prevent weird chains... */
388 bPoseChannel *pchan= pchanact;
390 if (pchan==pchansel) break;
391 pchan= pchan->parent;
394 error("IK root cannot be linked to IK tip");
400 if (pchan==pchanact) break;
401 pchan= pchan->parent;
404 error("IK tip cannot be linked to IK root");
409 con = add_new_constraint(CONSTRAINT_TYPE_KINEMATIC);
410 BLI_addtail(&pchanact->constraints, con);
411 unique_constraint_name(con, &pchanact->constraints);
412 pchanact->constflag |= PCHAN_HAS_IK; /* for draw, but also for detecting while pose solving */
414 pchanact->constflag |= PCHAN_HAS_TARGET;
415 if (proxylocked_constraints_owner(ob, pchanact))
416 con->flag |= CONSTRAINT_PROXY_LOCAL;
419 /* normal constraints - add data */
420 if (nr==1) con = add_new_constraint(CONSTRAINT_TYPE_LOCLIKE);
421 else if (nr==2) con = add_new_constraint(CONSTRAINT_TYPE_ROTLIKE);
422 else if (nr==3) con = add_new_constraint(CONSTRAINT_TYPE_TRACKTO);
423 else if (nr==4) con = add_new_constraint(CONSTRAINT_TYPE_MINMAX);
424 else if (nr==5) con = add_new_constraint(CONSTRAINT_TYPE_LOCKTRACK);
426 Curve *cu= obsel->data;
428 con = add_new_constraint(CONSTRAINT_TYPE_FOLLOWPATH);
430 else if (nr==7) con = add_new_constraint(CONSTRAINT_TYPE_STRETCHTO);
431 else if (nr==8) con = add_new_constraint(CONSTRAINT_TYPE_SIZELIKE);
432 else if (nr==13) con = add_new_constraint(CONSTRAINT_TYPE_LOCLIMIT);
433 else if (nr==14) con = add_new_constraint(CONSTRAINT_TYPE_ROTLIMIT);
434 else if (nr==15) con = add_new_constraint(CONSTRAINT_TYPE_SIZELIMIT);
436 /* TODO: add a popup-menu to display list of available actions to use (like for pyconstraints) */
437 con = add_new_constraint(CONSTRAINT_TYPE_ACTION);
440 Curve *cu= obsel->data;
442 con = add_new_constraint(CONSTRAINT_TYPE_CLAMPTO);
448 /* popup a list of usable scripts */
449 menustr = buildmenu_pyconstraints(NULL, &scriptint);
450 scriptint = pupmenu(menustr);
453 /* only add constraint if a script was chosen */
456 con = add_new_constraint(CONSTRAINT_TYPE_PYTHON);
457 validate_pyconstraint_cb(con->data, &scriptint);
459 /* make sure target allowance is set correctly */
460 BPY_pyconstraint_update(ob, con);
464 con = add_new_constraint(CONSTRAINT_TYPE_CHILDOF);
466 /* if this constraint is being added to a posechannel, make sure
467 * the constraint gets evaluated in pose-space
470 con->ownspace = CONSTRAINT_SPACE_POSE;
471 con->flag |= CONSTRAINT_SPACEONCE;
474 else if (nr==20) con = add_new_constraint(CONSTRAINT_TYPE_TRANSFORM);
475 else if (nr==21) con = add_new_constraint(CONSTRAINT_TYPE_DISTLIMIT);
477 if (con==NULL) return; /* paranoia */
480 BLI_addtail(&pchanact->constraints, con);
481 unique_constraint_name(con, &pchanact->constraints);
482 pchanact->constflag |= PCHAN_HAS_CONST; /* for draw */
483 if (proxylocked_constraints_owner(ob, pchanact))
484 con->flag |= CONSTRAINT_PROXY_LOCAL;
487 BLI_addtail(&ob->constraints, con);
488 unique_constraint_name(con, &ob->constraints);
489 if (proxylocked_constraints_owner(ob, NULL))
490 con->flag |= CONSTRAINT_PROXY_LOCAL;
496 set_constraint_nth_target(con, ob, pchansel->name, 0);
499 set_constraint_nth_target(con, obsel, "", 0);
501 else if (ELEM4(nr, 11, 13, 14, 15)==0) { /* add new empty as target */
502 Base *base= BASACT, *newbase;
505 obt= add_object(OB_EMPTY);
508 newbase->lay= base->lay;
509 obt->lay= newbase->lay;
511 /* transform cent to global coords for loc */
514 VecMat4MulVecfl(obt->loc, ob->obmat, pchanact->pose_tail);
516 VecMat4MulVecfl(obt->loc, ob->obmat, pchanact->pose_head);
519 VECCOPY(obt->loc, ob->obmat[3]);
521 set_constraint_nth_target(con, obt, "", 0);
523 /* restore, add_object sets active */
525 base->flag |= SELECT;
529 con->flag |= CONSTRAINT_ACTIVE;
530 for (con= con->prev; con; con= con->prev)
531 con->flag &= ~CONSTRAINT_ACTIVE;
533 DAG_scene_sort(G.scene); // sort order of objects
536 ob->pose->flag |= POSE_RECALC; // sort pose channels
537 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); // and all its relations
540 DAG_object_flush_update(G.scene, ob, OB_RECALC_OB); // and all its relations
542 allqueue(REDRAWVIEW3D, 0);
543 allqueue(REDRAWBUTSOBJECT, 0);
544 allqueue(REDRAWBUTSEDIT, 0);
545 allqueue(REDRAWOOPS, 0);
548 BIF_undo_push("Add IK Constraint");
550 BIF_undo_push("Add Constraint");
554 /* Remove all constraints from the active object */
555 void ob_clear_constraints (void)
559 /* paranoia checks */
560 if ((ob==NULL) || (ob==G.obedit) || (ob->flag & OB_POSEMODE))
563 /* get user permission */
564 if (okee("Clear Constraints")==0)
568 free_constraints(&ob->constraints);
571 DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
573 allqueue(REDRAWVIEW3D, 0);
574 allqueue(REDRAWBUTSOBJECT, 0);
575 allqueue(REDRAWOOPS, 0);
577 BIF_undo_push("Clear Constraint(s)");
580 /* Rename the given constraint
581 * - con already has the new name
583 void rename_constraint (Object *ob, bConstraint *con, char *oldname)
586 bConstraintChannel *conchan;
587 ListBase *conlist= NULL;
591 /* get context by searching for con (primitive...) */
592 for (tcon= ob->constraints.first; tcon; tcon= tcon->next) {
598 conlist= &ob->constraints;
605 for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
606 for (tcon= pchan->constraints.first; tcon; tcon= tcon->next) {
615 conlist= &pchan->constraints;
616 channame= pchan->name;
621 printf("rename constraint failed\n"); /* should not happen in UI */
625 /* first make sure it's a unique name within context */
626 unique_constraint_name (con, conlist);
630 for (conchan= ob->constraintChannels.first; conchan; conchan= conchan->next) {
631 if ( strcmp(oldname, conchan->name)==0 )
632 BLI_strncpy(conchan->name, con->name, sizeof(conchan->name));
638 bActionChannel *achan= get_action_channel(ob->action, channame);
640 conchan= get_constraint_channel(&achan->constraintChannels, oldname);
642 BLI_strncpy(conchan->name, con->name, sizeof(conchan->name));
648 /* ------------- Constraint Sanity Testing ------------------- */
650 /* checks validity of object pointers, and NULLs,
651 * if Bone doesnt exist it sets the CONSTRAINT_DISABLE flag
653 static void test_constraints (Object *owner, const char substring[])
656 ListBase *conlist= NULL;
659 if (owner==NULL) return;
662 if (strlen(substring)) {
663 switch (owner->type) {
665 type = CONSTRAINT_OBTYPE_BONE;
668 type = CONSTRAINT_OBTYPE_OBJECT;
673 type = CONSTRAINT_OBTYPE_OBJECT;
675 /* Get the constraint list for this object */
677 case CONSTRAINT_OBTYPE_OBJECT:
678 conlist = &owner->constraints;
680 case CONSTRAINT_OBTYPE_BONE:
685 bone = get_named_bone( ((bArmature *)owner->data), substring );
686 chan = get_pose_channel(owner->pose, substring);
688 conlist = &chan->constraints;
694 /* Check all constraints - is constraint valid? */
696 for (curcon = conlist->first; curcon; curcon=curcon->next) {
697 bConstraintTypeInfo *cti= constraint_get_typeinfo(curcon);
698 ListBase targets = {NULL, NULL};
699 bConstraintTarget *ct;
701 /* clear disabled-flag first */
702 curcon->flag &= ~CONSTRAINT_DISABLE;
704 /* Check specialised data (settings) for constraints that need this */
705 if (curcon->type == CONSTRAINT_TYPE_PYTHON) {
706 bPythonConstraint *data = curcon->data;
708 /* is there are valid script? */
709 if (data->text == NULL) {
710 curcon->flag |= CONSTRAINT_DISABLE;
712 else if (BPY_is_pyconstraint(data->text)==0) {
713 curcon->flag |= CONSTRAINT_DISABLE;
716 /* does the constraint require target input... also validates targets */
717 BPY_pyconstraint_update(owner, curcon);
720 /* targets have already been checked for this */
723 else if (curcon->type == CONSTRAINT_TYPE_KINEMATIC) {
724 bKinematicConstraint *data = curcon->data;
726 /* bad: we need a separate set of checks here as poletarget is
727 * optional... otherwise poletarget must exist too or else
728 * the constraint is deemed invalid
730 if (exist_object(data->tar) == 0) {
732 curcon->flag |= CONSTRAINT_DISABLE;
734 else if (data->tar == owner) {
735 if (!get_named_bone(get_armature(owner), data->subtarget)) {
736 curcon->flag |= CONSTRAINT_DISABLE;
741 if (exist_object(data->poletar) == 0) {
742 data->poletar = NULL;
743 curcon->flag |= CONSTRAINT_DISABLE;
745 else if (data->poletar == owner) {
746 if (!get_named_bone(get_armature(owner), data->polesubtarget)) {
747 curcon->flag |= CONSTRAINT_DISABLE;
752 /* targets have already been checked for this */
755 else if (curcon->type == CONSTRAINT_TYPE_ACTION) {
756 bActionConstraint *data = curcon->data;
758 /* validate action */
759 if (data->act == NULL)
760 curcon->flag |= CONSTRAINT_DISABLE;
762 else if (curcon->type == CONSTRAINT_TYPE_FOLLOWPATH) {
763 bFollowPathConstraint *data = curcon->data;
765 /* don't allow track/up axes to be the same */
766 if (data->upflag==data->trackflag)
767 curcon->flag |= CONSTRAINT_DISABLE;
768 if (data->upflag+3==data->trackflag)
769 curcon->flag |= CONSTRAINT_DISABLE;
771 else if (curcon->type == CONSTRAINT_TYPE_TRACKTO) {
772 bTrackToConstraint *data = curcon->data;
774 /* don't allow track/up axes to be the same */
775 if (data->reserved2==data->reserved1)
776 curcon->flag |= CONSTRAINT_DISABLE;
777 if (data->reserved2+3==data->reserved1)
778 curcon->flag |= CONSTRAINT_DISABLE;
780 else if (curcon->type == CONSTRAINT_TYPE_LOCKTRACK) {
781 bLockTrackConstraint *data = curcon->data;
783 if (data->lockflag==data->trackflag)
784 curcon->flag |= CONSTRAINT_DISABLE;
785 if (data->lockflag+3==data->trackflag)
786 curcon->flag |= CONSTRAINT_DISABLE;
789 /* Check targets for constraints */
790 if (cti && cti->get_constraint_targets) {
791 cti->get_constraint_targets(curcon, &targets);
793 /* disable and clear constraints targets that are incorrect */
794 for (ct= targets.first; ct; ct= ct->next) {
795 /* general validity checks (for those constraints that need this) */
796 if (exist_object(ct->tar) == 0) {
798 curcon->flag |= CONSTRAINT_DISABLE;
800 else if (ct->tar == owner) {
801 if (!get_named_bone(get_armature(owner), ct->subtarget)) {
802 curcon->flag |= CONSTRAINT_DISABLE;
806 /* target checks for specific constraints */
807 if (ELEM(curcon->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO)) {
809 if (ct->tar->type != OB_CURVE) {
811 curcon->flag |= CONSTRAINT_DISABLE;
814 Curve *cu= ct->tar->data;
816 /* auto-set 'Path' setting on curve so this works */
823 /* free any temporary targets */
824 if (cti->flush_constraint_targets)
825 cti->flush_constraint_targets(curcon, &targets, 0);
831 static void test_bonelist_constraints (Object *owner, ListBase *list)
835 for (bone = list->first; bone; bone = bone->next) {
836 test_constraints(owner, bone->name);
837 test_bonelist_constraints(owner, &bone->childbase);
841 void object_test_constraints (Object *owner)
843 test_constraints(owner, "");
845 if (owner->type==OB_ARMATURE) {
846 bArmature *arm= get_armature(owner);
849 test_bonelist_constraints(owner, &arm->bonebase);
853 /* ********************** CONSTRAINT-SPECIFIC STUFF ********************* */
854 /* ------------- PyConstraints ------------------ */
856 /* this callback sets the text-file to be used for selected menu item */
857 void validate_pyconstraint_cb (void *arg1, void *arg2)
859 bPythonConstraint *data = arg1;
861 int index = *((int *)arg2);
864 /* exception for no script */
866 /* innovative use of a for...loop to search */
867 for (text=G.main->text.first, i=1; text && index!=i; i++, text=text->id.next);
872 /* this returns a string for the list of usable pyconstraint script names */
873 char *buildmenu_pyconstraints (Text *con_text, int *pyconindex)
875 DynStr *pupds= BLI_dynstr_new();
881 /* add title first */
882 sprintf(buf, "Scripts: %%t|[None]%%x0|");
883 BLI_dynstr_append(pupds, buf);
885 /* init active-index first */
886 if (con_text == NULL)
889 /* loop through markers, adding them */
890 for (text=G.main->text.first, i=1; text; i++, text=text->id.next) {
891 /* this is important to ensure that right script is shown as active */
892 if (text == con_text) *pyconindex = i;
894 /* only include valid pyconstraint scripts */
895 if (BPY_is_pyconstraint(text)) {
896 BLI_dynstr_append(pupds, text->id.name+2);
898 sprintf(buf, "%%x%d", i);
899 BLI_dynstr_append(pupds, buf);
902 BLI_dynstr_append(pupds, "|");
906 /* convert to normal MEM_malloc'd string */
907 str= BLI_dynstr_get_cstring(pupds);
908 BLI_dynstr_free(pupds);
913 /* this callback gets called when the 'refresh' button of a pyconstraint gets pressed */
914 void update_pyconstraint_cb (void *arg1, void *arg2)
916 Object *owner= (Object *)arg1;
917 bConstraint *con= (bConstraint *)arg2;
920 BPY_pyconstraint_update(owner, con);
923 /* ------------- Child-Of Constraint ------------------ */
925 /* ChildOf Constraint - set inverse callback */
926 void childof_const_setinv (void *conv, void *unused)
928 bConstraint *con= (bConstraint *)conv;
929 bChildOfConstraint *data= (bChildOfConstraint *)con->data;
931 bPoseChannel *pchan= NULL;
933 /* try to find a pose channel */
935 pchan= get_active_posechannel(ob);
937 /* calculate/set inverse matrix */
939 float pmat[4][4], cinf;
940 float imat[4][4], tmat[4][4];
942 /* make copy of pchan's original pose-mat (for use later) */
943 Mat4CpyMat4(pmat, pchan->pose_mat);
945 /* disable constraint for pose to be solved without it */
949 /* solve pose without constraint */
952 /* determine effect of constraint by removing the newly calculated
953 * pchan->pose_mat from the original pchan->pose_mat, thus determining
954 * the effect of the constraint
956 Mat4Invert(imat, pchan->pose_mat);
957 Mat4MulMat4(tmat, imat, pmat);
958 Mat4Invert(data->invmat, tmat);
960 /* recalculate pose with new inv-mat */
965 /* use what_does_parent to find inverse - just like for normal parenting.
966 * NOTE: what_does_parent uses a static workob defined in object.c
968 what_does_parent(ob);
969 Mat4Invert(data->invmat, workob.obmat);
972 Mat4One(data->invmat);
975 /* ChildOf Constraint - clear inverse callback */
976 void childof_const_clearinv (void *conv, void *unused)
978 bConstraint *con= (bConstraint *)conv;
979 bChildOfConstraint *data= (bChildOfConstraint *)con->data;
981 /* simply clear the matrix */
982 Mat4One(data->invmat);