BL_ArmatureConstraint.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. /*
  2. * ***** BEGIN GPL LICENSE BLOCK *****
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License
  6. * as published by the Free Software Foundation; either version 2
  7. * of the License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software Foundation,
  16. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  17. *
  18. * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
  19. * All rights reserved.
  20. *
  21. * The Original Code is: all of this file.
  22. *
  23. * Contributor(s): none yet.
  24. *
  25. * ***** END GPL LICENSE BLOCK *****
  26. */
  27. /** \file gameengine/Converter/BL_ArmatureConstraint.cpp
  28. * \ingroup bgeconv
  29. */
  30. #include "DNA_constraint_types.h"
  31. #include "DNA_action_types.h"
  32. #include "BL_ArmatureConstraint.h"
  33. #include "BL_ArmatureObject.h"
  34. #include "BLI_math.h"
  35. #include "BLI_string.h"
  36. #include "KX_PythonInit.h"
  37. #ifdef WITH_PYTHON
  38. PyTypeObject BL_ArmatureConstraint::Type = {
  39. PyVarObject_HEAD_INIT(NULL, 0)
  40. "BL_ArmatureConstraint",
  41. sizeof(PyObjectPlus_Proxy),
  42. 0,
  43. py_base_dealloc,
  44. 0,
  45. 0,
  46. 0,
  47. 0,
  48. py_base_repr,
  49. 0,0,0,0,0,0,0,0,0,
  50. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
  51. 0,0,0,0,0,0,0,
  52. Methods,
  53. 0,
  54. 0,
  55. &CValue::Type,
  56. 0,0,0,0,0,0,
  57. py_base_new
  58. };
  59. PyObject *BL_ArmatureConstraint::py_repr(void)
  60. {
  61. return PyUnicode_FromString(m_name);
  62. }
  63. #endif // WITH_PYTHON
  64. BL_ArmatureConstraint::BL_ArmatureConstraint(
  65. BL_ArmatureObject *armature,
  66. bPoseChannel *posechannel,
  67. bConstraint *constraint,
  68. KX_GameObject* target,
  69. KX_GameObject* subtarget)
  70. : PyObjectPlus(), m_constraint(constraint), m_posechannel(posechannel), m_armature(armature)
  71. {
  72. m_target = target;
  73. m_blendtarget = (target) ? target->GetBlenderObject() : NULL;
  74. m_subtarget = subtarget;
  75. m_blendsubtarget = (subtarget) ? subtarget->GetBlenderObject() : NULL;
  76. m_pose = m_subpose = NULL;
  77. if (m_blendtarget) {
  78. copy_m4_m4(m_blendmat, m_blendtarget->obmat);
  79. if (m_blendtarget->type == OB_ARMATURE)
  80. m_pose = m_blendtarget->pose;
  81. }
  82. if (m_blendsubtarget) {
  83. copy_m4_m4(m_blendsubmat, m_blendsubtarget->obmat);
  84. if (m_blendsubtarget->type == OB_ARMATURE)
  85. m_subpose = m_blendsubtarget->pose;
  86. }
  87. if (m_target)
  88. m_target->RegisterObject(m_armature);
  89. if (m_subtarget)
  90. m_subtarget->RegisterObject(m_armature);
  91. BLI_snprintf(m_name, sizeof(m_name), "%s:%s", m_posechannel->name, m_constraint->name);
  92. }
  93. BL_ArmatureConstraint::~BL_ArmatureConstraint()
  94. {
  95. if (m_target)
  96. m_target->UnregisterObject(m_armature);
  97. if (m_subtarget)
  98. m_subtarget->UnregisterObject(m_armature);
  99. }
  100. BL_ArmatureConstraint* BL_ArmatureConstraint::GetReplica() const
  101. {
  102. BL_ArmatureConstraint* replica = new BL_ArmatureConstraint(*this);
  103. replica->ProcessReplica();
  104. return replica;
  105. }
  106. void BL_ArmatureConstraint::ReParent(BL_ArmatureObject* armature)
  107. {
  108. m_armature = armature;
  109. if (m_target)
  110. m_target->RegisterObject(armature);
  111. if (m_subtarget)
  112. m_subtarget->RegisterObject(armature);
  113. // find the corresponding constraint in the new armature object
  114. if (m_constraint) {
  115. bPose* newpose = armature->GetOrigPose();
  116. char* constraint = m_constraint->name;
  117. char* posechannel = m_posechannel->name;
  118. bPoseChannel* pchan;
  119. bConstraint* pcon;
  120. m_constraint = NULL;
  121. m_posechannel = NULL;
  122. // and locate the constraint
  123. for (pchan = (bPoseChannel*)newpose->chanbase.first; pchan; pchan = (bPoseChannel*)pchan->next) {
  124. if (!strcmp(pchan->name, posechannel)) {
  125. // now locate the constraint
  126. for (pcon = (bConstraint *)pchan->constraints.first; pcon; pcon = (bConstraint *)pcon->next) {
  127. if (!strcmp(pcon->name, constraint)) {
  128. m_constraint = pcon;
  129. m_posechannel = pchan;
  130. break;
  131. }
  132. }
  133. break;
  134. }
  135. }
  136. }
  137. }
  138. void BL_ArmatureConstraint::Relink(CTR_Map<CTR_HashedPtr, void*> *obj_map)
  139. {
  140. void **h_obj = (*obj_map)[m_target];
  141. if (h_obj) {
  142. m_target->UnregisterObject(m_armature);
  143. m_target = (KX_GameObject*)(*h_obj);
  144. m_target->RegisterObject(m_armature);
  145. }
  146. h_obj = (*obj_map)[m_subtarget];
  147. if (h_obj) {
  148. m_subtarget->UnregisterObject(m_armature);
  149. m_subtarget = (KX_GameObject*)(*h_obj);
  150. m_subtarget->RegisterObject(m_armature);
  151. }
  152. }
  153. bool BL_ArmatureConstraint::UnlinkObject(SCA_IObject* clientobj)
  154. {
  155. bool res=false;
  156. if (clientobj == m_target) {
  157. m_target = NULL;
  158. res = true;
  159. }
  160. if (clientobj == m_subtarget) {
  161. m_subtarget = NULL;
  162. res = true;
  163. }
  164. return res;
  165. }
  166. void BL_ArmatureConstraint::UpdateTarget()
  167. {
  168. if (m_constraint && !(m_constraint->flag&CONSTRAINT_OFF) && (!m_blendtarget || m_target)) {
  169. if (m_blendtarget) {
  170. // external target, must be updated
  171. m_target->UpdateBlenderObjectMatrix(m_blendtarget);
  172. if (m_pose && m_target->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE)
  173. // update the pose in case a bone is specified in the constraint target
  174. m_blendtarget->pose = ((BL_ArmatureObject*)m_target)->GetOrigPose();
  175. }
  176. if (m_blendsubtarget && m_subtarget) {
  177. m_subtarget->UpdateBlenderObjectMatrix(m_blendsubtarget);
  178. if (m_subpose && m_subtarget->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE)
  179. m_blendsubtarget->pose = ((BL_ArmatureObject*)m_subtarget)->GetOrigPose();
  180. }
  181. }
  182. }
  183. void BL_ArmatureConstraint::RestoreTarget()
  184. {
  185. if (m_constraint && !(m_constraint->flag&CONSTRAINT_OFF) && (!m_blendtarget || m_target)) {
  186. if (m_blendtarget) {
  187. copy_m4_m4(m_blendtarget->obmat, m_blendmat);
  188. if (m_pose)
  189. m_blendtarget->pose = m_pose;
  190. }
  191. if (m_blendsubtarget && m_subtarget) {
  192. copy_m4_m4(m_blendsubtarget->obmat, m_blendsubmat);
  193. if (m_subpose)
  194. m_blendsubtarget->pose = m_subpose;
  195. }
  196. }
  197. }
  198. bool BL_ArmatureConstraint::Match(const char* posechannel, const char* constraint)
  199. {
  200. return (!strcmp(m_posechannel->name, posechannel) && !strcmp(m_constraint->name, constraint));
  201. }
  202. void BL_ArmatureConstraint::SetTarget(KX_GameObject* target)
  203. {
  204. if (m_blendtarget) {
  205. if (target != m_target) {
  206. m_target->UnregisterObject(m_armature);
  207. m_target = target;
  208. if (m_target)
  209. m_target->RegisterObject(m_armature);
  210. }
  211. }
  212. }
  213. void BL_ArmatureConstraint::SetSubtarget(KX_GameObject* subtarget)
  214. {
  215. if (m_blendsubtarget) {
  216. if (subtarget != m_subtarget) {
  217. m_subtarget->UnregisterObject(m_armature);
  218. m_subtarget = subtarget;
  219. if (m_subtarget)
  220. m_subtarget->RegisterObject(m_armature);
  221. }
  222. }
  223. }
  224. #ifdef WITH_PYTHON
  225. // PYTHON
  226. PyMethodDef BL_ArmatureConstraint::Methods[] = {
  227. {NULL,NULL} //Sentinel
  228. };
  229. // order of definition of attributes, must match Attributes[] array
  230. #define BCA_TYPE 0
  231. #define BCA_NAME 1
  232. #define BCA_ENFORCE 2
  233. #define BCA_HEADTAIL 3
  234. #define BCA_LINERROR 4
  235. #define BCA_ROTERROR 5
  236. #define BCA_TARGET 6
  237. #define BCA_SUBTARGET 7
  238. #define BCA_ACTIVE 8
  239. #define BCA_IKWEIGHT 9
  240. #define BCA_IKTYPE 10
  241. #define BCA_IKFLAG 11
  242. #define BCA_IKDIST 12
  243. #define BCA_IKMODE 13
  244. PyAttributeDef BL_ArmatureConstraint::Attributes[] = {
  245. // Keep these attributes in order of BCA_ defines!!! used by py_attr_getattr and py_attr_setattr
  246. KX_PYATTRIBUTE_RO_FUNCTION("type",BL_ArmatureConstraint,py_attr_getattr),
  247. KX_PYATTRIBUTE_RO_FUNCTION("name",BL_ArmatureConstraint,py_attr_getattr),
  248. KX_PYATTRIBUTE_RW_FUNCTION("enforce",BL_ArmatureConstraint,py_attr_getattr,py_attr_setattr),
  249. KX_PYATTRIBUTE_RW_FUNCTION("headtail",BL_ArmatureConstraint,py_attr_getattr,py_attr_setattr),
  250. KX_PYATTRIBUTE_RO_FUNCTION("lin_error",BL_ArmatureConstraint,py_attr_getattr),
  251. KX_PYATTRIBUTE_RO_FUNCTION("rot_error",BL_ArmatureConstraint,py_attr_getattr),
  252. KX_PYATTRIBUTE_RW_FUNCTION("target",BL_ArmatureConstraint,py_attr_getattr,py_attr_setattr),
  253. KX_PYATTRIBUTE_RW_FUNCTION("subtarget",BL_ArmatureConstraint,py_attr_getattr,py_attr_setattr),
  254. KX_PYATTRIBUTE_RW_FUNCTION("active",BL_ArmatureConstraint,py_attr_getattr,py_attr_setattr),
  255. KX_PYATTRIBUTE_RW_FUNCTION("ik_weight",BL_ArmatureConstraint,py_attr_getattr,py_attr_setattr),
  256. KX_PYATTRIBUTE_RO_FUNCTION("ik_type",BL_ArmatureConstraint,py_attr_getattr),
  257. KX_PYATTRIBUTE_RO_FUNCTION("ik_flag",BL_ArmatureConstraint,py_attr_getattr),
  258. KX_PYATTRIBUTE_RW_FUNCTION("ik_dist",BL_ArmatureConstraint,py_attr_getattr,py_attr_setattr),
  259. KX_PYATTRIBUTE_RW_FUNCTION("ik_mode",BL_ArmatureConstraint,py_attr_getattr,py_attr_setattr),
  260. { NULL } //Sentinel
  261. };
  262. PyObject *BL_ArmatureConstraint::py_attr_getattr(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef)
  263. {
  264. BL_ArmatureConstraint* self = static_cast<BL_ArmatureConstraint*>(self_v);
  265. bConstraint* constraint = self->m_constraint;
  266. bKinematicConstraint* ikconstraint = (constraint && constraint->type == CONSTRAINT_TYPE_KINEMATIC) ? (bKinematicConstraint*)constraint->data : NULL;
  267. int attr_order = attrdef-Attributes;
  268. if (!constraint) {
  269. PyErr_SetString(PyExc_AttributeError, "constraint is NULL");
  270. return NULL;
  271. }
  272. switch (attr_order) {
  273. case BCA_TYPE:
  274. return PyLong_FromLong(constraint->type);
  275. case BCA_NAME:
  276. return PyUnicode_FromString(constraint->name);
  277. case BCA_ENFORCE:
  278. return PyFloat_FromDouble(constraint->enforce);
  279. case BCA_HEADTAIL:
  280. return PyFloat_FromDouble(constraint->headtail);
  281. case BCA_LINERROR:
  282. return PyFloat_FromDouble(constraint->lin_error);
  283. case BCA_ROTERROR:
  284. return PyFloat_FromDouble(constraint->rot_error);
  285. case BCA_TARGET:
  286. if (!self->m_target)
  287. Py_RETURN_NONE;
  288. else
  289. return self->m_target->GetProxy();
  290. case BCA_SUBTARGET:
  291. if (!self->m_subtarget)
  292. Py_RETURN_NONE;
  293. else
  294. return self->m_subtarget->GetProxy();
  295. case BCA_ACTIVE:
  296. return PyBool_FromLong((constraint->flag & CONSTRAINT_OFF) == 0);
  297. case BCA_IKWEIGHT:
  298. case BCA_IKTYPE:
  299. case BCA_IKFLAG:
  300. case BCA_IKDIST:
  301. case BCA_IKMODE:
  302. if (!ikconstraint) {
  303. PyErr_SetString(PyExc_AttributeError, "constraint is not of IK type");
  304. return NULL;
  305. }
  306. switch (attr_order) {
  307. case BCA_IKWEIGHT:
  308. return PyFloat_FromDouble(ikconstraint->weight);
  309. case BCA_IKTYPE:
  310. return PyLong_FromLong(ikconstraint->type);
  311. case BCA_IKFLAG:
  312. return PyLong_FromLong(ikconstraint->flag);
  313. case BCA_IKDIST:
  314. return PyFloat_FromDouble(ikconstraint->dist);
  315. case BCA_IKMODE:
  316. return PyLong_FromLong(ikconstraint->mode);
  317. }
  318. // should not come here
  319. break;
  320. }
  321. PyErr_SetString(PyExc_AttributeError, "constraint unknown attribute");
  322. return NULL;
  323. }
  324. int BL_ArmatureConstraint::py_attr_setattr(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
  325. {
  326. BL_ArmatureConstraint* self = static_cast<BL_ArmatureConstraint*>(self_v);
  327. bConstraint* constraint = self->m_constraint;
  328. bKinematicConstraint* ikconstraint = (constraint && constraint->type == CONSTRAINT_TYPE_KINEMATIC) ? (bKinematicConstraint*)constraint->data : NULL;
  329. int attr_order = attrdef-Attributes;
  330. int ival;
  331. double dval;
  332. // char* sval;
  333. SCA_LogicManager *logicmgr = KX_GetActiveScene()->GetLogicManager();
  334. KX_GameObject *oval;
  335. if (!constraint) {
  336. PyErr_SetString(PyExc_AttributeError, "constraint is NULL");
  337. return PY_SET_ATTR_FAIL;
  338. }
  339. switch (attr_order) {
  340. case BCA_ENFORCE:
  341. dval = PyFloat_AsDouble(value);
  342. if (dval < 0.0 || dval > 1.0) { /* also accounts for non float */
  343. PyErr_SetString(PyExc_AttributeError, "constraint.enforce = float: BL_ArmatureConstraint, expected a float between 0 and 1");
  344. return PY_SET_ATTR_FAIL;
  345. }
  346. constraint->enforce = dval;
  347. return PY_SET_ATTR_SUCCESS;
  348. case BCA_HEADTAIL:
  349. dval = PyFloat_AsDouble(value);
  350. if (dval < 0.0 || dval > 1.0) { /* also accounts for non float */
  351. PyErr_SetString(PyExc_AttributeError, "constraint.headtail = float: BL_ArmatureConstraint, expected a float between 0 and 1");
  352. return PY_SET_ATTR_FAIL;
  353. }
  354. constraint->headtail = dval;
  355. return PY_SET_ATTR_SUCCESS;
  356. case BCA_TARGET:
  357. if (!ConvertPythonToGameObject(logicmgr, value, &oval, true, "constraint.target = value: BL_ArmatureConstraint"))
  358. return PY_SET_ATTR_FAIL; // ConvertPythonToGameObject sets the error
  359. self->SetTarget(oval);
  360. return PY_SET_ATTR_SUCCESS;
  361. case BCA_SUBTARGET:
  362. if (!ConvertPythonToGameObject(logicmgr, value, &oval, true, "constraint.subtarget = value: BL_ArmatureConstraint"))
  363. return PY_SET_ATTR_FAIL; // ConvertPythonToGameObject sets the error
  364. self->SetSubtarget(oval);
  365. return PY_SET_ATTR_SUCCESS;
  366. case BCA_ACTIVE:
  367. ival = PyObject_IsTrue( value );
  368. if (ival == -1) {
  369. PyErr_SetString(PyExc_AttributeError, "constraint.active = bool: BL_ArmatureConstraint, expected True or False");
  370. return PY_SET_ATTR_FAIL;
  371. }
  372. self->m_constraint->flag = (self->m_constraint->flag & ~CONSTRAINT_OFF) | ((ival)?0:CONSTRAINT_OFF);
  373. return PY_SET_ATTR_SUCCESS;
  374. case BCA_IKWEIGHT:
  375. case BCA_IKDIST:
  376. case BCA_IKMODE:
  377. if (!ikconstraint) {
  378. PyErr_SetString(PyExc_AttributeError, "constraint is not of IK type");
  379. return PY_SET_ATTR_FAIL;
  380. }
  381. switch (attr_order) {
  382. case BCA_IKWEIGHT:
  383. dval = PyFloat_AsDouble(value);
  384. if (dval < 0.0 || dval > 1.0) { /* also accounts for non float */
  385. PyErr_SetString(PyExc_AttributeError, "constraint.weight = float: BL_ArmatureConstraint, expected a float between 0 and 1");
  386. return PY_SET_ATTR_FAIL;
  387. }
  388. ikconstraint->weight = dval;
  389. return PY_SET_ATTR_SUCCESS;
  390. case BCA_IKDIST:
  391. dval = PyFloat_AsDouble(value);
  392. if (dval < 0.0) { /* also accounts for non float */
  393. PyErr_SetString(PyExc_AttributeError, "constraint.ik_dist = float: BL_ArmatureConstraint, expected a positive float");
  394. return PY_SET_ATTR_FAIL;
  395. }
  396. ikconstraint->dist = dval;
  397. return PY_SET_ATTR_SUCCESS;
  398. case BCA_IKMODE:
  399. ival = PyLong_AsLong(value);
  400. if (ival < 0) {
  401. PyErr_SetString(PyExc_AttributeError, "constraint.ik_mode = integer: BL_ArmatureConstraint, expected a positive integer");
  402. return PY_SET_ATTR_FAIL;
  403. }
  404. ikconstraint->mode = ival;
  405. return PY_SET_ATTR_SUCCESS;
  406. }
  407. // should not come here
  408. break;
  409. }
  410. PyErr_SetString(PyExc_AttributeError, "constraint unknown attribute");
  411. return PY_SET_ATTR_FAIL;
  412. }
  413. #endif // WITH_PYTHON