NLA SoC: Merge from 2.5 - 21146 to 21178
[blender.git] / source / gameengine / Ketsji / KX_ObjectActuator.cpp
1 /**
2  * Do translation/rotation actions
3  *
4  * $Id$
5  *
6  * ***** BEGIN GPL LICENSE BLOCK *****
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23  * All rights reserved.
24  *
25  * The Original Code is: all of this file.
26  *
27  * Contributor(s): none yet.
28  *
29  * ***** END GPL LICENSE BLOCK *****
30  */
31
32 #include "KX_ObjectActuator.h"
33 #include "KX_GameObject.h"
34 #include "KX_PyMath.h" // For PyVecTo - should this include be put in PyObjectPlus?
35 #include "KX_IPhysicsController.h"
36
37 #ifdef HAVE_CONFIG_H
38 #include <config.h>
39 #endif
40
41 /* ------------------------------------------------------------------------- */
42 /* Native functions                                                          */
43 /* ------------------------------------------------------------------------- */
44
45 KX_ObjectActuator::
46 KX_ObjectActuator(
47         SCA_IObject* gameobj,
48         KX_GameObject* refobj,
49         const MT_Vector3& force,
50         const MT_Vector3& torque,
51         const MT_Vector3& dloc,
52         const MT_Vector3& drot,
53         const MT_Vector3& linV,
54         const MT_Vector3& angV,
55         const short damping,
56         const KX_LocalFlags& flag,
57         PyTypeObject* T
58 ) : 
59         SCA_IActuator(gameobj,T),
60         m_force(force),
61         m_torque(torque),
62         m_dloc(dloc),
63         m_drot(drot),
64         m_linear_velocity(linV),
65         m_angular_velocity(angV),
66         m_linear_length2(0.0),
67         m_current_linear_factor(0.0),
68         m_current_angular_factor(0.0),
69         m_damping(damping),
70         m_previous_error(0.0,0.0,0.0),
71         m_error_accumulator(0.0,0.0,0.0),
72         m_bitLocalFlag (flag),
73         m_reference(refobj),
74         m_active_combined_velocity (false),
75         m_linear_damping_active(false),
76         m_angular_damping_active(false)
77 {
78         if (m_bitLocalFlag.ServoControl)
79         {
80                 // in servo motion, the force is local if the target velocity is local
81                 m_bitLocalFlag.Force = m_bitLocalFlag.LinearVelocity;
82
83                 m_pid = m_torque;
84         }
85         if (m_reference)
86                 m_reference->RegisterActuator(this);
87         UpdateFuzzyFlags();
88 }
89
90 KX_ObjectActuator::~KX_ObjectActuator()
91 {
92         if (m_reference)
93                 m_reference->UnregisterActuator(this);
94 }
95
96 bool KX_ObjectActuator::Update()
97 {
98         
99         bool bNegativeEvent = IsNegativeEvent();
100         RemoveAllEvents();
101                 
102         KX_GameObject *parent = static_cast<KX_GameObject *>(GetParent()); 
103
104         if (bNegativeEvent) {
105                 // If we previously set the linear velocity we now have to inform
106                 // the physics controller that we no longer wish to apply it and that
107                 // it should reconcile the externally set velocity with it's 
108                 // own velocity.
109                 if (m_active_combined_velocity) {
110                         if (parent)
111                                 parent->ResolveCombinedVelocities(
112                                                 m_linear_velocity,
113                                                 m_angular_velocity,
114                                                 (m_bitLocalFlag.LinearVelocity) != 0,
115                                                 (m_bitLocalFlag.AngularVelocity) != 0
116                                         );
117                         m_active_combined_velocity = false;
118                 } 
119                 m_linear_damping_active = false;
120                 m_angular_damping_active = false;
121                 m_error_accumulator.setValue(0.0,0.0,0.0);
122                 m_previous_error.setValue(0.0,0.0,0.0);
123                 return false; 
124
125         } else if (parent)
126         {
127                 if (m_bitLocalFlag.ServoControl) 
128                 {
129                         // In this mode, we try to reach a target speed using force
130                         // As we don't know the friction, we must implement a generic 
131                         // servo control to achieve the speed in a configurable
132                         // v = current velocity
133                         // V = target velocity
134                         // e = V-v = speed error
135                         // dt = time interval since previous update
136                         // I = sum(e(t)*dt)
137                         // dv = e(t) - e(t-1)
138                         // KP, KD, KI : coefficient
139                         // F = KP*e+KI*I+KD*dv
140                         MT_Scalar mass = parent->GetMass();
141                         if (mass < MT_EPSILON)
142                                 return false;
143                         MT_Vector3 v = parent->GetLinearVelocity(m_bitLocalFlag.LinearVelocity);
144                         if (m_reference)
145                         {
146                                 const MT_Point3& mypos = parent->NodeGetWorldPosition();
147                                 const MT_Point3& refpos = m_reference->NodeGetWorldPosition();
148                                 MT_Point3 relpos;
149                                 relpos = (mypos-refpos);
150                                 MT_Vector3 vel= m_reference->GetVelocity(relpos);
151                                 if (m_bitLocalFlag.LinearVelocity)
152                                         // must convert in local space
153                                         vel = parent->NodeGetWorldOrientation().transposed()*vel;
154                                 v -= vel;
155                         }
156                         MT_Vector3 e = m_linear_velocity - v;
157                         MT_Vector3 dv = e - m_previous_error;
158                         MT_Vector3 I = m_error_accumulator + e;
159
160                         m_force = m_pid.x()*e+m_pid.y()*I+m_pid.z()*dv;
161                         // to automatically adapt the PID coefficient to mass;
162                         m_force *= mass;
163                         if (m_bitLocalFlag.Torque) 
164                         {
165                                 if (m_force[0] > m_dloc[0])
166                                 {
167                                         m_force[0] = m_dloc[0];
168                                         I[0] = m_error_accumulator[0];
169                                 } else if (m_force[0] < m_drot[0])
170                                 {
171                                         m_force[0] = m_drot[0];
172                                         I[0] = m_error_accumulator[0];
173                                 }
174                         }
175                         if (m_bitLocalFlag.DLoc) 
176                         {
177                                 if (m_force[1] > m_dloc[1])
178                                 {
179                                         m_force[1] = m_dloc[1];
180                                         I[1] = m_error_accumulator[1];
181                                 } else if (m_force[1] < m_drot[1])
182                                 {
183                                         m_force[1] = m_drot[1];
184                                         I[1] = m_error_accumulator[1];
185                                 }
186                         }
187                         if (m_bitLocalFlag.DRot) 
188                         {
189                                 if (m_force[2] > m_dloc[2])
190                                 {
191                                         m_force[2] = m_dloc[2];
192                                         I[2] = m_error_accumulator[2];
193                                 } else if (m_force[2] < m_drot[2])
194                                 {
195                                         m_force[2] = m_drot[2];
196                                         I[2] = m_error_accumulator[2];
197                                 }
198                         }
199                         m_previous_error = e;
200                         m_error_accumulator = I;
201                         parent->ApplyForce(m_force,(m_bitLocalFlag.LinearVelocity) != 0);
202                 } else
203                 {
204                         if (!m_bitLocalFlag.ZeroForce)
205                         {
206                                 parent->ApplyForce(m_force,(m_bitLocalFlag.Force) != 0);
207                         }
208                         if (!m_bitLocalFlag.ZeroTorque)
209                         {
210                                 parent->ApplyTorque(m_torque,(m_bitLocalFlag.Torque) != 0);
211                         }
212                         if (!m_bitLocalFlag.ZeroDLoc)
213                         {
214                                 parent->ApplyMovement(m_dloc,(m_bitLocalFlag.DLoc) != 0);
215                         }
216                         if (!m_bitLocalFlag.ZeroDRot)
217                         {
218                                 parent->ApplyRotation(m_drot,(m_bitLocalFlag.DRot) != 0);
219                         }
220                         if (!m_bitLocalFlag.ZeroLinearVelocity)
221                         {
222                                 if (m_bitLocalFlag.AddOrSetLinV) {
223                                         parent->addLinearVelocity(m_linear_velocity,(m_bitLocalFlag.LinearVelocity) != 0);
224                                 } else {
225                                         m_active_combined_velocity = true;
226                                         if (m_damping > 0) {
227                                                 MT_Vector3 linV;
228                                                 if (!m_linear_damping_active) {
229                                                         // delta and the start speed (depends on the existing speed in that direction)
230                                                         linV = parent->GetLinearVelocity(m_bitLocalFlag.LinearVelocity);
231                                                         // keep only the projection along the desired direction
232                                                         m_current_linear_factor = linV.dot(m_linear_velocity)/m_linear_length2;
233                                                         m_linear_damping_active = true;
234                                                 }
235                                                 if (m_current_linear_factor < 1.0)
236                                                         m_current_linear_factor += 1.0/m_damping;
237                                                 if (m_current_linear_factor > 1.0)
238                                                         m_current_linear_factor = 1.0;
239                                                 linV = m_current_linear_factor * m_linear_velocity;
240                                                 parent->setLinearVelocity(linV,(m_bitLocalFlag.LinearVelocity) != 0);
241                                         } else {
242                                                 parent->setLinearVelocity(m_linear_velocity,(m_bitLocalFlag.LinearVelocity) != 0);
243                                         }
244                                 }
245                         }
246                         if (!m_bitLocalFlag.ZeroAngularVelocity)
247                         {
248                                 m_active_combined_velocity = true;
249                                 if (m_damping > 0) {
250                                         MT_Vector3 angV;
251                                         if (!m_angular_damping_active) {
252                                                 // delta and the start speed (depends on the existing speed in that direction)
253                                                 angV = parent->GetAngularVelocity(m_bitLocalFlag.AngularVelocity);
254                                                 // keep only the projection along the desired direction
255                                                 m_current_angular_factor = angV.dot(m_angular_velocity)/m_angular_length2;
256                                                 m_angular_damping_active = true;
257                                         }
258                                         if (m_current_angular_factor < 1.0)
259                                                 m_current_angular_factor += 1.0/m_damping;
260                                         if (m_current_angular_factor > 1.0)
261                                                 m_current_angular_factor = 1.0;
262                                         angV = m_current_angular_factor * m_angular_velocity;
263                                         parent->setAngularVelocity(angV,(m_bitLocalFlag.AngularVelocity) != 0);
264                                 } else {
265                                         parent->setAngularVelocity(m_angular_velocity,(m_bitLocalFlag.AngularVelocity) != 0);
266                                 }
267                         }
268                 }
269                 
270         }
271         return true;
272 }
273
274
275
276 CValue* KX_ObjectActuator::GetReplica()
277 {
278         KX_ObjectActuator* replica = new KX_ObjectActuator(*this);//m_float,GetName());
279         replica->ProcessReplica();
280
281         return replica;
282 }
283
284 void KX_ObjectActuator::ProcessReplica()
285 {
286         SCA_IActuator::ProcessReplica();
287         if (m_reference)
288                 m_reference->RegisterActuator(this);
289 }
290
291 bool KX_ObjectActuator::UnlinkObject(SCA_IObject* clientobj)
292 {
293         if (clientobj == (SCA_IObject*)m_reference)
294         {
295                 // this object is being deleted, we cannot continue to use it as reference.
296                 m_reference = NULL;
297                 return true;
298         }
299         return false;
300 }
301
302 void KX_ObjectActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map)
303 {
304         void **h_obj = (*obj_map)[m_reference];
305         if (h_obj) {
306                 if (m_reference)
307                         m_reference->UnregisterActuator(this);
308                 m_reference = (KX_GameObject*)(*h_obj);
309                 m_reference->RegisterActuator(this);
310         }
311 }
312
313 /* some 'standard' utilities... */
314 bool KX_ObjectActuator::isValid(KX_ObjectActuator::KX_OBJECT_ACT_VEC_TYPE type)
315 {
316         bool res = false;
317         res = (type > KX_OBJECT_ACT_NODEF) && (type < KX_OBJECT_ACT_MAX);
318         return res;
319 }
320
321
322
323 /* ------------------------------------------------------------------------- */
324 /* Python functions                                                          */
325 /* ------------------------------------------------------------------------- */
326
327 /* Integration hooks ------------------------------------------------------- */
328 PyTypeObject KX_ObjectActuator::Type = {
329 #if (PY_VERSION_HEX >= 0x02060000)
330         PyVarObject_HEAD_INIT(NULL, 0)
331 #else
332         /* python 2.5 and below */
333         PyObject_HEAD_INIT( NULL )  /* required py macro */
334         0,                          /* ob_size */
335 #endif
336         "KX_ObjectActuator",
337         sizeof(PyObjectPlus_Proxy),
338         0,
339         py_base_dealloc,
340         0,
341         0,
342         0,
343         0,
344         py_base_repr,
345         0,0,0,0,0,0,
346         py_base_getattro,
347         py_base_setattro,
348         0,0,0,0,0,0,0,0,0,
349         Methods
350 };
351
352 PyParentObject KX_ObjectActuator::Parents[] = {
353         &KX_ObjectActuator::Type,
354         &SCA_IActuator::Type,
355         &SCA_ILogicBrick::Type,
356         &CValue::Type,
357         NULL
358 };
359
360 PyMethodDef KX_ObjectActuator::Methods[] = {
361         // Deprecated ----->
362         {"getForce", (PyCFunction) KX_ObjectActuator::sPyGetForce, METH_NOARGS},
363         {"setForce", (PyCFunction) KX_ObjectActuator::sPySetForce, METH_VARARGS},
364         {"getTorque", (PyCFunction) KX_ObjectActuator::sPyGetTorque, METH_NOARGS},
365         {"setTorque", (PyCFunction) KX_ObjectActuator::sPySetTorque, METH_VARARGS},
366         {"getDLoc", (PyCFunction) KX_ObjectActuator::sPyGetDLoc, METH_NOARGS},
367         {"setDLoc", (PyCFunction) KX_ObjectActuator::sPySetDLoc, METH_VARARGS},
368         {"getDRot", (PyCFunction) KX_ObjectActuator::sPyGetDRot, METH_NOARGS},
369         {"setDRot", (PyCFunction) KX_ObjectActuator::sPySetDRot, METH_VARARGS},
370         {"getLinearVelocity", (PyCFunction) KX_ObjectActuator::sPyGetLinearVelocity, METH_NOARGS},
371         {"setLinearVelocity", (PyCFunction) KX_ObjectActuator::sPySetLinearVelocity, METH_VARARGS},
372         {"getAngularVelocity", (PyCFunction) KX_ObjectActuator::sPyGetAngularVelocity, METH_NOARGS},
373         {"setAngularVelocity", (PyCFunction) KX_ObjectActuator::sPySetAngularVelocity, METH_VARARGS},
374         {"setDamping", (PyCFunction) KX_ObjectActuator::sPySetDamping, METH_VARARGS},
375         {"getDamping", (PyCFunction) KX_ObjectActuator::sPyGetDamping, METH_NOARGS},
376         {"setForceLimitX", (PyCFunction) KX_ObjectActuator::sPySetForceLimitX, METH_VARARGS},
377         {"getForceLimitX", (PyCFunction) KX_ObjectActuator::sPyGetForceLimitX, METH_NOARGS},
378         {"setForceLimitY", (PyCFunction) KX_ObjectActuator::sPySetForceLimitY, METH_VARARGS},
379         {"getForceLimitY", (PyCFunction) KX_ObjectActuator::sPyGetForceLimitY, METH_NOARGS},
380         {"setForceLimitZ", (PyCFunction) KX_ObjectActuator::sPySetForceLimitZ, METH_VARARGS},
381         {"getForceLimitZ", (PyCFunction) KX_ObjectActuator::sPyGetForceLimitZ, METH_NOARGS},
382         {"setPID", (PyCFunction) KX_ObjectActuator::sPyGetPID, METH_NOARGS},
383         {"getPID", (PyCFunction) KX_ObjectActuator::sPySetPID, METH_VARARGS},
384
385         // <----- Deprecated
386
387         {NULL,NULL} //Sentinel
388 };
389
390 PyAttributeDef KX_ObjectActuator::Attributes[] = {
391         KX_PYATTRIBUTE_VECTOR_RW_CHECK("force", -1000, 1000, false, KX_ObjectActuator, m_force, PyUpdateFuzzyFlags),
392         KX_PYATTRIBUTE_BOOL_RW("useLocalForce", KX_ObjectActuator, m_bitLocalFlag.Force),
393         KX_PYATTRIBUTE_VECTOR_RW_CHECK("torque", -1000, 1000, false, KX_ObjectActuator, m_torque, PyUpdateFuzzyFlags),
394         KX_PYATTRIBUTE_BOOL_RW("useLocalTorque", KX_ObjectActuator, m_bitLocalFlag.Torque),
395         KX_PYATTRIBUTE_VECTOR_RW_CHECK("dLoc", -1000, 1000, false, KX_ObjectActuator, m_dloc, PyUpdateFuzzyFlags),
396         KX_PYATTRIBUTE_BOOL_RW("useLocalDLoc", KX_ObjectActuator, m_bitLocalFlag.DLoc),
397         KX_PYATTRIBUTE_VECTOR_RW_CHECK("dRot", -1000, 1000, false, KX_ObjectActuator, m_drot, PyUpdateFuzzyFlags),
398         KX_PYATTRIBUTE_BOOL_RW("useLocalDRot", KX_ObjectActuator, m_bitLocalFlag.DRot),
399 #ifdef USE_MATHUTILS
400         KX_PYATTRIBUTE_RW_FUNCTION("linV", KX_ObjectActuator, pyattr_get_linV, pyattr_set_linV),
401         KX_PYATTRIBUTE_RW_FUNCTION("angV", KX_ObjectActuator, pyattr_get_angV, pyattr_set_angV),
402 #else
403         KX_PYATTRIBUTE_VECTOR_RW_CHECK("linV", -1000, 1000, false, KX_ObjectActuator, m_linear_velocity, PyUpdateFuzzyFlags),
404         KX_PYATTRIBUTE_VECTOR_RW_CHECK("angV", -1000, 1000, false, KX_ObjectActuator, m_angular_velocity, PyUpdateFuzzyFlags),
405 #endif
406         KX_PYATTRIBUTE_BOOL_RW("useLocalLinV", KX_ObjectActuator, m_bitLocalFlag.LinearVelocity),
407         KX_PYATTRIBUTE_BOOL_RW("useLocalAngV", KX_ObjectActuator, m_bitLocalFlag.AngularVelocity),
408         KX_PYATTRIBUTE_SHORT_RW("damping", 0, 1000, false, KX_ObjectActuator, m_damping),
409         KX_PYATTRIBUTE_RW_FUNCTION("forceLimitX", KX_ObjectActuator, pyattr_get_forceLimitX, pyattr_set_forceLimitX),
410         KX_PYATTRIBUTE_RW_FUNCTION("forceLimitY", KX_ObjectActuator, pyattr_get_forceLimitY, pyattr_set_forceLimitY),
411         KX_PYATTRIBUTE_RW_FUNCTION("forceLimitZ", KX_ObjectActuator, pyattr_get_forceLimitZ, pyattr_set_forceLimitZ),
412         KX_PYATTRIBUTE_VECTOR_RW_CHECK("pid", -100, 200, true, KX_ObjectActuator, m_pid, PyCheckPid),
413         KX_PYATTRIBUTE_RW_FUNCTION("reference", KX_ObjectActuator,pyattr_get_reference,pyattr_set_reference),
414         { NULL }        //Sentinel
415 };
416
417 PyObject* KX_ObjectActuator::py_getattro(PyObject *attr) {
418         py_getattro_up(SCA_IActuator);
419 }
420
421
422 PyObject* KX_ObjectActuator::py_getattro_dict() {
423         py_getattro_dict_up(SCA_IActuator);
424 }
425
426 int KX_ObjectActuator::py_setattro(PyObject *attr, PyObject *value)
427 {
428         py_setattro_up(SCA_IActuator);
429 }
430
431 /* Attribute get/set functions */
432
433 #ifdef USE_MATHUTILS
434
435 /* These require an SGNode */
436 #define MATHUTILS_VEC_CB_LINV 1
437 #define MATHUTILS_VEC_CB_ANGV 2
438
439 static int mathutils_kxobactu_vector_cb_index= -1; /* index for our callbacks */
440
441 static int mathutils_obactu_generic_check(PyObject *self_v)
442 {
443         KX_ObjectActuator* self= static_cast<KX_ObjectActuator*>BGE_PROXY_REF(self_v);
444         if(self==NULL)
445                 return 0;
446
447         return 1;
448 }
449
450 static int mathutils_obactu_vector_get(PyObject *self_v, int subtype, float *vec_from)
451 {
452         KX_ObjectActuator* self= static_cast<KX_ObjectActuator*>BGE_PROXY_REF(self_v);
453         if(self==NULL)
454                 return 0;
455
456         switch(subtype) {
457                 case MATHUTILS_VEC_CB_LINV:
458                         self->m_linear_velocity.getValue(vec_from);
459                         break;
460                 case MATHUTILS_VEC_CB_ANGV:
461                         self->m_angular_velocity.getValue(vec_from);
462                         break;
463         }
464
465         return 1;
466 }
467
468 static int mathutils_obactu_vector_set(PyObject *self_v, int subtype, float *vec_to)
469 {
470         KX_ObjectActuator* self= static_cast<KX_ObjectActuator*>BGE_PROXY_REF(self_v);
471         if(self==NULL)
472                 return 0;
473
474         switch(subtype) {
475                 case MATHUTILS_VEC_CB_LINV:
476                         self->m_linear_velocity.setValue(vec_to);
477                         break;
478                 case MATHUTILS_VEC_CB_ANGV:
479                         self->m_angular_velocity.setValue(vec_to);
480                         break;
481         }
482
483         return 1;
484 }
485
486 static int mathutils_obactu_vector_get_index(PyObject *self_v, int subtype, float *vec_from, int index)
487 {
488         float f[4];
489         /* lazy, avoid repeteing the case statement */
490         if(!mathutils_obactu_vector_get(self_v, subtype, f))
491                 return 0;
492
493         vec_from[index]= f[index];
494         return 1;
495 }
496
497 static int mathutils_obactu_vector_set_index(PyObject *self_v, int subtype, float *vec_to, int index)
498 {
499         float f= vec_to[index];
500
501         /* lazy, avoid repeteing the case statement */
502         if(!mathutils_obactu_vector_get(self_v, subtype, vec_to))
503                 return 0;
504
505         vec_to[index]= f;
506         mathutils_obactu_vector_set(self_v, subtype, vec_to);
507
508         return 1;
509 }
510
511 Mathutils_Callback mathutils_obactu_vector_cb = {
512         mathutils_obactu_generic_check,
513         mathutils_obactu_vector_get,
514         mathutils_obactu_vector_set,
515         mathutils_obactu_vector_get_index,
516         mathutils_obactu_vector_set_index
517 };
518
519 PyObject* KX_ObjectActuator::pyattr_get_linV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
520 {
521         return newVectorObject_cb((PyObject *)self_v, 3, mathutils_kxobactu_vector_cb_index, MATHUTILS_VEC_CB_LINV);
522 }
523
524 int KX_ObjectActuator::pyattr_set_linV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
525 {
526         KX_ObjectActuator* self= static_cast<KX_ObjectActuator*>(self_v);
527         if (!PyVecTo(value, self->m_linear_velocity))
528                 return PY_SET_ATTR_FAIL;
529
530         return PY_SET_ATTR_SUCCESS;
531 }
532
533 PyObject* KX_ObjectActuator::pyattr_get_angV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
534 {
535         return newVectorObject_cb((PyObject *)self_v, 3, mathutils_kxobactu_vector_cb_index, MATHUTILS_VEC_CB_ANGV);
536 }
537
538 int KX_ObjectActuator::pyattr_set_angV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
539 {
540         KX_ObjectActuator* self= static_cast<KX_ObjectActuator*>(self_v);
541         if (!PyVecTo(value, self->m_angular_velocity))
542                 return PY_SET_ATTR_FAIL;
543
544         return PY_SET_ATTR_SUCCESS;
545 }
546
547
548 void KX_ObjectActuator_Mathutils_Callback_Init(void)
549 {
550         // register mathutils callbacks, ok to run more then once.
551         mathutils_kxobactu_vector_cb_index= Mathutils_RegisterCallback(&mathutils_obactu_vector_cb);
552 }
553
554 #endif // USE_MATHUTILS
555
556 PyObject* KX_ObjectActuator::pyattr_get_forceLimitX(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
557 {
558         KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v);
559         PyObject *retVal = PyList_New(3);
560
561         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(self->m_drot[0]));
562         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(self->m_dloc[0]));
563         PyList_SET_ITEM(retVal, 2, PyBool_FromLong(self->m_bitLocalFlag.Torque));
564         
565         return retVal;
566 }
567
568 int KX_ObjectActuator::pyattr_set_forceLimitX(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
569 {
570         KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v);
571
572         PyObject* seq = PySequence_Fast(value, "");
573         if (seq && PySequence_Fast_GET_SIZE(seq) == 3)
574         {
575                 self->m_drot[0] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0));
576                 self->m_dloc[0] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 1));
577                 self->m_bitLocalFlag.Torque = (PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 2)) != 0);
578
579                 if (!PyErr_Occurred())
580                 {
581                         Py_DECREF(seq);
582                         return PY_SET_ATTR_SUCCESS;
583                 }
584         }
585
586         Py_XDECREF(seq);
587
588         PyErr_SetString(PyExc_ValueError, "expected a sequence of 2 floats and a bool");
589         return PY_SET_ATTR_FAIL;
590 }
591
592 PyObject* KX_ObjectActuator::pyattr_get_forceLimitY(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
593 {
594         KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v);
595         PyObject *retVal = PyList_New(3);
596
597         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(self->m_drot[1]));
598         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(self->m_dloc[1]));
599         PyList_SET_ITEM(retVal, 2, PyBool_FromLong(self->m_bitLocalFlag.DLoc));
600         
601         return retVal;
602 }
603
604 int     KX_ObjectActuator::pyattr_set_forceLimitY(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
605 {
606         KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v);
607
608         PyObject* seq = PySequence_Fast(value, "");
609         if (seq && PySequence_Fast_GET_SIZE(seq) == 3)
610         {
611                 self->m_drot[1] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0));
612                 self->m_dloc[1] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 1));
613                 self->m_bitLocalFlag.DLoc = (PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 2)) != 0);
614
615                 if (!PyErr_Occurred())
616                 {
617                         Py_DECREF(seq);
618                         return PY_SET_ATTR_SUCCESS;
619                 }
620         }
621
622         Py_XDECREF(seq);
623
624         PyErr_SetString(PyExc_ValueError, "expected a sequence of 2 floats and a bool");
625         return PY_SET_ATTR_FAIL;
626 }
627
628 PyObject* KX_ObjectActuator::pyattr_get_forceLimitZ(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
629 {
630         KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v);
631         PyObject *retVal = PyList_New(3);
632
633         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(self->m_drot[2]));
634         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(self->m_dloc[2]));
635         PyList_SET_ITEM(retVal, 2, PyBool_FromLong(self->m_bitLocalFlag.DRot));
636         
637         return retVal;
638 }
639
640 int     KX_ObjectActuator::pyattr_set_forceLimitZ(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
641 {
642         KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v);
643
644         PyObject* seq = PySequence_Fast(value, "");
645         if (seq && PySequence_Fast_GET_SIZE(seq) == 3)
646         {
647                 self->m_drot[2] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0));
648                 self->m_dloc[2] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 1));
649                 self->m_bitLocalFlag.DRot = (PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 2)) != 0);
650
651                 if (!PyErr_Occurred())
652                 {
653                         Py_DECREF(seq);
654                         return PY_SET_ATTR_SUCCESS;
655                 }
656         }
657
658         Py_XDECREF(seq);
659
660         PyErr_SetString(PyExc_ValueError, "expected a sequence of 2 floats and a bool");
661         return PY_SET_ATTR_FAIL;
662 }
663
664 PyObject* KX_ObjectActuator::pyattr_get_reference(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
665 {
666         KX_ObjectActuator* actuator = static_cast<KX_ObjectActuator*>(self);
667         if (!actuator->m_reference)
668                 Py_RETURN_NONE;
669         
670         return actuator->m_reference->GetProxy();
671 }
672
673 int KX_ObjectActuator::pyattr_set_reference(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
674 {
675         KX_ObjectActuator* actuator = static_cast<KX_ObjectActuator*>(self);
676         KX_GameObject *refOb;
677         
678         if (!ConvertPythonToGameObject(value, &refOb, true, "actu.reference = value: KX_ObjectActuator"))
679                 return PY_SET_ATTR_FAIL;
680         
681         if (actuator->m_reference)
682                 actuator->m_reference->UnregisterActuator(actuator);
683         
684         if(refOb==NULL) {
685                 actuator->m_reference= NULL;
686         }
687         else {  
688                 actuator->m_reference = refOb;
689                 actuator->m_reference->RegisterActuator(actuator);
690         }
691         
692         return PY_SET_ATTR_SUCCESS;
693 }
694
695
696 /* 1. set ------------------------------------------------------------------ */
697 /* Removed! */
698
699 /* 2. getForce                                                               */
700 PyObject* KX_ObjectActuator::PyGetForce()
701 {
702         ShowDeprecationWarning("getForce()", "the force and the useLocalForce properties");
703         PyObject *retVal = PyList_New(4);
704
705         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_force[0]));
706         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_force[1]));
707         PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_force[2]));
708         PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.Force));
709         
710         return retVal;
711 }
712 /* 3. setForce                                                               */
713 PyObject* KX_ObjectActuator::PySetForce(PyObject* args)
714 {
715         ShowDeprecationWarning("setForce()", "the force and the useLocalForce properties");
716         float vecArg[3];
717         int bToggle = 0;
718         if (!PyArg_ParseTuple(args, "fffi:setForce", &vecArg[0], &vecArg[1], 
719                                                   &vecArg[2], &bToggle)) {
720                 return NULL;
721         }
722         m_force.setValue(vecArg);
723         m_bitLocalFlag.Force = PyArgToBool(bToggle);
724         UpdateFuzzyFlags();
725         Py_RETURN_NONE;
726 }
727
728 /* 4. getTorque                                                              */
729 PyObject* KX_ObjectActuator::PyGetTorque()
730 {
731         ShowDeprecationWarning("getTorque()", "the torque and the useLocalTorque properties");
732         PyObject *retVal = PyList_New(4);
733
734         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_torque[0]));
735         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_torque[1]));
736         PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_torque[2]));
737         PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.Torque));
738         
739         return retVal;
740 }
741 /* 5. setTorque                                                              */
742 PyObject* KX_ObjectActuator::PySetTorque(PyObject* args)
743 {
744         ShowDeprecationWarning("setTorque()", "the torque and the useLocalTorque properties");
745         float vecArg[3];
746         int bToggle = 0;
747         if (!PyArg_ParseTuple(args, "fffi:setTorque", &vecArg[0], &vecArg[1], 
748                                                   &vecArg[2], &bToggle)) {
749                 return NULL;
750         }
751         m_torque.setValue(vecArg);
752         m_bitLocalFlag.Torque = PyArgToBool(bToggle);
753         UpdateFuzzyFlags();
754         Py_RETURN_NONE;
755 }
756
757 /* 6. getDLoc                                                                */
758 PyObject* KX_ObjectActuator::PyGetDLoc()
759 {
760         ShowDeprecationWarning("getDLoc()", "the dLoc and the useLocalDLoc properties");
761         PyObject *retVal = PyList_New(4);
762
763         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_dloc[0]));
764         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_dloc[1]));
765         PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_dloc[2]));
766         PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.DLoc));
767         
768         return retVal;
769 }
770 /* 7. setDLoc                                                                */
771 PyObject* KX_ObjectActuator::PySetDLoc(PyObject* args)
772 {
773         ShowDeprecationWarning("setDLoc()", "the dLoc and the useLocalDLoc properties");
774         float vecArg[3];
775         int bToggle = 0;
776         if(!PyArg_ParseTuple(args, "fffi:setDLoc", &vecArg[0], &vecArg[1], 
777                                                  &vecArg[2], &bToggle)) {
778                 return NULL;
779         }
780         m_dloc.setValue(vecArg);
781         m_bitLocalFlag.DLoc = PyArgToBool(bToggle);
782         UpdateFuzzyFlags();
783         Py_RETURN_NONE;
784 }
785
786 /* 8. getDRot                                                                */
787 PyObject* KX_ObjectActuator::PyGetDRot()
788 {
789         ShowDeprecationWarning("getDRot()", "the dRot and the useLocalDRot properties");
790         PyObject *retVal = PyList_New(4);
791
792         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_drot[0]));
793         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_drot[1]));
794         PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_drot[2]));
795         PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.DRot));
796         
797         return retVal;
798 }
799 /* 9. setDRot                                                                */
800 PyObject* KX_ObjectActuator::PySetDRot(PyObject* args)
801 {
802         ShowDeprecationWarning("setDRot()", "the dRot and the useLocalDRot properties");
803         float vecArg[3];
804         int bToggle = 0;
805         if (!PyArg_ParseTuple(args, "fffi:setDRot", &vecArg[0], &vecArg[1], 
806                                                   &vecArg[2], &bToggle)) {
807                 return NULL;
808         }
809         m_drot.setValue(vecArg);
810         m_bitLocalFlag.DRot = PyArgToBool(bToggle);
811         UpdateFuzzyFlags();
812         Py_RETURN_NONE;
813 }
814
815 /* 10. getLinearVelocity                                                 */
816 PyObject* KX_ObjectActuator::PyGetLinearVelocity() {
817         ShowDeprecationWarning("getLinearVelocity()", "the linV and the useLocalLinV properties");
818         PyObject *retVal = PyList_New(4);
819
820         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_linear_velocity[0]));
821         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_linear_velocity[1]));
822         PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_linear_velocity[2]));
823         PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.LinearVelocity));
824         
825         return retVal;
826 }
827
828 /* 11. setLinearVelocity                                                 */
829 PyObject* KX_ObjectActuator::PySetLinearVelocity(PyObject* args) {
830         ShowDeprecationWarning("setLinearVelocity()", "the linV and the useLocalLinV properties");
831         float vecArg[3];
832         int bToggle = 0;
833         if (!PyArg_ParseTuple(args, "fffi:setLinearVelocity", &vecArg[0], &vecArg[1], 
834                                                   &vecArg[2], &bToggle)) {
835                 return NULL;
836         }
837         m_linear_velocity.setValue(vecArg);
838         m_bitLocalFlag.LinearVelocity = PyArgToBool(bToggle);
839         UpdateFuzzyFlags();
840         Py_RETURN_NONE;
841 }
842
843
844 /* 12. getAngularVelocity                                                */
845 PyObject* KX_ObjectActuator::PyGetAngularVelocity() {
846         ShowDeprecationWarning("getAngularVelocity()", "the angV and the useLocalAngV properties");
847         PyObject *retVal = PyList_New(4);
848
849         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_angular_velocity[0]));
850         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_angular_velocity[1]));
851         PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_angular_velocity[2]));
852         PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.AngularVelocity));
853         
854         return retVal;
855 }
856 /* 13. setAngularVelocity                                                */
857 PyObject* KX_ObjectActuator::PySetAngularVelocity(PyObject* args) {
858         ShowDeprecationWarning("setAngularVelocity()", "the angV and the useLocalAngV properties");
859         float vecArg[3];
860         int bToggle = 0;
861         if (!PyArg_ParseTuple(args, "fffi:setAngularVelocity", &vecArg[0], &vecArg[1], 
862                                                   &vecArg[2], &bToggle)) {
863                 return NULL;
864         }
865         m_angular_velocity.setValue(vecArg);
866         m_bitLocalFlag.AngularVelocity = PyArgToBool(bToggle);
867         UpdateFuzzyFlags();
868         Py_RETURN_NONE;
869 }
870
871 /* 13. setDamping                                                */
872 PyObject* KX_ObjectActuator::PySetDamping(PyObject* args) {
873         ShowDeprecationWarning("setDamping()", "the damping property");
874         int damping = 0;
875         if (!PyArg_ParseTuple(args, "i:setDamping", &damping) || damping < 0 || damping > 1000) {
876                 return NULL;
877         }
878         m_damping = damping;
879         Py_RETURN_NONE;
880 }
881
882 /* 13. getVelocityDamping                                                */
883 PyObject* KX_ObjectActuator::PyGetDamping() {
884         ShowDeprecationWarning("getDamping()", "the damping property");
885         return Py_BuildValue("i",m_damping);
886 }
887 /* 6. getForceLimitX                                                                */
888 PyObject* KX_ObjectActuator::PyGetForceLimitX()
889 {
890         ShowDeprecationWarning("getForceLimitX()", "the forceLimitX property");
891         PyObject *retVal = PyList_New(3);
892
893         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_drot[0]));
894         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_dloc[0]));
895         PyList_SET_ITEM(retVal, 2, BoolToPyArg(m_bitLocalFlag.Torque));
896         
897         return retVal;
898 }
899 /* 7. setForceLimitX                                                         */
900 PyObject* KX_ObjectActuator::PySetForceLimitX(PyObject* args)
901 {
902         ShowDeprecationWarning("setForceLimitX()", "the forceLimitX property");
903         float vecArg[2];
904         int bToggle = 0;
905         if(!PyArg_ParseTuple(args, "ffi:setForceLimitX", &vecArg[0], &vecArg[1], &bToggle)) {
906                 return NULL;
907         }
908         m_drot[0] = vecArg[0];
909         m_dloc[0] = vecArg[1];
910         m_bitLocalFlag.Torque = PyArgToBool(bToggle);
911         Py_RETURN_NONE;
912 }
913
914 /* 6. getForceLimitY                                                                */
915 PyObject* KX_ObjectActuator::PyGetForceLimitY()
916 {
917         ShowDeprecationWarning("getForceLimitY()", "the forceLimitY property");
918         PyObject *retVal = PyList_New(3);
919
920         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_drot[1]));
921         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_dloc[1]));
922         PyList_SET_ITEM(retVal, 2, BoolToPyArg(m_bitLocalFlag.DLoc));
923         
924         return retVal;
925 }
926 /* 7. setForceLimitY                                                                */
927 PyObject* KX_ObjectActuator::PySetForceLimitY(PyObject* args)
928 {
929         ShowDeprecationWarning("setForceLimitY()", "the forceLimitY property");
930         float vecArg[2];
931         int bToggle = 0;
932         if(!PyArg_ParseTuple(args, "ffi:setForceLimitY", &vecArg[0], &vecArg[1], &bToggle)) {
933                 return NULL;
934         }
935         m_drot[1] = vecArg[0];
936         m_dloc[1] = vecArg[1];
937         m_bitLocalFlag.DLoc = PyArgToBool(bToggle);
938         Py_RETURN_NONE;
939 }
940
941 /* 6. getForceLimitZ                                                                */
942 PyObject* KX_ObjectActuator::PyGetForceLimitZ()
943 {
944         ShowDeprecationWarning("getForceLimitZ()", "the forceLimitZ property");
945         PyObject *retVal = PyList_New(3);
946
947         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_drot[2]));
948         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_dloc[2]));
949         PyList_SET_ITEM(retVal, 2, BoolToPyArg(m_bitLocalFlag.DRot));
950         
951         return retVal;
952 }
953 /* 7. setForceLimitZ                                                                */
954 PyObject* KX_ObjectActuator::PySetForceLimitZ(PyObject* args)
955 {
956         ShowDeprecationWarning("setForceLimitZ()", "the forceLimitZ property");
957         float vecArg[2];
958         int bToggle = 0;
959         if(!PyArg_ParseTuple(args, "ffi:setForceLimitZ", &vecArg[0], &vecArg[1], &bToggle)) {
960                 return NULL;
961         }
962         m_drot[2] = vecArg[0];
963         m_dloc[2] = vecArg[1];
964         m_bitLocalFlag.DRot = PyArgToBool(bToggle);
965         Py_RETURN_NONE;
966 }
967
968 /* 4. getPID                                                              */
969 PyObject* KX_ObjectActuator::PyGetPID()
970 {
971         ShowDeprecationWarning("getPID()", "the pid property");
972         PyObject *retVal = PyList_New(3);
973
974         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_pid[0]));
975         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_pid[1]));
976         PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_pid[2]));
977         
978         return retVal;
979 }
980 /* 5. setPID                                                              */
981 PyObject* KX_ObjectActuator::PySetPID(PyObject* args)
982 {
983         ShowDeprecationWarning("setPID()", "the pid property");
984         float vecArg[3];
985         if (!PyArg_ParseTuple(args, "fff:setPID", &vecArg[0], &vecArg[1], &vecArg[2])) {
986                 return NULL;
987         }
988         m_pid.setValue(vecArg);
989         Py_RETURN_NONE;
990 }
991
992
993
994
995
996 /* eof */