|
Blender
V2.59
|
00001 /* 00002 * $Id: KX_GameObject.cpp 38273 2011-07-09 19:59:32Z campbellbarton $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00021 * All rights reserved. 00022 * 00023 * The Original Code is: all of this file. 00024 * 00025 * Contributor(s): none yet. 00026 * 00027 * ***** END GPL LICENSE BLOCK ***** 00028 * Game object wrapper 00029 */ 00030 00036 #if defined(_WIN64) 00037 typedef unsigned __int64 uint_ptr; 00038 #else 00039 typedef unsigned long uint_ptr; 00040 #endif 00041 00042 #if defined(WIN32) && !defined(FREE_WINDOWS) 00043 // This warning tells us about truncation of __long__ stl-generated names. 00044 // It can occasionally cause DevStudio to have internal compiler warnings. 00045 #pragma warning( disable : 4786 ) 00046 #endif 00047 00048 00049 #define KX_INERTIA_INFINITE 10000 00050 #include "RAS_IPolygonMaterial.h" 00051 #include "KX_BlenderMaterial.h" 00052 #include "KX_GameObject.h" 00053 #include "KX_Camera.h" // only for their ::Type 00054 #include "KX_Light.h" // only for their ::Type 00055 #include "KX_FontObject.h" // only for their ::Type 00056 #include "RAS_MeshObject.h" 00057 #include "KX_MeshProxy.h" 00058 #include "KX_PolyProxy.h" 00059 #include <stdio.h> // printf 00060 #include "SG_Controller.h" 00061 #include "KX_IPhysicsController.h" 00062 #include "PHY_IGraphicController.h" 00063 #include "SG_Node.h" 00064 #include "SG_Controller.h" 00065 #include "KX_ClientObjectInfo.h" 00066 #include "RAS_BucketManager.h" 00067 #include "KX_RayCast.h" 00068 #include "KX_PythonInit.h" 00069 #include "KX_PyMath.h" 00070 #include "KX_PythonSeq.h" 00071 #include "KX_ConvertPhysicsObject.h" 00072 #include "SCA_IActuator.h" 00073 #include "SCA_ISensor.h" 00074 #include "SCA_IController.h" 00075 #include "NG_NetworkScene.h" //Needed for sendMessage() 00076 00077 #include "PyObjectPlus.h" /* python stuff */ 00078 00079 // This file defines relationships between parents and children 00080 // in the game engine. 00081 00082 #include "KX_SG_NodeRelationships.h" 00083 00084 #include "BLI_math.h" 00085 00086 static MT_Point3 dummy_point= MT_Point3(0.0, 0.0, 0.0); 00087 static MT_Vector3 dummy_scaling = MT_Vector3(1.0, 1.0, 1.0); 00088 static MT_Matrix3x3 dummy_orientation = MT_Matrix3x3( 1.0, 0.0, 0.0, 00089 0.0, 1.0, 0.0, 00090 0.0, 0.0, 1.0); 00091 00092 KX_GameObject::KX_GameObject( 00093 void* sgReplicationInfo, 00094 SG_Callbacks callbacks) 00095 : SCA_IObject(), 00096 m_bDyna(false), 00097 m_layer(0), 00098 m_pBlenderObject(NULL), 00099 m_pBlenderGroupObject(NULL), 00100 m_bSuspendDynamics(false), 00101 m_bUseObjectColor(false), 00102 m_bIsNegativeScaling(false), 00103 m_bVisible(true), 00104 m_bCulled(true), 00105 m_bOccluder(false), 00106 m_pPhysicsController1(NULL), 00107 m_pGraphicController(NULL), 00108 m_xray(false), 00109 m_pHitObject(NULL), 00110 m_isDeformable(false) 00111 #ifdef WITH_PYTHON 00112 , m_attr_dict(NULL) 00113 #endif 00114 { 00115 m_ignore_activity_culling = false; 00116 m_pClient_info = new KX_ClientObjectInfo(this, KX_ClientObjectInfo::ACTOR); 00117 m_pSGNode = new SG_Node(this,sgReplicationInfo,callbacks); 00118 00119 // define the relationship between this node and it's parent. 00120 00121 KX_NormalParentRelation * parent_relation = 00122 KX_NormalParentRelation::New(); 00123 m_pSGNode->SetParentRelation(parent_relation); 00124 }; 00125 00126 00127 00128 KX_GameObject::~KX_GameObject() 00129 { 00130 RemoveMeshes(); 00131 00132 // is this delete somewhere ? 00133 //if (m_sumoObj) 00134 // delete m_sumoObj; 00135 delete m_pClient_info; 00136 //if (m_pSGNode) 00137 // delete m_pSGNode; 00138 if (m_pSGNode) 00139 { 00140 // must go through controllers and make sure they will not use us anymore 00141 // This is important for KX_BulletPhysicsControllers that unregister themselves 00142 // from the object when they are deleted. 00143 SGControllerList::iterator contit; 00144 SGControllerList& controllers = m_pSGNode->GetSGControllerList(); 00145 for (contit = controllers.begin();contit!=controllers.end();++contit) 00146 { 00147 (*contit)->ClearObject(); 00148 } 00149 m_pSGNode->SetSGClientObject(NULL); 00150 00151 /* m_pSGNode is freed in KX_Scene::RemoveNodeDestructObject */ 00152 } 00153 if (m_pGraphicController) 00154 { 00155 delete m_pGraphicController; 00156 } 00157 #ifdef WITH_PYTHON 00158 if (m_attr_dict) { 00159 PyDict_Clear(m_attr_dict); /* incase of circular refs or other weird cases */ 00160 /* Py_CLEAR: Py_DECREF's and NULL's */ 00161 Py_CLEAR(m_attr_dict); 00162 } 00163 #endif // WITH_PYTHON 00164 } 00165 00166 KX_GameObject* KX_GameObject::GetClientObject(KX_ClientObjectInfo* info) 00167 { 00168 if (!info) 00169 return NULL; 00170 return info->m_gameobject; 00171 } 00172 00173 CValue* KX_GameObject:: Calc(VALUE_OPERATOR op, CValue *val) 00174 { 00175 return NULL; 00176 } 00177 00178 00179 00180 CValue* KX_GameObject::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val) 00181 { 00182 return NULL; 00183 } 00184 00185 00186 00187 const STR_String & KX_GameObject::GetText() 00188 { 00189 return m_text; 00190 } 00191 00192 00193 00194 double KX_GameObject::GetNumber() 00195 { 00196 return 0; 00197 } 00198 00199 00200 00201 STR_String& KX_GameObject::GetName() 00202 { 00203 return m_name; 00204 } 00205 00206 00207 00208 void KX_GameObject::SetName(const char *name) 00209 { 00210 m_name = name; 00211 }; // Set the name of the value 00212 00213 KX_IPhysicsController* KX_GameObject::GetPhysicsController() 00214 { 00215 return m_pPhysicsController1; 00216 } 00217 00218 KX_GameObject* KX_GameObject::GetParent() 00219 { 00220 KX_GameObject* result = NULL; 00221 SG_Node* node = m_pSGNode; 00222 00223 while (node && !result) 00224 { 00225 node = node->GetSGParent(); 00226 if (node) 00227 result = (KX_GameObject*)node->GetSGClientObject(); 00228 } 00229 00230 if (result) 00231 result->AddRef(); 00232 00233 return result; 00234 00235 } 00236 00237 void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj, bool addToCompound, bool ghost) 00238 { 00239 // check on valid node in case a python controller holds a reference to a deleted object 00240 if (obj && 00241 GetSGNode() && // object is not zombi 00242 obj->GetSGNode() && // object is not zombi 00243 GetSGNode()->GetSGParent() != obj->GetSGNode() && // not already parented to same object 00244 !GetSGNode()->IsAncessor(obj->GetSGNode()) && // no parenting loop 00245 this != obj) // not the object itself 00246 { 00247 // Make sure the objects have some scale 00248 MT_Vector3 scale1 = NodeGetWorldScaling(); 00249 MT_Vector3 scale2 = obj->NodeGetWorldScaling(); 00250 if (fabs(scale2[0]) < FLT_EPSILON || 00251 fabs(scale2[1]) < FLT_EPSILON || 00252 fabs(scale2[2]) < FLT_EPSILON || 00253 fabs(scale1[0]) < FLT_EPSILON || 00254 fabs(scale1[1]) < FLT_EPSILON || 00255 fabs(scale1[2]) < FLT_EPSILON) { return; } 00256 00257 // Remove us from our old parent and set our new parent 00258 RemoveParent(scene); 00259 obj->GetSGNode()->AddChild(GetSGNode()); 00260 00261 if (m_pPhysicsController1) 00262 { 00263 m_pPhysicsController1->SuspendDynamics(ghost); 00264 } 00265 // Set us to our new scale, position, and orientation 00266 scale2[0] = 1.0/scale2[0]; 00267 scale2[1] = 1.0/scale2[1]; 00268 scale2[2] = 1.0/scale2[2]; 00269 scale1 = scale1 * scale2; 00270 MT_Matrix3x3 invori = obj->NodeGetWorldOrientation().inverse(); 00271 MT_Vector3 newpos = invori*(NodeGetWorldPosition()-obj->NodeGetWorldPosition())*scale2; 00272 00273 NodeSetLocalScale(scale1); 00274 NodeSetLocalPosition(MT_Point3(newpos[0],newpos[1],newpos[2])); 00275 NodeSetLocalOrientation(invori*NodeGetWorldOrientation()); 00276 NodeUpdateGS(0.f); 00277 // object will now be a child, it must be removed from the parent list 00278 CListValue* rootlist = scene->GetRootParentList(); 00279 if (rootlist->RemoveValue(this)) 00280 // the object was in parent list, decrement ref count as it's now removed 00281 Release(); 00282 // if the new parent is a compound object, add this object shape to the compound shape. 00283 // step 0: verify this object has physical controller 00284 if (m_pPhysicsController1 && addToCompound) 00285 { 00286 // step 1: find the top parent (not necessarily obj) 00287 KX_GameObject* rootobj = (KX_GameObject*)obj->GetSGNode()->GetRootSGParent()->GetSGClientObject(); 00288 // step 2: verify it has a physical controller and compound shape 00289 if (rootobj != NULL && 00290 rootobj->m_pPhysicsController1 != NULL && 00291 rootobj->m_pPhysicsController1->IsCompound()) 00292 { 00293 rootobj->m_pPhysicsController1->AddCompoundChild(m_pPhysicsController1); 00294 } 00295 } 00296 // graphically, the object hasn't change place, no need to update m_pGraphicController 00297 } 00298 } 00299 00300 void KX_GameObject::RemoveParent(KX_Scene *scene) 00301 { 00302 // check on valid node in case a python controller holds a reference to a deleted object 00303 if (GetSGNode() && GetSGNode()->GetSGParent()) 00304 { 00305 // get the root object to remove us from compound object if needed 00306 KX_GameObject* rootobj = (KX_GameObject*)GetSGNode()->GetRootSGParent()->GetSGClientObject(); 00307 // Set us to the right spot 00308 GetSGNode()->SetLocalScale(GetSGNode()->GetWorldScaling()); 00309 GetSGNode()->SetLocalOrientation(GetSGNode()->GetWorldOrientation()); 00310 GetSGNode()->SetLocalPosition(GetSGNode()->GetWorldPosition()); 00311 00312 // Remove us from our parent 00313 GetSGNode()->DisconnectFromParent(); 00314 NodeUpdateGS(0.f); 00315 // the object is now a root object, add it to the parentlist 00316 CListValue* rootlist = scene->GetRootParentList(); 00317 if (!rootlist->SearchValue(this)) 00318 // object was not in root list, add it now and increment ref count 00319 rootlist->Add(AddRef()); 00320 if (m_pPhysicsController1) 00321 { 00322 // in case this controller was added as a child shape to the parent 00323 if (rootobj != NULL && 00324 rootobj->m_pPhysicsController1 != NULL && 00325 rootobj->m_pPhysicsController1->IsCompound()) 00326 { 00327 rootobj->m_pPhysicsController1->RemoveCompoundChild(m_pPhysicsController1); 00328 } 00329 m_pPhysicsController1->RestoreDynamics(); 00330 if (m_pPhysicsController1->IsDyna() && (rootobj != NULL && rootobj->m_pPhysicsController1)) 00331 { 00332 // dynamic object should remember the velocity they had while being parented 00333 MT_Point3 childPoint = GetSGNode()->GetWorldPosition(); 00334 MT_Point3 rootPoint = rootobj->GetSGNode()->GetWorldPosition(); 00335 MT_Point3 relPoint; 00336 relPoint = (childPoint-rootPoint); 00337 MT_Vector3 linVel = rootobj->m_pPhysicsController1->GetVelocity(relPoint); 00338 MT_Vector3 angVel = rootobj->m_pPhysicsController1->GetAngularVelocity(); 00339 m_pPhysicsController1->SetLinearVelocity(linVel, false); 00340 m_pPhysicsController1->SetAngularVelocity(angVel, false); 00341 } 00342 } 00343 // graphically, the object hasn't change place, no need to update m_pGraphicController 00344 } 00345 } 00346 00347 void KX_GameObject::ProcessReplica() 00348 { 00349 SCA_IObject::ProcessReplica(); 00350 00351 m_pPhysicsController1 = NULL; 00352 m_pGraphicController = NULL; 00353 m_pSGNode = NULL; 00354 m_pClient_info = new KX_ClientObjectInfo(*m_pClient_info); 00355 m_pClient_info->m_gameobject = this; 00356 m_state = 0; 00357 00358 #ifdef WITH_PYTHON 00359 if(m_attr_dict) 00360 m_attr_dict= PyDict_Copy(m_attr_dict); 00361 #endif 00362 00363 } 00364 00365 static void setGraphicController_recursive(SG_Node* node) 00366 { 00367 NodeList& children = node->GetSGChildren(); 00368 00369 for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit) 00370 { 00371 SG_Node* childnode = (*childit); 00372 KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject()); 00373 if (clientgameobj != NULL) // This is a GameObject 00374 clientgameobj->ActivateGraphicController(false); 00375 00376 // if the childobj is NULL then this may be an inverse parent link 00377 // so a non recursive search should still look down this node. 00378 setGraphicController_recursive(childnode); 00379 } 00380 } 00381 00382 00383 void KX_GameObject::ActivateGraphicController(bool recurse) 00384 { 00385 if (m_pGraphicController) 00386 { 00387 m_pGraphicController->Activate(m_bVisible); 00388 } 00389 if (recurse) 00390 { 00391 setGraphicController_recursive(GetSGNode()); 00392 } 00393 } 00394 00395 00396 CValue* KX_GameObject::GetReplica() 00397 { 00398 KX_GameObject* replica = new KX_GameObject(*this); 00399 00400 // this will copy properties and so on... 00401 replica->ProcessReplica(); 00402 00403 return replica; 00404 } 00405 00406 00407 00408 void KX_GameObject::ApplyForce(const MT_Vector3& force,bool local) 00409 { 00410 if (m_pPhysicsController1) 00411 m_pPhysicsController1->ApplyForce(force,local); 00412 } 00413 00414 00415 00416 void KX_GameObject::ApplyTorque(const MT_Vector3& torque,bool local) 00417 { 00418 if (m_pPhysicsController1) 00419 m_pPhysicsController1->ApplyTorque(torque,local); 00420 } 00421 00422 00423 00424 void KX_GameObject::ApplyMovement(const MT_Vector3& dloc,bool local) 00425 { 00426 if (GetSGNode()) 00427 { 00428 if (m_pPhysicsController1) // (IsDynamic()) 00429 { 00430 m_pPhysicsController1->RelativeTranslate(dloc,local); 00431 } 00432 GetSGNode()->RelativeTranslate(dloc,GetSGNode()->GetSGParent(),local); 00433 } 00434 } 00435 00436 00437 00438 void KX_GameObject::ApplyRotation(const MT_Vector3& drot,bool local) 00439 { 00440 MT_Matrix3x3 rotmat(drot); 00441 00442 if (GetSGNode()) { 00443 GetSGNode()->RelativeRotate(rotmat,local); 00444 00445 if (m_pPhysicsController1) { // (IsDynamic()) 00446 m_pPhysicsController1->RelativeRotate(rotmat,local); 00447 } 00448 } 00449 } 00450 00451 00452 00456 double* KX_GameObject::GetOpenGLMatrix() 00457 { 00458 // todo: optimize and only update if necessary 00459 double* fl = m_OpenGL_4x4Matrix.getPointer(); 00460 if (GetSGNode()) { 00461 MT_Transform trans; 00462 00463 trans.setOrigin(GetSGNode()->GetWorldPosition()); 00464 trans.setBasis(GetSGNode()->GetWorldOrientation()); 00465 00466 MT_Vector3 scaling = GetSGNode()->GetWorldScaling(); 00467 m_bIsNegativeScaling = ((scaling[0] < 0.0) ^ (scaling[1] < 0.0) ^ (scaling[2] < 0.0)) ? true : false; 00468 trans.scale(scaling[0], scaling[1], scaling[2]); 00469 trans.getValue(fl); 00470 GetSGNode()->ClearDirty(); 00471 } 00472 return fl; 00473 } 00474 00475 void KX_GameObject::UpdateBlenderObjectMatrix(Object* blendobj) 00476 { 00477 if (!blendobj) 00478 blendobj = m_pBlenderObject; 00479 if (blendobj) { 00480 const MT_Matrix3x3& rot = NodeGetWorldOrientation(); 00481 const MT_Vector3& scale = NodeGetWorldScaling(); 00482 const MT_Vector3& pos = NodeGetWorldPosition(); 00483 rot.getValue(blendobj->obmat[0]); 00484 pos.getValue(blendobj->obmat[3]); 00485 mul_v3_fl(blendobj->obmat[0], scale[0]); 00486 mul_v3_fl(blendobj->obmat[1], scale[1]); 00487 mul_v3_fl(blendobj->obmat[2], scale[2]); 00488 } 00489 } 00490 00491 void KX_GameObject::AddMeshUser() 00492 { 00493 for (size_t i=0;i<m_meshes.size();i++) 00494 { 00495 m_meshes[i]->AddMeshUser(this, &m_meshSlots, GetDeformer()); 00496 } 00497 // set the part of the mesh slot that never change 00498 double* fl = GetOpenGLMatrixPtr()->getPointer(); 00499 00500 SG_QList::iterator<RAS_MeshSlot> mit(m_meshSlots); 00501 // RAS_MeshSlot* ms; 00502 for(mit.begin(); !mit.end(); ++mit) 00503 { 00504 (*mit)->m_OpenGLMatrix = fl; 00505 } 00506 UpdateBuckets(false); 00507 } 00508 00509 static void UpdateBuckets_recursive(SG_Node* node) 00510 { 00511 NodeList& children = node->GetSGChildren(); 00512 00513 for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit) 00514 { 00515 SG_Node* childnode = (*childit); 00516 KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject()); 00517 if (clientgameobj != NULL) // This is a GameObject 00518 clientgameobj->UpdateBuckets(0); 00519 00520 // if the childobj is NULL then this may be an inverse parent link 00521 // so a non recursive search should still look down this node. 00522 UpdateBuckets_recursive(childnode); 00523 } 00524 } 00525 00526 void KX_GameObject::UpdateBuckets( bool recursive ) 00527 { 00528 if (GetSGNode()) { 00529 RAS_MeshSlot *ms; 00530 00531 if (GetSGNode()->IsDirty()) 00532 GetOpenGLMatrix(); 00533 00534 SG_QList::iterator<RAS_MeshSlot> mit(m_meshSlots); 00535 for(mit.begin(); !mit.end(); ++mit) 00536 { 00537 ms = *mit; 00538 ms->m_bObjectColor = m_bUseObjectColor; 00539 ms->m_RGBAcolor = m_objectColor; 00540 ms->m_bVisible = m_bVisible; 00541 ms->m_bCulled = m_bCulled || !m_bVisible; 00542 if (!ms->m_bCulled) 00543 ms->m_bucket->ActivateMesh(ms); 00544 00545 /* split if necessary */ 00546 #ifdef USE_SPLIT 00547 ms->Split(); 00548 #endif 00549 } 00550 00551 if (recursive) { 00552 UpdateBuckets_recursive(GetSGNode()); 00553 } 00554 } 00555 } 00556 00557 void KX_GameObject::RemoveMeshes() 00558 { 00559 for (size_t i=0;i<m_meshes.size();i++) 00560 m_meshes[i]->RemoveFromBuckets(this); 00561 00562 //note: meshes can be shared, and are deleted by KX_BlenderSceneConverter 00563 00564 m_meshes.clear(); 00565 } 00566 00567 void KX_GameObject::UpdateTransform() 00568 { 00569 // HACK: saves function call for dynamic object, they are handled differently 00570 if (m_pPhysicsController1 && !m_pPhysicsController1->IsDyna()) 00571 // Note that for Bullet, this does not even update the transform of static object 00572 // but merely sets there collision flag to "kinematic" because the synchronization is 00573 // done during physics simulation 00574 m_pPhysicsController1->SetSumoTransform(true); 00575 if (m_pGraphicController) 00576 // update the culling tree 00577 m_pGraphicController->SetGraphicTransform(); 00578 00579 } 00580 00581 void KX_GameObject::UpdateTransformFunc(SG_IObject* node, void* gameobj, void* scene) 00582 { 00583 ((KX_GameObject*)gameobj)->UpdateTransform(); 00584 } 00585 00586 void KX_GameObject::SynchronizeTransform() 00587 { 00588 // only used for sensor object, do full synchronization as bullet doesn't do it 00589 if (m_pPhysicsController1) 00590 m_pPhysicsController1->SetTransform(); 00591 if (m_pGraphicController) 00592 m_pGraphicController->SetGraphicTransform(); 00593 } 00594 00595 void KX_GameObject::SynchronizeTransformFunc(SG_IObject* node, void* gameobj, void* scene) 00596 { 00597 ((KX_GameObject*)gameobj)->SynchronizeTransform(); 00598 } 00599 00600 00601 void KX_GameObject::SetDebugColor(unsigned int bgra) 00602 { 00603 for (size_t i=0;i<m_meshes.size();i++) 00604 m_meshes[i]->DebugColor(bgra); 00605 } 00606 00607 00608 00609 void KX_GameObject::ResetDebugColor() 00610 { 00611 SetDebugColor(0xff000000); 00612 } 00613 00614 void KX_GameObject::InitIPO(bool ipo_as_force, 00615 bool ipo_add, 00616 bool ipo_local) 00617 { 00618 SGControllerList::iterator it = GetSGNode()->GetSGControllerList().begin(); 00619 00620 while (it != GetSGNode()->GetSGControllerList().end()) { 00621 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_RESET, true); 00622 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_AS_FORCE, ipo_as_force); 00623 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_ADD, ipo_add); 00624 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_LOCAL, ipo_local); 00625 it++; 00626 } 00627 } 00628 00629 void KX_GameObject::UpdateIPO(float curframetime, 00630 bool recurse) 00631 { 00632 // just the 'normal' update procedure. 00633 GetSGNode()->SetSimulatedTime(curframetime,recurse); 00634 GetSGNode()->UpdateWorldData(curframetime); 00635 UpdateTransform(); 00636 } 00637 00638 // IPO update 00639 void 00640 KX_GameObject::UpdateMaterialData( 00641 dword matname_hash, 00642 MT_Vector4 rgba, 00643 MT_Vector3 specrgb, 00644 MT_Scalar hard, 00645 MT_Scalar spec, 00646 MT_Scalar ref, 00647 MT_Scalar emit, 00648 MT_Scalar alpha 00649 00650 ) 00651 { 00652 int mesh = 0; 00653 if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0) { 00654 list<RAS_MeshMaterial>::iterator mit = m_meshes[mesh]->GetFirstMaterial(); 00655 00656 for(; mit != m_meshes[mesh]->GetLastMaterial(); ++mit) 00657 { 00658 RAS_IPolyMaterial* poly = mit->m_bucket->GetPolyMaterial(); 00659 00660 if(poly->GetFlag() & RAS_BLENDERMAT ) 00661 { 00662 KX_BlenderMaterial *m = static_cast<KX_BlenderMaterial*>(poly); 00663 00664 if (matname_hash == 0) 00665 { 00666 m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha); 00667 // if mesh has only one material attached to it then use original hack with no need to edit vertices (better performance) 00668 SetObjectColor(rgba); 00669 } 00670 else 00671 { 00672 if (matname_hash == poly->GetMaterialNameHash()) 00673 { 00674 m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha); 00675 m_meshes[mesh]->SetVertexColor(poly,rgba); 00676 00677 // no break here, because one blender material can be split into several game engine materials 00678 // (e.g. one uvsphere material is split into one material at poles with ras_mode TRIANGLE and one material for the body 00679 // if here was a break then would miss some vertices if material was split 00680 } 00681 } 00682 } 00683 } 00684 } 00685 } 00686 bool 00687 KX_GameObject::GetVisible( 00688 void 00689 ) 00690 { 00691 return m_bVisible; 00692 } 00693 00694 static void setVisible_recursive(SG_Node* node, bool v) 00695 { 00696 NodeList& children = node->GetSGChildren(); 00697 00698 for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit) 00699 { 00700 SG_Node* childnode = (*childit); 00701 KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject()); 00702 if (clientgameobj != NULL) // This is a GameObject 00703 clientgameobj->SetVisible(v, 0); 00704 00705 // if the childobj is NULL then this may be an inverse parent link 00706 // so a non recursive search should still look down this node. 00707 setVisible_recursive(childnode, v); 00708 } 00709 } 00710 00711 00712 void 00713 KX_GameObject::SetVisible( 00714 bool v, 00715 bool recursive 00716 ) 00717 { 00718 if (GetSGNode()) { 00719 m_bVisible = v; 00720 if (m_pGraphicController) 00721 m_pGraphicController->Activate(m_bVisible); 00722 if (recursive) 00723 setVisible_recursive(GetSGNode(), v); 00724 } 00725 } 00726 00727 static void setOccluder_recursive(SG_Node* node, bool v) 00728 { 00729 NodeList& children = node->GetSGChildren(); 00730 00731 for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit) 00732 { 00733 SG_Node* childnode = (*childit); 00734 KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject()); 00735 if (clientgameobj != NULL) // This is a GameObject 00736 clientgameobj->SetOccluder(v, false); 00737 00738 // if the childobj is NULL then this may be an inverse parent link 00739 // so a non recursive search should still look down this node. 00740 setOccluder_recursive(childnode, v); 00741 } 00742 } 00743 00744 void 00745 KX_GameObject::SetOccluder( 00746 bool v, 00747 bool recursive 00748 ) 00749 { 00750 if (GetSGNode()) { 00751 m_bOccluder = v; 00752 if (recursive) 00753 setOccluder_recursive(GetSGNode(), v); 00754 } 00755 } 00756 00757 void 00758 KX_GameObject::SetLayer( 00759 int l 00760 ) 00761 { 00762 m_layer = l; 00763 } 00764 00765 int 00766 KX_GameObject::GetLayer( 00767 void 00768 ) 00769 { 00770 return m_layer; 00771 } 00772 00773 void KX_GameObject::addLinearVelocity(const MT_Vector3& lin_vel,bool local) 00774 { 00775 if (m_pPhysicsController1) 00776 { 00777 MT_Vector3 lv = local ? NodeGetWorldOrientation() * lin_vel : lin_vel; 00778 m_pPhysicsController1->SetLinearVelocity(lv + m_pPhysicsController1->GetLinearVelocity(), 0); 00779 } 00780 } 00781 00782 00783 00784 void KX_GameObject::setLinearVelocity(const MT_Vector3& lin_vel,bool local) 00785 { 00786 if (m_pPhysicsController1) 00787 m_pPhysicsController1->SetLinearVelocity(lin_vel,local); 00788 } 00789 00790 00791 00792 void KX_GameObject::setAngularVelocity(const MT_Vector3& ang_vel,bool local) 00793 { 00794 if (m_pPhysicsController1) 00795 m_pPhysicsController1->SetAngularVelocity(ang_vel,local); 00796 } 00797 00798 00799 void KX_GameObject::ResolveCombinedVelocities( 00800 const MT_Vector3 & lin_vel, 00801 const MT_Vector3 & ang_vel, 00802 bool lin_vel_local, 00803 bool ang_vel_local 00804 ){ 00805 if (m_pPhysicsController1) 00806 { 00807 00808 MT_Vector3 lv = lin_vel_local ? NodeGetWorldOrientation() * lin_vel : lin_vel; 00809 MT_Vector3 av = ang_vel_local ? NodeGetWorldOrientation() * ang_vel : ang_vel; 00810 m_pPhysicsController1->resolveCombinedVelocities( 00811 lv.x(),lv.y(),lv.z(),av.x(),av.y(),av.z()); 00812 } 00813 } 00814 00815 00816 void KX_GameObject::SetObjectColor(const MT_Vector4& rgbavec) 00817 { 00818 m_bUseObjectColor = true; 00819 m_objectColor = rgbavec; 00820 } 00821 00822 const MT_Vector4& KX_GameObject::GetObjectColor() 00823 { 00824 return m_objectColor; 00825 } 00826 00827 void KX_GameObject::AlignAxisToVect(const MT_Vector3& dir, int axis, float fac) 00828 { 00829 MT_Matrix3x3 orimat; 00830 MT_Vector3 vect,ori,z,x,y; 00831 MT_Scalar len; 00832 00833 // check on valid node in case a python controller holds a reference to a deleted object 00834 if (!GetSGNode()) 00835 return; 00836 00837 vect = dir; 00838 len = vect.length(); 00839 if (MT_fuzzyZero(len)) 00840 { 00841 cout << "alignAxisToVect() Error: Null vector!\n"; 00842 return; 00843 } 00844 00845 if (fac<=0.0) { 00846 return; 00847 } 00848 00849 // normalize 00850 vect /= len; 00851 orimat = GetSGNode()->GetWorldOrientation(); 00852 switch (axis) 00853 { 00854 case 0: //x axis 00855 ori.setValue(orimat[0][2], orimat[1][2], orimat[2][2]); //pivot axis 00856 if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON) //is the vector parallel to the pivot? 00857 ori.setValue(orimat[0][1], orimat[1][1], orimat[2][1]); //change the pivot! 00858 if (fac == 1.0) { 00859 x = vect; 00860 } else { 00861 x = (vect * fac) + ((orimat * MT_Vector3(1.0, 0.0, 0.0)) * (1-fac)); 00862 len = x.length(); 00863 if (MT_fuzzyZero(len)) x = vect; 00864 else x /= len; 00865 } 00866 y = ori.cross(x); 00867 z = x.cross(y); 00868 break; 00869 case 1: //y axis 00870 ori.setValue(orimat[0][0], orimat[1][0], orimat[2][0]); 00871 if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON) 00872 ori.setValue(orimat[0][2], orimat[1][2], orimat[2][2]); 00873 if (fac == 1.0) { 00874 y = vect; 00875 } else { 00876 y = (vect * fac) + ((orimat * MT_Vector3(0.0, 1.0, 0.0)) * (1-fac)); 00877 len = y.length(); 00878 if (MT_fuzzyZero(len)) y = vect; 00879 else y /= len; 00880 } 00881 z = ori.cross(y); 00882 x = y.cross(z); 00883 break; 00884 case 2: //z axis 00885 ori.setValue(orimat[0][1], orimat[1][1], orimat[2][1]); 00886 if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON) 00887 ori.setValue(orimat[0][0], orimat[1][0], orimat[2][0]); 00888 if (fac == 1.0) { 00889 z = vect; 00890 } else { 00891 z = (vect * fac) + ((orimat * MT_Vector3(0.0, 0.0, 1.0)) * (1-fac)); 00892 len = z.length(); 00893 if (MT_fuzzyZero(len)) z = vect; 00894 else z /= len; 00895 } 00896 x = ori.cross(z); 00897 y = z.cross(x); 00898 break; 00899 default: //wrong input? 00900 cout << "alignAxisToVect(): Wrong axis '" << axis <<"'\n"; 00901 return; 00902 } 00903 x.normalize(); //normalize the vectors 00904 y.normalize(); 00905 z.normalize(); 00906 orimat.setValue( x[0],y[0],z[0], 00907 x[1],y[1],z[1], 00908 x[2],y[2],z[2]); 00909 if (GetSGNode()->GetSGParent() != NULL) 00910 { 00911 // the object is a child, adapt its local orientation so that 00912 // the global orientation is aligned as we want. 00913 MT_Matrix3x3 invori = GetSGNode()->GetSGParent()->GetWorldOrientation().inverse(); 00914 NodeSetLocalOrientation(invori*orimat); 00915 } 00916 else 00917 NodeSetLocalOrientation(orimat); 00918 } 00919 00920 MT_Scalar KX_GameObject::GetMass() 00921 { 00922 if (m_pPhysicsController1) 00923 { 00924 return m_pPhysicsController1->GetMass(); 00925 } 00926 return 0.0; 00927 } 00928 00929 MT_Vector3 KX_GameObject::GetLocalInertia() 00930 { 00931 MT_Vector3 local_inertia(0.0,0.0,0.0); 00932 if (m_pPhysicsController1) 00933 { 00934 local_inertia = m_pPhysicsController1->GetLocalInertia(); 00935 } 00936 return local_inertia; 00937 } 00938 00939 MT_Vector3 KX_GameObject::GetLinearVelocity(bool local) 00940 { 00941 MT_Vector3 velocity(0.0,0.0,0.0), locvel; 00942 MT_Matrix3x3 ori; 00943 if (m_pPhysicsController1) 00944 { 00945 velocity = m_pPhysicsController1->GetLinearVelocity(); 00946 00947 if (local) 00948 { 00949 ori = GetSGNode()->GetWorldOrientation(); 00950 00951 locvel = velocity * ori; 00952 return locvel; 00953 } 00954 } 00955 return velocity; 00956 } 00957 00958 MT_Vector3 KX_GameObject::GetAngularVelocity(bool local) 00959 { 00960 MT_Vector3 velocity(0.0,0.0,0.0), locvel; 00961 MT_Matrix3x3 ori; 00962 if (m_pPhysicsController1) 00963 { 00964 velocity = m_pPhysicsController1->GetAngularVelocity(); 00965 00966 if (local) 00967 { 00968 ori = GetSGNode()->GetWorldOrientation(); 00969 00970 locvel = velocity * ori; 00971 return locvel; 00972 } 00973 } 00974 return velocity; 00975 } 00976 00977 MT_Vector3 KX_GameObject::GetVelocity(const MT_Point3& point) 00978 { 00979 if (m_pPhysicsController1) 00980 { 00981 return m_pPhysicsController1->GetVelocity(point); 00982 } 00983 return MT_Vector3(0.0,0.0,0.0); 00984 } 00985 00986 // scenegraph node stuff 00987 00988 void KX_GameObject::NodeSetLocalPosition(const MT_Point3& trans) 00989 { 00990 // check on valid node in case a python controller holds a reference to a deleted object 00991 if (!GetSGNode()) 00992 return; 00993 00994 if (m_pPhysicsController1 && !GetSGNode()->GetSGParent()) 00995 { 00996 // don't update physic controller if the object is a child: 00997 // 1) the transformation will not be right 00998 // 2) in this case, the physic controller is necessarily a static object 00999 // that is updated from the normal kinematic synchronization 01000 m_pPhysicsController1->setPosition(trans); 01001 } 01002 01003 GetSGNode()->SetLocalPosition(trans); 01004 01005 } 01006 01007 01008 01009 void KX_GameObject::NodeSetLocalOrientation(const MT_Matrix3x3& rot) 01010 { 01011 // check on valid node in case a python controller holds a reference to a deleted object 01012 if (!GetSGNode()) 01013 return; 01014 01015 if (m_pPhysicsController1 && !GetSGNode()->GetSGParent()) 01016 { 01017 // see note above 01018 m_pPhysicsController1->setOrientation(rot); 01019 } 01020 GetSGNode()->SetLocalOrientation(rot); 01021 } 01022 01023 void KX_GameObject::NodeSetGlobalOrientation(const MT_Matrix3x3& rot) 01024 { 01025 // check on valid node in case a python controller holds a reference to a deleted object 01026 if (!GetSGNode()) 01027 return; 01028 01029 if (GetSGNode()->GetSGParent()) 01030 GetSGNode()->SetLocalOrientation(GetSGNode()->GetSGParent()->GetWorldOrientation().inverse()*rot); 01031 else 01032 NodeSetLocalOrientation(rot); 01033 } 01034 01035 void KX_GameObject::NodeSetLocalScale(const MT_Vector3& scale) 01036 { 01037 // check on valid node in case a python controller holds a reference to a deleted object 01038 if (!GetSGNode()) 01039 return; 01040 01041 if (m_pPhysicsController1 && !GetSGNode()->GetSGParent()) 01042 { 01043 // see note above 01044 m_pPhysicsController1->setScaling(scale); 01045 } 01046 GetSGNode()->SetLocalScale(scale); 01047 } 01048 01049 01050 01051 void KX_GameObject::NodeSetRelativeScale(const MT_Vector3& scale) 01052 { 01053 if (GetSGNode()) 01054 { 01055 GetSGNode()->RelativeScale(scale); 01056 if (m_pPhysicsController1 && (!GetSGNode()->GetSGParent())) 01057 { 01058 // see note above 01059 // we can use the local scale: it's the same thing for a root object 01060 // and the world scale is not yet updated 01061 MT_Vector3 newscale = GetSGNode()->GetLocalScale(); 01062 m_pPhysicsController1->setScaling(newscale); 01063 } 01064 } 01065 } 01066 01067 void KX_GameObject::NodeSetWorldPosition(const MT_Point3& trans) 01068 { 01069 if (!GetSGNode()) 01070 return; 01071 SG_Node* parent = GetSGNode()->GetSGParent(); 01072 if (parent != NULL) 01073 { 01074 // Make sure the objects have some scale 01075 MT_Vector3 scale = parent->GetWorldScaling(); 01076 if (fabs(scale[0]) < FLT_EPSILON || 01077 fabs(scale[1]) < FLT_EPSILON || 01078 fabs(scale[2]) < FLT_EPSILON) 01079 { 01080 return; 01081 } 01082 scale[0] = 1.0/scale[0]; 01083 scale[1] = 1.0/scale[1]; 01084 scale[2] = 1.0/scale[2]; 01085 MT_Matrix3x3 invori = parent->GetWorldOrientation().inverse(); 01086 MT_Vector3 newpos = invori*(trans-parent->GetWorldPosition())*scale; 01087 NodeSetLocalPosition(MT_Point3(newpos[0],newpos[1],newpos[2])); 01088 } 01089 else 01090 { 01091 NodeSetLocalPosition(trans); 01092 } 01093 } 01094 01095 01096 void KX_GameObject::NodeUpdateGS(double time) 01097 { 01098 if (GetSGNode()) 01099 GetSGNode()->UpdateWorldData(time); 01100 } 01101 01102 01103 01104 const MT_Matrix3x3& KX_GameObject::NodeGetWorldOrientation() const 01105 { 01106 // check on valid node in case a python controller holds a reference to a deleted object 01107 if (!GetSGNode()) 01108 return dummy_orientation; 01109 return GetSGNode()->GetWorldOrientation(); 01110 } 01111 01112 const MT_Matrix3x3& KX_GameObject::NodeGetLocalOrientation() const 01113 { 01114 // check on valid node in case a python controller holds a reference to a deleted object 01115 if (!GetSGNode()) 01116 return dummy_orientation; 01117 return GetSGNode()->GetLocalOrientation(); 01118 } 01119 01120 const MT_Vector3& KX_GameObject::NodeGetWorldScaling() const 01121 { 01122 // check on valid node in case a python controller holds a reference to a deleted object 01123 if (!GetSGNode()) 01124 return dummy_scaling; 01125 01126 return GetSGNode()->GetWorldScaling(); 01127 } 01128 01129 const MT_Vector3& KX_GameObject::NodeGetLocalScaling() const 01130 { 01131 // check on valid node in case a python controller holds a reference to a deleted object 01132 if (!GetSGNode()) 01133 return dummy_scaling; 01134 01135 return GetSGNode()->GetLocalScale(); 01136 } 01137 01138 const MT_Point3& KX_GameObject::NodeGetWorldPosition() const 01139 { 01140 // check on valid node in case a python controller holds a reference to a deleted object 01141 if (GetSGNode()) 01142 return GetSGNode()->GetWorldPosition(); 01143 else 01144 return dummy_point; 01145 } 01146 01147 const MT_Point3& KX_GameObject::NodeGetLocalPosition() const 01148 { 01149 // check on valid node in case a python controller holds a reference to a deleted object 01150 if (GetSGNode()) 01151 return GetSGNode()->GetLocalPosition(); 01152 else 01153 return dummy_point; 01154 } 01155 01156 01157 /* Suspend/ resume: for the dynamic behaviour, there is a simple 01158 * method. For the residual motion, there is not. I wonder what the 01159 * correct solution is for Sumo. Remove from the motion-update tree? 01160 * 01161 * So far, only switch the physics and logic. 01162 * */ 01163 01164 void KX_GameObject::Resume(void) 01165 { 01166 if (m_suspended) { 01167 SCA_IObject::Resume(); 01168 if(GetPhysicsController()) 01169 GetPhysicsController()->RestoreDynamics(); 01170 01171 m_suspended = false; 01172 } 01173 } 01174 01175 void KX_GameObject::Suspend() 01176 { 01177 if ((!m_ignore_activity_culling) 01178 && (!m_suspended)) { 01179 SCA_IObject::Suspend(); 01180 if(GetPhysicsController()) 01181 GetPhysicsController()->SuspendDynamics(); 01182 m_suspended = true; 01183 } 01184 } 01185 01186 static void walk_children(SG_Node* node, CListValue* list, bool recursive) 01187 { 01188 if (!node) 01189 return; 01190 NodeList& children = node->GetSGChildren(); 01191 01192 for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit) 01193 { 01194 SG_Node* childnode = (*childit); 01195 CValue* childobj = (CValue*)childnode->GetSGClientObject(); 01196 if (childobj != NULL) // This is a GameObject 01197 { 01198 // add to the list 01199 list->Add(childobj->AddRef()); 01200 } 01201 01202 // if the childobj is NULL then this may be an inverse parent link 01203 // so a non recursive search should still look down this node. 01204 if (recursive || childobj==NULL) { 01205 walk_children(childnode, list, recursive); 01206 } 01207 } 01208 } 01209 01210 CListValue* KX_GameObject::GetChildren() 01211 { 01212 CListValue* list = new CListValue(); 01213 walk_children(GetSGNode(), list, 0); /* GetSGNode() is always valid or it would have raised an exception before this */ 01214 return list; 01215 } 01216 01217 CListValue* KX_GameObject::GetChildrenRecursive() 01218 { 01219 CListValue* list = new CListValue(); 01220 walk_children(GetSGNode(), list, 1); 01221 return list; 01222 } 01223 01224 /* --------------------------------------------------------------------- 01225 * Some stuff taken from the header 01226 * --------------------------------------------------------------------- */ 01227 void KX_GameObject::Relink(CTR_Map<CTR_HashedPtr, void*> *map_parameter) 01228 { 01229 // we will relink the sensors and actuators that use object references 01230 // if the object is part of the replicated hierarchy, use the new 01231 // object reference instead 01232 SCA_SensorList& sensorlist = GetSensors(); 01233 SCA_SensorList::iterator sit; 01234 for (sit=sensorlist.begin(); sit != sensorlist.end(); sit++) 01235 { 01236 (*sit)->Relink(map_parameter); 01237 } 01238 SCA_ActuatorList& actuatorlist = GetActuators(); 01239 SCA_ActuatorList::iterator ait; 01240 for (ait=actuatorlist.begin(); ait != actuatorlist.end(); ait++) 01241 { 01242 (*ait)->Relink(map_parameter); 01243 } 01244 } 01245 01246 #ifdef USE_MATHUTILS 01247 01248 /* These require an SGNode */ 01249 #define MATHUTILS_VEC_CB_POS_LOCAL 1 01250 #define MATHUTILS_VEC_CB_POS_GLOBAL 2 01251 #define MATHUTILS_VEC_CB_SCALE_LOCAL 3 01252 #define MATHUTILS_VEC_CB_SCALE_GLOBAL 4 01253 #define MATHUTILS_VEC_CB_INERTIA_LOCAL 5 01254 #define MATHUTILS_VEC_CB_OBJECT_COLOR 6 01255 #define MATHUTILS_VEC_CB_LINVEL_LOCAL 7 01256 #define MATHUTILS_VEC_CB_LINVEL_GLOBAL 8 01257 #define MATHUTILS_VEC_CB_ANGVEL_LOCAL 9 01258 #define MATHUTILS_VEC_CB_ANGVEL_GLOBAL 10 01259 01260 static int mathutils_kxgameob_vector_cb_index= -1; /* index for our callbacks */ 01261 01262 static int mathutils_kxgameob_generic_check(BaseMathObject *bmo) 01263 { 01264 KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(bmo->cb_user); 01265 if(self==NULL) 01266 return -1; 01267 01268 return 0; 01269 } 01270 01271 static int mathutils_kxgameob_vector_get(BaseMathObject *bmo, int subtype) 01272 { 01273 KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(bmo->cb_user); 01274 if(self==NULL) 01275 return -1; 01276 01277 #define PHYS_ERR(attr) PyErr_SetString(PyExc_AttributeError, "KX_GameObject." attr ", is missing a physics controller") 01278 01279 switch(subtype) { 01280 case MATHUTILS_VEC_CB_POS_LOCAL: 01281 self->NodeGetLocalPosition().getValue(bmo->data); 01282 break; 01283 case MATHUTILS_VEC_CB_POS_GLOBAL: 01284 self->NodeGetWorldPosition().getValue(bmo->data); 01285 break; 01286 case MATHUTILS_VEC_CB_SCALE_LOCAL: 01287 self->NodeGetLocalScaling().getValue(bmo->data); 01288 break; 01289 case MATHUTILS_VEC_CB_SCALE_GLOBAL: 01290 self->NodeGetWorldScaling().getValue(bmo->data); 01291 break; 01292 case MATHUTILS_VEC_CB_INERTIA_LOCAL: 01293 if(!self->GetPhysicsController()) return PHYS_ERR("localInertia"), -1; 01294 self->GetPhysicsController()->GetLocalInertia().getValue(bmo->data); 01295 break; 01296 case MATHUTILS_VEC_CB_OBJECT_COLOR: 01297 self->GetObjectColor().getValue(bmo->data); 01298 break; 01299 case MATHUTILS_VEC_CB_LINVEL_LOCAL: 01300 if(!self->GetPhysicsController()) return PHYS_ERR("localLinearVelocity"), -1; 01301 self->GetLinearVelocity(true).getValue(bmo->data); 01302 break; 01303 case MATHUTILS_VEC_CB_LINVEL_GLOBAL: 01304 if(!self->GetPhysicsController()) return PHYS_ERR("worldLinearVelocity"), -1; 01305 self->GetLinearVelocity(false).getValue(bmo->data); 01306 break; 01307 case MATHUTILS_VEC_CB_ANGVEL_LOCAL: 01308 if(!self->GetPhysicsController()) return PHYS_ERR("localLinearVelocity"), -1; 01309 self->GetAngularVelocity(true).getValue(bmo->data); 01310 break; 01311 case MATHUTILS_VEC_CB_ANGVEL_GLOBAL: 01312 if(!self->GetPhysicsController()) return PHYS_ERR("worldLinearVelocity"), -1; 01313 self->GetAngularVelocity(false).getValue(bmo->data); 01314 break; 01315 01316 } 01317 01318 #undef PHYS_ERR 01319 01320 return 0; 01321 } 01322 01323 static int mathutils_kxgameob_vector_set(BaseMathObject *bmo, int subtype) 01324 { 01325 KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(bmo->cb_user); 01326 if(self==NULL) 01327 return -1; 01328 01329 switch(subtype) { 01330 case MATHUTILS_VEC_CB_POS_LOCAL: 01331 self->NodeSetLocalPosition(MT_Point3(bmo->data)); 01332 self->NodeUpdateGS(0.f); 01333 break; 01334 case MATHUTILS_VEC_CB_POS_GLOBAL: 01335 self->NodeSetWorldPosition(MT_Point3(bmo->data)); 01336 self->NodeUpdateGS(0.f); 01337 break; 01338 case MATHUTILS_VEC_CB_SCALE_LOCAL: 01339 self->NodeSetLocalScale(MT_Point3(bmo->data)); 01340 self->NodeUpdateGS(0.f); 01341 break; 01342 case MATHUTILS_VEC_CB_SCALE_GLOBAL: 01343 PyErr_SetString(PyExc_AttributeError, "KX_GameObject.worldScale is read-only"); 01344 return -1; 01345 case MATHUTILS_VEC_CB_INERTIA_LOCAL: 01346 /* read only */ 01347 break; 01348 case MATHUTILS_VEC_CB_OBJECT_COLOR: 01349 self->SetObjectColor(MT_Vector4(bmo->data)); 01350 break; 01351 case MATHUTILS_VEC_CB_LINVEL_LOCAL: 01352 self->setLinearVelocity(MT_Point3(bmo->data),true); 01353 break; 01354 case MATHUTILS_VEC_CB_LINVEL_GLOBAL: 01355 self->setLinearVelocity(MT_Point3(bmo->data),false); 01356 break; 01357 case MATHUTILS_VEC_CB_ANGVEL_LOCAL: 01358 self->setAngularVelocity(MT_Point3(bmo->data),true); 01359 break; 01360 case MATHUTILS_VEC_CB_ANGVEL_GLOBAL: 01361 self->setAngularVelocity(MT_Point3(bmo->data),false); 01362 break; 01363 } 01364 01365 return 0; 01366 } 01367 01368 static int mathutils_kxgameob_vector_get_index(BaseMathObject *bmo, int subtype, int index) 01369 { 01370 /* lazy, avoid repeteing the case statement */ 01371 if(mathutils_kxgameob_vector_get(bmo, subtype) == -1) 01372 return -1; 01373 return 0; 01374 } 01375 01376 static int mathutils_kxgameob_vector_set_index(BaseMathObject *bmo, int subtype, int index) 01377 { 01378 float f= bmo->data[index]; 01379 01380 /* lazy, avoid repeteing the case statement */ 01381 if(mathutils_kxgameob_vector_get(bmo, subtype) == -1) 01382 return -1; 01383 01384 bmo->data[index]= f; 01385 return mathutils_kxgameob_vector_set(bmo, subtype); 01386 } 01387 01388 Mathutils_Callback mathutils_kxgameob_vector_cb = { 01389 mathutils_kxgameob_generic_check, 01390 mathutils_kxgameob_vector_get, 01391 mathutils_kxgameob_vector_set, 01392 mathutils_kxgameob_vector_get_index, 01393 mathutils_kxgameob_vector_set_index 01394 }; 01395 01396 /* Matrix */ 01397 #define MATHUTILS_MAT_CB_ORI_LOCAL 1 01398 #define MATHUTILS_MAT_CB_ORI_GLOBAL 2 01399 01400 static int mathutils_kxgameob_matrix_cb_index= -1; /* index for our callbacks */ 01401 01402 static int mathutils_kxgameob_matrix_get(BaseMathObject *bmo, int subtype) 01403 { 01404 KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(bmo->cb_user); 01405 if(self==NULL) 01406 return -1; 01407 01408 switch(subtype) { 01409 case MATHUTILS_MAT_CB_ORI_LOCAL: 01410 self->NodeGetLocalOrientation().getValue3x3(bmo->data); 01411 break; 01412 case MATHUTILS_MAT_CB_ORI_GLOBAL: 01413 self->NodeGetWorldOrientation().getValue3x3(bmo->data); 01414 break; 01415 } 01416 01417 return 0; 01418 } 01419 01420 01421 static int mathutils_kxgameob_matrix_set(BaseMathObject *bmo, int subtype) 01422 { 01423 KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(bmo->cb_user); 01424 if(self==NULL) 01425 return -1; 01426 01427 MT_Matrix3x3 mat3x3; 01428 switch(subtype) { 01429 case MATHUTILS_MAT_CB_ORI_LOCAL: 01430 mat3x3.setValue3x3(bmo->data); 01431 self->NodeSetLocalOrientation(mat3x3); 01432 self->NodeUpdateGS(0.f); 01433 break; 01434 case MATHUTILS_MAT_CB_ORI_GLOBAL: 01435 mat3x3.setValue3x3(bmo->data); 01436 self->NodeSetLocalOrientation(mat3x3); 01437 self->NodeUpdateGS(0.f); 01438 break; 01439 } 01440 01441 return 0; 01442 } 01443 01444 Mathutils_Callback mathutils_kxgameob_matrix_cb = { 01445 mathutils_kxgameob_generic_check, 01446 mathutils_kxgameob_matrix_get, 01447 mathutils_kxgameob_matrix_set, 01448 NULL, 01449 NULL 01450 }; 01451 01452 01453 void KX_GameObject_Mathutils_Callback_Init(void) 01454 { 01455 // register mathutils callbacks, ok to run more then once. 01456 mathutils_kxgameob_vector_cb_index= Mathutils_RegisterCallback(&mathutils_kxgameob_vector_cb); 01457 mathutils_kxgameob_matrix_cb_index= Mathutils_RegisterCallback(&mathutils_kxgameob_matrix_cb); 01458 } 01459 01460 #endif // USE_MATHUTILS 01461 01462 #ifdef WITH_PYTHON 01463 /* ------- python stuff ---------------------------------------------------*/ 01464 PyMethodDef KX_GameObject::Methods[] = { 01465 {"applyForce", (PyCFunction) KX_GameObject::sPyApplyForce, METH_VARARGS}, 01466 {"applyTorque", (PyCFunction) KX_GameObject::sPyApplyTorque, METH_VARARGS}, 01467 {"applyRotation", (PyCFunction) KX_GameObject::sPyApplyRotation, METH_VARARGS}, 01468 {"applyMovement", (PyCFunction) KX_GameObject::sPyApplyMovement, METH_VARARGS}, 01469 {"getLinearVelocity", (PyCFunction) KX_GameObject::sPyGetLinearVelocity, METH_VARARGS}, 01470 {"setLinearVelocity", (PyCFunction) KX_GameObject::sPySetLinearVelocity, METH_VARARGS}, 01471 {"getAngularVelocity", (PyCFunction) KX_GameObject::sPyGetAngularVelocity, METH_VARARGS}, 01472 {"setAngularVelocity", (PyCFunction) KX_GameObject::sPySetAngularVelocity, METH_VARARGS}, 01473 {"getVelocity", (PyCFunction) KX_GameObject::sPyGetVelocity, METH_VARARGS}, 01474 {"getReactionForce", (PyCFunction) KX_GameObject::sPyGetReactionForce, METH_NOARGS}, 01475 {"alignAxisToVect",(PyCFunction) KX_GameObject::sPyAlignAxisToVect, METH_VARARGS}, 01476 {"getAxisVect",(PyCFunction) KX_GameObject::sPyGetAxisVect, METH_O}, 01477 {"suspendDynamics", (PyCFunction)KX_GameObject::sPySuspendDynamics,METH_NOARGS}, 01478 {"restoreDynamics", (PyCFunction)KX_GameObject::sPyRestoreDynamics,METH_NOARGS}, 01479 {"enableRigidBody", (PyCFunction)KX_GameObject::sPyEnableRigidBody,METH_NOARGS}, 01480 {"disableRigidBody", (PyCFunction)KX_GameObject::sPyDisableRigidBody,METH_NOARGS}, 01481 {"applyImpulse", (PyCFunction) KX_GameObject::sPyApplyImpulse, METH_VARARGS}, 01482 {"setCollisionMargin", (PyCFunction) KX_GameObject::sPySetCollisionMargin, METH_O}, 01483 {"setParent", (PyCFunction)KX_GameObject::sPySetParent,METH_VARARGS}, 01484 {"setVisible",(PyCFunction) KX_GameObject::sPySetVisible, METH_VARARGS}, 01485 {"setOcclusion",(PyCFunction) KX_GameObject::sPySetOcclusion, METH_VARARGS}, 01486 {"removeParent", (PyCFunction)KX_GameObject::sPyRemoveParent,METH_NOARGS}, 01487 01488 01489 {"getPhysicsId", (PyCFunction)KX_GameObject::sPyGetPhysicsId,METH_NOARGS}, 01490 {"getPropertyNames", (PyCFunction)KX_GameObject::sPyGetPropertyNames,METH_NOARGS}, 01491 {"replaceMesh",(PyCFunction) KX_GameObject::sPyReplaceMesh, METH_VARARGS}, 01492 {"endObject",(PyCFunction) KX_GameObject::sPyEndObject, METH_NOARGS}, 01493 {"reinstancePhysicsMesh", (PyCFunction)KX_GameObject::sPyReinstancePhysicsMesh,METH_VARARGS}, 01494 01495 KX_PYMETHODTABLE(KX_GameObject, rayCastTo), 01496 KX_PYMETHODTABLE(KX_GameObject, rayCast), 01497 KX_PYMETHODTABLE_O(KX_GameObject, getDistanceTo), 01498 KX_PYMETHODTABLE_O(KX_GameObject, getVectTo), 01499 KX_PYMETHODTABLE(KX_GameObject, sendMessage), 01500 01501 // dict style access for props 01502 {"get",(PyCFunction) KX_GameObject::sPyget, METH_VARARGS}, 01503 01504 {NULL,NULL} //Sentinel 01505 }; 01506 01507 PyAttributeDef KX_GameObject::Attributes[] = { 01508 KX_PYATTRIBUTE_RO_FUNCTION("name", KX_GameObject, pyattr_get_name), 01509 KX_PYATTRIBUTE_RO_FUNCTION("parent", KX_GameObject, pyattr_get_parent), 01510 KX_PYATTRIBUTE_RO_FUNCTION("life", KX_GameObject, pyattr_get_life), 01511 KX_PYATTRIBUTE_RW_FUNCTION("mass", KX_GameObject, pyattr_get_mass, pyattr_set_mass), 01512 KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMin", KX_GameObject, pyattr_get_lin_vel_min, pyattr_set_lin_vel_min), 01513 KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMax", KX_GameObject, pyattr_get_lin_vel_max, pyattr_set_lin_vel_max), 01514 KX_PYATTRIBUTE_RW_FUNCTION("visible", KX_GameObject, pyattr_get_visible, pyattr_set_visible), 01515 KX_PYATTRIBUTE_BOOL_RW ("occlusion", KX_GameObject, m_bOccluder), 01516 KX_PYATTRIBUTE_RW_FUNCTION("position", KX_GameObject, pyattr_get_worldPosition, pyattr_set_localPosition), 01517 KX_PYATTRIBUTE_RO_FUNCTION("localInertia", KX_GameObject, pyattr_get_localInertia), 01518 KX_PYATTRIBUTE_RW_FUNCTION("orientation",KX_GameObject,pyattr_get_worldOrientation,pyattr_set_localOrientation), 01519 KX_PYATTRIBUTE_RW_FUNCTION("scaling", KX_GameObject, pyattr_get_worldScaling, pyattr_set_localScaling), 01520 KX_PYATTRIBUTE_RW_FUNCTION("timeOffset",KX_GameObject, pyattr_get_timeOffset,pyattr_set_timeOffset), 01521 KX_PYATTRIBUTE_RW_FUNCTION("state", KX_GameObject, pyattr_get_state, pyattr_set_state), 01522 KX_PYATTRIBUTE_RO_FUNCTION("meshes", KX_GameObject, pyattr_get_meshes), 01523 KX_PYATTRIBUTE_RW_FUNCTION("localOrientation",KX_GameObject,pyattr_get_localOrientation,pyattr_set_localOrientation), 01524 KX_PYATTRIBUTE_RW_FUNCTION("worldOrientation",KX_GameObject,pyattr_get_worldOrientation,pyattr_set_worldOrientation), 01525 KX_PYATTRIBUTE_RW_FUNCTION("localPosition", KX_GameObject, pyattr_get_localPosition, pyattr_set_localPosition), 01526 KX_PYATTRIBUTE_RW_FUNCTION("worldPosition", KX_GameObject, pyattr_get_worldPosition, pyattr_set_worldPosition), 01527 KX_PYATTRIBUTE_RW_FUNCTION("localScale", KX_GameObject, pyattr_get_localScaling, pyattr_set_localScaling), 01528 KX_PYATTRIBUTE_RO_FUNCTION("worldScale", KX_GameObject, pyattr_get_worldScaling), 01529 KX_PYATTRIBUTE_RW_FUNCTION("linearVelocity", KX_GameObject, pyattr_get_localLinearVelocity, pyattr_set_worldLinearVelocity), 01530 KX_PYATTRIBUTE_RW_FUNCTION("localLinearVelocity", KX_GameObject, pyattr_get_localLinearVelocity, pyattr_set_localLinearVelocity), 01531 KX_PYATTRIBUTE_RW_FUNCTION("worldLinearVelocity", KX_GameObject, pyattr_get_worldLinearVelocity, pyattr_set_worldLinearVelocity), 01532 KX_PYATTRIBUTE_RW_FUNCTION("angularVelocity", KX_GameObject, pyattr_get_localAngularVelocity, pyattr_set_worldAngularVelocity), 01533 KX_PYATTRIBUTE_RW_FUNCTION("localAngularVelocity", KX_GameObject, pyattr_get_localAngularVelocity, pyattr_set_localAngularVelocity), 01534 KX_PYATTRIBUTE_RW_FUNCTION("worldAngularVelocity", KX_GameObject, pyattr_get_worldAngularVelocity, pyattr_set_worldAngularVelocity), 01535 KX_PYATTRIBUTE_RO_FUNCTION("children", KX_GameObject, pyattr_get_children), 01536 KX_PYATTRIBUTE_RO_FUNCTION("childrenRecursive", KX_GameObject, pyattr_get_children_recursive), 01537 KX_PYATTRIBUTE_RO_FUNCTION("attrDict", KX_GameObject, pyattr_get_attrDict), 01538 KX_PYATTRIBUTE_RW_FUNCTION("color", KX_GameObject, pyattr_get_obcolor, pyattr_set_obcolor), 01539 01540 /* Experemental, dont rely on these yet */ 01541 KX_PYATTRIBUTE_RO_FUNCTION("sensors", KX_GameObject, pyattr_get_sensors), 01542 KX_PYATTRIBUTE_RO_FUNCTION("controllers", KX_GameObject, pyattr_get_controllers), 01543 KX_PYATTRIBUTE_RO_FUNCTION("actuators", KX_GameObject, pyattr_get_actuators), 01544 {NULL} //Sentinel 01545 }; 01546 01547 PyObject* KX_GameObject::PyReplaceMesh(PyObject* args) 01548 { 01549 KX_Scene *scene = KX_GetActiveScene(); 01550 01551 PyObject *value; 01552 int use_gfx= 1, use_phys= 0; 01553 RAS_MeshObject *new_mesh; 01554 01555 if (!PyArg_ParseTuple(args,"O|ii:replaceMesh", &value, &use_gfx, &use_phys)) 01556 return NULL; 01557 01558 if (!ConvertPythonToMesh(value, &new_mesh, false, "gameOb.replaceMesh(value): KX_GameObject")) 01559 return NULL; 01560 01561 scene->ReplaceMesh(this, new_mesh, (bool)use_gfx, (bool)use_phys); 01562 Py_RETURN_NONE; 01563 } 01564 01565 PyObject* KX_GameObject::PyEndObject() 01566 { 01567 KX_Scene *scene = KX_GetActiveScene(); 01568 01569 scene->DelayedRemoveObject(this); 01570 01571 Py_RETURN_NONE; 01572 01573 } 01574 01575 PyObject* KX_GameObject::PyReinstancePhysicsMesh(PyObject* args) 01576 { 01577 KX_GameObject *gameobj= NULL; 01578 RAS_MeshObject *mesh= NULL; 01579 01580 PyObject *gameobj_py= NULL; 01581 PyObject *mesh_py= NULL; 01582 01583 if ( !PyArg_ParseTuple(args,"|OO:reinstancePhysicsMesh",&gameobj_py, &mesh_py) || 01584 (gameobj_py && !ConvertPythonToGameObject(gameobj_py, &gameobj, true, "gameOb.reinstancePhysicsMesh(obj, mesh): KX_GameObject")) || 01585 (mesh_py && !ConvertPythonToMesh(mesh_py, &mesh, true, "gameOb.reinstancePhysicsMesh(obj, mesh): KX_GameObject")) 01586 ) { 01587 return NULL; 01588 } 01589 #ifdef USE_BULLET 01590 /* gameobj and mesh can be NULL */ 01591 if(KX_ReInstanceBulletShapeFromMesh(this, gameobj, mesh)) 01592 Py_RETURN_TRUE; 01593 #endif 01594 Py_RETURN_FALSE; 01595 } 01596 01597 static PyObject *Map_GetItem(PyObject *self_v, PyObject *item) 01598 { 01599 KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v); 01600 const char *attr_str= _PyUnicode_AsString(item); 01601 CValue* resultattr; 01602 PyObject* pyconvert; 01603 01604 if (self==NULL) { 01605 PyErr_SetString(PyExc_SystemError, "val = gameOb[key]: KX_GameObject, "BGE_PROXY_ERROR_MSG); 01606 return NULL; 01607 } 01608 01609 /* first see if the attributes a string and try get the cvalue attribute */ 01610 if(attr_str && (resultattr=self->GetProperty(attr_str))) { 01611 pyconvert = resultattr->ConvertValueToPython(); 01612 return pyconvert ? pyconvert:resultattr->GetProxy(); 01613 } 01614 /* no CValue attribute, try get the python only m_attr_dict attribute */ 01615 else if (self->m_attr_dict && (pyconvert=PyDict_GetItem(self->m_attr_dict, item))) { 01616 01617 if (attr_str) 01618 PyErr_Clear(); 01619 Py_INCREF(pyconvert); 01620 return pyconvert; 01621 } 01622 else { 01623 if(attr_str) PyErr_Format(PyExc_KeyError, "value = gameOb[key]: KX_GameObject, key \"%s\" does not exist", attr_str); 01624 else PyErr_SetString(PyExc_KeyError, "value = gameOb[key]: KX_GameObject, key does not exist"); 01625 return NULL; 01626 } 01627 01628 } 01629 01630 01631 static int Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val) 01632 { 01633 KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v); 01634 const char *attr_str= _PyUnicode_AsString(key); 01635 if(attr_str==NULL) 01636 PyErr_Clear(); 01637 01638 if (self==NULL) { 01639 PyErr_SetString(PyExc_SystemError, "gameOb[key] = value: KX_GameObject, "BGE_PROXY_ERROR_MSG); 01640 return -1; 01641 } 01642 01643 if (val==NULL) { /* del ob["key"] */ 01644 int del= 0; 01645 01646 /* try remove both just incase */ 01647 if(attr_str) 01648 del |= (self->RemoveProperty(attr_str)==true) ? 1:0; 01649 01650 if(self->m_attr_dict) 01651 del |= (PyDict_DelItem(self->m_attr_dict, key)==0) ? 1:0; 01652 01653 if (del==0) { 01654 if(attr_str) PyErr_Format(PyExc_KeyError, "gameOb[key] = value: KX_GameObject, key \"%s\" could not be set", attr_str); 01655 else PyErr_SetString(PyExc_KeyError, "del gameOb[key]: KX_GameObject, key could not be deleted"); 01656 return -1; 01657 } 01658 else if (self->m_attr_dict) { 01659 PyErr_Clear(); /* PyDict_DelItem sets an error when it fails */ 01660 } 01661 } 01662 else { /* ob["key"] = value */ 01663 int set= 0; 01664 01665 /* as CValue */ 01666 if(attr_str && PyObject_TypeCheck(val, &PyObjectPlus::Type)==0) /* dont allow GameObjects for eg to be assigned to CValue props */ 01667 { 01668 CValue* vallie = self->ConvertPythonToValue(val, ""); /* error unused */ 01669 01670 if(vallie) 01671 { 01672 CValue* oldprop = self->GetProperty(attr_str); 01673 01674 if (oldprop) 01675 oldprop->SetValue(vallie); 01676 else 01677 self->SetProperty(attr_str, vallie); 01678 01679 vallie->Release(); 01680 set= 1; 01681 01682 /* try remove dict value to avoid double ups */ 01683 if (self->m_attr_dict){ 01684 if (PyDict_DelItem(self->m_attr_dict, key) != 0) 01685 PyErr_Clear(); 01686 } 01687 } 01688 else { 01689 PyErr_Clear(); 01690 } 01691 } 01692 01693 if(set==0) 01694 { 01695 if (self->m_attr_dict==NULL) /* lazy init */ 01696 self->m_attr_dict= PyDict_New(); 01697 01698 01699 if(PyDict_SetItem(self->m_attr_dict, key, val)==0) 01700 { 01701 if(attr_str) 01702 self->RemoveProperty(attr_str); /* overwrite the CValue if it exists */ 01703 set= 1; 01704 } 01705 else { 01706 if(attr_str) PyErr_Format(PyExc_KeyError, "gameOb[key] = value: KX_GameObject, key \"%s\" not be added to internal dictionary", attr_str); 01707 else PyErr_SetString(PyExc_KeyError, "gameOb[key] = value: KX_GameObject, key not be added to internal dictionary"); 01708 } 01709 } 01710 01711 if(set==0) 01712 return -1; /* pythons error value */ 01713 01714 } 01715 01716 return 0; /* success */ 01717 } 01718 01719 static int Seq_Contains(PyObject *self_v, PyObject *value) 01720 { 01721 KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v); 01722 01723 if (self==NULL) { 01724 PyErr_SetString(PyExc_SystemError, "val in gameOb: KX_GameObject, "BGE_PROXY_ERROR_MSG); 01725 return -1; 01726 } 01727 01728 if(PyUnicode_Check(value) && self->GetProperty(_PyUnicode_AsString(value))) 01729 return 1; 01730 01731 if (self->m_attr_dict && PyDict_GetItem(self->m_attr_dict, value)) 01732 return 1; 01733 01734 return 0; 01735 } 01736 01737 01738 PyMappingMethods KX_GameObject::Mapping = { 01739 (lenfunc)NULL , /*inquiry mp_length */ 01740 (binaryfunc)Map_GetItem, /*binaryfunc mp_subscript */ 01741 (objobjargproc)Map_SetItem, /*objobjargproc mp_ass_subscript */ 01742 }; 01743 01744 PySequenceMethods KX_GameObject::Sequence = { 01745 NULL, /* Cant set the len otherwise it can evaluate as false */ 01746 NULL, /* sq_concat */ 01747 NULL, /* sq_repeat */ 01748 NULL, /* sq_item */ 01749 NULL, /* sq_slice */ 01750 NULL, /* sq_ass_item */ 01751 NULL, /* sq_ass_slice */ 01752 (objobjproc)Seq_Contains, /* sq_contains */ 01753 (binaryfunc) NULL, /* sq_inplace_concat */ 01754 (ssizeargfunc) NULL, /* sq_inplace_repeat */ 01755 }; 01756 01757 PyTypeObject KX_GameObject::Type = { 01758 PyVarObject_HEAD_INIT(NULL, 0) 01759 "KX_GameObject", 01760 sizeof(PyObjectPlus_Proxy), 01761 0, 01762 py_base_dealloc, 01763 0, 01764 0, 01765 0, 01766 0, 01767 py_base_repr, 01768 0, 01769 &Sequence, 01770 &Mapping, 01771 0,0,0, 01772 NULL, 01773 NULL, 01774 0, 01775 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, 01776 0,0,0,0,0,0,0, 01777 Methods, 01778 0, 01779 0, 01780 &SCA_IObject::Type, 01781 0,0,0,0,0,0, 01782 py_base_new 01783 }; 01784 01785 PyObject* KX_GameObject::pyattr_get_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 01786 { 01787 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 01788 return PyUnicode_FromString(self->GetName().ReadPtr()); 01789 } 01790 01791 PyObject* KX_GameObject::pyattr_get_parent(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 01792 { 01793 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 01794 KX_GameObject* parent = self->GetParent(); 01795 if (parent) { 01796 parent->Release(); /* self->GetParent() AddRef's */ 01797 return parent->GetProxy(); 01798 } 01799 Py_RETURN_NONE; 01800 } 01801 01802 PyObject* KX_GameObject::pyattr_get_life(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 01803 { 01804 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 01805 01806 CValue *life = self->GetProperty("::timebomb"); 01807 if (life) 01808 // this convert the timebomb seconds to frames, hard coded 50.0 (assuming 50fps) 01809 // value hardcoded in KX_Scene::AddReplicaObject() 01810 return PyFloat_FromDouble(life->GetNumber() * 50.0); 01811 else 01812 Py_RETURN_NONE; 01813 } 01814 01815 PyObject* KX_GameObject::pyattr_get_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 01816 { 01817 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 01818 KX_IPhysicsController *spc = self->GetPhysicsController(); 01819 return PyFloat_FromDouble(spc ? spc->GetMass() : 0.0f); 01820 } 01821 01822 int KX_GameObject::pyattr_set_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) 01823 { 01824 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 01825 KX_IPhysicsController *spc = self->GetPhysicsController(); 01826 MT_Scalar val = PyFloat_AsDouble(value); 01827 if (val < 0.0f) { /* also accounts for non float */ 01828 PyErr_SetString(PyExc_AttributeError, "gameOb.mass = float: KX_GameObject, expected a float zero or above"); 01829 return PY_SET_ATTR_FAIL; 01830 } 01831 01832 if (spc) 01833 spc->SetMass(val); 01834 01835 return PY_SET_ATTR_SUCCESS; 01836 } 01837 01838 PyObject* KX_GameObject::pyattr_get_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 01839 { 01840 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 01841 KX_IPhysicsController *spc = self->GetPhysicsController(); 01842 return PyFloat_FromDouble(spc ? spc->GetLinVelocityMax() : 0.0f); 01843 } 01844 01845 int KX_GameObject::pyattr_set_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) 01846 { 01847 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 01848 KX_IPhysicsController *spc = self->GetPhysicsController(); 01849 MT_Scalar val = PyFloat_AsDouble(value); 01850 if (val < 0.0f) { /* also accounts for non float */ 01851 PyErr_SetString(PyExc_AttributeError, "gameOb.linVelocityMin = float: KX_GameObject, expected a float zero or above"); 01852 return PY_SET_ATTR_FAIL; 01853 } 01854 01855 if (spc) 01856 spc->SetLinVelocityMin(val); 01857 01858 return PY_SET_ATTR_SUCCESS; 01859 } 01860 01861 PyObject* KX_GameObject::pyattr_get_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 01862 { 01863 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 01864 KX_IPhysicsController *spc = self->GetPhysicsController(); 01865 return PyFloat_FromDouble(spc ? spc->GetLinVelocityMax() : 0.0f); 01866 } 01867 01868 int KX_GameObject::pyattr_set_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) 01869 { 01870 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 01871 KX_IPhysicsController *spc = self->GetPhysicsController(); 01872 MT_Scalar val = PyFloat_AsDouble(value); 01873 if (val < 0.0f) { /* also accounts for non float */ 01874 PyErr_SetString(PyExc_AttributeError, "gameOb.linVelocityMax = float: KX_GameObject, expected a float zero or above"); 01875 return PY_SET_ATTR_FAIL; 01876 } 01877 01878 if (spc) 01879 spc->SetLinVelocityMax(val); 01880 01881 return PY_SET_ATTR_SUCCESS; 01882 } 01883 01884 01885 PyObject* KX_GameObject::pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 01886 { 01887 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 01888 return PyBool_FromLong(self->GetVisible()); 01889 } 01890 01891 int KX_GameObject::pyattr_set_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) 01892 { 01893 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 01894 int param = PyObject_IsTrue( value ); 01895 if (param == -1) { 01896 PyErr_SetString(PyExc_AttributeError, "gameOb.visible = bool: KX_GameObject, expected True or False"); 01897 return PY_SET_ATTR_FAIL; 01898 } 01899 01900 self->SetVisible(param, false); 01901 self->UpdateBuckets(false); 01902 return PY_SET_ATTR_SUCCESS; 01903 } 01904 01905 PyObject* KX_GameObject::pyattr_get_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 01906 { 01907 #ifdef USE_MATHUTILS 01908 return newVectorObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_GLOBAL); 01909 #else 01910 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 01911 return PyObjectFrom(self->NodeGetWorldPosition()); 01912 #endif 01913 } 01914 01915 int KX_GameObject::pyattr_set_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) 01916 { 01917 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 01918 MT_Point3 pos; 01919 if (!PyVecTo(value, pos)) 01920 return PY_SET_ATTR_FAIL; 01921 01922 self->NodeSetWorldPosition(pos); 01923 self->NodeUpdateGS(0.f); 01924 return PY_SET_ATTR_SUCCESS; 01925 } 01926 01927 PyObject* KX_GameObject::pyattr_get_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 01928 { 01929 #ifdef USE_MATHUTILS 01930 return newVectorObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_LOCAL); 01931 #else 01932 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 01933 return PyObjectFrom(self->NodeGetLocalPosition()); 01934 #endif 01935 } 01936 01937 int KX_GameObject::pyattr_set_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) 01938 { 01939 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 01940 MT_Point3 pos; 01941 if (!PyVecTo(value, pos)) 01942 return PY_SET_ATTR_FAIL; 01943 01944 self->NodeSetLocalPosition(pos); 01945 self->NodeUpdateGS(0.f); 01946 return PY_SET_ATTR_SUCCESS; 01947 } 01948 01949 PyObject* KX_GameObject::pyattr_get_localInertia(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 01950 { 01951 #ifdef USE_MATHUTILS 01952 return newVectorObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_INERTIA_LOCAL); 01953 #else 01954 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 01955 if (self->GetPhysicsController()) 01956 return PyObjectFrom(self->GetPhysicsController()->GetLocalInertia()); 01957 return Py_BuildValue("fff", 0.0f, 0.0f, 0.0f); 01958 #endif 01959 } 01960 01961 PyObject* KX_GameObject::pyattr_get_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 01962 { 01963 #ifdef USE_MATHUTILS 01964 return newMatrixObject_cb(BGE_PROXY_FROM_REF(self_v), 3, 3, mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_GLOBAL); 01965 #else 01966 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 01967 return PyObjectFrom(self->NodeGetWorldOrientation()); 01968 #endif 01969 } 01970 01971 int KX_GameObject::pyattr_set_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) 01972 { 01973 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 01974 01975 /* if value is not a sequence PyOrientationTo makes an error */ 01976 MT_Matrix3x3 rot; 01977 if (!PyOrientationTo(value, rot, "gameOb.worldOrientation = sequence: KX_GameObject, ")) 01978 return PY_SET_ATTR_FAIL; 01979 01980 self->NodeSetGlobalOrientation(rot); 01981 01982 self->NodeUpdateGS(0.f); 01983 return PY_SET_ATTR_SUCCESS; 01984 } 01985 01986 PyObject* KX_GameObject::pyattr_get_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 01987 { 01988 #ifdef USE_MATHUTILS 01989 return newMatrixObject_cb(BGE_PROXY_FROM_REF(self_v), 3, 3, mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_LOCAL); 01990 #else 01991 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 01992 return PyObjectFrom(self->NodeGetLocalOrientation()); 01993 #endif 01994 } 01995 01996 int KX_GameObject::pyattr_set_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) 01997 { 01998 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 01999 02000 /* if value is not a sequence PyOrientationTo makes an error */ 02001 MT_Matrix3x3 rot; 02002 if (!PyOrientationTo(value, rot, "gameOb.localOrientation = sequence: KX_GameObject, ")) 02003 return PY_SET_ATTR_FAIL; 02004 02005 self->NodeSetLocalOrientation(rot); 02006 self->NodeUpdateGS(0.f); 02007 return PY_SET_ATTR_SUCCESS; 02008 } 02009 02010 PyObject* KX_GameObject::pyattr_get_worldScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 02011 { 02012 #ifdef USE_MATHUTILS 02013 return newVectorObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_GLOBAL); 02014 #else 02015 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 02016 return PyObjectFrom(self->NodeGetWorldScaling()); 02017 #endif 02018 } 02019 02020 PyObject* KX_GameObject::pyattr_get_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 02021 { 02022 #ifdef USE_MATHUTILS 02023 return newVectorObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_LOCAL); 02024 #else 02025 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 02026 return PyObjectFrom(self->NodeGetLocalScaling()); 02027 #endif 02028 } 02029 02030 int KX_GameObject::pyattr_set_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) 02031 { 02032 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 02033 MT_Vector3 scale; 02034 if (!PyVecTo(value, scale)) 02035 return PY_SET_ATTR_FAIL; 02036 02037 self->NodeSetLocalScale(scale); 02038 self->NodeUpdateGS(0.f); 02039 return PY_SET_ATTR_SUCCESS; 02040 } 02041 02042 02043 PyObject* KX_GameObject::pyattr_get_worldLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 02044 { 02045 #ifdef USE_MATHUTILS 02046 return newVectorObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_LINVEL_GLOBAL); 02047 #else 02048 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 02049 return PyObjectFrom(GetLinearVelocity(false)); 02050 #endif 02051 } 02052 02053 int KX_GameObject::pyattr_set_worldLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) 02054 { 02055 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 02056 MT_Vector3 velocity; 02057 if (!PyVecTo(value, velocity)) 02058 return PY_SET_ATTR_FAIL; 02059 02060 self->setLinearVelocity(velocity, false); 02061 02062 return PY_SET_ATTR_SUCCESS; 02063 } 02064 02065 PyObject* KX_GameObject::pyattr_get_localLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 02066 { 02067 #ifdef USE_MATHUTILS 02068 return newVectorObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_LINVEL_LOCAL); 02069 #else 02070 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 02071 return PyObjectFrom(GetLinearVelocity(true)); 02072 #endif 02073 } 02074 02075 int KX_GameObject::pyattr_set_localLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) 02076 { 02077 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 02078 MT_Vector3 velocity; 02079 if (!PyVecTo(value, velocity)) 02080 return PY_SET_ATTR_FAIL; 02081 02082 self->setLinearVelocity(velocity, true); 02083 02084 return PY_SET_ATTR_SUCCESS; 02085 } 02086 02087 PyObject* KX_GameObject::pyattr_get_worldAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 02088 { 02089 #ifdef USE_MATHUTILS 02090 return newVectorObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_ANGVEL_GLOBAL); 02091 #else 02092 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 02093 return PyObjectFrom(GetAngularVelocity(false)); 02094 #endif 02095 } 02096 02097 int KX_GameObject::pyattr_set_worldAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) 02098 { 02099 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 02100 MT_Vector3 velocity; 02101 if (!PyVecTo(value, velocity)) 02102 return PY_SET_ATTR_FAIL; 02103 02104 self->setAngularVelocity(velocity, false); 02105 02106 return PY_SET_ATTR_SUCCESS; 02107 } 02108 02109 PyObject* KX_GameObject::pyattr_get_localAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 02110 { 02111 #ifdef USE_MATHUTILS 02112 return newVectorObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_ANGVEL_LOCAL); 02113 #else 02114 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 02115 return PyObjectFrom(GetAngularVelocity(true)); 02116 #endif 02117 } 02118 02119 int KX_GameObject::pyattr_set_localAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) 02120 { 02121 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 02122 MT_Vector3 velocity; 02123 if (!PyVecTo(value, velocity)) 02124 return PY_SET_ATTR_FAIL; 02125 02126 self->setAngularVelocity(velocity, true); 02127 02128 return PY_SET_ATTR_SUCCESS; 02129 } 02130 02131 02132 PyObject* KX_GameObject::pyattr_get_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 02133 { 02134 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 02135 SG_Node* sg_parent; 02136 if (self->GetSGNode() && (sg_parent = self->GetSGNode()->GetSGParent()) != NULL && sg_parent->IsSlowParent()) { 02137 return PyFloat_FromDouble(static_cast<KX_SlowParentRelation *>(sg_parent->GetParentRelation())->GetTimeOffset()); 02138 } else { 02139 return PyFloat_FromDouble(0.0); 02140 } 02141 } 02142 02143 int KX_GameObject::pyattr_set_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) 02144 { 02145 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 02146 if (self->GetSGNode()) { 02147 MT_Scalar val = PyFloat_AsDouble(value); 02148 SG_Node* sg_parent= self->GetSGNode()->GetSGParent(); 02149 if (val < 0.0f) { /* also accounts for non float */ 02150 PyErr_SetString(PyExc_AttributeError, "gameOb.timeOffset = float: KX_GameObject, expected a float zero or above"); 02151 return PY_SET_ATTR_FAIL; 02152 } 02153 if (sg_parent && sg_parent->IsSlowParent()) 02154 static_cast<KX_SlowParentRelation *>(sg_parent->GetParentRelation())->SetTimeOffset(val); 02155 } 02156 return PY_SET_ATTR_SUCCESS; 02157 } 02158 02159 PyObject* KX_GameObject::pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 02160 { 02161 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 02162 int state = 0; 02163 state |= self->GetState(); 02164 return PyLong_FromSsize_t(state); 02165 } 02166 02167 int KX_GameObject::pyattr_set_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) 02168 { 02169 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 02170 int state_i = PyLong_AsSsize_t(value); 02171 unsigned int state = 0; 02172 02173 if (state_i == -1 && PyErr_Occurred()) { 02174 PyErr_SetString(PyExc_TypeError, "gameOb.state = int: KX_GameObject, expected an int bit field"); 02175 return PY_SET_ATTR_FAIL; 02176 } 02177 02178 state |= state_i; 02179 if ((state & ((1<<30)-1)) == 0) { 02180 PyErr_SetString(PyExc_AttributeError, "gameOb.state = int: KX_GameObject, state bitfield was not between 0 and 30 (1<<0 and 1<<29)"); 02181 return PY_SET_ATTR_FAIL; 02182 } 02183 self->SetState(state); 02184 return PY_SET_ATTR_SUCCESS; 02185 } 02186 02187 PyObject* KX_GameObject::pyattr_get_meshes(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 02188 { 02189 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 02190 PyObject *meshes= PyList_New(self->m_meshes.size()); 02191 int i; 02192 02193 for(i=0; i < (int)self->m_meshes.size(); i++) 02194 { 02195 KX_MeshProxy* meshproxy = new KX_MeshProxy(self->m_meshes[i]); 02196 PyList_SET_ITEM(meshes, i, meshproxy->NewProxy(true)); 02197 } 02198 02199 return meshes; 02200 } 02201 02202 PyObject* KX_GameObject::pyattr_get_obcolor(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 02203 { 02204 #ifdef USE_MATHUTILS 02205 return newVectorObject_cb(BGE_PROXY_FROM_REF(self_v), 4, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_OBJECT_COLOR); 02206 #else 02207 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 02208 return PyObjectFrom(self->GetObjectColor()); 02209 #endif 02210 } 02211 02212 int KX_GameObject::pyattr_set_obcolor(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) 02213 { 02214 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 02215 MT_Vector4 obcolor; 02216 if (!PyVecTo(value, obcolor)) 02217 return PY_SET_ATTR_FAIL; 02218 02219 self->SetObjectColor(obcolor); 02220 return PY_SET_ATTR_SUCCESS; 02221 } 02222 02223 /* These are experimental! */ 02224 PyObject* KX_GameObject::pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 02225 { 02226 return KX_PythonSeq_CreatePyObject((static_cast<KX_GameObject*>(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_SENSORS); 02227 } 02228 02229 PyObject* KX_GameObject::pyattr_get_controllers(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 02230 { 02231 return KX_PythonSeq_CreatePyObject((static_cast<KX_GameObject*>(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_CONTROLLERS); 02232 } 02233 02234 PyObject* KX_GameObject::pyattr_get_actuators(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 02235 { 02236 return KX_PythonSeq_CreatePyObject((static_cast<KX_GameObject*>(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_ACTUATORS); 02237 } 02238 /* End experimental */ 02239 02240 PyObject* KX_GameObject::pyattr_get_children(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 02241 { 02242 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 02243 return self->GetChildren()->NewProxy(true); 02244 } 02245 02246 PyObject* KX_GameObject::pyattr_get_children_recursive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 02247 { 02248 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 02249 return self->GetChildrenRecursive()->NewProxy(true); 02250 } 02251 02252 PyObject* KX_GameObject::pyattr_get_attrDict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) 02253 { 02254 KX_GameObject* self= static_cast<KX_GameObject*>(self_v); 02255 02256 if(self->m_attr_dict==NULL) 02257 self->m_attr_dict= PyDict_New(); 02258 02259 Py_INCREF(self->m_attr_dict); 02260 return self->m_attr_dict; 02261 } 02262 02263 PyObject* KX_GameObject::PyApplyForce(PyObject* args) 02264 { 02265 int local = 0; 02266 PyObject* pyvect; 02267 02268 if (PyArg_ParseTuple(args, "O|i:applyForce", &pyvect, &local)) { 02269 MT_Vector3 force; 02270 if (PyVecTo(pyvect, force)) { 02271 ApplyForce(force, (local!=0)); 02272 Py_RETURN_NONE; 02273 } 02274 } 02275 return NULL; 02276 } 02277 02278 PyObject* KX_GameObject::PyApplyTorque(PyObject* args) 02279 { 02280 int local = 0; 02281 PyObject* pyvect; 02282 02283 if (PyArg_ParseTuple(args, "O|i:applyTorque", &pyvect, &local)) { 02284 MT_Vector3 torque; 02285 if (PyVecTo(pyvect, torque)) { 02286 ApplyTorque(torque, (local!=0)); 02287 Py_RETURN_NONE; 02288 } 02289 } 02290 return NULL; 02291 } 02292 02293 PyObject* KX_GameObject::PyApplyRotation(PyObject* args) 02294 { 02295 int local = 0; 02296 PyObject* pyvect; 02297 02298 if (PyArg_ParseTuple(args, "O|i:applyRotation", &pyvect, &local)) { 02299 MT_Vector3 rotation; 02300 if (PyVecTo(pyvect, rotation)) { 02301 ApplyRotation(rotation, (local!=0)); 02302 Py_RETURN_NONE; 02303 } 02304 } 02305 return NULL; 02306 } 02307 02308 PyObject* KX_GameObject::PyApplyMovement(PyObject* args) 02309 { 02310 int local = 0; 02311 PyObject* pyvect; 02312 02313 if (PyArg_ParseTuple(args, "O|i:applyMovement", &pyvect, &local)) { 02314 MT_Vector3 movement; 02315 if (PyVecTo(pyvect, movement)) { 02316 ApplyMovement(movement, (local!=0)); 02317 Py_RETURN_NONE; 02318 } 02319 } 02320 return NULL; 02321 } 02322 02323 PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* args) 02324 { 02325 // only can get the velocity if we have a physics object connected to us... 02326 int local = 0; 02327 if (PyArg_ParseTuple(args,"|i:getLinearVelocity",&local)) 02328 { 02329 return PyObjectFrom(GetLinearVelocity((local!=0))); 02330 } 02331 else 02332 { 02333 return NULL; 02334 } 02335 } 02336 02337 PyObject* KX_GameObject::PySetLinearVelocity(PyObject* args) 02338 { 02339 int local = 0; 02340 PyObject* pyvect; 02341 02342 if (PyArg_ParseTuple(args,"O|i:setLinearVelocity",&pyvect,&local)) { 02343 MT_Vector3 velocity; 02344 if (PyVecTo(pyvect, velocity)) { 02345 setLinearVelocity(velocity, (local!=0)); 02346 Py_RETURN_NONE; 02347 } 02348 } 02349 return NULL; 02350 } 02351 02352 PyObject* KX_GameObject::PyGetAngularVelocity(PyObject* args) 02353 { 02354 // only can get the velocity if we have a physics object connected to us... 02355 int local = 0; 02356 if (PyArg_ParseTuple(args,"|i:getAngularVelocity",&local)) 02357 { 02358 return PyObjectFrom(GetAngularVelocity((local!=0))); 02359 } 02360 else 02361 { 02362 return NULL; 02363 } 02364 } 02365 02366 PyObject* KX_GameObject::PySetAngularVelocity(PyObject* args) 02367 { 02368 int local = 0; 02369 PyObject* pyvect; 02370 02371 if (PyArg_ParseTuple(args,"O|i:setAngularVelocity",&pyvect,&local)) { 02372 MT_Vector3 velocity; 02373 if (PyVecTo(pyvect, velocity)) { 02374 setAngularVelocity(velocity, (local!=0)); 02375 Py_RETURN_NONE; 02376 } 02377 } 02378 return NULL; 02379 } 02380 02381 PyObject* KX_GameObject::PySetVisible(PyObject* args) 02382 { 02383 int visible, recursive = 0; 02384 if (!PyArg_ParseTuple(args,"i|i:setVisible",&visible, &recursive)) 02385 return NULL; 02386 02387 SetVisible(visible ? true:false, recursive ? true:false); 02388 UpdateBuckets(recursive ? true:false); 02389 Py_RETURN_NONE; 02390 02391 } 02392 02393 PyObject* KX_GameObject::PySetOcclusion(PyObject* args) 02394 { 02395 int occlusion, recursive = 0; 02396 if (!PyArg_ParseTuple(args,"i|i:setOcclusion",&occlusion, &recursive)) 02397 return NULL; 02398 02399 SetOccluder(occlusion ? true:false, recursive ? true:false); 02400 Py_RETURN_NONE; 02401 } 02402 02403 PyObject* KX_GameObject::PyGetVelocity(PyObject* args) 02404 { 02405 // only can get the velocity if we have a physics object connected to us... 02406 MT_Point3 point(0.0,0.0,0.0); 02407 PyObject* pypos = NULL; 02408 02409 if (!PyArg_ParseTuple(args, "|O:getVelocity", &pypos) || (pypos && !PyVecTo(pypos, point))) 02410 return NULL; 02411 02412 if (m_pPhysicsController1) 02413 { 02414 return PyObjectFrom(m_pPhysicsController1->GetVelocity(point)); 02415 } 02416 else { 02417 return PyObjectFrom(MT_Vector3(0.0,0.0,0.0)); 02418 } 02419 } 02420 02421 PyObject* KX_GameObject::PyGetReactionForce() 02422 { 02423 // only can get the velocity if we have a physics object connected to us... 02424 02425 // XXX - Currently not working with bullet intergration, see KX_BulletPhysicsController.cpp's getReactionForce 02426 /* 02427 if (GetPhysicsController()) 02428 return PyObjectFrom(GetPhysicsController()->getReactionForce()); 02429 return PyObjectFrom(dummy_point); 02430 */ 02431 02432 return Py_BuildValue("fff", 0.0f, 0.0f, 0.0f); 02433 02434 } 02435 02436 02437 02438 PyObject* KX_GameObject::PyEnableRigidBody() 02439 { 02440 if(GetPhysicsController()) 02441 GetPhysicsController()->setRigidBody(true); 02442 02443 Py_RETURN_NONE; 02444 } 02445 02446 02447 02448 PyObject* KX_GameObject::PyDisableRigidBody() 02449 { 02450 if(GetPhysicsController()) 02451 GetPhysicsController()->setRigidBody(false); 02452 02453 Py_RETURN_NONE; 02454 } 02455 02456 02457 PyObject* KX_GameObject::PySetParent(PyObject* args) 02458 { 02459 KX_Scene *scene = KX_GetActiveScene(); 02460 PyObject* pyobj; 02461 KX_GameObject *obj; 02462 int addToCompound=1, ghost=1; 02463 02464 if (!PyArg_ParseTuple(args,"O|ii:setParent", &pyobj, &addToCompound, &ghost)) { 02465 return NULL; // Python sets a simple error 02466 } 02467 if (!ConvertPythonToGameObject(pyobj, &obj, true, "gameOb.setParent(obj): KX_GameObject")) 02468 return NULL; 02469 if (obj) 02470 this->SetParent(scene, obj, addToCompound, ghost); 02471 Py_RETURN_NONE; 02472 } 02473 02474 PyObject* KX_GameObject::PyRemoveParent() 02475 { 02476 KX_Scene *scene = KX_GetActiveScene(); 02477 02478 this->RemoveParent(scene); 02479 Py_RETURN_NONE; 02480 } 02481 02482 02483 PyObject* KX_GameObject::PySetCollisionMargin(PyObject* value) 02484 { 02485 float collisionMargin = PyFloat_AsDouble(value); 02486 02487 if (collisionMargin==-1 && PyErr_Occurred()) { 02488 PyErr_SetString(PyExc_TypeError, "expected a float"); 02489 return NULL; 02490 } 02491 02492 if (m_pPhysicsController1) 02493 { 02494 m_pPhysicsController1->setMargin(collisionMargin); 02495 Py_RETURN_NONE; 02496 } 02497 PyErr_SetString(PyExc_RuntimeError, "This object has no physics controller"); 02498 return NULL; 02499 } 02500 02501 02502 02503 PyObject* KX_GameObject::PyApplyImpulse(PyObject* args) 02504 { 02505 PyObject* pyattach; 02506 PyObject* pyimpulse; 02507 02508 if (!m_pPhysicsController1) { 02509 PyErr_SetString(PyExc_RuntimeError, "This object has no physics controller"); 02510 return NULL; 02511 } 02512 02513 if (PyArg_ParseTuple(args, "OO:applyImpulse", &pyattach, &pyimpulse)) 02514 { 02515 MT_Point3 attach; 02516 MT_Vector3 impulse; 02517 if (PyVecTo(pyattach, attach) && PyVecTo(pyimpulse, impulse)) 02518 { 02519 m_pPhysicsController1->applyImpulse(attach, impulse); 02520 Py_RETURN_NONE; 02521 } 02522 02523 } 02524 02525 return NULL; 02526 } 02527 02528 02529 02530 PyObject* KX_GameObject::PySuspendDynamics() 02531 { 02532 SuspendDynamics(); 02533 Py_RETURN_NONE; 02534 } 02535 02536 02537 02538 PyObject* KX_GameObject::PyRestoreDynamics() 02539 { 02540 RestoreDynamics(); 02541 Py_RETURN_NONE; 02542 } 02543 02544 02545 PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* args) 02546 { 02547 PyObject* pyvect; 02548 int axis = 2; //z axis is the default 02549 float fac = 1.0; 02550 02551 if (PyArg_ParseTuple(args,"O|if:alignAxisToVect",&pyvect,&axis, &fac)) 02552 { 02553 MT_Vector3 vect; 02554 if (PyVecTo(pyvect, vect)) 02555 { 02556 if (fac<=0.0) Py_RETURN_NONE; // Nothing to do. 02557 if (fac> 1.0) fac= 1.0; 02558 02559 AlignAxisToVect(vect,axis,fac); 02560 NodeUpdateGS(0.f); 02561 Py_RETURN_NONE; 02562 } 02563 } 02564 return NULL; 02565 } 02566 02567 PyObject* KX_GameObject::PyGetAxisVect(PyObject* value) 02568 { 02569 MT_Vector3 vect; 02570 if (PyVecTo(value, vect)) 02571 { 02572 return PyObjectFrom(NodeGetWorldOrientation() * vect); 02573 } 02574 return NULL; 02575 } 02576 02577 02578 PyObject* KX_GameObject::PyGetPhysicsId() 02579 { 02580 KX_IPhysicsController* ctrl = GetPhysicsController(); 02581 uint_ptr physid=0; 02582 if (ctrl) 02583 { 02584 physid= (uint_ptr)ctrl->GetUserData(); 02585 } 02586 return PyLong_FromSsize_t((long)physid); 02587 } 02588 02589 PyObject* KX_GameObject::PyGetPropertyNames() 02590 { 02591 PyObject *list= ConvertKeysToPython(); 02592 02593 if(m_attr_dict) { 02594 PyObject *key, *value; 02595 Py_ssize_t pos = 0; 02596 02597 while (PyDict_Next(m_attr_dict, &pos, &key, &value)) { 02598 PyList_Append(list, key); 02599 } 02600 } 02601 return list; 02602 } 02603 02604 KX_PYMETHODDEF_DOC_O(KX_GameObject, getDistanceTo, 02605 "getDistanceTo(other): get distance to another point/KX_GameObject") 02606 { 02607 MT_Point3 b; 02608 if (PyVecTo(value, b)) 02609 { 02610 return PyFloat_FromDouble(NodeGetWorldPosition().distance(b)); 02611 } 02612 PyErr_Clear(); 02613 02614 KX_GameObject *other; 02615 if (ConvertPythonToGameObject(value, &other, false, "gameOb.getDistanceTo(value): KX_GameObject")) 02616 { 02617 return PyFloat_FromDouble(NodeGetWorldPosition().distance(other->NodeGetWorldPosition())); 02618 } 02619 02620 return NULL; 02621 } 02622 02623 KX_PYMETHODDEF_DOC_O(KX_GameObject, getVectTo, 02624 "getVectTo(other): get vector and the distance to another point/KX_GameObject\n" 02625 "Returns a 3-tuple with (distance,worldVector,localVector)\n") 02626 { 02627 MT_Point3 toPoint, fromPoint; 02628 MT_Vector3 toDir, locToDir; 02629 MT_Scalar distance; 02630 02631 PyObject *returnValue; 02632 02633 if (!PyVecTo(value, toPoint)) 02634 { 02635 PyErr_Clear(); 02636 02637 KX_GameObject *other; 02638 if (ConvertPythonToGameObject(value, &other, false, "")) /* error will be overwritten */ 02639 { 02640 toPoint = other->NodeGetWorldPosition(); 02641 } else 02642 { 02643 PyErr_SetString(PyExc_TypeError, "gameOb.getVectTo(other): KX_GameObject, expected a 3D Vector or KX_GameObject type"); 02644 return NULL; 02645 } 02646 } 02647 02648 fromPoint = NodeGetWorldPosition(); 02649 toDir = toPoint-fromPoint; 02650 distance = toDir.length(); 02651 02652 if (MT_fuzzyZero(distance)) 02653 { 02654 //cout << "getVectTo() Error: Null vector!\n"; 02655 locToDir = toDir = MT_Vector3(0.0,0.0,0.0); 02656 distance = 0.0; 02657 } else { 02658 toDir.normalize(); 02659 locToDir = toDir * NodeGetWorldOrientation(); 02660 } 02661 02662 returnValue = PyTuple_New(3); 02663 if (returnValue) { // very unlikely to fail, python sets a memory error here. 02664 PyTuple_SET_ITEM(returnValue, 0, PyFloat_FromDouble(distance)); 02665 PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(toDir)); 02666 PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(locToDir)); 02667 } 02668 return returnValue; 02669 } 02670 02671 bool KX_GameObject::RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data) 02672 { 02673 KX_GameObject* hitKXObj = client->m_gameobject; 02674 02675 // if X-ray option is selected, the unwnted objects were not tested, so get here only with true hit 02676 // if not, all objects were tested and the front one may not be the correct one. 02677 if (m_xray || m_testPropName.Length() == 0 || hitKXObj->GetProperty(m_testPropName) != NULL) 02678 { 02679 m_pHitObject = hitKXObj; 02680 return true; 02681 } 02682 // return true to stop RayCast::RayTest from looping, the above test was decisive 02683 // We would want to loop only if we want to get more than one hit point 02684 return true; 02685 } 02686 02687 /* this function is used to pre-filter the object before casting the ray on them. 02688 This is useful for "X-Ray" option when we want to see "through" unwanted object. 02689 */ 02690 bool KX_GameObject::NeedRayCast(KX_ClientObjectInfo* client) 02691 { 02692 KX_GameObject* hitKXObj = client->m_gameobject; 02693 02694 if (client->m_type > KX_ClientObjectInfo::ACTOR) 02695 { 02696 // Unknown type of object, skip it. 02697 // Should not occur as the sensor objects are filtered in RayTest() 02698 printf("Invalid client type %d found in ray casting\n", client->m_type); 02699 return false; 02700 } 02701 02702 // if X-Ray option is selected, skip object that don't match the criteria as we see through them 02703 // if not, test all objects because we don't know yet which one will be on front 02704 if (!m_xray || m_testPropName.Length() == 0 || hitKXObj->GetProperty(m_testPropName) != NULL) 02705 { 02706 return true; 02707 } 02708 // skip the object 02709 return false; 02710 } 02711 02712 KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo, 02713 "rayCastTo(other,dist,prop): look towards another point/KX_GameObject and return first object hit within dist that matches prop\n" 02714 " prop = property name that object must have; can be omitted => detect any object\n" 02715 " dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to other\n" 02716 " other = 3-tuple or object reference") 02717 { 02718 MT_Point3 toPoint; 02719 PyObject* pyarg; 02720 float dist = 0.0f; 02721 char *propName = NULL; 02722 02723 if (!PyArg_ParseTuple(args,"O|fs:rayCastTo", &pyarg, &dist, &propName)) { 02724 return NULL; // python sets simple error 02725 } 02726 02727 if (!PyVecTo(pyarg, toPoint)) 02728 { 02729 KX_GameObject *other; 02730 PyErr_Clear(); 02731 02732 if (ConvertPythonToGameObject(pyarg, &other, false, "")) /* error will be overwritten */ 02733 { 02734 toPoint = other->NodeGetWorldPosition(); 02735 } else 02736 { 02737 PyErr_SetString(PyExc_TypeError, "gameOb.rayCastTo(other,dist,prop): KX_GameObject, the first argument to rayCastTo must be a vector or a KX_GameObject"); 02738 return NULL; 02739 } 02740 } 02741 MT_Point3 fromPoint = NodeGetWorldPosition(); 02742 02743 if (dist != 0.0f) 02744 toPoint = fromPoint + dist * (toPoint-fromPoint).safe_normalized(); 02745 02746 PHY_IPhysicsEnvironment* pe = KX_GetActiveScene()->GetPhysicsEnvironment(); 02747 KX_IPhysicsController *spc = GetPhysicsController(); 02748 KX_GameObject *parent = GetParent(); 02749 if (!spc && parent) 02750 spc = parent->GetPhysicsController(); 02751 if (parent) 02752 parent->Release(); 02753 02754 m_pHitObject = NULL; 02755 if (propName) 02756 m_testPropName = propName; 02757 else 02758 m_testPropName.SetLength(0); 02759 KX_RayCast::Callback<KX_GameObject> callback(this,spc); 02760 KX_RayCast::RayTest(pe, fromPoint, toPoint, callback); 02761 02762 if (m_pHitObject) 02763 return m_pHitObject->GetProxy(); 02764 02765 Py_RETURN_NONE; 02766 } 02767 02768 /* faster then Py_BuildValue since some scripts call raycast a lot */ 02769 static PyObject *none_tuple_3() 02770 { 02771 PyObject *ret= PyTuple_New(3); 02772 PyTuple_SET_ITEM(ret, 0, Py_None); 02773 PyTuple_SET_ITEM(ret, 1, Py_None); 02774 PyTuple_SET_ITEM(ret, 2, Py_None); 02775 02776 Py_INCREF(Py_None); 02777 Py_INCREF(Py_None); 02778 Py_INCREF(Py_None); 02779 return ret; 02780 } 02781 static PyObject *none_tuple_4() 02782 { 02783 PyObject *ret= PyTuple_New(4); 02784 PyTuple_SET_ITEM(ret, 0, Py_None); 02785 PyTuple_SET_ITEM(ret, 1, Py_None); 02786 PyTuple_SET_ITEM(ret, 2, Py_None); 02787 PyTuple_SET_ITEM(ret, 3, Py_None); 02788 02789 Py_INCREF(Py_None); 02790 Py_INCREF(Py_None); 02791 Py_INCREF(Py_None); 02792 Py_INCREF(Py_None); 02793 return ret; 02794 } 02795 02796 static PyObject *none_tuple_5() 02797 { 02798 PyObject *ret= PyTuple_New(5); 02799 PyTuple_SET_ITEM(ret, 0, Py_None); 02800 PyTuple_SET_ITEM(ret, 1, Py_None); 02801 PyTuple_SET_ITEM(ret, 2, Py_None); 02802 PyTuple_SET_ITEM(ret, 3, Py_None); 02803 PyTuple_SET_ITEM(ret, 4, Py_None); 02804 02805 Py_INCREF(Py_None); 02806 Py_INCREF(Py_None); 02807 Py_INCREF(Py_None); 02808 Py_INCREF(Py_None); 02809 Py_INCREF(Py_None); 02810 return ret; 02811 } 02812 02813 KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, 02814 "rayCast(to,from,dist,prop,face,xray,poly): cast a ray and return 3-tuple (object,hit,normal) or 4-tuple (object,hit,normal,polygon) or 4-tuple (object,hit,normal,polygon,hituv) of contact point with object within dist that matches prop.\n" 02815 " If no hit, return (None,None,None) or (None,None,None,None) or (None,None,None,None,None).\n" 02816 " to = 3-tuple or object reference for destination of ray (if object, use center of object)\n" 02817 " from = 3-tuple or object reference for origin of ray (if object, use center of object)\n" 02818 " Can be None or omitted => start from self object center\n" 02819 " dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to to\n" 02820 " prop = property name that object must have; can be omitted => detect any object\n" 02821 " face = normal option: 1=>return face normal; 0 or omitted => normal is oriented towards origin\n" 02822 " xray = X-ray option: 1=>skip objects that don't match prop; 0 or omitted => stop on first object\n" 02823 " poly = polygon option: 1=>return value is a 4-tuple and the 4th element is a KX_PolyProxy object\n" 02824 " which can be None if hit object has no mesh or if there is no hit\n" 02825 " 2=>return value is a 5-tuple, the 4th element is the KX_PolyProxy object\n" 02826 " and the 5th element is the vector of UV coordinates at the hit point of the None if there is no UV mapping\n" 02827 " If 0 or omitted, return value is a 3-tuple\n" 02828 "Note: The object on which you call this method matters: the ray will ignore it.\n" 02829 " prop and xray option interact as follow:\n" 02830 " prop off, xray off: return closest hit or no hit if there is no object on the full extend of the ray\n" 02831 " prop off, xray on : idem\n" 02832 " prop on, xray off: return closest hit if it matches prop, no hit otherwise\n" 02833 " prop on, xray on : return closest hit matching prop or no hit if there is no object matching prop on the full extend of the ray\n") 02834 { 02835 MT_Point3 toPoint; 02836 MT_Point3 fromPoint; 02837 PyObject* pyto; 02838 PyObject* pyfrom = NULL; 02839 float dist = 0.0f; 02840 char *propName = NULL; 02841 KX_GameObject *other; 02842 int face=0, xray=0, poly=0; 02843 02844 if (!PyArg_ParseTuple(args,"O|Ofsiii:rayCast", &pyto, &pyfrom, &dist, &propName, &face, &xray, &poly)) { 02845 return NULL; // Python sets a simple error 02846 } 02847 02848 if (!PyVecTo(pyto, toPoint)) 02849 { 02850 PyErr_Clear(); 02851 02852 if (ConvertPythonToGameObject(pyto, &other, false, "")) /* error will be overwritten */ 02853 { 02854 toPoint = other->NodeGetWorldPosition(); 02855 } else 02856 { 02857 PyErr_SetString(PyExc_TypeError, "the first argument to rayCast must be a vector or a KX_GameObject"); 02858 return NULL; 02859 } 02860 } 02861 if (!pyfrom || pyfrom == Py_None) 02862 { 02863 fromPoint = NodeGetWorldPosition(); 02864 } 02865 else if (!PyVecTo(pyfrom, fromPoint)) 02866 { 02867 PyErr_Clear(); 02868 02869 if (ConvertPythonToGameObject(pyfrom, &other, false, "")) /* error will be overwritten */ 02870 { 02871 fromPoint = other->NodeGetWorldPosition(); 02872 } else 02873 { 02874 PyErr_SetString(PyExc_TypeError, "gameOb.rayCast(to,from,dist,prop,face,xray,poly): KX_GameObject, the second optional argument to rayCast must be a vector or a KX_GameObject"); 02875 return NULL; 02876 } 02877 } 02878 02879 if (dist != 0.0f) { 02880 MT_Vector3 toDir = toPoint-fromPoint; 02881 if (MT_fuzzyZero(toDir.length2())) { 02882 //return Py_BuildValue("OOO", Py_None, Py_None, Py_None); 02883 return none_tuple_3(); 02884 } 02885 toDir.normalize(); 02886 toPoint = fromPoint + (dist) * toDir; 02887 } else if (MT_fuzzyZero((toPoint-fromPoint).length2())) { 02888 //return Py_BuildValue("OOO", Py_None, Py_None, Py_None); 02889 return none_tuple_3(); 02890 } 02891 02892 PHY_IPhysicsEnvironment* pe = KX_GetActiveScene()->GetPhysicsEnvironment(); 02893 KX_IPhysicsController *spc = GetPhysicsController(); 02894 KX_GameObject *parent = GetParent(); 02895 if (!spc && parent) 02896 spc = parent->GetPhysicsController(); 02897 if (parent) 02898 parent->Release(); 02899 02900 m_pHitObject = NULL; 02901 if (propName) 02902 m_testPropName = propName; 02903 else 02904 m_testPropName.SetLength(0); 02905 m_xray = xray; 02906 // to get the hit results 02907 KX_RayCast::Callback<KX_GameObject> callback(this,spc,NULL,face,(poly==2)); 02908 KX_RayCast::RayTest(pe, fromPoint, toPoint, callback); 02909 02910 if (m_pHitObject) 02911 { 02912 PyObject* returnValue = (poly==2) ? PyTuple_New(5) : (poly) ? PyTuple_New(4) : PyTuple_New(3); 02913 if (returnValue) { // unlikely this would ever fail, if it does python sets an error 02914 PyTuple_SET_ITEM(returnValue, 0, m_pHitObject->GetProxy()); 02915 PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(callback.m_hitPoint)); 02916 PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(callback.m_hitNormal)); 02917 if (poly) 02918 { 02919 if (callback.m_hitMesh) 02920 { 02921 // if this field is set, then we can trust that m_hitPolygon is a valid polygon 02922 RAS_Polygon* polygon = callback.m_hitMesh->GetPolygon(callback.m_hitPolygon); 02923 KX_PolyProxy* polyproxy = new KX_PolyProxy(callback.m_hitMesh, polygon); 02924 PyTuple_SET_ITEM(returnValue, 3, polyproxy->NewProxy(true)); 02925 if (poly == 2) 02926 { 02927 if (callback.m_hitUVOK) 02928 PyTuple_SET_ITEM(returnValue, 4, PyObjectFrom(callback.m_hitUV)); 02929 else { 02930 Py_INCREF(Py_None); 02931 PyTuple_SET_ITEM(returnValue, 4, Py_None); 02932 } 02933 } 02934 } 02935 else 02936 { 02937 Py_INCREF(Py_None); 02938 PyTuple_SET_ITEM(returnValue, 3, Py_None); 02939 if (poly==2) 02940 { 02941 Py_INCREF(Py_None); 02942 PyTuple_SET_ITEM(returnValue, 4, Py_None); 02943 } 02944 } 02945 } 02946 } 02947 return returnValue; 02948 } 02949 // no hit 02950 if (poly == 2) 02951 return none_tuple_5(); 02952 else if (poly) 02953 return none_tuple_4(); 02954 else 02955 return none_tuple_3(); 02956 } 02957 02958 KX_PYMETHODDEF_DOC_VARARGS(KX_GameObject, sendMessage, 02959 "sendMessage(subject, [body, to])\n" 02960 "sends a message in same manner as a message actuator" 02961 "subject = Subject of the message (string)" 02962 "body = Message body (string)" 02963 "to = Name of object to send the message to") 02964 { 02965 KX_Scene *scene = KX_GetActiveScene(); 02966 char* subject; 02967 char* body = (char *)""; 02968 char* to = (char *)""; 02969 const STR_String& from = GetName(); 02970 02971 if (!PyArg_ParseTuple(args, "s|ss:sendMessage", &subject, &body, &to)) 02972 return NULL; 02973 02974 scene->GetNetworkScene()->SendMessage(to, from, subject, body); 02975 Py_RETURN_NONE; 02976 } 02977 02978 /* dict style access */ 02979 02980 02981 /* Matches python dict.get(key, [default]) */ 02982 PyObject* KX_GameObject::Pyget(PyObject *args) 02983 { 02984 PyObject *key; 02985 PyObject* def = Py_None; 02986 PyObject* ret; 02987 02988 if (!PyArg_ParseTuple(args, "O|O:get", &key, &def)) 02989 return NULL; 02990 02991 02992 if(PyUnicode_Check(key)) { 02993 CValue *item = GetProperty(_PyUnicode_AsString(key)); 02994 if (item) { 02995 ret = item->ConvertValueToPython(); 02996 if(ret) 02997 return ret; 02998 else 02999 return item->GetProxy(); 03000 } 03001 } 03002 03003 if (m_attr_dict && (ret=PyDict_GetItem(m_attr_dict, key))) { 03004 Py_INCREF(ret); 03005 return ret; 03006 } 03007 03008 Py_INCREF(def); 03009 return def; 03010 } 03011 03012 bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py_none_ok, const char *error_prefix) 03013 { 03014 if (value==NULL) { 03015 PyErr_Format(PyExc_TypeError, "%s, python pointer NULL, should never happen", error_prefix); 03016 *object = NULL; 03017 return false; 03018 } 03019 03020 if (value==Py_None) { 03021 *object = NULL; 03022 03023 if (py_none_ok) { 03024 return true; 03025 } else { 03026 PyErr_Format(PyExc_TypeError, "%s, expected KX_GameObject or a KX_GameObject name, None is invalid", error_prefix); 03027 return false; 03028 } 03029 } 03030 03031 if (PyUnicode_Check(value)) { 03032 *object = (KX_GameObject*)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String( _PyUnicode_AsString(value) )); 03033 03034 if (*object) { 03035 return true; 03036 } else { 03037 PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_GameObject in this scene", error_prefix, _PyUnicode_AsString(value)); 03038 return false; 03039 } 03040 } 03041 03042 if ( PyObject_TypeCheck(value, &KX_GameObject::Type) || 03043 PyObject_TypeCheck(value, &KX_LightObject::Type) || 03044 PyObject_TypeCheck(value, &KX_Camera::Type) || 03045 PyObject_TypeCheck(value, &KX_FontObject::Type)) 03046 { 03047 *object = static_cast<KX_GameObject*>BGE_PROXY_REF(value); 03048 03049 /* sets the error */ 03050 if (*object==NULL) { 03051 PyErr_Format(PyExc_SystemError, "%s, " BGE_PROXY_ERROR_MSG, error_prefix); 03052 return false; 03053 } 03054 03055 return true; 03056 } 03057 03058 *object = NULL; 03059 03060 if (py_none_ok) { 03061 PyErr_Format(PyExc_TypeError, "%s, expect a KX_GameObject, a string or None", error_prefix); 03062 } else { 03063 PyErr_Format(PyExc_TypeError, "%s, expect a KX_GameObject or a string", error_prefix); 03064 } 03065 03066 return false; 03067 } 03068 #endif // WITH_PYTHON