Blender V2.61 - r43446

KX_ObjectActuator.cpp

Go to the documentation of this file.
00001 /*
00002  * Do translation/rotation actions
00003  *
00004  *
00005  * ***** BEGIN GPL LICENSE BLOCK *****
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software Foundation,
00019  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00022  * All rights reserved.
00023  *
00024  * The Original Code is: all of this file.
00025  *
00026  * Contributor(s): none yet.
00027  *
00028  * ***** END GPL LICENSE BLOCK *****
00029  */
00030 
00036 #include "KX_ObjectActuator.h"
00037 #include "KX_GameObject.h"
00038 #include "KX_PyMath.h" // For PyVecTo - should this include be put in PyObjectPlus?
00039 #include "KX_IPhysicsController.h"
00040 
00041 /* ------------------------------------------------------------------------- */
00042 /* Native functions                                                          */
00043 /* ------------------------------------------------------------------------- */
00044 
00045 KX_ObjectActuator::
00046 KX_ObjectActuator(
00047     SCA_IObject* gameobj,
00048     KX_GameObject* refobj,
00049     const MT_Vector3& force,
00050     const MT_Vector3& torque,
00051     const MT_Vector3& dloc,
00052     const MT_Vector3& drot,
00053     const MT_Vector3& linV,
00054     const MT_Vector3& angV,
00055     const short damping,
00056     const KX_LocalFlags& flag
00057 ) : 
00058     SCA_IActuator(gameobj, KX_ACT_OBJECT),
00059     m_force(force),
00060     m_torque(torque),
00061     m_dloc(dloc),
00062     m_drot(drot),
00063     m_linear_velocity(linV),
00064     m_angular_velocity(angV),
00065     m_linear_length2(0.0),
00066     m_current_linear_factor(0.0),
00067     m_current_angular_factor(0.0),
00068     m_damping(damping),
00069     m_previous_error(0.0,0.0,0.0),
00070     m_error_accumulator(0.0,0.0,0.0),
00071     m_bitLocalFlag (flag),
00072     m_reference(refobj),
00073     m_active_combined_velocity (false),
00074     m_linear_damping_active(false),
00075     m_angular_damping_active(false)
00076 {
00077     if (m_bitLocalFlag.ServoControl)
00078     {
00079         // in servo motion, the force is local if the target velocity is local
00080         m_bitLocalFlag.Force = m_bitLocalFlag.LinearVelocity;
00081 
00082         m_pid = m_torque;
00083     }
00084     if (m_reference)
00085         m_reference->RegisterActuator(this);
00086     UpdateFuzzyFlags();
00087 }
00088 
00089 KX_ObjectActuator::~KX_ObjectActuator()
00090 {
00091     if (m_reference)
00092         m_reference->UnregisterActuator(this);
00093 }
00094 
00095 bool KX_ObjectActuator::Update()
00096 {
00097     
00098     bool bNegativeEvent = IsNegativeEvent();
00099     RemoveAllEvents();
00100         
00101     KX_GameObject *parent = static_cast<KX_GameObject *>(GetParent()); 
00102 
00103     if (bNegativeEvent) {
00104         // If we previously set the linear velocity we now have to inform
00105         // the physics controller that we no longer wish to apply it and that
00106         // it should reconcile the externally set velocity with it's 
00107         // own velocity.
00108         if (m_active_combined_velocity) {
00109             if (parent)
00110                 parent->ResolveCombinedVelocities(
00111                         m_linear_velocity,
00112                         m_angular_velocity,
00113                         (m_bitLocalFlag.LinearVelocity) != 0,
00114                         (m_bitLocalFlag.AngularVelocity) != 0
00115                     );
00116             m_active_combined_velocity = false;
00117         } 
00118         m_linear_damping_active = false;
00119         m_angular_damping_active = false;
00120         m_error_accumulator.setValue(0.0,0.0,0.0);
00121         m_previous_error.setValue(0.0,0.0,0.0);
00122         return false; 
00123 
00124     } else if (parent)
00125     {
00126         if (m_bitLocalFlag.ServoControl) 
00127         {
00128             // In this mode, we try to reach a target speed using force
00129             // As we don't know the friction, we must implement a generic 
00130             // servo control to achieve the speed in a configurable
00131             // v = current velocity
00132             // V = target velocity
00133             // e = V-v = speed error
00134             // dt = time interval since previous update
00135             // I = sum(e(t)*dt)
00136             // dv = e(t) - e(t-1)
00137             // KP, KD, KI : coefficient
00138             // F = KP*e+KI*I+KD*dv
00139             MT_Scalar mass = parent->GetMass();
00140             if (mass < MT_EPSILON)
00141                 return false;
00142             MT_Vector3 v = parent->GetLinearVelocity(m_bitLocalFlag.LinearVelocity);
00143             if (m_reference)
00144             {
00145                 const MT_Point3& mypos = parent->NodeGetWorldPosition();
00146                 const MT_Point3& refpos = m_reference->NodeGetWorldPosition();
00147                 MT_Point3 relpos;
00148                 relpos = (mypos-refpos);
00149                 MT_Vector3 vel= m_reference->GetVelocity(relpos);
00150                 if (m_bitLocalFlag.LinearVelocity)
00151                     // must convert in local space
00152                     vel = parent->NodeGetWorldOrientation().transposed()*vel;
00153                 v -= vel;
00154             }
00155             MT_Vector3 e = m_linear_velocity - v;
00156             MT_Vector3 dv = e - m_previous_error;
00157             MT_Vector3 I = m_error_accumulator + e;
00158 
00159             m_force = m_pid.x()*e+m_pid.y()*I+m_pid.z()*dv;
00160             // to automatically adapt the PID coefficient to mass;
00161             m_force *= mass;
00162             if (m_bitLocalFlag.Torque) 
00163             {
00164                 if (m_force[0] > m_dloc[0])
00165                 {
00166                     m_force[0] = m_dloc[0];
00167                     I[0] = m_error_accumulator[0];
00168                 } else if (m_force[0] < m_drot[0])
00169                 {
00170                     m_force[0] = m_drot[0];
00171                     I[0] = m_error_accumulator[0];
00172                 }
00173             }
00174             if (m_bitLocalFlag.DLoc) 
00175             {
00176                 if (m_force[1] > m_dloc[1])
00177                 {
00178                     m_force[1] = m_dloc[1];
00179                     I[1] = m_error_accumulator[1];
00180                 } else if (m_force[1] < m_drot[1])
00181                 {
00182                     m_force[1] = m_drot[1];
00183                     I[1] = m_error_accumulator[1];
00184                 }
00185             }
00186             if (m_bitLocalFlag.DRot) 
00187             {
00188                 if (m_force[2] > m_dloc[2])
00189                 {
00190                     m_force[2] = m_dloc[2];
00191                     I[2] = m_error_accumulator[2];
00192                 } else if (m_force[2] < m_drot[2])
00193                 {
00194                     m_force[2] = m_drot[2];
00195                     I[2] = m_error_accumulator[2];
00196                 }
00197             }
00198             m_previous_error = e;
00199             m_error_accumulator = I;
00200             parent->ApplyForce(m_force,(m_bitLocalFlag.LinearVelocity) != 0);
00201         } else
00202         {
00203             if (!m_bitLocalFlag.ZeroForce)
00204             {
00205                 parent->ApplyForce(m_force,(m_bitLocalFlag.Force) != 0);
00206             }
00207             if (!m_bitLocalFlag.ZeroTorque)
00208             {
00209                 parent->ApplyTorque(m_torque,(m_bitLocalFlag.Torque) != 0);
00210             }
00211             if (!m_bitLocalFlag.ZeroDLoc)
00212             {
00213                 parent->ApplyMovement(m_dloc,(m_bitLocalFlag.DLoc) != 0);
00214             }
00215             if (!m_bitLocalFlag.ZeroDRot)
00216             {
00217                 parent->ApplyRotation(m_drot,(m_bitLocalFlag.DRot) != 0);
00218             }
00219             if (!m_bitLocalFlag.ZeroLinearVelocity)
00220             {
00221                 if (m_bitLocalFlag.AddOrSetLinV) {
00222                     parent->addLinearVelocity(m_linear_velocity,(m_bitLocalFlag.LinearVelocity) != 0);
00223                 } else {
00224                     m_active_combined_velocity = true;
00225                     if (m_damping > 0) {
00226                         MT_Vector3 linV;
00227                         if (!m_linear_damping_active) {
00228                             // delta and the start speed (depends on the existing speed in that direction)
00229                             linV = parent->GetLinearVelocity(m_bitLocalFlag.LinearVelocity);
00230                             // keep only the projection along the desired direction
00231                             m_current_linear_factor = linV.dot(m_linear_velocity)/m_linear_length2;
00232                             m_linear_damping_active = true;
00233                         }
00234                         if (m_current_linear_factor < 1.0)
00235                             m_current_linear_factor += 1.0/m_damping;
00236                         if (m_current_linear_factor > 1.0)
00237                             m_current_linear_factor = 1.0;
00238                         linV = m_current_linear_factor * m_linear_velocity;
00239                         parent->setLinearVelocity(linV,(m_bitLocalFlag.LinearVelocity) != 0);
00240                     } else {
00241                         parent->setLinearVelocity(m_linear_velocity,(m_bitLocalFlag.LinearVelocity) != 0);
00242                     }
00243                 }
00244             }
00245             if (!m_bitLocalFlag.ZeroAngularVelocity)
00246             {
00247                 m_active_combined_velocity = true;
00248                 if (m_damping > 0) {
00249                     MT_Vector3 angV;
00250                     if (!m_angular_damping_active) {
00251                         // delta and the start speed (depends on the existing speed in that direction)
00252                         angV = parent->GetAngularVelocity(m_bitLocalFlag.AngularVelocity);
00253                         // keep only the projection along the desired direction
00254                         m_current_angular_factor = angV.dot(m_angular_velocity)/m_angular_length2;
00255                         m_angular_damping_active = true;
00256                     }
00257                     if (m_current_angular_factor < 1.0)
00258                         m_current_angular_factor += 1.0/m_damping;
00259                     if (m_current_angular_factor > 1.0)
00260                         m_current_angular_factor = 1.0;
00261                     angV = m_current_angular_factor * m_angular_velocity;
00262                     parent->setAngularVelocity(angV,(m_bitLocalFlag.AngularVelocity) != 0);
00263                 } else {
00264                     parent->setAngularVelocity(m_angular_velocity,(m_bitLocalFlag.AngularVelocity) != 0);
00265                 }
00266             }
00267         }
00268         
00269     }
00270     return true;
00271 }
00272 
00273 
00274 
00275 CValue* KX_ObjectActuator::GetReplica()
00276 {
00277     KX_ObjectActuator* replica = new KX_ObjectActuator(*this);//m_float,GetName());
00278     replica->ProcessReplica();
00279 
00280     return replica;
00281 }
00282 
00283 void KX_ObjectActuator::ProcessReplica()
00284 {
00285     SCA_IActuator::ProcessReplica();
00286     if (m_reference)
00287         m_reference->RegisterActuator(this);
00288 }
00289 
00290 bool KX_ObjectActuator::UnlinkObject(SCA_IObject* clientobj)
00291 {
00292     if (clientobj == (SCA_IObject*)m_reference)
00293     {
00294         // this object is being deleted, we cannot continue to use it as reference.
00295         m_reference = NULL;
00296         return true;
00297     }
00298     return false;
00299 }
00300 
00301 void KX_ObjectActuator::Relink(CTR_Map<CTR_HashedPtr, void*> *obj_map)
00302 {
00303     void **h_obj = (*obj_map)[m_reference];
00304     if (h_obj) {
00305         if (m_reference)
00306             m_reference->UnregisterActuator(this);
00307         m_reference = (KX_GameObject*)(*h_obj);
00308         m_reference->RegisterActuator(this);
00309     }
00310 }
00311 
00312 /* some 'standard' utilities... */
00313 bool KX_ObjectActuator::isValid(KX_ObjectActuator::KX_OBJECT_ACT_VEC_TYPE type)
00314 {
00315     bool res = false;
00316     res = (type > KX_OBJECT_ACT_NODEF) && (type < KX_OBJECT_ACT_MAX);
00317     return res;
00318 }
00319 
00320 #ifdef WITH_PYTHON
00321 
00322 /* ------------------------------------------------------------------------- */
00323 /* Python functions                                                          */
00324 /* ------------------------------------------------------------------------- */
00325 
00326 /* Integration hooks ------------------------------------------------------- */
00327 PyTypeObject KX_ObjectActuator::Type = {
00328     PyVarObject_HEAD_INIT(NULL, 0)
00329     "KX_ObjectActuator",
00330     sizeof(PyObjectPlus_Proxy),
00331     0,
00332     py_base_dealloc,
00333     0,
00334     0,
00335     0,
00336     0,
00337     py_base_repr,
00338     0,0,0,0,0,0,0,0,0,
00339     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
00340     0,0,0,0,0,0,0,
00341     Methods,
00342     0,
00343     0,
00344     &SCA_IActuator::Type,
00345     0,0,0,0,0,0,
00346     py_base_new
00347 };
00348 
00349 PyMethodDef KX_ObjectActuator::Methods[] = {
00350     {NULL,NULL} //Sentinel
00351 };
00352 
00353 PyAttributeDef KX_ObjectActuator::Attributes[] = {
00354     KX_PYATTRIBUTE_VECTOR_RW_CHECK("force", -1000, 1000, false, KX_ObjectActuator, m_force, PyUpdateFuzzyFlags),
00355     KX_PYATTRIBUTE_BOOL_RW("useLocalForce", KX_ObjectActuator, m_bitLocalFlag.Force),
00356     KX_PYATTRIBUTE_VECTOR_RW_CHECK("torque", -1000, 1000, false, KX_ObjectActuator, m_torque, PyUpdateFuzzyFlags),
00357     KX_PYATTRIBUTE_BOOL_RW("useLocalTorque", KX_ObjectActuator, m_bitLocalFlag.Torque),
00358     KX_PYATTRIBUTE_VECTOR_RW_CHECK("dLoc", -1000, 1000, false, KX_ObjectActuator, m_dloc, PyUpdateFuzzyFlags),
00359     KX_PYATTRIBUTE_BOOL_RW("useLocalDLoc", KX_ObjectActuator, m_bitLocalFlag.DLoc),
00360     KX_PYATTRIBUTE_VECTOR_RW_CHECK("dRot", -1000, 1000, false, KX_ObjectActuator, m_drot, PyUpdateFuzzyFlags),
00361     KX_PYATTRIBUTE_BOOL_RW("useLocalDRot", KX_ObjectActuator, m_bitLocalFlag.DRot),
00362 #ifdef USE_MATHUTILS
00363     KX_PYATTRIBUTE_RW_FUNCTION("linV", KX_ObjectActuator, pyattr_get_linV, pyattr_set_linV),
00364     KX_PYATTRIBUTE_RW_FUNCTION("angV", KX_ObjectActuator, pyattr_get_angV, pyattr_set_angV),
00365 #else
00366     KX_PYATTRIBUTE_VECTOR_RW_CHECK("linV", -1000, 1000, false, KX_ObjectActuator, m_linear_velocity, PyUpdateFuzzyFlags),
00367     KX_PYATTRIBUTE_VECTOR_RW_CHECK("angV", -1000, 1000, false, KX_ObjectActuator, m_angular_velocity, PyUpdateFuzzyFlags),
00368 #endif
00369     KX_PYATTRIBUTE_BOOL_RW("useLocalLinV", KX_ObjectActuator, m_bitLocalFlag.LinearVelocity),
00370     KX_PYATTRIBUTE_BOOL_RW("useLocalAngV", KX_ObjectActuator, m_bitLocalFlag.AngularVelocity),
00371     KX_PYATTRIBUTE_SHORT_RW("damping", 0, 1000, false, KX_ObjectActuator, m_damping),
00372     KX_PYATTRIBUTE_RW_FUNCTION("forceLimitX", KX_ObjectActuator, pyattr_get_forceLimitX, pyattr_set_forceLimitX),
00373     KX_PYATTRIBUTE_RW_FUNCTION("forceLimitY", KX_ObjectActuator, pyattr_get_forceLimitY, pyattr_set_forceLimitY),
00374     KX_PYATTRIBUTE_RW_FUNCTION("forceLimitZ", KX_ObjectActuator, pyattr_get_forceLimitZ, pyattr_set_forceLimitZ),
00375     KX_PYATTRIBUTE_VECTOR_RW_CHECK("pid", -100, 200, true, KX_ObjectActuator, m_pid, PyCheckPid),
00376     KX_PYATTRIBUTE_RW_FUNCTION("reference", KX_ObjectActuator,pyattr_get_reference,pyattr_set_reference),
00377     { NULL }    //Sentinel
00378 };
00379 
00380 /* Attribute get/set functions */
00381 
00382 #ifdef USE_MATHUTILS
00383 
00384 /* These require an SGNode */
00385 #define MATHUTILS_VEC_CB_LINV 1
00386 #define MATHUTILS_VEC_CB_ANGV 2
00387 
00388 static int mathutils_kxobactu_vector_cb_index= -1; /* index for our callbacks */
00389 
00390 static int mathutils_obactu_generic_check(BaseMathObject *bmo)
00391 {
00392     KX_ObjectActuator* self= static_cast<KX_ObjectActuator*>BGE_PROXY_REF(bmo->cb_user);
00393     if(self==NULL)
00394         return -1;
00395 
00396     return 0;
00397 }
00398 
00399 static int mathutils_obactu_vector_get(BaseMathObject *bmo, int subtype)
00400 {
00401     KX_ObjectActuator* self= static_cast<KX_ObjectActuator*>BGE_PROXY_REF(bmo->cb_user);
00402     if(self==NULL)
00403         return -1;
00404 
00405     switch(subtype) {
00406         case MATHUTILS_VEC_CB_LINV:
00407             self->m_linear_velocity.getValue(bmo->data);
00408             break;
00409         case MATHUTILS_VEC_CB_ANGV:
00410             self->m_angular_velocity.getValue(bmo->data);
00411             break;
00412     }
00413 
00414     return 0;
00415 }
00416 
00417 static int mathutils_obactu_vector_set(BaseMathObject *bmo, int subtype)
00418 {
00419     KX_ObjectActuator* self= static_cast<KX_ObjectActuator*>BGE_PROXY_REF(bmo->cb_user);
00420     if(self==NULL)
00421         return -1;
00422 
00423     switch(subtype) {
00424         case MATHUTILS_VEC_CB_LINV:
00425             self->m_linear_velocity.setValue(bmo->data);
00426             break;
00427         case MATHUTILS_VEC_CB_ANGV:
00428             self->m_angular_velocity.setValue(bmo->data);
00429             break;
00430     }
00431 
00432     return 0;
00433 }
00434 
00435 static int mathutils_obactu_vector_get_index(BaseMathObject *bmo, int subtype, int index)
00436 {
00437     /* lazy, avoid repeteing the case statement */
00438     if(mathutils_obactu_vector_get(bmo, subtype) == -1)
00439         return -1;
00440     return 0;
00441 }
00442 
00443 static int mathutils_obactu_vector_set_index(BaseMathObject *bmo, int subtype, int index)
00444 {
00445     float f= bmo->data[index];
00446 
00447     /* lazy, avoid repeteing the case statement */
00448     if(mathutils_obactu_vector_get(bmo, subtype) == -1)
00449         return -1;
00450 
00451     bmo->data[index]= f;
00452     return mathutils_obactu_vector_set(bmo, subtype);
00453 }
00454 
00455 Mathutils_Callback mathutils_obactu_vector_cb = {
00456     mathutils_obactu_generic_check,
00457     mathutils_obactu_vector_get,
00458     mathutils_obactu_vector_set,
00459     mathutils_obactu_vector_get_index,
00460     mathutils_obactu_vector_set_index
00461 };
00462 
00463 PyObject* KX_ObjectActuator::pyattr_get_linV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
00464 {
00465     return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxobactu_vector_cb_index, MATHUTILS_VEC_CB_LINV);
00466 }
00467 
00468 int KX_ObjectActuator::pyattr_set_linV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
00469 {
00470     KX_ObjectActuator* self= static_cast<KX_ObjectActuator*>(self_v);
00471     if (!PyVecTo(value, self->m_linear_velocity))
00472         return PY_SET_ATTR_FAIL;
00473 
00474     self->UpdateFuzzyFlags();
00475 
00476     return PY_SET_ATTR_SUCCESS;
00477 }
00478 
00479 PyObject* KX_ObjectActuator::pyattr_get_angV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
00480 {
00481     return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxobactu_vector_cb_index, MATHUTILS_VEC_CB_ANGV);
00482 }
00483 
00484 int KX_ObjectActuator::pyattr_set_angV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
00485 {
00486     KX_ObjectActuator* self= static_cast<KX_ObjectActuator*>(self_v);
00487     if (!PyVecTo(value, self->m_angular_velocity))
00488         return PY_SET_ATTR_FAIL;
00489 
00490     self->UpdateFuzzyFlags();
00491 
00492     return PY_SET_ATTR_SUCCESS;
00493 }
00494 
00495 
00496 void KX_ObjectActuator_Mathutils_Callback_Init(void)
00497 {
00498     // register mathutils callbacks, ok to run more then once.
00499     mathutils_kxobactu_vector_cb_index= Mathutils_RegisterCallback(&mathutils_obactu_vector_cb);
00500 }
00501 
00502 #endif // USE_MATHUTILS
00503 
00504 PyObject* KX_ObjectActuator::pyattr_get_forceLimitX(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
00505 {
00506     KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v);
00507     PyObject *retVal = PyList_New(3);
00508 
00509     PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(self->m_drot[0]));
00510     PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(self->m_dloc[0]));
00511     PyList_SET_ITEM(retVal, 2, PyBool_FromLong(self->m_bitLocalFlag.Torque));
00512     
00513     return retVal;
00514 }
00515 
00516 int KX_ObjectActuator::pyattr_set_forceLimitX(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
00517 {
00518     KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v);
00519 
00520     PyObject* seq = PySequence_Fast(value, "");
00521     if (seq && PySequence_Fast_GET_SIZE(seq) == 3)
00522     {
00523         self->m_drot[0] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0));
00524         self->m_dloc[0] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 1));
00525         self->m_bitLocalFlag.Torque = (PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 2)) != 0);
00526 
00527         if (!PyErr_Occurred())
00528         {
00529             Py_DECREF(seq);
00530             return PY_SET_ATTR_SUCCESS;
00531         }
00532     }
00533 
00534     Py_XDECREF(seq);
00535 
00536     PyErr_SetString(PyExc_ValueError, "expected a sequence of 2 floats and a bool");
00537     return PY_SET_ATTR_FAIL;
00538 }
00539 
00540 PyObject* KX_ObjectActuator::pyattr_get_forceLimitY(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
00541 {
00542     KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v);
00543     PyObject *retVal = PyList_New(3);
00544 
00545     PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(self->m_drot[1]));
00546     PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(self->m_dloc[1]));
00547     PyList_SET_ITEM(retVal, 2, PyBool_FromLong(self->m_bitLocalFlag.DLoc));
00548     
00549     return retVal;
00550 }
00551 
00552 int KX_ObjectActuator::pyattr_set_forceLimitY(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
00553 {
00554     KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v);
00555 
00556     PyObject* seq = PySequence_Fast(value, "");
00557     if (seq && PySequence_Fast_GET_SIZE(seq) == 3)
00558     {
00559         self->m_drot[1] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0));
00560         self->m_dloc[1] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 1));
00561         self->m_bitLocalFlag.DLoc = (PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 2)) != 0);
00562 
00563         if (!PyErr_Occurred())
00564         {
00565             Py_DECREF(seq);
00566             return PY_SET_ATTR_SUCCESS;
00567         }
00568     }
00569 
00570     Py_XDECREF(seq);
00571 
00572     PyErr_SetString(PyExc_ValueError, "expected a sequence of 2 floats and a bool");
00573     return PY_SET_ATTR_FAIL;
00574 }
00575 
00576 PyObject* KX_ObjectActuator::pyattr_get_forceLimitZ(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
00577 {
00578     KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v);
00579     PyObject *retVal = PyList_New(3);
00580 
00581     PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(self->m_drot[2]));
00582     PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(self->m_dloc[2]));
00583     PyList_SET_ITEM(retVal, 2, PyBool_FromLong(self->m_bitLocalFlag.DRot));
00584     
00585     return retVal;
00586 }
00587 
00588 int KX_ObjectActuator::pyattr_set_forceLimitZ(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
00589 {
00590     KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v);
00591 
00592     PyObject* seq = PySequence_Fast(value, "");
00593     if (seq && PySequence_Fast_GET_SIZE(seq) == 3)
00594     {
00595         self->m_drot[2] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0));
00596         self->m_dloc[2] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 1));
00597         self->m_bitLocalFlag.DRot = (PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 2)) != 0);
00598 
00599         if (!PyErr_Occurred())
00600         {
00601             Py_DECREF(seq);
00602             return PY_SET_ATTR_SUCCESS;
00603         }
00604     }
00605 
00606     Py_XDECREF(seq);
00607 
00608     PyErr_SetString(PyExc_ValueError, "expected a sequence of 2 floats and a bool");
00609     return PY_SET_ATTR_FAIL;
00610 }
00611 
00612 PyObject* KX_ObjectActuator::pyattr_get_reference(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
00613 {
00614     KX_ObjectActuator* actuator = static_cast<KX_ObjectActuator*>(self);
00615     if (!actuator->m_reference)
00616         Py_RETURN_NONE;
00617     
00618     return actuator->m_reference->GetProxy();
00619 }
00620 
00621 int KX_ObjectActuator::pyattr_set_reference(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
00622 {
00623     KX_ObjectActuator* actuator = static_cast<KX_ObjectActuator*>(self);
00624     KX_GameObject *refOb;
00625     
00626     if (!ConvertPythonToGameObject(value, &refOb, true, "actu.reference = value: KX_ObjectActuator"))
00627         return PY_SET_ATTR_FAIL;
00628     
00629     if (actuator->m_reference)
00630         actuator->m_reference->UnregisterActuator(actuator);
00631     
00632     if(refOb==NULL) {
00633         actuator->m_reference= NULL;
00634     }
00635     else {  
00636         actuator->m_reference = refOb;
00637         actuator->m_reference->RegisterActuator(actuator);
00638     }
00639     
00640     return PY_SET_ATTR_SUCCESS;
00641 }
00642 
00643 #endif // WITH_PYTHON
00644 
00645 /* eof */