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