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