Blender V2.61 - r43446
|
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 */