BGE Python API
[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_NOARGS},
308         {"setForce", (PyCFunction) KX_ObjectActuator::sPySetForce, METH_VARARGS},
309         {"getTorque", (PyCFunction) KX_ObjectActuator::sPyGetTorque, METH_NOARGS},
310         {"setTorque", (PyCFunction) KX_ObjectActuator::sPySetTorque, METH_VARARGS},
311         {"getDLoc", (PyCFunction) KX_ObjectActuator::sPyGetDLoc, METH_NOARGS},
312         {"setDLoc", (PyCFunction) KX_ObjectActuator::sPySetDLoc, METH_VARARGS},
313         {"getDRot", (PyCFunction) KX_ObjectActuator::sPyGetDRot, METH_NOARGS},
314         {"setDRot", (PyCFunction) KX_ObjectActuator::sPySetDRot, METH_VARARGS},
315         {"getLinearVelocity", (PyCFunction) KX_ObjectActuator::sPyGetLinearVelocity, METH_NOARGS},
316         {"setLinearVelocity", (PyCFunction) KX_ObjectActuator::sPySetLinearVelocity, METH_VARARGS},
317         {"getAngularVelocity", (PyCFunction) KX_ObjectActuator::sPyGetAngularVelocity, METH_NOARGS},
318         {"setAngularVelocity", (PyCFunction) KX_ObjectActuator::sPySetAngularVelocity, METH_VARARGS},
319         {"setDamping", (PyCFunction) KX_ObjectActuator::sPySetDamping, METH_VARARGS},
320         {"getDamping", (PyCFunction) KX_ObjectActuator::sPyGetDamping, METH_NOARGS},
321         {"setForceLimitX", (PyCFunction) KX_ObjectActuator::sPySetForceLimitX, METH_VARARGS},
322         {"getForceLimitX", (PyCFunction) KX_ObjectActuator::sPyGetForceLimitX, METH_NOARGS},
323         {"setForceLimitY", (PyCFunction) KX_ObjectActuator::sPySetForceLimitY, METH_VARARGS},
324         {"getForceLimitY", (PyCFunction) KX_ObjectActuator::sPyGetForceLimitY, METH_NOARGS},
325         {"setForceLimitZ", (PyCFunction) KX_ObjectActuator::sPySetForceLimitZ, METH_VARARGS},
326         {"getForceLimitZ", (PyCFunction) KX_ObjectActuator::sPyGetForceLimitZ, METH_NOARGS},
327         {"setPID", (PyCFunction) KX_ObjectActuator::sPyGetPID, METH_NOARGS},
328         {"getPID", (PyCFunction) KX_ObjectActuator::sPySetPID, METH_VARARGS},
329
330
331
332         {NULL,NULL} //Sentinel
333 };
334
335 PyObject* KX_ObjectActuator::_getattr(const char *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 {
345         PyObject *retVal = PyList_New(4);
346
347         PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_force[0]));
348         PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_force[1]));
349         PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_force[2]));
350         PyList_SetItem(retVal, 3, BoolToPyArg(m_bitLocalFlag.Force));
351         
352         return retVal;
353 }
354 /* 3. setForce                                                               */
355 PyObject* KX_ObjectActuator::PySetForce(PyObject* self, 
356                                                                                 PyObject* args, 
357                                                                                 PyObject* kwds)
358 {
359         float vecArg[3];
360         int bToggle = 0;
361         if (!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1], 
362                                                   &vecArg[2], &bToggle)) {
363                 return NULL;
364         }
365         m_force.setValue(vecArg);
366         m_bitLocalFlag.Force = PyArgToBool(bToggle);
367         UpdateFuzzyFlags();
368         Py_Return;
369 }
370
371 /* 4. getTorque                                                              */
372 PyObject* KX_ObjectActuator::PyGetTorque(PyObject* self)
373 {
374         PyObject *retVal = PyList_New(4);
375
376         PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_torque[0]));
377         PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_torque[1]));
378         PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_torque[2]));
379         PyList_SetItem(retVal, 3, BoolToPyArg(m_bitLocalFlag.Torque));
380         
381         return retVal;
382 }
383 /* 5. setTorque                                                              */
384 PyObject* KX_ObjectActuator::PySetTorque(PyObject* self, 
385                                                                                  PyObject* args, 
386                                                                                  PyObject* kwds)
387 {
388         float vecArg[3];
389         int bToggle = 0;
390         if (!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1], 
391                                                   &vecArg[2], &bToggle)) {
392                 return NULL;
393         }
394         m_torque.setValue(vecArg);
395         m_bitLocalFlag.Torque = PyArgToBool(bToggle);
396         UpdateFuzzyFlags();
397         Py_Return;
398 }
399
400 /* 6. getDLoc                                                                */
401 PyObject* KX_ObjectActuator::PyGetDLoc(PyObject* self)
402 {
403         PyObject *retVal = PyList_New(4);
404
405         PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_dloc[0]));
406         PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_dloc[1]));
407         PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_dloc[2]));
408         PyList_SetItem(retVal, 3, BoolToPyArg(m_bitLocalFlag.DLoc));
409         
410         return retVal;
411 }
412 /* 7. setDLoc                                                                */
413 PyObject* KX_ObjectActuator::PySetDLoc(PyObject* self, 
414                                                                            PyObject* args, 
415                                                                            PyObject* kwds)
416 {
417         float vecArg[3];
418         int bToggle = 0;
419         if(!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1], 
420                                                  &vecArg[2], &bToggle)) {
421                 return NULL;
422         }
423         m_dloc.setValue(vecArg);
424         m_bitLocalFlag.DLoc = PyArgToBool(bToggle);
425         UpdateFuzzyFlags();
426         Py_Return;
427 }
428
429 /* 8. getDRot                                                                */
430 PyObject* KX_ObjectActuator::PyGetDRot(PyObject* self)
431 {
432         PyObject *retVal = PyList_New(4);
433
434         PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_drot[0]));
435         PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_drot[1]));
436         PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_drot[2]));
437         PyList_SetItem(retVal, 3, BoolToPyArg(m_bitLocalFlag.DRot));
438         
439         return retVal;
440 }
441 /* 9. setDRot                                                                */
442 PyObject* KX_ObjectActuator::PySetDRot(PyObject* self, 
443                                                                            PyObject* args, 
444                                                                            PyObject* kwds)
445 {
446         float vecArg[3];
447         int bToggle = 0;
448         if (!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1], 
449                                                   &vecArg[2], &bToggle)) {
450                 return NULL;
451         }
452         m_drot.setValue(vecArg);
453         m_bitLocalFlag.DRot = PyArgToBool(bToggle);
454         UpdateFuzzyFlags();
455         Py_Return;
456 }
457
458 /* 10. getLinearVelocity                                                 */
459 PyObject* KX_ObjectActuator::PyGetLinearVelocity(PyObject* self) {
460         PyObject *retVal = PyList_New(4);
461
462         PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_linear_velocity[0]));
463         PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_linear_velocity[1]));
464         PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_linear_velocity[2]));
465         PyList_SetItem(retVal, 3, BoolToPyArg(m_bitLocalFlag.LinearVelocity));
466         
467         return retVal;
468 }
469
470 /* 11. setLinearVelocity                                                 */
471 PyObject* KX_ObjectActuator::PySetLinearVelocity(PyObject* self, 
472                                                                                                  PyObject* args, 
473                                                                                                  PyObject* kwds) {
474         float vecArg[3];
475         int bToggle = 0;
476         if (!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1], 
477                                                   &vecArg[2], &bToggle)) {
478                 return NULL;
479         }
480         m_linear_velocity.setValue(vecArg);
481         m_bitLocalFlag.LinearVelocity = PyArgToBool(bToggle);
482         UpdateFuzzyFlags();
483         Py_Return;
484 }
485
486
487 /* 12. getAngularVelocity                                                */
488 PyObject* KX_ObjectActuator::PyGetAngularVelocity(PyObject* self) {
489         PyObject *retVal = PyList_New(4);
490
491         PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_angular_velocity[0]));
492         PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_angular_velocity[1]));
493         PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_angular_velocity[2]));
494         PyList_SetItem(retVal, 3, BoolToPyArg(m_bitLocalFlag.AngularVelocity));
495         
496         return retVal;
497 }
498 /* 13. setAngularVelocity                                                */
499 PyObject* KX_ObjectActuator::PySetAngularVelocity(PyObject* self, 
500                                                                                                   PyObject* args, 
501                                                                                                   PyObject* kwds) {
502         float vecArg[3];
503         int bToggle = 0;
504         if (!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1], 
505                                                   &vecArg[2], &bToggle)) {
506                 return NULL;
507         }
508         m_angular_velocity.setValue(vecArg);
509         m_bitLocalFlag.AngularVelocity = PyArgToBool(bToggle);
510         UpdateFuzzyFlags();
511         Py_Return;
512 }
513
514 /* 13. setDamping                                                */
515 PyObject* KX_ObjectActuator::PySetDamping(PyObject* self, 
516                                                                                   PyObject* args, 
517                                                                                   PyObject* kwds) {
518         int damping = 0;
519         if (!PyArg_ParseTuple(args, "i", &damping) || damping < 0 || damping > 1000) {
520                 return NULL;
521         }
522         m_damping = damping;
523         Py_Return;
524 }
525
526 /* 13. getVelocityDamping                                                */
527 PyObject* KX_ObjectActuator::PyGetDamping(PyObject* self) {
528         return Py_BuildValue("i",m_damping);
529 }
530 /* 6. getForceLimitX                                                                */
531 PyObject* KX_ObjectActuator::PyGetForceLimitX(PyObject* self)
532 {
533         PyObject *retVal = PyList_New(3);
534
535         PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_drot[0]));
536         PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_dloc[0]));
537         PyList_SetItem(retVal, 2, BoolToPyArg(m_bitLocalFlag.Torque));
538         
539         return retVal;
540 }
541 /* 7. setForceLimitX                                                         */
542 PyObject* KX_ObjectActuator::PySetForceLimitX(PyObject* self, 
543                                                                                           PyObject* args, 
544                                                                                           PyObject* kwds)
545 {
546         float vecArg[2];
547         int bToggle = 0;
548         if(!PyArg_ParseTuple(args, "ffi", &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;
555 }
556
557 /* 6. getForceLimitY                                                                */
558 PyObject* KX_ObjectActuator::PyGetForceLimitY(PyObject* self)
559 {
560         PyObject *retVal = PyList_New(3);
561
562         PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_drot[1]));
563         PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_dloc[1]));
564         PyList_SetItem(retVal, 2, BoolToPyArg(m_bitLocalFlag.DLoc));
565         
566         return retVal;
567 }
568 /* 7. setForceLimitY                                                                */
569 PyObject* KX_ObjectActuator::PySetForceLimitY(PyObject* self, 
570                                                                                           PyObject* args, 
571                                                                                           PyObject* kwds)
572 {
573         float vecArg[2];
574         int bToggle = 0;
575         if(!PyArg_ParseTuple(args, "ffi", &vecArg[0], &vecArg[1], &bToggle)) {
576                 return NULL;
577         }
578         m_drot[1] = vecArg[0];
579         m_dloc[1] = vecArg[1];
580         m_bitLocalFlag.DLoc = PyArgToBool(bToggle);
581         Py_Return;
582 }
583
584 /* 6. getForceLimitZ                                                                */
585 PyObject* KX_ObjectActuator::PyGetForceLimitZ(PyObject* self)
586 {
587         PyObject *retVal = PyList_New(3);
588
589         PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_drot[2]));
590         PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_dloc[2]));
591         PyList_SetItem(retVal, 2, BoolToPyArg(m_bitLocalFlag.DRot));
592         
593         return retVal;
594 }
595 /* 7. setForceLimitZ                                                                */
596 PyObject* KX_ObjectActuator::PySetForceLimitZ(PyObject* self, 
597                                                                                           PyObject* args, 
598                                                                                           PyObject* kwds)
599 {
600         float vecArg[2];
601         int bToggle = 0;
602         if(!PyArg_ParseTuple(args, "ffi", &vecArg[0], &vecArg[1], &bToggle)) {
603                 return NULL;
604         }
605         m_drot[2] = vecArg[0];
606         m_dloc[2] = vecArg[1];
607         m_bitLocalFlag.DRot = PyArgToBool(bToggle);
608         Py_Return;
609 }
610
611 /* 4. getPID                                                              */
612 PyObject* KX_ObjectActuator::PyGetPID(PyObject* self)
613 {
614         PyObject *retVal = PyList_New(3);
615
616         PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_torque[0]));
617         PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_torque[1]));
618         PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_torque[2]));
619         
620         return retVal;
621 }
622 /* 5. setPID                                                              */
623 PyObject* KX_ObjectActuator::PySetPID(PyObject* self, 
624                                                                           PyObject* args, 
625                                                                           PyObject* kwds)
626 {
627         float vecArg[3];
628         if (!PyArg_ParseTuple(args, "fff", &vecArg[0], &vecArg[1], &vecArg[2])) {
629                 return NULL;
630         }
631         m_torque.setValue(vecArg);
632         Py_Return;
633 }
634
635
636
637
638
639 /* eof */