9ac0b4d47038855b92bfed9efc8424c8fc387b08
[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_bitLocalFlag (flag),
69         m_active_combined_velocity (false),
70         m_linear_damping_active(false),
71         m_angular_damping_active(false),
72         m_error_accumulator(0.0,0.0,0.0),
73         m_previous_error(0.0,0.0,0.0)
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         // this will copy properties and so on...
257         CValue::AddDataToReplica(replica);
258
259         return replica;
260 }
261
262
263
264 /* some 'standard' utilities... */
265 bool KX_ObjectActuator::isValid(KX_ObjectActuator::KX_OBJECT_ACT_VEC_TYPE type)
266 {
267         bool res = false;
268         res = (type > KX_OBJECT_ACT_NODEF) && (type < KX_OBJECT_ACT_MAX);
269         return res;
270 }
271
272
273
274 /* ------------------------------------------------------------------------- */
275 /* Python functions                                                          */
276 /* ------------------------------------------------------------------------- */
277
278 /* Integration hooks ------------------------------------------------------- */
279 PyTypeObject KX_ObjectActuator::Type = {
280         PyObject_HEAD_INIT(&PyType_Type)
281         0,
282         "KX_ObjectActuator",
283         sizeof(KX_ObjectActuator),
284         0,
285         PyDestructor,
286         0,
287         __getattr,
288         __setattr,
289         0, //&MyPyCompare,
290         __repr,
291         0, //&cvalue_as_number,
292         0,
293         0,
294         0,
295         0
296 };
297
298 PyParentObject KX_ObjectActuator::Parents[] = {
299         &KX_ObjectActuator::Type,
300         &SCA_IActuator::Type,
301         &SCA_ILogicBrick::Type,
302         &CValue::Type,
303         NULL
304 };
305
306 PyMethodDef KX_ObjectActuator::Methods[] = {
307         {"getForce", (PyCFunction) KX_ObjectActuator::sPyGetForce, METH_VARARGS},
308         {"setForce", (PyCFunction) KX_ObjectActuator::sPySetForce, METH_VARARGS},
309         {"getTorque", (PyCFunction) KX_ObjectActuator::sPyGetTorque, METH_VARARGS},
310         {"setTorque", (PyCFunction) KX_ObjectActuator::sPySetTorque, METH_VARARGS},
311         {"getDLoc", (PyCFunction) KX_ObjectActuator::sPyGetDLoc, METH_VARARGS},
312         {"setDLoc", (PyCFunction) KX_ObjectActuator::sPySetDLoc, METH_VARARGS},
313         {"getDRot", (PyCFunction) KX_ObjectActuator::sPyGetDRot, METH_VARARGS},
314         {"setDRot", (PyCFunction) KX_ObjectActuator::sPySetDRot, METH_VARARGS},
315         {"getLinearVelocity", (PyCFunction) KX_ObjectActuator::sPyGetLinearVelocity, METH_VARARGS},
316         {"setLinearVelocity", (PyCFunction) KX_ObjectActuator::sPySetLinearVelocity, METH_VARARGS},
317         {"getAngularVelocity", (PyCFunction) KX_ObjectActuator::sPyGetAngularVelocity, METH_VARARGS},
318         {"setAngularVelocity", (PyCFunction) KX_ObjectActuator::sPySetAngularVelocity, METH_VARARGS},
319         {"setDamping", (PyCFunction) KX_ObjectActuator::sPySetDamping, METH_VARARGS},
320         {"getDamping", (PyCFunction) KX_ObjectActuator::sPyGetDamping, METH_VARARGS},
321         {"setForceLimitX", (PyCFunction) KX_ObjectActuator::sPySetForceLimitX, METH_VARARGS},
322         {"getForceLimitX", (PyCFunction) KX_ObjectActuator::sPyGetForceLimitX, METH_VARARGS},
323         {"setForceLimitY", (PyCFunction) KX_ObjectActuator::sPySetForceLimitY, METH_VARARGS},
324         {"getForceLimitY", (PyCFunction) KX_ObjectActuator::sPyGetForceLimitY, METH_VARARGS},
325         {"setForceLimitZ", (PyCFunction) KX_ObjectActuator::sPySetForceLimitZ, METH_VARARGS},
326         {"getForceLimitZ", (PyCFunction) KX_ObjectActuator::sPyGetForceLimitZ, METH_VARARGS},
327         {"setPID", (PyCFunction) KX_ObjectActuator::sPyGetPID, METH_VARARGS},
328         {"getPID", (PyCFunction) KX_ObjectActuator::sPySetPID, METH_VARARGS},
329
330
331
332         {NULL,NULL} //Sentinel
333 };
334
335 PyObject* KX_ObjectActuator::_getattr(const STR_String& attr) {
336         _getattr_up(SCA_IActuator);
337 };
338
339 /* 1. set ------------------------------------------------------------------ */
340 /* Removed! */
341
342 /* 2. getForce                                                               */
343 PyObject* KX_ObjectActuator::PyGetForce(PyObject* self, 
344                                                                                 PyObject* args, 
345                                                                                 PyObject* kwds)
346 {
347         PyObject *retVal = PyList_New(4);
348
349         PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_force[0]));
350         PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_force[1]));
351         PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_force[2]));
352         PyList_SetItem(retVal, 3, BoolToPyArg(m_bitLocalFlag.Force));
353         
354         return retVal;
355 }
356 /* 3. setForce                                                               */
357 PyObject* KX_ObjectActuator::PySetForce(PyObject* self, 
358                                                                                 PyObject* args, 
359                                                                                 PyObject* kwds)
360 {
361         float vecArg[3];
362         int bToggle = 0;
363         if (!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1], 
364                                                   &vecArg[2], &bToggle)) {
365                 return NULL;
366         }
367         m_force.setValue(vecArg);
368         m_bitLocalFlag.Force = PyArgToBool(bToggle);
369         UpdateFuzzyFlags();
370         Py_Return;
371 }
372
373 /* 4. getTorque                                                              */
374 PyObject* KX_ObjectActuator::PyGetTorque(PyObject* self, 
375                                                                                  PyObject* args, 
376                                                                                  PyObject* kwds)
377 {
378         PyObject *retVal = PyList_New(4);
379
380         PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_torque[0]));
381         PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_torque[1]));
382         PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_torque[2]));
383         PyList_SetItem(retVal, 3, BoolToPyArg(m_bitLocalFlag.Torque));
384         
385         return retVal;
386 }
387 /* 5. setTorque                                                              */
388 PyObject* KX_ObjectActuator::PySetTorque(PyObject* self, 
389                                                                                  PyObject* args, 
390                                                                                  PyObject* kwds)
391 {
392         float vecArg[3];
393         int bToggle = 0;
394         if (!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1], 
395                                                   &vecArg[2], &bToggle)) {
396                 return NULL;
397         }
398         m_torque.setValue(vecArg);
399         m_bitLocalFlag.Torque = PyArgToBool(bToggle);
400         UpdateFuzzyFlags();
401         Py_Return;
402 }
403
404 /* 6. getDLoc                                                                */
405 PyObject* KX_ObjectActuator::PyGetDLoc(PyObject* self, 
406                                                                            PyObject* args, 
407                                                                            PyObject* kwds)
408 {
409         PyObject *retVal = PyList_New(4);
410
411         PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_dloc[0]));
412         PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_dloc[1]));
413         PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_dloc[2]));
414         PyList_SetItem(retVal, 3, BoolToPyArg(m_bitLocalFlag.DLoc));
415         
416         return retVal;
417 }
418 /* 7. setDLoc                                                                */
419 PyObject* KX_ObjectActuator::PySetDLoc(PyObject* self, 
420                                                                            PyObject* args, 
421                                                                            PyObject* kwds)
422 {
423         float vecArg[3];
424         int bToggle = 0;
425         if(!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1], 
426                                                  &vecArg[2], &bToggle)) {
427                 return NULL;
428         }
429         m_dloc.setValue(vecArg);
430         m_bitLocalFlag.DLoc = PyArgToBool(bToggle);
431         UpdateFuzzyFlags();
432         Py_Return;
433 }
434
435 /* 8. getDRot                                                                */
436 PyObject* KX_ObjectActuator::PyGetDRot(PyObject* self, 
437                                                                            PyObject* args, 
438                                                                            PyObject* kwds)
439 {
440         PyObject *retVal = PyList_New(4);
441
442         PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_drot[0]));
443         PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_drot[1]));
444         PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_drot[2]));
445         PyList_SetItem(retVal, 3, BoolToPyArg(m_bitLocalFlag.DRot));
446         
447         return retVal;
448 }
449 /* 9. setDRot                                                                */
450 PyObject* KX_ObjectActuator::PySetDRot(PyObject* self, 
451                                                                            PyObject* args, 
452                                                                            PyObject* kwds)
453 {
454         float vecArg[3];
455         int bToggle = 0;
456         if (!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1], 
457                                                   &vecArg[2], &bToggle)) {
458                 return NULL;
459         }
460         m_drot.setValue(vecArg);
461         m_bitLocalFlag.DRot = PyArgToBool(bToggle);
462         UpdateFuzzyFlags();
463         Py_Return;
464 }
465
466 /* 10. getLinearVelocity                                                 */
467 PyObject* KX_ObjectActuator::PyGetLinearVelocity(PyObject* self, 
468                                                                                                  PyObject* args, 
469                                                                                                  PyObject* kwds) {
470         PyObject *retVal = PyList_New(4);
471
472         PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_linear_velocity[0]));
473         PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_linear_velocity[1]));
474         PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_linear_velocity[2]));
475         PyList_SetItem(retVal, 3, BoolToPyArg(m_bitLocalFlag.LinearVelocity));
476         
477         return retVal;
478 }
479
480 /* 11. setLinearVelocity                                                 */
481 PyObject* KX_ObjectActuator::PySetLinearVelocity(PyObject* self, 
482                                                                                                  PyObject* args, 
483                                                                                                  PyObject* kwds) {
484         float vecArg[3];
485         int bToggle = 0;
486         if (!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1], 
487                                                   &vecArg[2], &bToggle)) {
488                 return NULL;
489         }
490         m_linear_velocity.setValue(vecArg);
491         m_bitLocalFlag.LinearVelocity = PyArgToBool(bToggle);
492         UpdateFuzzyFlags();
493         Py_Return;
494 }
495
496
497 /* 12. getAngularVelocity                                                */
498 PyObject* KX_ObjectActuator::PyGetAngularVelocity(PyObject* self, 
499                                                                                                   PyObject* args, 
500                                                                                                   PyObject* kwds) {
501         PyObject *retVal = PyList_New(4);
502
503         PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_angular_velocity[0]));
504         PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_angular_velocity[1]));
505         PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_angular_velocity[2]));
506         PyList_SetItem(retVal, 3, BoolToPyArg(m_bitLocalFlag.AngularVelocity));
507         
508         return retVal;
509 }
510 /* 13. setAngularVelocity                                                */
511 PyObject* KX_ObjectActuator::PySetAngularVelocity(PyObject* self, 
512                                                                                                   PyObject* args, 
513                                                                                                   PyObject* kwds) {
514         float vecArg[3];
515         int bToggle = 0;
516         if (!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1], 
517                                                   &vecArg[2], &bToggle)) {
518                 return NULL;
519         }
520         m_angular_velocity.setValue(vecArg);
521         m_bitLocalFlag.AngularVelocity = PyArgToBool(bToggle);
522         UpdateFuzzyFlags();
523         Py_Return;
524 }
525
526 /* 13. setDamping                                                */
527 PyObject* KX_ObjectActuator::PySetDamping(PyObject* self, 
528                                                                                   PyObject* args, 
529                                                                                   PyObject* kwds) {
530         int damping = 0;
531         if (!PyArg_ParseTuple(args, "i", &damping) || damping < 0 || damping > 1000) {
532                 return NULL;
533         }
534         m_damping = damping;
535         Py_Return;
536 }
537
538 /* 13. getVelocityDamping                                                */
539 PyObject* KX_ObjectActuator::PyGetDamping(PyObject* self, 
540                                                                                   PyObject* args, 
541                                                                                   PyObject* kwds) {
542         return Py_BuildValue("i",m_damping);
543 }
544 /* 6. getForceLimitX                                                                */
545 PyObject* KX_ObjectActuator::PyGetForceLimitX(PyObject* self, 
546                                                                                           PyObject* args, 
547                                                                                           PyObject* kwds)
548 {
549         PyObject *retVal = PyList_New(3);
550
551         PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_drot[0]));
552         PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_dloc[0]));
553         PyList_SetItem(retVal, 2, BoolToPyArg(m_bitLocalFlag.Torque));
554         
555         return retVal;
556 }
557 /* 7. setForceLimitX                                                         */
558 PyObject* KX_ObjectActuator::PySetForceLimitX(PyObject* self, 
559                                                                                           PyObject* args, 
560                                                                                           PyObject* kwds)
561 {
562         float vecArg[2];
563         int bToggle = 0;
564         if(!PyArg_ParseTuple(args, "ffi", &vecArg[0], &vecArg[1], &bToggle)) {
565                 return NULL;
566         }
567         m_drot[0] = vecArg[0];
568         m_dloc[0] = vecArg[1];
569         m_bitLocalFlag.Torque = PyArgToBool(bToggle);
570         Py_Return;
571 }
572
573 /* 6. getForceLimitY                                                                */
574 PyObject* KX_ObjectActuator::PyGetForceLimitY(PyObject* self, 
575                                                                                           PyObject* args, 
576                                                                                           PyObject* kwds)
577 {
578         PyObject *retVal = PyList_New(3);
579
580         PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_drot[1]));
581         PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_dloc[1]));
582         PyList_SetItem(retVal, 2, BoolToPyArg(m_bitLocalFlag.DLoc));
583         
584         return retVal;
585 }
586 /* 7. setForceLimitY                                                                */
587 PyObject* KX_ObjectActuator::PySetForceLimitY(PyObject* self, 
588                                                                                           PyObject* args, 
589                                                                                           PyObject* kwds)
590 {
591         float vecArg[2];
592         int bToggle = 0;
593         if(!PyArg_ParseTuple(args, "ffi", &vecArg[0], &vecArg[1], &bToggle)) {
594                 return NULL;
595         }
596         m_drot[1] = vecArg[0];
597         m_dloc[1] = vecArg[1];
598         m_bitLocalFlag.DLoc = PyArgToBool(bToggle);
599         Py_Return;
600 }
601
602 /* 6. getForceLimitZ                                                                */
603 PyObject* KX_ObjectActuator::PyGetForceLimitZ(PyObject* self, 
604                                                                                           PyObject* args, 
605                                                                                           PyObject* kwds)
606 {
607         PyObject *retVal = PyList_New(3);
608
609         PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_drot[2]));
610         PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_dloc[2]));
611         PyList_SetItem(retVal, 2, BoolToPyArg(m_bitLocalFlag.DRot));
612         
613         return retVal;
614 }
615 /* 7. setForceLimitZ                                                                */
616 PyObject* KX_ObjectActuator::PySetForceLimitZ(PyObject* self, 
617                                                                                           PyObject* args, 
618                                                                                           PyObject* kwds)
619 {
620         float vecArg[2];
621         int bToggle = 0;
622         if(!PyArg_ParseTuple(args, "ffi", &vecArg[0], &vecArg[1], &bToggle)) {
623                 return NULL;
624         }
625         m_drot[2] = vecArg[0];
626         m_dloc[2] = vecArg[1];
627         m_bitLocalFlag.DRot = PyArgToBool(bToggle);
628         Py_Return;
629 }
630
631 /* 4. getPID                                                              */
632 PyObject* KX_ObjectActuator::PyGetPID(PyObject* self, 
633                                                                           PyObject* args, 
634                                                                           PyObject* kwds)
635 {
636         PyObject *retVal = PyList_New(3);
637
638         PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_torque[0]));
639         PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_torque[1]));
640         PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_torque[2]));
641         
642         return retVal;
643 }
644 /* 5. setPID                                                              */
645 PyObject* KX_ObjectActuator::PySetPID(PyObject* self, 
646                                                                           PyObject* args, 
647                                                                           PyObject* kwds)
648 {
649         float vecArg[3];
650         if (!PyArg_ParseTuple(args, "fff", &vecArg[0], &vecArg[1], &vecArg[2])) {
651                 return NULL;
652         }
653         m_torque.setValue(vecArg);
654         Py_Return;
655 }
656
657
658
659
660
661 /* eof */