Blender V2.61 - r43446

KX_GameObject.cpp

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