svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r22099:22130
[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 ) : 
58         SCA_IActuator(gameobj),
59         m_force(force),
60         m_torque(torque),
61         m_dloc(dloc),
62         m_drot(drot),
63         m_linear_velocity(linV),
64         m_angular_velocity(angV),
65         m_linear_length2(0.0),
66         m_current_linear_factor(0.0),
67         m_current_angular_factor(0.0),
68         m_damping(damping),
69         m_previous_error(0.0,0.0,0.0),
70         m_error_accumulator(0.0,0.0,0.0),
71         m_bitLocalFlag (flag),
72         m_reference(refobj),
73         m_active_combined_velocity (false),
74         m_linear_damping_active(false),
75         m_angular_damping_active(false)
76 {
77         if (m_bitLocalFlag.ServoControl)
78         {
79                 // in servo motion, the force is local if the target velocity is local
80                 m_bitLocalFlag.Force = m_bitLocalFlag.LinearVelocity;
81
82                 m_pid = m_torque;
83         }
84         if (m_reference)
85                 m_reference->RegisterActuator(this);
86         UpdateFuzzyFlags();
87 }
88
89 KX_ObjectActuator::~KX_ObjectActuator()
90 {
91         if (m_reference)
92                 m_reference->UnregisterActuator(this);
93 }
94
95 bool KX_ObjectActuator::Update()
96 {
97         
98         bool bNegativeEvent = IsNegativeEvent();
99         RemoveAllEvents();
100                 
101         KX_GameObject *parent = static_cast<KX_GameObject *>(GetParent()); 
102
103         if (bNegativeEvent) {
104                 // If we previously set the linear velocity we now have to inform
105                 // the physics controller that we no longer wish to apply it and that
106                 // it should reconcile the externally set velocity with it's 
107                 // own velocity.
108                 if (m_active_combined_velocity) {
109                         if (parent)
110                                 parent->ResolveCombinedVelocities(
111                                                 m_linear_velocity,
112                                                 m_angular_velocity,
113                                                 (m_bitLocalFlag.LinearVelocity) != 0,
114                                                 (m_bitLocalFlag.AngularVelocity) != 0
115                                         );
116                         m_active_combined_velocity = false;
117                 } 
118                 m_linear_damping_active = false;
119                 m_angular_damping_active = false;
120                 m_error_accumulator.setValue(0.0,0.0,0.0);
121                 m_previous_error.setValue(0.0,0.0,0.0);
122                 return false; 
123
124         } else if (parent)
125         {
126                 if (m_bitLocalFlag.ServoControl) 
127                 {
128                         // In this mode, we try to reach a target speed using force
129                         // As we don't know the friction, we must implement a generic 
130                         // servo control to achieve the speed in a configurable
131                         // v = current velocity
132                         // V = target velocity
133                         // e = V-v = speed error
134                         // dt = time interval since previous update
135                         // I = sum(e(t)*dt)
136                         // dv = e(t) - e(t-1)
137                         // KP, KD, KI : coefficient
138                         // F = KP*e+KI*I+KD*dv
139                         MT_Scalar mass = parent->GetMass();
140                         if (mass < MT_EPSILON)
141                                 return false;
142                         MT_Vector3 v = parent->GetLinearVelocity(m_bitLocalFlag.LinearVelocity);
143                         if (m_reference)
144                         {
145                                 const MT_Point3& mypos = parent->NodeGetWorldPosition();
146                                 const MT_Point3& refpos = m_reference->NodeGetWorldPosition();
147                                 MT_Point3 relpos;
148                                 relpos = (mypos-refpos);
149                                 MT_Vector3 vel= m_reference->GetVelocity(relpos);
150                                 if (m_bitLocalFlag.LinearVelocity)
151                                         // must convert in local space
152                                         vel = parent->NodeGetWorldOrientation().transposed()*vel;
153                                 v -= vel;
154                         }
155                         MT_Vector3 e = m_linear_velocity - v;
156                         MT_Vector3 dv = e - m_previous_error;
157                         MT_Vector3 I = m_error_accumulator + e;
158
159                         m_force = m_pid.x()*e+m_pid.y()*I+m_pid.z()*dv;
160                         // to automatically adapt the PID coefficient to mass;
161                         m_force *= mass;
162                         if (m_bitLocalFlag.Torque) 
163                         {
164                                 if (m_force[0] > m_dloc[0])
165                                 {
166                                         m_force[0] = m_dloc[0];
167                                         I[0] = m_error_accumulator[0];
168                                 } else if (m_force[0] < m_drot[0])
169                                 {
170                                         m_force[0] = m_drot[0];
171                                         I[0] = m_error_accumulator[0];
172                                 }
173                         }
174                         if (m_bitLocalFlag.DLoc) 
175                         {
176                                 if (m_force[1] > m_dloc[1])
177                                 {
178                                         m_force[1] = m_dloc[1];
179                                         I[1] = m_error_accumulator[1];
180                                 } else if (m_force[1] < m_drot[1])
181                                 {
182                                         m_force[1] = m_drot[1];
183                                         I[1] = m_error_accumulator[1];
184                                 }
185                         }
186                         if (m_bitLocalFlag.DRot) 
187                         {
188                                 if (m_force[2] > m_dloc[2])
189                                 {
190                                         m_force[2] = m_dloc[2];
191                                         I[2] = m_error_accumulator[2];
192                                 } else if (m_force[2] < m_drot[2])
193                                 {
194                                         m_force[2] = m_drot[2];
195                                         I[2] = m_error_accumulator[2];
196                                 }
197                         }
198                         m_previous_error = e;
199                         m_error_accumulator = I;
200                         parent->ApplyForce(m_force,(m_bitLocalFlag.LinearVelocity) != 0);
201                 } else
202                 {
203                         if (!m_bitLocalFlag.ZeroForce)
204                         {
205                                 parent->ApplyForce(m_force,(m_bitLocalFlag.Force) != 0);
206                         }
207                         if (!m_bitLocalFlag.ZeroTorque)
208                         {
209                                 parent->ApplyTorque(m_torque,(m_bitLocalFlag.Torque) != 0);
210                         }
211                         if (!m_bitLocalFlag.ZeroDLoc)
212                         {
213                                 parent->ApplyMovement(m_dloc,(m_bitLocalFlag.DLoc) != 0);
214                         }
215                         if (!m_bitLocalFlag.ZeroDRot)
216                         {
217                                 parent->ApplyRotation(m_drot,(m_bitLocalFlag.DRot) != 0);
218                         }
219                         if (!m_bitLocalFlag.ZeroLinearVelocity)
220                         {
221                                 if (m_bitLocalFlag.AddOrSetLinV) {
222                                         parent->addLinearVelocity(m_linear_velocity,(m_bitLocalFlag.LinearVelocity) != 0);
223                                 } else {
224                                         m_active_combined_velocity = true;
225                                         if (m_damping > 0) {
226                                                 MT_Vector3 linV;
227                                                 if (!m_linear_damping_active) {
228                                                         // delta and the start speed (depends on the existing speed in that direction)
229                                                         linV = parent->GetLinearVelocity(m_bitLocalFlag.LinearVelocity);
230                                                         // keep only the projection along the desired direction
231                                                         m_current_linear_factor = linV.dot(m_linear_velocity)/m_linear_length2;
232                                                         m_linear_damping_active = true;
233                                                 }
234                                                 if (m_current_linear_factor < 1.0)
235                                                         m_current_linear_factor += 1.0/m_damping;
236                                                 if (m_current_linear_factor > 1.0)
237                                                         m_current_linear_factor = 1.0;
238                                                 linV = m_current_linear_factor * m_linear_velocity;
239                                                 parent->setLinearVelocity(linV,(m_bitLocalFlag.LinearVelocity) != 0);
240                                         } else {
241                                                 parent->setLinearVelocity(m_linear_velocity,(m_bitLocalFlag.LinearVelocity) != 0);
242                                         }
243                                 }
244                         }
245                         if (!m_bitLocalFlag.ZeroAngularVelocity)
246                         {
247                                 m_active_combined_velocity = true;
248                                 if (m_damping > 0) {
249                                         MT_Vector3 angV;
250                                         if (!m_angular_damping_active) {
251                                                 // delta and the start speed (depends on the existing speed in that direction)
252                                                 angV = parent->GetAngularVelocity(m_bitLocalFlag.AngularVelocity);
253                                                 // keep only the projection along the desired direction
254                                                 m_current_angular_factor = angV.dot(m_angular_velocity)/m_angular_length2;
255                                                 m_angular_damping_active = true;
256                                         }
257                                         if (m_current_angular_factor < 1.0)
258                                                 m_current_angular_factor += 1.0/m_damping;
259                                         if (m_current_angular_factor > 1.0)
260                                                 m_current_angular_factor = 1.0;
261                                         angV = m_current_angular_factor * m_angular_velocity;
262                                         parent->setAngularVelocity(angV,(m_bitLocalFlag.AngularVelocity) != 0);
263                                 } else {
264                                         parent->setAngularVelocity(m_angular_velocity,(m_bitLocalFlag.AngularVelocity) != 0);
265                                 }
266                         }
267                 }
268                 
269         }
270         return true;
271 }
272
273
274
275 CValue* KX_ObjectActuator::GetReplica()
276 {
277         KX_ObjectActuator* replica = new KX_ObjectActuator(*this);//m_float,GetName());
278         replica->ProcessReplica();
279
280         return replica;
281 }
282
283 void KX_ObjectActuator::ProcessReplica()
284 {
285         SCA_IActuator::ProcessReplica();
286         if (m_reference)
287                 m_reference->RegisterActuator(this);
288 }
289
290 bool KX_ObjectActuator::UnlinkObject(SCA_IObject* clientobj)
291 {
292         if (clientobj == (SCA_IObject*)m_reference)
293         {
294                 // this object is being deleted, we cannot continue to use it as reference.
295                 m_reference = NULL;
296                 return true;
297         }
298         return false;
299 }
300
301 void KX_ObjectActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map)
302 {
303         void **h_obj = (*obj_map)[m_reference];
304         if (h_obj) {
305                 if (m_reference)
306                         m_reference->UnregisterActuator(this);
307                 m_reference = (KX_GameObject*)(*h_obj);
308                 m_reference->RegisterActuator(this);
309         }
310 }
311
312 /* some 'standard' utilities... */
313 bool KX_ObjectActuator::isValid(KX_ObjectActuator::KX_OBJECT_ACT_VEC_TYPE type)
314 {
315         bool res = false;
316         res = (type > KX_OBJECT_ACT_NODEF) && (type < KX_OBJECT_ACT_MAX);
317         return res;
318 }
319
320
321
322 /* ------------------------------------------------------------------------- */
323 /* Python functions                                                          */
324 /* ------------------------------------------------------------------------- */
325
326 /* Integration hooks ------------------------------------------------------- */
327 PyTypeObject KX_ObjectActuator::Type = {
328 #if (PY_VERSION_HEX >= 0x02060000)
329         PyVarObject_HEAD_INIT(NULL, 0)
330 #else
331         /* python 2.5 and below */
332         PyObject_HEAD_INIT( NULL )  /* required py macro */
333         0,                          /* ob_size */
334 #endif
335         "KX_ObjectActuator",
336         sizeof(PyObjectPlus_Proxy),
337         0,
338         py_base_dealloc,
339         0,
340         0,
341         0,
342         0,
343         py_base_repr,
344         0,0,0,0,0,0,0,0,0,
345         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
346         0,0,0,0,0,0,0,
347         Methods,
348         0,
349         0,
350         &SCA_IActuator::Type,
351         0,0,0,0,0,0,
352         py_base_new
353 };
354
355 PyMethodDef KX_ObjectActuator::Methods[] = {
356         // Deprecated ----->
357         {"getForce", (PyCFunction) KX_ObjectActuator::sPyGetForce, METH_NOARGS},
358         {"setForce", (PyCFunction) KX_ObjectActuator::sPySetForce, METH_VARARGS},
359         {"getTorque", (PyCFunction) KX_ObjectActuator::sPyGetTorque, METH_NOARGS},
360         {"setTorque", (PyCFunction) KX_ObjectActuator::sPySetTorque, METH_VARARGS},
361         {"getDLoc", (PyCFunction) KX_ObjectActuator::sPyGetDLoc, METH_NOARGS},
362         {"setDLoc", (PyCFunction) KX_ObjectActuator::sPySetDLoc, METH_VARARGS},
363         {"getDRot", (PyCFunction) KX_ObjectActuator::sPyGetDRot, METH_NOARGS},
364         {"setDRot", (PyCFunction) KX_ObjectActuator::sPySetDRot, METH_VARARGS},
365         {"getLinearVelocity", (PyCFunction) KX_ObjectActuator::sPyGetLinearVelocity, METH_NOARGS},
366         {"setLinearVelocity", (PyCFunction) KX_ObjectActuator::sPySetLinearVelocity, METH_VARARGS},
367         {"getAngularVelocity", (PyCFunction) KX_ObjectActuator::sPyGetAngularVelocity, METH_NOARGS},
368         {"setAngularVelocity", (PyCFunction) KX_ObjectActuator::sPySetAngularVelocity, METH_VARARGS},
369         {"setDamping", (PyCFunction) KX_ObjectActuator::sPySetDamping, METH_VARARGS},
370         {"getDamping", (PyCFunction) KX_ObjectActuator::sPyGetDamping, METH_NOARGS},
371         {"setForceLimitX", (PyCFunction) KX_ObjectActuator::sPySetForceLimitX, METH_VARARGS},
372         {"getForceLimitX", (PyCFunction) KX_ObjectActuator::sPyGetForceLimitX, METH_NOARGS},
373         {"setForceLimitY", (PyCFunction) KX_ObjectActuator::sPySetForceLimitY, METH_VARARGS},
374         {"getForceLimitY", (PyCFunction) KX_ObjectActuator::sPyGetForceLimitY, METH_NOARGS},
375         {"setForceLimitZ", (PyCFunction) KX_ObjectActuator::sPySetForceLimitZ, METH_VARARGS},
376         {"getForceLimitZ", (PyCFunction) KX_ObjectActuator::sPyGetForceLimitZ, METH_NOARGS},
377         {"setPID", (PyCFunction) KX_ObjectActuator::sPyGetPID, METH_NOARGS},
378         {"getPID", (PyCFunction) KX_ObjectActuator::sPySetPID, METH_VARARGS},
379
380         // <----- Deprecated
381
382         {NULL,NULL} //Sentinel
383 };
384
385 PyAttributeDef KX_ObjectActuator::Attributes[] = {
386         KX_PYATTRIBUTE_VECTOR_RW_CHECK("force", -1000, 1000, false, KX_ObjectActuator, m_force, PyUpdateFuzzyFlags),
387         KX_PYATTRIBUTE_BOOL_RW("useLocalForce", KX_ObjectActuator, m_bitLocalFlag.Force),
388         KX_PYATTRIBUTE_VECTOR_RW_CHECK("torque", -1000, 1000, false, KX_ObjectActuator, m_torque, PyUpdateFuzzyFlags),
389         KX_PYATTRIBUTE_BOOL_RW("useLocalTorque", KX_ObjectActuator, m_bitLocalFlag.Torque),
390         KX_PYATTRIBUTE_VECTOR_RW_CHECK("dLoc", -1000, 1000, false, KX_ObjectActuator, m_dloc, PyUpdateFuzzyFlags),
391         KX_PYATTRIBUTE_BOOL_RW("useLocalDLoc", KX_ObjectActuator, m_bitLocalFlag.DLoc),
392         KX_PYATTRIBUTE_VECTOR_RW_CHECK("dRot", -1000, 1000, false, KX_ObjectActuator, m_drot, PyUpdateFuzzyFlags),
393         KX_PYATTRIBUTE_BOOL_RW("useLocalDRot", KX_ObjectActuator, m_bitLocalFlag.DRot),
394 #ifdef USE_MATHUTILS
395         KX_PYATTRIBUTE_RW_FUNCTION("linV", KX_ObjectActuator, pyattr_get_linV, pyattr_set_linV),
396         KX_PYATTRIBUTE_RW_FUNCTION("angV", KX_ObjectActuator, pyattr_get_angV, pyattr_set_angV),
397 #else
398         KX_PYATTRIBUTE_VECTOR_RW_CHECK("linV", -1000, 1000, false, KX_ObjectActuator, m_linear_velocity, PyUpdateFuzzyFlags),
399         KX_PYATTRIBUTE_VECTOR_RW_CHECK("angV", -1000, 1000, false, KX_ObjectActuator, m_angular_velocity, PyUpdateFuzzyFlags),
400 #endif
401         KX_PYATTRIBUTE_BOOL_RW("useLocalLinV", KX_ObjectActuator, m_bitLocalFlag.LinearVelocity),
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 /* Attribute get/set functions */
413
414 #ifdef USE_MATHUTILS
415
416 /* These require an SGNode */
417 #define MATHUTILS_VEC_CB_LINV 1
418 #define MATHUTILS_VEC_CB_ANGV 2
419
420 static int mathutils_kxobactu_vector_cb_index= -1; /* index for our callbacks */
421
422 static int mathutils_obactu_generic_check(PyObject *self_v)
423 {
424         KX_ObjectActuator* self= static_cast<KX_ObjectActuator*>BGE_PROXY_REF(self_v);
425         if(self==NULL)
426                 return 0;
427
428         return 1;
429 }
430
431 static int mathutils_obactu_vector_get(PyObject *self_v, int subtype, float *vec_from)
432 {
433         KX_ObjectActuator* self= static_cast<KX_ObjectActuator*>BGE_PROXY_REF(self_v);
434         if(self==NULL)
435                 return 0;
436
437         switch(subtype) {
438                 case MATHUTILS_VEC_CB_LINV:
439                         self->m_linear_velocity.getValue(vec_from);
440                         break;
441                 case MATHUTILS_VEC_CB_ANGV:
442                         self->m_angular_velocity.getValue(vec_from);
443                         break;
444         }
445
446         return 1;
447 }
448
449 static int mathutils_obactu_vector_set(PyObject *self_v, int subtype, float *vec_to)
450 {
451         KX_ObjectActuator* self= static_cast<KX_ObjectActuator*>BGE_PROXY_REF(self_v);
452         if(self==NULL)
453                 return 0;
454
455         switch(subtype) {
456                 case MATHUTILS_VEC_CB_LINV:
457                         self->m_linear_velocity.setValue(vec_to);
458                         break;
459                 case MATHUTILS_VEC_CB_ANGV:
460                         self->m_angular_velocity.setValue(vec_to);
461                         break;
462         }
463
464         return 1;
465 }
466
467 static int mathutils_obactu_vector_get_index(PyObject *self_v, int subtype, float *vec_from, int index)
468 {
469         float f[4];
470         /* lazy, avoid repeteing the case statement */
471         if(!mathutils_obactu_vector_get(self_v, subtype, f))
472                 return 0;
473
474         vec_from[index]= f[index];
475         return 1;
476 }
477
478 static int mathutils_obactu_vector_set_index(PyObject *self_v, int subtype, float *vec_to, int index)
479 {
480         float f= vec_to[index];
481
482         /* lazy, avoid repeteing the case statement */
483         if(!mathutils_obactu_vector_get(self_v, subtype, vec_to))
484                 return 0;
485
486         vec_to[index]= f;
487         mathutils_obactu_vector_set(self_v, subtype, vec_to);
488
489         return 1;
490 }
491
492 Mathutils_Callback mathutils_obactu_vector_cb = {
493         mathutils_obactu_generic_check,
494         mathutils_obactu_vector_get,
495         mathutils_obactu_vector_set,
496         mathutils_obactu_vector_get_index,
497         mathutils_obactu_vector_set_index
498 };
499
500 PyObject* KX_ObjectActuator::pyattr_get_linV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
501 {
502         return newVectorObject_cb((PyObject *)self_v, 3, mathutils_kxobactu_vector_cb_index, MATHUTILS_VEC_CB_LINV);
503 }
504
505 int KX_ObjectActuator::pyattr_set_linV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
506 {
507         KX_ObjectActuator* self= static_cast<KX_ObjectActuator*>(self_v);
508         if (!PyVecTo(value, self->m_linear_velocity))
509                 return PY_SET_ATTR_FAIL;
510
511         return PY_SET_ATTR_SUCCESS;
512 }
513
514 PyObject* KX_ObjectActuator::pyattr_get_angV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
515 {
516         return newVectorObject_cb((PyObject *)self_v, 3, mathutils_kxobactu_vector_cb_index, MATHUTILS_VEC_CB_ANGV);
517 }
518
519 int KX_ObjectActuator::pyattr_set_angV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
520 {
521         KX_ObjectActuator* self= static_cast<KX_ObjectActuator*>(self_v);
522         if (!PyVecTo(value, self->m_angular_velocity))
523                 return PY_SET_ATTR_FAIL;
524
525         return PY_SET_ATTR_SUCCESS;
526 }
527
528
529 void KX_ObjectActuator_Mathutils_Callback_Init(void)
530 {
531         // register mathutils callbacks, ok to run more then once.
532         mathutils_kxobactu_vector_cb_index= Mathutils_RegisterCallback(&mathutils_obactu_vector_cb);
533 }
534
535 #endif // USE_MATHUTILS
536
537 PyObject* KX_ObjectActuator::pyattr_get_forceLimitX(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
538 {
539         KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v);
540         PyObject *retVal = PyList_New(3);
541
542         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(self->m_drot[0]));
543         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(self->m_dloc[0]));
544         PyList_SET_ITEM(retVal, 2, PyBool_FromLong(self->m_bitLocalFlag.Torque));
545         
546         return retVal;
547 }
548
549 int KX_ObjectActuator::pyattr_set_forceLimitX(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
550 {
551         KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v);
552
553         PyObject* seq = PySequence_Fast(value, "");
554         if (seq && PySequence_Fast_GET_SIZE(seq) == 3)
555         {
556                 self->m_drot[0] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0));
557                 self->m_dloc[0] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 1));
558                 self->m_bitLocalFlag.Torque = (PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 2)) != 0);
559
560                 if (!PyErr_Occurred())
561                 {
562                         Py_DECREF(seq);
563                         return PY_SET_ATTR_SUCCESS;
564                 }
565         }
566
567         Py_XDECREF(seq);
568
569         PyErr_SetString(PyExc_ValueError, "expected a sequence of 2 floats and a bool");
570         return PY_SET_ATTR_FAIL;
571 }
572
573 PyObject* KX_ObjectActuator::pyattr_get_forceLimitY(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
574 {
575         KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v);
576         PyObject *retVal = PyList_New(3);
577
578         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(self->m_drot[1]));
579         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(self->m_dloc[1]));
580         PyList_SET_ITEM(retVal, 2, PyBool_FromLong(self->m_bitLocalFlag.DLoc));
581         
582         return retVal;
583 }
584
585 int     KX_ObjectActuator::pyattr_set_forceLimitY(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
586 {
587         KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v);
588
589         PyObject* seq = PySequence_Fast(value, "");
590         if (seq && PySequence_Fast_GET_SIZE(seq) == 3)
591         {
592                 self->m_drot[1] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0));
593                 self->m_dloc[1] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 1));
594                 self->m_bitLocalFlag.DLoc = (PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 2)) != 0);
595
596                 if (!PyErr_Occurred())
597                 {
598                         Py_DECREF(seq);
599                         return PY_SET_ATTR_SUCCESS;
600                 }
601         }
602
603         Py_XDECREF(seq);
604
605         PyErr_SetString(PyExc_ValueError, "expected a sequence of 2 floats and a bool");
606         return PY_SET_ATTR_FAIL;
607 }
608
609 PyObject* KX_ObjectActuator::pyattr_get_forceLimitZ(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
610 {
611         KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v);
612         PyObject *retVal = PyList_New(3);
613
614         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(self->m_drot[2]));
615         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(self->m_dloc[2]));
616         PyList_SET_ITEM(retVal, 2, PyBool_FromLong(self->m_bitLocalFlag.DRot));
617         
618         return retVal;
619 }
620
621 int     KX_ObjectActuator::pyattr_set_forceLimitZ(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
622 {
623         KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v);
624
625         PyObject* seq = PySequence_Fast(value, "");
626         if (seq && PySequence_Fast_GET_SIZE(seq) == 3)
627         {
628                 self->m_drot[2] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0));
629                 self->m_dloc[2] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 1));
630                 self->m_bitLocalFlag.DRot = (PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 2)) != 0);
631
632                 if (!PyErr_Occurred())
633                 {
634                         Py_DECREF(seq);
635                         return PY_SET_ATTR_SUCCESS;
636                 }
637         }
638
639         Py_XDECREF(seq);
640
641         PyErr_SetString(PyExc_ValueError, "expected a sequence of 2 floats and a bool");
642         return PY_SET_ATTR_FAIL;
643 }
644
645 PyObject* KX_ObjectActuator::pyattr_get_reference(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
646 {
647         KX_ObjectActuator* actuator = static_cast<KX_ObjectActuator*>(self);
648         if (!actuator->m_reference)
649                 Py_RETURN_NONE;
650         
651         return actuator->m_reference->GetProxy();
652 }
653
654 int KX_ObjectActuator::pyattr_set_reference(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
655 {
656         KX_ObjectActuator* actuator = static_cast<KX_ObjectActuator*>(self);
657         KX_GameObject *refOb;
658         
659         if (!ConvertPythonToGameObject(value, &refOb, true, "actu.reference = value: KX_ObjectActuator"))
660                 return PY_SET_ATTR_FAIL;
661         
662         if (actuator->m_reference)
663                 actuator->m_reference->UnregisterActuator(actuator);
664         
665         if(refOb==NULL) {
666                 actuator->m_reference= NULL;
667         }
668         else {  
669                 actuator->m_reference = refOb;
670                 actuator->m_reference->RegisterActuator(actuator);
671         }
672         
673         return PY_SET_ATTR_SUCCESS;
674 }
675
676
677 /* 1. set ------------------------------------------------------------------ */
678 /* Removed! */
679
680 /* 2. getForce                                                               */
681 PyObject* KX_ObjectActuator::PyGetForce()
682 {
683         ShowDeprecationWarning("getForce()", "the force and the useLocalForce properties");
684         PyObject *retVal = PyList_New(4);
685
686         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_force[0]));
687         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_force[1]));
688         PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_force[2]));
689         PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.Force));
690         
691         return retVal;
692 }
693 /* 3. setForce                                                               */
694 PyObject* KX_ObjectActuator::PySetForce(PyObject* args)
695 {
696         ShowDeprecationWarning("setForce()", "the force and the useLocalForce properties");
697         float vecArg[3];
698         int bToggle = 0;
699         if (!PyArg_ParseTuple(args, "fffi:setForce", &vecArg[0], &vecArg[1], 
700                                                   &vecArg[2], &bToggle)) {
701                 return NULL;
702         }
703         m_force.setValue(vecArg);
704         m_bitLocalFlag.Force = PyArgToBool(bToggle);
705         UpdateFuzzyFlags();
706         Py_RETURN_NONE;
707 }
708
709 /* 4. getTorque                                                              */
710 PyObject* KX_ObjectActuator::PyGetTorque()
711 {
712         ShowDeprecationWarning("getTorque()", "the torque and the useLocalTorque properties");
713         PyObject *retVal = PyList_New(4);
714
715         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_torque[0]));
716         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_torque[1]));
717         PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_torque[2]));
718         PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.Torque));
719         
720         return retVal;
721 }
722 /* 5. setTorque                                                              */
723 PyObject* KX_ObjectActuator::PySetTorque(PyObject* args)
724 {
725         ShowDeprecationWarning("setTorque()", "the torque and the useLocalTorque properties");
726         float vecArg[3];
727         int bToggle = 0;
728         if (!PyArg_ParseTuple(args, "fffi:setTorque", &vecArg[0], &vecArg[1], 
729                                                   &vecArg[2], &bToggle)) {
730                 return NULL;
731         }
732         m_torque.setValue(vecArg);
733         m_bitLocalFlag.Torque = PyArgToBool(bToggle);
734         UpdateFuzzyFlags();
735         Py_RETURN_NONE;
736 }
737
738 /* 6. getDLoc                                                                */
739 PyObject* KX_ObjectActuator::PyGetDLoc()
740 {
741         ShowDeprecationWarning("getDLoc()", "the dLoc and the useLocalDLoc properties");
742         PyObject *retVal = PyList_New(4);
743
744         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_dloc[0]));
745         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_dloc[1]));
746         PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_dloc[2]));
747         PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.DLoc));
748         
749         return retVal;
750 }
751 /* 7. setDLoc                                                                */
752 PyObject* KX_ObjectActuator::PySetDLoc(PyObject* args)
753 {
754         ShowDeprecationWarning("setDLoc()", "the dLoc and the useLocalDLoc properties");
755         float vecArg[3];
756         int bToggle = 0;
757         if(!PyArg_ParseTuple(args, "fffi:setDLoc", &vecArg[0], &vecArg[1], 
758                                                  &vecArg[2], &bToggle)) {
759                 return NULL;
760         }
761         m_dloc.setValue(vecArg);
762         m_bitLocalFlag.DLoc = PyArgToBool(bToggle);
763         UpdateFuzzyFlags();
764         Py_RETURN_NONE;
765 }
766
767 /* 8. getDRot                                                                */
768 PyObject* KX_ObjectActuator::PyGetDRot()
769 {
770         ShowDeprecationWarning("getDRot()", "the dRot and the useLocalDRot properties");
771         PyObject *retVal = PyList_New(4);
772
773         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_drot[0]));
774         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_drot[1]));
775         PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_drot[2]));
776         PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.DRot));
777         
778         return retVal;
779 }
780 /* 9. setDRot                                                                */
781 PyObject* KX_ObjectActuator::PySetDRot(PyObject* args)
782 {
783         ShowDeprecationWarning("setDRot()", "the dRot and the useLocalDRot properties");
784         float vecArg[3];
785         int bToggle = 0;
786         if (!PyArg_ParseTuple(args, "fffi:setDRot", &vecArg[0], &vecArg[1], 
787                                                   &vecArg[2], &bToggle)) {
788                 return NULL;
789         }
790         m_drot.setValue(vecArg);
791         m_bitLocalFlag.DRot = PyArgToBool(bToggle);
792         UpdateFuzzyFlags();
793         Py_RETURN_NONE;
794 }
795
796 /* 10. getLinearVelocity                                                 */
797 PyObject* KX_ObjectActuator::PyGetLinearVelocity() {
798         ShowDeprecationWarning("getLinearVelocity()", "the linV and the useLocalLinV properties");
799         PyObject *retVal = PyList_New(4);
800
801         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_linear_velocity[0]));
802         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_linear_velocity[1]));
803         PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_linear_velocity[2]));
804         PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.LinearVelocity));
805         
806         return retVal;
807 }
808
809 /* 11. setLinearVelocity                                                 */
810 PyObject* KX_ObjectActuator::PySetLinearVelocity(PyObject* args) {
811         ShowDeprecationWarning("setLinearVelocity()", "the linV and the useLocalLinV properties");
812         float vecArg[3];
813         int bToggle = 0;
814         if (!PyArg_ParseTuple(args, "fffi:setLinearVelocity", &vecArg[0], &vecArg[1], 
815                                                   &vecArg[2], &bToggle)) {
816                 return NULL;
817         }
818         m_linear_velocity.setValue(vecArg);
819         m_bitLocalFlag.LinearVelocity = PyArgToBool(bToggle);
820         UpdateFuzzyFlags();
821         Py_RETURN_NONE;
822 }
823
824
825 /* 12. getAngularVelocity                                                */
826 PyObject* KX_ObjectActuator::PyGetAngularVelocity() {
827         ShowDeprecationWarning("getAngularVelocity()", "the angV and the useLocalAngV properties");
828         PyObject *retVal = PyList_New(4);
829
830         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_angular_velocity[0]));
831         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_angular_velocity[1]));
832         PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_angular_velocity[2]));
833         PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.AngularVelocity));
834         
835         return retVal;
836 }
837 /* 13. setAngularVelocity                                                */
838 PyObject* KX_ObjectActuator::PySetAngularVelocity(PyObject* args) {
839         ShowDeprecationWarning("setAngularVelocity()", "the angV and the useLocalAngV properties");
840         float vecArg[3];
841         int bToggle = 0;
842         if (!PyArg_ParseTuple(args, "fffi:setAngularVelocity", &vecArg[0], &vecArg[1], 
843                                                   &vecArg[2], &bToggle)) {
844                 return NULL;
845         }
846         m_angular_velocity.setValue(vecArg);
847         m_bitLocalFlag.AngularVelocity = PyArgToBool(bToggle);
848         UpdateFuzzyFlags();
849         Py_RETURN_NONE;
850 }
851
852 /* 13. setDamping                                                */
853 PyObject* KX_ObjectActuator::PySetDamping(PyObject* args) {
854         ShowDeprecationWarning("setDamping()", "the damping property");
855         int damping = 0;
856         if (!PyArg_ParseTuple(args, "i:setDamping", &damping) || damping < 0 || damping > 1000) {
857                 return NULL;
858         }
859         m_damping = damping;
860         Py_RETURN_NONE;
861 }
862
863 /* 13. getVelocityDamping                                                */
864 PyObject* KX_ObjectActuator::PyGetDamping() {
865         ShowDeprecationWarning("getDamping()", "the damping property");
866         return Py_BuildValue("i",m_damping);
867 }
868 /* 6. getForceLimitX                                                                */
869 PyObject* KX_ObjectActuator::PyGetForceLimitX()
870 {
871         ShowDeprecationWarning("getForceLimitX()", "the forceLimitX property");
872         PyObject *retVal = PyList_New(3);
873
874         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_drot[0]));
875         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_dloc[0]));
876         PyList_SET_ITEM(retVal, 2, BoolToPyArg(m_bitLocalFlag.Torque));
877         
878         return retVal;
879 }
880 /* 7. setForceLimitX                                                         */
881 PyObject* KX_ObjectActuator::PySetForceLimitX(PyObject* args)
882 {
883         ShowDeprecationWarning("setForceLimitX()", "the forceLimitX property");
884         float vecArg[2];
885         int bToggle = 0;
886         if(!PyArg_ParseTuple(args, "ffi:setForceLimitX", &vecArg[0], &vecArg[1], &bToggle)) {
887                 return NULL;
888         }
889         m_drot[0] = vecArg[0];
890         m_dloc[0] = vecArg[1];
891         m_bitLocalFlag.Torque = PyArgToBool(bToggle);
892         Py_RETURN_NONE;
893 }
894
895 /* 6. getForceLimitY                                                                */
896 PyObject* KX_ObjectActuator::PyGetForceLimitY()
897 {
898         ShowDeprecationWarning("getForceLimitY()", "the forceLimitY property");
899         PyObject *retVal = PyList_New(3);
900
901         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_drot[1]));
902         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_dloc[1]));
903         PyList_SET_ITEM(retVal, 2, BoolToPyArg(m_bitLocalFlag.DLoc));
904         
905         return retVal;
906 }
907 /* 7. setForceLimitY                                                                */
908 PyObject* KX_ObjectActuator::PySetForceLimitY(PyObject* args)
909 {
910         ShowDeprecationWarning("setForceLimitY()", "the forceLimitY property");
911         float vecArg[2];
912         int bToggle = 0;
913         if(!PyArg_ParseTuple(args, "ffi:setForceLimitY", &vecArg[0], &vecArg[1], &bToggle)) {
914                 return NULL;
915         }
916         m_drot[1] = vecArg[0];
917         m_dloc[1] = vecArg[1];
918         m_bitLocalFlag.DLoc = PyArgToBool(bToggle);
919         Py_RETURN_NONE;
920 }
921
922 /* 6. getForceLimitZ                                                                */
923 PyObject* KX_ObjectActuator::PyGetForceLimitZ()
924 {
925         ShowDeprecationWarning("getForceLimitZ()", "the forceLimitZ property");
926         PyObject *retVal = PyList_New(3);
927
928         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_drot[2]));
929         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_dloc[2]));
930         PyList_SET_ITEM(retVal, 2, BoolToPyArg(m_bitLocalFlag.DRot));
931         
932         return retVal;
933 }
934 /* 7. setForceLimitZ                                                                */
935 PyObject* KX_ObjectActuator::PySetForceLimitZ(PyObject* args)
936 {
937         ShowDeprecationWarning("setForceLimitZ()", "the forceLimitZ property");
938         float vecArg[2];
939         int bToggle = 0;
940         if(!PyArg_ParseTuple(args, "ffi:setForceLimitZ", &vecArg[0], &vecArg[1], &bToggle)) {
941                 return NULL;
942         }
943         m_drot[2] = vecArg[0];
944         m_dloc[2] = vecArg[1];
945         m_bitLocalFlag.DRot = PyArgToBool(bToggle);
946         Py_RETURN_NONE;
947 }
948
949 /* 4. getPID                                                              */
950 PyObject* KX_ObjectActuator::PyGetPID()
951 {
952         ShowDeprecationWarning("getPID()", "the pid property");
953         PyObject *retVal = PyList_New(3);
954
955         PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_pid[0]));
956         PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_pid[1]));
957         PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_pid[2]));
958         
959         return retVal;
960 }
961 /* 5. setPID                                                              */
962 PyObject* KX_ObjectActuator::PySetPID(PyObject* args)
963 {
964         ShowDeprecationWarning("setPID()", "the pid property");
965         float vecArg[3];
966         if (!PyArg_ParseTuple(args, "fff:setPID", &vecArg[0], &vecArg[1], &vecArg[2])) {
967                 return NULL;
968         }
969         m_pid.setValue(vecArg);
970         Py_RETURN_NONE;
971 }
972
973
974
975
976
977 /* eof */