Blender  V2.59
KX_GameObject.cpp
Go to the documentation of this file.
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