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