Merge of itasc branch. Project files, scons and cmake should be working. Makefile...
[blender.git] / source / gameengine / Converter / BL_ArmatureChannel.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_armature_types.h"
34 #include "BL_ArmatureChannel.h"
35 #include "BL_ArmatureObject.h"
36 #include "BL_ArmatureConstraint.h"
37 #include "BLI_arithb.h"
38 #include "BLI_string.h"
39
40 PyTypeObject BL_ArmatureChannel::Type = {
41         PyVarObject_HEAD_INIT(NULL, 0)
42         "BL_ArmatureChannel",
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_ArmatureChannel::py_repr(void)
63 {
64         return PyUnicode_FromString(m_posechannel->name);
65 }
66
67 PyObject *BL_ArmatureChannel::GetProxy()
68 {
69         return GetProxyPlus_Ext(this, &Type, m_posechannel);
70 }
71
72 PyObject *BL_ArmatureChannel::NewProxy(bool py_owns)
73 {
74         return NewProxyPlus_Ext(this, &Type, m_posechannel, py_owns);
75 }
76
77 BL_ArmatureChannel::BL_ArmatureChannel(
78         BL_ArmatureObject *armature, 
79         bPoseChannel *posechannel)
80         : PyObjectPlus(), m_posechannel(posechannel), m_armature(armature)
81 {
82 }
83
84 BL_ArmatureChannel::~BL_ArmatureChannel()
85 {
86 }
87
88 // PYTHON
89
90 PyMethodDef BL_ArmatureChannel::Methods[] = {
91   {NULL,NULL} //Sentinel
92 };
93
94 // order of definition of attributes, must match Attributes[] array
95 #define BCA_BONE                0
96 #define BCA_PARENT              1
97
98 PyAttributeDef BL_ArmatureChannel::Attributes[] = {
99         // Keep these attributes in order of BCA_ defines!!! used by py_attr_getattr and py_attr_setattr
100         KX_PYATTRIBUTE_RO_FUNCTION("bone",BL_ArmatureChannel,py_attr_getattr),  
101         KX_PYATTRIBUTE_RO_FUNCTION("parent",BL_ArmatureChannel,py_attr_getattr),        
102         
103         { NULL }        //Sentinel
104 };
105
106 /* attributes directly taken from bPoseChannel */
107 PyAttributeDef BL_ArmatureChannel::AttributesPtr[] = {
108         KX_PYATTRIBUTE_CHAR_RO("name",bPoseChannel,name),
109         KX_PYATTRIBUTE_FLAG_RO("has_ik",bPoseChannel,flag, POSE_CHAIN),
110         KX_PYATTRIBUTE_FLAG_NEGATIVE_RO("ik_dof_x",bPoseChannel,ikflag, BONE_IK_NO_XDOF),
111         KX_PYATTRIBUTE_FLAG_NEGATIVE_RO("ik_dof_y",bPoseChannel,ikflag, BONE_IK_NO_YDOF),
112         KX_PYATTRIBUTE_FLAG_NEGATIVE_RO("ik_dof_z",bPoseChannel,ikflag, BONE_IK_NO_ZDOF),
113         KX_PYATTRIBUTE_FLAG_RO("ik_limit_x",bPoseChannel,ikflag, BONE_IK_XLIMIT),
114         KX_PYATTRIBUTE_FLAG_RO("ik_limit_y",bPoseChannel,ikflag, BONE_IK_YLIMIT),
115         KX_PYATTRIBUTE_FLAG_RO("ik_limit_z",bPoseChannel,ikflag, BONE_IK_ZLIMIT),
116         KX_PYATTRIBUTE_FLAG_RO("ik_rot_control",bPoseChannel,ikflag, BONE_IK_ROTCTL),
117         KX_PYATTRIBUTE_FLAG_RO("ik_lin_control",bPoseChannel,ikflag, BONE_IK_LINCTL),
118         KX_PYATTRIBUTE_FLOAT_VECTOR_RW("location",-FLT_MAX,FLT_MAX,bPoseChannel,loc,3),
119         KX_PYATTRIBUTE_FLOAT_VECTOR_RW("scale",-FLT_MAX,FLT_MAX,bPoseChannel,size,3),
120         KX_PYATTRIBUTE_FLOAT_VECTOR_RW("rotation",-1.0f,1.0f,bPoseChannel,quat,4),
121         KX_PYATTRIBUTE_FLOAT_VECTOR_RW("euler_rotation",-10.f,10.f,bPoseChannel,eul,3),
122         KX_PYATTRIBUTE_SHORT_RW("rotation_mode",0,PCHAN_ROT_MAX-1,false,bPoseChannel,rotmode),
123         KX_PYATTRIBUTE_FLOAT_MATRIX_RO("channel_matrix",bPoseChannel,chan_mat,4),
124         KX_PYATTRIBUTE_FLOAT_MATRIX_RO("pose_matrix",bPoseChannel,pose_mat,4),
125         KX_PYATTRIBUTE_FLOAT_VECTOR_RO("pose_head",bPoseChannel,pose_head,3),
126         KX_PYATTRIBUTE_FLOAT_VECTOR_RO("pose_tail",bPoseChannel,pose_tail,3),
127         KX_PYATTRIBUTE_FLOAT_RO("ik_min_x",bPoseChannel,limitmin[0]),
128         KX_PYATTRIBUTE_FLOAT_RO("ik_max_x",bPoseChannel,limitmax[0]),
129         KX_PYATTRIBUTE_FLOAT_RO("ik_min_y",bPoseChannel,limitmin[1]),
130         KX_PYATTRIBUTE_FLOAT_RO("ik_max_y",bPoseChannel,limitmax[1]),
131         KX_PYATTRIBUTE_FLOAT_RO("ik_min_z",bPoseChannel,limitmin[2]),
132         KX_PYATTRIBUTE_FLOAT_RO("ik_max_z",bPoseChannel,limitmax[2]),
133         KX_PYATTRIBUTE_FLOAT_RO("ik_stiffness_x",bPoseChannel,stiffness[0]),
134         KX_PYATTRIBUTE_FLOAT_RO("ik_stiffness_y",bPoseChannel,stiffness[1]),
135         KX_PYATTRIBUTE_FLOAT_RO("ik_stiffness_z",bPoseChannel,stiffness[2]),
136         KX_PYATTRIBUTE_FLOAT_RO("ik_stretch",bPoseChannel,ikstretch),
137         KX_PYATTRIBUTE_FLOAT_RW("ik_rot_weight",0,1.0f,bPoseChannel,ikrotweight),
138         KX_PYATTRIBUTE_FLOAT_RW("ik_lin_weight",0,1.0f,bPoseChannel,iklinweight),
139         KX_PYATTRIBUTE_RW_FUNCTION("joint_rotation",BL_ArmatureChannel,py_attr_get_joint_rotation,py_attr_set_joint_rotation),
140         { NULL }        //Sentinel
141 };
142
143 PyObject* BL_ArmatureChannel::py_attr_getattr(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef)
144 {
145         BL_ArmatureChannel* self= static_cast<BL_ArmatureChannel*>(self_v);
146         bPoseChannel* channel = self->m_posechannel;
147         int attr_order = attrdef-Attributes;
148
149         if (!channel) {
150                 PyErr_SetString(PyExc_AttributeError, "channel is NULL");
151                 return NULL;
152         }
153
154         switch (attr_order) {
155         case BCA_BONE:
156                 // bones are standalone proxy
157                 return NewProxyPlus_Ext(NULL,&BL_ArmatureBone::Type,channel->bone,false);
158         case BCA_PARENT:
159                 {
160                         BL_ArmatureChannel* parent = self->m_armature->GetChannel(channel->parent);
161                         if (parent)
162                                 return parent->GetProxy();
163                         else
164                                 Py_RETURN_NONE;
165                 }
166         }
167         PyErr_SetString(PyExc_AttributeError, "channel unknown attribute");
168         return NULL;
169 }
170
171 int BL_ArmatureChannel::py_attr_setattr(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
172 {
173         BL_ArmatureChannel* self= static_cast<BL_ArmatureChannel*>(self_v);
174         bPoseChannel* channel = self->m_posechannel;
175         int attr_order = attrdef-Attributes;
176
177         int ival;
178         double dval;
179         char* sval;
180         KX_GameObject *oval;
181
182         if (!channel) {
183                 PyErr_SetString(PyExc_AttributeError, "channel is NULL");
184                 return PY_SET_ATTR_FAIL;
185         }
186         
187         switch (attr_order) {
188         default:
189                 break;
190         }
191
192         PyErr_SetString(PyExc_AttributeError, "channel unknown attribute");
193         return PY_SET_ATTR_FAIL;
194 }
195
196 PyObject* BL_ArmatureChannel::py_attr_get_joint_rotation(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef)
197 {
198         BL_ArmatureChannel* self= static_cast<BL_ArmatureChannel*>(self_v);
199         bPoseChannel* pchan = self->m_posechannel;
200         // decompose the pose matrix in euler rotation
201         float rest_mat[3][3];
202         float pose_mat[3][3];
203         float joint_mat[3][3];
204         float joints[3];
205         float norm;
206         double sa, ca;
207         // get rotation in armature space
208         Mat3CpyMat4(pose_mat, pchan->pose_mat);
209         Mat3Ortho(pose_mat);
210         if (pchan->parent) {
211                 // bone has a parent, compute the rest pose of the bone taking actual pose of parent
212                 Mat3IsMat3MulMat4(rest_mat, pchan->bone->bone_mat, pchan->parent->pose_mat);
213                 Mat3Ortho(rest_mat);
214         } else {
215                 // otherwise, the bone matrix in armature space is the rest pose
216                 Mat3CpyMat4(rest_mat, pchan->bone->arm_mat);
217         }
218         // remove the rest pose to get the joint movement
219         Mat3Transp(rest_mat);
220         Mat3MulMat3(joint_mat, rest_mat, pose_mat);             
221         joints[0] = joints[1] = joints[2] = 0.f;
222         // returns a 3 element list that gives corresponding joint
223         int flag = 0;
224         if (!(pchan->ikflag & BONE_IK_NO_XDOF))
225                 flag |= 1;
226         if (!(pchan->ikflag & BONE_IK_NO_YDOF))
227                 flag |= 2;
228         if (!(pchan->ikflag & BONE_IK_NO_ZDOF))
229                 flag |= 4;
230         switch (flag) {
231         case 0: // fixed joint
232                 break;
233         case 1: // X only
234                 Mat3ToEulO(joint_mat, joints, EULER_ORDER_XYZ);
235                 joints[1] = joints[2] = 0.f;
236                 break;
237         case 2: // Y only
238                 Mat3ToEulO(joint_mat, joints, EULER_ORDER_XYZ);
239                 joints[0] = joints[2] = 0.f;
240                 break;
241         case 3: // X+Y
242                 Mat3ToEulO(joint_mat, joints, EULER_ORDER_ZYX);
243                 joints[2] = 0.f;
244                 break;
245         case 4: // Z only
246                 Mat3ToEulO(joint_mat, joints, EULER_ORDER_XYZ);
247                 joints[0] = joints[1] = 0.f;
248                 break;
249         case 5: // X+Z
250                 // decompose this as an equivalent rotation vector in X/Z plane
251                 joints[0] = joint_mat[1][2];
252                 joints[2] = -joint_mat[1][0];
253                 norm = Normalize(joints);
254                 if (norm < FLT_EPSILON) {
255                         norm = (joint_mat[1][1] < 0.f) ? M_PI : 0.f;
256                 } else {
257                         norm = acos(joint_mat[1][1]);
258                 }
259                 VecMulf(joints, norm);
260                 break;
261         case 6: // Y+Z
262                 Mat3ToEulO(joint_mat, joints, EULER_ORDER_XYZ);
263                 joints[0] = 0.f;
264                 break;
265         case 7: // X+Y+Z
266                 // equivalent axis
267                 joints[0] = (joint_mat[1][2]-joint_mat[2][1])*0.5f;
268                 joints[1] = (joint_mat[2][0]-joint_mat[0][2])*0.5f;
269                 joints[2] = (joint_mat[0][1]-joint_mat[1][0])*0.5f;
270                 sa = VecLength(joints);
271                 ca = (joint_mat[0][0]+joint_mat[1][1]+joint_mat[1][1]-1.0f)*0.5f;
272                 if (sa > FLT_EPSILON) {
273                         norm = atan2(sa,ca)/sa;
274                 } else {
275                    if (ca < 0.0) {
276                            norm = M_PI;
277                            VecMulf(joints,0.f);
278                            if (joint_mat[0][0] > 0.f) {
279                                    joints[0] = 1.0f;
280                            } else if (joint_mat[1][1] > 0.f) {
281                                    joints[1] = 1.0f;
282                            } else {
283                                    joints[2] = 1.0f;
284                            }
285                    } else {
286                            norm = 0.0;
287                    }
288                 }
289                 VecMulf(joints,norm);
290                 break;
291         }
292         return newVectorObject(joints, 3, Py_NEW, NULL);
293 }
294
295 int BL_ArmatureChannel::py_attr_set_joint_rotation(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
296 {
297         BL_ArmatureChannel* self= static_cast<BL_ArmatureChannel*>(self_v);
298         bPoseChannel* pchan = self->m_posechannel;
299         PyObject *item;
300         float joints[3];
301         float quat[4];
302
303         if (!PySequence_Check(value) || PySequence_Size(value) != 3) {
304                 PyErr_SetString(PyExc_AttributeError, "expected a sequence of [3] floats");
305                 return PY_SET_ATTR_FAIL;
306         }
307         for (int i=0; i<3; i++) {
308                 item = PySequence_GetItem(value, i); /* new ref */
309                 joints[i] = PyFloat_AsDouble(item);
310                 Py_DECREF(item);
311                 if (joints[i] == -1.0f && PyErr_Occurred()) {
312                         PyErr_SetString(PyExc_AttributeError, "expected a sequence of [3] floats");
313                         return PY_SET_ATTR_FAIL;
314                 }
315         }
316
317         int flag = 0;
318         if (!(pchan->ikflag & BONE_IK_NO_XDOF))
319                 flag |= 1;
320         if (!(pchan->ikflag & BONE_IK_NO_YDOF))
321                 flag |= 2;
322         if (!(pchan->ikflag & BONE_IK_NO_ZDOF))
323                 flag |= 4;
324         QuatOne(quat);
325         switch (flag) {
326         case 0: // fixed joint
327                 break;
328         case 1: // X only
329                 joints[1] = joints[2] = 0.f;
330                 EulOToQuat(joints, EULER_ORDER_XYZ, quat);
331                 break;
332         case 2: // Y only
333                 joints[0] = joints[2] = 0.f;
334                 EulOToQuat(joints, EULER_ORDER_XYZ, quat);
335                 break;
336         case 3: // X+Y
337                 joints[2] = 0.f;
338                 EulOToQuat(joints, EULER_ORDER_ZYX, quat);
339                 break;
340         case 4: // Z only
341                 joints[0] = joints[1] = 0.f;
342                 EulOToQuat(joints, EULER_ORDER_XYZ, quat);
343                 break;
344         case 5: // X+Z
345                 // X and Z are components of an equivalent rotation axis
346                 joints[1] = 0;
347                 VecRotToQuat(joints, VecLength(joints), quat);
348                 break;
349         case 6: // Y+Z
350                 joints[0] = 0.f;
351                 EulOToQuat(joints, EULER_ORDER_XYZ, quat);
352                 break;
353         case 7: // X+Y+Z
354                 // equivalent axis
355                 VecRotToQuat(joints, VecLength(joints), quat);
356                 break;
357         }
358         if (pchan->rotmode > 0) {
359                 QuatToEulO(quat, joints, pchan->rotmode);
360                 VecCopyf(pchan->eul, joints);
361         } else
362                 QuatCopy(pchan->quat, quat);
363         return PY_SET_ATTR_SUCCESS;
364 }
365
366 // *************************
367 // BL_ArmatureBone
368 //
369 // Access to Bone structure
370 PyTypeObject BL_ArmatureBone::Type = {
371         PyVarObject_HEAD_INIT(NULL, 0)
372         "BL_ArmatureBone",
373         sizeof(PyObjectPlus_Proxy),
374         0,
375         py_base_dealloc,
376         0,
377         0,
378         0,
379         0,
380         py_bone_repr,
381         0,0,0,0,0,0,0,0,0,
382         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
383         0,0,0,0,0,0,0,
384         Methods,
385         0,
386         0,
387         &CValue::Type,
388         0,0,0,0,0,0,
389         py_base_new
390 };
391
392 // not used since this class is never instantiated
393 PyObject *BL_ArmatureBone::GetProxy() 
394
395         return NULL; 
396 }
397 PyObject *BL_ArmatureBone::NewProxy(bool py_owns) 
398
399         return NULL; 
400 }
401
402 PyObject *BL_ArmatureBone::py_bone_repr(PyObject *self)
403 {
404         Bone* bone = static_cast<Bone*>BGE_PROXY_PTR(self);
405         return PyUnicode_FromString(bone->name);
406 }
407
408 PyMethodDef BL_ArmatureBone::Methods[] = {
409         {NULL,NULL} //Sentinel
410 };
411
412 /* no attributes on C++ class since it is never instantiated */
413 PyAttributeDef BL_ArmatureBone::Attributes[] = {
414         { NULL }        //Sentinel
415 };
416
417 // attributes that work on proxy ptr (points to a Bone structure)
418 PyAttributeDef BL_ArmatureBone::AttributesPtr[] = {
419         KX_PYATTRIBUTE_CHAR_RO("name",Bone,name),
420         KX_PYATTRIBUTE_FLAG_RO("connected",Bone,flag, BONE_CONNECTED),
421         KX_PYATTRIBUTE_FLAG_RO("hinge",Bone,flag, BONE_HINGE),
422         KX_PYATTRIBUTE_FLAG_NEGATIVE_RO("inherit_scale",Bone,flag, BONE_NO_SCALE),
423         KX_PYATTRIBUTE_SHORT_RO("bbone_segments",Bone,segments),
424         KX_PYATTRIBUTE_FLOAT_RO("roll",Bone,roll),
425         KX_PYATTRIBUTE_FLOAT_VECTOR_RO("head",Bone,head,3),
426         KX_PYATTRIBUTE_FLOAT_VECTOR_RO("tail",Bone,tail,3),
427         KX_PYATTRIBUTE_FLOAT_RO("length",Bone,length),
428         KX_PYATTRIBUTE_FLOAT_VECTOR_RO("arm_head",Bone,arm_head,3),
429         KX_PYATTRIBUTE_FLOAT_VECTOR_RO("arm_tail",Bone,arm_tail,3),
430         KX_PYATTRIBUTE_FLOAT_MATRIX_RO("arm_mat",Bone,arm_mat,4),
431         KX_PYATTRIBUTE_FLOAT_MATRIX_RO("bone_mat",Bone,bone_mat,4),
432         KX_PYATTRIBUTE_RO_FUNCTION("parent",BL_ArmatureBone,py_bone_get_parent),
433         KX_PYATTRIBUTE_RO_FUNCTION("children",BL_ArmatureBone,py_bone_get_parent),
434         { NULL }        //Sentinel
435 };
436
437 PyObject *BL_ArmatureBone::py_bone_get_parent(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
438 {
439         Bone* bone = reinterpret_cast<Bone*>BGE_PROXY_PTR(self);
440         if (bone->parent) {
441                 // create a proxy unconnected to any GE object
442                 return NewProxyPlus_Ext(NULL,&Type,bone->parent,false);
443         }
444         Py_RETURN_NONE;
445 }
446
447 PyObject *BL_ArmatureBone::py_bone_get_children(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
448 {
449         Bone* bone = reinterpret_cast<Bone*>BGE_PROXY_PTR(self);
450         Bone* child;
451         int count = 0;
452         for (child=(Bone*)bone->childbase.first; child; child=(Bone*)child->next)
453                 count++;
454
455         PyObject* childrenlist = PyList_New(count);
456
457         for (count = 0, child=(Bone*)bone->childbase.first; child; child=(Bone*)child->next, ++count)
458                 PyList_SET_ITEM(childrenlist,count,NewProxyPlus_Ext(NULL,&Type,child,false));
459
460         return childrenlist;
461 }