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