patch from Mitchell Stokes, comments only - KX_PYATTRIBUTE_TODO for missing attributes
[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         PyObject_HEAD_INIT(NULL)
278         0,
279         "KX_ObjectActuator",
280         sizeof(PyObjectPlus_Proxy),
281         0,
282         py_base_dealloc,
283         0,
284         0,
285         0,
286         0,
287         py_base_repr,
288         0,0,0,0,0,0,
289         py_base_getattro,
290         py_base_setattro,
291         0,0,0,0,0,0,0,0,0,
292         Methods
293 };
294
295 PyParentObject KX_ObjectActuator::Parents[] = {
296         &KX_ObjectActuator::Type,
297         &SCA_IActuator::Type,
298         &SCA_ILogicBrick::Type,
299         &CValue::Type,
300         NULL
301 };
302
303 PyMethodDef KX_ObjectActuator::Methods[] = {
304         {"getForce", (PyCFunction) KX_ObjectActuator::sPyGetForce, METH_NOARGS},
305         {"setForce", (PyCFunction) KX_ObjectActuator::sPySetForce, METH_VARARGS},
306         {"getTorque", (PyCFunction) KX_ObjectActuator::sPyGetTorque, METH_NOARGS},
307         {"setTorque", (PyCFunction) KX_ObjectActuator::sPySetTorque, METH_VARARGS},
308         {"getDLoc", (PyCFunction) KX_ObjectActuator::sPyGetDLoc, METH_NOARGS},
309         {"setDLoc", (PyCFunction) KX_ObjectActuator::sPySetDLoc, METH_VARARGS},
310         {"getDRot", (PyCFunction) KX_ObjectActuator::sPyGetDRot, METH_NOARGS},
311         {"setDRot", (PyCFunction) KX_ObjectActuator::sPySetDRot, METH_VARARGS},
312         {"getLinearVelocity", (PyCFunction) KX_ObjectActuator::sPyGetLinearVelocity, METH_NOARGS},
313         {"setLinearVelocity", (PyCFunction) KX_ObjectActuator::sPySetLinearVelocity, METH_VARARGS},
314         {"getAngularVelocity", (PyCFunction) KX_ObjectActuator::sPyGetAngularVelocity, METH_NOARGS},
315         {"setAngularVelocity", (PyCFunction) KX_ObjectActuator::sPySetAngularVelocity, METH_VARARGS},
316         {"setDamping", (PyCFunction) KX_ObjectActuator::sPySetDamping, METH_VARARGS},
317         {"getDamping", (PyCFunction) KX_ObjectActuator::sPyGetDamping, METH_NOARGS},
318         {"setForceLimitX", (PyCFunction) KX_ObjectActuator::sPySetForceLimitX, METH_VARARGS},
319         {"getForceLimitX", (PyCFunction) KX_ObjectActuator::sPyGetForceLimitX, METH_NOARGS},
320         {"setForceLimitY", (PyCFunction) KX_ObjectActuator::sPySetForceLimitY, METH_VARARGS},
321         {"getForceLimitY", (PyCFunction) KX_ObjectActuator::sPyGetForceLimitY, METH_NOARGS},
322         {"setForceLimitZ", (PyCFunction) KX_ObjectActuator::sPySetForceLimitZ, METH_VARARGS},
323         {"getForceLimitZ", (PyCFunction) KX_ObjectActuator::sPyGetForceLimitZ, METH_NOARGS},
324         {"setPID", (PyCFunction) KX_ObjectActuator::sPyGetPID, METH_NOARGS},
325         {"getPID", (PyCFunction) KX_ObjectActuator::sPySetPID, METH_VARARGS},
326
327
328
329         {NULL,NULL} //Sentinel
330 };
331
332 PyAttributeDef KX_ObjectActuator::Attributes[] = {
333         //KX_PYATTRIBUTE_TODO("force"),
334         //KX_PYATTRIBUTE_TODO("torque"),
335         //KX_PYATTRIBUTE_TODO("dLoc"),
336         //KX_PYATTRIBUTE_TODO("dRot"),
337         //KX_PYATTRIBUTE_TODO("linV"),
338         //KX_PYATTRIBUTE_TODO("angV"),
339         //KX_PYATTRIBUTE_TODO("damping"),
340         //KX_PYATTRIBUTE_TODO("forceLimitX"),
341         //KX_PYATTRIBUTE_TODO("forceLimitY"),
342         //KX_PYATTRIBUTE_TODO("forceLimitZ"),
343         //KX_PYATTRIBUTE_TODO("pid"),
344         { NULL }        //Sentinel
345 };
346
347 PyObject* KX_ObjectActuator::py_getattro(PyObject *attr) {
348         py_getattro_up(SCA_IActuator);
349 };
350
351 PyObject* KX_ObjectActuator::py_getattro_dict() {
352         py_getattro_dict_up(SCA_IActuator);
353 }
354
355 /* 1. set ------------------------------------------------------------------ */
356 /* Removed! */
357
358 /* 2. getForce                                                               */
359 PyObject* KX_ObjectActuator::PyGetForce()
360 {
361         PyObject *retVal = PyList_New(4);
362
363         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_force[0]));
364         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_force[1]));
365         PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_force[2]));
366         PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.Force));
367         
368         return retVal;
369 }
370 /* 3. setForce                                                               */
371 PyObject* KX_ObjectActuator::PySetForce(PyObject* args)
372 {
373         float vecArg[3];
374         int bToggle = 0;
375         if (!PyArg_ParseTuple(args, "fffi:setForce", &vecArg[0], &vecArg[1], 
376                                                   &vecArg[2], &bToggle)) {
377                 return NULL;
378         }
379         m_force.setValue(vecArg);
380         m_bitLocalFlag.Force = PyArgToBool(bToggle);
381         UpdateFuzzyFlags();
382         Py_RETURN_NONE;
383 }
384
385 /* 4. getTorque                                                              */
386 PyObject* KX_ObjectActuator::PyGetTorque()
387 {
388         PyObject *retVal = PyList_New(4);
389
390         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_torque[0]));
391         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_torque[1]));
392         PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_torque[2]));
393         PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.Torque));
394         
395         return retVal;
396 }
397 /* 5. setTorque                                                              */
398 PyObject* KX_ObjectActuator::PySetTorque(PyObject* args)
399 {
400         float vecArg[3];
401         int bToggle = 0;
402         if (!PyArg_ParseTuple(args, "fffi:setTorque", &vecArg[0], &vecArg[1], 
403                                                   &vecArg[2], &bToggle)) {
404                 return NULL;
405         }
406         m_torque.setValue(vecArg);
407         m_bitLocalFlag.Torque = PyArgToBool(bToggle);
408         UpdateFuzzyFlags();
409         Py_RETURN_NONE;
410 }
411
412 /* 6. getDLoc                                                                */
413 PyObject* KX_ObjectActuator::PyGetDLoc()
414 {
415         PyObject *retVal = PyList_New(4);
416
417         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_dloc[0]));
418         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_dloc[1]));
419         PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_dloc[2]));
420         PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.DLoc));
421         
422         return retVal;
423 }
424 /* 7. setDLoc                                                                */
425 PyObject* KX_ObjectActuator::PySetDLoc(PyObject* args)
426 {
427         float vecArg[3];
428         int bToggle = 0;
429         if(!PyArg_ParseTuple(args, "fffi:setDLoc", &vecArg[0], &vecArg[1], 
430                                                  &vecArg[2], &bToggle)) {
431                 return NULL;
432         }
433         m_dloc.setValue(vecArg);
434         m_bitLocalFlag.DLoc = PyArgToBool(bToggle);
435         UpdateFuzzyFlags();
436         Py_RETURN_NONE;
437 }
438
439 /* 8. getDRot                                                                */
440 PyObject* KX_ObjectActuator::PyGetDRot()
441 {
442         PyObject *retVal = PyList_New(4);
443
444         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_drot[0]));
445         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_drot[1]));
446         PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_drot[2]));
447         PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.DRot));
448         
449         return retVal;
450 }
451 /* 9. setDRot                                                                */
452 PyObject* KX_ObjectActuator::PySetDRot(PyObject* args)
453 {
454         float vecArg[3];
455         int bToggle = 0;
456         if (!PyArg_ParseTuple(args, "fffi:setDRot", &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_NONE;
464 }
465
466 /* 10. getLinearVelocity                                                 */
467 PyObject* KX_ObjectActuator::PyGetLinearVelocity() {
468         PyObject *retVal = PyList_New(4);
469
470         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_linear_velocity[0]));
471         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_linear_velocity[1]));
472         PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_linear_velocity[2]));
473         PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.LinearVelocity));
474         
475         return retVal;
476 }
477
478 /* 11. setLinearVelocity                                                 */
479 PyObject* KX_ObjectActuator::PySetLinearVelocity(PyObject* args) {
480         float vecArg[3];
481         int bToggle = 0;
482         if (!PyArg_ParseTuple(args, "fffi:setLinearVelocity", &vecArg[0], &vecArg[1], 
483                                                   &vecArg[2], &bToggle)) {
484                 return NULL;
485         }
486         m_linear_velocity.setValue(vecArg);
487         m_bitLocalFlag.LinearVelocity = PyArgToBool(bToggle);
488         UpdateFuzzyFlags();
489         Py_RETURN_NONE;
490 }
491
492
493 /* 12. getAngularVelocity                                                */
494 PyObject* KX_ObjectActuator::PyGetAngularVelocity() {
495         PyObject *retVal = PyList_New(4);
496
497         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_angular_velocity[0]));
498         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_angular_velocity[1]));
499         PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_angular_velocity[2]));
500         PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.AngularVelocity));
501         
502         return retVal;
503 }
504 /* 13. setAngularVelocity                                                */
505 PyObject* KX_ObjectActuator::PySetAngularVelocity(PyObject* args) {
506         float vecArg[3];
507         int bToggle = 0;
508         if (!PyArg_ParseTuple(args, "fffi:setAngularVelocity", &vecArg[0], &vecArg[1], 
509                                                   &vecArg[2], &bToggle)) {
510                 return NULL;
511         }
512         m_angular_velocity.setValue(vecArg);
513         m_bitLocalFlag.AngularVelocity = PyArgToBool(bToggle);
514         UpdateFuzzyFlags();
515         Py_RETURN_NONE;
516 }
517
518 /* 13. setDamping                                                */
519 PyObject* KX_ObjectActuator::PySetDamping(PyObject* args) {
520         int damping = 0;
521         if (!PyArg_ParseTuple(args, "i:setDamping", &damping) || damping < 0 || damping > 1000) {
522                 return NULL;
523         }
524         m_damping = damping;
525         Py_RETURN_NONE;
526 }
527
528 /* 13. getVelocityDamping                                                */
529 PyObject* KX_ObjectActuator::PyGetDamping() {
530         return Py_BuildValue("i",m_damping);
531 }
532 /* 6. getForceLimitX                                                                */
533 PyObject* KX_ObjectActuator::PyGetForceLimitX()
534 {
535         PyObject *retVal = PyList_New(3);
536
537         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_drot[0]));
538         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_dloc[0]));
539         PyList_SET_ITEM(retVal, 2, BoolToPyArg(m_bitLocalFlag.Torque));
540         
541         return retVal;
542 }
543 /* 7. setForceLimitX                                                         */
544 PyObject* KX_ObjectActuator::PySetForceLimitX(PyObject* args)
545 {
546         float vecArg[2];
547         int bToggle = 0;
548         if(!PyArg_ParseTuple(args, "ffi:setForceLimitX", &vecArg[0], &vecArg[1], &bToggle)) {
549                 return NULL;
550         }
551         m_drot[0] = vecArg[0];
552         m_dloc[0] = vecArg[1];
553         m_bitLocalFlag.Torque = PyArgToBool(bToggle);
554         Py_RETURN_NONE;
555 }
556
557 /* 6. getForceLimitY                                                                */
558 PyObject* KX_ObjectActuator::PyGetForceLimitY()
559 {
560         PyObject *retVal = PyList_New(3);
561
562         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_drot[1]));
563         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_dloc[1]));
564         PyList_SET_ITEM(retVal, 2, BoolToPyArg(m_bitLocalFlag.DLoc));
565         
566         return retVal;
567 }
568 /* 7. setForceLimitY                                                                */
569 PyObject* KX_ObjectActuator::PySetForceLimitY(PyObject* args)
570 {
571         float vecArg[2];
572         int bToggle = 0;
573         if(!PyArg_ParseTuple(args, "ffi:setForceLimitY", &vecArg[0], &vecArg[1], &bToggle)) {
574                 return NULL;
575         }
576         m_drot[1] = vecArg[0];
577         m_dloc[1] = vecArg[1];
578         m_bitLocalFlag.DLoc = PyArgToBool(bToggle);
579         Py_RETURN_NONE;
580 }
581
582 /* 6. getForceLimitZ                                                                */
583 PyObject* KX_ObjectActuator::PyGetForceLimitZ()
584 {
585         PyObject *retVal = PyList_New(3);
586
587         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_drot[2]));
588         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_dloc[2]));
589         PyList_SET_ITEM(retVal, 2, BoolToPyArg(m_bitLocalFlag.DRot));
590         
591         return retVal;
592 }
593 /* 7. setForceLimitZ                                                                */
594 PyObject* KX_ObjectActuator::PySetForceLimitZ(PyObject* args)
595 {
596         float vecArg[2];
597         int bToggle = 0;
598         if(!PyArg_ParseTuple(args, "ffi:setForceLimitZ", &vecArg[0], &vecArg[1], &bToggle)) {
599                 return NULL;
600         }
601         m_drot[2] = vecArg[0];
602         m_dloc[2] = vecArg[1];
603         m_bitLocalFlag.DRot = PyArgToBool(bToggle);
604         Py_RETURN_NONE;
605 }
606
607 /* 4. getPID                                                              */
608 PyObject* KX_ObjectActuator::PyGetPID()
609 {
610         PyObject *retVal = PyList_New(3);
611
612         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_torque[0]));
613         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_torque[1]));
614         PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_torque[2]));
615         
616         return retVal;
617 }
618 /* 5. setPID                                                              */
619 PyObject* KX_ObjectActuator::PySetPID(PyObject* args)
620 {
621         float vecArg[3];
622         if (!PyArg_ParseTuple(args, "fff:setPID", &vecArg[0], &vecArg[1], &vecArg[2])) {
623                 return NULL;
624         }
625         m_torque.setValue(vecArg);
626         Py_RETURN_NONE;
627 }
628
629
630
631
632
633 /* eof */