BGE Physics
[blender.git] / source / gameengine / Ketsji / KX_GameObject.cpp
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
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.
10  *
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.
15  *
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.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  * Game object wrapper
29  */
30
31 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
34
35 #if defined(_WIN64)
36 typedef unsigned __int64 uint_ptr;
37 #else
38 typedef unsigned long uint_ptr;
39 #endif
40
41 #ifdef WIN32
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 )     
45 #endif
46
47
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"
61 #include "SG_Node.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 "KX_ConvertPhysicsObject.h"
70 #include "SCA_IActuator.h"
71 #include "SCA_ISensor.h"
72 #include "SCA_IController.h"
73 #include "NG_NetworkScene.h" //Needed for sendMessage()
74
75 #include "PyObjectPlus.h" /* python stuff */
76
77 // This file defines relationships between parents and children
78 // in the game engine.
79
80 #include "KX_SG_NodeRelationships.h"
81
82 static MT_Point3 dummy_point= MT_Point3(0.0, 0.0, 0.0);
83 static MT_Vector3 dummy_scaling = MT_Vector3(1.0, 1.0, 1.0);
84 static MT_Matrix3x3 dummy_orientation = MT_Matrix3x3(   1.0, 0.0, 0.0,
85                                                                                                                 0.0, 1.0, 0.0,
86                                                                                                                 0.0, 0.0, 1.0);
87
88 KX_GameObject::KX_GameObject(
89         void* sgReplicationInfo,
90         SG_Callbacks callbacks,
91         PyTypeObject* T
92 ) : 
93         SCA_IObject(T),
94         m_bDyna(false),
95         m_layer(0),
96         m_pBlenderObject(NULL),
97         m_pBlenderGroupObject(NULL),
98         m_bSuspendDynamics(false),
99         m_bUseObjectColor(false),
100         m_bIsNegativeScaling(false),
101         m_bVisible(true),
102         m_bCulled(true),
103         m_bOccluder(false),
104         m_pPhysicsController1(NULL),
105         m_pGraphicController(NULL),
106         m_pPhysicsEnvironment(NULL),
107         m_xray(false),
108         m_pHitObject(NULL),
109         m_isDeformable(false),
110         m_attr_dict(NULL)
111 {
112         m_ignore_activity_culling = false;
113         m_pClient_info = new KX_ClientObjectInfo(this, KX_ClientObjectInfo::ACTOR);
114         m_pSGNode = new SG_Node(this,sgReplicationInfo,callbacks);
115
116         // define the relationship between this node and it's parent.
117         
118         KX_NormalParentRelation * parent_relation = 
119                 KX_NormalParentRelation::New();
120         m_pSGNode->SetParentRelation(parent_relation);
121 };
122
123
124
125 KX_GameObject::~KX_GameObject()
126 {
127         RemoveMeshes();
128
129         // is this delete somewhere ?
130         //if (m_sumoObj)
131         //      delete m_sumoObj;
132         delete m_pClient_info;
133         //if (m_pSGNode)
134         //      delete m_pSGNode;
135         if (m_pSGNode)
136         {
137                 // must go through controllers and make sure they will not use us anymore
138                 // This is important for KX_BulletPhysicsControllers that unregister themselves
139                 // from the object when they are deleted.
140                 SGControllerList::iterator contit;
141                 SGControllerList& controllers = m_pSGNode->GetSGControllerList();
142                 for (contit = controllers.begin();contit!=controllers.end();++contit)
143                 {
144                         (*contit)->ClearObject();
145                 }
146                 m_pSGNode->SetSGClientObject(NULL);
147         }
148         if (m_pGraphicController)
149         {
150                 delete m_pGraphicController;
151         }
152         
153         if (m_attr_dict) {
154                 PyDict_Clear(m_attr_dict); /* incase of circular refs or other weired cases */
155                 Py_DECREF(m_attr_dict);
156         }
157 }
158
159 KX_GameObject* KX_GameObject::GetClientObject(KX_ClientObjectInfo* info)
160 {
161         if (!info)
162                 return NULL;
163         return info->m_gameobject;
164 }
165
166 CValue* KX_GameObject:: Calc(VALUE_OPERATOR op, CValue *val) 
167 {
168         return NULL;
169 }
170
171
172
173 CValue* KX_GameObject::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val)
174 {
175         return NULL;
176 }
177
178
179
180 const STR_String & KX_GameObject::GetText()
181 {
182         return m_text;
183 }
184
185
186
187 double KX_GameObject::GetNumber()
188 {
189         return 0;
190 }
191
192
193
194 STR_String& KX_GameObject::GetName()
195 {
196         return m_name;
197 }
198
199
200
201 void KX_GameObject::SetName(const char *name)
202 {
203         m_name = name;
204 };                                                              // Set the name of the value
205
206 KX_IPhysicsController* KX_GameObject::GetPhysicsController()
207 {
208         return m_pPhysicsController1;
209 }
210
211 KX_GameObject* KX_GameObject::GetParent()
212 {
213         KX_GameObject* result = NULL;
214         SG_Node* node = m_pSGNode;
215         
216         while (node && !result)
217         {
218                 node = node->GetSGParent();
219                 if (node)
220                         result = (KX_GameObject*)node->GetSGClientObject();
221         }
222         
223         if (result)
224                 result->AddRef();
225
226         return result;
227         
228 }
229
230 void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj, bool addToCompound, bool ghost)
231 {
232         // check on valid node in case a python controller holds a reference to a deleted object
233         if (obj && GetSGNode() && obj->GetSGNode() && GetSGNode()->GetSGParent() != obj->GetSGNode())
234         {
235                 // Make sure the objects have some scale
236                 MT_Vector3 scale1 = NodeGetWorldScaling();
237                 MT_Vector3 scale2 = obj->NodeGetWorldScaling();
238                 if (fabs(scale2[0]) < FLT_EPSILON || 
239                         fabs(scale2[1]) < FLT_EPSILON || 
240                         fabs(scale2[2]) < FLT_EPSILON || 
241                         fabs(scale1[0]) < FLT_EPSILON || 
242                         fabs(scale1[1]) < FLT_EPSILON || 
243                         fabs(scale1[2]) < FLT_EPSILON) { return; }
244
245                 // Remove us from our old parent and set our new parent
246                 RemoveParent(scene);
247                 obj->GetSGNode()->AddChild(GetSGNode());
248
249                 if (m_pPhysicsController1) 
250                 {
251                         m_pPhysicsController1->SuspendDynamics(ghost);
252                 }
253                 // Set us to our new scale, position, and orientation
254                 scale2[0] = 1.0/scale2[0];
255                 scale2[1] = 1.0/scale2[1];
256                 scale2[2] = 1.0/scale2[2];
257                 scale1 = scale1 * scale2;
258                 MT_Matrix3x3 invori = obj->NodeGetWorldOrientation().inverse();
259                 MT_Vector3 newpos = invori*(NodeGetWorldPosition()-obj->NodeGetWorldPosition())*scale2;
260
261                 NodeSetLocalScale(scale1);
262                 NodeSetLocalPosition(MT_Point3(newpos[0],newpos[1],newpos[2]));
263                 NodeSetLocalOrientation(invori*NodeGetWorldOrientation());
264                 NodeUpdateGS(0.f);
265                 // object will now be a child, it must be removed from the parent list
266                 CListValue* rootlist = scene->GetRootParentList();
267                 if (rootlist->RemoveValue(this))
268                         // the object was in parent list, decrement ref count as it's now removed
269                         Release();
270                 // if the new parent is a compound object, add this object shape to the compound shape.
271                 // step 0: verify this object has physical controller
272                 if (m_pPhysicsController1 && addToCompound)
273                 {
274                         // step 1: find the top parent (not necessarily obj)
275                         KX_GameObject* rootobj = (KX_GameObject*)obj->GetSGNode()->GetRootSGParent()->GetSGClientObject();
276                         // step 2: verify it has a physical controller and compound shape
277                         if (rootobj != NULL && 
278                                 rootobj->m_pPhysicsController1 != NULL &&
279                                 rootobj->m_pPhysicsController1->IsCompound())
280                         {
281                                 rootobj->m_pPhysicsController1->AddCompoundChild(m_pPhysicsController1);
282                         }
283                 }
284                 // graphically, the object hasn't change place, no need to update m_pGraphicController
285         }
286 }
287
288 void KX_GameObject::RemoveParent(KX_Scene *scene)
289 {
290         // check on valid node in case a python controller holds a reference to a deleted object
291         if (GetSGNode() && GetSGNode()->GetSGParent())
292         {
293                 // get the root object to remove us from compound object if needed
294                 KX_GameObject* rootobj = (KX_GameObject*)GetSGNode()->GetRootSGParent()->GetSGClientObject();
295                 // Set us to the right spot 
296                 GetSGNode()->SetLocalScale(GetSGNode()->GetWorldScaling());
297                 GetSGNode()->SetLocalOrientation(GetSGNode()->GetWorldOrientation());
298                 GetSGNode()->SetLocalPosition(GetSGNode()->GetWorldPosition());
299
300                 // Remove us from our parent
301                 GetSGNode()->DisconnectFromParent();
302                 NodeUpdateGS(0.f);
303                 // the object is now a root object, add it to the parentlist
304                 CListValue* rootlist = scene->GetRootParentList();
305                 if (!rootlist->SearchValue(this))
306                         // object was not in root list, add it now and increment ref count
307                         rootlist->Add(AddRef());
308                 if (m_pPhysicsController1) 
309                 {
310                         // in case this controller was added as a child shape to the parent
311                         if (rootobj != NULL && 
312                                 rootobj->m_pPhysicsController1 != NULL &&
313                                 rootobj->m_pPhysicsController1->IsCompound())
314                         {
315                                 rootobj->m_pPhysicsController1->RemoveCompoundChild(m_pPhysicsController1);
316                         }
317                         m_pPhysicsController1->RestoreDynamics();
318                         if (m_pPhysicsController1->IsDyna() && rootobj->m_pPhysicsController1)
319                         {
320                                 // dynamic object should remember the velocity they had while being parented
321                                 MT_Point3 childPoint = GetSGNode()->GetWorldPosition();
322                                 MT_Point3 rootPoint = rootobj->GetSGNode()->GetWorldPosition();
323                                 MT_Point3 relPoint;
324                                 relPoint = (childPoint-rootPoint);
325                                 MT_Vector3 linVel = rootobj->m_pPhysicsController1->GetVelocity(relPoint);
326                                 MT_Vector3 angVel = rootobj->m_pPhysicsController1->GetAngularVelocity();
327                                 m_pPhysicsController1->SetLinearVelocity(linVel, false);
328                                 m_pPhysicsController1->SetAngularVelocity(angVel, false);
329                         }
330                 }
331                 // graphically, the object hasn't change place, no need to update m_pGraphicController
332         }
333 }
334
335 void KX_GameObject::ProcessReplica()
336 {
337         SCA_IObject::ProcessReplica();
338         
339         m_pPhysicsController1 = NULL;
340         m_pGraphicController = NULL;
341         m_pSGNode = NULL;
342         m_pClient_info = new KX_ClientObjectInfo(*m_pClient_info);
343         m_pClient_info->m_gameobject = this;
344         m_state = 0;
345         if(m_attr_dict)
346                 m_attr_dict= PyDict_Copy(m_attr_dict);
347                 
348 }
349
350 static void setGraphicController_recursive(SG_Node* node)
351 {
352         NodeList& children = node->GetSGChildren();
353
354         for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
355         {
356                 SG_Node* childnode = (*childit);
357                 KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject());
358                 if (clientgameobj != NULL) // This is a GameObject
359                         clientgameobj->ActivateGraphicController(false);
360                 
361                 // if the childobj is NULL then this may be an inverse parent link
362                 // so a non recursive search should still look down this node.
363                 setGraphicController_recursive(childnode);
364         }
365 }
366
367
368 void KX_GameObject::ActivateGraphicController(bool recurse)
369 {
370         if (m_pGraphicController)
371         {
372                 m_pGraphicController->Activate(m_bVisible);
373         }
374         if (recurse)
375         {
376                 setGraphicController_recursive(GetSGNode());
377         }
378 }
379
380
381 CValue* KX_GameObject::GetReplica()
382 {
383         KX_GameObject* replica = new KX_GameObject(*this);
384
385         // this will copy properties and so on...
386         replica->ProcessReplica();
387
388         return replica;
389 }
390
391
392
393 void KX_GameObject::ApplyForce(const MT_Vector3& force,bool local)
394 {
395         if (m_pPhysicsController1)
396                 m_pPhysicsController1->ApplyForce(force,local);
397 }
398
399
400
401 void KX_GameObject::ApplyTorque(const MT_Vector3& torque,bool local)
402 {
403         if (m_pPhysicsController1)
404                 m_pPhysicsController1->ApplyTorque(torque,local);
405 }
406
407
408
409 void KX_GameObject::ApplyMovement(const MT_Vector3& dloc,bool local)
410 {
411         if (GetSGNode()) 
412         {
413                 if (m_pPhysicsController1) // (IsDynamic())
414                 {
415                         m_pPhysicsController1->RelativeTranslate(dloc,local);
416                 }
417                 GetSGNode()->RelativeTranslate(dloc,GetSGNode()->GetSGParent(),local);
418         }
419 }
420
421
422
423 void KX_GameObject::ApplyRotation(const MT_Vector3& drot,bool local)
424 {
425         MT_Matrix3x3 rotmat(drot);
426         
427         if (GetSGNode()) {
428                 GetSGNode()->RelativeRotate(rotmat,local);
429
430                 if (m_pPhysicsController1) { // (IsDynamic())
431                         m_pPhysicsController1->RelativeRotate(rotmat,local); 
432                 }
433         }
434 }
435
436
437
438 /**
439 GetOpenGL Matrix, returns an OpenGL 'compatible' matrix
440 */
441 double* KX_GameObject::GetOpenGLMatrix()
442 {
443         // todo: optimize and only update if necessary
444         double* fl = m_OpenGL_4x4Matrix.getPointer();
445         if (GetSGNode()) {
446                 MT_Transform trans;
447         
448                 trans.setOrigin(GetSGNode()->GetWorldPosition());
449                 trans.setBasis(GetSGNode()->GetWorldOrientation());
450         
451                 MT_Vector3 scaling = GetSGNode()->GetWorldScaling();
452                 m_bIsNegativeScaling = ((scaling[0] < 0.0) ^ (scaling[1] < 0.0) ^ (scaling[2] < 0.0)) ? true : false;
453                 trans.scale(scaling[0], scaling[1], scaling[2]);
454                 trans.getValue(fl);
455                 GetSGNode()->ClearDirty();
456         }
457         return fl;
458 }
459
460 void KX_GameObject::AddMeshUser()
461 {
462         for (size_t i=0;i<m_meshes.size();i++)
463         {
464                 m_meshes[i]->AddMeshUser(this, &m_meshSlots, GetDeformer());
465         }
466         // set the part of the mesh slot that never change
467         double* fl = GetOpenGLMatrixPtr()->getPointer();
468
469         SG_QList::iterator<RAS_MeshSlot> mit(m_meshSlots);
470         RAS_MeshSlot* ms;
471         for(mit.begin(); !mit.end(); ++mit)
472         {
473                 (*mit)->m_OpenGLMatrix = fl;
474         }
475         UpdateBuckets(false);
476 }
477
478 static void UpdateBuckets_recursive(SG_Node* node)
479 {
480         NodeList& children = node->GetSGChildren();
481
482         for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
483         {
484                 SG_Node* childnode = (*childit);
485                 KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject());
486                 if (clientgameobj != NULL) // This is a GameObject
487                         clientgameobj->UpdateBuckets(0);
488                 
489                 // if the childobj is NULL then this may be an inverse parent link
490                 // so a non recursive search should still look down this node.
491                 UpdateBuckets_recursive(childnode);
492         }
493 }
494
495 void KX_GameObject::UpdateBuckets( bool recursive )
496 {
497         if (GetSGNode()) {
498                 RAS_MeshSlot *ms;
499
500                 if (GetSGNode()->IsDirty())
501                         GetOpenGLMatrix();
502
503                 SG_QList::iterator<RAS_MeshSlot> mit(m_meshSlots);
504                 for(mit.begin(); !mit.end(); ++mit)
505                 {
506                         ms = *mit;
507                         ms->m_bObjectColor = m_bUseObjectColor;
508                         ms->m_RGBAcolor = m_objectColor;
509                         ms->m_bVisible = m_bVisible;
510                         ms->m_bCulled = m_bCulled || !m_bVisible;
511                         if (!ms->m_bCulled) 
512                                 ms->m_bucket->ActivateMesh(ms);
513                         
514                         /* split if necessary */
515 #ifdef USE_SPLIT
516                         ms->Split();
517 #endif
518                 }
519         
520                 if (recursive) {
521                         UpdateBuckets_recursive(GetSGNode());
522                 }
523         }
524 }
525
526 void KX_GameObject::RemoveMeshes()
527 {
528         for (size_t i=0;i<m_meshes.size();i++)
529                 m_meshes[i]->RemoveFromBuckets(this);
530
531         //note: meshes can be shared, and are deleted by KX_BlenderSceneConverter
532
533         m_meshes.clear();
534 }
535
536 void KX_GameObject::UpdateTransform()
537 {
538         // HACK: saves function call for dynamic object, they are handled differently
539         if (m_pPhysicsController1 && !m_pPhysicsController1->IsDyna())
540                 // Note that for Bullet, this does not even update the transform of static object
541                 // but merely sets there collision flag to "kinematic" because the synchronization is 
542                 // done during physics simulation
543                 m_pPhysicsController1->SetSumoTransform(true);
544         if (m_pGraphicController)
545                 // update the culling tree
546                 m_pGraphicController->SetGraphicTransform();
547
548 }
549
550 void KX_GameObject::UpdateTransformFunc(SG_IObject* node, void* gameobj, void* scene)
551 {
552         ((KX_GameObject*)gameobj)->UpdateTransform();
553 }
554
555 void KX_GameObject::SynchronizeTransform()
556 {
557         // only used for sensor object, do full synchronization as bullet doesn't do it
558         if (m_pPhysicsController1)
559                 m_pPhysicsController1->SetTransform();
560         if (m_pGraphicController)
561                 m_pGraphicController->SetGraphicTransform();
562 }
563
564 void KX_GameObject::SynchronizeTransformFunc(SG_IObject* node, void* gameobj, void* scene)
565 {
566         ((KX_GameObject*)gameobj)->SynchronizeTransform();
567 }
568
569
570 void KX_GameObject::SetDebugColor(unsigned int bgra)
571 {
572         for (size_t i=0;i<m_meshes.size();i++)
573                 m_meshes[i]->DebugColor(bgra);  
574 }
575
576
577
578 void KX_GameObject::ResetDebugColor()
579 {
580         SetDebugColor(0xff000000);
581 }
582
583 void KX_GameObject::InitIPO(bool ipo_as_force,
584                                                         bool ipo_add,
585                                                         bool ipo_local)
586 {
587         SGControllerList::iterator it = GetSGNode()->GetSGControllerList().begin();
588
589         while (it != GetSGNode()->GetSGControllerList().end()) {
590                 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_RESET, true);
591                 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_AS_FORCE, ipo_as_force);
592                 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_ADD, ipo_add);
593                 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_LOCAL, ipo_local);
594                 it++;
595         }
596
597
598 void KX_GameObject::UpdateIPO(float curframetime,
599                                                           bool recurse) 
600 {
601         // just the 'normal' update procedure.
602         GetSGNode()->SetSimulatedTime(curframetime,recurse);
603         GetSGNode()->UpdateWorldData(curframetime);
604         UpdateTransform();
605 }
606
607 // IPO update
608 void 
609 KX_GameObject::UpdateMaterialData(
610                 dword matname_hash,
611                 MT_Vector4 rgba,
612                 MT_Vector3 specrgb,
613                 MT_Scalar hard,
614                 MT_Scalar spec,
615                 MT_Scalar ref,
616                 MT_Scalar emit,
617                 MT_Scalar alpha
618
619         )
620 {
621         int mesh = 0;
622         if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0) {
623                 list<RAS_MeshMaterial>::iterator mit = m_meshes[mesh]->GetFirstMaterial();
624
625                 for(; mit != m_meshes[mesh]->GetLastMaterial(); ++mit)
626                 {
627                         RAS_IPolyMaterial* poly = mit->m_bucket->GetPolyMaterial();
628
629                         if(poly->GetFlag() & RAS_BLENDERMAT )
630                         {
631                                 KX_BlenderMaterial *m =  static_cast<KX_BlenderMaterial*>(poly);
632                                 
633                                 if (matname_hash == 0)
634                                 {
635                                         m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha);
636                                         // if mesh has only one material attached to it then use original hack with no need to edit vertices (better performance)
637                                         SetObjectColor(rgba);
638                                 }
639                                 else
640                                 {
641                                         if (matname_hash == poly->GetMaterialNameHash())
642                                         {
643                                                 m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha);
644                                                 m_meshes[mesh]->SetVertexColor(poly,rgba);
645                                                 
646                                                 // no break here, because one blender material can be split into several game engine materials
647                                                 // (e.g. one uvsphere material is split into one material at poles with ras_mode TRIANGLE and one material for the body
648                                                 // if here was a break then would miss some vertices if material was split
649                                         }
650                                 }
651                         }
652                 }
653         }
654 }
655 bool
656 KX_GameObject::GetVisible(
657         void
658         )
659 {
660         return m_bVisible;
661 }
662
663 static void setVisible_recursive(SG_Node* node, bool v)
664 {
665         NodeList& children = node->GetSGChildren();
666
667         for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
668         {
669                 SG_Node* childnode = (*childit);
670                 KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject());
671                 if (clientgameobj != NULL) // This is a GameObject
672                         clientgameobj->SetVisible(v, 0);
673                 
674                 // if the childobj is NULL then this may be an inverse parent link
675                 // so a non recursive search should still look down this node.
676                 setVisible_recursive(childnode, v);
677         }
678 }
679
680
681 void
682 KX_GameObject::SetVisible(
683         bool v,
684         bool recursive
685         )
686 {
687         if (GetSGNode()) {
688                 m_bVisible = v;
689                 if (m_pGraphicController)
690                         m_pGraphicController->Activate(m_bVisible);
691                 if (recursive)
692                         setVisible_recursive(GetSGNode(), v);
693         }
694 }
695
696 static void setOccluder_recursive(SG_Node* node, bool v)
697 {
698         NodeList& children = node->GetSGChildren();
699
700         for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
701         {
702                 SG_Node* childnode = (*childit);
703                 KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject());
704                 if (clientgameobj != NULL) // This is a GameObject
705                         clientgameobj->SetOccluder(v, false);
706                 
707                 // if the childobj is NULL then this may be an inverse parent link
708                 // so a non recursive search should still look down this node.
709                 setOccluder_recursive(childnode, v);
710         }
711 }
712
713 void
714 KX_GameObject::SetOccluder(
715         bool v,
716         bool recursive
717         )
718 {
719         if (GetSGNode()) {
720                 m_bOccluder = v;
721                 if (recursive)
722                         setOccluder_recursive(GetSGNode(), v);
723         }
724 }
725
726 void
727 KX_GameObject::SetLayer(
728         int l
729         )
730 {
731         m_layer = l;
732 }
733
734 int
735 KX_GameObject::GetLayer(
736         void
737         )
738 {
739         return m_layer;
740 }
741
742 void KX_GameObject::addLinearVelocity(const MT_Vector3& lin_vel,bool local)
743 {
744         if (m_pPhysicsController1) 
745         {
746                 MT_Vector3 lv = local ? NodeGetWorldOrientation() * lin_vel : lin_vel;
747                 m_pPhysicsController1->SetLinearVelocity(lv + m_pPhysicsController1->GetLinearVelocity(), 0);
748         }
749 }
750
751
752
753 void KX_GameObject::setLinearVelocity(const MT_Vector3& lin_vel,bool local)
754 {
755         if (m_pPhysicsController1)
756                 m_pPhysicsController1->SetLinearVelocity(lin_vel,local);
757 }
758
759
760
761 void KX_GameObject::setAngularVelocity(const MT_Vector3& ang_vel,bool local)
762 {
763         if (m_pPhysicsController1)
764                 m_pPhysicsController1->SetAngularVelocity(ang_vel,local);
765 }
766
767
768 void KX_GameObject::ResolveCombinedVelocities(
769         const MT_Vector3 & lin_vel,
770         const MT_Vector3 & ang_vel,
771         bool lin_vel_local,
772         bool ang_vel_local
773 ){
774         if (m_pPhysicsController1)
775         {
776
777                 MT_Vector3 lv = lin_vel_local ? NodeGetWorldOrientation() * lin_vel : lin_vel;
778                 MT_Vector3 av = ang_vel_local ? NodeGetWorldOrientation() * ang_vel : ang_vel;
779                 m_pPhysicsController1->resolveCombinedVelocities(
780                         lv.x(),lv.y(),lv.z(),av.x(),av.y(),av.z());
781         }
782 }
783
784
785 void KX_GameObject::SetObjectColor(const MT_Vector4& rgbavec)
786 {
787         m_bUseObjectColor = true;
788         m_objectColor = rgbavec;
789 }
790
791 void KX_GameObject::AlignAxisToVect(const MT_Vector3& dir, int axis, float fac)
792 {
793         MT_Matrix3x3 orimat;
794         MT_Vector3 vect,ori,z,x,y;
795         MT_Scalar len;
796
797         // check on valid node in case a python controller holds a reference to a deleted object
798         if (!GetSGNode())
799                 return;
800
801         vect = dir;
802         len = vect.length();
803         if (MT_fuzzyZero(len))
804         {
805                 cout << "alignAxisToVect() Error: Null vector!\n";
806                 return;
807         }
808         
809         if (fac<=0.0) {
810                 return;
811         }
812         
813         // normalize
814         vect /= len;
815         orimat = GetSGNode()->GetWorldOrientation();
816         switch (axis)
817         {       
818                 case 0: //x axis
819                         ori.setValue(orimat[0][2], orimat[1][2], orimat[2][2]); //pivot axis
820                         if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON) //is the vector paralell to the pivot?
821                                 ori.setValue(orimat[0][1], orimat[1][1], orimat[2][1]); //change the pivot!
822                         if (fac == 1.0) {
823                                 x = vect;
824                         } else {
825                                 x = (vect * fac) + ((orimat * MT_Vector3(1.0, 0.0, 0.0)) * (1-fac));
826                                 len = x.length();
827                                 if (MT_fuzzyZero(len)) x = vect;
828                                 else x /= len;
829                         }
830                         y = ori.cross(x);
831                         z = x.cross(y);
832                         break;
833                 case 1: //y axis
834                         ori.setValue(orimat[0][0], orimat[1][0], orimat[2][0]);
835                         if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON)
836                                 ori.setValue(orimat[0][2], orimat[1][2], orimat[2][2]);
837                         if (fac == 1.0) {
838                                 y = vect;
839                         } else {
840                                 y = (vect * fac) + ((orimat * MT_Vector3(0.0, 1.0, 0.0)) * (1-fac));
841                                 len = y.length();
842                                 if (MT_fuzzyZero(len)) y = vect;
843                                 else y /= len;
844                         }
845                         z = ori.cross(y);
846                         x = y.cross(z);
847                         break;
848                 case 2: //z axis
849                         ori.setValue(orimat[0][1], orimat[1][1], orimat[2][1]);
850                         if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON)
851                                 ori.setValue(orimat[0][0], orimat[1][0], orimat[2][0]);
852                         if (fac == 1.0) {
853                                 z = vect;
854                         } else {
855                                 z = (vect * fac) + ((orimat * MT_Vector3(0.0, 0.0, 1.0)) * (1-fac));
856                                 len = z.length();
857                                 if (MT_fuzzyZero(len)) z = vect;
858                                 else z /= len;
859                         }
860                         x = ori.cross(z);
861                         y = z.cross(x);
862                         break;
863                 default: //wrong input?
864                         cout << "alignAxisToVect(): Wrong axis '" << axis <<"'\n";
865                         return;
866         }
867         x.normalize(); //normalize the vectors
868         y.normalize();
869         z.normalize();
870         orimat.setValue(        x[0],y[0],z[0],
871                                                 x[1],y[1],z[1],
872                                                 x[2],y[2],z[2]);
873         if (GetSGNode()->GetSGParent() != NULL)
874         {
875                 // the object is a child, adapt its local orientation so that 
876                 // the global orientation is aligned as we want.
877                 MT_Matrix3x3 invori = GetSGNode()->GetSGParent()->GetWorldOrientation().inverse();
878                 NodeSetLocalOrientation(invori*orimat);
879         }
880         else
881                 NodeSetLocalOrientation(orimat);
882 }
883
884 MT_Scalar KX_GameObject::GetMass()
885 {
886         if (m_pPhysicsController1)
887         {
888                 return m_pPhysicsController1->GetMass();
889         }
890         return 0.0;
891 }
892
893 MT_Vector3 KX_GameObject::GetLocalInertia()
894 {
895         MT_Vector3 local_inertia(0.0,0.0,0.0);
896         if (m_pPhysicsController1)
897         {
898                 local_inertia = m_pPhysicsController1->GetLocalInertia();
899         }
900         return local_inertia;
901 }
902
903 MT_Vector3 KX_GameObject::GetLinearVelocity(bool local)
904 {
905         MT_Vector3 velocity(0.0,0.0,0.0), locvel;
906         MT_Matrix3x3 ori;
907         if (m_pPhysicsController1)
908         {
909                 velocity = m_pPhysicsController1->GetLinearVelocity();
910                 
911                 if (local)
912                 {
913                         ori = GetSGNode()->GetWorldOrientation();
914                         
915                         locvel = velocity * ori;
916                         return locvel;
917                 }
918         }
919         return velocity;        
920 }
921
922 MT_Vector3 KX_GameObject::GetAngularVelocity(bool local)
923 {
924         MT_Vector3 velocity(0.0,0.0,0.0), locvel;
925         MT_Matrix3x3 ori;
926         if (m_pPhysicsController1)
927         {
928                 velocity = m_pPhysicsController1->GetAngularVelocity();
929                 
930                 if (local)
931                 {
932                         ori = GetSGNode()->GetWorldOrientation();
933                         
934                         locvel = velocity * ori;
935                         return locvel;
936                 }
937         }
938         return velocity;        
939 }
940
941 MT_Vector3 KX_GameObject::GetVelocity(const MT_Point3& point)
942 {
943         if (m_pPhysicsController1)
944         {
945                 return m_pPhysicsController1->GetVelocity(point);
946         }
947         return MT_Vector3(0.0,0.0,0.0);
948 }
949
950 // scenegraph node stuff
951
952 void KX_GameObject::NodeSetLocalPosition(const MT_Point3& trans)
953 {
954         // check on valid node in case a python controller holds a reference to a deleted object
955         if (!GetSGNode())
956                 return;
957
958         if (m_pPhysicsController1 && !GetSGNode()->GetSGParent())
959         {
960                 // don't update physic controller if the object is a child:
961                 // 1) the transformation will not be right
962                 // 2) in this case, the physic controller is necessarily a static object
963                 //    that is updated from the normal kinematic synchronization
964                 m_pPhysicsController1->setPosition(trans);
965         }
966
967         GetSGNode()->SetLocalPosition(trans);
968
969 }
970
971
972
973 void KX_GameObject::NodeSetLocalOrientation(const MT_Matrix3x3& rot)
974 {
975         // check on valid node in case a python controller holds a reference to a deleted object
976         if (!GetSGNode())
977                 return;
978
979         if (m_pPhysicsController1 && !GetSGNode()->GetSGParent())
980         {
981                 // see note above
982                 m_pPhysicsController1->setOrientation(rot);
983         }
984         GetSGNode()->SetLocalOrientation(rot);
985 }
986
987
988
989 void KX_GameObject::NodeSetLocalScale(const MT_Vector3& scale)
990 {
991         // check on valid node in case a python controller holds a reference to a deleted object
992         if (!GetSGNode())
993                 return;
994
995         if (m_pPhysicsController1 && !GetSGNode()->GetSGParent())
996         {
997                 // see note above
998                 m_pPhysicsController1->setScaling(scale);
999         }
1000         GetSGNode()->SetLocalScale(scale);
1001 }
1002
1003
1004
1005 void KX_GameObject::NodeSetRelativeScale(const MT_Vector3& scale)
1006 {
1007         if (GetSGNode())
1008         {
1009                 GetSGNode()->RelativeScale(scale);
1010                 if (m_pPhysicsController1 && (!GetSGNode()->GetSGParent()))
1011                 {
1012                         // see note above
1013                         // we can use the local scale: it's the same thing for a root object 
1014                         // and the world scale is not yet updated
1015                         MT_Vector3 newscale = GetSGNode()->GetLocalScale();
1016                         m_pPhysicsController1->setScaling(newscale);
1017                 }
1018         }
1019 }
1020
1021 void KX_GameObject::NodeSetWorldPosition(const MT_Point3& trans)
1022 {
1023         if (!GetSGNode())
1024                 return;
1025         SG_Node* parent = GetSGNode()->GetSGParent();
1026         if (parent != NULL)
1027         {
1028                 // Make sure the objects have some scale
1029                 MT_Vector3 scale = parent->GetWorldScaling();
1030                 if (fabs(scale[0]) < FLT_EPSILON || 
1031                         fabs(scale[1]) < FLT_EPSILON || 
1032                         fabs(scale[2]) < FLT_EPSILON)
1033                 { 
1034                         return; 
1035                 }
1036                 scale[0] = 1.0/scale[0];
1037                 scale[1] = 1.0/scale[1];
1038                 scale[2] = 1.0/scale[2];
1039                 MT_Matrix3x3 invori = parent->GetWorldOrientation().inverse();
1040                 MT_Vector3 newpos = invori*(trans-parent->GetWorldPosition())*scale;
1041                 NodeSetLocalPosition(MT_Point3(newpos[0],newpos[1],newpos[2]));
1042         }
1043         else 
1044         {
1045                 NodeSetLocalPosition(trans);
1046         }
1047 }
1048
1049
1050 void KX_GameObject::NodeUpdateGS(double time)
1051 {
1052         if (GetSGNode())
1053                 GetSGNode()->UpdateWorldData(time);
1054 }
1055
1056
1057
1058 const MT_Matrix3x3& KX_GameObject::NodeGetWorldOrientation() const
1059 {
1060         // check on valid node in case a python controller holds a reference to a deleted object
1061         if (!GetSGNode())
1062                 return dummy_orientation;
1063         return GetSGNode()->GetWorldOrientation();
1064 }
1065
1066
1067
1068 const MT_Vector3& KX_GameObject::NodeGetWorldScaling() const
1069 {
1070         // check on valid node in case a python controller holds a reference to a deleted object
1071         if (!GetSGNode())
1072                 return dummy_scaling;
1073
1074         return GetSGNode()->GetWorldScaling();
1075 }
1076
1077
1078
1079 const MT_Point3& KX_GameObject::NodeGetWorldPosition() const
1080 {
1081         // check on valid node in case a python controller holds a reference to a deleted object
1082         if (GetSGNode())
1083                 return GetSGNode()->GetWorldPosition();
1084         else
1085                 return dummy_point;
1086 }
1087
1088 /* Suspend/ resume: for the dynamic behaviour, there is a simple
1089  * method. For the residual motion, there is not. I wonder what the
1090  * correct solution is for Sumo. Remove from the motion-update tree?
1091  *
1092  * So far, only switch the physics and logic.
1093  * */
1094
1095 void KX_GameObject::Resume(void)
1096 {
1097         if (m_suspended) {
1098                 SCA_IObject::Resume();
1099                 if(GetPhysicsController())
1100                         GetPhysicsController()->RestoreDynamics();
1101
1102                 m_suspended = false;
1103         }
1104 }
1105
1106 void KX_GameObject::Suspend()
1107 {
1108         if ((!m_ignore_activity_culling) 
1109                 && (!m_suspended))  {
1110                 SCA_IObject::Suspend();
1111                 if(GetPhysicsController())
1112                         GetPhysicsController()->SuspendDynamics();
1113                 m_suspended = true;
1114         }
1115 }
1116
1117 static void walk_children(SG_Node* node, CListValue* list, bool recursive)
1118 {
1119         if (!node)
1120                 return;
1121         NodeList& children = node->GetSGChildren();
1122
1123         for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
1124         {
1125                 SG_Node* childnode = (*childit);
1126                 CValue* childobj = (CValue*)childnode->GetSGClientObject();
1127                 if (childobj != NULL) // This is a GameObject
1128                 {
1129                         // add to the list
1130                         list->Add(childobj->AddRef());
1131                 }
1132                 
1133                 // if the childobj is NULL then this may be an inverse parent link
1134                 // so a non recursive search should still look down this node.
1135                 if (recursive || childobj==NULL) {
1136                         walk_children(childnode, list, recursive);
1137                 }
1138         }
1139 }
1140
1141 CListValue* KX_GameObject::GetChildren()
1142 {
1143         CListValue* list = new CListValue();
1144         walk_children(GetSGNode(), list, 0); /* GetSGNode() is always valid or it would have raised an exception before this */
1145         return list;
1146 }
1147
1148 CListValue* KX_GameObject::GetChildrenRecursive()
1149 {
1150         CListValue* list = new CListValue();
1151         walk_children(GetSGNode(), list, 1);
1152         return list;
1153 }
1154
1155
1156 /* ------- python stuff ---------------------------------------------------*/
1157
1158 PyMethodDef KX_GameObject::Methods[] = {
1159         {"applyForce", (PyCFunction)    KX_GameObject::sPyApplyForce, METH_VARARGS},
1160         {"applyTorque", (PyCFunction)   KX_GameObject::sPyApplyTorque, METH_VARARGS},
1161         {"applyRotation", (PyCFunction) KX_GameObject::sPyApplyRotation, METH_VARARGS},
1162         {"applyMovement", (PyCFunction) KX_GameObject::sPyApplyMovement, METH_VARARGS},
1163         {"getLinearVelocity", (PyCFunction) KX_GameObject::sPyGetLinearVelocity, METH_VARARGS},
1164         {"setLinearVelocity", (PyCFunction) KX_GameObject::sPySetLinearVelocity, METH_VARARGS},
1165         {"getAngularVelocity", (PyCFunction) KX_GameObject::sPyGetAngularVelocity, METH_VARARGS},
1166         {"setAngularVelocity", (PyCFunction) KX_GameObject::sPySetAngularVelocity, METH_VARARGS},
1167         {"getVelocity", (PyCFunction) KX_GameObject::sPyGetVelocity, METH_VARARGS},
1168         {"getReactionForce", (PyCFunction) KX_GameObject::sPyGetReactionForce, METH_NOARGS},
1169         {"alignAxisToVect",(PyCFunction) KX_GameObject::sPyAlignAxisToVect, METH_VARARGS},
1170         {"getAxisVect",(PyCFunction) KX_GameObject::sPyGetAxisVect, METH_O},
1171         {"suspendDynamics", (PyCFunction)KX_GameObject::sPySuspendDynamics,METH_NOARGS},
1172         {"restoreDynamics", (PyCFunction)KX_GameObject::sPyRestoreDynamics,METH_NOARGS},
1173         {"enableRigidBody", (PyCFunction)KX_GameObject::sPyEnableRigidBody,METH_NOARGS},
1174         {"disableRigidBody", (PyCFunction)KX_GameObject::sPyDisableRigidBody,METH_NOARGS},
1175         {"applyImpulse", (PyCFunction) KX_GameObject::sPyApplyImpulse, METH_VARARGS},
1176         {"setCollisionMargin", (PyCFunction) KX_GameObject::sPySetCollisionMargin, METH_O},
1177         {"setParent", (PyCFunction)KX_GameObject::sPySetParent,METH_VARARGS},
1178         {"setVisible",(PyCFunction) KX_GameObject::sPySetVisible, METH_VARARGS},
1179         {"setOcclusion",(PyCFunction) KX_GameObject::sPySetOcclusion, METH_VARARGS},
1180         {"removeParent", (PyCFunction)KX_GameObject::sPyRemoveParent,METH_NOARGS},
1181         {"getChildren", (PyCFunction)KX_GameObject::sPyGetChildren,METH_NOARGS},
1182         {"getChildrenRecursive", (PyCFunction)KX_GameObject::sPyGetChildrenRecursive,METH_NOARGS},
1183         {"getPhysicsId", (PyCFunction)KX_GameObject::sPyGetPhysicsId,METH_NOARGS},
1184         {"getPropertyNames", (PyCFunction)KX_GameObject::sPyGetPropertyNames,METH_NOARGS},
1185         {"replaceMesh",(PyCFunction) KX_GameObject::sPyReplaceMesh, METH_O},
1186         {"endObject",(PyCFunction) KX_GameObject::sPyEndObject, METH_NOARGS},
1187         {"reinstancePhysicsMesh", (PyCFunction)KX_GameObject::sPyReinstancePhysicsMesh,METH_VARARGS},
1188         
1189         KX_PYMETHODTABLE(KX_GameObject, rayCastTo),
1190         KX_PYMETHODTABLE(KX_GameObject, rayCast),
1191         KX_PYMETHODTABLE_O(KX_GameObject, getDistanceTo),
1192         KX_PYMETHODTABLE_O(KX_GameObject, getVectTo),
1193         KX_PYMETHODTABLE(KX_GameObject, sendMessage),
1194         
1195         // dict style access for props
1196         {"has_key",(PyCFunction) KX_GameObject::sPyhas_key, METH_O},
1197         {"get",(PyCFunction) KX_GameObject::sPyget, METH_VARARGS},
1198         
1199         // deprecated
1200         {"getPosition", (PyCFunction) KX_GameObject::sPyGetPosition, METH_NOARGS},
1201         {"setPosition", (PyCFunction) KX_GameObject::sPySetPosition, METH_O},
1202         {"setWorldPosition", (PyCFunction) KX_GameObject::sPySetWorldPosition, METH_O},
1203         {"getOrientation", (PyCFunction) KX_GameObject::sPyGetOrientation, METH_NOARGS},
1204         {"setOrientation", (PyCFunction) KX_GameObject::sPySetOrientation, METH_O},
1205         {"getState",(PyCFunction) KX_GameObject::sPyGetState, METH_NOARGS},
1206         {"setState",(PyCFunction) KX_GameObject::sPySetState, METH_O},
1207         {"getParent", (PyCFunction)KX_GameObject::sPyGetParent,METH_NOARGS},
1208         {"getVisible",(PyCFunction) KX_GameObject::sPyGetVisible, METH_NOARGS},
1209         {"getMass", (PyCFunction) KX_GameObject::sPyGetMass, METH_NOARGS},
1210         {"getMesh", (PyCFunction)KX_GameObject::sPyGetMesh,METH_VARARGS},
1211         {NULL,NULL} //Sentinel
1212 };
1213
1214 PyAttributeDef KX_GameObject::Attributes[] = {
1215         KX_PYATTRIBUTE_RO_FUNCTION("name",              KX_GameObject, pyattr_get_name),
1216         KX_PYATTRIBUTE_RO_FUNCTION("parent",    KX_GameObject, pyattr_get_parent),
1217         KX_PYATTRIBUTE_RW_FUNCTION("mass",              KX_GameObject, pyattr_get_mass,         pyattr_set_mass),
1218         KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMin",            KX_GameObject, pyattr_get_lin_vel_min, pyattr_set_lin_vel_min),
1219         KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMax",            KX_GameObject, pyattr_get_lin_vel_max, pyattr_set_lin_vel_max),
1220         KX_PYATTRIBUTE_RW_FUNCTION("visible",   KX_GameObject, pyattr_get_visible,      pyattr_set_visible),
1221         KX_PYATTRIBUTE_BOOL_RW    ("occlusion", KX_GameObject, m_bOccluder),
1222         KX_PYATTRIBUTE_RW_FUNCTION("position",  KX_GameObject, pyattr_get_worldPosition,        pyattr_set_localPosition),
1223         KX_PYATTRIBUTE_RO_FUNCTION("localInertia",      KX_GameObject, pyattr_get_localInertia),
1224         KX_PYATTRIBUTE_RW_FUNCTION("orientation",KX_GameObject,pyattr_get_worldOrientation,pyattr_set_localOrientation),
1225         KX_PYATTRIBUTE_RW_FUNCTION("scaling",   KX_GameObject, pyattr_get_worldScaling, pyattr_set_localScaling),
1226         KX_PYATTRIBUTE_RW_FUNCTION("timeOffset",KX_GameObject, pyattr_get_timeOffset,pyattr_set_timeOffset),
1227         KX_PYATTRIBUTE_RW_FUNCTION("state",             KX_GameObject, pyattr_get_state,        pyattr_set_state),
1228         KX_PYATTRIBUTE_RO_FUNCTION("meshes",    KX_GameObject, pyattr_get_meshes),
1229         KX_PYATTRIBUTE_RW_FUNCTION("localOrientation",KX_GameObject,pyattr_get_localOrientation,pyattr_set_localOrientation),
1230         KX_PYATTRIBUTE_RW_FUNCTION("worldOrientation",KX_GameObject,pyattr_get_worldOrientation,pyattr_set_worldOrientation),
1231         KX_PYATTRIBUTE_RW_FUNCTION("localPosition",     KX_GameObject, pyattr_get_localPosition,        pyattr_set_localPosition),
1232         KX_PYATTRIBUTE_RW_FUNCTION("worldPosition",     KX_GameObject, pyattr_get_worldPosition,    pyattr_set_worldPosition),
1233         KX_PYATTRIBUTE_RW_FUNCTION("localScale",        KX_GameObject, pyattr_get_localScaling, pyattr_set_localScaling),
1234         KX_PYATTRIBUTE_RO_FUNCTION("worldScale",        KX_GameObject, pyattr_get_worldScaling),
1235         KX_PYATTRIBUTE_RO_FUNCTION("children",  KX_GameObject, pyattr_get_children),
1236         KX_PYATTRIBUTE_RO_FUNCTION("childrenRecursive", KX_GameObject, pyattr_get_children_recursive),
1237         KX_PYATTRIBUTE_RO_FUNCTION("attrDict",  KX_GameObject, pyattr_get_attrDict),
1238         
1239         /* Experemental, dont rely on these yet */
1240         KX_PYATTRIBUTE_RO_FUNCTION("sensors",           KX_GameObject, pyattr_get_sensors),
1241         KX_PYATTRIBUTE_RO_FUNCTION("controllers",       KX_GameObject, pyattr_get_controllers),
1242         KX_PYATTRIBUTE_RO_FUNCTION("actuators",         KX_GameObject, pyattr_get_actuators),
1243         {NULL} //Sentinel
1244 };
1245
1246
1247 /*
1248 bool KX_GameObject::ConvertPythonVectorArgs(PyObject* args,
1249                                                                                         MT_Vector3& pos,
1250                                                                                         MT_Vector3& pos2)
1251 {
1252         PyObject* pylist;
1253         PyObject* pylist2;
1254         bool error = (PyArg_ParseTuple(args,"OO",&pylist,&pylist2)) != 0;
1255
1256         pos = ConvertPythonPylist(pylist);
1257         pos2 = ConvertPythonPylist(pylist2);
1258                 
1259         return error;
1260 }
1261 */
1262
1263 PyObject* KX_GameObject::PyReplaceMesh(PyObject* value)
1264 {
1265         KX_Scene *scene = KX_GetActiveScene();
1266         RAS_MeshObject* new_mesh;
1267         
1268         if (!ConvertPythonToMesh(value, &new_mesh, false, "gameOb.replaceMesh(value): KX_GameObject"))
1269                 return NULL;
1270         
1271         scene->ReplaceMesh(this, new_mesh);
1272         Py_RETURN_NONE;
1273 }
1274
1275 PyObject* KX_GameObject::PyEndObject()
1276 {
1277         KX_Scene *scene = KX_GetActiveScene();
1278         
1279         scene->DelayedRemoveObject(this);
1280         
1281         Py_RETURN_NONE;
1282
1283 }
1284
1285 PyObject* KX_GameObject::PyReinstancePhysicsMesh(PyObject* args)
1286 {
1287         KX_GameObject *gameobj= NULL;
1288         RAS_MeshObject *mesh= NULL;
1289         
1290         PyObject *gameobj_py= NULL;
1291         PyObject *mesh_py= NULL;
1292
1293         if (    !PyArg_ParseTuple(args,"|OO:reinstancePhysicsMesh",&gameobj_py, &mesh_py) ||
1294                         (gameobj_py && !ConvertPythonToGameObject(gameobj_py, &gameobj, true, "gameOb.reinstancePhysicsMesh(obj, mesh): KX_GameObject")) || 
1295                         (mesh_py && !ConvertPythonToMesh(mesh_py, &mesh, true, "gameOb.reinstancePhysicsMesh(obj, mesh): KX_GameObject"))
1296                 ) {
1297                 return NULL;
1298         }
1299         
1300         /* gameobj and mesh can be NULL */
1301         if(KX_ReInstanceBulletShapeFromMesh(this, gameobj, mesh))
1302                 Py_RETURN_TRUE;
1303
1304         Py_RETURN_FALSE;
1305 }
1306
1307
1308 PyObject* KX_GameObject::PyGetPosition()
1309 {
1310         ShowDeprecationWarning("getPosition()", "the position property");
1311         return PyObjectFrom(NodeGetWorldPosition());
1312 }
1313
1314 static PyObject *Map_GetItem(PyObject *self_v, PyObject *item)
1315 {
1316         KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
1317         const char *attr_str= PyString_AsString(item);
1318         CValue* resultattr;
1319         PyObject* pyconvert;
1320         
1321         if (self==NULL) {
1322                 PyErr_SetString(PyExc_SystemError, "val = gameOb[key]: KX_GameObject, "BGE_PROXY_ERROR_MSG);
1323                 return NULL;
1324         }
1325         
1326         /* first see if the attributes a string and try get the cvalue attribute */
1327         if(attr_str && (resultattr=self->GetProperty(attr_str))) {
1328                 pyconvert = resultattr->ConvertValueToPython();                 
1329                 return pyconvert ? pyconvert:resultattr->GetProxy();
1330         }
1331         /* no CValue attribute, try get the python only m_attr_dict attribute */
1332         else if (self->m_attr_dict && (pyconvert=PyDict_GetItem(self->m_attr_dict, item))) {
1333                 
1334                 if (attr_str)
1335                         PyErr_Clear();
1336                 Py_INCREF(pyconvert);
1337                 return pyconvert;
1338         }
1339         else {
1340                 if(attr_str)    PyErr_Format(PyExc_KeyError, "value = gameOb[key]: KX_GameObject, key \"%s\" does not exist", attr_str);
1341                 else                    PyErr_SetString(PyExc_KeyError, "value = gameOb[key]: KX_GameObject, key does not exist");
1342                 return NULL;
1343         }
1344                 
1345 }
1346
1347
1348 static int Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val)
1349 {
1350         KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
1351         const char *attr_str= PyString_AsString(key);
1352         if(attr_str==NULL)
1353                 PyErr_Clear();
1354         
1355         if (self==NULL) {
1356                 PyErr_SetString(PyExc_SystemError, "gameOb[key] = value: KX_GameObject, "BGE_PROXY_ERROR_MSG);
1357                 return -1;
1358         }
1359         
1360         if (val==NULL) { /* del ob["key"] */
1361                 int del= 0;
1362                 
1363                 /* try remove both just incase */
1364                 if(attr_str)
1365                         del |= (self->RemoveProperty(attr_str)==true) ? 1:0;
1366                 
1367                 if(self->m_attr_dict)
1368                         del |= (PyDict_DelItem(self->m_attr_dict, key)==0) ? 1:0;
1369                 
1370                 if (del==0) {
1371                         if(attr_str)    PyErr_Format(PyExc_KeyError, "gameOb[key] = value: KX_GameObject, key \"%s\" could not be set", attr_str);
1372                         else                    PyErr_SetString(PyExc_KeyError, "del gameOb[key]: KX_GameObject, key could not be deleted");
1373                         return -1;
1374                 }
1375                 else if (self->m_attr_dict) {
1376                         PyErr_Clear(); /* PyDict_DelItem sets an error when it fails */
1377                 }
1378         }
1379         else { /* ob["key"] = value */
1380                 int set= 0;
1381                 
1382                 /* as CValue */
1383                 if(attr_str && BGE_PROXY_CHECK_TYPE(val)==0) /* dont allow GameObjects for eg to be assigned to CValue props */
1384                 {
1385                         CValue* vallie = self->ConvertPythonToValue(val, ""); /* error unused */
1386                         
1387                         if(vallie)
1388                         {
1389                                 CValue* oldprop = self->GetProperty(attr_str);
1390                                 
1391                                 if (oldprop)
1392                                         oldprop->SetValue(vallie);
1393                                 else
1394                                         self->SetProperty(attr_str, vallie);
1395                                 
1396                                 vallie->Release();
1397                                 set= 1;
1398                                 
1399                                 /* try remove dict value to avoid double ups */
1400                                 if (self->m_attr_dict){
1401                                         if (PyDict_DelItem(self->m_attr_dict, key) != 0)
1402                                                 PyErr_Clear();
1403                                 }
1404                         }
1405                         else {
1406                                 PyErr_Clear();
1407                         }
1408                 }
1409                 
1410                 if(set==0)
1411                 {
1412                         if (self->m_attr_dict==NULL) /* lazy init */
1413                                 self->m_attr_dict= PyDict_New();
1414                         
1415                         
1416                         if(PyDict_SetItem(self->m_attr_dict, key, val)==0)
1417                         {
1418                                 if(attr_str)
1419                                         self->RemoveProperty(attr_str); /* overwrite the CValue if it exists */
1420                                 set= 1;
1421                         }
1422                         else {
1423                                 if(attr_str)    PyErr_Format(PyExc_KeyError, "gameOb[key] = value: KX_GameObject, key \"%s\" not be added to internal dictionary", attr_str);
1424                                 else                    PyErr_SetString(PyExc_KeyError, "gameOb[key] = value: KX_GameObject, key not be added to internal dictionary");
1425                         }
1426                 }
1427                 
1428                 if(set==0)
1429                         return -1; /* pythons error value */
1430                 
1431         }
1432         
1433         return 0; /* success */
1434 }
1435
1436 static int Seq_Contains(PyObject *self_v, PyObject *value)
1437 {
1438         KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
1439         
1440         if (self==NULL) {
1441                 PyErr_SetString(PyExc_SystemError, "val in gameOb: KX_GameObject, "BGE_PROXY_ERROR_MSG);
1442                 return -1;
1443         }
1444         
1445         if(PyString_Check(value) && self->GetProperty(PyString_AsString(value)))
1446                 return 1;
1447         
1448         if (self->m_attr_dict && PyDict_GetItem(self->m_attr_dict, value))
1449                 return 1;
1450         
1451         return 0;
1452 }
1453
1454
1455 PyMappingMethods KX_GameObject::Mapping = {
1456         (lenfunc)NULL                                   ,                       /*inquiry mp_length */
1457         (binaryfunc)Map_GetItem,                /*binaryfunc mp_subscript */
1458         (objobjargproc)Map_SetItem,     /*objobjargproc mp_ass_subscript */
1459 };
1460
1461 PySequenceMethods KX_GameObject::Sequence = {
1462         NULL,           /* Cant set the len otherwise it can evaluate as false */
1463         NULL,           /* sq_concat */
1464         NULL,           /* sq_repeat */
1465         NULL,           /* sq_item */
1466         NULL,           /* sq_slice */
1467         NULL,           /* sq_ass_item */
1468         NULL,           /* sq_ass_slice */
1469         (objobjproc)Seq_Contains,       /* sq_contains */
1470 };
1471
1472 PyTypeObject KX_GameObject::Type = {
1473 #if (PY_VERSION_HEX >= 0x02060000)
1474         PyVarObject_HEAD_INIT(NULL, 0)
1475 #else
1476         /* python 2.5 and below */
1477         PyObject_HEAD_INIT( NULL )  /* required py macro */
1478         0,                          /* ob_size */
1479 #endif
1480                 "KX_GameObject",
1481                 sizeof(PyObjectPlus_Proxy),
1482                 0,
1483                 py_base_dealloc,
1484                 0,
1485                 0,
1486                 0,
1487                 0,
1488                 py_base_repr,
1489                 0,
1490                 &Sequence,
1491                 &Mapping,
1492                 0,0,0,
1493                 py_base_getattro,
1494                 py_base_setattro,
1495                 0,
1496                 Py_TPFLAGS_DEFAULT,
1497                 0,0,0,0,0,0,0,
1498                 Methods
1499 };
1500
1501
1502
1503
1504
1505
1506 PyParentObject KX_GameObject::Parents[] = {
1507         &KX_GameObject::Type,
1508                 &SCA_IObject::Type,
1509                 &CValue::Type,
1510                 NULL
1511 };
1512
1513 PyObject* KX_GameObject::pyattr_get_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1514 {
1515         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1516         return PyString_FromString(self->GetName().ReadPtr());
1517 }
1518
1519 PyObject* KX_GameObject::pyattr_get_parent(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1520 {
1521         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1522         KX_GameObject* parent = self->GetParent();
1523         if (parent) {
1524                 parent->Release(); /* self->GetParent() AddRef's */
1525                 return parent->GetProxy();
1526         }
1527         Py_RETURN_NONE;
1528 }
1529
1530 PyObject* KX_GameObject::pyattr_get_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1531 {
1532         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1533         KX_IPhysicsController *spc = self->GetPhysicsController();
1534         return PyFloat_FromDouble(spc ? spc->GetMass() : 0.0f);
1535 }
1536
1537 int KX_GameObject::pyattr_set_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1538 {
1539         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1540         KX_IPhysicsController *spc = self->GetPhysicsController();
1541         MT_Scalar val = PyFloat_AsDouble(value);
1542         if (val < 0.0f) { /* also accounts for non float */
1543                 PyErr_SetString(PyExc_AttributeError, "gameOb.mass = float: KX_GameObject, expected a float zero or above");
1544                 return PY_SET_ATTR_FAIL;
1545         }
1546
1547         if (spc)
1548                 spc->SetMass(val);
1549
1550         return PY_SET_ATTR_SUCCESS;
1551 }
1552
1553 PyObject* KX_GameObject::pyattr_get_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1554 {
1555         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1556         KX_IPhysicsController *spc = self->GetPhysicsController();
1557         return PyFloat_FromDouble(spc ? spc->GetLinVelocityMax() : 0.0f);
1558 }
1559
1560 int KX_GameObject::pyattr_set_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1561 {
1562         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1563         KX_IPhysicsController *spc = self->GetPhysicsController();
1564         MT_Scalar val = PyFloat_AsDouble(value);
1565         if (val < 0.0f) { /* also accounts for non float */
1566                 PyErr_SetString(PyExc_AttributeError, "gameOb.linVelocityMin = float: KX_GameObject, expected a float zero or above");
1567                 return PY_SET_ATTR_FAIL;
1568         }
1569
1570         if (spc)
1571                 spc->SetLinVelocityMin(val);
1572
1573         return PY_SET_ATTR_SUCCESS;
1574 }
1575
1576 PyObject* KX_GameObject::pyattr_get_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1577 {
1578         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1579         KX_IPhysicsController *spc = self->GetPhysicsController();
1580         return PyFloat_FromDouble(spc ? spc->GetLinVelocityMax() : 0.0f);
1581 }
1582
1583 int KX_GameObject::pyattr_set_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1584 {
1585         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1586         KX_IPhysicsController *spc = self->GetPhysicsController();
1587         MT_Scalar val = PyFloat_AsDouble(value);
1588         if (val < 0.0f) { /* also accounts for non float */
1589                 PyErr_SetString(PyExc_AttributeError, "gameOb.linVelocityMax = float: KX_GameObject, expected a float zero or above");
1590                 return PY_SET_ATTR_FAIL;
1591         }
1592
1593         if (spc)
1594                 spc->SetLinVelocityMax(val);
1595
1596         return PY_SET_ATTR_SUCCESS;
1597 }
1598
1599
1600 PyObject* KX_GameObject::pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1601 {
1602         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1603         return PyBool_FromLong(self->GetVisible());
1604 }
1605
1606 int KX_GameObject::pyattr_set_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1607 {
1608         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1609         int param = PyObject_IsTrue( value );
1610         if (param == -1) {
1611                 PyErr_SetString(PyExc_AttributeError, "gameOb.visible = bool: KX_GameObject, expected True or False");
1612                 return PY_SET_ATTR_FAIL;
1613         }
1614
1615         self->SetVisible(param, false);
1616         self->UpdateBuckets(false);
1617         return PY_SET_ATTR_SUCCESS;
1618 }
1619
1620 PyObject* KX_GameObject::pyattr_get_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1621 {
1622         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1623         return PyObjectFrom(self->NodeGetWorldPosition());
1624 }
1625
1626 int KX_GameObject::pyattr_set_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1627 {
1628         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1629         MT_Point3 pos;
1630         if (!PyVecTo(value, pos))
1631                 return PY_SET_ATTR_FAIL;
1632         
1633         self->NodeSetWorldPosition(pos);
1634         self->NodeUpdateGS(0.f);
1635         return PY_SET_ATTR_SUCCESS;
1636 }
1637
1638 PyObject* KX_GameObject::pyattr_get_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1639 {
1640         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1641         if (self->GetSGNode())
1642                 return PyObjectFrom(self->GetSGNode()->GetLocalPosition());
1643         else
1644                 return PyObjectFrom(dummy_point);
1645 }
1646
1647 int KX_GameObject::pyattr_set_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1648 {
1649         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1650         MT_Point3 pos;
1651         if (!PyVecTo(value, pos))
1652                 return PY_SET_ATTR_FAIL;
1653         
1654         self->NodeSetLocalPosition(pos);
1655         self->NodeUpdateGS(0.f);
1656         return PY_SET_ATTR_SUCCESS;
1657 }
1658
1659 PyObject* KX_GameObject::pyattr_get_localInertia(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1660 {
1661         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1662         if (self->GetPhysicsController())
1663         {
1664                 return PyObjectFrom(self->GetPhysicsController()->GetLocalInertia());
1665         }
1666         return Py_BuildValue("fff", 0.0f, 0.0f, 0.0f);
1667 }
1668
1669 PyObject* KX_GameObject::pyattr_get_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1670 {
1671         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1672         return PyObjectFrom(self->NodeGetWorldOrientation());
1673 }
1674
1675 int KX_GameObject::pyattr_set_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1676 {
1677         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1678         
1679         /* if value is not a sequence PyOrientationTo makes an error */
1680         MT_Matrix3x3 rot;
1681         if (!PyOrientationTo(value, rot, "gameOb.worldOrientation = sequence: KX_GameObject, "))
1682                 return PY_SET_ATTR_FAIL;
1683
1684         if (self->GetSGNode() && self->GetSGNode()->GetSGParent()) {
1685                 self->NodeSetLocalOrientation(self->GetSGNode()->GetSGParent()->GetWorldOrientation().inverse()*rot);
1686         }
1687         else {
1688                 self->NodeSetLocalOrientation(rot);
1689         }
1690         
1691         self->NodeUpdateGS(0.f);
1692         return PY_SET_ATTR_SUCCESS;
1693 }
1694
1695 PyObject* KX_GameObject::pyattr_get_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1696 {
1697         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1698         if (self->GetSGNode())
1699                 return PyObjectFrom(self->GetSGNode()->GetLocalOrientation());
1700         else
1701                 return PyObjectFrom(dummy_orientation);
1702 }
1703
1704 int KX_GameObject::pyattr_set_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1705 {
1706         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1707         
1708         /* if value is not a sequence PyOrientationTo makes an error */
1709         MT_Matrix3x3 rot;
1710         if (!PyOrientationTo(value, rot, "gameOb.localOrientation = sequence: KX_GameObject, "))
1711                 return PY_SET_ATTR_FAIL;
1712
1713         self->NodeSetLocalOrientation(rot);
1714         self->NodeUpdateGS(0.f);
1715         return PY_SET_ATTR_SUCCESS;
1716 }
1717
1718 PyObject* KX_GameObject::pyattr_get_worldScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1719 {
1720         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1721         return PyObjectFrom(self->NodeGetWorldScaling());
1722 }
1723
1724 PyObject* KX_GameObject::pyattr_get_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1725 {
1726         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1727         if (self->GetSGNode())
1728                 return PyObjectFrom(self->GetSGNode()->GetLocalScale());
1729         else
1730                 return PyObjectFrom(dummy_scaling);
1731 }
1732
1733 int KX_GameObject::pyattr_set_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1734 {
1735         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1736         MT_Vector3 scale;
1737         if (!PyVecTo(value, scale))
1738                 return PY_SET_ATTR_FAIL;
1739
1740         self->NodeSetLocalScale(scale);
1741         self->NodeUpdateGS(0.f);
1742         return PY_SET_ATTR_SUCCESS;
1743 }
1744
1745 PyObject* KX_GameObject::pyattr_get_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1746 {
1747         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1748         SG_Node* sg_parent;
1749         if (self->GetSGNode() && (sg_parent = self->GetSGNode()->GetSGParent()) != NULL && sg_parent->IsSlowParent()) {
1750                 return PyFloat_FromDouble(static_cast<KX_SlowParentRelation *>(sg_parent->GetParentRelation())->GetTimeOffset());
1751         } else {
1752                 return PyFloat_FromDouble(0.0);
1753         }
1754 }
1755
1756 int KX_GameObject::pyattr_set_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1757 {
1758         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1759         if (self->GetSGNode()) {
1760                 MT_Scalar val = PyFloat_AsDouble(value);
1761                 SG_Node* sg_parent= self->GetSGNode()->GetSGParent();
1762                 if (val < 0.0f) { /* also accounts for non float */
1763                         PyErr_SetString(PyExc_AttributeError, "gameOb.timeOffset = float: KX_GameObject, expected a float zero or above");
1764                         return PY_SET_ATTR_FAIL;
1765                 }
1766                 if (sg_parent && sg_parent->IsSlowParent())
1767                         static_cast<KX_SlowParentRelation *>(sg_parent->GetParentRelation())->SetTimeOffset(val);
1768         }
1769         return PY_SET_ATTR_SUCCESS;
1770 }
1771
1772 PyObject* KX_GameObject::pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1773 {
1774         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1775         int state = 0;
1776         state |= self->GetState();
1777         return PyInt_FromLong(state);
1778 }
1779
1780 int KX_GameObject::pyattr_set_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1781 {
1782         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1783         int state_i = PyInt_AsLong(value);
1784         unsigned int state = 0;
1785         
1786         if (state_i == -1 && PyErr_Occurred()) {
1787                 PyErr_SetString(PyExc_TypeError, "gameOb.state = int: KX_GameObject, expected an int bit field");
1788                 return PY_SET_ATTR_FAIL;
1789         }
1790         
1791         state |= state_i;
1792         if ((state & ((1<<30)-1)) == 0) {
1793                 PyErr_SetString(PyExc_AttributeError, "gameOb.state = int: KX_GameObject, state bitfield was not between 0 and 30 (1<<0 and 1<<29)");
1794                 return PY_SET_ATTR_FAIL;
1795         }
1796         self->SetState(state);
1797         return PY_SET_ATTR_SUCCESS;
1798 }
1799
1800 PyObject* KX_GameObject::pyattr_get_meshes(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1801 {
1802         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1803         PyObject *meshes= PyList_New(self->m_meshes.size());
1804         int i;
1805         
1806         for(i=0; i < (int)self->m_meshes.size(); i++)
1807         {
1808                 KX_MeshProxy* meshproxy = new KX_MeshProxy(self->m_meshes[i]);
1809                 PyList_SET_ITEM(meshes, i, meshproxy->NewProxy(true));
1810         }
1811         
1812         return meshes;
1813 }
1814
1815 /* experemental! */
1816 PyObject* KX_GameObject::pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1817 {
1818         return KX_PythonSeq_CreatePyObject((static_cast<KX_GameObject*>(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_SENSORS);
1819 }
1820
1821 PyObject* KX_GameObject::pyattr_get_controllers(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1822 {
1823         return KX_PythonSeq_CreatePyObject((static_cast<KX_GameObject*>(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_CONTROLLERS);
1824 }
1825
1826 PyObject* KX_GameObject::pyattr_get_actuators(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1827 {
1828         return KX_PythonSeq_CreatePyObject((static_cast<KX_GameObject*>(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_ACTUATORS);
1829 }
1830
1831 PyObject* KX_GameObject::pyattr_get_children(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1832 {
1833         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1834         return self->GetChildren()->NewProxy(true);
1835 }
1836
1837 PyObject* KX_GameObject::pyattr_get_children_recursive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1838 {
1839         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1840         return self->GetChildrenRecursive()->NewProxy(true);
1841 }
1842
1843 PyObject* KX_GameObject::pyattr_get_attrDict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1844 {
1845         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1846         
1847         if(self->m_attr_dict==NULL)
1848                 self->m_attr_dict= PyDict_New();
1849         
1850         Py_INCREF(self->m_attr_dict);
1851         return self->m_attr_dict;
1852 }
1853
1854 /* We need these because the macros have a return in them */
1855 PyObject* KX_GameObject::py_getattro__internal(PyObject *attr)
1856 {
1857         py_getattro_up(SCA_IObject);
1858 }
1859
1860 int KX_GameObject::py_setattro__internal(PyObject *attr, PyObject *value)       // py_setattro method
1861 {
1862         py_setattro_up(SCA_IObject);
1863 }
1864
1865
1866 PyObject* KX_GameObject::py_getattro(PyObject *attr)
1867 {
1868         PyObject *object= py_getattro__internal(attr);
1869         
1870         if (object==NULL && m_attr_dict)
1871         {
1872                 /* backup the exception incase the attr doesnt exist in the dict either */
1873                 PyObject *err_type, *err_value, *err_tb;
1874                 PyErr_Fetch(&err_type, &err_value, &err_tb);
1875                 
1876                 object= PyDict_GetItem(m_attr_dict, attr);
1877                 if (object) {
1878                         Py_INCREF(object);
1879                         
1880                         PyErr_Clear();
1881                         Py_XDECREF( err_type );
1882                         Py_XDECREF( err_value );
1883                         Py_XDECREF( err_tb );
1884                 }
1885                 else {
1886                         PyErr_Restore(err_type, err_value, err_tb); /* use the error from the parent function */
1887                 }
1888         }
1889         return object;
1890 }
1891
1892 PyObject* KX_GameObject::py_getattro_dict() {
1893         //py_getattro_dict_up(SCA_IObject);
1894         PyObject *dict= py_getattr_dict(SCA_IObject::py_getattro_dict(), Type.tp_dict);
1895         if(dict==NULL)
1896                 return NULL;
1897         
1898         /* normally just return this but KX_GameObject has some more items */
1899
1900         
1901         /* Not super fast getting as a list then making into dict keys but its only for dir() */
1902         PyObject *list= ConvertKeysToPython();
1903         if(list)
1904         {
1905                 int i;
1906                 for(i=0; i<PyList_Size(list); i++)
1907                         PyDict_SetItem(dict, PyList_GET_ITEM(list, i), Py_None);
1908         }
1909         else
1910                 PyErr_Clear();
1911         
1912         Py_DECREF(list);
1913         
1914         /* Add m_attr_dict if we have it */
1915         if(m_attr_dict)
1916                 PyDict_Update(dict, m_attr_dict);
1917         
1918         return dict;
1919 }
1920
1921 int KX_GameObject::py_setattro(PyObject *attr, PyObject *value) // py_setattro method
1922 {
1923         int ret= py_setattro__internal(attr, value);
1924         
1925         if (ret==PY_SET_ATTR_SUCCESS) {
1926                 /* remove attribute in our own dict to avoid double ups */
1927                 /* NOTE: Annoying that we also do this for setting builtin attributes like mass and visibility :/ */
1928                 if (m_attr_dict) {
1929                         if (PyDict_DelItem(m_attr_dict, attr) != 0)
1930                                 PyErr_Clear();
1931                 }
1932         }
1933         
1934         if (ret==PY_SET_ATTR_COERCE_FAIL) {
1935                 /* CValue attribute exists, remove CValue and add PyDict value */
1936                 RemoveProperty(PyString_AsString(attr));
1937                 ret= PY_SET_ATTR_MISSING;
1938         }
1939         
1940         if (ret==PY_SET_ATTR_MISSING) {
1941                 /* Lazy initialization */
1942                 if (m_attr_dict==NULL)
1943                         m_attr_dict = PyDict_New();
1944                 
1945                 if (PyDict_SetItem(m_attr_dict, attr, value)==0) {
1946                         PyErr_Clear();
1947                         ret= PY_SET_ATTR_SUCCESS;
1948                 }
1949                 else {
1950                         PyErr_Format(PyExc_AttributeError, "gameOb.myAttr = value: KX_GameObject, failed assigning value to internal dictionary");
1951                         ret= PY_SET_ATTR_FAIL;
1952                 }
1953         }
1954         
1955         return ret;     
1956 }
1957
1958
1959 int     KX_GameObject::py_delattro(PyObject *attr)
1960 {
1961         ShowDeprecationWarning("del ob.attr", "del ob['attr'] for user defined properties");
1962         
1963         char *attr_str= PyString_AsString(attr); 
1964         
1965         if (RemoveProperty(attr_str)) // XXX - should call CValues instead but its only 2 lines here
1966                 return PY_SET_ATTR_SUCCESS;
1967         
1968         if (m_attr_dict && (PyDict_DelItem(m_attr_dict, attr) == 0))
1969                 return PY_SET_ATTR_SUCCESS;
1970         
1971         PyErr_Format(PyExc_AttributeError, "del gameOb.myAttr: KX_GameObject, attribute \"%s\" dosnt exist", attr_str);
1972         return PY_SET_ATTR_MISSING;
1973 }
1974
1975
1976 PyObject* KX_GameObject::PyApplyForce(PyObject* args)
1977 {
1978         int local = 0;
1979         PyObject* pyvect;
1980
1981         if (PyArg_ParseTuple(args, "O|i:applyForce", &pyvect, &local)) {
1982                 MT_Vector3 force;
1983                 if (PyVecTo(pyvect, force)) {
1984                         ApplyForce(force, (local!=0));
1985                         Py_RETURN_NONE;
1986                 }
1987         }
1988         return NULL;
1989 }
1990
1991 PyObject* KX_GameObject::PyApplyTorque(PyObject* args)
1992 {
1993         int local = 0;
1994         PyObject* pyvect;
1995
1996         if (PyArg_ParseTuple(args, "O|i:applyTorque", &pyvect, &local)) {
1997                 MT_Vector3 torque;
1998                 if (PyVecTo(pyvect, torque)) {
1999                         ApplyTorque(torque, (local!=0));
2000                         Py_RETURN_NONE;
2001                 }
2002         }
2003         return NULL;
2004 }
2005
2006 PyObject* KX_GameObject::PyApplyRotation(PyObject* args)
2007 {
2008         int local = 0;
2009         PyObject* pyvect;
2010
2011         if (PyArg_ParseTuple(args, "O|i:applyRotation", &pyvect, &local)) {
2012                 MT_Vector3 rotation;
2013                 if (PyVecTo(pyvect, rotation)) {
2014                         ApplyRotation(rotation, (local!=0));
2015                         Py_RETURN_NONE;
2016                 }
2017         }
2018         return NULL;
2019 }
2020
2021 PyObject* KX_GameObject::PyApplyMovement(PyObject* args)
2022 {
2023         int local = 0;
2024         PyObject* pyvect;
2025
2026         if (PyArg_ParseTuple(args, "O|i:applyMovement", &pyvect, &local)) {
2027                 MT_Vector3 movement;
2028                 if (PyVecTo(pyvect, movement)) {
2029                         ApplyMovement(movement, (local!=0));
2030                         Py_RETURN_NONE;
2031                 }
2032         }
2033         return NULL;
2034 }
2035
2036 PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* args)
2037 {
2038         // only can get the velocity if we have a physics object connected to us...
2039         int local = 0;
2040         if (PyArg_ParseTuple(args,"|i:getLinearVelocity",&local))
2041         {
2042                 return PyObjectFrom(GetLinearVelocity((local!=0)));
2043         }
2044         else
2045         {
2046                 return NULL;
2047         }
2048 }
2049
2050 PyObject* KX_GameObject::PySetLinearVelocity(PyObject* args)
2051 {
2052         int local = 0;
2053         PyObject* pyvect;
2054         
2055         if (PyArg_ParseTuple(args,"O|i:setLinearVelocity",&pyvect,&local)) {
2056                 MT_Vector3 velocity;
2057                 if (PyVecTo(pyvect, velocity)) {
2058                         setLinearVelocity(velocity, (local!=0));
2059                         Py_RETURN_NONE;
2060                 }
2061         }
2062         return NULL;
2063 }
2064
2065 PyObject* KX_GameObject::PyGetAngularVelocity(PyObject* args)
2066 {
2067         // only can get the velocity if we have a physics object connected to us...
2068         int local = 0;
2069         if (PyArg_ParseTuple(args,"|i:getAngularVelocity",&local))
2070         {
2071                 return PyObjectFrom(GetAngularVelocity((local!=0)));
2072         }
2073         else
2074         {
2075                 return NULL;
2076         }
2077 }
2078
2079 PyObject* KX_GameObject::PySetAngularVelocity(PyObject* args)
2080 {
2081         int local = 0;
2082         PyObject* pyvect;
2083         
2084         if (PyArg_ParseTuple(args,"O|i:setAngularVelocity",&pyvect,&local)) {
2085                 MT_Vector3 velocity;
2086                 if (PyVecTo(pyvect, velocity)) {
2087                         setAngularVelocity(velocity, (local!=0));
2088                         Py_RETURN_NONE;
2089                 }
2090         }
2091         return NULL;
2092 }
2093
2094 PyObject* KX_GameObject::PySetVisible(PyObject* args)
2095 {
2096         int visible, recursive = 0;
2097         if (!PyArg_ParseTuple(args,"i|i:setVisible",&visible, &recursive))
2098                 return NULL;
2099         
2100         SetVisible(visible ? true:false, recursive ? true:false);
2101         UpdateBuckets(recursive ? true:false);
2102         Py_RETURN_NONE;
2103         
2104 }
2105
2106 PyObject* KX_GameObject::PySetOcclusion(PyObject* args)
2107 {
2108         int occlusion, recursive = 0;
2109         if (!PyArg_ParseTuple(args,"i|i:setOcclusion",&occlusion, &recursive))
2110                 return NULL;
2111         
2112         SetOccluder(occlusion ? true:false, recursive ? true:false);
2113         Py_RETURN_NONE;
2114 }
2115
2116 PyObject* KX_GameObject::PyGetVisible()
2117 {
2118         ShowDeprecationWarning("getVisible()", "the visible property");
2119         return PyInt_FromLong(m_bVisible);      
2120 }
2121
2122 PyObject* KX_GameObject::PyGetState()
2123 {
2124         ShowDeprecationWarning("getState()", "the state property");
2125         int state = 0;
2126         state |= GetState();
2127         return PyInt_FromLong(state);
2128 }
2129
2130 PyObject* KX_GameObject::PySetState(PyObject* value)
2131 {
2132         ShowDeprecationWarning("setState()", "the state property");
2133         int state_i = PyInt_AsLong(value);
2134         unsigned int state = 0;
2135         
2136         if (state_i == -1 && PyErr_Occurred()) {
2137                 PyErr_SetString(PyExc_TypeError, "expected an int bit field");
2138                 return NULL;
2139         }
2140         
2141         state |= state_i;
2142         if ((state & ((1<<30)-1)) == 0) {
2143                 PyErr_SetString(PyExc_AttributeError, "The state bitfield was not between 0 and 30 (1<<0 and 1<<29)");
2144                 return NULL;
2145         }
2146         SetState(state);
2147         
2148         Py_RETURN_NONE;
2149 }
2150
2151 PyObject* KX_GameObject::PyGetVelocity(PyObject* args)
2152 {
2153         // only can get the velocity if we have a physics object connected to us...
2154         MT_Point3 point(0.0,0.0,0.0);
2155         PyObject* pypos = NULL;
2156         
2157         if (!PyArg_ParseTuple(args, "|O:getVelocity", &pypos) || (pypos && !PyVecTo(pypos, point)))
2158                 return NULL;
2159         
2160         if (m_pPhysicsController1)
2161         {
2162                 return PyObjectFrom(m_pPhysicsController1->GetVelocity(point));
2163         }
2164         else {
2165                 return PyObjectFrom(MT_Vector3(0.0,0.0,0.0));
2166         }
2167 }
2168
2169
2170
2171 PyObject* KX_GameObject::PyGetMass()
2172 {
2173         ShowDeprecationWarning("getMass()", "the mass property");
2174         return PyFloat_FromDouble((GetPhysicsController() != NULL) ? GetPhysicsController()->GetMass() : 0.0f);
2175 }
2176
2177 PyObject* KX_GameObject::PyGetReactionForce()
2178 {
2179         // only can get the velocity if we have a physics object connected to us...
2180         
2181         // XXX - Currently not working with bullet intergration, see KX_BulletPhysicsController.cpp's getReactionForce
2182         /*
2183         if (GetPhysicsController())
2184                 return PyObjectFrom(GetPhysicsController()->getReactionForce());
2185         return PyObjectFrom(dummy_point);
2186         */
2187         
2188         return Py_BuildValue("fff", 0.0f, 0.0f, 0.0f);
2189         
2190 }
2191
2192
2193
2194 PyObject* KX_GameObject::PyEnableRigidBody()
2195 {
2196         if(GetPhysicsController())
2197                 GetPhysicsController()->setRigidBody(true);
2198
2199         Py_RETURN_NONE;
2200 }
2201
2202
2203
2204 PyObject* KX_GameObject::PyDisableRigidBody()
2205 {
2206         if(GetPhysicsController())
2207                 GetPhysicsController()->setRigidBody(false);
2208
2209         Py_RETURN_NONE;
2210 }
2211
2212
2213
2214 PyObject* KX_GameObject::PyGetParent()
2215 {
2216         ShowDeprecationWarning("getParent()", "the parent property");
2217         KX_GameObject* parent = this->GetParent();
2218         if (parent) {
2219                 parent->Release(); /* self->GetParent() AddRef's */
2220                 return parent->GetProxy();
2221         }
2222         Py_RETURN_NONE;
2223 }
2224
2225 PyObject* KX_GameObject::PySetParent(PyObject* args)
2226 {
2227         KX_Scene *scene = KX_GetActiveScene();
2228         PyObject* pyobj;
2229         KX_GameObject *obj;
2230         int addToCompound=1, ghost=1;
2231         
2232         if (!PyArg_ParseTuple(args,"O|ii:setParent", &pyobj, &addToCompound, &ghost)) {
2233                 return NULL; // Python sets a simple error
2234         }
2235         if (!ConvertPythonToGameObject(pyobj, &obj, true, "gameOb.setParent(obj): KX_GameObject"))
2236                 return NULL;
2237         if (obj)
2238                 this->SetParent(scene, obj, addToCompound, ghost);
2239         Py_RETURN_NONE;
2240 }
2241
2242 PyObject* KX_GameObject::PyRemoveParent()
2243 {
2244         KX_Scene *scene = KX_GetActiveScene();
2245         
2246         this->RemoveParent(scene);
2247         Py_RETURN_NONE;
2248 }
2249
2250 PyObject* KX_GameObject::PyGetChildren()
2251 {
2252         ShowDeprecationWarning("getChildren()", "the children property");
2253         
2254         return GetChildren()->NewProxy(true);
2255 }
2256
2257 PyObject* KX_GameObject::PyGetChildrenRecursive()
2258 {
2259         ShowDeprecationWarning("getChildrenRecursive()", "the childrenRecursive property");
2260         
2261         return GetChildrenRecursive()->NewProxy(true);
2262 }
2263
2264 PyObject* KX_GameObject::PyGetMesh(PyObject* args)
2265 {
2266         ShowDeprecationWarning("getMesh()", "the meshes property (now a list of meshes)");
2267         
2268         int mesh = 0;
2269
2270         if (!PyArg_ParseTuple(args, "|i:getMesh", &mesh))
2271                 return NULL; // python sets a simple error
2272         
2273         if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0)
2274         {
2275                 KX_MeshProxy* meshproxy = new KX_MeshProxy(m_meshes[mesh]);
2276                 return meshproxy->NewProxy(true); // XXX Todo Python own.
2277         }
2278         
2279         Py_RETURN_NONE;
2280 }
2281
2282
2283
2284
2285
2286 PyObject* KX_GameObject::PySetCollisionMargin(PyObject* value)
2287 {
2288         float collisionMargin = PyFloat_AsDouble(value);
2289         
2290         if (collisionMargin==-1 && PyErr_Occurred()) {
2291                 PyErr_SetString(PyExc_TypeError, "expected a float");
2292                 return NULL;
2293         }
2294         
2295         if (m_pPhysicsController1)
2296         {
2297                 m_pPhysicsController1->setMargin(collisionMargin);
2298                 Py_RETURN_NONE;
2299         }
2300         PyErr_SetString(PyExc_RuntimeError, "This object has no physics controller");
2301         return NULL;
2302 }
2303
2304
2305
2306 PyObject* KX_GameObject::PyApplyImpulse(PyObject* args)
2307 {
2308         PyObject* pyattach;
2309         PyObject* pyimpulse;
2310         
2311         if (!m_pPhysicsController1)     {
2312                 PyErr_SetString(PyExc_RuntimeError, "This object has no physics controller");
2313                 return NULL;
2314         }
2315         
2316         if (PyArg_ParseTuple(args, "OO:applyImpulse", &pyattach, &pyimpulse))
2317         {
2318                 MT_Point3  attach;
2319                 MT_Vector3 impulse;
2320                 if (PyVecTo(pyattach, attach) && PyVecTo(pyimpulse, impulse))
2321                 {
2322                         m_pPhysicsController1->applyImpulse(attach, impulse);
2323                         Py_RETURN_NONE;
2324                 }
2325
2326         }
2327         
2328         return NULL;
2329 }
2330
2331
2332
2333 PyObject* KX_GameObject::PySuspendDynamics()
2334 {
2335         SuspendDynamics();
2336         Py_RETURN_NONE;
2337 }
2338
2339
2340
2341 PyObject* KX_GameObject::PyRestoreDynamics()
2342 {
2343         RestoreDynamics();
2344         Py_RETURN_NONE;
2345 }
2346
2347
2348
2349 PyObject* KX_GameObject::PyGetOrientation() //keywords
2350 {
2351         ShowDeprecationWarning("getOrientation()", "the orientation property");
2352         return PyObjectFrom(NodeGetWorldOrientation());
2353 }
2354
2355
2356
2357 PyObject* KX_GameObject::PySetOrientation(PyObject* value)
2358 {
2359         ShowDeprecationWarning("setOrientation()", "the orientation property");
2360         MT_Matrix3x3 rot;
2361         
2362         /* if value is not a sequence PyOrientationTo makes an error */
2363         if (!PyOrientationTo(value, rot, "gameOb.setOrientation(sequence): KX_GameObject, "))
2364                 return NULL;
2365
2366         NodeSetLocalOrientation(rot);
2367         NodeUpdateGS(0.f);
2368         Py_RETURN_NONE;
2369 }
2370
2371 PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* args)
2372 {
2373         PyObject* pyvect;
2374         int axis = 2; //z axis is the default
2375         float fac = 1.0;
2376         
2377         if (PyArg_ParseTuple(args,"O|if:alignAxisToVect",&pyvect,&axis, &fac))
2378         {
2379                 MT_Vector3 vect;
2380                 if (PyVecTo(pyvect, vect))
2381                 {
2382                         if (fac<=0.0) Py_RETURN_NONE; // Nothing to do.
2383                         if (fac> 1.0) fac= 1.0;
2384                         
2385                         AlignAxisToVect(vect,axis,fac);
2386                         NodeUpdateGS(0.f);
2387                         Py_RETURN_NONE;
2388                 }
2389         }
2390         return NULL;
2391 }
2392
2393 PyObject* KX_GameObject::PyGetAxisVect(PyObject* value)
2394 {
2395         MT_Vector3 vect;
2396         if (PyVecTo(value, vect))
2397         {
2398                 return PyObjectFrom(NodeGetWorldOrientation() * vect);
2399         }
2400         return NULL;
2401 }
2402
2403 PyObject* KX_GameObject::PySetPosition(PyObject* value)
2404 {
2405         ShowDeprecationWarning("setPosition()", "the localPosition property");
2406         MT_Point3 pos;
2407         if (PyVecTo(value, pos))
2408         {
2409                 NodeSetLocalPosition(pos);
2410                 NodeUpdateGS(0.f);
2411                 Py_RETURN_NONE;
2412         }
2413
2414         return NULL;
2415 }
2416
2417 PyObject* KX_GameObject::PySetWorldPosition(PyObject* value)
2418 {
2419         ShowDeprecationWarning("setWorldPosition()", "the worldPosition property");
2420         MT_Point3 pos;
2421         if (PyVecTo(value, pos))
2422         {
2423                 NodeSetWorldPosition(pos);
2424                 NodeUpdateGS(0.f);
2425                 Py_RETURN_NONE;
2426         }
2427
2428         return NULL;
2429 }
2430
2431 PyObject* KX_GameObject::PyGetPhysicsId()
2432 {
2433         KX_IPhysicsController* ctrl = GetPhysicsController();
2434         uint_ptr physid=0;
2435         if (ctrl)
2436         {
2437                 physid= (uint_ptr)ctrl->GetUserData();
2438         }
2439         return PyInt_FromLong((long)physid);
2440 }
2441
2442 PyObject* KX_GameObject::PyGetPropertyNames()
2443 {
2444         PyObject *list=  ConvertKeysToPython();
2445         
2446         if(m_attr_dict) {
2447                 PyObject *key, *value;
2448                 Py_ssize_t pos = 0;
2449
2450                 while (PyDict_Next(m_attr_dict, &pos, &key, &value)) {
2451                         PyList_Append(list, key);
2452                 }
2453         }
2454         return list;
2455 }
2456
2457 KX_PYMETHODDEF_DOC_O(KX_GameObject, getDistanceTo,
2458 "getDistanceTo(other): get distance to another point/KX_GameObject")
2459 {
2460         MT_Point3 b;
2461         if (PyVecTo(value, b))
2462         {
2463                 return PyFloat_FromDouble(NodeGetWorldPosition().distance(b));
2464         }
2465         PyErr_Clear();
2466         
2467         KX_GameObject *other;
2468         if (ConvertPythonToGameObject(value, &other, false, "gameOb.getDistanceTo(value): KX_GameObject"))
2469         {
2470                 return PyFloat_FromDouble(NodeGetWorldPosition().distance(other->NodeGetWorldPosition()));
2471         }
2472         
2473         return NULL;
2474 }
2475
2476 KX_PYMETHODDEF_DOC_O(KX_GameObject, getVectTo,
2477 "getVectTo(other): get vector and the distance to another point/KX_GameObject\n"
2478 "Returns a 3-tuple with (distance,worldVector,localVector)\n")
2479 {
2480         MT_Point3 toPoint, fromPoint;
2481         MT_Vector3 toDir, locToDir;
2482         MT_Scalar distance;
2483
2484         PyObject *returnValue;
2485
2486         if (!PyVecTo(value, toPoint))
2487         {
2488                 PyErr_Clear();
2489                 
2490                 KX_GameObject *other;
2491                 if (ConvertPythonToGameObject(value, &other, false, "")) /* error will be overwritten */
2492                 {
2493                         toPoint = other->NodeGetWorldPosition();
2494                 } else
2495                 {
2496                         PyErr_SetString(PyExc_TypeError, "gameOb.getVectTo(other): KX_GameObject, expected a 3D Vector or KX_GameObject type");
2497                         return NULL;
2498                 }
2499         }
2500
2501         fromPoint = NodeGetWorldPosition();
2502         toDir = toPoint-fromPoint;
2503         distance = toDir.length();
2504
2505         if (MT_fuzzyZero(distance))
2506         {
2507                 //cout << "getVectTo() Error: Null vector!\n";
2508                 locToDir = toDir = MT_Vector3(0.0,0.0,0.0);
2509                 distance = 0.0;
2510         } else {
2511                 toDir.normalize();
2512                 locToDir = toDir * NodeGetWorldOrientation();
2513         }
2514         
2515         returnValue = PyTuple_New(3);
2516         if (returnValue) { // very unlikely to fail, python sets a memory error here.
2517                 PyTuple_SET_ITEM(returnValue, 0, PyFloat_FromDouble(distance));
2518                 PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(toDir));
2519                 PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(locToDir));
2520         }
2521         return returnValue;
2522 }
2523
2524 bool KX_GameObject::RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data)
2525 {
2526         KX_GameObject* hitKXObj = client->m_gameobject;
2527         
2528         // if X-ray option is selected, the unwnted objects were not tested, so get here only with true hit
2529         // if not, all objects were tested and the front one may not be the correct one.
2530         if (m_xray || m_testPropName.Length() == 0 || hitKXObj->GetProperty(m_testPropName) != NULL)
2531         {
2532                 m_pHitObject = hitKXObj;
2533                 return true;
2534         }
2535         // return true to stop RayCast::RayTest from looping, the above test was decisive
2536         // We would want to loop only if we want to get more than one hit point
2537         return true;
2538 }
2539
2540 /* this function is used to pre-filter the object before casting the ray on them.
2541    This is useful for "X-Ray" option when we want to see "through" unwanted object.
2542  */
2543 bool KX_GameObject::NeedRayCast(KX_ClientObjectInfo* client)
2544 {
2545         KX_GameObject* hitKXObj = client->m_gameobject;
2546         
2547         if (client->m_type > KX_ClientObjectInfo::ACTOR)
2548         {
2549                 // Unknown type of object, skip it.
2550                 // Should not occur as the sensor objects are filtered in RayTest()
2551                 printf("Invalid client type %d found in ray casting\n", client->m_type);
2552                 return false;
2553         }
2554         
2555         // if X-Ray option is selected, skip object that don't match the criteria as we see through them
2556         // if not, test all objects because we don't know yet which one will be on front
2557         if (!m_xray || m_testPropName.Length() == 0 || hitKXObj->GetProperty(m_testPropName) != NULL)
2558         {
2559                 return true;
2560         }
2561         // skip the object
2562         return false;
2563 }
2564
2565 KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo,
2566 "rayCastTo(other,dist,prop): look towards another point/KX_GameObject and return first object hit within dist that matches prop\n"
2567 " prop = property name that object must have; can be omitted => detect any object\n"
2568 " dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to other\n"
2569 " other = 3-tuple or object reference")
2570 {
2571         MT_Point3 toPoint;
2572         PyObject* pyarg;
2573         float dist = 0.0f;
2574         char *propName = NULL;
2575
2576         if (!PyArg_ParseTuple(args,"O|fs:rayCastTo", &pyarg, &dist, &propName)) {
2577                 return NULL; // python sets simple error
2578         }
2579
2580         if (!PyVecTo(pyarg, toPoint))
2581         {
2582                 KX_GameObject *other;
2583                 PyErr_Clear();
2584                 
2585                 if (ConvertPythonToGameObject(pyarg, &other, false, "")) /* error will be overwritten */
2586                 {
2587                         toPoint = other->NodeGetWorldPosition();
2588                 } else
2589                 {
2590                         PyErr_SetString(PyExc_TypeError, "gameOb.rayCastTo(other,dist,prop): KX_GameObject, the first argument to rayCastTo must be a vector or a KX_GameObject");
2591                         return NULL;
2592                 }
2593         }
2594         MT_Point3 fromPoint = NodeGetWorldPosition();
2595         if (dist != 0.0f)
2596         {
2597                 MT_Vector3 toDir = toPoint-fromPoint;
2598                 toDir.normalize();
2599                 toPoint = fromPoint + (dist) * toDir;
2600         }
2601
2602         PHY_IPhysicsEnvironment* pe = GetPhysicsEnvironment();
2603         KX_IPhysicsController *spc = GetPhysicsController();
2604         KX_GameObject *parent = GetParent();
2605         if (!spc && parent)
2606                 spc = parent->GetPhysicsController();
2607         if (parent)
2608                 parent->Release();
2609         
2610         m_pHitObject = NULL;
2611         if (propName)
2612                 m_testPropName = propName;
2613         else
2614                 m_testPropName.SetLength(0);
2615         KX_RayCast::Callback<KX_GameObject> callback(this,spc);
2616         KX_RayCast::RayTest(pe, fromPoint, toPoint, callback);
2617
2618     if (m_pHitObject)
2619                 return m_pHitObject->GetProxy();
2620         
2621         Py_RETURN_NONE;
2622 }
2623
2624 /* faster then Py_BuildValue since some scripts call raycast a lot */
2625 static PyObject *none_tuple_3()
2626 {
2627         PyObject *ret= PyTuple_New(3);
2628         PyTuple_SET_ITEM(ret, 0, Py_None);
2629         PyTuple_SET_ITEM(ret, 1, Py_None);
2630         PyTuple_SET_ITEM(ret, 2, Py_None);
2631         
2632         Py_INCREF(Py_None);
2633         Py_INCREF(Py_None);
2634         Py_INCREF(Py_None);
2635         return ret;
2636 }
2637 static PyObject *none_tuple_4()
2638 {
2639         PyObject *ret= PyTuple_New(4);
2640         PyTuple_SET_ITEM(ret, 0, Py_None);
2641         PyTuple_SET_ITEM(ret, 1, Py_None);
2642         PyTuple_SET_ITEM(ret, 2, Py_None);
2643         PyTuple_SET_ITEM(ret, 3, Py_None);
2644         
2645         Py_INCREF(Py_None);
2646         Py_INCREF(Py_None);
2647         Py_INCREF(Py_None);
2648         Py_INCREF(Py_None);
2649         return ret;
2650 }
2651
2652 KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
2653                                    "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"
2654                                    " If no hit, return (None,None,None) or (None,None,None,None).\n"
2655 " to   = 3-tuple or object reference for destination of ray (if object, use center of object)\n"
2656 " from = 3-tuple or object reference for origin of ray (if object, use center of object)\n"
2657 "        Can be None or omitted => start from self object center\n"
2658 " dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to to\n"
2659 " prop = property name that object must have; can be omitted => detect any object\n"
2660 " face = normal option: 1=>return face normal; 0 or omitted => normal is oriented towards origin\n"
2661 " xray = X-ray option: 1=>skip objects that don't match prop; 0 or omitted => stop on first object\n"
2662 " poly = polygon option: 1=>return value is a 4-tuple and the 4th element is a KX_PolyProxy object\n"
2663 "                           which can be None if hit object has no mesh or if there is no hit\n"
2664 "        If 0 or omitted, return value is a 3-tuple\n"
2665 "Note: The object on which you call this method matters: the ray will ignore it.\n"
2666 "      prop and xray option interact as follow:\n"
2667 "        prop off, xray off: return closest hit or no hit if there is no object on the full extend of the ray\n"
2668 "        prop off, xray on : idem\n"
2669 "        prop on,  xray off: return closest hit if it matches prop, no hit otherwise\n"
2670 "        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")
2671 {
2672         MT_Point3 toPoint;
2673         MT_Point3 fromPoint;
2674         PyObject* pyto;
2675         PyObject* pyfrom = NULL;
2676         float dist = 0.0f;
2677         char *propName = NULL;
2678         KX_GameObject *other;
2679         int face=0, xray=0, poly=0;
2680
2681         if (!PyArg_ParseTuple(args,"O|Ofsiii:rayCast", &pyto, &pyfrom, &dist, &propName, &face, &xray, &poly)) {
2682                 return NULL; // Python sets a simple error
2683         }
2684
2685         if (!PyVecTo(pyto, toPoint))
2686         {
2687                 PyErr_Clear();
2688                 
2689                 if (ConvertPythonToGameObject(pyto, &other, false, ""))  /* error will be overwritten */
2690                 {
2691                         toPoint = other->NodeGetWorldPosition();
2692                 } else
2693                 {
2694                         PyErr_SetString(PyExc_TypeError, "the first argument to rayCast must be a vector or a KX_GameObject");
2695                         return NULL;
2696                 }
2697         }
2698         if (!pyfrom || pyfrom == Py_None)
2699         {
2700                 fromPoint = NodeGetWorldPosition();
2701         }
2702         else if (!PyVecTo(pyfrom, fromPoint))
2703         {
2704                 PyErr_Clear();
2705                 
2706                 if (ConvertPythonToGameObject(pyfrom, &other, false, "")) /* error will be overwritten */
2707                 {
2708                         fromPoint = other->NodeGetWorldPosition();
2709                 } else
2710                 {
2711                         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");
2712                         return NULL;
2713                 }
2714         }
2715         
2716         if (dist != 0.0f) {
2717                 MT_Vector3 toDir = toPoint-fromPoint;
2718                 if (MT_fuzzyZero(toDir.length2())) {
2719                         //return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
2720                         return none_tuple_3();
2721                 }
2722                 toDir.normalize();
2723                 toPoint = fromPoint + (dist) * toDir;
2724         } else if (MT_fuzzyZero((toPoint-fromPoint).length2())) {
2725                 //return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
2726                 return none_tuple_3();
2727         }
2728         
2729         PHY_IPhysicsEnvironment* pe = GetPhysicsEnvironment();
2730         KX_IPhysicsController *spc = GetPhysicsController();
2731         KX_GameObject *parent = GetParent();
2732         if (!spc && parent)
2733                 spc = parent->GetPhysicsController();
2734         if (parent)
2735                 parent->Release();
2736         
2737         m_pHitObject = NULL;
2738         if (propName)
2739                 m_testPropName = propName;
2740         else
2741                 m_testPropName.SetLength(0);
2742         m_xray = xray;
2743         // to get the hit results
2744         KX_RayCast::Callback<KX_GameObject> callback(this,spc,NULL,face);
2745         KX_RayCast::RayTest(pe, fromPoint, toPoint, callback);
2746
2747         if (m_pHitObject)
2748         {
2749                 PyObject* returnValue = (poly) ? PyTuple_New(4) : PyTuple_New(3);
2750                 if (returnValue) { // unlikely this would ever fail, if it does python sets an error
2751                         PyTuple_SET_ITEM(returnValue, 0, m_pHitObject->GetProxy());
2752                         PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(callback.m_hitPoint));
2753                         PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(callback.m_hitNormal));
2754                         if (poly)
2755                         {
2756                                 if (callback.m_hitMesh)
2757                                 {
2758                                         // if this field is set, then we can trust that m_hitPolygon is a valid polygon
2759                                         RAS_Polygon* polygon = callback.m_hitMesh->GetPolygon(callback.m_hitPolygon);
2760                                         KX_PolyProxy* polyproxy = new KX_PolyProxy(callback.m_hitMesh, polygon);
2761                                         PyTuple_SET_ITEM(returnValue, 3, polyproxy->NewProxy(true));
2762                                 }
2763                                 else
2764                                 {
2765                                         Py_INCREF(Py_None);
2766                                         PyTuple_SET_ITEM(returnValue, 3, Py_None);
2767                                 }
2768                         }
2769                 }
2770                 return returnValue;
2771         }
2772         // no hit
2773         if (poly)
2774                 //return Py_BuildValue("OOOO", Py_None, Py_None, Py_None, Py_None);
2775                 return none_tuple_4();
2776         else
2777                 //return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
2778                 return none_tuple_3();
2779 }
2780
2781 KX_PYMETHODDEF_DOC_VARARGS(KX_GameObject, sendMessage, 
2782                                                    "sendMessage(subject, [body, to])\n"
2783 "sends a message in same manner as a message actuator"
2784 "subject = Subject of the message (string)"
2785 "body = Message body (string)"
2786 "to = Name of object to send the message to")
2787 {
2788         KX_Scene *scene = KX_GetActiveScene();
2789         char* subject;
2790         char* body = (char *)"";
2791         char* to = (char *)"";
2792         const STR_String& from = GetName();
2793
2794         if (!PyArg_ParseTuple(args, "s|sss:sendMessage", &subject, &body, &to))
2795                 return NULL;
2796         
2797         scene->GetNetworkScene()->SendMessage(to, from, subject, body);
2798         Py_RETURN_NONE;
2799 }
2800
2801 /* dict style access */
2802
2803
2804 /* Matches python dict.get(key, [default]) */
2805 PyObject* KX_GameObject::Pyget(PyObject *args)
2806 {
2807         PyObject *key;
2808         PyObject* def = Py_None;
2809         PyObject* ret;
2810
2811         if (!PyArg_ParseTuple(args, "O|O:get", &key, &def))
2812                 return NULL;
2813         
2814         
2815         if(PyString_Check(key)) {
2816                 CValue *item = GetProperty(PyString_AsString(key));
2817                 if (item) {
2818                         ret = item->ConvertValueToPython();
2819                         if(ret)
2820                                 return ret;
2821                         else
2822                                 return item->GetProxy();
2823                 }
2824         }
2825         
2826         if (m_attr_dict && (ret=PyDict_GetItem(m_attr_dict, key))) {
2827                 Py_INCREF(ret);
2828                 return ret;
2829         }
2830         
2831         Py_INCREF(def);
2832         return def;
2833 }
2834
2835 /* Matches python dict.has_key() */
2836 PyObject* KX_GameObject::Pyhas_key(PyObject* value)
2837 {
2838         // the ONLY error case is invalid data, this is checked by the macro'd static function
2839         // that calls this one. but make sure Seq_Contains doesnt add extra errors later on.
2840         return PyBool_FromLong(Seq_Contains((PyObject *)this, value));
2841 }
2842
2843 /* --------------------------------------------------------------------- 
2844  * Some stuff taken from the header
2845  * --------------------------------------------------------------------- */
2846 void KX_GameObject::Relink(GEN_Map<GEN_HashedPtr, void*> *map_parameter)        
2847 {
2848         // we will relink the sensors and actuators that use object references
2849         // if the object is part of the replicated hierarchy, use the new
2850         // object reference instead
2851         SCA_SensorList& sensorlist = GetSensors();
2852         SCA_SensorList::iterator sit;
2853         for (sit=sensorlist.begin(); sit != sensorlist.end(); sit++)
2854         {
2855                 (*sit)->Relink(map_parameter);
2856         }
2857         SCA_ActuatorList& actuatorlist = GetActuators();
2858         SCA_ActuatorList::iterator ait;
2859         for (ait=actuatorlist.begin(); ait != actuatorlist.end(); ait++)
2860         {
2861                 (*ait)->Relink(map_parameter);
2862         }
2863 }
2864
2865
2866 bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py_none_ok, const char *error_prefix)
2867 {
2868         if (value==NULL) {
2869                 PyErr_Format(PyExc_TypeError, "%s, python pointer NULL, should never happen", error_prefix);
2870                 *object = NULL;
2871                 return false;
2872         }
2873                 
2874         if (value==Py_None) {
2875                 *object = NULL;
2876                 
2877                 if (py_none_ok) {
2878                         return true;
2879                 } else {
2880                         PyErr_Format(PyExc_TypeError, "%s, expected KX_GameObject or a KX_GameObject name, None is invalid", error_prefix);
2881                         return false;
2882                 }
2883         }
2884         
2885         if (PyString_Check(value)) {
2886                 *object = (KX_GameObject*)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String( PyString_AsString(value) ));
2887                 
2888                 if (*object) {
2889                         return true;
2890                 } else {
2891                         PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_GameObject in this scene", error_prefix, PyString_AsString(value));
2892                         return false;
2893                 }
2894         }
2895         
2896         if (    PyObject_TypeCheck(value, &KX_GameObject::Type) ||
2897                         PyObject_TypeCheck(value, &KX_LightObject::Type)        ||
2898                         PyObject_TypeCheck(value, &KX_Camera::Type)     )
2899         {
2900                 *object = static_cast<KX_GameObject*>BGE_PROXY_REF(value);
2901                 
2902                 /* sets the error */
2903                 if (*object==NULL) {
2904                         PyErr_Format(PyExc_SystemError, "%s, " BGE_PROXY_ERROR_MSG, error_prefix);
2905                         return false;
2906                 }
2907                 
2908                 return true;
2909         }
2910         
2911         *object = NULL;
2912         
2913         if (py_none_ok) {
2914                 PyErr_Format(PyExc_TypeError, "%s, expect a KX_GameObject, a string or None", error_prefix);
2915         } else {
2916                 PyErr_Format(PyExc_TypeError, "%s, expect a KX_GameObject or a string", error_prefix);
2917         }
2918         
2919         return false;
2920 }