4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21 * All rights reserved.
23 * The Original Code is: all of this file.
25 * Contributor(s): none yet.
27 * ***** END GPL LICENSE BLOCK *****
36 typedef unsigned __int64 uint_ptr;
38 typedef unsigned long uint_ptr;
42 // This warning tells us about truncation of __long__ stl-generated names.
43 // It can occasionally cause DevStudio to have internal compiler warnings.
44 #pragma warning( disable : 4786 )
48 #define KX_INERTIA_INFINITE 10000
49 #include "RAS_IPolygonMaterial.h"
50 #include "KX_BlenderMaterial.h"
51 #include "KX_GameObject.h"
52 #include "KX_Camera.h" // only for their ::Type
53 #include "KX_Light.h" // only for their ::Type
54 #include "RAS_MeshObject.h"
55 #include "KX_MeshProxy.h"
56 #include "KX_PolyProxy.h"
57 #include <stdio.h> // printf
58 #include "SG_Controller.h"
59 #include "KX_IPhysicsController.h"
60 #include "PHY_IGraphicController.h"
62 #include "SG_Controller.h"
63 #include "KX_ClientObjectInfo.h"
64 #include "RAS_BucketManager.h"
65 #include "KX_RayCast.h"
66 #include "KX_PythonInit.h"
67 #include "KX_PyMath.h"
68 #include "KX_PythonSeq.h"
69 #include "SCA_IActuator.h"
70 #include "SCA_ISensor.h"
71 #include "SCA_IController.h"
72 #include "NG_NetworkScene.h" //Needed for sendMessage()
74 #include "PyObjectPlus.h" /* python stuff */
76 // This file defines relationships between parents and children
77 // in the game engine.
79 #include "KX_SG_NodeRelationships.h"
81 static MT_Point3 dummy_point= MT_Point3(0.0, 0.0, 0.0);
82 static MT_Vector3 dummy_scaling = MT_Vector3(1.0, 1.0, 1.0);
83 static MT_Matrix3x3 dummy_orientation = MT_Matrix3x3( 1.0, 0.0, 0.0,
87 KX_GameObject::KX_GameObject(
88 void* sgReplicationInfo,
89 SG_Callbacks callbacks,
95 m_pBlenderObject(NULL),
96 m_pBlenderGroupObject(NULL),
97 m_bSuspendDynamics(false),
98 m_bUseObjectColor(false),
99 m_bIsNegativeScaling(false),
103 m_pPhysicsController1(NULL),
104 m_pGraphicController(NULL),
105 m_pPhysicsEnvironment(NULL),
108 m_isDeformable(false),
111 m_ignore_activity_culling = false;
112 m_pClient_info = new KX_ClientObjectInfo(this, KX_ClientObjectInfo::ACTOR);
113 m_pSGNode = new SG_Node(this,sgReplicationInfo,callbacks);
115 // define the relationship between this node and it's parent.
117 KX_NormalParentRelation * parent_relation =
118 KX_NormalParentRelation::New();
119 m_pSGNode->SetParentRelation(parent_relation);
124 KX_GameObject::~KX_GameObject()
128 // is this delete somewhere ?
131 delete m_pClient_info;
136 // must go through controllers and make sure they will not use us anymore
137 // This is important for KX_BulletPhysicsControllers that unregister themselves
138 // from the object when they are deleted.
139 SGControllerList::iterator contit;
140 SGControllerList& controllers = m_pSGNode->GetSGControllerList();
141 for (contit = controllers.begin();contit!=controllers.end();++contit)
143 (*contit)->ClearObject();
145 m_pSGNode->SetSGClientObject(NULL);
147 if (m_pGraphicController)
149 delete m_pGraphicController;
153 PyDict_Clear(m_attr_dict); /* incase of circular refs or other weired cases */
154 Py_DECREF(m_attr_dict);
158 KX_GameObject* KX_GameObject::GetClientObject(KX_ClientObjectInfo* info)
162 return info->m_gameobject;
165 CValue* KX_GameObject:: Calc(VALUE_OPERATOR op, CValue *val)
172 CValue* KX_GameObject::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val)
179 const STR_String & KX_GameObject::GetText()
186 double KX_GameObject::GetNumber()
193 STR_String& KX_GameObject::GetName()
200 void KX_GameObject::SetName(const char *name)
203 }; // Set the name of the value
205 KX_IPhysicsController* KX_GameObject::GetPhysicsController()
207 return m_pPhysicsController1;
210 KX_GameObject* KX_GameObject::GetParent()
212 KX_GameObject* result = NULL;
213 SG_Node* node = m_pSGNode;
215 while (node && !result)
217 node = node->GetSGParent();
219 result = (KX_GameObject*)node->GetSGClientObject();
229 void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj, bool addToCompound, bool ghost)
231 // check on valid node in case a python controller holds a reference to a deleted object
232 if (obj && GetSGNode() && obj->GetSGNode() && GetSGNode()->GetSGParent() != obj->GetSGNode())
234 // Make sure the objects have some scale
235 MT_Vector3 scale1 = NodeGetWorldScaling();
236 MT_Vector3 scale2 = obj->NodeGetWorldScaling();
237 if (fabs(scale2[0]) < FLT_EPSILON ||
238 fabs(scale2[1]) < FLT_EPSILON ||
239 fabs(scale2[2]) < FLT_EPSILON ||
240 fabs(scale1[0]) < FLT_EPSILON ||
241 fabs(scale1[1]) < FLT_EPSILON ||
242 fabs(scale1[2]) < FLT_EPSILON) { return; }
244 // Remove us from our old parent and set our new parent
246 obj->GetSGNode()->AddChild(GetSGNode());
248 if (m_pPhysicsController1)
250 m_pPhysicsController1->SuspendDynamics(ghost);
252 // Set us to our new scale, position, and orientation
253 scale2[0] = 1.0/scale2[0];
254 scale2[1] = 1.0/scale2[1];
255 scale2[2] = 1.0/scale2[2];
256 scale1 = scale1 * scale2;
257 MT_Matrix3x3 invori = obj->NodeGetWorldOrientation().inverse();
258 MT_Vector3 newpos = invori*(NodeGetWorldPosition()-obj->NodeGetWorldPosition())*scale2;
260 NodeSetLocalScale(scale1);
261 NodeSetLocalPosition(MT_Point3(newpos[0],newpos[1],newpos[2]));
262 NodeSetLocalOrientation(invori*NodeGetWorldOrientation());
264 // object will now be a child, it must be removed from the parent list
265 CListValue* rootlist = scene->GetRootParentList();
266 if (rootlist->RemoveValue(this))
267 // the object was in parent list, decrement ref count as it's now removed
269 // if the new parent is a compound object, add this object shape to the compound shape.
270 // step 0: verify this object has physical controller
271 if (m_pPhysicsController1 && addToCompound)
273 // step 1: find the top parent (not necessarily obj)
274 KX_GameObject* rootobj = (KX_GameObject*)obj->GetSGNode()->GetRootSGParent()->GetSGClientObject();
275 // step 2: verify it has a physical controller and compound shape
276 if (rootobj != NULL &&
277 rootobj->m_pPhysicsController1 != NULL &&
278 rootobj->m_pPhysicsController1->IsCompound())
280 rootobj->m_pPhysicsController1->AddCompoundChild(m_pPhysicsController1);
283 // graphically, the object hasn't change place, no need to update m_pGraphicController
287 void KX_GameObject::RemoveParent(KX_Scene *scene)
289 // check on valid node in case a python controller holds a reference to a deleted object
290 if (GetSGNode() && GetSGNode()->GetSGParent())
292 // get the root object to remove us from compound object if needed
293 KX_GameObject* rootobj = (KX_GameObject*)GetSGNode()->GetRootSGParent()->GetSGClientObject();
294 // Set us to the right spot
295 GetSGNode()->SetLocalScale(GetSGNode()->GetWorldScaling());
296 GetSGNode()->SetLocalOrientation(GetSGNode()->GetWorldOrientation());
297 GetSGNode()->SetLocalPosition(GetSGNode()->GetWorldPosition());
299 // Remove us from our parent
300 GetSGNode()->DisconnectFromParent();
302 // the object is now a root object, add it to the parentlist
303 CListValue* rootlist = scene->GetRootParentList();
304 if (!rootlist->SearchValue(this))
305 // object was not in root list, add it now and increment ref count
306 rootlist->Add(AddRef());
307 if (m_pPhysicsController1)
309 // in case this controller was added as a child shape to the parent
310 if (rootobj != NULL &&
311 rootobj->m_pPhysicsController1 != NULL &&
312 rootobj->m_pPhysicsController1->IsCompound())
314 rootobj->m_pPhysicsController1->RemoveCompoundChild(m_pPhysicsController1);
316 m_pPhysicsController1->RestoreDynamics();
317 if (m_pPhysicsController1->IsDyna() && rootobj->m_pPhysicsController1)
319 // dynamic object should remember the velocity they had while being parented
320 MT_Point3 childPoint = GetSGNode()->GetWorldPosition();
321 MT_Point3 rootPoint = rootobj->GetSGNode()->GetWorldPosition();
323 relPoint = (childPoint-rootPoint);
324 MT_Vector3 linVel = rootobj->m_pPhysicsController1->GetVelocity(relPoint);
325 MT_Vector3 angVel = rootobj->m_pPhysicsController1->GetAngularVelocity();
326 m_pPhysicsController1->SetLinearVelocity(linVel, false);
327 m_pPhysicsController1->SetAngularVelocity(angVel, false);
330 // graphically, the object hasn't change place, no need to update m_pGraphicController
334 void KX_GameObject::ProcessReplica()
336 SCA_IObject::ProcessReplica();
338 m_pPhysicsController1 = NULL;
339 m_pGraphicController = NULL;
341 m_pClient_info = new KX_ClientObjectInfo(*m_pClient_info);
342 m_pClient_info->m_gameobject = this;
345 m_attr_dict= PyDict_Copy(m_attr_dict);
349 static void setGraphicController_recursive(SG_Node* node)
351 NodeList& children = node->GetSGChildren();
353 for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
355 SG_Node* childnode = (*childit);
356 KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject());
357 if (clientgameobj != NULL) // This is a GameObject
358 clientgameobj->ActivateGraphicController(false);
360 // if the childobj is NULL then this may be an inverse parent link
361 // so a non recursive search should still look down this node.
362 setGraphicController_recursive(childnode);
367 void KX_GameObject::ActivateGraphicController(bool recurse)
369 if (m_pGraphicController)
371 m_pGraphicController->Activate(m_bVisible);
375 setGraphicController_recursive(GetSGNode());
380 CValue* KX_GameObject::GetReplica()
382 KX_GameObject* replica = new KX_GameObject(*this);
384 // this will copy properties and so on...
385 replica->ProcessReplica();
392 void KX_GameObject::ApplyForce(const MT_Vector3& force,bool local)
394 if (m_pPhysicsController1)
395 m_pPhysicsController1->ApplyForce(force,local);
400 void KX_GameObject::ApplyTorque(const MT_Vector3& torque,bool local)
402 if (m_pPhysicsController1)
403 m_pPhysicsController1->ApplyTorque(torque,local);
408 void KX_GameObject::ApplyMovement(const MT_Vector3& dloc,bool local)
412 if (m_pPhysicsController1) // (IsDynamic())
414 m_pPhysicsController1->RelativeTranslate(dloc,local);
416 GetSGNode()->RelativeTranslate(dloc,GetSGNode()->GetSGParent(),local);
422 void KX_GameObject::ApplyRotation(const MT_Vector3& drot,bool local)
424 MT_Matrix3x3 rotmat(drot);
427 GetSGNode()->RelativeRotate(rotmat,local);
429 if (m_pPhysicsController1) { // (IsDynamic())
430 m_pPhysicsController1->RelativeRotate(rotmat,local);
438 GetOpenGL Matrix, returns an OpenGL 'compatible' matrix
440 double* KX_GameObject::GetOpenGLMatrix()
442 // todo: optimize and only update if necessary
443 double* fl = m_OpenGL_4x4Matrix.getPointer();
447 trans.setOrigin(GetSGNode()->GetWorldPosition());
448 trans.setBasis(GetSGNode()->GetWorldOrientation());
450 MT_Vector3 scaling = GetSGNode()->GetWorldScaling();
451 m_bIsNegativeScaling = ((scaling[0] < 0.0) ^ (scaling[1] < 0.0) ^ (scaling[2] < 0.0)) ? true : false;
452 trans.scale(scaling[0], scaling[1], scaling[2]);
454 GetSGNode()->ClearDirty();
459 void KX_GameObject::AddMeshUser()
461 for (size_t i=0;i<m_meshes.size();i++)
463 m_meshes[i]->AddMeshUser(this, &m_meshSlots, GetDeformer());
465 // set the part of the mesh slot that never change
466 double* fl = GetOpenGLMatrixPtr()->getPointer();
468 SG_QList::iterator<RAS_MeshSlot> mit(m_meshSlots);
470 for(mit.begin(); !mit.end(); ++mit)
472 (*mit)->m_OpenGLMatrix = fl;
474 UpdateBuckets(false);
477 static void UpdateBuckets_recursive(SG_Node* node)
479 NodeList& children = node->GetSGChildren();
481 for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
483 SG_Node* childnode = (*childit);
484 KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject());
485 if (clientgameobj != NULL) // This is a GameObject
486 clientgameobj->UpdateBuckets(0);
488 // if the childobj is NULL then this may be an inverse parent link
489 // so a non recursive search should still look down this node.
490 UpdateBuckets_recursive(childnode);
494 void KX_GameObject::UpdateBuckets( bool recursive )
499 if (GetSGNode()->IsDirty())
502 SG_QList::iterator<RAS_MeshSlot> mit(m_meshSlots);
503 for(mit.begin(); !mit.end(); ++mit)
506 ms->m_bObjectColor = m_bUseObjectColor;
507 ms->m_RGBAcolor = m_objectColor;
508 ms->m_bVisible = m_bVisible;
509 ms->m_bCulled = m_bCulled || !m_bVisible;
511 ms->m_bucket->ActivateMesh(ms);
513 /* split if necessary */
520 UpdateBuckets_recursive(GetSGNode());
525 void KX_GameObject::RemoveMeshes()
527 for (size_t i=0;i<m_meshes.size();i++)
528 m_meshes[i]->RemoveFromBuckets(this);
530 //note: meshes can be shared, and are deleted by KX_BlenderSceneConverter
535 void KX_GameObject::UpdateTransform()
537 // HACK: saves function call for dynamic object, they are handled differently
538 if (m_pPhysicsController1 && !m_pPhysicsController1->IsDyna())
539 // Note that for Bullet, this does not even update the transform of static object
540 // but merely sets there collision flag to "kinematic" because the synchronization is
541 // done during physics simulation
542 m_pPhysicsController1->SetSumoTransform(true);
543 if (m_pGraphicController)
544 // update the culling tree
545 m_pGraphicController->SetGraphicTransform();
549 void KX_GameObject::UpdateTransformFunc(SG_IObject* node, void* gameobj, void* scene)
551 ((KX_GameObject*)gameobj)->UpdateTransform();
554 void KX_GameObject::SynchronizeTransform()
556 // only used for sensor object, do full synchronization as bullet doesn't do it
557 if (m_pPhysicsController1)
558 m_pPhysicsController1->SetTransform();
559 if (m_pGraphicController)
560 m_pGraphicController->SetGraphicTransform();
563 void KX_GameObject::SynchronizeTransformFunc(SG_IObject* node, void* gameobj, void* scene)
565 ((KX_GameObject*)gameobj)->SynchronizeTransform();
569 void KX_GameObject::SetDebugColor(unsigned int bgra)
571 for (size_t i=0;i<m_meshes.size();i++)
572 m_meshes[i]->DebugColor(bgra);
577 void KX_GameObject::ResetDebugColor()
579 SetDebugColor(0xff000000);
582 void KX_GameObject::InitIPO(bool ipo_as_force,
586 SGControllerList::iterator it = GetSGNode()->GetSGControllerList().begin();
588 while (it != GetSGNode()->GetSGControllerList().end()) {
589 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_RESET, true);
590 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_AS_FORCE, ipo_as_force);
591 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_ADD, ipo_add);
592 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_LOCAL, ipo_local);
597 void KX_GameObject::UpdateIPO(float curframetime,
600 // just the 'normal' update procedure.
601 GetSGNode()->SetSimulatedTime(curframetime,recurse);
602 GetSGNode()->UpdateWorldData(curframetime);
608 KX_GameObject::UpdateMaterialData(
621 if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0) {
622 list<RAS_MeshMaterial>::iterator mit = m_meshes[mesh]->GetFirstMaterial();
624 for(; mit != m_meshes[mesh]->GetLastMaterial(); ++mit)
626 RAS_IPolyMaterial* poly = mit->m_bucket->GetPolyMaterial();
628 if(poly->GetFlag() & RAS_BLENDERMAT )
630 KX_BlenderMaterial *m = static_cast<KX_BlenderMaterial*>(poly);
632 if (matname_hash == 0)
634 m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha);
635 // if mesh has only one material attached to it then use original hack with no need to edit vertices (better performance)
636 SetObjectColor(rgba);
640 if (matname_hash == poly->GetMaterialNameHash())
642 m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha);
643 m_meshes[mesh]->SetVertexColor(poly,rgba);
645 // no break here, because one blender material can be split into several game engine materials
646 // (e.g. one uvsphere material is split into one material at poles with ras_mode TRIANGLE and one material for the body
647 // if here was a break then would miss some vertices if material was split
655 KX_GameObject::GetVisible(
662 static void setVisible_recursive(SG_Node* node, bool v)
664 NodeList& children = node->GetSGChildren();
666 for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
668 SG_Node* childnode = (*childit);
669 KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject());
670 if (clientgameobj != NULL) // This is a GameObject
671 clientgameobj->SetVisible(v, 0);
673 // if the childobj is NULL then this may be an inverse parent link
674 // so a non recursive search should still look down this node.
675 setVisible_recursive(childnode, v);
681 KX_GameObject::SetVisible(
688 if (m_pGraphicController)
689 m_pGraphicController->Activate(m_bVisible);
691 setVisible_recursive(GetSGNode(), v);
695 static void setOccluder_recursive(SG_Node* node, bool v)
697 NodeList& children = node->GetSGChildren();
699 for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
701 SG_Node* childnode = (*childit);
702 KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject());
703 if (clientgameobj != NULL) // This is a GameObject
704 clientgameobj->SetOccluder(v, false);
706 // if the childobj is NULL then this may be an inverse parent link
707 // so a non recursive search should still look down this node.
708 setOccluder_recursive(childnode, v);
713 KX_GameObject::SetOccluder(
721 setOccluder_recursive(GetSGNode(), v);
726 KX_GameObject::SetLayer(
734 KX_GameObject::GetLayer(
741 void KX_GameObject::addLinearVelocity(const MT_Vector3& lin_vel,bool local)
743 if (m_pPhysicsController1)
745 MT_Vector3 lv = local ? NodeGetWorldOrientation() * lin_vel : lin_vel;
746 m_pPhysicsController1->SetLinearVelocity(lv + m_pPhysicsController1->GetLinearVelocity(), 0);
752 void KX_GameObject::setLinearVelocity(const MT_Vector3& lin_vel,bool local)
754 if (m_pPhysicsController1)
755 m_pPhysicsController1->SetLinearVelocity(lin_vel,local);
760 void KX_GameObject::setAngularVelocity(const MT_Vector3& ang_vel,bool local)
762 if (m_pPhysicsController1)
763 m_pPhysicsController1->SetAngularVelocity(ang_vel,local);
767 void KX_GameObject::ResolveCombinedVelocities(
768 const MT_Vector3 & lin_vel,
769 const MT_Vector3 & ang_vel,
773 if (m_pPhysicsController1)
776 MT_Vector3 lv = lin_vel_local ? NodeGetWorldOrientation() * lin_vel : lin_vel;
777 MT_Vector3 av = ang_vel_local ? NodeGetWorldOrientation() * ang_vel : ang_vel;
778 m_pPhysicsController1->resolveCombinedVelocities(
779 lv.x(),lv.y(),lv.z(),av.x(),av.y(),av.z());
784 void KX_GameObject::SetObjectColor(const MT_Vector4& rgbavec)
786 m_bUseObjectColor = true;
787 m_objectColor = rgbavec;
790 void KX_GameObject::AlignAxisToVect(const MT_Vector3& dir, int axis, float fac)
793 MT_Vector3 vect,ori,z,x,y;
796 // check on valid node in case a python controller holds a reference to a deleted object
802 if (MT_fuzzyZero(len))
804 cout << "alignAxisToVect() Error: Null vector!\n";
814 orimat = GetSGNode()->GetWorldOrientation();
818 ori.setValue(orimat[0][2], orimat[1][2], orimat[2][2]); //pivot axis
819 if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON) //is the vector paralell to the pivot?
820 ori.setValue(orimat[0][1], orimat[1][1], orimat[2][1]); //change the pivot!
824 x = (vect * fac) + ((orimat * MT_Vector3(1.0, 0.0, 0.0)) * (1-fac));
826 if (MT_fuzzyZero(len)) x = vect;
833 ori.setValue(orimat[0][0], orimat[1][0], orimat[2][0]);
834 if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON)
835 ori.setValue(orimat[0][2], orimat[1][2], orimat[2][2]);
839 y = (vect * fac) + ((orimat * MT_Vector3(0.0, 1.0, 0.0)) * (1-fac));
841 if (MT_fuzzyZero(len)) y = vect;
848 ori.setValue(orimat[0][1], orimat[1][1], orimat[2][1]);
849 if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON)
850 ori.setValue(orimat[0][0], orimat[1][0], orimat[2][0]);
854 z = (vect * fac) + ((orimat * MT_Vector3(0.0, 0.0, 1.0)) * (1-fac));
856 if (MT_fuzzyZero(len)) z = vect;
862 default: //wrong input?
863 cout << "alignAxisToVect(): Wrong axis '" << axis <<"'\n";
866 x.normalize(); //normalize the vectors
869 orimat.setValue( x[0],y[0],z[0],
872 if (GetSGNode()->GetSGParent() != NULL)
874 // the object is a child, adapt its local orientation so that
875 // the global orientation is aligned as we want.
876 MT_Matrix3x3 invori = GetSGNode()->GetSGParent()->GetWorldOrientation().inverse();
877 NodeSetLocalOrientation(invori*orimat);
880 NodeSetLocalOrientation(orimat);
883 MT_Scalar KX_GameObject::GetMass()
885 if (m_pPhysicsController1)
887 return m_pPhysicsController1->GetMass();
892 MT_Vector3 KX_GameObject::GetLocalInertia()
894 MT_Vector3 local_inertia(0.0,0.0,0.0);
895 if (m_pPhysicsController1)
897 local_inertia = m_pPhysicsController1->GetLocalInertia();
899 return local_inertia;
902 MT_Vector3 KX_GameObject::GetLinearVelocity(bool local)
904 MT_Vector3 velocity(0.0,0.0,0.0), locvel;
906 if (m_pPhysicsController1)
908 velocity = m_pPhysicsController1->GetLinearVelocity();
912 ori = GetSGNode()->GetWorldOrientation();
914 locvel = velocity * ori;
921 MT_Vector3 KX_GameObject::GetAngularVelocity(bool local)
923 MT_Vector3 velocity(0.0,0.0,0.0), locvel;
925 if (m_pPhysicsController1)
927 velocity = m_pPhysicsController1->GetAngularVelocity();
931 ori = GetSGNode()->GetWorldOrientation();
933 locvel = velocity * ori;
940 MT_Vector3 KX_GameObject::GetVelocity(const MT_Point3& point)
942 if (m_pPhysicsController1)
944 return m_pPhysicsController1->GetVelocity(point);
946 return MT_Vector3(0.0,0.0,0.0);
949 // scenegraph node stuff
951 void KX_GameObject::NodeSetLocalPosition(const MT_Point3& trans)
953 // check on valid node in case a python controller holds a reference to a deleted object
957 if (m_pPhysicsController1 && !GetSGNode()->GetSGParent())
959 // don't update physic controller if the object is a child:
960 // 1) the transformation will not be right
961 // 2) in this case, the physic controller is necessarily a static object
962 // that is updated from the normal kinematic synchronization
963 m_pPhysicsController1->setPosition(trans);
966 GetSGNode()->SetLocalPosition(trans);
972 void KX_GameObject::NodeSetLocalOrientation(const MT_Matrix3x3& rot)
974 // check on valid node in case a python controller holds a reference to a deleted object
978 if (m_pPhysicsController1 && !GetSGNode()->GetSGParent())
981 m_pPhysicsController1->setOrientation(rot);
983 GetSGNode()->SetLocalOrientation(rot);
986 void KX_GameObject::NodeSetGlobalOrientation(const MT_Matrix3x3& rot)
988 // check on valid node in case a python controller holds a reference to a deleted object
992 if (GetSGNode()->GetSGParent())
993 GetSGNode()->SetLocalOrientation(GetSGNode()->GetSGParent()->GetWorldOrientation().inverse()*rot);
995 GetSGNode()->SetLocalOrientation(rot);
998 void KX_GameObject::NodeSetLocalScale(const MT_Vector3& scale)
1000 // check on valid node in case a python controller holds a reference to a deleted object
1004 if (m_pPhysicsController1 && !GetSGNode()->GetSGParent())
1007 m_pPhysicsController1->setScaling(scale);
1009 GetSGNode()->SetLocalScale(scale);
1014 void KX_GameObject::NodeSetRelativeScale(const MT_Vector3& scale)
1018 GetSGNode()->RelativeScale(scale);
1019 if (m_pPhysicsController1 && (!GetSGNode()->GetSGParent()))
1022 // we can use the local scale: it's the same thing for a root object
1023 // and the world scale is not yet updated
1024 MT_Vector3 newscale = GetSGNode()->GetLocalScale();
1025 m_pPhysicsController1->setScaling(newscale);
1030 void KX_GameObject::NodeSetWorldPosition(const MT_Point3& trans)
1034 SG_Node* parent = GetSGNode()->GetSGParent();
1037 // Make sure the objects have some scale
1038 MT_Vector3 scale = parent->GetWorldScaling();
1039 if (fabs(scale[0]) < FLT_EPSILON ||
1040 fabs(scale[1]) < FLT_EPSILON ||
1041 fabs(scale[2]) < FLT_EPSILON)
1045 scale[0] = 1.0/scale[0];
1046 scale[1] = 1.0/scale[1];
1047 scale[2] = 1.0/scale[2];
1048 MT_Matrix3x3 invori = parent->GetWorldOrientation().inverse();
1049 MT_Vector3 newpos = invori*(trans-parent->GetWorldPosition())*scale;
1050 NodeSetLocalPosition(MT_Point3(newpos[0],newpos[1],newpos[2]));
1054 NodeSetLocalPosition(trans);
1059 void KX_GameObject::NodeUpdateGS(double time)
1062 GetSGNode()->UpdateWorldData(time);
1067 const MT_Matrix3x3& KX_GameObject::NodeGetWorldOrientation() const
1069 // check on valid node in case a python controller holds a reference to a deleted object
1071 return dummy_orientation;
1072 return GetSGNode()->GetWorldOrientation();
1075 const MT_Matrix3x3& KX_GameObject::NodeGetLocalOrientation() const
1077 // check on valid node in case a python controller holds a reference to a deleted object
1079 return dummy_orientation;
1080 return GetSGNode()->GetLocalOrientation();
1083 const MT_Vector3& KX_GameObject::NodeGetWorldScaling() const
1085 // check on valid node in case a python controller holds a reference to a deleted object
1087 return dummy_scaling;
1089 return GetSGNode()->GetWorldScaling();
1092 const MT_Vector3& KX_GameObject::NodeGetLocalScaling() const
1094 // check on valid node in case a python controller holds a reference to a deleted object
1096 return dummy_scaling;
1098 return GetSGNode()->GetLocalScale();
1101 const MT_Point3& KX_GameObject::NodeGetWorldPosition() const
1103 // check on valid node in case a python controller holds a reference to a deleted object
1105 return GetSGNode()->GetWorldPosition();
1110 const MT_Point3& KX_GameObject::NodeGetLocalPosition() const
1112 // check on valid node in case a python controller holds a reference to a deleted object
1114 return GetSGNode()->GetLocalPosition();
1120 /* Suspend/ resume: for the dynamic behaviour, there is a simple
1121 * method. For the residual motion, there is not. I wonder what the
1122 * correct solution is for Sumo. Remove from the motion-update tree?
1124 * So far, only switch the physics and logic.
1127 void KX_GameObject::Resume(void)
1130 SCA_IObject::Resume();
1131 if(GetPhysicsController())
1132 GetPhysicsController()->RestoreDynamics();
1134 m_suspended = false;
1138 void KX_GameObject::Suspend()
1140 if ((!m_ignore_activity_culling)
1141 && (!m_suspended)) {
1142 SCA_IObject::Suspend();
1143 if(GetPhysicsController())
1144 GetPhysicsController()->SuspendDynamics();
1149 static void walk_children(SG_Node* node, CListValue* list, bool recursive)
1153 NodeList& children = node->GetSGChildren();
1155 for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
1157 SG_Node* childnode = (*childit);
1158 CValue* childobj = (CValue*)childnode->GetSGClientObject();
1159 if (childobj != NULL) // This is a GameObject
1162 list->Add(childobj->AddRef());
1165 // if the childobj is NULL then this may be an inverse parent link
1166 // so a non recursive search should still look down this node.
1167 if (recursive || childobj==NULL) {
1168 walk_children(childnode, list, recursive);
1173 CListValue* KX_GameObject::GetChildren()
1175 CListValue* list = new CListValue();
1176 walk_children(GetSGNode(), list, 0); /* GetSGNode() is always valid or it would have raised an exception before this */
1180 CListValue* KX_GameObject::GetChildrenRecursive()
1182 CListValue* list = new CListValue();
1183 walk_children(GetSGNode(), list, 1);
1187 #ifdef USE_MATHUTILS
1189 /* These require an SGNode */
1190 #define MATHUTILS_VEC_CB_POS_LOCAL 1
1191 #define MATHUTILS_VEC_CB_POS_GLOBAL 2
1192 #define MATHUTILS_VEC_CB_SCALE_LOCAL 3
1193 #define MATHUTILS_VEC_CB_SCALE_GLOBAL 4
1194 #define MATHUTILS_VEC_CB_INERTIA_LOCAL 5
1196 static int mathutils_kxgameob_vector_cb_index= -1; /* index for our callbacks */
1198 static int mathutils_kxgameob_generic_check(PyObject *self_v)
1200 KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
1207 static int mathutils_kxgameob_vector_get(PyObject *self_v, int subtype, float *vec_from)
1209 KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
1214 case MATHUTILS_VEC_CB_POS_LOCAL:
1215 self->NodeGetLocalPosition().getValue(vec_from);
1217 case MATHUTILS_VEC_CB_POS_GLOBAL:
1218 self->NodeGetWorldPosition().getValue(vec_from);
1220 case MATHUTILS_VEC_CB_SCALE_LOCAL:
1221 self->NodeGetLocalScaling().getValue(vec_from);
1223 case MATHUTILS_VEC_CB_SCALE_GLOBAL:
1224 self->NodeGetWorldScaling().getValue(vec_from);
1226 case MATHUTILS_VEC_CB_INERTIA_LOCAL:
1227 if(!self->GetPhysicsController()) return 0;
1228 self->GetPhysicsController()->GetLocalInertia().getValue(vec_from);
1235 static int mathutils_kxgameob_vector_set(PyObject *self_v, int subtype, float *vec_to)
1237 KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
1242 case MATHUTILS_VEC_CB_POS_LOCAL:
1243 self->NodeSetLocalPosition(MT_Point3(vec_to));
1244 self->NodeUpdateGS(0.f);
1246 case MATHUTILS_VEC_CB_POS_GLOBAL:
1247 self->NodeSetWorldPosition(MT_Point3(vec_to));
1248 self->NodeUpdateGS(0.f);
1250 case MATHUTILS_VEC_CB_SCALE_LOCAL:
1251 self->NodeSetLocalScale(MT_Point3(vec_to));
1252 self->NodeUpdateGS(0.f);
1254 case MATHUTILS_VEC_CB_SCALE_GLOBAL:
1256 case MATHUTILS_VEC_CB_INERTIA_LOCAL:
1264 static int mathutils_kxgameob_vector_get_index(PyObject *self_v, int subtype, float *vec_from, int index)
1267 /* lazy, avoid repeteing the case statement */
1268 if(!mathutils_kxgameob_vector_get(self_v, subtype, f))
1271 vec_from[index]= f[index];
1275 static int mathutils_kxgameob_vector_set_index(PyObject *self_v, int subtype, float *vec_to, int index)
1277 float f= vec_to[index];
1279 /* lazy, avoid repeteing the case statement */
1280 if(!mathutils_kxgameob_vector_get(self_v, subtype, vec_to))
1284 mathutils_kxgameob_vector_set(self_v, subtype, vec_to);
1289 Mathutils_Callback mathutils_kxgameob_vector_cb = {
1290 mathutils_kxgameob_generic_check,
1291 mathutils_kxgameob_vector_get,
1292 mathutils_kxgameob_vector_set,
1293 mathutils_kxgameob_vector_get_index,
1294 mathutils_kxgameob_vector_set_index
1298 #define MATHUTILS_MAT_CB_ORI_LOCAL 1
1299 #define MATHUTILS_MAT_CB_ORI_GLOBAL 2
1301 static int mathutils_kxgameob_matrix_cb_index= -1; /* index for our callbacks */
1303 static int mathutils_kxgameob_matrix_get(PyObject *self_v, int subtype, float *mat_from)
1305 KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
1310 case MATHUTILS_MAT_CB_ORI_LOCAL:
1311 self->NodeGetLocalOrientation().getValue3x3(mat_from);
1313 case MATHUTILS_MAT_CB_ORI_GLOBAL:
1314 self->NodeGetWorldOrientation().getValue3x3(mat_from);
1322 static int mathutils_kxgameob_matrix_set(PyObject *self_v, int subtype, float *mat_to)
1324 KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
1328 MT_Matrix3x3 mat3x3;
1330 case MATHUTILS_MAT_CB_ORI_LOCAL:
1331 mat3x3.setValue3x3(mat_to);
1332 self->NodeSetLocalOrientation(mat3x3);
1333 self->NodeUpdateGS(0.f);
1335 case MATHUTILS_MAT_CB_ORI_GLOBAL:
1336 mat3x3.setValue3x3(mat_to);
1337 self->NodeSetLocalOrientation(mat3x3);
1338 self->NodeUpdateGS(0.f);
1345 Mathutils_Callback mathutils_kxgameob_matrix_cb = {
1346 mathutils_kxgameob_generic_check,
1347 mathutils_kxgameob_matrix_get,
1348 mathutils_kxgameob_matrix_set,
1354 void KX_GameObject_Mathutils_Callback_Init(void)
1356 // register mathutils callbacks, ok to run more then once.
1357 mathutils_kxgameob_vector_cb_index= Mathutils_RegisterCallback(&mathutils_kxgameob_vector_cb);
1358 mathutils_kxgameob_matrix_cb_index= Mathutils_RegisterCallback(&mathutils_kxgameob_matrix_cb);
1361 #endif // USE_MATHUTILS
1363 /* ------- python stuff ---------------------------------------------------*/
1365 PyMethodDef KX_GameObject::Methods[] = {
1366 {"applyForce", (PyCFunction) KX_GameObject::sPyApplyForce, METH_VARARGS},
1367 {"applyTorque", (PyCFunction) KX_GameObject::sPyApplyTorque, METH_VARARGS},
1368 {"applyRotation", (PyCFunction) KX_GameObject::sPyApplyRotation, METH_VARARGS},
1369 {"applyMovement", (PyCFunction) KX_GameObject::sPyApplyMovement, METH_VARARGS},
1370 {"getLinearVelocity", (PyCFunction) KX_GameObject::sPyGetLinearVelocity, METH_VARARGS},
1371 {"setLinearVelocity", (PyCFunction) KX_GameObject::sPySetLinearVelocity, METH_VARARGS},
1372 {"getAngularVelocity", (PyCFunction) KX_GameObject::sPyGetAngularVelocity, METH_VARARGS},
1373 {"setAngularVelocity", (PyCFunction) KX_GameObject::sPySetAngularVelocity, METH_VARARGS},
1374 {"getVelocity", (PyCFunction) KX_GameObject::sPyGetVelocity, METH_VARARGS},
1375 {"getReactionForce", (PyCFunction) KX_GameObject::sPyGetReactionForce, METH_NOARGS},
1376 {"alignAxisToVect",(PyCFunction) KX_GameObject::sPyAlignAxisToVect, METH_VARARGS},
1377 {"getAxisVect",(PyCFunction) KX_GameObject::sPyGetAxisVect, METH_O},
1378 {"suspendDynamics", (PyCFunction)KX_GameObject::sPySuspendDynamics,METH_NOARGS},
1379 {"restoreDynamics", (PyCFunction)KX_GameObject::sPyRestoreDynamics,METH_NOARGS},
1380 {"enableRigidBody", (PyCFunction)KX_GameObject::sPyEnableRigidBody,METH_NOARGS},
1381 {"disableRigidBody", (PyCFunction)KX_GameObject::sPyDisableRigidBody,METH_NOARGS},
1382 {"applyImpulse", (PyCFunction) KX_GameObject::sPyApplyImpulse, METH_VARARGS},
1383 {"setCollisionMargin", (PyCFunction) KX_GameObject::sPySetCollisionMargin, METH_O},
1384 {"setParent", (PyCFunction)KX_GameObject::sPySetParent,METH_VARARGS},
1385 {"setVisible",(PyCFunction) KX_GameObject::sPySetVisible, METH_VARARGS},
1386 {"setOcclusion",(PyCFunction) KX_GameObject::sPySetOcclusion, METH_VARARGS},
1387 {"removeParent", (PyCFunction)KX_GameObject::sPyRemoveParent,METH_NOARGS},
1388 {"getChildren", (PyCFunction)KX_GameObject::sPyGetChildren,METH_NOARGS},
1389 {"getChildrenRecursive", (PyCFunction)KX_GameObject::sPyGetChildrenRecursive,METH_NOARGS},
1390 {"getPhysicsId", (PyCFunction)KX_GameObject::sPyGetPhysicsId,METH_NOARGS},
1391 {"getPropertyNames", (PyCFunction)KX_GameObject::sPyGetPropertyNames,METH_NOARGS},
1392 {"replaceMesh",(PyCFunction) KX_GameObject::sPyReplaceMesh, METH_O},
1393 {"endObject",(PyCFunction) KX_GameObject::sPyEndObject, METH_NOARGS},
1395 KX_PYMETHODTABLE(KX_GameObject, rayCastTo),
1396 KX_PYMETHODTABLE(KX_GameObject, rayCast),
1397 KX_PYMETHODTABLE_O(KX_GameObject, getDistanceTo),
1398 KX_PYMETHODTABLE_O(KX_GameObject, getVectTo),
1399 KX_PYMETHODTABLE(KX_GameObject, sendMessage),
1401 // dict style access for props
1402 {"has_key",(PyCFunction) KX_GameObject::sPyhas_key, METH_O},
1403 {"get",(PyCFunction) KX_GameObject::sPyget, METH_VARARGS},
1406 {"getPosition", (PyCFunction) KX_GameObject::sPyGetPosition, METH_NOARGS},
1407 {"setPosition", (PyCFunction) KX_GameObject::sPySetPosition, METH_O},
1408 {"setWorldPosition", (PyCFunction) KX_GameObject::sPySetWorldPosition, METH_O},
1409 {"getOrientation", (PyCFunction) KX_GameObject::sPyGetOrientation, METH_NOARGS},
1410 {"setOrientation", (PyCFunction) KX_GameObject::sPySetOrientation, METH_O},
1411 {"getState",(PyCFunction) KX_GameObject::sPyGetState, METH_NOARGS},
1412 {"setState",(PyCFunction) KX_GameObject::sPySetState, METH_O},
1413 {"getParent", (PyCFunction)KX_GameObject::sPyGetParent,METH_NOARGS},
1414 {"getVisible",(PyCFunction) KX_GameObject::sPyGetVisible, METH_NOARGS},
1415 {"getMass", (PyCFunction) KX_GameObject::sPyGetMass, METH_NOARGS},
1416 {"getMesh", (PyCFunction)KX_GameObject::sPyGetMesh,METH_VARARGS},
1417 {NULL,NULL} //Sentinel
1420 PyAttributeDef KX_GameObject::Attributes[] = {
1421 KX_PYATTRIBUTE_RO_FUNCTION("name", KX_GameObject, pyattr_get_name),
1422 KX_PYATTRIBUTE_RO_FUNCTION("parent", KX_GameObject, pyattr_get_parent),
1423 KX_PYATTRIBUTE_RW_FUNCTION("mass", KX_GameObject, pyattr_get_mass, pyattr_set_mass),
1424 KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMin", KX_GameObject, pyattr_get_lin_vel_min, pyattr_set_lin_vel_min),
1425 KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMax", KX_GameObject, pyattr_get_lin_vel_max, pyattr_set_lin_vel_max),
1426 KX_PYATTRIBUTE_RW_FUNCTION("visible", KX_GameObject, pyattr_get_visible, pyattr_set_visible),
1427 KX_PYATTRIBUTE_BOOL_RW ("occlusion", KX_GameObject, m_bOccluder),
1428 KX_PYATTRIBUTE_RW_FUNCTION("position", KX_GameObject, pyattr_get_worldPosition, pyattr_set_localPosition),
1429 KX_PYATTRIBUTE_RO_FUNCTION("localInertia", KX_GameObject, pyattr_get_localInertia),
1430 KX_PYATTRIBUTE_RW_FUNCTION("orientation",KX_GameObject,pyattr_get_worldOrientation,pyattr_set_localOrientation),
1431 KX_PYATTRIBUTE_RW_FUNCTION("scaling", KX_GameObject, pyattr_get_worldScaling, pyattr_set_localScaling),
1432 KX_PYATTRIBUTE_RW_FUNCTION("timeOffset",KX_GameObject, pyattr_get_timeOffset,pyattr_set_timeOffset),
1433 KX_PYATTRIBUTE_RW_FUNCTION("state", KX_GameObject, pyattr_get_state, pyattr_set_state),
1434 KX_PYATTRIBUTE_RO_FUNCTION("meshes", KX_GameObject, pyattr_get_meshes),
1435 KX_PYATTRIBUTE_RW_FUNCTION("localOrientation",KX_GameObject,pyattr_get_localOrientation,pyattr_set_localOrientation),
1436 KX_PYATTRIBUTE_RW_FUNCTION("worldOrientation",KX_GameObject,pyattr_get_worldOrientation,pyattr_set_worldOrientation),
1437 KX_PYATTRIBUTE_RW_FUNCTION("localPosition", KX_GameObject, pyattr_get_localPosition, pyattr_set_localPosition),
1438 KX_PYATTRIBUTE_RW_FUNCTION("worldPosition", KX_GameObject, pyattr_get_worldPosition, pyattr_set_worldPosition),
1439 KX_PYATTRIBUTE_RW_FUNCTION("localScale", KX_GameObject, pyattr_get_localScaling, pyattr_set_localScaling),
1440 KX_PYATTRIBUTE_RO_FUNCTION("worldScale", KX_GameObject, pyattr_get_worldScaling),
1441 KX_PYATTRIBUTE_RO_FUNCTION("children", KX_GameObject, pyattr_get_children),
1442 KX_PYATTRIBUTE_RO_FUNCTION("childrenRecursive", KX_GameObject, pyattr_get_children_recursive),
1443 KX_PYATTRIBUTE_RO_FUNCTION("attrDict", KX_GameObject, pyattr_get_attrDict),
1445 /* Experemental, dont rely on these yet */
1446 KX_PYATTRIBUTE_RO_FUNCTION("sensors", KX_GameObject, pyattr_get_sensors),
1447 KX_PYATTRIBUTE_RO_FUNCTION("controllers", KX_GameObject, pyattr_get_controllers),
1448 KX_PYATTRIBUTE_RO_FUNCTION("actuators", KX_GameObject, pyattr_get_actuators),
1454 bool KX_GameObject::ConvertPythonVectorArgs(PyObject* args,
1460 bool error = (PyArg_ParseTuple(args,"OO",&pylist,&pylist2)) != 0;
1462 pos = ConvertPythonPylist(pylist);
1463 pos2 = ConvertPythonPylist(pylist2);
1469 PyObject* KX_GameObject::PyReplaceMesh(PyObject* value)
1471 KX_Scene *scene = KX_GetActiveScene();
1472 RAS_MeshObject* new_mesh;
1474 if (!ConvertPythonToMesh(value, &new_mesh, false, "gameOb.replaceMesh(value): KX_GameObject"))
1477 scene->ReplaceMesh(this, new_mesh);
1481 PyObject* KX_GameObject::PyEndObject()
1483 KX_Scene *scene = KX_GetActiveScene();
1485 scene->DelayedRemoveObject(this);
1492 PyObject* KX_GameObject::PyGetPosition()
1494 ShowDeprecationWarning("getPosition()", "the position property");
1495 return PyObjectFrom(NodeGetWorldPosition());
1498 static PyObject *Map_GetItem(PyObject *self_v, PyObject *item)
1500 KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
1501 const char *attr_str= PyString_AsString(item);
1503 PyObject* pyconvert;
1506 PyErr_SetString(PyExc_SystemError, "val = gameOb[key]: KX_GameObject, "BGE_PROXY_ERROR_MSG);
1510 /* first see if the attributes a string and try get the cvalue attribute */
1511 if(attr_str && (resultattr=self->GetProperty(attr_str))) {
1512 pyconvert = resultattr->ConvertValueToPython();
1513 return pyconvert ? pyconvert:resultattr->GetProxy();
1515 /* no CValue attribute, try get the python only m_attr_dict attribute */
1516 else if (self->m_attr_dict && (pyconvert=PyDict_GetItem(self->m_attr_dict, item))) {
1520 Py_INCREF(pyconvert);
1524 if(attr_str) PyErr_Format(PyExc_KeyError, "value = gameOb[key]: KX_GameObject, key \"%s\" does not exist", attr_str);
1525 else PyErr_SetString(PyExc_KeyError, "value = gameOb[key]: KX_GameObject, key does not exist");
1532 static int Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val)
1534 KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
1535 const char *attr_str= PyString_AsString(key);
1540 PyErr_SetString(PyExc_SystemError, "gameOb[key] = value: KX_GameObject, "BGE_PROXY_ERROR_MSG);
1544 if (val==NULL) { /* del ob["key"] */
1547 /* try remove both just incase */
1549 del |= (self->RemoveProperty(attr_str)==true) ? 1:0;
1551 if(self->m_attr_dict)
1552 del |= (PyDict_DelItem(self->m_attr_dict, key)==0) ? 1:0;
1555 if(attr_str) PyErr_Format(PyExc_KeyError, "gameOb[key] = value: KX_GameObject, key \"%s\" could not be set", attr_str);
1556 else PyErr_SetString(PyExc_KeyError, "del gameOb[key]: KX_GameObject, key could not be deleted");
1559 else if (self->m_attr_dict) {
1560 PyErr_Clear(); /* PyDict_DelItem sets an error when it fails */
1563 else { /* ob["key"] = value */
1567 if(attr_str && BGE_PROXY_CHECK_TYPE(val)==0) /* dont allow GameObjects for eg to be assigned to CValue props */
1569 CValue* vallie = self->ConvertPythonToValue(val, ""); /* error unused */
1573 CValue* oldprop = self->GetProperty(attr_str);
1576 oldprop->SetValue(vallie);
1578 self->SetProperty(attr_str, vallie);
1583 /* try remove dict value to avoid double ups */
1584 if (self->m_attr_dict){
1585 if (PyDict_DelItem(self->m_attr_dict, key) != 0)
1596 if (self->m_attr_dict==NULL) /* lazy init */
1597 self->m_attr_dict= PyDict_New();
1600 if(PyDict_SetItem(self->m_attr_dict, key, val)==0)
1603 self->RemoveProperty(attr_str); /* overwrite the CValue if it exists */
1607 if(attr_str) PyErr_Format(PyExc_KeyError, "gameOb[key] = value: KX_GameObject, key \"%s\" not be added to internal dictionary", attr_str);
1608 else PyErr_SetString(PyExc_KeyError, "gameOb[key] = value: KX_GameObject, key not be added to internal dictionary");
1613 return -1; /* pythons error value */
1617 return 0; /* success */
1620 static int Seq_Contains(PyObject *self_v, PyObject *value)
1622 KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
1625 PyErr_SetString(PyExc_SystemError, "val in gameOb: KX_GameObject, "BGE_PROXY_ERROR_MSG);
1629 if(PyString_Check(value) && self->GetProperty(PyString_AsString(value)))
1632 if (self->m_attr_dict && PyDict_GetItem(self->m_attr_dict, value))
1639 PyMappingMethods KX_GameObject::Mapping = {
1640 (lenfunc)NULL , /*inquiry mp_length */
1641 (binaryfunc)Map_GetItem, /*binaryfunc mp_subscript */
1642 (objobjargproc)Map_SetItem, /*objobjargproc mp_ass_subscript */
1645 PySequenceMethods KX_GameObject::Sequence = {
1646 NULL, /* Cant set the len otherwise it can evaluate as false */
1647 NULL, /* sq_concat */
1648 NULL, /* sq_repeat */
1650 NULL, /* sq_slice */
1651 NULL, /* sq_ass_item */
1652 NULL, /* sq_ass_slice */
1653 (objobjproc)Seq_Contains, /* sq_contains */
1656 PyTypeObject KX_GameObject::Type = {
1657 #if (PY_VERSION_HEX >= 0x02060000)
1658 PyVarObject_HEAD_INIT(NULL, 0)
1660 /* python 2.5 and below */
1661 PyObject_HEAD_INIT( NULL ) /* required py macro */
1665 sizeof(PyObjectPlus_Proxy),
1690 PyParentObject KX_GameObject::Parents[] = {
1691 &KX_GameObject::Type,
1697 PyObject* KX_GameObject::pyattr_get_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1699 KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1700 return PyString_FromString(self->GetName().ReadPtr());
1703 PyObject* KX_GameObject::pyattr_get_parent(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1705 KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1706 KX_GameObject* parent = self->GetParent();
1708 parent->Release(); /* self->GetParent() AddRef's */
1709 return parent->GetProxy();
1714 PyObject* KX_GameObject::pyattr_get_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1716 KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1717 KX_IPhysicsController *spc = self->GetPhysicsController();
1718 return PyFloat_FromDouble(spc ? spc->GetMass() : 0.0f);
1721 int KX_GameObject::pyattr_set_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1723 KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1724 KX_IPhysicsController *spc = self->GetPhysicsController();
1725 MT_Scalar val = PyFloat_AsDouble(value);
1726 if (val < 0.0f) { /* also accounts for non float */
1727 PyErr_SetString(PyExc_AttributeError, "gameOb.mass = float: KX_GameObject, expected a float zero or above");
1728 return PY_SET_ATTR_FAIL;
1734 return PY_SET_ATTR_SUCCESS;
1737 PyObject* KX_GameObject::pyattr_get_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1739 KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1740 KX_IPhysicsController *spc = self->GetPhysicsController();
1741 return PyFloat_FromDouble(spc ? spc->GetLinVelocityMax() : 0.0f);
1744 int KX_GameObject::pyattr_set_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1746 KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1747 KX_IPhysicsController *spc = self->GetPhysicsController();
1748 MT_Scalar val = PyFloat_AsDouble(value);
1749 if (val < 0.0f) { /* also accounts for non float */
1750 PyErr_SetString(PyExc_AttributeError, "gameOb.linVelocityMin = float: KX_GameObject, expected a float zero or above");
1751 return PY_SET_ATTR_FAIL;
1755 spc->SetLinVelocityMin(val);
1757 return PY_SET_ATTR_SUCCESS;
1760 PyObject* KX_GameObject::pyattr_get_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1762 KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1763 KX_IPhysicsController *spc = self->GetPhysicsController();
1764 return PyFloat_FromDouble(spc ? spc->GetLinVelocityMax() : 0.0f);
1767 int KX_GameObject::pyattr_set_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1769 KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1770 KX_IPhysicsController *spc = self->GetPhysicsController();
1771 MT_Scalar val = PyFloat_AsDouble(value);
1772 if (val < 0.0f) { /* also accounts for non float */
1773 PyErr_SetString(PyExc_AttributeError, "gameOb.linVelocityMax = float: KX_GameObject, expected a float zero or above");
1774 return PY_SET_ATTR_FAIL;
1778 spc->SetLinVelocityMax(val);
1780 return PY_SET_ATTR_SUCCESS;
1784 PyObject* KX_GameObject::pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1786 KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1787 return PyBool_FromLong(self->GetVisible());
1790 int KX_GameObject::pyattr_set_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1792 KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1793 int param = PyObject_IsTrue( value );
1795 PyErr_SetString(PyExc_AttributeError, "gameOb.visible = bool: KX_GameObject, expected True or False");
1796 return PY_SET_ATTR_FAIL;
1799 self->SetVisible(param, false);
1800 self->UpdateBuckets(false);
1801 return PY_SET_ATTR_SUCCESS;
1804 PyObject* KX_GameObject::pyattr_get_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1806 KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1807 #ifdef USE_MATHUTILS
1808 return newVectorObject_cb((PyObject *)self_v, 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_GLOBAL);
1810 return PyObjectFrom(self->NodeGetWorldPosition());
1814 int KX_GameObject::pyattr_set_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1816 KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1818 if (!PyVecTo(value, pos))
1819 return PY_SET_ATTR_FAIL;
1821 self->NodeSetWorldPosition(pos);
1822 self->NodeUpdateGS(0.f);
1823 return PY_SET_ATTR_SUCCESS;
1826 PyObject* KX_GameObject::pyattr_get_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1828 KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1829 #ifdef USE_MATHUTILS
1830 return newVectorObject_cb((PyObject *)self_v, 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_LOCAL);
1832 return PyObjectFrom(self->NodeGetLocalPosition());
1836 int KX_GameObject::pyattr_set_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1838 KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1840 if (!PyVecTo(value, pos))
1841 return PY_SET_ATTR_FAIL;
1843 self->NodeSetLocalPosition(pos);
1844 self->NodeUpdateGS(0.f);
1845 return PY_SET_ATTR_SUCCESS;
1848 PyObject* KX_GameObject::pyattr_get_localInertia(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1850 KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1851 #ifdef USE_MATHUTILS
1852 return newVectorObject_cb((PyObject *)self_v, 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_INERTIA_LOCAL);
1854 if (self->GetPhysicsController())
1855 return PyObjectFrom(self->GetPhysicsController()->GetLocalInertia());
1856 return Py_BuildValue("fff", 0.0f, 0.0f, 0.0f);
1860 PyObject* KX_GameObject::pyattr_get_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1862 #ifdef USE_MATHUTILS
1863 return newMatrixObject_cb((PyObject *)self_v, 3, 3, mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_GLOBAL);
1865 KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1866 return PyObjectFrom(self->NodeGetWorldOrientation());
1870 int KX_GameObject::pyattr_set_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1872 KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1874 /* if value is not a sequence PyOrientationTo makes an error */
1876 if (!PyOrientationTo(value, rot, "gameOb.worldOrientation = sequence: KX_GameObject, "))
1877 return PY_SET_ATTR_FAIL;
1879 self->NodeSetGlobalOrientation(rot);
1881 self->NodeUpdateGS(0.f);
1882 return PY_SET_ATTR_SUCCESS;
1885 PyObject* KX_GameObject::pyattr_get_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1887 #ifdef USE_MATHUTILS
1888 return newMatrixObject_cb((PyObject *)self_v, 3, 3, mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_LOCAL);
1890 KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1891 return PyObjectFrom(self->NodeGetLocalOrientation());
1895 int KX_GameObject::pyattr_set_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1897 KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1899 /* if value is not a sequence PyOrientationTo makes an error */
1901 if (!PyOrientationTo(value, rot, "gameOb.localOrientation = sequence: KX_GameObject, "))
1902 return PY_SET_ATTR_FAIL;
1904 self->NodeSetLocalOrientation(rot);
1905 self->NodeUpdateGS(0.f);
1906 return PY_SET_ATTR_SUCCESS;
1909 PyObject* KX_GameObject::pyattr_get_worldScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1911 KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1912 #ifdef USE_MATHUTILS
1913 return newVectorObject_cb((PyObject *)self_v, 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_GLOBAL);
1915 return PyObjectFrom(self->NodeGetWorldScaling());
1919 PyObject* KX_GameObject::pyattr_get_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1921 KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1922 #ifdef USE_MATHUTILS
1923 return newVectorObject_cb((PyObject *)self_v, 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_LOCAL);
1925 return PyObjectFrom(self->NodeGetLocalScale());
1929 int KX_GameObject::pyattr_set_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1931 KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1933 if (!PyVecTo(value, scale))
1934 return PY_SET_ATTR_FAIL;
1936 self->NodeSetLocalScale(scale);
1937 self->NodeUpdateGS(0.f);
1938 return PY_SET_ATTR_SUCCESS;
1941 PyObject* KX_GameObject::pyattr_get_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1943 KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1945 if (self->GetSGNode() && (sg_parent = self->GetSGNode()->GetSGParent()) != NULL && sg_parent->IsSlowParent()) {
1946 return PyFloat_FromDouble(static_cast<KX_SlowParentRelation *>(sg_parent->GetParentRelation())->GetTimeOffset());
1948 return PyFloat_FromDouble(0.0);
1952 int KX_GameObject::pyattr_set_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1954 KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1955 if (self->GetSGNode()) {
1956 MT_Scalar val = PyFloat_AsDouble(value);
1957 SG_Node* sg_parent= self->GetSGNode()->GetSGParent();
1958 if (val < 0.0f) { /* also accounts for non float */
1959 PyErr_SetString(PyExc_AttributeError, "gameOb.timeOffset = float: KX_GameObject, expected a float zero or above");
1960 return PY_SET_ATTR_FAIL;
1962 if (sg_parent && sg_parent->IsSlowParent())
1963 static_cast<KX_SlowParentRelation *>(sg_parent->GetParentRelation())->SetTimeOffset(val);
1965 return PY_SET_ATTR_SUCCESS;
1968 PyObject* KX_GameObject::pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1970 KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1972 state |= self->GetState();
1973 return PyInt_FromLong(state);
1976 int KX_GameObject::pyattr_set_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1978 KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1979 int state_i = PyInt_AsLong(value);
1980 unsigned int state = 0;
1982 if (state_i == -1 && PyErr_Occurred()) {
1983 PyErr_SetString(PyExc_TypeError, "gameOb.state = int: KX_GameObject, expected an int bit field");
1984 return PY_SET_ATTR_FAIL;
1988 if ((state & ((1<<30)-1)) == 0) {
1989 PyErr_SetString(PyExc_AttributeError, "gameOb.state = int: KX_GameObject, state bitfield was not between 0 and 30 (1<<0 and 1<<29)");
1990 return PY_SET_ATTR_FAIL;
1992 self->SetState(state);
1993 return PY_SET_ATTR_SUCCESS;
1996 PyObject* KX_GameObject::pyattr_get_meshes(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1998 KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1999 PyObject *meshes= PyList_New(self->m_meshes.size());
2002 for(i=0; i < (int)self->m_meshes.size(); i++)
2004 KX_MeshProxy* meshproxy = new KX_MeshProxy(self->m_meshes[i]);
2005 PyList_SET_ITEM(meshes, i, meshproxy->NewProxy(true));
2012 PyObject* KX_GameObject::pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2014 return KX_PythonSeq_CreatePyObject((static_cast<KX_GameObject*>(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_SENSORS);
2017 PyObject* KX_GameObject::pyattr_get_controllers(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2019 return KX_PythonSeq_CreatePyObject((static_cast<KX_GameObject*>(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_CONTROLLERS);
2022 PyObject* KX_GameObject::pyattr_get_actuators(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2024 return KX_PythonSeq_CreatePyObject((static_cast<KX_GameObject*>(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_ACTUATORS);
2027 PyObject* KX_GameObject::pyattr_get_children(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2029 KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
2030 return self->GetChildren()->NewProxy(true);
2033 PyObject* KX_GameObject::pyattr_get_children_recursive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2035 KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
2036 return self->GetChildrenRecursive()->NewProxy(true);
2039 PyObject* KX_GameObject::pyattr_get_attrDict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2041 KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
2043 if(self->m_attr_dict==NULL)
2044 self->m_attr_dict= PyDict_New();
2046 Py_INCREF(self->m_attr_dict);
2047 return self->m_attr_dict;
2050 /* We need these because the macros have a return in them */
2051 PyObject* KX_GameObject::py_getattro__internal(PyObject *attr)
2053 py_getattro_up(SCA_IObject);
2056 int KX_GameObject::py_setattro__internal(PyObject *attr, PyObject *value) // py_setattro method
2058 py_setattro_up(SCA_IObject);
2062 PyObject* KX_GameObject::py_getattro(PyObject *attr)
2064 PyObject *object= py_getattro__internal(attr);
2066 if (object==NULL && m_attr_dict)
2068 /* backup the exception incase the attr doesnt exist in the dict either */
2069 PyObject *err_type, *err_value, *err_tb;
2070 PyErr_Fetch(&err_type, &err_value, &err_tb);
2072 object= PyDict_GetItem(m_attr_dict, attr);
2077 Py_XDECREF( err_type );
2078 Py_XDECREF( err_value );
2079 Py_XDECREF( err_tb );
2082 PyErr_Restore(err_type, err_value, err_tb); /* use the error from the parent function */
2088 PyObject* KX_GameObject::py_getattro_dict() {
2089 //py_getattro_dict_up(SCA_IObject);
2090 PyObject *dict= py_getattr_dict(SCA_IObject::py_getattro_dict(), Type.tp_dict);
2094 /* normally just return this but KX_GameObject has some more items */
2097 /* Not super fast getting as a list then making into dict keys but its only for dir() */
2098 PyObject *list= ConvertKeysToPython();
2102 for(i=0; i<PyList_Size(list); i++)
2103 PyDict_SetItem(dict, PyList_GET_ITEM(list, i), Py_None);
2110 /* Add m_attr_dict if we have it */
2112 PyDict_Update(dict, m_attr_dict);
2117 int KX_GameObject::py_setattro(PyObject *attr, PyObject *value) // py_setattro method
2119 int ret= py_setattro__internal(attr, value);
2121 if (ret==PY_SET_ATTR_SUCCESS) {
2122 /* remove attribute in our own dict to avoid double ups */
2123 /* NOTE: Annoying that we also do this for setting builtin attributes like mass and visibility :/ */
2125 if (PyDict_DelItem(m_attr_dict, attr) != 0)
2130 if (ret==PY_SET_ATTR_COERCE_FAIL) {
2131 /* CValue attribute exists, remove CValue and add PyDict value */
2132 RemoveProperty(PyString_AsString(attr));
2133 ret= PY_SET_ATTR_MISSING;
2136 if (ret==PY_SET_ATTR_MISSING) {
2137 /* Lazy initialization */
2138 if (m_attr_dict==NULL)
2139 m_attr_dict = PyDict_New();
2141 if (PyDict_SetItem(m_attr_dict, attr, value)==0) {
2143 ret= PY_SET_ATTR_SUCCESS;
2146 PyErr_Format(PyExc_AttributeError, "gameOb.myAttr = value: KX_GameObject, failed assigning value to internal dictionary");
2147 ret= PY_SET_ATTR_FAIL;
2155 int KX_GameObject::py_delattro(PyObject *attr)
2157 ShowDeprecationWarning("del ob.attr", "del ob['attr'] for user defined properties");
2159 char *attr_str= PyString_AsString(attr);
2161 if (RemoveProperty(attr_str)) // XXX - should call CValues instead but its only 2 lines here
2162 return PY_SET_ATTR_SUCCESS;
2164 if (m_attr_dict && (PyDict_DelItem(m_attr_dict, attr) == 0))
2165 return PY_SET_ATTR_SUCCESS;
2167 PyErr_Format(PyExc_AttributeError, "del gameOb.myAttr: KX_GameObject, attribute \"%s\" dosnt exist", attr_str);
2168 return PY_SET_ATTR_MISSING;
2172 PyObject* KX_GameObject::PyApplyForce(PyObject* args)
2177 if (PyArg_ParseTuple(args, "O|i:applyForce", &pyvect, &local)) {
2179 if (PyVecTo(pyvect, force)) {
2180 ApplyForce(force, (local!=0));
2187 PyObject* KX_GameObject::PyApplyTorque(PyObject* args)
2192 if (PyArg_ParseTuple(args, "O|i:applyTorque", &pyvect, &local)) {
2194 if (PyVecTo(pyvect, torque)) {
2195 ApplyTorque(torque, (local!=0));
2202 PyObject* KX_GameObject::PyApplyRotation(PyObject* args)
2207 if (PyArg_ParseTuple(args, "O|i:applyRotation", &pyvect, &local)) {
2208 MT_Vector3 rotation;
2209 if (PyVecTo(pyvect, rotation)) {
2210 ApplyRotation(rotation, (local!=0));
2217 PyObject* KX_GameObject::PyApplyMovement(PyObject* args)
2222 if (PyArg_ParseTuple(args, "O|i:applyMovement", &pyvect, &local)) {
2223 MT_Vector3 movement;
2224 if (PyVecTo(pyvect, movement)) {
2225 ApplyMovement(movement, (local!=0));
2232 PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* args)
2234 // only can get the velocity if we have a physics object connected to us...
2236 if (PyArg_ParseTuple(args,"|i:getLinearVelocity",&local))
2238 return PyObjectFrom(GetLinearVelocity((local!=0)));
2246 PyObject* KX_GameObject::PySetLinearVelocity(PyObject* args)
2251 if (PyArg_ParseTuple(args,"O|i:setLinearVelocity",&pyvect,&local)) {
2252 MT_Vector3 velocity;
2253 if (PyVecTo(pyvect, velocity)) {
2254 setLinearVelocity(velocity, (local!=0));
2261 PyObject* KX_GameObject::PyGetAngularVelocity(PyObject* args)
2263 // only can get the velocity if we have a physics object connected to us...
2265 if (PyArg_ParseTuple(args,"|i:getAngularVelocity",&local))
2267 return PyObjectFrom(GetAngularVelocity((local!=0)));
2275 PyObject* KX_GameObject::PySetAngularVelocity(PyObject* args)
2280 if (PyArg_ParseTuple(args,"O|i:setAngularVelocity",&pyvect,&local)) {
2281 MT_Vector3 velocity;
2282 if (PyVecTo(pyvect, velocity)) {
2283 setAngularVelocity(velocity, (local!=0));
2290 PyObject* KX_GameObject::PySetVisible(PyObject* args)
2292 int visible, recursive = 0;
2293 if (!PyArg_ParseTuple(args,"i|i:setVisible",&visible, &recursive))
2296 SetVisible(visible ? true:false, recursive ? true:false);
2297 UpdateBuckets(recursive ? true:false);
2302 PyObject* KX_GameObject::PySetOcclusion(PyObject* args)
2304 int occlusion, recursive = 0;
2305 if (!PyArg_ParseTuple(args,"i|i:setOcclusion",&occlusion, &recursive))
2308 SetOccluder(occlusion ? true:false, recursive ? true:false);
2312 PyObject* KX_GameObject::PyGetVisible()
2314 ShowDeprecationWarning("getVisible()", "the visible property");
2315 return PyInt_FromLong(m_bVisible);
2318 PyObject* KX_GameObject::PyGetState()
2320 ShowDeprecationWarning("getState()", "the state property");
2322 state |= GetState();
2323 return PyInt_FromLong(state);
2326 PyObject* KX_GameObject::PySetState(PyObject* value)
2328 ShowDeprecationWarning("setState()", "the state property");
2329 int state_i = PyInt_AsLong(value);
2330 unsigned int state = 0;
2332 if (state_i == -1 && PyErr_Occurred()) {
2333 PyErr_SetString(PyExc_TypeError, "expected an int bit field");
2338 if ((state & ((1<<30)-1)) == 0) {
2339 PyErr_SetString(PyExc_AttributeError, "The state bitfield was not between 0 and 30 (1<<0 and 1<<29)");
2347 PyObject* KX_GameObject::PyGetVelocity(PyObject* args)
2349 // only can get the velocity if we have a physics object connected to us...
2350 MT_Point3 point(0.0,0.0,0.0);
2351 PyObject* pypos = NULL;
2353 if (!PyArg_ParseTuple(args, "|O:getVelocity", &pypos) || (pypos && !PyVecTo(pypos, point)))
2356 if (m_pPhysicsController1)
2358 return PyObjectFrom(m_pPhysicsController1->GetVelocity(point));
2361 return PyObjectFrom(MT_Vector3(0.0,0.0,0.0));
2367 PyObject* KX_GameObject::PyGetMass()
2369 ShowDeprecationWarning("getMass()", "the mass property");
2370 return PyFloat_FromDouble((GetPhysicsController() != NULL) ? GetPhysicsController()->GetMass() : 0.0f);
2373 PyObject* KX_GameObject::PyGetReactionForce()
2375 // only can get the velocity if we have a physics object connected to us...
2377 // XXX - Currently not working with bullet intergration, see KX_BulletPhysicsController.cpp's getReactionForce
2379 if (GetPhysicsController())
2380 return PyObjectFrom(GetPhysicsController()->getReactionForce());
2381 return PyObjectFrom(dummy_point);
2384 return Py_BuildValue("fff", 0.0f, 0.0f, 0.0f);
2390 PyObject* KX_GameObject::PyEnableRigidBody()
2392 if(GetPhysicsController())
2393 GetPhysicsController()->setRigidBody(true);
2400 PyObject* KX_GameObject::PyDisableRigidBody()
2402 if(GetPhysicsController())
2403 GetPhysicsController()->setRigidBody(false);
2410 PyObject* KX_GameObject::PyGetParent()
2412 ShowDeprecationWarning("getParent()", "the parent property");
2413 KX_GameObject* parent = this->GetParent();
2415 parent->Release(); /* self->GetParent() AddRef's */
2416 return parent->GetProxy();
2421 PyObject* KX_GameObject::PySetParent(PyObject* args)
2423 KX_Scene *scene = KX_GetActiveScene();
2426 int addToCompound=1, ghost=1;
2428 if (!PyArg_ParseTuple(args,"O|ii:setParent", &pyobj, &addToCompound, &ghost)) {
2429 return NULL; // Python sets a simple error
2431 if (!ConvertPythonToGameObject(pyobj, &obj, true, "gameOb.setParent(obj): KX_GameObject"))
2434 this->SetParent(scene, obj, addToCompound, ghost);
2438 PyObject* KX_GameObject::PyRemoveParent()
2440 KX_Scene *scene = KX_GetActiveScene();
2442 this->RemoveParent(scene);
2446 PyObject* KX_GameObject::PyGetChildren()
2448 ShowDeprecationWarning("getChildren()", "the children property");
2450 return GetChildren()->NewProxy(true);
2453 PyObject* KX_GameObject::PyGetChildrenRecursive()
2455 ShowDeprecationWarning("getChildrenRecursive()", "the childrenRecursive property");
2457 return GetChildrenRecursive()->NewProxy(true);
2460 PyObject* KX_GameObject::PyGetMesh(PyObject* args)
2462 ShowDeprecationWarning("getMesh()", "the meshes property (now a list of meshes)");
2466 if (!PyArg_ParseTuple(args, "|i:getMesh", &mesh))
2467 return NULL; // python sets a simple error
2469 if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0)
2471 KX_MeshProxy* meshproxy = new KX_MeshProxy(m_meshes[mesh]);
2472 return meshproxy->NewProxy(true); // XXX Todo Python own.
2482 PyObject* KX_GameObject::PySetCollisionMargin(PyObject* value)
2484 float collisionMargin = PyFloat_AsDouble(value);
2486 if (collisionMargin==-1 && PyErr_Occurred()) {
2487 PyErr_SetString(PyExc_TypeError, "expected a float");
2491 if (m_pPhysicsController1)
2493 m_pPhysicsController1->setMargin(collisionMargin);
2496 PyErr_SetString(PyExc_RuntimeError, "This object has no physics controller");
2502 PyObject* KX_GameObject::PyApplyImpulse(PyObject* args)
2505 PyObject* pyimpulse;
2507 if (!m_pPhysicsController1) {
2508 PyErr_SetString(PyExc_RuntimeError, "This object has no physics controller");
2512 if (PyArg_ParseTuple(args, "OO:applyImpulse", &pyattach, &pyimpulse))
2516 if (PyVecTo(pyattach, attach) && PyVecTo(pyimpulse, impulse))
2518 m_pPhysicsController1->applyImpulse(attach, impulse);
2529 PyObject* KX_GameObject::PySuspendDynamics()
2537 PyObject* KX_GameObject::PyRestoreDynamics()
2545 PyObject* KX_GameObject::PyGetOrientation() //keywords
2547 ShowDeprecationWarning("getOrientation()", "the orientation property");
2548 return PyObjectFrom(NodeGetWorldOrientation());
2553 PyObject* KX_GameObject::PySetOrientation(PyObject* value)
2555 ShowDeprecationWarning("setOrientation()", "the orientation property");
2558 /* if value is not a sequence PyOrientationTo makes an error */
2559 if (!PyOrientationTo(value, rot, "gameOb.setOrientation(sequence): KX_GameObject, "))
2562 NodeSetLocalOrientation(rot);
2567 PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* args)
2570 int axis = 2; //z axis is the default
2573 if (PyArg_ParseTuple(args,"O|if:alignAxisToVect",&pyvect,&axis, &fac))
2576 if (PyVecTo(pyvect, vect))
2578 if (fac<=0.0) Py_RETURN_NONE; // Nothing to do.
2579 if (fac> 1.0) fac= 1.0;
2581 AlignAxisToVect(vect,axis,fac);
2589 PyObject* KX_GameObject::PyGetAxisVect(PyObject* value)
2592 if (PyVecTo(value, vect))
2594 return PyObjectFrom(NodeGetWorldOrientation() * vect);
2599 PyObject* KX_GameObject::PySetPosition(PyObject* value)
2601 ShowDeprecationWarning("setPosition()", "the localPosition property");
2603 if (PyVecTo(value, pos))
2605 NodeSetLocalPosition(pos);
2613 PyObject* KX_GameObject::PySetWorldPosition(PyObject* value)
2615 ShowDeprecationWarning("setWorldPosition()", "the worldPosition property");
2617 if (PyVecTo(value, pos))
2619 NodeSetWorldPosition(pos);
2627 PyObject* KX_GameObject::PyGetPhysicsId()
2629 KX_IPhysicsController* ctrl = GetPhysicsController();
2633 physid= (uint_ptr)ctrl->GetUserData();
2635 return PyInt_FromLong((long)physid);
2638 PyObject* KX_GameObject::PyGetPropertyNames()
2640 PyObject *list= ConvertKeysToPython();
2643 PyObject *key, *value;
2646 while (PyDict_Next(m_attr_dict, &pos, &key, &value)) {
2647 PyList_Append(list, key);
2653 KX_PYMETHODDEF_DOC_O(KX_GameObject, getDistanceTo,
2654 "getDistanceTo(other): get distance to another point/KX_GameObject")
2657 if (PyVecTo(value, b))
2659 return PyFloat_FromDouble(NodeGetWorldPosition().distance(b));
2663 KX_GameObject *other;
2664 if (ConvertPythonToGameObject(value, &other, false, "gameOb.getDistanceTo(value): KX_GameObject"))
2666 return PyFloat_FromDouble(NodeGetWorldPosition().distance(other->NodeGetWorldPosition()));
2672 KX_PYMETHODDEF_DOC_O(KX_GameObject, getVectTo,
2673 "getVectTo(other): get vector and the distance to another point/KX_GameObject\n"
2674 "Returns a 3-tuple with (distance,worldVector,localVector)\n")
2676 MT_Point3 toPoint, fromPoint;
2677 MT_Vector3 toDir, locToDir;
2680 PyObject *returnValue;
2682 if (!PyVecTo(value, toPoint))
2686 KX_GameObject *other;
2687 if (ConvertPythonToGameObject(value, &other, false, "")) /* error will be overwritten */
2689 toPoint = other->NodeGetWorldPosition();
2692 PyErr_SetString(PyExc_TypeError, "gameOb.getVectTo(other): KX_GameObject, expected a 3D Vector or KX_GameObject type");
2697 fromPoint = NodeGetWorldPosition();
2698 toDir = toPoint-fromPoint;
2699 distance = toDir.length();
2701 if (MT_fuzzyZero(distance))
2703 //cout << "getVectTo() Error: Null vector!\n";
2704 locToDir = toDir = MT_Vector3(0.0,0.0,0.0);
2708 locToDir = toDir * NodeGetWorldOrientation();
2711 returnValue = PyTuple_New(3);
2712 if (returnValue) { // very unlikely to fail, python sets a memory error here.
2713 PyTuple_SET_ITEM(returnValue, 0, PyFloat_FromDouble(distance));
2714 PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(toDir));
2715 PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(locToDir));
2720 bool KX_GameObject::RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data)
2722 KX_GameObject* hitKXObj = client->m_gameobject;
2724 // if X-ray option is selected, the unwnted objects were not tested, so get here only with true hit
2725 // if not, all objects were tested and the front one may not be the correct one.
2726 if (m_xray || m_testPropName.Length() == 0 || hitKXObj->GetProperty(m_testPropName) != NULL)
2728 m_pHitObject = hitKXObj;
2731 // return true to stop RayCast::RayTest from looping, the above test was decisive
2732 // We would want to loop only if we want to get more than one hit point
2736 /* this function is used to pre-filter the object before casting the ray on them.
2737 This is useful for "X-Ray" option when we want to see "through" unwanted object.
2739 bool KX_GameObject::NeedRayCast(KX_ClientObjectInfo* client)
2741 KX_GameObject* hitKXObj = client->m_gameobject;
2743 if (client->m_type > KX_ClientObjectInfo::ACTOR)
2745 // Unknown type of object, skip it.
2746 // Should not occur as the sensor objects are filtered in RayTest()
2747 printf("Invalid client type %d found in ray casting\n", client->m_type);
2751 // if X-Ray option is selected, skip object that don't match the criteria as we see through them
2752 // if not, test all objects because we don't know yet which one will be on front
2753 if (!m_xray || m_testPropName.Length() == 0 || hitKXObj->GetProperty(m_testPropName) != NULL)
2761 KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo,
2762 "rayCastTo(other,dist,prop): look towards another point/KX_GameObject and return first object hit within dist that matches prop\n"
2763 " prop = property name that object must have; can be omitted => detect any object\n"
2764 " dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to other\n"
2765 " other = 3-tuple or object reference")
2770 char *propName = NULL;
2772 if (!PyArg_ParseTuple(args,"O|fs:rayCastTo", &pyarg, &dist, &propName)) {
2773 return NULL; // python sets simple error
2776 if (!PyVecTo(pyarg, toPoint))
2778 KX_GameObject *other;
2781 if (ConvertPythonToGameObject(pyarg, &other, false, "")) /* error will be overwritten */
2783 toPoint = other->NodeGetWorldPosition();
2786 PyErr_SetString(PyExc_TypeError, "gameOb.rayCastTo(other,dist,prop): KX_GameObject, the first argument to rayCastTo must be a vector or a KX_GameObject");
2790 MT_Point3 fromPoint = NodeGetWorldPosition();
2793 MT_Vector3 toDir = toPoint-fromPoint;
2795 toPoint = fromPoint + (dist) * toDir;
2798 PHY_IPhysicsEnvironment* pe = GetPhysicsEnvironment();
2799 KX_IPhysicsController *spc = GetPhysicsController();
2800 KX_GameObject *parent = GetParent();
2802 spc = parent->GetPhysicsController();
2806 m_pHitObject = NULL;
2808 m_testPropName = propName;
2810 m_testPropName.SetLength(0);
2811 KX_RayCast::Callback<KX_GameObject> callback(this,spc);
2812 KX_RayCast::RayTest(pe, fromPoint, toPoint, callback);
2815 return m_pHitObject->GetProxy();
2820 /* faster then Py_BuildValue since some scripts call raycast a lot */
2821 static PyObject *none_tuple_3()
2823 PyObject *ret= PyTuple_New(3);
2824 PyTuple_SET_ITEM(ret, 0, Py_None);
2825 PyTuple_SET_ITEM(ret, 1, Py_None);
2826 PyTuple_SET_ITEM(ret, 2, Py_None);
2833 static PyObject *none_tuple_4()
2835 PyObject *ret= PyTuple_New(4);
2836 PyTuple_SET_ITEM(ret, 0, Py_None);
2837 PyTuple_SET_ITEM(ret, 1, Py_None);
2838 PyTuple_SET_ITEM(ret, 2, Py_None);
2839 PyTuple_SET_ITEM(ret, 3, Py_None);
2848 KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
2849 "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) of contact point with object within dist that matches prop.\n"
2850 " If no hit, return (None,None,None) or (None,None,None,None).\n"
2851 " to = 3-tuple or object reference for destination of ray (if object, use center of object)\n"
2852 " from = 3-tuple or object reference for origin of ray (if object, use center of object)\n"
2853 " Can be None or omitted => start from self object center\n"
2854 " dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to to\n"
2855 " prop = property name that object must have; can be omitted => detect any object\n"
2856 " face = normal option: 1=>return face normal; 0 or omitted => normal is oriented towards origin\n"
2857 " xray = X-ray option: 1=>skip objects that don't match prop; 0 or omitted => stop on first object\n"
2858 " poly = polygon option: 1=>return value is a 4-tuple and the 4th element is a KX_PolyProxy object\n"
2859 " which can be None if hit object has no mesh or if there is no hit\n"
2860 " If 0 or omitted, return value is a 3-tuple\n"
2861 "Note: The object on which you call this method matters: the ray will ignore it.\n"
2862 " prop and xray option interact as follow:\n"
2863 " prop off, xray off: return closest hit or no hit if there is no object on the full extend of the ray\n"
2864 " prop off, xray on : idem\n"
2865 " prop on, xray off: return closest hit if it matches prop, no hit otherwise\n"
2866 " 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")
2869 MT_Point3 fromPoint;
2871 PyObject* pyfrom = NULL;
2873 char *propName = NULL;
2874 KX_GameObject *other;
2875 int face=0, xray=0, poly=0;
2877 if (!PyArg_ParseTuple(args,"O|Ofsiii:rayCast", &pyto, &pyfrom, &dist, &propName, &face, &xray, &poly)) {
2878 return NULL; // Python sets a simple error
2881 if (!PyVecTo(pyto, toPoint))
2885 if (ConvertPythonToGameObject(pyto, &other, false, "")) /* error will be overwritten */
2887 toPoint = other->NodeGetWorldPosition();
2890 PyErr_SetString(PyExc_TypeError, "the first argument to rayCast must be a vector or a KX_GameObject");
2894 if (!pyfrom || pyfrom == Py_None)
2896 fromPoint = NodeGetWorldPosition();
2898 else if (!PyVecTo(pyfrom, fromPoint))
2902 if (ConvertPythonToGameObject(pyfrom, &other, false, "")) /* error will be overwritten */
2904 fromPoint = other->NodeGetWorldPosition();
2907 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");
2913 MT_Vector3 toDir = toPoint-fromPoint;
2914 if (MT_fuzzyZero(toDir.length2())) {
2915 //return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
2916 return none_tuple_3();
2919 toPoint = fromPoint + (dist) * toDir;
2920 } else if (MT_fuzzyZero((toPoint-fromPoint).length2())) {
2921 //return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
2922 return none_tuple_3();
2925 PHY_IPhysicsEnvironment* pe = GetPhysicsEnvironment();
2926 KX_IPhysicsController *spc = GetPhysicsController();
2927 KX_GameObject *parent = GetParent();
2929 spc = parent->GetPhysicsController();
2933 m_pHitObject = NULL;
2935 m_testPropName = propName;
2937 m_testPropName.SetLength(0);
2939 // to get the hit results
2940 KX_RayCast::Callback<KX_GameObject> callback(this,spc,NULL,face);
2941 KX_RayCast::RayTest(pe, fromPoint, toPoint, callback);
2945 PyObject* returnValue = (poly) ? PyTuple_New(4) : PyTuple_New(3);
2946 if (returnValue) { // unlikely this would ever fail, if it does python sets an error
2947 PyTuple_SET_ITEM(returnValue, 0, m_pHitObject->GetProxy());
2948 PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(callback.m_hitPoint));
2949 PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(callback.m_hitNormal));
2952 if (callback.m_hitMesh)
2954 // if this field is set, then we can trust that m_hitPolygon is a valid polygon
2955 RAS_Polygon* polygon = callback.m_hitMesh->GetPolygon(callback.m_hitPolygon);
2956 KX_PolyProxy* polyproxy = new KX_PolyProxy(callback.m_hitMesh, polygon);
2957 PyTuple_SET_ITEM(returnValue, 3, polyproxy->NewProxy(true));
2962 PyTuple_SET_ITEM(returnValue, 3, Py_None);
2970 //return Py_BuildValue("OOOO", Py_None, Py_None, Py_None, Py_None);
2971 return none_tuple_4();
2973 //return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
2974 return none_tuple_3();
2977 KX_PYMETHODDEF_DOC_VARARGS(KX_GameObject, sendMessage,
2978 "sendMessage(subject, [body, to])\n"
2979 "sends a message in same manner as a message actuator"
2980 "subject = Subject of the message (string)"
2981 "body = Message body (string)"
2982 "to = Name of object to send the message to")
2984 KX_Scene *scene = KX_GetActiveScene();
2986 char* body = (char *)"";
2987 char* to = (char *)"";
2988 const STR_String& from = GetName();
2990 if (!PyArg_ParseTuple(args, "s|sss:sendMessage", &subject, &body, &to))
2993 scene->GetNetworkScene()->SendMessage(to, from, subject, body);
2997 /* dict style access */
3000 /* Matches python dict.get(key, [default]) */
3001 PyObject* KX_GameObject::Pyget(PyObject *args)
3004 PyObject* def = Py_None;
3007 if (!PyArg_ParseTuple(args, "O|O:get", &key, &def))
3011 if(PyString_Check(key)) {
3012 CValue *item = GetProperty(PyString_AsString(key));
3014 ret = item->ConvertValueToPython();
3018 return item->GetProxy();
3022 if (m_attr_dict && (ret=PyDict_GetItem(m_attr_dict, key))) {
3031 /* Matches python dict.has_key() */
3032 PyObject* KX_GameObject::Pyhas_key(PyObject* value)
3034 // the ONLY error case is invalid data, this is checked by the macro'd static function
3035 // that calls this one. but make sure Seq_Contains doesnt add extra errors later on.
3036 return PyBool_FromLong(Seq_Contains((PyObject *)this, value));
3039 /* ---------------------------------------------------------------------
3040 * Some stuff taken from the header
3041 * --------------------------------------------------------------------- */
3042 void KX_GameObject::Relink(GEN_Map<GEN_HashedPtr, void*> *map_parameter)
3044 // we will relink the sensors and actuators that use object references
3045 // if the object is part of the replicated hierarchy, use the new
3046 // object reference instead
3047 SCA_SensorList& sensorlist = GetSensors();
3048 SCA_SensorList::iterator sit;
3049 for (sit=sensorlist.begin(); sit != sensorlist.end(); sit++)
3051 (*sit)->Relink(map_parameter);
3053 SCA_ActuatorList& actuatorlist = GetActuators();
3054 SCA_ActuatorList::iterator ait;
3055 for (ait=actuatorlist.begin(); ait != actuatorlist.end(); ait++)
3057 (*ait)->Relink(map_parameter);
3062 bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py_none_ok, const char *error_prefix)
3065 PyErr_Format(PyExc_TypeError, "%s, python pointer NULL, should never happen", error_prefix);
3070 if (value==Py_None) {
3076 PyErr_Format(PyExc_TypeError, "%s, expected KX_GameObject or a KX_GameObject name, None is invalid", error_prefix);
3081 if (PyString_Check(value)) {
3082 *object = (KX_GameObject*)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String( PyString_AsString(value) ));
3087 PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_GameObject in this scene", error_prefix, PyString_AsString(value));
3092 if ( PyObject_TypeCheck(value, &KX_GameObject::Type) ||
3093 PyObject_TypeCheck(value, &KX_LightObject::Type) ||
3094 PyObject_TypeCheck(value, &KX_Camera::Type) )
3096 *object = static_cast<KX_GameObject*>BGE_PROXY_REF(value);
3098 /* sets the error */
3099 if (*object==NULL) {
3100 PyErr_Format(PyExc_SystemError, "%s, " BGE_PROXY_ERROR_MSG, error_prefix);
3110 PyErr_Format(PyExc_TypeError, "%s, expect a KX_GameObject, a string or None", error_prefix);
3112 PyErr_Format(PyExc_TypeError, "%s, expect a KX_GameObject or a string", error_prefix);