own rna naming commits r31439 r31472 also renamed BGE vars unintentionally
[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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 #include "DNA_constraint_types.h"
30 #include "DNA_action_types.h"
31 #include "BL_ArmatureConstraint.h"
32 #include "BL_ArmatureObject.h"
33 #include "BLI_math.h"
34 #include "BLI_string.h"
35
36 #ifndef DISABLE_PYTHON
37
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
60 PyObject* BL_ArmatureConstraint::py_repr(void)
61 {
62         return PyUnicode_FromString(m_name);
63 }
64
65 #endif // DISABLE_PYTHON
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_constraint(constraint), m_posechannel(posechannel), m_armature(armature)
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                 copy_m4_m4(m_blendmat, m_blendtarget->obmat);
82                 if (m_blendtarget->type == OB_ARMATURE)
83                         m_pose = m_blendtarget->pose;
84         }
85         if (m_blendsubtarget) {
86                 copy_m4_m4(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                         copy_m4_m4(m_blendtarget->obmat, m_blendmat);
198                         if (m_pose)
199                                 m_blendtarget->pose = m_pose;
200                 }
201                 if (m_blendsubtarget && m_subtarget) {
202                         copy_m4_m4(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 #ifndef DISABLE_PYTHON
241
242 // PYTHON
243
244 PyMethodDef BL_ArmatureConstraint::Methods[] = {
245   {NULL,NULL} //Sentinel
246 };
247
248 // order of definition of attributes, must match Attributes[] array
249 #define BCA_TYPE                0
250 #define BCA_NAME                1
251 #define BCA_ENFORCE             2
252 #define BCA_HEADTAIL    3
253 #define BCA_LINERROR    4
254 #define BCA_ROTERROR    5
255 #define BCA_TARGET              6
256 #define BCA_SUBTARGET   7
257 #define BCA_ACTIVE              8
258 #define BCA_IKWEIGHT    9
259 #define BCA_IKTYPE              10
260 #define BCA_IKFLAG              11
261 #define BCA_IKDIST              12
262 #define BCA_IKMODE              13
263
264 PyAttributeDef BL_ArmatureConstraint::Attributes[] = {
265         // Keep these attributes in order of BCA_ defines!!! used by py_attr_getattr and py_attr_setattr
266         KX_PYATTRIBUTE_RO_FUNCTION("type",BL_ArmatureConstraint,py_attr_getattr),       
267         KX_PYATTRIBUTE_RO_FUNCTION("name",BL_ArmatureConstraint,py_attr_getattr),       
268         KX_PYATTRIBUTE_RW_FUNCTION("enforce",BL_ArmatureConstraint,py_attr_getattr,py_attr_setattr),
269         KX_PYATTRIBUTE_RW_FUNCTION("headtail",BL_ArmatureConstraint,py_attr_getattr,py_attr_setattr),
270         KX_PYATTRIBUTE_RO_FUNCTION("lin_error",BL_ArmatureConstraint,py_attr_getattr),
271         KX_PYATTRIBUTE_RO_FUNCTION("rot_error",BL_ArmatureConstraint,py_attr_getattr),
272         KX_PYATTRIBUTE_RW_FUNCTION("target",BL_ArmatureConstraint,py_attr_getattr,py_attr_setattr),
273         KX_PYATTRIBUTE_RW_FUNCTION("subtarget",BL_ArmatureConstraint,py_attr_getattr,py_attr_setattr),
274         KX_PYATTRIBUTE_RW_FUNCTION("active",BL_ArmatureConstraint,py_attr_getattr,py_attr_setattr),
275         KX_PYATTRIBUTE_RW_FUNCTION("ik_weight",BL_ArmatureConstraint,py_attr_getattr,py_attr_setattr),
276         KX_PYATTRIBUTE_RO_FUNCTION("ik_type",BL_ArmatureConstraint,py_attr_getattr),
277         KX_PYATTRIBUTE_RO_FUNCTION("ik_flag",BL_ArmatureConstraint,py_attr_getattr),
278         KX_PYATTRIBUTE_RW_FUNCTION("ik_dist",BL_ArmatureConstraint,py_attr_getattr,py_attr_setattr),
279         KX_PYATTRIBUTE_RW_FUNCTION("ik_mode",BL_ArmatureConstraint,py_attr_getattr,py_attr_setattr),
280         
281         { NULL }        //Sentinel
282 };
283
284
285 PyObject* BL_ArmatureConstraint::py_attr_getattr(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef)
286 {
287         BL_ArmatureConstraint* self= static_cast<BL_ArmatureConstraint*>(self_v);
288         bConstraint* constraint = self->m_constraint;
289         bKinematicConstraint* ikconstraint = (constraint && constraint->type == CONSTRAINT_TYPE_KINEMATIC) ? (bKinematicConstraint*)constraint->data : NULL;
290         int attr_order = attrdef-Attributes;
291
292         if (!constraint) {
293                 PyErr_SetString(PyExc_AttributeError, "constraint is NULL");
294                 return NULL;
295         }
296
297         switch (attr_order) {
298         case BCA_TYPE:
299                 return PyLong_FromLong(constraint->type);
300         case BCA_NAME:
301                 return PyUnicode_FromString(constraint->name);
302         case BCA_ENFORCE:
303                 return PyFloat_FromDouble(constraint->enforce);
304         case BCA_HEADTAIL:
305                 return PyFloat_FromDouble(constraint->headtail);
306         case BCA_LINERROR:
307                 return PyFloat_FromDouble(constraint->lin_error);
308         case BCA_ROTERROR:
309                 return PyFloat_FromDouble(constraint->rot_error);
310         case BCA_TARGET:
311                 if (!self->m_target)    
312                         Py_RETURN_NONE;
313                 else
314                         return self->m_target->GetProxy();
315         case BCA_SUBTARGET:
316                 if (!self->m_subtarget) 
317                         Py_RETURN_NONE;
318                 else
319                         return self->m_subtarget->GetProxy();
320         case BCA_ACTIVE:
321                 return PyBool_FromLong(constraint->flag & CONSTRAINT_OFF);
322         case BCA_IKWEIGHT:
323         case BCA_IKTYPE:
324         case BCA_IKFLAG:
325         case BCA_IKDIST:
326         case BCA_IKMODE:
327                 if (!ikconstraint) {
328                         PyErr_SetString(PyExc_AttributeError, "constraint is not of IK type");
329                         return NULL;
330                 }
331                 switch (attr_order) {
332                 case BCA_IKWEIGHT:
333                         return PyFloat_FromDouble((ikconstraint)?ikconstraint->weight:0.0);
334                 case BCA_IKTYPE:
335                         return PyLong_FromLong(ikconstraint->type);
336                 case BCA_IKFLAG:
337                         return PyLong_FromLong(ikconstraint->flag);
338                 case BCA_IKDIST:
339                         return PyFloat_FromDouble(ikconstraint->dist);
340                 case BCA_IKMODE:
341                         return PyLong_FromLong(ikconstraint->mode);
342                 }
343                 // should not come here
344                 break;
345         }
346         PyErr_SetString(PyExc_AttributeError, "constraint unknown attribute");
347         return NULL;
348 }
349
350 int BL_ArmatureConstraint::py_attr_setattr(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
351 {
352         BL_ArmatureConstraint* self= static_cast<BL_ArmatureConstraint*>(self_v);
353         bConstraint* constraint = self->m_constraint;
354         bKinematicConstraint* ikconstraint = (constraint && constraint->type == CONSTRAINT_TYPE_KINEMATIC) ? (bKinematicConstraint*)constraint->data : NULL;
355         int attr_order = attrdef-Attributes;
356         int ival;
357         double dval;
358 //      char* sval;
359         KX_GameObject *oval;
360
361         if (!constraint) {
362                 PyErr_SetString(PyExc_AttributeError, "constraint is NULL");
363                 return PY_SET_ATTR_FAIL;
364         }
365         
366         switch (attr_order) {
367         case BCA_ENFORCE:
368                 dval = PyFloat_AsDouble(value);
369                 if (dval < 0.0f || dval > 1.0f) { /* also accounts for non float */
370                         PyErr_SetString(PyExc_AttributeError, "constraint.enforce = float: BL_ArmatureConstraint, expected a float between 0 and 1");
371                         return PY_SET_ATTR_FAIL;
372                 }
373                 constraint->enforce = dval;
374                 return PY_SET_ATTR_SUCCESS;
375
376         case BCA_HEADTAIL:
377                 dval = PyFloat_AsDouble(value);
378                 if (dval < 0.0f || dval > 1.0f) { /* also accounts for non float */
379                         PyErr_SetString(PyExc_AttributeError, "constraint.headtail = float: BL_ArmatureConstraint, expected a float between 0 and 1");
380                         return PY_SET_ATTR_FAIL;
381                 }
382                 constraint->headtail = dval;
383                 return PY_SET_ATTR_SUCCESS;
384
385         case BCA_TARGET:
386                 if (!ConvertPythonToGameObject(value, &oval, true, "constraint.target = value: BL_ArmatureConstraint"))
387                         return PY_SET_ATTR_FAIL; // ConvertPythonToGameObject sets the error
388                 self->SetTarget(oval);
389                 return PY_SET_ATTR_SUCCESS;
390
391         case BCA_SUBTARGET:
392                 if (!ConvertPythonToGameObject(value, &oval, true, "constraint.subtarget = value: BL_ArmatureConstraint"))
393                         return PY_SET_ATTR_FAIL; // ConvertPythonToGameObject sets the error
394                 self->SetSubtarget(oval);
395                 return PY_SET_ATTR_SUCCESS;
396
397         case BCA_ACTIVE:
398                 ival = PyObject_IsTrue( value );
399                 if (ival == -1) {
400                         PyErr_SetString(PyExc_AttributeError, "constraint.active = bool: BL_ArmatureConstraint, expected True or False");
401                         return PY_SET_ATTR_FAIL;
402                 }
403                 self->m_constraint->flag = (self->m_constraint->flag & ~CONSTRAINT_OFF) | ((ival)?0:CONSTRAINT_OFF);
404                 return PY_SET_ATTR_SUCCESS;
405
406         case BCA_IKWEIGHT:
407         case BCA_IKDIST:
408         case BCA_IKMODE:
409                 if (!ikconstraint) {
410                         PyErr_SetString(PyExc_AttributeError, "constraint is not of IK type");
411                         return PY_SET_ATTR_FAIL;
412                 }
413                 switch (attr_order) {
414                 case BCA_IKWEIGHT:
415                         dval = PyFloat_AsDouble(value);
416                         if (dval < 0.0f || dval > 1.0f) { /* also accounts for non float */
417                                 PyErr_SetString(PyExc_AttributeError, "constraint.weight = float: BL_ArmatureConstraint, expected a float between 0 and 1");
418                                 return PY_SET_ATTR_FAIL;
419                         }
420                         ikconstraint->weight = dval;
421                         return PY_SET_ATTR_SUCCESS;
422
423                 case BCA_IKDIST:
424                         dval = PyFloat_AsDouble(value);
425                         if (dval < 0.0f) { /* also accounts for non float */
426                                 PyErr_SetString(PyExc_AttributeError, "constraint.ik_dist = float: BL_ArmatureConstraint, expected a positive float");
427                                 return PY_SET_ATTR_FAIL;
428                         }
429                         ikconstraint->dist = dval;
430                         return PY_SET_ATTR_SUCCESS;
431
432                 case BCA_IKMODE:
433                         ival = PyLong_AsLong(value);
434                         if (ival < 0) {
435                                 PyErr_SetString(PyExc_AttributeError, "constraint.ik_mode = integer: BL_ArmatureConstraint, expected a positive integer");
436                                 return PY_SET_ATTR_FAIL;
437                         }
438                         ikconstraint->mode = ival;
439                         return PY_SET_ATTR_SUCCESS;
440                 }
441                 // should not come here
442                 break;
443
444         }
445
446         PyErr_SetString(PyExc_AttributeError, "constraint unknown attribute");
447         return PY_SET_ATTR_FAIL;
448 }
449
450 #endif // DISABLE_PYTHON