Blender V2.61 - r43446

BL_ArmatureConstraint.cpp

Go to the documentation of this file.
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): none yet.
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 #include "DNA_constraint_types.h"
00034 #include "DNA_action_types.h"
00035 #include "BL_ArmatureConstraint.h"
00036 #include "BL_ArmatureObject.h"
00037 #include "BLI_math.h"
00038 #include "BLI_string.h"
00039 
00040 #ifdef WITH_PYTHON
00041 
00042 PyTypeObject BL_ArmatureConstraint::Type = {
00043     PyVarObject_HEAD_INIT(NULL, 0)
00044     "BL_ArmatureConstraint",
00045     sizeof(PyObjectPlus_Proxy),
00046     0,
00047     py_base_dealloc,
00048     0,
00049     0,
00050     0,
00051     0,
00052     py_base_repr,
00053     0,0,0,0,0,0,0,0,0,
00054     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
00055     0,0,0,0,0,0,0,
00056     Methods,
00057     0,
00058     0,
00059     &CValue::Type,
00060     0,0,0,0,0,0,
00061     py_base_new
00062 };
00063 
00064 PyObject* BL_ArmatureConstraint::py_repr(void)
00065 {
00066     return PyUnicode_FromString(m_name);
00067 }
00068 
00069 #endif // WITH_PYTHON
00070 
00071 BL_ArmatureConstraint::BL_ArmatureConstraint(
00072     BL_ArmatureObject *armature, 
00073     bPoseChannel *posechannel,
00074     bConstraint *constraint, 
00075     KX_GameObject* target,
00076     KX_GameObject* subtarget)
00077     : PyObjectPlus(), m_constraint(constraint), m_posechannel(posechannel), m_armature(armature)
00078 {
00079     m_target = target;
00080     m_blendtarget = (target) ? target->GetBlenderObject() : NULL;
00081     m_subtarget = subtarget;
00082     m_blendsubtarget = (subtarget) ? subtarget->GetBlenderObject() : NULL;
00083     m_pose = m_subpose = NULL;
00084     if (m_blendtarget) {
00085         copy_m4_m4(m_blendmat, m_blendtarget->obmat);
00086         if (m_blendtarget->type == OB_ARMATURE)
00087             m_pose = m_blendtarget->pose;
00088     }
00089     if (m_blendsubtarget) {
00090         copy_m4_m4(m_blendsubmat, m_blendsubtarget->obmat);
00091         if (m_blendsubtarget->type == OB_ARMATURE)
00092             m_subpose = m_blendsubtarget->pose;
00093     }
00094     if (m_target)
00095         m_target->RegisterObject(m_armature);
00096     if (m_subtarget)
00097         m_subtarget->RegisterObject(m_armature);
00098     BLI_snprintf(m_name, sizeof(m_name), "%s:%s", m_posechannel->name, m_constraint->name);
00099 }
00100 
00101 BL_ArmatureConstraint::~BL_ArmatureConstraint()
00102 {
00103     if (m_target)
00104         m_target->UnregisterObject(m_armature);
00105     if (m_subtarget)
00106         m_subtarget->UnregisterObject(m_armature);
00107 }
00108 
00109 BL_ArmatureConstraint* BL_ArmatureConstraint::GetReplica() const
00110 {
00111     BL_ArmatureConstraint* replica = new BL_ArmatureConstraint(*this);
00112     replica->ProcessReplica();
00113     return replica;
00114 }
00115 
00116 void BL_ArmatureConstraint::ReParent(BL_ArmatureObject* armature)
00117 {
00118     m_armature = armature;
00119     if (m_target)
00120         m_target->RegisterObject(armature);
00121     if (m_subtarget)
00122         m_subtarget->RegisterObject(armature);
00123     // find the corresponding constraint in the new armature object
00124     if (m_constraint) {
00125         bPose* newpose = armature->GetOrigPose();
00126         char* constraint = m_constraint->name;
00127         char* posechannel = m_posechannel->name;
00128         bPoseChannel* pchan;
00129         bConstraint* pcon;
00130         m_constraint = NULL;
00131         m_posechannel = NULL;
00132         // and locate the constraint
00133         for (pchan = (bPoseChannel*)newpose->chanbase.first; pchan; pchan=(bPoseChannel*)pchan->next) {
00134             if (!strcmp(pchan->name, posechannel)) {
00135                 // now locate the constraint
00136                 for (pcon = (bConstraint*)pchan->constraints.first; pcon; pcon=(bConstraint*)pcon->next) {
00137                     if (!strcmp(pcon->name, constraint)) {
00138                         m_constraint = pcon;
00139                         m_posechannel = pchan;
00140                         break;
00141                     }
00142                 }
00143                 break;
00144             }
00145         }
00146     }
00147 }
00148 
00149 void BL_ArmatureConstraint::Relink(CTR_Map<CTR_HashedPtr, void*> *obj_map)
00150 {
00151     void **h_obj = (*obj_map)[m_target];
00152     if (h_obj) {
00153         m_target->UnregisterObject(m_armature);
00154         m_target = (KX_GameObject*)(*h_obj);
00155         m_target->RegisterObject(m_armature);
00156     }
00157     h_obj = (*obj_map)[m_subtarget];
00158     if (h_obj) {
00159         m_subtarget->UnregisterObject(m_armature);
00160         m_subtarget = (KX_GameObject*)(*h_obj);
00161         m_subtarget->RegisterObject(m_armature);
00162     }
00163 }
00164 
00165 bool BL_ArmatureConstraint::UnlinkObject(SCA_IObject* clientobj)
00166 {
00167     bool res=false;
00168     if (clientobj == m_target) {
00169         m_target = NULL;
00170         res = true;
00171     }
00172     if (clientobj == m_subtarget) {
00173         m_subtarget = NULL;
00174         res = true;
00175     }
00176     return res;
00177 }
00178 
00179 void BL_ArmatureConstraint::UpdateTarget()
00180 {
00181     if (m_constraint && !(m_constraint->flag&CONSTRAINT_OFF) && (!m_blendtarget || m_target)) {
00182         if (m_blendtarget) {
00183             // external target, must be updated
00184             m_target->UpdateBlenderObjectMatrix(m_blendtarget);
00185             if (m_pose && m_target->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE)
00186                 // update the pose in case a bone is specified in the constraint target
00187                 m_blendtarget->pose = ((BL_ArmatureObject*)m_target)->GetOrigPose();
00188         }
00189         if (m_blendsubtarget && m_subtarget) {
00190             m_subtarget->UpdateBlenderObjectMatrix(m_blendsubtarget);
00191             if (m_subpose && m_subtarget->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE)
00192                 m_blendsubtarget->pose = ((BL_ArmatureObject*)m_target)->GetOrigPose();
00193         }
00194     }
00195 }
00196 
00197 void BL_ArmatureConstraint::RestoreTarget()
00198 {
00199     if (m_constraint && !(m_constraint->flag&CONSTRAINT_OFF) && (!m_blendtarget || m_target)) {
00200         if (m_blendtarget) {
00201             copy_m4_m4(m_blendtarget->obmat, m_blendmat);
00202             if (m_pose)
00203                 m_blendtarget->pose = m_pose;
00204         }
00205         if (m_blendsubtarget && m_subtarget) {
00206             copy_m4_m4(m_blendsubtarget->obmat, m_blendsubmat);
00207             if (m_subpose)
00208                 m_blendsubtarget->pose = m_subpose;
00209         }
00210     }
00211 }
00212 
00213 bool BL_ArmatureConstraint::Match(const char* posechannel, const char* constraint)
00214 {
00215     return (!strcmp(m_posechannel->name, posechannel) && !strcmp(m_constraint->name, constraint));
00216 }
00217 
00218 void BL_ArmatureConstraint::SetTarget(KX_GameObject* target)
00219 {
00220     if (m_blendtarget) {
00221         if (target != m_target) {
00222             m_target->UnregisterObject(m_armature);
00223             m_target = target;
00224             if (m_target)
00225                 m_target->RegisterObject(m_armature);
00226         }
00227     }
00228 
00229 }
00230 
00231 void BL_ArmatureConstraint::SetSubtarget(KX_GameObject* subtarget)
00232 {
00233     if (m_blendsubtarget) {
00234         if (subtarget != m_subtarget) {
00235             m_subtarget->UnregisterObject(m_armature);
00236             m_subtarget = subtarget;
00237             if (m_subtarget)
00238                 m_subtarget->RegisterObject(m_armature);
00239         }
00240     }
00241 
00242 }
00243 
00244 #ifdef WITH_PYTHON
00245 
00246 // PYTHON
00247 
00248 PyMethodDef BL_ArmatureConstraint::Methods[] = {
00249   {NULL,NULL} //Sentinel
00250 };
00251 
00252 // order of definition of attributes, must match Attributes[] array
00253 #define BCA_TYPE        0
00254 #define BCA_NAME        1
00255 #define BCA_ENFORCE     2
00256 #define BCA_HEADTAIL    3
00257 #define BCA_LINERROR    4
00258 #define BCA_ROTERROR    5
00259 #define BCA_TARGET      6
00260 #define BCA_SUBTARGET   7
00261 #define BCA_ACTIVE      8
00262 #define BCA_IKWEIGHT    9
00263 #define BCA_IKTYPE      10
00264 #define BCA_IKFLAG      11
00265 #define BCA_IKDIST      12
00266 #define BCA_IKMODE      13
00267 
00268 PyAttributeDef BL_ArmatureConstraint::Attributes[] = {
00269     // Keep these attributes in order of BCA_ defines!!! used by py_attr_getattr and py_attr_setattr
00270     KX_PYATTRIBUTE_RO_FUNCTION("type",BL_ArmatureConstraint,py_attr_getattr),   
00271     KX_PYATTRIBUTE_RO_FUNCTION("name",BL_ArmatureConstraint,py_attr_getattr),   
00272     KX_PYATTRIBUTE_RW_FUNCTION("enforce",BL_ArmatureConstraint,py_attr_getattr,py_attr_setattr),
00273     KX_PYATTRIBUTE_RW_FUNCTION("headtail",BL_ArmatureConstraint,py_attr_getattr,py_attr_setattr),
00274     KX_PYATTRIBUTE_RO_FUNCTION("lin_error",BL_ArmatureConstraint,py_attr_getattr),
00275     KX_PYATTRIBUTE_RO_FUNCTION("rot_error",BL_ArmatureConstraint,py_attr_getattr),
00276     KX_PYATTRIBUTE_RW_FUNCTION("target",BL_ArmatureConstraint,py_attr_getattr,py_attr_setattr),
00277     KX_PYATTRIBUTE_RW_FUNCTION("subtarget",BL_ArmatureConstraint,py_attr_getattr,py_attr_setattr),
00278     KX_PYATTRIBUTE_RW_FUNCTION("active",BL_ArmatureConstraint,py_attr_getattr,py_attr_setattr),
00279     KX_PYATTRIBUTE_RW_FUNCTION("ik_weight",BL_ArmatureConstraint,py_attr_getattr,py_attr_setattr),
00280     KX_PYATTRIBUTE_RO_FUNCTION("ik_type",BL_ArmatureConstraint,py_attr_getattr),
00281     KX_PYATTRIBUTE_RO_FUNCTION("ik_flag",BL_ArmatureConstraint,py_attr_getattr),
00282     KX_PYATTRIBUTE_RW_FUNCTION("ik_dist",BL_ArmatureConstraint,py_attr_getattr,py_attr_setattr),
00283     KX_PYATTRIBUTE_RW_FUNCTION("ik_mode",BL_ArmatureConstraint,py_attr_getattr,py_attr_setattr),
00284     
00285     { NULL }    //Sentinel
00286 };
00287 
00288 
00289 PyObject* BL_ArmatureConstraint::py_attr_getattr(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef)
00290 {
00291     BL_ArmatureConstraint* self= static_cast<BL_ArmatureConstraint*>(self_v);
00292     bConstraint* constraint = self->m_constraint;
00293     bKinematicConstraint* ikconstraint = (constraint && constraint->type == CONSTRAINT_TYPE_KINEMATIC) ? (bKinematicConstraint*)constraint->data : NULL;
00294     int attr_order = attrdef-Attributes;
00295 
00296     if (!constraint) {
00297         PyErr_SetString(PyExc_AttributeError, "constraint is NULL");
00298         return NULL;
00299     }
00300 
00301     switch (attr_order) {
00302     case BCA_TYPE:
00303         return PyLong_FromLong(constraint->type);
00304     case BCA_NAME:
00305         return PyUnicode_FromString(constraint->name);
00306     case BCA_ENFORCE:
00307         return PyFloat_FromDouble(constraint->enforce);
00308     case BCA_HEADTAIL:
00309         return PyFloat_FromDouble(constraint->headtail);
00310     case BCA_LINERROR:
00311         return PyFloat_FromDouble(constraint->lin_error);
00312     case BCA_ROTERROR:
00313         return PyFloat_FromDouble(constraint->rot_error);
00314     case BCA_TARGET:
00315         if (!self->m_target)    
00316             Py_RETURN_NONE;
00317         else
00318             return self->m_target->GetProxy();
00319     case BCA_SUBTARGET:
00320         if (!self->m_subtarget) 
00321             Py_RETURN_NONE;
00322         else
00323             return self->m_subtarget->GetProxy();
00324     case BCA_ACTIVE:
00325         return PyBool_FromLong(constraint->flag & CONSTRAINT_OFF);
00326     case BCA_IKWEIGHT:
00327     case BCA_IKTYPE:
00328     case BCA_IKFLAG:
00329     case BCA_IKDIST:
00330     case BCA_IKMODE:
00331         if (!ikconstraint) {
00332             PyErr_SetString(PyExc_AttributeError, "constraint is not of IK type");
00333             return NULL;
00334         }
00335         switch (attr_order) {
00336         case BCA_IKWEIGHT:
00337             return PyFloat_FromDouble((ikconstraint)?ikconstraint->weight:0.0);
00338         case BCA_IKTYPE:
00339             return PyLong_FromLong(ikconstraint->type);
00340         case BCA_IKFLAG:
00341             return PyLong_FromLong(ikconstraint->flag);
00342         case BCA_IKDIST:
00343             return PyFloat_FromDouble(ikconstraint->dist);
00344         case BCA_IKMODE:
00345             return PyLong_FromLong(ikconstraint->mode);
00346         }
00347         // should not come here
00348         break;
00349     }
00350     PyErr_SetString(PyExc_AttributeError, "constraint unknown attribute");
00351     return NULL;
00352 }
00353 
00354 int BL_ArmatureConstraint::py_attr_setattr(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
00355 {
00356     BL_ArmatureConstraint* self= static_cast<BL_ArmatureConstraint*>(self_v);
00357     bConstraint* constraint = self->m_constraint;
00358     bKinematicConstraint* ikconstraint = (constraint && constraint->type == CONSTRAINT_TYPE_KINEMATIC) ? (bKinematicConstraint*)constraint->data : NULL;
00359     int attr_order = attrdef-Attributes;
00360     int ival;
00361     double dval;
00362 //  char* sval;
00363     KX_GameObject *oval;
00364 
00365     if (!constraint) {
00366         PyErr_SetString(PyExc_AttributeError, "constraint is NULL");
00367         return PY_SET_ATTR_FAIL;
00368     }
00369     
00370     switch (attr_order) {
00371     case BCA_ENFORCE:
00372         dval = PyFloat_AsDouble(value);
00373         if (dval < 0.0f || dval > 1.0f) { /* also accounts for non float */
00374             PyErr_SetString(PyExc_AttributeError, "constraint.enforce = float: BL_ArmatureConstraint, expected a float between 0 and 1");
00375             return PY_SET_ATTR_FAIL;
00376         }
00377         constraint->enforce = dval;
00378         return PY_SET_ATTR_SUCCESS;
00379 
00380     case BCA_HEADTAIL:
00381         dval = PyFloat_AsDouble(value);
00382         if (dval < 0.0f || dval > 1.0f) { /* also accounts for non float */
00383             PyErr_SetString(PyExc_AttributeError, "constraint.headtail = float: BL_ArmatureConstraint, expected a float between 0 and 1");
00384             return PY_SET_ATTR_FAIL;
00385         }
00386         constraint->headtail = dval;
00387         return PY_SET_ATTR_SUCCESS;
00388 
00389     case BCA_TARGET:
00390         if (!ConvertPythonToGameObject(value, &oval, true, "constraint.target = value: BL_ArmatureConstraint"))
00391             return PY_SET_ATTR_FAIL; // ConvertPythonToGameObject sets the error
00392         self->SetTarget(oval);
00393         return PY_SET_ATTR_SUCCESS;
00394 
00395     case BCA_SUBTARGET:
00396         if (!ConvertPythonToGameObject(value, &oval, true, "constraint.subtarget = value: BL_ArmatureConstraint"))
00397             return PY_SET_ATTR_FAIL; // ConvertPythonToGameObject sets the error
00398         self->SetSubtarget(oval);
00399         return PY_SET_ATTR_SUCCESS;
00400 
00401     case BCA_ACTIVE:
00402         ival = PyObject_IsTrue( value );
00403         if (ival == -1) {
00404             PyErr_SetString(PyExc_AttributeError, "constraint.active = bool: BL_ArmatureConstraint, expected True or False");
00405             return PY_SET_ATTR_FAIL;
00406         }
00407         self->m_constraint->flag = (self->m_constraint->flag & ~CONSTRAINT_OFF) | ((ival)?0:CONSTRAINT_OFF);
00408         return PY_SET_ATTR_SUCCESS;
00409 
00410     case BCA_IKWEIGHT:
00411     case BCA_IKDIST:
00412     case BCA_IKMODE:
00413         if (!ikconstraint) {
00414             PyErr_SetString(PyExc_AttributeError, "constraint is not of IK type");
00415             return PY_SET_ATTR_FAIL;
00416         }
00417         switch (attr_order) {
00418         case BCA_IKWEIGHT:
00419             dval = PyFloat_AsDouble(value);
00420             if (dval < 0.0f || dval > 1.0f) { /* also accounts for non float */
00421                 PyErr_SetString(PyExc_AttributeError, "constraint.weight = float: BL_ArmatureConstraint, expected a float between 0 and 1");
00422                 return PY_SET_ATTR_FAIL;
00423             }
00424             ikconstraint->weight = dval;
00425             return PY_SET_ATTR_SUCCESS;
00426 
00427         case BCA_IKDIST:
00428             dval = PyFloat_AsDouble(value);
00429             if (dval < 0.0f) { /* also accounts for non float */
00430                 PyErr_SetString(PyExc_AttributeError, "constraint.ik_dist = float: BL_ArmatureConstraint, expected a positive float");
00431                 return PY_SET_ATTR_FAIL;
00432             }
00433             ikconstraint->dist = dval;
00434             return PY_SET_ATTR_SUCCESS;
00435 
00436         case BCA_IKMODE:
00437             ival = PyLong_AsLong(value);
00438             if (ival < 0) {
00439                 PyErr_SetString(PyExc_AttributeError, "constraint.ik_mode = integer: BL_ArmatureConstraint, expected a positive integer");
00440                 return PY_SET_ATTR_FAIL;
00441             }
00442             ikconstraint->mode = ival;
00443             return PY_SET_ATTR_SUCCESS;
00444         }
00445         // should not come here
00446         break;
00447 
00448     }
00449 
00450     PyErr_SetString(PyExc_AttributeError, "constraint unknown attribute");
00451     return PY_SET_ATTR_FAIL;
00452 }
00453 
00454 #endif // WITH_PYTHON