Blender V2.61 - r43446
|
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