ifdef's for future py3 support, after this adding py3 can mostly be done with defines...
[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_IPhysicsController.h"
35
36 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif
39
40 /* ------------------------------------------------------------------------- */
41 /* Native functions                                                          */
42 /* ------------------------------------------------------------------------- */
43
44 KX_ObjectActuator::
45 KX_ObjectActuator(
46         SCA_IObject* gameobj,
47         const MT_Vector3& force,
48         const MT_Vector3& torque,
49         const MT_Vector3& dloc,
50         const MT_Vector3& drot,
51         const MT_Vector3& linV,
52         const MT_Vector3& angV,
53         const short damping,
54         const KX_LocalFlags& flag,
55         PyTypeObject* T
56 ) : 
57         SCA_IActuator(gameobj,T),
58         m_force(force),
59         m_torque(torque),
60         m_dloc(dloc),
61         m_drot(drot),
62         m_linear_velocity(linV),
63         m_angular_velocity(angV),
64         m_linear_length2(0.0),
65         m_current_linear_factor(0.0),
66         m_current_angular_factor(0.0),
67         m_damping(damping),
68         m_previous_error(0.0,0.0,0.0),
69         m_error_accumulator(0.0,0.0,0.0),
70         m_bitLocalFlag (flag),
71         m_active_combined_velocity (false),
72         m_linear_damping_active(false),
73         m_angular_damping_active(false)
74 {
75         if (m_bitLocalFlag.ServoControl)
76         {
77                 // in servo motion, the force is local if the target velocity is local
78                 m_bitLocalFlag.Force = m_bitLocalFlag.LinearVelocity;
79         }
80         UpdateFuzzyFlags();
81 }
82
83 bool KX_ObjectActuator::Update()
84 {
85         
86         bool bNegativeEvent = IsNegativeEvent();
87         RemoveAllEvents();
88                 
89         KX_GameObject *parent = static_cast<KX_GameObject *>(GetParent()); 
90
91         if (bNegativeEvent) {
92                 // If we previously set the linear velocity we now have to inform
93                 // the physics controller that we no longer wish to apply it and that
94                 // it should reconcile the externally set velocity with it's 
95                 // own velocity.
96                 if (m_active_combined_velocity) {
97                         if (parent)
98                                 parent->ResolveCombinedVelocities(
99                                                 m_linear_velocity,
100                                                 m_angular_velocity,
101                                                 (m_bitLocalFlag.LinearVelocity) != 0,
102                                                 (m_bitLocalFlag.AngularVelocity) != 0
103                                         );
104                         m_active_combined_velocity = false;
105                 } 
106                 m_linear_damping_active = false;
107                 m_angular_damping_active = false;
108                 m_error_accumulator.setValue(0.0,0.0,0.0);
109                 m_previous_error.setValue(0.0,0.0,0.0);
110                 return false; 
111
112         } else if (parent)
113         {
114                 if (m_bitLocalFlag.ServoControl) 
115                 {
116                         // In this mode, we try to reach a target speed using force
117                         // As we don't know the friction, we must implement a generic 
118                         // servo control to achieve the speed in a configurable
119                         // v = current velocity
120                         // V = target velocity
121                         // e = V-v = speed error
122                         // dt = time interval since previous update
123                         // I = sum(e(t)*dt)
124                         // dv = e(t) - e(t-1)
125                         // KP, KD, KI : coefficient
126                         // F = KP*e+KI*I+KD*dv
127                         MT_Scalar mass = parent->GetMass();
128                         if (mass < MT_EPSILON)
129                                 return false;
130                         MT_Vector3 v = parent->GetLinearVelocity(m_bitLocalFlag.LinearVelocity);
131                         MT_Vector3 e = m_linear_velocity - v;
132                         MT_Vector3 dv = e - m_previous_error;
133                         MT_Vector3 I = m_error_accumulator + e;
134
135                         m_force = m_torque.x()*e+m_torque.y()*I+m_torque.z()*dv;
136                         // to automatically adapt the PID coefficient to mass;
137                         m_force *= mass;
138                         if (m_bitLocalFlag.Torque) 
139                         {
140                                 if (m_force[0] > m_dloc[0])
141                                 {
142                                         m_force[0] = m_dloc[0];
143                                         I[0] = m_error_accumulator[0];
144                                 } else if (m_force[0] < m_drot[0])
145                                 {
146                                         m_force[0] = m_drot[0];
147                                         I[0] = m_error_accumulator[0];
148                                 }
149                         }
150                         if (m_bitLocalFlag.DLoc) 
151                         {
152                                 if (m_force[1] > m_dloc[1])
153                                 {
154                                         m_force[1] = m_dloc[1];
155                                         I[1] = m_error_accumulator[1];
156                                 } else if (m_force[1] < m_drot[1])
157                                 {
158                                         m_force[1] = m_drot[1];
159                                         I[1] = m_error_accumulator[1];
160                                 }
161                         }
162                         if (m_bitLocalFlag.DRot) 
163                         {
164                                 if (m_force[2] > m_dloc[2])
165                                 {
166                                         m_force[2] = m_dloc[2];
167                                         I[2] = m_error_accumulator[2];
168                                 } else if (m_force[2] < m_drot[2])
169                                 {
170                                         m_force[2] = m_drot[2];
171                                         I[2] = m_error_accumulator[2];
172                                 }
173                         }
174                         m_previous_error = e;
175                         m_error_accumulator = I;
176                         parent->ApplyForce(m_force,(m_bitLocalFlag.LinearVelocity) != 0);
177                 } else
178                 {
179                         if (!m_bitLocalFlag.ZeroForce)
180                         {
181                                 parent->ApplyForce(m_force,(m_bitLocalFlag.Force) != 0);
182                         }
183                         if (!m_bitLocalFlag.ZeroTorque)
184                         {
185                                 parent->ApplyTorque(m_torque,(m_bitLocalFlag.Torque) != 0);
186                         }
187                         if (!m_bitLocalFlag.ZeroDLoc)
188                         {
189                                 parent->ApplyMovement(m_dloc,(m_bitLocalFlag.DLoc) != 0);
190                         }
191                         if (!m_bitLocalFlag.ZeroDRot)
192                         {
193                                 parent->ApplyRotation(m_drot,(m_bitLocalFlag.DRot) != 0);
194                         }
195                         if (!m_bitLocalFlag.ZeroLinearVelocity)
196                         {
197                                 if (m_bitLocalFlag.AddOrSetLinV) {
198                                         parent->addLinearVelocity(m_linear_velocity,(m_bitLocalFlag.LinearVelocity) != 0);
199                                 } else {
200                                         m_active_combined_velocity = true;
201                                         if (m_damping > 0) {
202                                                 MT_Vector3 linV;
203                                                 if (!m_linear_damping_active) {
204                                                         // delta and the start speed (depends on the existing speed in that direction)
205                                                         linV = parent->GetLinearVelocity(m_bitLocalFlag.LinearVelocity);
206                                                         // keep only the projection along the desired direction
207                                                         m_current_linear_factor = linV.dot(m_linear_velocity)/m_linear_length2;
208                                                         m_linear_damping_active = true;
209                                                 }
210                                                 if (m_current_linear_factor < 1.0)
211                                                         m_current_linear_factor += 1.0/m_damping;
212                                                 if (m_current_linear_factor > 1.0)
213                                                         m_current_linear_factor = 1.0;
214                                                 linV = m_current_linear_factor * m_linear_velocity;
215                                                 parent->setLinearVelocity(linV,(m_bitLocalFlag.LinearVelocity) != 0);
216                                         } else {
217                                                 parent->setLinearVelocity(m_linear_velocity,(m_bitLocalFlag.LinearVelocity) != 0);
218                                         }
219                                 }
220                         }
221                         if (!m_bitLocalFlag.ZeroAngularVelocity)
222                         {
223                                 m_active_combined_velocity = true;
224                                 if (m_damping > 0) {
225                                         MT_Vector3 angV;
226                                         if (!m_angular_damping_active) {
227                                                 // delta and the start speed (depends on the existing speed in that direction)
228                                                 angV = parent->GetAngularVelocity(m_bitLocalFlag.AngularVelocity);
229                                                 // keep only the projection along the desired direction
230                                                 m_current_angular_factor = angV.dot(m_angular_velocity)/m_angular_length2;
231                                                 m_angular_damping_active = true;
232                                         }
233                                         if (m_current_angular_factor < 1.0)
234                                                 m_current_angular_factor += 1.0/m_damping;
235                                         if (m_current_angular_factor > 1.0)
236                                                 m_current_angular_factor = 1.0;
237                                         angV = m_current_angular_factor * m_angular_velocity;
238                                         parent->setAngularVelocity(angV,(m_bitLocalFlag.AngularVelocity) != 0);
239                                 } else {
240                                         parent->setAngularVelocity(m_angular_velocity,(m_bitLocalFlag.AngularVelocity) != 0);
241                                 }
242                         }
243                 }
244                 
245         }
246         return true;
247 }
248
249
250
251 CValue* KX_ObjectActuator::GetReplica()
252 {
253         KX_ObjectActuator* replica = new KX_ObjectActuator(*this);//m_float,GetName());
254         replica->ProcessReplica();
255
256         return replica;
257 }
258
259
260
261 /* some 'standard' utilities... */
262 bool KX_ObjectActuator::isValid(KX_ObjectActuator::KX_OBJECT_ACT_VEC_TYPE type)
263 {
264         bool res = false;
265         res = (type > KX_OBJECT_ACT_NODEF) && (type < KX_OBJECT_ACT_MAX);
266         return res;
267 }
268
269
270
271 /* ------------------------------------------------------------------------- */
272 /* Python functions                                                          */
273 /* ------------------------------------------------------------------------- */
274
275 /* Integration hooks ------------------------------------------------------- */
276 PyTypeObject KX_ObjectActuator::Type = {
277 #if (PY_VERSION_HEX >= 0x02060000)
278         PyVarObject_HEAD_INIT(NULL, 0)
279 #else
280         /* python 2.5 and below */
281         PyObject_HEAD_INIT( NULL )  /* required py macro */
282         0,                          /* ob_size */
283 #endif
284         "KX_ObjectActuator",
285         sizeof(PyObjectPlus_Proxy),
286         0,
287         py_base_dealloc,
288         0,
289         0,
290         0,
291         0,
292         py_base_repr,
293         0,0,0,0,0,0,
294         py_base_getattro,
295         py_base_setattro,
296         0,0,0,0,0,0,0,0,0,
297         Methods
298 };
299
300 PyParentObject KX_ObjectActuator::Parents[] = {
301         &KX_ObjectActuator::Type,
302         &SCA_IActuator::Type,
303         &SCA_ILogicBrick::Type,
304         &CValue::Type,
305         NULL
306 };
307
308 PyMethodDef KX_ObjectActuator::Methods[] = {
309         {"getForce", (PyCFunction) KX_ObjectActuator::sPyGetForce, METH_NOARGS},
310         {"setForce", (PyCFunction) KX_ObjectActuator::sPySetForce, METH_VARARGS},
311         {"getTorque", (PyCFunction) KX_ObjectActuator::sPyGetTorque, METH_NOARGS},
312         {"setTorque", (PyCFunction) KX_ObjectActuator::sPySetTorque, METH_VARARGS},
313         {"getDLoc", (PyCFunction) KX_ObjectActuator::sPyGetDLoc, METH_NOARGS},
314         {"setDLoc", (PyCFunction) KX_ObjectActuator::sPySetDLoc, METH_VARARGS},
315         {"getDRot", (PyCFunction) KX_ObjectActuator::sPyGetDRot, METH_NOARGS},
316         {"setDRot", (PyCFunction) KX_ObjectActuator::sPySetDRot, METH_VARARGS},
317         {"getLinearVelocity", (PyCFunction) KX_ObjectActuator::sPyGetLinearVelocity, METH_NOARGS},
318         {"setLinearVelocity", (PyCFunction) KX_ObjectActuator::sPySetLinearVelocity, METH_VARARGS},
319         {"getAngularVelocity", (PyCFunction) KX_ObjectActuator::sPyGetAngularVelocity, METH_NOARGS},
320         {"setAngularVelocity", (PyCFunction) KX_ObjectActuator::sPySetAngularVelocity, METH_VARARGS},
321         {"setDamping", (PyCFunction) KX_ObjectActuator::sPySetDamping, METH_VARARGS},
322         {"getDamping", (PyCFunction) KX_ObjectActuator::sPyGetDamping, METH_NOARGS},
323         {"setForceLimitX", (PyCFunction) KX_ObjectActuator::sPySetForceLimitX, METH_VARARGS},
324         {"getForceLimitX", (PyCFunction) KX_ObjectActuator::sPyGetForceLimitX, METH_NOARGS},
325         {"setForceLimitY", (PyCFunction) KX_ObjectActuator::sPySetForceLimitY, METH_VARARGS},
326         {"getForceLimitY", (PyCFunction) KX_ObjectActuator::sPyGetForceLimitY, METH_NOARGS},
327         {"setForceLimitZ", (PyCFunction) KX_ObjectActuator::sPySetForceLimitZ, METH_VARARGS},
328         {"getForceLimitZ", (PyCFunction) KX_ObjectActuator::sPyGetForceLimitZ, METH_NOARGS},
329         {"setPID", (PyCFunction) KX_ObjectActuator::sPyGetPID, METH_NOARGS},
330         {"getPID", (PyCFunction) KX_ObjectActuator::sPySetPID, METH_VARARGS},
331
332
333
334         {NULL,NULL} //Sentinel
335 };
336
337 PyAttributeDef KX_ObjectActuator::Attributes[] = {
338         //KX_PYATTRIBUTE_TODO("force"),
339         //KX_PYATTRIBUTE_TODO("torque"),
340         //KX_PYATTRIBUTE_TODO("dLoc"),
341         //KX_PYATTRIBUTE_TODO("dRot"),
342         //KX_PYATTRIBUTE_TODO("linV"),
343         //KX_PYATTRIBUTE_TODO("angV"),
344         //KX_PYATTRIBUTE_TODO("damping"),
345         //KX_PYATTRIBUTE_TODO("forceLimitX"),
346         //KX_PYATTRIBUTE_TODO("forceLimitY"),
347         //KX_PYATTRIBUTE_TODO("forceLimitZ"),
348         //KX_PYATTRIBUTE_TODO("pid"),
349         { NULL }        //Sentinel
350 };
351
352 PyObject* KX_ObjectActuator::py_getattro(PyObject *attr) {
353         py_getattro_up(SCA_IActuator);
354 };
355
356 PyObject* KX_ObjectActuator::py_getattro_dict() {
357         py_getattro_dict_up(SCA_IActuator);
358 }
359
360 /* 1. set ------------------------------------------------------------------ */
361 /* Removed! */
362
363 /* 2. getForce                                                               */
364 PyObject* KX_ObjectActuator::PyGetForce()
365 {
366         PyObject *retVal = PyList_New(4);
367
368         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_force[0]));
369         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_force[1]));
370         PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_force[2]));
371         PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.Force));
372         
373         return retVal;
374 }
375 /* 3. setForce                                                               */
376 PyObject* KX_ObjectActuator::PySetForce(PyObject* args)
377 {
378         float vecArg[3];
379         int bToggle = 0;
380         if (!PyArg_ParseTuple(args, "fffi:setForce", &vecArg[0], &vecArg[1], 
381                                                   &vecArg[2], &bToggle)) {
382                 return NULL;
383         }
384         m_force.setValue(vecArg);
385         m_bitLocalFlag.Force = PyArgToBool(bToggle);
386         UpdateFuzzyFlags();
387         Py_RETURN_NONE;
388 }
389
390 /* 4. getTorque                                                              */
391 PyObject* KX_ObjectActuator::PyGetTorque()
392 {
393         PyObject *retVal = PyList_New(4);
394
395         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_torque[0]));
396         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_torque[1]));
397         PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_torque[2]));
398         PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.Torque));
399         
400         return retVal;
401 }
402 /* 5. setTorque                                                              */
403 PyObject* KX_ObjectActuator::PySetTorque(PyObject* args)
404 {
405         float vecArg[3];
406         int bToggle = 0;
407         if (!PyArg_ParseTuple(args, "fffi:setTorque", &vecArg[0], &vecArg[1], 
408                                                   &vecArg[2], &bToggle)) {
409                 return NULL;
410         }
411         m_torque.setValue(vecArg);
412         m_bitLocalFlag.Torque = PyArgToBool(bToggle);
413         UpdateFuzzyFlags();
414         Py_RETURN_NONE;
415 }
416
417 /* 6. getDLoc                                                                */
418 PyObject* KX_ObjectActuator::PyGetDLoc()
419 {
420         PyObject *retVal = PyList_New(4);
421
422         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_dloc[0]));
423         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_dloc[1]));
424         PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_dloc[2]));
425         PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.DLoc));
426         
427         return retVal;
428 }
429 /* 7. setDLoc                                                                */
430 PyObject* KX_ObjectActuator::PySetDLoc(PyObject* args)
431 {
432         float vecArg[3];
433         int bToggle = 0;
434         if(!PyArg_ParseTuple(args, "fffi:setDLoc", &vecArg[0], &vecArg[1], 
435                                                  &vecArg[2], &bToggle)) {
436                 return NULL;
437         }
438         m_dloc.setValue(vecArg);
439         m_bitLocalFlag.DLoc = PyArgToBool(bToggle);
440         UpdateFuzzyFlags();
441         Py_RETURN_NONE;
442 }
443
444 /* 8. getDRot                                                                */
445 PyObject* KX_ObjectActuator::PyGetDRot()
446 {
447         PyObject *retVal = PyList_New(4);
448
449         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_drot[0]));
450         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_drot[1]));
451         PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_drot[2]));
452         PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.DRot));
453         
454         return retVal;
455 }
456 /* 9. setDRot                                                                */
457 PyObject* KX_ObjectActuator::PySetDRot(PyObject* args)
458 {
459         float vecArg[3];
460         int bToggle = 0;
461         if (!PyArg_ParseTuple(args, "fffi:setDRot", &vecArg[0], &vecArg[1], 
462                                                   &vecArg[2], &bToggle)) {
463                 return NULL;
464         }
465         m_drot.setValue(vecArg);
466         m_bitLocalFlag.DRot = PyArgToBool(bToggle);
467         UpdateFuzzyFlags();
468         Py_RETURN_NONE;
469 }
470
471 /* 10. getLinearVelocity                                                 */
472 PyObject* KX_ObjectActuator::PyGetLinearVelocity() {
473         PyObject *retVal = PyList_New(4);
474
475         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_linear_velocity[0]));
476         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_linear_velocity[1]));
477         PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_linear_velocity[2]));
478         PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.LinearVelocity));
479         
480         return retVal;
481 }
482
483 /* 11. setLinearVelocity                                                 */
484 PyObject* KX_ObjectActuator::PySetLinearVelocity(PyObject* args) {
485         float vecArg[3];
486         int bToggle = 0;
487         if (!PyArg_ParseTuple(args, "fffi:setLinearVelocity", &vecArg[0], &vecArg[1], 
488                                                   &vecArg[2], &bToggle)) {
489                 return NULL;
490         }
491         m_linear_velocity.setValue(vecArg);
492         m_bitLocalFlag.LinearVelocity = PyArgToBool(bToggle);
493         UpdateFuzzyFlags();
494         Py_RETURN_NONE;
495 }
496
497
498 /* 12. getAngularVelocity                                                */
499 PyObject* KX_ObjectActuator::PyGetAngularVelocity() {
500         PyObject *retVal = PyList_New(4);
501
502         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_angular_velocity[0]));
503         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_angular_velocity[1]));
504         PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_angular_velocity[2]));
505         PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.AngularVelocity));
506         
507         return retVal;
508 }
509 /* 13. setAngularVelocity                                                */
510 PyObject* KX_ObjectActuator::PySetAngularVelocity(PyObject* args) {
511         float vecArg[3];
512         int bToggle = 0;
513         if (!PyArg_ParseTuple(args, "fffi:setAngularVelocity", &vecArg[0], &vecArg[1], 
514                                                   &vecArg[2], &bToggle)) {
515                 return NULL;
516         }
517         m_angular_velocity.setValue(vecArg);
518         m_bitLocalFlag.AngularVelocity = PyArgToBool(bToggle);
519         UpdateFuzzyFlags();
520         Py_RETURN_NONE;
521 }
522
523 /* 13. setDamping                                                */
524 PyObject* KX_ObjectActuator::PySetDamping(PyObject* args) {
525         int damping = 0;
526         if (!PyArg_ParseTuple(args, "i:setDamping", &damping) || damping < 0 || damping > 1000) {
527                 return NULL;
528         }
529         m_damping = damping;
530         Py_RETURN_NONE;
531 }
532
533 /* 13. getVelocityDamping                                                */
534 PyObject* KX_ObjectActuator::PyGetDamping() {
535         return Py_BuildValue("i",m_damping);
536 }
537 /* 6. getForceLimitX                                                                */
538 PyObject* KX_ObjectActuator::PyGetForceLimitX()
539 {
540         PyObject *retVal = PyList_New(3);
541
542         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_drot[0]));
543         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_dloc[0]));
544         PyList_SET_ITEM(retVal, 2, BoolToPyArg(m_bitLocalFlag.Torque));
545         
546         return retVal;
547 }
548 /* 7. setForceLimitX                                                         */
549 PyObject* KX_ObjectActuator::PySetForceLimitX(PyObject* args)
550 {
551         float vecArg[2];
552         int bToggle = 0;
553         if(!PyArg_ParseTuple(args, "ffi:setForceLimitX", &vecArg[0], &vecArg[1], &bToggle)) {
554                 return NULL;
555         }
556         m_drot[0] = vecArg[0];
557         m_dloc[0] = vecArg[1];
558         m_bitLocalFlag.Torque = PyArgToBool(bToggle);
559         Py_RETURN_NONE;
560 }
561
562 /* 6. getForceLimitY                                                                */
563 PyObject* KX_ObjectActuator::PyGetForceLimitY()
564 {
565         PyObject *retVal = PyList_New(3);
566
567         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_drot[1]));
568         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_dloc[1]));
569         PyList_SET_ITEM(retVal, 2, BoolToPyArg(m_bitLocalFlag.DLoc));
570         
571         return retVal;
572 }
573 /* 7. setForceLimitY                                                                */
574 PyObject* KX_ObjectActuator::PySetForceLimitY(PyObject* args)
575 {
576         float vecArg[2];
577         int bToggle = 0;
578         if(!PyArg_ParseTuple(args, "ffi:setForceLimitY", &vecArg[0], &vecArg[1], &bToggle)) {
579                 return NULL;
580         }
581         m_drot[1] = vecArg[0];
582         m_dloc[1] = vecArg[1];
583         m_bitLocalFlag.DLoc = PyArgToBool(bToggle);
584         Py_RETURN_NONE;
585 }
586
587 /* 6. getForceLimitZ                                                                */
588 PyObject* KX_ObjectActuator::PyGetForceLimitZ()
589 {
590         PyObject *retVal = PyList_New(3);
591
592         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_drot[2]));
593         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_dloc[2]));
594         PyList_SET_ITEM(retVal, 2, BoolToPyArg(m_bitLocalFlag.DRot));
595         
596         return retVal;
597 }
598 /* 7. setForceLimitZ                                                                */
599 PyObject* KX_ObjectActuator::PySetForceLimitZ(PyObject* args)
600 {
601         float vecArg[2];
602         int bToggle = 0;
603         if(!PyArg_ParseTuple(args, "ffi:setForceLimitZ", &vecArg[0], &vecArg[1], &bToggle)) {
604                 return NULL;
605         }
606         m_drot[2] = vecArg[0];
607         m_dloc[2] = vecArg[1];
608         m_bitLocalFlag.DRot = PyArgToBool(bToggle);
609         Py_RETURN_NONE;
610 }
611
612 /* 4. getPID                                                              */
613 PyObject* KX_ObjectActuator::PyGetPID()
614 {
615         PyObject *retVal = PyList_New(3);
616
617         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_torque[0]));
618         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_torque[1]));
619         PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_torque[2]));
620         
621         return retVal;
622 }
623 /* 5. setPID                                                              */
624 PyObject* KX_ObjectActuator::PySetPID(PyObject* args)
625 {
626         float vecArg[3];
627         if (!PyArg_ParseTuple(args, "fff:setPID", &vecArg[0], &vecArg[1], &vecArg[2])) {
628                 return NULL;
629         }
630         m_torque.setValue(vecArg);
631         Py_RETURN_NONE;
632 }
633
634
635
636
637
638 /* eof */