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