diff options
Diffstat (limited to 'source/blender/src/editconstraint.c')
-rw-r--r-- | source/blender/src/editconstraint.c | 1103 |
1 files changed, 0 insertions, 1103 deletions
diff --git a/source/blender/src/editconstraint.c b/source/blender/src/editconstraint.c deleted file mode 100644 index e0588b4c2a0..00000000000 --- a/source/blender/src/editconstraint.c +++ /dev/null @@ -1,1103 +0,0 @@ -/** - * $Id$ - * - * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** - */ - -#include <stdio.h> -#include <string.h> - -#include "MEM_guardedalloc.h" - -#include "BLI_blenlib.h" -#include "BLI_arithb.h" - -#include "DNA_action_types.h" -#include "DNA_armature_types.h" -#include "DNA_constraint_types.h" -#include "DNA_curve_types.h" -#include "DNA_object_types.h" -#include "DNA_scene_types.h" -#include "DNA_screen_types.h" -#include "DNA_text_types.h" -#include "DNA_view3d_types.h" - -#include "BKE_action.h" -#include "BKE_armature.h" -#include "BKE_constraint.h" -#include "BKE_depsgraph.h" -#include "BKE_global.h" -#include "BKE_main.h" -#include "BKE_ipo.h" -#include "BKE_object.h" -#include "BKE_utildefines.h" - -#include "BIF_editaction.h" -#include "BIF_editarmature.h" -#include "BIF_editconstraint.h" -#include "BIF_poseobject.h" -#include "BIF_interface.h" -#include "BIF_screen.h" -#include "BIF_space.h" -#include "BIF_toolbox.h" - -#include "BPY_extern.h" - -#include "blendef.h" -#include "nla.h" -#include "mydevice.h" - - -ListBase *get_active_constraint_channels (Object *ob, int forcevalid) -{ - char ipstr[64]; - - if (!ob) - return NULL; - - /* See if we are a bone constraint */ - if (ob->flag & OB_POSEMODE) { - bActionChannel *achan; - bPoseChannel *pchan; - - pchan = get_active_posechannel(ob); - if (pchan) { - - /* Make sure we have an action */ - if (!ob->action){ - if (!forcevalid) - return NULL; - - ob->action=add_empty_action("Action"); - } - - /* Make sure we have an actionchannel */ - achan = get_action_channel(ob->action, pchan->name); - if (!achan){ - if (!forcevalid) - return NULL; - - achan = MEM_callocN (sizeof(bActionChannel), "actionChannel"); - - strcpy (achan->name, pchan->name); - sprintf (ipstr, "%s.%s", ob->action->id.name+2, achan->name); - ipstr[23]=0; - achan->ipo= add_ipo(ipstr, ID_AC); - - BLI_addtail (&ob->action->chanbase, achan); - } - - return &achan->constraintChannels; - } - else return NULL; - } - /* else we return object constraints */ - else { - if(ob->ipoflag & OB_ACTION_OB) { - bActionChannel *achan = get_action_channel(ob->action, "Object"); - if(achan) - return &achan->constraintChannels; - else - return NULL; - } - - return &ob->constraintChannels; - } -} - - -/* if object in posemode, active bone constraints, else object constraints */ -ListBase *get_active_constraints(Object *ob) -{ - if (!ob) - return NULL; - - if (ob->flag & OB_POSEMODE) { - bPoseChannel *pchan; - - pchan = get_active_posechannel(ob); - if (pchan) - return &pchan->constraints; - } - else - return &ob->constraints; - - return NULL; -} - -/* single constraint */ -bConstraint *get_active_constraint(Object *ob) -{ - ListBase *lb= get_active_constraints(ob); - - if (lb) { - bConstraint *con; - for (con= lb->first; con; con=con->next) - if (con->flag & CONSTRAINT_ACTIVE) - return con; - } - return NULL; -} - -/* single channel, for ipo */ -bConstraintChannel *get_active_constraint_channel(Object *ob) -{ - bConstraint *con; - bConstraintChannel *chan; - - if (ob->flag & OB_POSEMODE) { - if(ob->action) { - bPoseChannel *pchan; - - pchan = get_active_posechannel(ob); - if (pchan) { - for (con= pchan->constraints.first; con; con= con->next) - if (con->flag & CONSTRAINT_ACTIVE) - break; - if (con) { - bActionChannel *achan = get_action_channel(ob->action, pchan->name); - if (achan) { - for (chan= achan->constraintChannels.first; chan; chan= chan->next) - if (!strcmp(chan->name, con->name)) - break; - return chan; - } - } - } - } - } - else { - for(con= ob->constraints.first; con; con= con->next) - if(con->flag & CONSTRAINT_ACTIVE) - break; - if(con) { - ListBase *lb= get_active_constraint_channels(ob, 0); - - if(lb) { - for(chan= lb->first; chan; chan= chan->next) - if(!strcmp(chan->name, con->name)) - break; - return chan; - } - } - } - - return NULL; -} - - -bConstraint *add_new_constraint(short type) -{ - bConstraint *con; - bConstraintTypeInfo *cti; - - con = MEM_callocN(sizeof(bConstraint), "constraint"); - - /* Set up a generic constraint datablock */ - con->type = type; - con->flag |= CONSTRAINT_EXPAND; - con->enforce = 1.0F; - strcpy(con->name, "Const"); - - /* Load the data for it */ - cti = constraint_get_typeinfo(con); - if (cti) { - con->data = MEM_callocN(cti->size, cti->structName); - - /* only constraints that change any settings need this */ - if (cti->new_data) - cti->new_data(con->data); - } - - return con; -} - -void add_constraint_to_object(bConstraint *con, Object *ob) -{ - ListBase *list; - list = &ob->constraints; - - if (list) { - unique_constraint_name(con, list); - BLI_addtail(list, con); - - con->flag |= CONSTRAINT_ACTIVE; - for (con= con->prev; con; con= con->prev) - con->flag &= ~CONSTRAINT_ACTIVE; - } -} - -/* checks validity of object pointers, and NULLs, - * if Bone doesnt exist it sets the CONSTRAINT_DISABLE flag - */ -static void test_constraints (Object *owner, const char substring[]) -{ - - bConstraint *curcon; - ListBase *conlist= NULL; - int type; - - if (owner==NULL) return; - - /* Check parents */ - /* Get the constraint list for this object */ - - if (strlen (substring)) { - switch (owner->type) { - case OB_ARMATURE: - type = CONSTRAINT_OBTYPE_BONE; - break; - default: - type = CONSTRAINT_OBTYPE_OBJECT; - break; - } - } - else - type = CONSTRAINT_OBTYPE_OBJECT; - - - switch (type) { - case CONSTRAINT_OBTYPE_OBJECT: - conlist = &owner->constraints; - break; - case CONSTRAINT_OBTYPE_BONE: - { - Bone *bone; - bPoseChannel *chan; - - bone = get_named_bone( ((bArmature *)owner->data ), substring ); - chan = get_pose_channel(owner->pose, substring); - if (bone && chan) { - conlist = &chan->constraints; - } - } - break; - } - - /* Check all constraints - is constraint valid? */ - if (conlist) { - for (curcon = conlist->first; curcon; curcon=curcon->next) { - curcon->flag &= ~CONSTRAINT_DISABLE; - - switch (curcon->type) { - case CONSTRAINT_TYPE_PYTHON: - { - bPythonConstraint *data = curcon->data; - - /* is there are valid script? */ - if (!data->text) { - curcon->flag |= CONSTRAINT_DISABLE; - break; - } - else if (!BPY_is_pyconstraint(data->text)) { - curcon->flag |= CONSTRAINT_DISABLE; - break; - } - - /* does the constraint require target input... also validates targets */ - BPY_pyconstraint_update(owner, curcon); - } - break; - case CONSTRAINT_TYPE_ACTION: - { - bActionConstraint *data = curcon->data; - - if (!exist_object(data->tar)) { - data->tar = NULL; - curcon->flag |= CONSTRAINT_DISABLE; - break; - } - - if ( (data->tar == owner) && - (!get_named_bone(get_armature(owner), - data->subtarget))) { - curcon->flag |= CONSTRAINT_DISABLE; - break; - } - } - break; - case CONSTRAINT_TYPE_LOCLIKE: - { - bLocateLikeConstraint *data = curcon->data; - - if (!exist_object(data->tar)) { - data->tar = NULL; - curcon->flag |= CONSTRAINT_DISABLE; - break; - } - - if ( (data->tar == owner) && - (!get_named_bone(get_armature(owner), - data->subtarget))) { - curcon->flag |= CONSTRAINT_DISABLE; - break; - } - } - break; - case CONSTRAINT_TYPE_MINMAX: - { - bMinMaxConstraint *data = curcon->data; - - if (!exist_object(data->tar)) { - data->tar = NULL; - curcon->flag |= CONSTRAINT_DISABLE; - break; - } - - if ( (data->tar == owner) && - (!get_named_bone(get_armature(owner), - data->subtarget))) { - curcon->flag |= CONSTRAINT_DISABLE; - break; - } - } - break; - case CONSTRAINT_TYPE_ROTLIKE: - { - bRotateLikeConstraint *data = curcon->data; - - if (!exist_object(data->tar)) { - data->tar = NULL; - curcon->flag |= CONSTRAINT_DISABLE; - break; - } - - if ( (data->tar == owner) && - (!get_named_bone(get_armature(owner), - data->subtarget))) { - curcon->flag |= CONSTRAINT_DISABLE; - break; - } - } - break; - case CONSTRAINT_TYPE_SIZELIKE: - { - bSizeLikeConstraint *data = curcon->data; - - if (!exist_object(data->tar)) { - data->tar = NULL; - curcon->flag |= CONSTRAINT_DISABLE; - break; - } - - if ( (data->tar == owner) && - (!get_named_bone(get_armature(owner), - data->subtarget))) { - curcon->flag |= CONSTRAINT_DISABLE; - break; - } - } - break; - case CONSTRAINT_TYPE_KINEMATIC: - { - bKinematicConstraint *data = curcon->data; - - if (!exist_object(data->tar)) { - data->tar = NULL; - curcon->flag |= CONSTRAINT_DISABLE; - } - else if ( (data->tar == owner) && - (!get_named_bone(get_armature(owner), - data->subtarget))) { - curcon->flag |= CONSTRAINT_DISABLE; - } - - if (data->poletar && !exist_object(data->poletar)) { - data->poletar = NULL; - } - else if ( (data->poletar == owner) && - (!get_named_bone(get_armature(owner), - data->polesubtarget))) { - curcon->flag |= CONSTRAINT_DISABLE; - } - - } - break; - case CONSTRAINT_TYPE_TRACKTO: - { - bTrackToConstraint *data = curcon->data; - if (!exist_object(data->tar)) { - data->tar = NULL; - curcon->flag |= CONSTRAINT_DISABLE; - break; - } - - if ( (data->tar == owner) && - (!get_named_bone(get_armature(owner), - data->subtarget))) { - curcon->flag |= CONSTRAINT_DISABLE; - break; - } - if (data->reserved2==data->reserved1) { - curcon->flag |= CONSTRAINT_DISABLE; - break; - } - if (data->reserved2+3==data->reserved1) { - curcon->flag |= CONSTRAINT_DISABLE; - break; - } - } - break; - case CONSTRAINT_TYPE_LOCKTRACK: - { - bLockTrackConstraint *data = curcon->data; - - if (!exist_object(data->tar)) { - data->tar = NULL; - curcon->flag |= CONSTRAINT_DISABLE; - break; - } - - if ( (data->tar == owner) && - (!get_named_bone(get_armature(owner), - data->subtarget))) { - curcon->flag |= CONSTRAINT_DISABLE; - break; - } - - if (data->lockflag==data->trackflag) { - curcon->flag |= CONSTRAINT_DISABLE; - break; - } - if (data->lockflag+3==data->trackflag) { - curcon->flag |= CONSTRAINT_DISABLE; - break; - } - } - break; - case CONSTRAINT_TYPE_STRETCHTO: - { - bStretchToConstraint *data = curcon->data; - - if (!exist_object(data->tar)) { - data->tar = NULL; - curcon->flag |= CONSTRAINT_DISABLE; - break; - } - - if ( (data->tar == owner) && - (!get_named_bone(get_armature(owner), - data->subtarget))) { - curcon->flag |= CONSTRAINT_DISABLE; - break; - } - } - break; - case CONSTRAINT_TYPE_FOLLOWPATH: - { - bFollowPathConstraint *data = curcon->data; - - if (!exist_object(data->tar)) { - data->tar = NULL; - curcon->flag |= CONSTRAINT_DISABLE; - break; - } - if (data->tar->type != OB_CURVE) { - data->tar = NULL; - curcon->flag |= CONSTRAINT_DISABLE; - break; - } - if (data->upflag==data->trackflag) { - curcon->flag |= CONSTRAINT_DISABLE; - break; - } - if (data->upflag+3==data->trackflag) { - curcon->flag |= CONSTRAINT_DISABLE; - break; - } - } - break; - case CONSTRAINT_TYPE_CLAMPTO: - { - bClampToConstraint *data = curcon->data; - - if (!exist_object(data->tar)) { - data->tar = NULL; - curcon->flag |= CONSTRAINT_DISABLE; - break; - } - - if (data->tar->type != OB_CURVE) { - data->tar = NULL; - curcon->flag |= CONSTRAINT_DISABLE; - break; - } - else { - Curve *cu= data->tar->data; - - /* auto-set 'Path' setting on curve so this works */ - cu->flag |= CU_PATH; - } - } - break; - case CONSTRAINT_TYPE_TRANSFORM: - { - bTransformConstraint *data = curcon->data; - - if (!exist_object(data->tar)) { - data->tar = NULL; - curcon->flag |= CONSTRAINT_DISABLE; - break; - } - - if ( (data->tar == owner) && - (!get_named_bone(get_armature(owner), - data->subtarget))) { - curcon->flag |= CONSTRAINT_DISABLE; - break; - } - } - break; - } - } - } -} - -static void test_bonelist_constraints (Object *owner, ListBase *list) -{ - Bone *bone; - - for (bone = list->first; bone; bone=bone->next) { - - test_constraints(owner, bone->name); - test_bonelist_constraints (owner, &bone->childbase); - } -} - -void object_test_constraints (Object *owner) -{ - test_constraints(owner, ""); - - if(owner->type==OB_ARMATURE) { - bArmature *arm; - arm = get_armature(owner); - if (arm) - test_bonelist_constraints (owner, &arm->bonebase); - } - -} - -/* helper function for add_constriant - sets the last target for the active constraint */ -static void set_constraint_nth_target(bConstraint *con, Object *target, char subtarget[], int index) -{ - bConstraintTypeInfo *cti= constraint_get_typeinfo(con); - ListBase targets = {NULL, NULL}; - bConstraintTarget *ct; - int num_targets, i; - - if (cti && cti->get_constraint_targets) { - cti->get_constraint_targets(con, &targets); - num_targets= BLI_countlist(&targets); - - if (index < 0) { - if (abs(index) < num_targets) - index= num_targets - abs(index); - else - index= num_targets - 1; - } - else if (index >= num_targets) { - index= num_targets - 1; - } - - for (ct=targets.first, i=0; ct; ct= ct->next, i++) { - if (i == index) { - ct->tar= target; - strcpy(ct->subtarget, subtarget); - break; - } - } - - if (cti->flush_constraint_targets) - cti->flush_constraint_targets(con, &targets, 0); - } -} - -/* context: active object in posemode, active channel, optional selected channel */ -void add_constraint(int only_IK) -{ - Object *ob= OBACT, *obsel=NULL; - bPoseChannel *pchanact=NULL, *pchansel=NULL; - bConstraint *con=NULL; - Base *base; - short nr; - - /* paranoia checks */ - if(ob==NULL || ob==G.obedit) return; - - if(ob->pose && (ob->flag & OB_POSEMODE)) { - bArmature *arm= ob->data; - - /* find active channel */ - pchanact= get_active_posechannel(ob); - if(pchanact==NULL) return; - - /* check protection */ - if(ob->proxy && (pchanact->bone->layer & arm->layer_protected)) { - error("Bone is Proxy protected"); - return; - } - - /* find selected bone */ - for(pchansel= ob->pose->chanbase.first; pchansel; pchansel= pchansel->next) { - if(pchansel!=pchanact) - if(pchansel->bone->flag & BONE_SELECTED) - if(pchansel->bone->layer & arm->layer) - break; - } - } - - /* find selected object */ - for(base= FIRSTBASE; base; base= base->next) - if( TESTBASE(base) && base->object!=ob ) - obsel= base->object; - - /* the only_IK caller has checked for posemode! */ - if(only_IK) { - for(con= pchanact->constraints.first; con; con= con->next) { - if(con->type==CONSTRAINT_TYPE_KINEMATIC) break; - } - if(con) { - error("Pose Channel already has IK"); - return; - } - - if(pchansel) - nr= pupmenu("Add IK Constraint%t|To Active Bone%x10"); - else if(obsel) - nr= pupmenu("Add IK Constraint%t|To Active Object%x10"); - else - nr= pupmenu("Add IK Constraint%t|To New Empty Object%x10|Without Target%x11"); - } - else { - if(pchanact) { - if(pchansel) - nr= pupmenu("Add Constraint to Active Bone%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Action%x16|Script%x18"); - else if(obsel && obsel->type==OB_CURVE) - nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6|Clamp To%x17|Stretch To%x7|%l|Action%x16|Script%x18"); - else if(obsel) - 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|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Action%x16|Script%x18"); - else - nr= pupmenu("Add Constraint to New Empty Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Action%x16|Script%x18"); - } - else { - if(obsel && obsel->type==OB_CURVE) - nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6|Clamp To%x17|%l|Action%x16|Script%x18"); - else if(obsel) - nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|%l|Action%x16|Script%x18"); - else - nr= pupmenu("Add Constraint to New Empty Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|%l|Action%x16|Script%x18"); - } - } - - if(nr<1) return; - - /* handle IK separate */ - if(nr==10 || nr==11) { - - /* prevent weird chains... */ - if(pchansel) { - bPoseChannel *pchan= pchanact; - while(pchan) { - if(pchan==pchansel) break; - pchan= pchan->parent; - } - if(pchan) { - error("IK root cannot be linked to IK tip"); - return; - } - pchan= pchansel; - while(pchan) { - if(pchan==pchanact) break; - pchan= pchan->parent; - } - if(pchan) { - error("IK tip cannot be linked to IK root"); - return; - } - } - - con = add_new_constraint(CONSTRAINT_TYPE_KINEMATIC); - BLI_addtail(&pchanact->constraints, con); - unique_constraint_name(con, &pchanact->constraints); - pchanact->constflag |= PCHAN_HAS_IK; // for draw, but also for detecting while pose solving - if(nr==11) pchanact->constflag |= PCHAN_HAS_TARGET; - } - else { - - if (nr==1) con = add_new_constraint(CONSTRAINT_TYPE_LOCLIKE); - else if (nr==2) con = add_new_constraint(CONSTRAINT_TYPE_ROTLIKE); - else if (nr==3) con = add_new_constraint(CONSTRAINT_TYPE_TRACKTO); - else if (nr==4) con = add_new_constraint(CONSTRAINT_TYPE_MINMAX); - else if (nr==5) con = add_new_constraint(CONSTRAINT_TYPE_LOCKTRACK); - else if (nr==6) { - Curve *cu= obsel->data; - cu->flag |= CU_PATH; - con = add_new_constraint(CONSTRAINT_TYPE_FOLLOWPATH); - } - else if (nr==7) con = add_new_constraint(CONSTRAINT_TYPE_STRETCHTO); - else if (nr==8) con = add_new_constraint(CONSTRAINT_TYPE_SIZELIKE); - else if (nr==13) con = add_new_constraint(CONSTRAINT_TYPE_LOCLIMIT); - else if (nr==14) con = add_new_constraint(CONSTRAINT_TYPE_ROTLIMIT); - else if (nr==15) con = add_new_constraint(CONSTRAINT_TYPE_SIZELIMIT); - else if (nr==16) { - /* TODO: add a popup-menu to display list of available actions to use (like for pyconstraints) */ - con = add_new_constraint(CONSTRAINT_TYPE_ACTION); - } - else if (nr==17) { - Curve *cu= obsel->data; - cu->flag |= CU_PATH; - con = add_new_constraint(CONSTRAINT_TYPE_CLAMPTO); - } - else if (nr==18) { - char *menustr; - int scriptint= 0; - - /* popup a list of usable scripts */ - menustr = buildmenu_pyconstraints(NULL, &scriptint); - scriptint = pupmenu(menustr); - MEM_freeN(menustr); - - /* only add constraint if a script was chosen */ - if (scriptint) { - /* add constraint */ - con = add_new_constraint(CONSTRAINT_TYPE_PYTHON); - validate_pyconstraint_cb(con->data, &scriptint); - - /* make sure target allowance is set correctly */ - BPY_pyconstraint_update(ob, con); - } - } - else if (nr==19) { - con = add_new_constraint(CONSTRAINT_TYPE_CHILDOF); - - /* if this constraint is being added to a posechannel, make sure - * the constraint gets evaluated in pose-space - */ - if (pchanact) { - con->ownspace = CONSTRAINT_SPACE_POSE; - con->flag |= CONSTRAINT_SPACEONCE; - } - } - else if (nr==20) con = add_new_constraint(CONSTRAINT_TYPE_TRANSFORM); - - if (con==NULL) return; /* paranoia */ - - if (pchanact) { - BLI_addtail(&pchanact->constraints, con); - unique_constraint_name(con, &pchanact->constraints); - pchanact->constflag |= PCHAN_HAS_CONST; /* for draw */ - } - else { - BLI_addtail(&ob->constraints, con); - unique_constraint_name(con, &ob->constraints); - } - } - - /* set the target */ - if (pchansel) { - set_constraint_nth_target(con, ob, pchansel->name, 0); - } - else if(obsel) { - set_constraint_nth_target(con, obsel, "", 0); - } - else if (ELEM4(nr, 11, 13, 14, 15)==0) { /* add new empty as target */ - Base *base= BASACT, *newbase; - Object *obt; - - obt= add_object(OB_EMPTY); - /* set layers OK */ - newbase= BASACT; - newbase->lay= base->lay; - obt->lay= newbase->lay; - - /* transform cent to global coords for loc */ - if (pchanact) { - if(only_IK) - VecMat4MulVecfl(obt->loc, ob->obmat, pchanact->pose_tail); - else - VecMat4MulVecfl(obt->loc, ob->obmat, pchanact->pose_head); - } - else - VECCOPY(obt->loc, ob->obmat[3]); - - set_constraint_nth_target(con, obt, "", 0); - - /* restore, add_object sets active */ - BASACT= base; - base->flag |= SELECT; - } - - /* active flag */ - con->flag |= CONSTRAINT_ACTIVE; - for(con= con->prev; con; con= con->prev) - con->flag &= ~CONSTRAINT_ACTIVE; - - DAG_scene_sort(G.scene); // sort order of objects - - if (pchanact) { - ob->pose->flag |= POSE_RECALC; // sort pose channels - DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); // and all its relations - } - else - DAG_object_flush_update(G.scene, ob, OB_RECALC_OB); // and all its relations - - allqueue (REDRAWVIEW3D, 0); - allqueue (REDRAWBUTSOBJECT, 0); - allqueue (REDRAWOOPS, 0); - - if (only_IK) - BIF_undo_push("Add IK Constraint"); - else - BIF_undo_push("Add Constraint"); - -} - -void ob_clear_constraints(void) -{ - Object *ob= OBACT; - - /* paranoia checks */ - if(!ob) return; - if(ob==G.obedit || (ob->flag & OB_POSEMODE)) return; - - if(okee("Clear Constraints")==0) return; - - free_constraints(&ob->constraints); - - DAG_object_flush_update(G.scene, ob, OB_RECALC_OB); - - allqueue (REDRAWVIEW3D, 0); - allqueue (REDRAWBUTSOBJECT, 0); - allqueue (REDRAWOOPS, 0); - - BIF_undo_push("Clear Constraint(s)"); - -} - -/* con already has the new name */ -void rename_constraint(Object *ob, bConstraint *con, char *oldname) -{ - bConstraint *tcon; - bConstraintChannel *conchan; - ListBase *conlist= NULL; - int from_object= 0; - char *channame=""; - - /* get context by searching for con (primitive...) */ - for(tcon= ob->constraints.first; tcon; tcon= tcon->next) - if(tcon==con) - break; - - if(tcon) { - conlist= &ob->constraints; - channame= "Object"; - from_object= 1; - } - else if(ob->pose) { - bPoseChannel *pchan; - - for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { - for(tcon= pchan->constraints.first; tcon; tcon= tcon->next) { - if(tcon==con) - break; - } - if(tcon) - break; - } - if(tcon) { - conlist= &pchan->constraints; - channame= pchan->name; - } - } - - if(conlist==NULL) { - printf("rename constraint failed\n"); /* should not happen in UI */ - return; - } - - /* first make sure it's a unique name within context */ - unique_constraint_name (con, conlist); - - /* own channels */ - if(from_object) { - for(conchan= ob->constraintChannels.first; conchan; conchan= conchan->next) { - if( strcmp(oldname, conchan->name)==0 ) - BLI_strncpy(conchan->name, con->name, sizeof(conchan->name)); - } - } - /* own action */ - if(ob->action) { - bActionChannel *achan= get_action_channel(ob->action, channame); - if(achan) { - conchan= get_constraint_channel(&achan->constraintChannels, oldname); - if(conchan) - BLI_strncpy(conchan->name, con->name, sizeof(conchan->name)); - } - } - -} - -/* ********************** CONSTRAINT-SPECIFIC STUFF ********************* */ -/* ------------- PyConstraints ------------------ */ - -/* this callback sets the text-file to be used for selected menu item */ -void validate_pyconstraint_cb(void *arg1, void *arg2) -{ - bPythonConstraint *data = arg1; - Text *text; - int index = *((int *)arg2); - int i; - - /* innovative use of a for...loop to search */ - for (text=G.main->text.first, i=1; text && index!=i; i++, text=text->id.next); - data->text = text; -} - -/* this returns a string for the list of usable pyconstraint script names */ -char *buildmenu_pyconstraints(Text *con_text, int *pyconindex) -{ - Text *text; - char *menustr = MEM_callocN(128, "menustr pyconstraints"); - char *name, stmp[128]; - int buf = 128; - int used = strlen("Scripts: %t") + 1; - int i; - - sprintf(menustr, "%s", "Scripts: %t"); - - for (text=G.main->text.first, i=1; text; i++, text=text->id.next) { - /* this is important to ensure that right script is shown as active */ - if (text == con_text) *pyconindex = i; - - /* menu entry is length of name + 3(len(|%X)) + 6 characters for the int.*/ - if (BPY_is_pyconstraint(text)) { - name= text->id.name; - if (strlen(name)+used+10 >= buf) { - char *newbuf = MEM_callocN(buf+128, "menustr pyconstraints 2"); - memcpy(newbuf, menustr, used); - MEM_freeN(menustr); - menustr = newbuf; - buf += 128; - } - sprintf(stmp, "|%s%%x%d", name, i); - strcat(menustr, stmp); - used += strlen(name)+10; - } - } - - return menustr; -} - -/* this callback gets called when the 'refresh' button of a pyconstraint gets pressed */ -void update_pyconstraint_cb(void *arg1, void *arg2) -{ - Object *owner= (Object *)arg1; - bConstraint *con= (bConstraint *)arg2; - - if (owner && con) - BPY_pyconstraint_update(owner, con); -} - -/* ------------- Child-Of Constraint ------------------ */ - -/* ChildOf Constraint - set inverse callback */ -void childof_const_setinv (void *conv, void *unused) -{ - bChildOfConstraint *data= (bChildOfConstraint *)conv; - Object *ob= OBACT; - bPoseChannel *pchan= NULL; - - /* try to find a pose channel */ - if (ob && ob->pose) - pchan= get_active_posechannel(ob); - - /* calculate/set inverse matrix */ - if (pchan) { - bConstraintOb *cob; - float ctime= bsystem_time(ob, (float)G.scene->r.cfra, 0.0); /* not accurate... */ - float pmat[4][4], chmat[4][4], cimat[4][4]; - float vec0[3]={0,0,0}, vec1[3]={1,1,1}; - - /* make copies of pchan's original matrices (to be restored later) */ - Mat4CpyMat4(pmat, pchan->pose_mat); - Mat4CpyMat4(chmat, pchan->chan_mat); - Mat4CpyMat4(cimat, pchan->constinv); - - - /* clear pchan's transform (for constraint solving) */ - LocEulSizeToMat4(pchan->chan_mat, vec0, vec0, vec1); - Mat4MulMat4(pchan->pose_mat, pmat, cimat); - Mat4One(pchan->constinv); - Mat4One(data->invmat); - - - /* do constraint solving on pose-matrix containing no transforms - * N.B. code is copied from armature.c (where_is_pose_bone) - */ - cob= constraints_make_evalob(ob, pchan, CONSTRAINT_OBTYPE_BONE); - solve_constraints(&pchan->constraints, cob, ctime); - constraints_clear_evalob(cob); - - - /* parent-inverse matrix for this constraint is given by taking the - * local-space (i.e. without any standard parents + restpose) pose_matrix - * (that was calulated with no transforms applied), and inverting it. - */ - Mat4CpyMat4(pchan->constinv, pchan->pose_mat); - - constraint_mat_convertspace(ob, pchan, pchan->constinv, - CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL); - - Mat4Invert(data->invmat, pchan->constinv); - - - /* restore original matrices of pchan */ - Mat4CpyMat4(pchan->pose_mat, pmat); - Mat4CpyMat4(pchan->chan_mat, chmat); - Mat4CpyMat4(pchan->constinv, cimat); - } - else if (ob) { - /* use what_does_parent to find inverse - just like for normal parenting. - * NOTE: what_does_parent uses a static workob defined in object.c - */ - what_does_parent(ob); - Mat4Invert(data->invmat, workob.obmat); - } - else - Mat4One(data->invmat); -} - -/* ChildOf Constraint - clear inverse callback */ -void childof_const_clearinv (void *conv, void *unused) -{ - bChildOfConstraint *data= (bChildOfConstraint *)conv; - - /* simply clear the matrix */ - Mat4One(data->invmat); -} |