BGE: Added 'ghost' arg to KX_GameObject.suspendDynamics() method
[blender.git] / source / gameengine / Ketsji / KX_GameObject.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  * Game object wrapper
27  */
28
29 /** \file gameengine/Ketsji/KX_GameObject.cpp
30  *  \ingroup ketsji
31  */
32
33 #ifdef _MSC_VER
34   /* This warning tells us about truncation of __long__ stl-generated names.
35    * It can occasionally cause DevStudio to have internal compiler warnings. */
36 #  pragma warning( disable:4786 )
37 #endif
38
39 #include "RAS_IPolygonMaterial.h"
40 #include "KX_BlenderMaterial.h"
41 #include "KX_GameObject.h"
42 #include "KX_Camera.h" // only for their ::Type
43 #include "KX_Light.h"  // only for their ::Type
44 #include "KX_FontObject.h"  // only for their ::Type
45 #include "RAS_MeshObject.h"
46 #include "KX_NavMeshObject.h"
47 #include "KX_MeshProxy.h"
48 #include "KX_PolyProxy.h"
49 #include <stdio.h> // printf
50 #include <climits> // USHRT_MAX
51 #include "SG_Controller.h"
52 #include "PHY_IGraphicController.h"
53 #include "SG_Node.h"
54 #include "KX_ClientObjectInfo.h"
55 #include "RAS_BucketManager.h"
56 #include "KX_RayCast.h"
57 #include "KX_PythonInit.h"
58 #include "KX_PyMath.h"
59 #include "KX_PythonSeq.h"
60 #include "SCA_IActuator.h"
61 #include "SCA_ISensor.h"
62 #include "SCA_IController.h"
63 #include "NG_NetworkScene.h" //Needed for sendMessage()
64 #include "KX_ObstacleSimulation.h"
65 #include "KX_Scene.h"
66
67 #include "BKE_object.h"
68
69 #include "BL_ActionManager.h"
70 #include "BL_Action.h"
71
72 #include "KX_PythonCallBack.h"
73 #include "PyObjectPlus.h" /* python stuff */
74 #include "BLI_utildefines.h"
75 #include "python_utildefines.h"
76
77 // This file defines relationships between parents and children
78 // in the game engine.
79
80 #include "KX_SG_NodeRelationships.h"
81
82 #include "BLI_math.h"
83
84 static MT_Point3 dummy_point= MT_Point3(0.0, 0.0, 0.0);
85 static MT_Vector3 dummy_scaling = MT_Vector3(1.0, 1.0, 1.0);
86 static MT_Matrix3x3 dummy_orientation = MT_Matrix3x3(1.0, 0.0, 0.0,
87                                                      0.0, 1.0, 0.0,
88                                                      0.0, 0.0, 1.0);
89
90 KX_GameObject::KX_GameObject(
91         void* sgReplicationInfo,
92         SG_Callbacks callbacks)
93     : SCA_IObject(),
94       m_bDyna(false),
95       m_layer(0),
96       m_currentLodLevel(0),
97       m_previousLodLevel(0),
98       m_pBlenderObject(NULL),
99       m_pBlenderGroupObject(NULL),
100       m_bUseObjectColor(false),
101       m_bIsNegativeScaling(false),
102       m_objectColor(1.0, 1.0, 1.0, 1.0),
103       m_bVisible(true),
104       m_bCulled(true),
105       m_bOccluder(false),
106       m_pPhysicsController(NULL),
107       m_pGraphicController(NULL),
108       m_xray(false),
109       m_pHitObject(NULL),
110       m_pObstacleSimulation(NULL),
111       m_pInstanceObjects(NULL),
112       m_pDupliGroupObject(NULL),
113       m_actionManager(NULL),
114       m_bRecordAnimation(false),
115       m_isDeformable(false)
116
117 #ifdef WITH_PYTHON
118     , m_attr_dict(NULL),
119     m_collisionCallbacks(NULL)
120 #endif
121 {
122         m_ignore_activity_culling = false;
123         m_pClient_info = new KX_ClientObjectInfo(this, KX_ClientObjectInfo::ACTOR);
124         m_pSGNode = new SG_Node(this,sgReplicationInfo,callbacks);
125
126         // define the relationship between this node and it's parent.
127         
128         KX_NormalParentRelation * parent_relation = 
129                 KX_NormalParentRelation::New();
130         m_pSGNode->SetParentRelation(parent_relation);
131 };
132
133
134
135 KX_GameObject::~KX_GameObject()
136 {
137 #ifdef WITH_PYTHON
138         if (m_attr_dict) {
139                 PyDict_Clear(m_attr_dict); /* in case of circular refs or other weird cases */
140                 /* Py_CLEAR: Py_DECREF's and NULL's */
141                 Py_CLEAR(m_attr_dict);
142         }
143         // Unregister collision callbacks
144         // Do this before we start freeing physics information like m_pClient_info
145         if (m_collisionCallbacks){
146                 UnregisterCollisionCallbacks();
147                 Py_CLEAR(m_collisionCallbacks);
148         }
149 #endif // WITH_PYTHON
150
151         RemoveMeshes();
152
153         // is this delete somewhere ?
154         //if (m_sumoObj)
155         //      delete m_sumoObj;
156         delete m_pClient_info;
157         //if (m_pSGNode)
158         //      delete m_pSGNode;
159         if (m_pSGNode)
160         {
161                 // must go through controllers and make sure they will not use us anymore
162                 // This is important for KX_BulletPhysicsControllers that unregister themselves
163                 // from the object when they are deleted.
164                 SGControllerList::iterator contit;
165                 SGControllerList& controllers = m_pSGNode->GetSGControllerList();
166                 for (contit = controllers.begin();contit!=controllers.end();++contit)
167                 {
168                         (*contit)->ClearObject();
169                 }
170                 m_pSGNode->SetSGClientObject(NULL);
171
172                 /* m_pSGNode is freed in KX_Scene::RemoveNodeDestructObject */
173         }
174         if (m_pGraphicController)
175         {
176                 delete m_pGraphicController;
177         }
178
179         if (m_pPhysicsController)
180         {
181                 delete m_pPhysicsController;
182         }
183
184         if (m_pObstacleSimulation)
185         {
186                 m_pObstacleSimulation->DestroyObstacleForObj(this);
187         }
188
189         if (m_actionManager)
190         {
191                 delete m_actionManager;
192         }
193
194         if (m_pDupliGroupObject)
195         {
196                 m_pDupliGroupObject->Release();
197         }
198
199         if (m_pInstanceObjects)
200         {
201                 m_pInstanceObjects->Release();
202         }
203 }
204
205 KX_GameObject* KX_GameObject::GetClientObject(KX_ClientObjectInfo *info)
206 {
207         if (!info)
208                 return NULL;
209         return info->m_gameobject;
210 }
211
212 CValue* KX_GameObject:: Calc(VALUE_OPERATOR op, CValue *val) 
213 {
214         return NULL;
215 }
216
217
218
219 CValue* KX_GameObject::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val)
220 {
221         return NULL;
222 }
223
224
225
226 const STR_String & KX_GameObject::GetText()
227 {
228         return m_text;
229 }
230
231
232
233 double KX_GameObject::GetNumber()
234 {
235         return 0;
236 }
237
238
239
240 STR_String& KX_GameObject::GetName()
241 {
242         return m_name;
243 }
244
245
246 /* Set the name of the value */
247 void KX_GameObject::SetName(const char *name)
248 {
249         m_name = name;
250 }
251
252 PHY_IPhysicsController* KX_GameObject::GetPhysicsController()
253 {
254         return m_pPhysicsController;
255 }
256
257 KX_GameObject* KX_GameObject::GetDupliGroupObject()
258
259         return m_pDupliGroupObject;
260 }
261
262 CListValue* KX_GameObject::GetInstanceObjects()
263
264         return m_pInstanceObjects;
265 }
266
267 void KX_GameObject::AddInstanceObjects(KX_GameObject* obj)
268 {
269         if (!m_pInstanceObjects)
270                 m_pInstanceObjects = new CListValue();
271
272         obj->AddRef();
273         m_pInstanceObjects->Add(obj);
274 }
275
276 void KX_GameObject::RemoveInstanceObject(KX_GameObject* obj)
277 {
278         assert(m_pInstanceObjects);
279         m_pInstanceObjects->RemoveValue(obj);
280         obj->Release();
281 }
282
283 void KX_GameObject::RemoveDupliGroupObject()
284 {
285         if (m_pDupliGroupObject) {
286                 m_pDupliGroupObject->Release();
287                 m_pDupliGroupObject = NULL;
288         }
289 }
290
291 void KX_GameObject::SetDupliGroupObject(KX_GameObject* obj)
292 {
293         obj->AddRef();
294         m_pDupliGroupObject = obj;
295 }
296
297 void KX_GameObject::AddConstraint(bRigidBodyJointConstraint *cons)
298 {
299         m_constraints.push_back(cons);
300 }
301
302 std::vector<bRigidBodyJointConstraint*> KX_GameObject::GetConstraints()
303 {
304         return m_constraints;
305 }
306
307 void KX_GameObject::ClearConstraints()
308 {
309         m_constraints.clear();
310 }
311
312 KX_GameObject* KX_GameObject::GetParent()
313 {
314         KX_GameObject* result = NULL;
315         SG_Node* node = m_pSGNode;
316         
317         while (node && !result)
318         {
319                 node = node->GetSGParent();
320                 if (node)
321                         result = (KX_GameObject*)node->GetSGClientObject();
322         }
323
324         return result;
325         
326 }
327
328 void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj, bool addToCompound, bool ghost)
329 {
330         // check on valid node in case a python controller holds a reference to a deleted object
331         if (obj && 
332                 GetSGNode() &&                  // object is not zombi
333                 obj->GetSGNode() &&             // object is not zombi
334                 GetSGNode()->GetSGParent() != obj->GetSGNode() &&       // not already parented to same object
335                 !GetSGNode()->IsAncessor(obj->GetSGNode()) &&           // no parenting loop
336                 this != obj)                                                                            // not the object itself
337         {
338                 // Make sure the objects have some scale
339                 MT_Vector3 scale1 = NodeGetWorldScaling();
340                 MT_Vector3 scale2 = obj->NodeGetWorldScaling();
341                 if (fabs(scale2[0]) < (MT_Scalar)FLT_EPSILON ||
342                         fabs(scale2[1]) < (MT_Scalar)FLT_EPSILON ||
343                         fabs(scale2[2]) < (MT_Scalar)FLT_EPSILON ||
344                         fabs(scale1[0]) < (MT_Scalar)FLT_EPSILON ||
345                         fabs(scale1[1]) < (MT_Scalar)FLT_EPSILON ||
346                         fabs(scale1[2]) < (MT_Scalar)FLT_EPSILON) { return; }
347
348                 // Remove us from our old parent and set our new parent
349                 RemoveParent(scene);
350                 obj->GetSGNode()->AddChild(GetSGNode());
351
352                 if (m_pPhysicsController)
353                 {
354                         m_pPhysicsController->SuspendDynamics(ghost);
355                 }
356                 // Set us to our new scale, position, and orientation
357                 scale2[0] = 1.0/scale2[0];
358                 scale2[1] = 1.0/scale2[1];
359                 scale2[2] = 1.0/scale2[2];
360                 scale1 = scale1 * scale2;
361                 MT_Matrix3x3 invori = obj->NodeGetWorldOrientation().inverse();
362                 MT_Vector3 newpos = invori*(NodeGetWorldPosition()-obj->NodeGetWorldPosition())*scale2;
363
364                 NodeSetLocalScale(scale1);
365                 NodeSetLocalPosition(MT_Point3(newpos[0],newpos[1],newpos[2]));
366                 NodeSetLocalOrientation(invori*NodeGetWorldOrientation());
367                 NodeUpdateGS(0.f);
368                 // object will now be a child, it must be removed from the parent list
369                 CListValue* rootlist = scene->GetRootParentList();
370                 if (rootlist->RemoveValue(this))
371                         // the object was in parent list, decrement ref count as it's now removed
372                         Release();
373                 // if the new parent is a compound object, add this object shape to the compound shape.
374                 // step 0: verify this object has physical controller
375                 if (m_pPhysicsController && addToCompound)
376                 {
377                         // step 1: find the top parent (not necessarily obj)
378                         KX_GameObject* rootobj = (KX_GameObject*)obj->GetSGNode()->GetRootSGParent()->GetSGClientObject();
379                         // step 2: verify it has a physical controller and compound shape
380                         if (rootobj != NULL && 
381                                 rootobj->m_pPhysicsController != NULL &&
382                                 rootobj->m_pPhysicsController->IsCompound())
383                         {
384                                 rootobj->m_pPhysicsController->AddCompoundChild(m_pPhysicsController);
385                         }
386                 }
387                 // graphically, the object hasn't change place, no need to update m_pGraphicController
388         }
389 }
390
391 void KX_GameObject::RemoveParent(KX_Scene *scene)
392 {
393         // check on valid node in case a python controller holds a reference to a deleted object
394         if (GetSGNode() && GetSGNode()->GetSGParent())
395         {
396                 // get the root object to remove us from compound object if needed
397                 KX_GameObject* rootobj = (KX_GameObject*)GetSGNode()->GetRootSGParent()->GetSGClientObject();
398                 // Set us to the right spot 
399                 GetSGNode()->SetLocalScale(GetSGNode()->GetWorldScaling());
400                 GetSGNode()->SetLocalOrientation(GetSGNode()->GetWorldOrientation());
401                 GetSGNode()->SetLocalPosition(GetSGNode()->GetWorldPosition());
402
403                 // Remove us from our parent
404                 GetSGNode()->DisconnectFromParent();
405                 NodeUpdateGS(0.f);
406                 // the object is now a root object, add it to the parentlist
407                 CListValue* rootlist = scene->GetRootParentList();
408                 if (!rootlist->SearchValue(this))
409                         // object was not in root list, add it now and increment ref count
410                         rootlist->Add(AddRef());
411                 if (m_pPhysicsController)
412                 {
413                         // in case this controller was added as a child shape to the parent
414                         if (rootobj != NULL && 
415                                 rootobj->m_pPhysicsController != NULL &&
416                                 rootobj->m_pPhysicsController->IsCompound())
417                         {
418                                 rootobj->m_pPhysicsController->RemoveCompoundChild(m_pPhysicsController);
419                         }
420                         m_pPhysicsController->RestoreDynamics();
421                         if (m_pPhysicsController->IsDynamic() && (rootobj != NULL && rootobj->m_pPhysicsController))
422                         {
423                                 // dynamic object should remember the velocity they had while being parented
424                                 MT_Point3 childPoint = GetSGNode()->GetWorldPosition();
425                                 MT_Point3 rootPoint = rootobj->GetSGNode()->GetWorldPosition();
426                                 MT_Point3 relPoint;
427                                 relPoint = (childPoint-rootPoint);
428                                 MT_Vector3 linVel = rootobj->m_pPhysicsController->GetVelocity(relPoint);
429                                 MT_Vector3 angVel = rootobj->m_pPhysicsController->GetAngularVelocity();
430                                 m_pPhysicsController->SetLinearVelocity(linVel, false);
431                                 m_pPhysicsController->SetAngularVelocity(angVel, false);
432                         }
433                 }
434                 // graphically, the object hasn't change place, no need to update m_pGraphicController
435         }
436 }
437
438 BL_ActionManager* KX_GameObject::GetActionManager()
439 {
440         // We only want to create an action manager if we need it
441         if (!m_actionManager)
442         {
443                 GetScene()->AddAnimatedObject(this);
444                 m_actionManager = new BL_ActionManager(this);
445         }
446         return m_actionManager;
447 }
448
449 bool KX_GameObject::PlayAction(const char* name,
450                                                                 float start,
451                                                                 float end,
452                                                                 short layer,
453                                                                 short priority,
454                                                                 float blendin,
455                                                                 short play_mode,
456                                                                 float layer_weight,
457                                                                 short ipo_flags,
458                                                                 float playback_speed,
459                                                                 short blend_mode)
460 {
461         return GetActionManager()->PlayAction(name, start, end, layer, priority, blendin, play_mode, layer_weight, ipo_flags, playback_speed, blend_mode);
462 }
463
464 void KX_GameObject::StopAction(short layer)
465 {
466         GetActionManager()->StopAction(layer);
467 }
468
469 bool KX_GameObject::IsActionDone(short layer)
470 {
471         return GetActionManager()->IsActionDone(layer);
472 }
473
474 void KX_GameObject::UpdateActionManager(float curtime)
475 {
476         GetActionManager()->Update(curtime);
477 }
478
479 void KX_GameObject::UpdateActionIPOs()
480 {
481         GetActionManager()->UpdateIPOs();
482 }
483
484 float KX_GameObject::GetActionFrame(short layer)
485 {
486         return GetActionManager()->GetActionFrame(layer);
487 }
488
489 void KX_GameObject::SetActionFrame(short layer, float frame)
490 {
491         GetActionManager()->SetActionFrame(layer, frame);
492 }
493
494 bAction *KX_GameObject::GetCurrentAction(short layer)
495 {
496         return GetActionManager()->GetCurrentAction(layer);
497 }
498
499 void KX_GameObject::SetPlayMode(short layer, short mode)
500 {
501         GetActionManager()->SetPlayMode(layer, mode);
502 }
503
504 void KX_GameObject::SetTimes(short layer, float start, float end)
505 {
506         GetActionManager()->SetTimes(layer, start, end);
507 }
508
509 void KX_GameObject::ProcessReplica()
510 {
511         SCA_IObject::ProcessReplica();
512
513         m_pGraphicController = NULL;
514         m_pPhysicsController = NULL;
515         m_pSGNode = NULL;
516         m_pClient_info = new KX_ClientObjectInfo(*m_pClient_info);
517         m_pClient_info->m_gameobject = this;
518         m_actionManager = NULL;
519         m_state = 0;
520
521         KX_Scene* scene = KX_GetActiveScene();
522         KX_ObstacleSimulation* obssimulation = scene->GetObstacleSimulation();
523         struct Object* blenderobject = GetBlenderObject();
524         if (obssimulation && (blenderobject->gameflag & OB_HASOBSTACLE))
525         {
526                 obssimulation->AddObstacleForObj(this);
527         }
528
529 #ifdef WITH_PYTHON
530         if (m_attr_dict)
531                 m_attr_dict= PyDict_Copy(m_attr_dict);
532 #endif
533                 
534 }
535
536 static void setGraphicController_recursive(SG_Node* node)
537 {
538         NodeList& children = node->GetSGChildren();
539
540         for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
541         {
542                 SG_Node* childnode = (*childit);
543                 KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject());
544                 if (clientgameobj != NULL) // This is a GameObject
545                         clientgameobj->ActivateGraphicController(false);
546                 
547                 // if the childobj is NULL then this may be an inverse parent link
548                 // so a non recursive search should still look down this node.
549                 setGraphicController_recursive(childnode);
550         }
551 }
552
553
554 void KX_GameObject::ActivateGraphicController(bool recurse)
555 {
556         if (m_pGraphicController)
557         {
558                 m_pGraphicController->Activate(m_bVisible);
559         }
560         if (recurse)
561         {
562                 setGraphicController_recursive(GetSGNode());
563         }
564 }
565
566 void KX_GameObject::SetUserCollisionGroup(unsigned short group)
567 {
568         m_userCollisionGroup = group;
569         if (m_pPhysicsController)
570                 m_pPhysicsController->RefreshCollisions();
571 }
572 void KX_GameObject::SetUserCollisionMask(unsigned short mask)
573 {
574         m_userCollisionMask = mask;
575         if (m_pPhysicsController)
576                 m_pPhysicsController->RefreshCollisions();
577 }
578
579 unsigned short KX_GameObject::GetUserCollisionGroup()
580 {
581         return m_userCollisionGroup;
582 }
583 unsigned short KX_GameObject::GetUserCollisionMask()
584 {
585         return m_userCollisionMask;
586 }
587
588 bool KX_GameObject::CheckCollision(KX_GameObject* other)
589 {
590         return this->m_userCollisionGroup & other->m_userCollisionMask;
591 }
592
593 CValue* KX_GameObject::GetReplica()
594 {
595         KX_GameObject* replica = new KX_GameObject(*this);
596
597         // this will copy properties and so on...
598         replica->ProcessReplica();
599
600         return replica;
601 }
602
603 bool KX_GameObject::IsDynamicsSuspended() const
604 {
605         if (m_pPhysicsController)
606                 return m_pPhysicsController->IsSuspended();
607         return false;
608 }
609
610 float KX_GameObject::getLinearDamping() const
611 {
612         if (m_pPhysicsController)
613                 return m_pPhysicsController->GetLinearDamping();
614         return 0;
615 }
616
617 float KX_GameObject::getAngularDamping() const
618 {
619         if (m_pPhysicsController)
620                 return m_pPhysicsController->GetAngularDamping();
621         return 0;
622 }
623
624 void KX_GameObject::setLinearDamping(float damping)
625 {
626         if (m_pPhysicsController)
627                 m_pPhysicsController->SetLinearDamping(damping);
628 }
629
630
631 void KX_GameObject::setAngularDamping(float damping)
632 {
633         if (m_pPhysicsController)
634                 m_pPhysicsController->SetAngularDamping(damping);
635 }
636
637
638 void KX_GameObject::setDamping(float linear, float angular)
639 {
640         if (m_pPhysicsController)
641                 m_pPhysicsController->SetDamping(linear, angular);
642 }
643
644
645 void KX_GameObject::ApplyForce(const MT_Vector3& force,bool local)
646 {
647         if (m_pPhysicsController)
648                 m_pPhysicsController->ApplyForce(force,local);
649 }
650
651
652
653 void KX_GameObject::ApplyTorque(const MT_Vector3& torque,bool local)
654 {
655         if (m_pPhysicsController)
656                 m_pPhysicsController->ApplyTorque(torque,local);
657 }
658
659
660
661 void KX_GameObject::ApplyMovement(const MT_Vector3& dloc,bool local)
662 {
663         if (GetSGNode()) 
664         {
665                 if (m_pPhysicsController) // (IsDynamic())
666                 {
667                         m_pPhysicsController->RelativeTranslate(dloc,local);
668                 }
669                 GetSGNode()->RelativeTranslate(dloc,GetSGNode()->GetSGParent(),local);
670         }
671 }
672
673
674
675 void KX_GameObject::ApplyRotation(const MT_Vector3& drot,bool local)
676 {
677         MT_Matrix3x3 rotmat(drot);
678         
679         if (GetSGNode()) {
680                 GetSGNode()->RelativeRotate(rotmat,local);
681
682                 if (m_pPhysicsController) { // (IsDynamic())
683                         m_pPhysicsController->RelativeRotate(rotmat,local);
684                 }
685         }
686 }
687
688
689
690 /**
691  * GetOpenGL Matrix, returns an OpenGL 'compatible' matrix
692  */
693 double* KX_GameObject::GetOpenGLMatrix()
694 {
695         // todo: optimize and only update if necessary
696         double* fl = m_OpenGL_4x4Matrix.getPointer();
697         if (GetSGNode()) {
698                 MT_Transform trans;
699         
700                 trans.setOrigin(GetSGNode()->GetWorldPosition());
701                 trans.setBasis(GetSGNode()->GetWorldOrientation());
702         
703                 MT_Vector3 scaling = GetSGNode()->GetWorldScaling();
704                 m_bIsNegativeScaling = ((scaling[0] < 0.0) ^ (scaling[1] < 0.0) ^ (scaling[2] < 0.0)) ? true : false;
705                 trans.scale(scaling[0], scaling[1], scaling[2]);
706                 trans.getValue(fl);
707                 GetSGNode()->ClearDirty();
708         }
709         return fl;
710 }
711
712 void KX_GameObject::UpdateBlenderObjectMatrix(Object* blendobj)
713 {
714         if (!blendobj)
715                 blendobj = m_pBlenderObject;
716         if (blendobj) {
717                 const MT_Matrix3x3& rot = NodeGetWorldOrientation();
718                 const MT_Vector3& scale = NodeGetWorldScaling();
719                 const MT_Vector3& pos = NodeGetWorldPosition();
720                 rot.getValue(blendobj->obmat[0]);
721                 pos.getValue(blendobj->obmat[3]);
722                 mul_v3_fl(blendobj->obmat[0], scale[0]);
723                 mul_v3_fl(blendobj->obmat[1], scale[1]);
724                 mul_v3_fl(blendobj->obmat[2], scale[2]);
725         }
726 }
727
728 void KX_GameObject::AddMeshUser()
729 {
730         for (size_t i=0;i<m_meshes.size();i++)
731         {
732                 m_meshes[i]->AddMeshUser(this, &m_meshSlots, GetDeformer());
733         }
734         // set the part of the mesh slot that never change
735         double* fl = GetOpenGLMatrixPtr()->getPointer();
736
737         SG_QList::iterator<RAS_MeshSlot> mit(m_meshSlots);
738 //      RAS_MeshSlot* ms;
739         for (mit.begin(); !mit.end(); ++mit)
740         {
741                 (*mit)->m_OpenGLMatrix = fl;
742         }
743         UpdateBuckets(false);
744 }
745
746 static void UpdateBuckets_recursive(SG_Node* node)
747 {
748         NodeList& children = node->GetSGChildren();
749
750         for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
751         {
752                 SG_Node* childnode = (*childit);
753                 KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject());
754                 if (clientgameobj != NULL) // This is a GameObject
755                         clientgameobj->UpdateBuckets(0);
756                 
757                 // if the childobj is NULL then this may be an inverse parent link
758                 // so a non recursive search should still look down this node.
759                 UpdateBuckets_recursive(childnode);
760         }
761 }
762
763 void KX_GameObject::UpdateBuckets( bool recursive )
764 {
765         if (GetSGNode()) {
766                 RAS_MeshSlot *ms;
767
768                 if (GetSGNode()->IsDirty())
769                         GetOpenGLMatrix();
770
771                 SG_QList::iterator<RAS_MeshSlot> mit(m_meshSlots);
772                 for (mit.begin(); !mit.end(); ++mit)
773                 {
774                         ms = *mit;
775                         ms->m_bObjectColor = m_bUseObjectColor;
776                         ms->m_RGBAcolor = m_objectColor;
777                         ms->m_bVisible = m_bVisible;
778                         ms->m_bCulled = m_bCulled || !m_bVisible;
779                         if (!ms->m_bCulled) 
780                                 ms->m_bucket->ActivateMesh(ms);
781                         
782                         /* split if necessary */
783 #ifdef USE_SPLIT
784                         ms->Split();
785 #endif
786                 }
787         
788                 if (recursive) {
789                         UpdateBuckets_recursive(GetSGNode());
790                 }
791         }
792 }
793
794 void KX_GameObject::RemoveMeshes()
795 {
796         for (size_t i=0;i<m_meshes.size();i++)
797                 m_meshes[i]->RemoveFromBuckets(this);
798
799         //note: meshes can be shared, and are deleted by KX_BlenderSceneConverter
800
801         m_meshes.clear();
802 }
803
804 void KX_GameObject::AddLodMesh(RAS_MeshObject* mesh)
805 {
806         m_lodmeshes.push_back(mesh);
807 }
808
809 void KX_GameObject::UpdateLod(MT_Vector3 &cam_pos)
810 {
811         // Handle dupligroups
812         if (this->m_pInstanceObjects) {
813                 KX_GameObject * instob;
814                 int count = this->m_pInstanceObjects->GetCount();
815                 for (int i = 0; i < count; i++) {
816                         instob = (KX_GameObject*)this->m_pInstanceObjects->GetValue(i);
817                         instob->UpdateLod(cam_pos);
818                 }
819         }
820
821         if (this->m_lodmeshes.empty()) return;
822
823         MT_Vector3 delta = this->NodeGetWorldPosition() - cam_pos;
824         float distance2 = delta.length2();
825
826         int level = 0;
827         Object *bob = this->GetBlenderObject();
828         LodLevel *lod = (LodLevel*) bob->lodlevels.first;
829         KX_Scene *kxscene = this->GetScene();
830
831         for (; lod; lod = lod->next, level++) {
832                 if (!lod->source || lod->source->type != OB_MESH) level--;
833                 if (!lod->next) break;
834                 if (level == (this->m_previousLodLevel) || (level == (this->m_previousLodLevel + 1))) {
835                         short hysteresis = 0;
836                         if (kxscene->IsActivedLodHysteresis()) {
837                                 // if exists, LoD level hysteresis will override scene hysteresis
838                                 if (lod->next->flags & OB_LOD_USE_HYST) {
839                                         hysteresis = lod->next->obhysteresis;
840                                 }
841                                 else {
842                                         hysteresis = kxscene->GetLodHysteresisValue();
843                                 }
844                         }
845                         float hystvariance = MT_abs(lod->next->distance - lod->distance) * hysteresis / 100;
846                         if ((lod->next->distance + hystvariance) * (lod->next->distance + hystvariance) > distance2)
847                                 break;
848                 }
849                 else if (level == (this->m_previousLodLevel - 1)) {
850                         short hysteresis = 0;
851                         if (kxscene->IsActivedLodHysteresis()) {
852                                 // if exists, LoD level hysteresis will override scene hysteresis
853                                 if (lod->next->flags & OB_LOD_USE_HYST) {
854                                         hysteresis = lod->next->obhysteresis;
855                                 }
856                                 else {
857                                         hysteresis = kxscene->GetLodHysteresisValue();
858                                 }
859                         }
860                         float hystvariance = MT_abs(lod->next->distance - lod->distance) * hysteresis / 100;
861                         if ((lod->next->distance - hystvariance) * (lod->next->distance - hystvariance) > distance2)
862                                 break;
863                 }
864         }
865
866         RAS_MeshObject *mesh = this->m_lodmeshes[level];
867         this->m_currentLodLevel = level;
868         if (mesh != this->m_meshes[0]) {
869                 this->m_previousLodLevel = level;
870                 this->GetScene()->ReplaceMesh(this, mesh, true, false);
871         }
872 }
873
874 void KX_GameObject::UpdateTransform()
875 {
876         // HACK: saves function call for dynamic object, they are handled differently
877         if (m_pPhysicsController && !m_pPhysicsController->IsDynamic())
878                 m_pPhysicsController->SetTransform();
879         if (m_pGraphicController)
880                 // update the culling tree
881                 m_pGraphicController->SetGraphicTransform();
882
883 }
884
885 void KX_GameObject::UpdateTransformFunc(SG_IObject* node, void* gameobj, void* scene)
886 {
887         ((KX_GameObject*)gameobj)->UpdateTransform();
888 }
889
890 void KX_GameObject::SynchronizeTransform()
891 {
892         // only used for sensor object, do full synchronization as bullet doesn't do it
893         if (m_pPhysicsController)
894                 m_pPhysicsController->SetTransform();
895         if (m_pGraphicController)
896                 m_pGraphicController->SetGraphicTransform();
897 }
898
899 void KX_GameObject::SynchronizeTransformFunc(SG_IObject* node, void* gameobj, void* scene)
900 {
901         ((KX_GameObject*)gameobj)->SynchronizeTransform();
902 }
903
904
905 void KX_GameObject::SetDebugColor(unsigned int bgra)
906 {
907         for (size_t i=0;i<m_meshes.size();i++)
908                 m_meshes[i]->DebugColor(bgra);
909 }
910
911
912
913 void KX_GameObject::ResetDebugColor()
914 {
915         SetDebugColor(0xff000000);
916 }
917
918 void KX_GameObject::InitIPO(bool ipo_as_force,
919                             bool ipo_add,
920                             bool ipo_local)
921 {
922         SGControllerList::iterator it = GetSGNode()->GetSGControllerList().begin();
923
924         while (it != GetSGNode()->GetSGControllerList().end()) {
925                 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_RESET, true);
926                 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_AS_FORCE, ipo_as_force);
927                 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_ADD, ipo_add);
928                 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_LOCAL, ipo_local);
929                 it++;
930         }
931
932
933 void KX_GameObject::UpdateIPO(float curframetime,
934                                                           bool recurse) 
935 {
936         // just the 'normal' update procedure.
937         GetSGNode()->SetSimulatedTime(curframetime,recurse);
938         GetSGNode()->UpdateWorldData(curframetime);
939         UpdateTransform();
940 }
941
942 // IPO update
943 void 
944 KX_GameObject::UpdateMaterialData(
945                 dword matname_hash,
946                 MT_Vector4 rgba,
947                 MT_Vector3 specrgb,
948                 MT_Scalar hard,
949                 MT_Scalar spec,
950                 MT_Scalar ref,
951                 MT_Scalar emit,
952                 MT_Scalar alpha
953
954         )
955 {
956         int mesh = 0;
957         if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0) {
958                 list<RAS_MeshMaterial>::iterator mit = m_meshes[mesh]->GetFirstMaterial();
959
960                 for (; mit != m_meshes[mesh]->GetLastMaterial(); ++mit)
961                 {
962                         RAS_IPolyMaterial* poly = mit->m_bucket->GetPolyMaterial();
963
964                         if (poly->GetFlag() & RAS_BLENDERMAT )
965                         {
966                                 KX_BlenderMaterial *m =  static_cast<KX_BlenderMaterial*>(poly);
967                                 
968                                 if (matname_hash == 0)
969                                 {
970                                         m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha);
971                                         // if mesh has only one material attached to it then use original hack with no need to edit vertices (better performance)
972                                         SetObjectColor(rgba);
973                                 }
974                                 else
975                                 {
976                                         if (matname_hash == poly->GetMaterialNameHash())
977                                         {
978                                                 m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha);
979                                                 m_meshes[mesh]->SetVertexColor(poly,rgba);
980                                                 
981                                                 // no break here, because one blender material can be split into several game engine materials
982                                                 // (e.g. one uvsphere material is split into one material at poles with ras_mode TRIANGLE and one material for the body
983                                                 // if here was a break then would miss some vertices if material was split
984                                         }
985                                 }
986                         }
987                 }
988         }
989 }
990 bool
991 KX_GameObject::GetVisible(
992         void
993         )
994 {
995         return m_bVisible;
996 }
997
998 static void setVisible_recursive(SG_Node* node, bool v)
999 {
1000         NodeList& children = node->GetSGChildren();
1001
1002         for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
1003         {
1004                 SG_Node* childnode = (*childit);
1005                 KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject());
1006                 if (clientgameobj != NULL) // This is a GameObject
1007                         clientgameobj->SetVisible(v, 0);
1008                 
1009                 // if the childobj is NULL then this may be an inverse parent link
1010                 // so a non recursive search should still look down this node.
1011                 setVisible_recursive(childnode, v);
1012         }
1013 }
1014
1015
1016 void
1017 KX_GameObject::SetVisible(
1018         bool v,
1019         bool recursive
1020         )
1021 {
1022         if (GetSGNode()) {
1023                 m_bVisible = v;
1024                 if (m_pGraphicController)
1025                         m_pGraphicController->Activate(m_bVisible);
1026                 if (recursive)
1027                         setVisible_recursive(GetSGNode(), v);
1028         }
1029 }
1030
1031 static void setOccluder_recursive(SG_Node* node, bool v)
1032 {
1033         NodeList& children = node->GetSGChildren();
1034
1035         for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
1036         {
1037                 SG_Node* childnode = (*childit);
1038                 KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject());
1039                 if (clientgameobj != NULL) // This is a GameObject
1040                         clientgameobj->SetOccluder(v, false);
1041                 
1042                 // if the childobj is NULL then this may be an inverse parent link
1043                 // so a non recursive search should still look down this node.
1044                 setOccluder_recursive(childnode, v);
1045         }
1046 }
1047
1048 void
1049 KX_GameObject::SetOccluder(
1050         bool v,
1051         bool recursive
1052         )
1053 {
1054         if (GetSGNode()) {
1055                 m_bOccluder = v;
1056                 if (recursive)
1057                         setOccluder_recursive(GetSGNode(), v);
1058         }
1059 }
1060
1061 static void setDebug_recursive(SG_Node *node, bool debug)
1062 {
1063         NodeList& children = node->GetSGChildren();
1064         KX_Scene *scene = KX_GetActiveScene();
1065
1066         for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit) {
1067                 SG_Node *childnode = (*childit);
1068                 KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject());
1069                 if (clientgameobj != NULL) {
1070                         if (debug) {
1071                                 if (!scene->ObjectInDebugList(clientgameobj))
1072                                         scene->AddObjectDebugProperties(clientgameobj);
1073                         }
1074                         else
1075                                 scene->RemoveObjectDebugProperties(clientgameobj);
1076                 }
1077
1078                 /* if the childobj is NULL then this may be an inverse parent link
1079                  * so a non recursive search should still look down this node. */
1080                 setDebug_recursive(childnode, debug);
1081         }
1082 }
1083
1084 void KX_GameObject::SetUseDebugProperties( bool debug, bool recursive )
1085 {
1086         KX_Scene *scene = KX_GetActiveScene();
1087
1088         if (debug) {
1089                 if (!scene->ObjectInDebugList(this))
1090                         scene->AddObjectDebugProperties(this);
1091         }
1092         else
1093                 scene->RemoveObjectDebugProperties(this);
1094
1095         if (recursive)
1096                 setDebug_recursive(GetSGNode(), debug);
1097 }
1098
1099 void
1100 KX_GameObject::SetLayer(
1101         int l
1102         )
1103 {
1104         m_layer = l;
1105 }
1106
1107 int
1108 KX_GameObject::GetLayer(
1109         void
1110         )
1111 {
1112         return m_layer;
1113 }
1114
1115 void KX_GameObject::addLinearVelocity(const MT_Vector3& lin_vel,bool local)
1116 {
1117         if (m_pPhysicsController)
1118         {
1119                 MT_Vector3 lv = local ? NodeGetWorldOrientation() * lin_vel : lin_vel;
1120                 m_pPhysicsController->SetLinearVelocity(lv + m_pPhysicsController->GetLinearVelocity(), 0);
1121         }
1122 }
1123
1124
1125
1126 void KX_GameObject::setLinearVelocity(const MT_Vector3& lin_vel,bool local)
1127 {
1128         if (m_pPhysicsController)
1129                 m_pPhysicsController->SetLinearVelocity(lin_vel,local);
1130 }
1131
1132
1133
1134 void KX_GameObject::setAngularVelocity(const MT_Vector3& ang_vel,bool local)
1135 {
1136         if (m_pPhysicsController)
1137                 m_pPhysicsController->SetAngularVelocity(ang_vel,local);
1138 }
1139
1140
1141 void KX_GameObject::ResolveCombinedVelocities(
1142         const MT_Vector3 & lin_vel,
1143         const MT_Vector3 & ang_vel,
1144         bool lin_vel_local,
1145         bool ang_vel_local
1146 ) {
1147         if (m_pPhysicsController)
1148         {
1149
1150                 MT_Vector3 lv = lin_vel_local ? NodeGetWorldOrientation() * lin_vel : lin_vel;
1151                 MT_Vector3 av = ang_vel_local ? NodeGetWorldOrientation() * ang_vel : ang_vel;
1152                 m_pPhysicsController->ResolveCombinedVelocities(
1153                         lv.x(),lv.y(),lv.z(),av.x(),av.y(),av.z());
1154         }
1155 }
1156
1157
1158 void KX_GameObject::SetObjectColor(const MT_Vector4& rgbavec)
1159 {
1160         m_bUseObjectColor = true;
1161         m_objectColor = rgbavec;
1162 }
1163
1164 const MT_Vector4& KX_GameObject::GetObjectColor()
1165 {
1166         return m_objectColor;
1167 }
1168
1169 void KX_GameObject::AlignAxisToVect(const MT_Vector3& dir, int axis, float fac)
1170 {
1171         MT_Matrix3x3 orimat;
1172         MT_Vector3 vect,ori,z,x,y;
1173         MT_Scalar len;
1174
1175         // check on valid node in case a python controller holds a reference to a deleted object
1176         if (!GetSGNode())
1177                 return;
1178
1179         vect = dir;
1180         len = vect.length();
1181         if (MT_fuzzyZero(len))
1182         {
1183                 cout << "alignAxisToVect() Error: Null vector!\n";
1184                 return;
1185         }
1186         
1187         if (fac <= 0.0f) {
1188                 return;
1189         }
1190         
1191         // normalize
1192         vect /= len;
1193         orimat = GetSGNode()->GetWorldOrientation();
1194         switch (axis)
1195         {
1196                 case 0: //x axis
1197                         ori.setValue(orimat[0][2], orimat[1][2], orimat[2][2]); //pivot axis
1198                         if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON) //is the vector parallel to the pivot?
1199                                 ori.setValue(orimat[0][1], orimat[1][1], orimat[2][1]); //change the pivot!
1200                         if (fac == 1.0f) {
1201                                 x = vect;
1202                         } else {
1203                                 x = (vect * fac) + ((orimat * MT_Vector3(1.0, 0.0, 0.0)) * (1.0f - fac));
1204                                 len = x.length();
1205                                 if (MT_fuzzyZero(len)) x = vect;
1206                                 else x /= len;
1207                         }
1208                         y = ori.cross(x);
1209                         z = x.cross(y);
1210                         break;
1211                 case 1: //y axis
1212                         ori.setValue(orimat[0][0], orimat[1][0], orimat[2][0]);
1213                         if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON)
1214                                 ori.setValue(orimat[0][2], orimat[1][2], orimat[2][2]);
1215                         if (fac == 1.0f) {
1216                                 y = vect;
1217                         } else {
1218                                 y = (vect * fac) + ((orimat * MT_Vector3(0.0, 1.0, 0.0)) * (1.0f - fac));
1219                                 len = y.length();
1220                                 if (MT_fuzzyZero(len)) y = vect;
1221                                 else y /= len;
1222                         }
1223                         z = ori.cross(y);
1224                         x = y.cross(z);
1225                         break;
1226                 case 2: //z axis
1227                         ori.setValue(orimat[0][1], orimat[1][1], orimat[2][1]);
1228                         if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON)
1229                                 ori.setValue(orimat[0][0], orimat[1][0], orimat[2][0]);
1230                         if (fac == 1.0f) {
1231                                 z = vect;
1232                         } else {
1233                                 z = (vect * fac) + ((orimat * MT_Vector3(0.0, 0.0, 1.0)) * (1.0f - fac));
1234                                 len = z.length();
1235                                 if (MT_fuzzyZero(len)) z = vect;
1236                                 else z /= len;
1237                         }
1238                         x = ori.cross(z);
1239                         y = z.cross(x);
1240                         break;
1241                 default: //wrong input?
1242                         cout << "alignAxisToVect(): Wrong axis '" << axis <<"'\n";
1243                         return;
1244         }
1245         x.normalize(); //normalize the vectors
1246         y.normalize();
1247         z.normalize();
1248         orimat.setValue(        x[0],y[0],z[0],
1249                                                 x[1],y[1],z[1],
1250                                                 x[2],y[2],z[2]);
1251         if (GetSGNode()->GetSGParent() != NULL)
1252         {
1253                 // the object is a child, adapt its local orientation so that 
1254                 // the global orientation is aligned as we want.
1255                 MT_Matrix3x3 invori = GetSGNode()->GetSGParent()->GetWorldOrientation().inverse();
1256                 NodeSetLocalOrientation(invori*orimat);
1257         }
1258         else
1259                 NodeSetLocalOrientation(orimat);
1260 }
1261
1262 MT_Scalar KX_GameObject::GetMass()
1263 {
1264         if (m_pPhysicsController)
1265         {
1266                 return m_pPhysicsController->GetMass();
1267         }
1268         return 0.0;
1269 }
1270
1271 MT_Vector3 KX_GameObject::GetLocalInertia()
1272 {
1273         MT_Vector3 local_inertia(0.0,0.0,0.0);
1274         if (m_pPhysicsController)
1275         {
1276                 local_inertia = m_pPhysicsController->GetLocalInertia();
1277         }
1278         return local_inertia;
1279 }
1280
1281 MT_Vector3 KX_GameObject::GetLinearVelocity(bool local)
1282 {
1283         MT_Vector3 velocity(0.0,0.0,0.0), locvel;
1284         MT_Matrix3x3 ori;
1285         if (m_pPhysicsController)
1286         {
1287                 velocity = m_pPhysicsController->GetLinearVelocity();
1288                 
1289                 if (local)
1290                 {
1291                         ori = GetSGNode()->GetWorldOrientation();
1292                         
1293                         locvel = velocity * ori;
1294                         return locvel;
1295                 }
1296         }
1297         return velocity;
1298 }
1299
1300 MT_Vector3 KX_GameObject::GetAngularVelocity(bool local)
1301 {
1302         MT_Vector3 velocity(0.0,0.0,0.0), locvel;
1303         MT_Matrix3x3 ori;
1304         if (m_pPhysicsController)
1305         {
1306                 velocity = m_pPhysicsController->GetAngularVelocity();
1307                 
1308                 if (local)
1309                 {
1310                         ori = GetSGNode()->GetWorldOrientation();
1311                         
1312                         locvel = velocity * ori;
1313                         return locvel;
1314                 }
1315         }
1316         return velocity;
1317 }
1318
1319 MT_Vector3 KX_GameObject::GetVelocity(const MT_Point3& point)
1320 {
1321         if (m_pPhysicsController)
1322         {
1323                 return m_pPhysicsController->GetVelocity(point);
1324         }
1325         return MT_Vector3(0.0,0.0,0.0);
1326 }
1327
1328 // scenegraph node stuff
1329
1330 void KX_GameObject::NodeSetLocalPosition(const MT_Point3& trans)
1331 {
1332         // check on valid node in case a python controller holds a reference to a deleted object
1333         if (!GetSGNode())
1334                 return;
1335
1336         if (m_pPhysicsController && !GetSGNode()->GetSGParent())
1337         {
1338                 // don't update physic controller if the object is a child:
1339                 // 1) the transformation will not be right
1340                 // 2) in this case, the physic controller is necessarily a static object
1341                 //    that is updated from the normal kinematic synchronization
1342                 m_pPhysicsController->SetPosition(trans);
1343         }
1344
1345         GetSGNode()->SetLocalPosition(trans);
1346
1347 }
1348
1349
1350
1351 void KX_GameObject::NodeSetLocalOrientation(const MT_Matrix3x3& rot)
1352 {
1353         // check on valid node in case a python controller holds a reference to a deleted object
1354         if (!GetSGNode())
1355                 return;
1356
1357         if (m_pPhysicsController && !GetSGNode()->GetSGParent())
1358         {
1359                 // see note above
1360                 m_pPhysicsController->SetOrientation(rot);
1361         }
1362         GetSGNode()->SetLocalOrientation(rot);
1363 }
1364
1365 void KX_GameObject::NodeSetGlobalOrientation(const MT_Matrix3x3& rot)
1366 {
1367         // check on valid node in case a python controller holds a reference to a deleted object
1368         if (!GetSGNode())
1369                 return;
1370
1371         if (GetSGNode()->GetSGParent())
1372                 GetSGNode()->SetLocalOrientation(GetSGNode()->GetSGParent()->GetWorldOrientation().inverse()*rot);
1373         else
1374                 NodeSetLocalOrientation(rot);
1375 }
1376
1377 void KX_GameObject::NodeSetLocalScale(const MT_Vector3& scale)
1378 {
1379         // check on valid node in case a python controller holds a reference to a deleted object
1380         if (!GetSGNode())
1381                 return;
1382
1383         if (m_pPhysicsController && !GetSGNode()->GetSGParent())
1384         {
1385                 // see note above
1386                 m_pPhysicsController->SetScaling(scale);
1387         }
1388         GetSGNode()->SetLocalScale(scale);
1389 }
1390
1391
1392
1393 void KX_GameObject::NodeSetRelativeScale(const MT_Vector3& scale)
1394 {
1395         if (GetSGNode())
1396         {
1397                 GetSGNode()->RelativeScale(scale);
1398                 if (m_pPhysicsController && (!GetSGNode()->GetSGParent()))
1399                 {
1400                         // see note above
1401                         // we can use the local scale: it's the same thing for a root object 
1402                         // and the world scale is not yet updated
1403                         MT_Vector3 newscale = GetSGNode()->GetLocalScale();
1404                         m_pPhysicsController->SetScaling(newscale);
1405                 }
1406         }
1407 }
1408
1409 void KX_GameObject::NodeSetWorldScale(const MT_Vector3& scale)
1410 {
1411         if (!GetSGNode())
1412                 return;
1413         SG_Node* parent = GetSGNode()->GetSGParent();
1414         if (parent != NULL)
1415         {
1416                 // Make sure the objects have some scale
1417                 MT_Vector3 p_scale = parent->GetWorldScaling();
1418                 if (fabs(p_scale[0]) < (MT_Scalar)FLT_EPSILON ||
1419                         fabs(p_scale[1]) < (MT_Scalar)FLT_EPSILON ||
1420                         fabs(p_scale[2]) < (MT_Scalar)FLT_EPSILON)
1421                 { 
1422                         return; 
1423                 }
1424
1425                 p_scale[0] = 1/p_scale[0];
1426                 p_scale[1] = 1/p_scale[1];
1427                 p_scale[2] = 1/p_scale[2];
1428
1429                 NodeSetLocalScale(scale * p_scale);
1430         }
1431         else
1432         {
1433                 NodeSetLocalScale(scale);
1434         }
1435 }
1436
1437 void KX_GameObject::NodeSetWorldPosition(const MT_Point3& trans)
1438 {
1439         if (!GetSGNode())
1440                 return;
1441         SG_Node* parent = GetSGNode()->GetSGParent();
1442         if (parent != NULL)
1443         {
1444                 // Make sure the objects have some scale
1445                 MT_Vector3 scale = parent->GetWorldScaling();
1446                 if (fabs(scale[0]) < (MT_Scalar)FLT_EPSILON ||
1447                         fabs(scale[1]) < (MT_Scalar)FLT_EPSILON ||
1448                         fabs(scale[2]) < (MT_Scalar)FLT_EPSILON)
1449                 { 
1450                         return; 
1451                 }
1452                 scale[0] = 1.0/scale[0];
1453                 scale[1] = 1.0/scale[1];
1454                 scale[2] = 1.0/scale[2];
1455                 MT_Matrix3x3 invori = parent->GetWorldOrientation().inverse();
1456                 MT_Vector3 newpos = invori*(trans-parent->GetWorldPosition())*scale;
1457                 NodeSetLocalPosition(MT_Point3(newpos[0],newpos[1],newpos[2]));
1458         }
1459         else
1460         {
1461                 NodeSetLocalPosition(trans);
1462         }
1463 }
1464
1465
1466 void KX_GameObject::NodeUpdateGS(double time)
1467 {
1468         if (GetSGNode())
1469                 GetSGNode()->UpdateWorldData(time);
1470 }
1471
1472
1473
1474 const MT_Matrix3x3& KX_GameObject::NodeGetWorldOrientation() const
1475 {
1476         // check on valid node in case a python controller holds a reference to a deleted object
1477         if (!GetSGNode())
1478                 return dummy_orientation;
1479         return GetSGNode()->GetWorldOrientation();
1480 }
1481
1482 const MT_Matrix3x3& KX_GameObject::NodeGetLocalOrientation() const
1483 {
1484         // check on valid node in case a python controller holds a reference to a deleted object
1485         if (!GetSGNode())
1486                 return dummy_orientation;
1487         return GetSGNode()->GetLocalOrientation();
1488 }
1489
1490 const MT_Vector3& KX_GameObject::NodeGetWorldScaling() const
1491 {
1492         // check on valid node in case a python controller holds a reference to a deleted object
1493         if (!GetSGNode())
1494                 return dummy_scaling;
1495
1496         return GetSGNode()->GetWorldScaling();
1497 }
1498
1499 const MT_Vector3& KX_GameObject::NodeGetLocalScaling() const
1500 {
1501         // check on valid node in case a python controller holds a reference to a deleted object
1502         if (!GetSGNode())
1503                 return dummy_scaling;
1504
1505         return GetSGNode()->GetLocalScale();
1506 }
1507
1508 const MT_Point3& KX_GameObject::NodeGetWorldPosition() const
1509 {
1510         // check on valid node in case a python controller holds a reference to a deleted object
1511         if (GetSGNode())
1512                 return GetSGNode()->GetWorldPosition();
1513         else
1514                 return dummy_point;
1515 }
1516
1517 const MT_Point3& KX_GameObject::NodeGetLocalPosition() const
1518 {
1519         // check on valid node in case a python controller holds a reference to a deleted object
1520         if (GetSGNode())
1521                 return GetSGNode()->GetLocalPosition();
1522         else
1523                 return dummy_point;
1524 }
1525
1526
1527 void KX_GameObject::UnregisterCollisionCallbacks()
1528 {
1529         if (!GetPhysicsController()) {
1530                 printf("Warning, trying to unregister collision callbacks for object without collisions: %s!\n", GetName().ReadPtr());
1531                 return;
1532         }
1533
1534         // Unregister from callbacks
1535         KX_Scene* scene = GetScene();
1536         PHY_IPhysicsEnvironment* pe = scene->GetPhysicsEnvironment();
1537         PHY_IPhysicsController* spc = GetPhysicsController();
1538         // If we are the last to unregister on this physics controller
1539         if (pe->RemoveCollisionCallback(spc)){
1540                 // If we are a sensor object
1541                 if (m_pClient_info->isSensor())
1542                         // Remove sensor body from physics world
1543                         pe->RemoveSensor(spc);
1544         }
1545 }
1546
1547 void KX_GameObject::RegisterCollisionCallbacks()
1548 {
1549         if (!GetPhysicsController()) {
1550                 printf("Warning, trying to register collision callbacks for object without collisions: %s!\n", GetName().ReadPtr());
1551                 return;
1552         }
1553
1554         // Register from callbacks
1555         KX_Scene* scene = GetScene();
1556         PHY_IPhysicsEnvironment* pe = scene->GetPhysicsEnvironment();
1557         PHY_IPhysicsController* spc = GetPhysicsController();
1558         // If we are the first to register on this physics controller
1559         if (pe->RequestCollisionCallback(spc)){
1560                 // If we are a sensor object
1561                 if (m_pClient_info->isSensor())
1562                         // Add sensor body to physics world
1563                         pe->AddSensor(spc);
1564         }
1565 }
1566 void KX_GameObject::RunCollisionCallbacks(KX_GameObject *collider, const MT_Vector3 &point, const MT_Vector3 &normal)
1567 {
1568 #ifdef WITH_PYTHON
1569         if (!m_collisionCallbacks || PyList_GET_SIZE(m_collisionCallbacks) == 0)
1570                 return;
1571
1572         PyObject *args[] = {collider->GetProxy(), PyObjectFrom(point), PyObjectFrom(normal)};
1573         RunPythonCallBackList(m_collisionCallbacks, args, 1, ARRAY_SIZE(args));
1574
1575         for (unsigned int i = 0; i < ARRAY_SIZE(args); ++i) {
1576                 Py_DECREF(args[i]);
1577         }
1578 #endif
1579 }
1580
1581 /* Suspend/ resume: for the dynamic behavior, there is a simple
1582  * method. For the residual motion, there is not. I wonder what the
1583  * correct solution is for Sumo. Remove from the motion-update tree?
1584  *
1585  * So far, only switch the physics and logic.
1586  * */
1587
1588 void KX_GameObject::Resume(void)
1589 {
1590         if (m_suspended) {
1591                 SCA_IObject::Resume();
1592                 if (GetPhysicsController())
1593                         GetPhysicsController()->RestoreDynamics();
1594
1595                 m_suspended = false;
1596         }
1597 }
1598
1599 void KX_GameObject::Suspend()
1600 {
1601         if ((!m_ignore_activity_culling) && (!m_suspended)) {
1602                 SCA_IObject::Suspend();
1603                 if (GetPhysicsController())
1604                         GetPhysicsController()->SuspendDynamics();
1605                 m_suspended = true;
1606         }
1607 }
1608
1609 static void walk_children(SG_Node* node, CListValue* list, bool recursive)
1610 {
1611         if (!node)
1612                 return;
1613         NodeList& children = node->GetSGChildren();
1614
1615         for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
1616         {
1617                 SG_Node* childnode = (*childit);
1618                 CValue* childobj = (CValue*)childnode->GetSGClientObject();
1619                 if (childobj != NULL) // This is a GameObject
1620                 {
1621                         // add to the list
1622                         list->Add(childobj->AddRef());
1623                 }
1624                 
1625                 // if the childobj is NULL then this may be an inverse parent link
1626                 // so a non recursive search should still look down this node.
1627                 if (recursive || childobj==NULL) {
1628                         walk_children(childnode, list, recursive);
1629                 }
1630         }
1631 }
1632
1633 CListValue* KX_GameObject::GetChildren()
1634 {
1635         CListValue* list = new CListValue();
1636         walk_children(GetSGNode(), list, 0); /* GetSGNode() is always valid or it would have raised an exception before this */
1637         return list;
1638 }
1639
1640 CListValue* KX_GameObject::GetChildrenRecursive()
1641 {
1642         CListValue* list = new CListValue();
1643         walk_children(GetSGNode(), list, 1);
1644         return list;
1645 }
1646
1647 KX_Scene* KX_GameObject::GetScene()
1648 {
1649         SG_Node* node = this->GetSGNode();
1650     if (node == NULL)
1651         // this happens for object in non active layers, rely on static scene then
1652         return KX_GetActiveScene();
1653     return static_cast<KX_Scene*>(node->GetSGClientInfo());
1654 }
1655
1656 /* ---------------------------------------------------------------------
1657  * Some stuff taken from the header
1658  * --------------------------------------------------------------------- */
1659 void KX_GameObject::Relink(CTR_Map<CTR_HashedPtr, void*> *map_parameter)
1660 {
1661         // we will relink the sensors and actuators that use object references
1662         // if the object is part of the replicated hierarchy, use the new
1663         // object reference instead
1664         SCA_SensorList& sensorlist = GetSensors();
1665         SCA_SensorList::iterator sit;
1666         for (sit=sensorlist.begin(); sit != sensorlist.end(); sit++)
1667         {
1668                 (*sit)->Relink(map_parameter);
1669         }
1670         SCA_ActuatorList& actuatorlist = GetActuators();
1671         SCA_ActuatorList::iterator ait;
1672         for (ait=actuatorlist.begin(); ait != actuatorlist.end(); ait++)
1673         {
1674                 (*ait)->Relink(map_parameter);
1675         }
1676 }
1677
1678 #ifdef USE_MATHUTILS
1679
1680 /* These require an SGNode */
1681 #define MATHUTILS_VEC_CB_POS_LOCAL 1
1682 #define MATHUTILS_VEC_CB_POS_GLOBAL 2
1683 #define MATHUTILS_VEC_CB_SCALE_LOCAL 3
1684 #define MATHUTILS_VEC_CB_SCALE_GLOBAL 4
1685 #define MATHUTILS_VEC_CB_INERTIA_LOCAL 5
1686 #define MATHUTILS_VEC_CB_OBJECT_COLOR 6
1687 #define MATHUTILS_VEC_CB_LINVEL_LOCAL 7
1688 #define MATHUTILS_VEC_CB_LINVEL_GLOBAL 8
1689 #define MATHUTILS_VEC_CB_ANGVEL_LOCAL 9
1690 #define MATHUTILS_VEC_CB_ANGVEL_GLOBAL 10
1691
1692 static unsigned char mathutils_kxgameob_vector_cb_index= -1; /* index for our callbacks */
1693
1694 static int mathutils_kxgameob_generic_check(BaseMathObject *bmo)
1695 {
1696         KX_GameObject* self = static_cast<KX_GameObject*>BGE_PROXY_REF(bmo->cb_user);
1697         if (self == NULL)
1698                 return -1;
1699         
1700         return 0;
1701 }
1702
1703 static int mathutils_kxgameob_vector_get(BaseMathObject *bmo, int subtype)
1704 {
1705         KX_GameObject* self = static_cast<KX_GameObject*>BGE_PROXY_REF(bmo->cb_user);
1706         if (self == NULL)
1707                 return -1;
1708
1709 #define PHYS_ERR(attr) PyErr_SetString(PyExc_AttributeError, "KX_GameObject." attr ", is missing a physics controller")
1710
1711         switch (subtype) {
1712                 case MATHUTILS_VEC_CB_POS_LOCAL:
1713                         self->NodeGetLocalPosition().getValue(bmo->data);
1714                         break;
1715                 case MATHUTILS_VEC_CB_POS_GLOBAL:
1716                         self->NodeGetWorldPosition().getValue(bmo->data);
1717                         break;
1718                 case MATHUTILS_VEC_CB_SCALE_LOCAL:
1719                         self->NodeGetLocalScaling().getValue(bmo->data);
1720                         break;
1721                 case MATHUTILS_VEC_CB_SCALE_GLOBAL:
1722                         self->NodeGetWorldScaling().getValue(bmo->data);
1723                         break;
1724                 case MATHUTILS_VEC_CB_INERTIA_LOCAL:
1725                         if (!self->GetPhysicsController()) return PHYS_ERR("localInertia"), -1;
1726                         self->GetPhysicsController()->GetLocalInertia().getValue(bmo->data);
1727                         break;
1728                 case MATHUTILS_VEC_CB_OBJECT_COLOR:
1729                         self->GetObjectColor().getValue(bmo->data);
1730                         break;
1731                 case MATHUTILS_VEC_CB_LINVEL_LOCAL:
1732                         if (!self->GetPhysicsController()) return PHYS_ERR("localLinearVelocity"), -1;
1733                         self->GetLinearVelocity(true).getValue(bmo->data);
1734                         break;
1735                 case MATHUTILS_VEC_CB_LINVEL_GLOBAL:
1736                         if (!self->GetPhysicsController()) return PHYS_ERR("worldLinearVelocity"), -1;
1737                         self->GetLinearVelocity(false).getValue(bmo->data);
1738                         break;
1739                 case MATHUTILS_VEC_CB_ANGVEL_LOCAL:
1740                         if (!self->GetPhysicsController()) return PHYS_ERR("localLinearVelocity"), -1;
1741                         self->GetAngularVelocity(true).getValue(bmo->data);
1742                         break;
1743                 case MATHUTILS_VEC_CB_ANGVEL_GLOBAL:
1744                         if (!self->GetPhysicsController()) return PHYS_ERR("worldLinearVelocity"), -1;
1745                         self->GetAngularVelocity(false).getValue(bmo->data);
1746                         break;
1747                         
1748         }
1749         
1750 #undef PHYS_ERR
1751         
1752         return 0;
1753 }
1754
1755 static int mathutils_kxgameob_vector_set(BaseMathObject *bmo, int subtype)
1756 {
1757         KX_GameObject* self = static_cast<KX_GameObject*>BGE_PROXY_REF(bmo->cb_user);
1758         if (self == NULL)
1759                 return -1;
1760         
1761         switch (subtype) {
1762                 case MATHUTILS_VEC_CB_POS_LOCAL:
1763                         self->NodeSetLocalPosition(MT_Point3(bmo->data));
1764                         self->NodeUpdateGS(0.f);
1765                         break;
1766                 case MATHUTILS_VEC_CB_POS_GLOBAL:
1767                         self->NodeSetWorldPosition(MT_Point3(bmo->data));
1768                         self->NodeUpdateGS(0.f);
1769                         break;
1770                 case MATHUTILS_VEC_CB_SCALE_LOCAL:
1771                         self->NodeSetLocalScale(MT_Point3(bmo->data));
1772                         self->NodeUpdateGS(0.f);
1773                         break;
1774                 case MATHUTILS_VEC_CB_SCALE_GLOBAL:
1775                         PyErr_SetString(PyExc_AttributeError, "KX_GameObject.worldScale is read-only");
1776                         return -1;
1777                 case MATHUTILS_VEC_CB_INERTIA_LOCAL:
1778                         /* read only */
1779                         break;
1780                 case MATHUTILS_VEC_CB_OBJECT_COLOR:
1781                         self->SetObjectColor(MT_Vector4(bmo->data));
1782                         break;
1783                 case MATHUTILS_VEC_CB_LINVEL_LOCAL:
1784                         self->setLinearVelocity(MT_Point3(bmo->data),true);
1785                         break;
1786                 case MATHUTILS_VEC_CB_LINVEL_GLOBAL:
1787                         self->setLinearVelocity(MT_Point3(bmo->data),false);
1788                         break;
1789                 case MATHUTILS_VEC_CB_ANGVEL_LOCAL:
1790                         self->setAngularVelocity(MT_Point3(bmo->data),true);
1791                         break;
1792                 case MATHUTILS_VEC_CB_ANGVEL_GLOBAL:
1793                         self->setAngularVelocity(MT_Point3(bmo->data),false);
1794                         break;
1795         }
1796         
1797         return 0;
1798 }
1799
1800 static int mathutils_kxgameob_vector_get_index(BaseMathObject *bmo, int subtype, int index)
1801 {
1802         /* lazy, avoid repeteing the case statement */
1803         if (mathutils_kxgameob_vector_get(bmo, subtype) == -1)
1804                 return -1;
1805         return 0;
1806 }
1807
1808 static int mathutils_kxgameob_vector_set_index(BaseMathObject *bmo, int subtype, int index)
1809 {
1810         float f= bmo->data[index];
1811         
1812         /* lazy, avoid repeteing the case statement */
1813         if (mathutils_kxgameob_vector_get(bmo, subtype) == -1)
1814                 return -1;
1815         
1816         bmo->data[index] = f;
1817         return mathutils_kxgameob_vector_set(bmo, subtype);
1818 }
1819
1820 static Mathutils_Callback mathutils_kxgameob_vector_cb = {
1821         mathutils_kxgameob_generic_check,
1822         mathutils_kxgameob_vector_get,
1823         mathutils_kxgameob_vector_set,
1824         mathutils_kxgameob_vector_get_index,
1825         mathutils_kxgameob_vector_set_index
1826 };
1827
1828 /* Matrix */
1829 #define MATHUTILS_MAT_CB_ORI_LOCAL 1
1830 #define MATHUTILS_MAT_CB_ORI_GLOBAL 2
1831
1832 static unsigned char mathutils_kxgameob_matrix_cb_index= -1; /* index for our callbacks */
1833
1834 static int mathutils_kxgameob_matrix_get(BaseMathObject *bmo, int subtype)
1835 {
1836         KX_GameObject* self = static_cast<KX_GameObject*>BGE_PROXY_REF(bmo->cb_user);
1837         if (self == NULL)
1838                 return -1;
1839
1840         switch (subtype) {
1841                 case MATHUTILS_MAT_CB_ORI_LOCAL:
1842                         self->NodeGetLocalOrientation().getValue3x3(bmo->data);
1843                         break;
1844                 case MATHUTILS_MAT_CB_ORI_GLOBAL:
1845                         self->NodeGetWorldOrientation().getValue3x3(bmo->data);
1846                         break;
1847         }
1848         
1849         return 0;
1850 }
1851
1852
1853 static int mathutils_kxgameob_matrix_set(BaseMathObject *bmo, int subtype)
1854 {
1855         KX_GameObject* self = static_cast<KX_GameObject*>BGE_PROXY_REF(bmo->cb_user);
1856         if (self == NULL)
1857                 return -1;
1858         
1859         MT_Matrix3x3 mat3x3;
1860         switch (subtype) {
1861                 case MATHUTILS_MAT_CB_ORI_LOCAL:
1862                         mat3x3.setValue3x3(bmo->data);
1863                         self->NodeSetLocalOrientation(mat3x3);
1864                         self->NodeUpdateGS(0.f);
1865                         break;
1866                 case MATHUTILS_MAT_CB_ORI_GLOBAL:
1867                         mat3x3.setValue3x3(bmo->data);
1868                         self->NodeSetLocalOrientation(mat3x3);
1869                         self->NodeUpdateGS(0.f);
1870                         break;
1871         }
1872         
1873         return 0;
1874 }
1875
1876 static Mathutils_Callback mathutils_kxgameob_matrix_cb = {
1877         mathutils_kxgameob_generic_check,
1878         mathutils_kxgameob_matrix_get,
1879         mathutils_kxgameob_matrix_set,
1880         NULL,
1881         NULL
1882 };
1883
1884
1885 void KX_GameObject_Mathutils_Callback_Init(void)
1886 {
1887         // register mathutils callbacks, ok to run more than once.
1888         mathutils_kxgameob_vector_cb_index= Mathutils_RegisterCallback(&mathutils_kxgameob_vector_cb);
1889         mathutils_kxgameob_matrix_cb_index= Mathutils_RegisterCallback(&mathutils_kxgameob_matrix_cb);
1890 }
1891
1892 #endif // USE_MATHUTILS
1893
1894 #ifdef WITH_PYTHON
1895 /* ------- python stuff ---------------------------------------------------*/
1896 PyMethodDef KX_GameObject::Methods[] = {
1897         {"applyForce", (PyCFunction)    KX_GameObject::sPyApplyForce, METH_VARARGS},
1898         {"applyTorque", (PyCFunction)   KX_GameObject::sPyApplyTorque, METH_VARARGS},
1899         {"applyRotation", (PyCFunction) KX_GameObject::sPyApplyRotation, METH_VARARGS},
1900         {"applyMovement", (PyCFunction) KX_GameObject::sPyApplyMovement, METH_VARARGS},
1901         {"getLinearVelocity", (PyCFunction) KX_GameObject::sPyGetLinearVelocity, METH_VARARGS},
1902         {"setLinearVelocity", (PyCFunction) KX_GameObject::sPySetLinearVelocity, METH_VARARGS},
1903         {"getAngularVelocity", (PyCFunction) KX_GameObject::sPyGetAngularVelocity, METH_VARARGS},
1904         {"setAngularVelocity", (PyCFunction) KX_GameObject::sPySetAngularVelocity, METH_VARARGS},
1905         {"getVelocity", (PyCFunction) KX_GameObject::sPyGetVelocity, METH_VARARGS},
1906         {"setDamping", (PyCFunction) KX_GameObject::sPySetDamping, METH_VARARGS},
1907         {"getReactionForce", (PyCFunction) KX_GameObject::sPyGetReactionForce, METH_NOARGS},
1908         {"alignAxisToVect",(PyCFunction) KX_GameObject::sPyAlignAxisToVect, METH_VARARGS},
1909         {"getAxisVect",(PyCFunction) KX_GameObject::sPyGetAxisVect, METH_O},
1910         {"suspendDynamics", (PyCFunction)KX_GameObject::sPySuspendDynamics, METH_VARARGS},
1911         {"restoreDynamics", (PyCFunction)KX_GameObject::sPyRestoreDynamics,METH_NOARGS},
1912         {"enableRigidBody", (PyCFunction)KX_GameObject::sPyEnableRigidBody,METH_NOARGS},
1913         {"disableRigidBody", (PyCFunction)KX_GameObject::sPyDisableRigidBody,METH_NOARGS},
1914         {"applyImpulse", (PyCFunction) KX_GameObject::sPyApplyImpulse, METH_VARARGS},
1915         {"setCollisionMargin", (PyCFunction) KX_GameObject::sPySetCollisionMargin, METH_O},
1916         {"setParent", (PyCFunction)KX_GameObject::sPySetParent,METH_VARARGS},
1917         {"setVisible",(PyCFunction) KX_GameObject::sPySetVisible, METH_VARARGS},
1918         {"setOcclusion",(PyCFunction) KX_GameObject::sPySetOcclusion, METH_VARARGS},
1919         {"removeParent", (PyCFunction)KX_GameObject::sPyRemoveParent,METH_NOARGS},
1920
1921
1922         {"getPhysicsId", (PyCFunction)KX_GameObject::sPyGetPhysicsId,METH_NOARGS},
1923         {"getPropertyNames", (PyCFunction)KX_GameObject::sPyGetPropertyNames,METH_NOARGS},
1924         {"replaceMesh",(PyCFunction) KX_GameObject::sPyReplaceMesh, METH_VARARGS},
1925         {"endObject",(PyCFunction) KX_GameObject::sPyEndObject, METH_NOARGS},
1926         {"reinstancePhysicsMesh", (PyCFunction)KX_GameObject::sPyReinstancePhysicsMesh,METH_VARARGS},
1927         
1928         KX_PYMETHODTABLE(KX_GameObject, rayCastTo),
1929         KX_PYMETHODTABLE(KX_GameObject, rayCast),
1930         KX_PYMETHODTABLE_O(KX_GameObject, getDistanceTo),
1931         KX_PYMETHODTABLE_O(KX_GameObject, getVectTo),
1932         KX_PYMETHODTABLE(KX_GameObject, sendMessage),
1933         KX_PYMETHODTABLE(KX_GameObject, addDebugProperty),
1934
1935         KX_PYMETHODTABLE_KEYWORDS(KX_GameObject, playAction),
1936         KX_PYMETHODTABLE(KX_GameObject, stopAction),
1937         KX_PYMETHODTABLE(KX_GameObject, getActionFrame),
1938         KX_PYMETHODTABLE(KX_GameObject, setActionFrame),
1939         KX_PYMETHODTABLE(KX_GameObject, isPlayingAction),
1940         
1941         // dict style access for props
1942         {"get",(PyCFunction) KX_GameObject::sPyget, METH_VARARGS},
1943         
1944         {NULL,NULL} //Sentinel
1945 };
1946
1947 PyAttributeDef KX_GameObject::Attributes[] = {
1948         KX_PYATTRIBUTE_INT_RO("currentLodLevel", KX_GameObject, m_currentLodLevel),
1949         KX_PYATTRIBUTE_RO_FUNCTION("name",              KX_GameObject, pyattr_get_name),
1950         KX_PYATTRIBUTE_RO_FUNCTION("parent",    KX_GameObject, pyattr_get_parent),
1951         KX_PYATTRIBUTE_RO_FUNCTION("groupMembers",      KX_GameObject, pyattr_get_group_members),
1952         KX_PYATTRIBUTE_RO_FUNCTION("groupObject",       KX_GameObject, pyattr_get_group_object),
1953         KX_PYATTRIBUTE_RO_FUNCTION("scene",             KX_GameObject, pyattr_get_scene),
1954         KX_PYATTRIBUTE_RO_FUNCTION("life",              KX_GameObject, pyattr_get_life),
1955         KX_PYATTRIBUTE_RW_FUNCTION("mass",              KX_GameObject, pyattr_get_mass,         pyattr_set_mass),
1956         KX_PYATTRIBUTE_RO_FUNCTION("isSuspendDynamics",         KX_GameObject, pyattr_get_is_suspend_dynamics),
1957         KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMin",            KX_GameObject, pyattr_get_lin_vel_min, pyattr_set_lin_vel_min),
1958         KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMax",            KX_GameObject, pyattr_get_lin_vel_max, pyattr_set_lin_vel_max),
1959         KX_PYATTRIBUTE_RW_FUNCTION("visible",   KX_GameObject, pyattr_get_visible,      pyattr_set_visible),
1960         KX_PYATTRIBUTE_RW_FUNCTION("record_animation",  KX_GameObject, pyattr_get_record_animation,     pyattr_set_record_animation),
1961         KX_PYATTRIBUTE_BOOL_RW    ("occlusion", KX_GameObject, m_bOccluder),
1962         KX_PYATTRIBUTE_RW_FUNCTION("position",  KX_GameObject, pyattr_get_worldPosition,        pyattr_set_localPosition),
1963         KX_PYATTRIBUTE_RO_FUNCTION("localInertia",      KX_GameObject, pyattr_get_localInertia),
1964         KX_PYATTRIBUTE_RW_FUNCTION("orientation",KX_GameObject,pyattr_get_worldOrientation,pyattr_set_localOrientation),
1965         KX_PYATTRIBUTE_RW_FUNCTION("scaling",   KX_GameObject, pyattr_get_worldScaling, pyattr_set_localScaling),
1966         KX_PYATTRIBUTE_RW_FUNCTION("timeOffset",KX_GameObject, pyattr_get_timeOffset,pyattr_set_timeOffset),
1967         KX_PYATTRIBUTE_RW_FUNCTION("collisionCallbacks",                KX_GameObject, pyattr_get_collisionCallbacks,   pyattr_set_collisionCallbacks),
1968         KX_PYATTRIBUTE_RW_FUNCTION("collisionGroup",                    KX_GameObject, pyattr_get_collisionGroup, pyattr_set_collisionGroup),
1969         KX_PYATTRIBUTE_RW_FUNCTION("collisionMask",                             KX_GameObject, pyattr_get_collisionMask, pyattr_set_collisionMask),
1970         KX_PYATTRIBUTE_RW_FUNCTION("state",             KX_GameObject, pyattr_get_state,        pyattr_set_state),
1971         KX_PYATTRIBUTE_RO_FUNCTION("meshes",    KX_GameObject, pyattr_get_meshes),
1972         KX_PYATTRIBUTE_RW_FUNCTION("localOrientation",KX_GameObject,pyattr_get_localOrientation,pyattr_set_localOrientation),
1973         KX_PYATTRIBUTE_RW_FUNCTION("worldOrientation",KX_GameObject,pyattr_get_worldOrientation,pyattr_set_worldOrientation),
1974         KX_PYATTRIBUTE_RW_FUNCTION("localPosition",     KX_GameObject, pyattr_get_localPosition,        pyattr_set_localPosition),
1975         KX_PYATTRIBUTE_RW_FUNCTION("worldPosition",     KX_GameObject, pyattr_get_worldPosition,    pyattr_set_worldPosition),
1976         KX_PYATTRIBUTE_RW_FUNCTION("localScale",        KX_GameObject, pyattr_get_localScaling, pyattr_set_localScaling),
1977         KX_PYATTRIBUTE_RW_FUNCTION("worldScale",        KX_GameObject, pyattr_get_worldScaling, pyattr_set_worldScaling),
1978         KX_PYATTRIBUTE_RW_FUNCTION("localTransform",            KX_GameObject, pyattr_get_localTransform, pyattr_set_localTransform),
1979         KX_PYATTRIBUTE_RW_FUNCTION("worldTransform",            KX_GameObject, pyattr_get_worldTransform, pyattr_set_worldTransform),
1980         KX_PYATTRIBUTE_RW_FUNCTION("linearVelocity", KX_GameObject, pyattr_get_localLinearVelocity, pyattr_set_worldLinearVelocity),
1981         KX_PYATTRIBUTE_RW_FUNCTION("localLinearVelocity", KX_GameObject, pyattr_get_localLinearVelocity, pyattr_set_localLinearVelocity),
1982         KX_PYATTRIBUTE_RW_FUNCTION("worldLinearVelocity", KX_GameObject, pyattr_get_worldLinearVelocity, pyattr_set_worldLinearVelocity),
1983         KX_PYATTRIBUTE_RW_FUNCTION("angularVelocity", KX_GameObject, pyattr_get_localAngularVelocity, pyattr_set_worldAngularVelocity),
1984         KX_PYATTRIBUTE_RW_FUNCTION("localAngularVelocity", KX_GameObject, pyattr_get_localAngularVelocity, pyattr_set_localAngularVelocity),
1985         KX_PYATTRIBUTE_RW_FUNCTION("worldAngularVelocity", KX_GameObject, pyattr_get_worldAngularVelocity, pyattr_set_worldAngularVelocity),
1986         KX_PYATTRIBUTE_RW_FUNCTION("linearDamping", KX_GameObject, pyattr_get_linearDamping, pyattr_set_linearDamping),
1987         KX_PYATTRIBUTE_RW_FUNCTION("angularDamping", KX_GameObject, pyattr_get_angularDamping, pyattr_set_angularDamping),
1988         KX_PYATTRIBUTE_RO_FUNCTION("children",  KX_GameObject, pyattr_get_children),
1989         KX_PYATTRIBUTE_RO_FUNCTION("childrenRecursive", KX_GameObject, pyattr_get_children_recursive),
1990         KX_PYATTRIBUTE_RO_FUNCTION("attrDict",  KX_GameObject, pyattr_get_attrDict),
1991         KX_PYATTRIBUTE_RW_FUNCTION("color", KX_GameObject, pyattr_get_obcolor, pyattr_set_obcolor),
1992         KX_PYATTRIBUTE_RW_FUNCTION("debug",     KX_GameObject, pyattr_get_debug, pyattr_set_debug),
1993         KX_PYATTRIBUTE_RW_FUNCTION("debugRecursive",    KX_GameObject, pyattr_get_debugRecursive, pyattr_set_debugRecursive),
1994         
1995         /* experimental, don't rely on these yet */
1996         KX_PYATTRIBUTE_RO_FUNCTION("sensors",           KX_GameObject, pyattr_get_sensors),
1997         KX_PYATTRIBUTE_RO_FUNCTION("controllers",       KX_GameObject, pyattr_get_controllers),
1998         KX_PYATTRIBUTE_RO_FUNCTION("actuators",         KX_GameObject, pyattr_get_actuators),
1999         {NULL} //Sentinel
2000 };
2001
2002 PyObject *KX_GameObject::PyReplaceMesh(PyObject *args)
2003 {
2004         KX_Scene *scene = KX_GetActiveScene();
2005         
2006         PyObject *value;
2007         int use_gfx= 1, use_phys= 0;
2008         RAS_MeshObject *new_mesh;
2009         
2010         if (!PyArg_ParseTuple(args,"O|ii:replaceMesh", &value, &use_gfx, &use_phys))
2011                 return NULL;
2012         
2013         if (!ConvertPythonToMesh(value, &new_mesh, false, "gameOb.replaceMesh(value): KX_GameObject"))
2014                 return NULL;
2015         
2016         scene->ReplaceMesh(this, new_mesh, (bool)use_gfx, (bool)use_phys);
2017         Py_RETURN_NONE;
2018 }
2019
2020 PyObject *KX_GameObject::PyEndObject()
2021 {
2022         KX_Scene* scene = GetScene();
2023         
2024         scene->DelayedRemoveObject(this);
2025         
2026         Py_RETURN_NONE;
2027
2028 }
2029
2030 PyObject *KX_GameObject::PyReinstancePhysicsMesh(PyObject *args)
2031 {
2032         KX_GameObject *gameobj= NULL;
2033         RAS_MeshObject *mesh= NULL;
2034         
2035         PyObject *gameobj_py= NULL;
2036         PyObject *mesh_py= NULL;
2037
2038         if (    !PyArg_ParseTuple(args,"|OO:reinstancePhysicsMesh",&gameobj_py, &mesh_py) ||
2039                         (gameobj_py && !ConvertPythonToGameObject(gameobj_py, &gameobj, true, "gameOb.reinstancePhysicsMesh(obj, mesh): KX_GameObject")) || 
2040                         (mesh_py && !ConvertPythonToMesh(mesh_py, &mesh, true, "gameOb.reinstancePhysicsMesh(obj, mesh): KX_GameObject"))
2041                 ) {
2042                 return NULL;
2043         }
2044
2045         /* gameobj and mesh can be NULL */
2046         if (GetPhysicsController() && GetPhysicsController()->ReinstancePhysicsShape(gameobj, mesh))
2047                 Py_RETURN_TRUE;
2048
2049         Py_RETURN_FALSE;
2050 }
2051
2052 static PyObject *Map_GetItem(PyObject *self_v, PyObject *item)
2053 {
2054         KX_GameObject* self = static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
2055         const char *attr_str= _PyUnicode_AsString(item);
2056         CValue* resultattr;
2057         PyObject *pyconvert;
2058         
2059         if (self == NULL) {
2060                 PyErr_SetString(PyExc_SystemError, "val = gameOb[key]: KX_GameObject, " BGE_PROXY_ERROR_MSG);
2061                 return NULL;
2062         }
2063         
2064         /* first see if the attributes a string and try get the cvalue attribute */
2065         if (attr_str && (resultattr=self->GetProperty(attr_str))) {
2066                 pyconvert = resultattr->ConvertValueToPython();
2067                 return pyconvert ? pyconvert:resultattr->GetProxy();
2068         }
2069         /* no CValue attribute, try get the python only m_attr_dict attribute */
2070         else if (self->m_attr_dict && (pyconvert=PyDict_GetItem(self->m_attr_dict, item))) {
2071                 
2072                 if (attr_str)
2073                         PyErr_Clear();
2074                 Py_INCREF(pyconvert);
2075                 return pyconvert;
2076         }
2077         else {
2078                 if (attr_str)   PyErr_Format(PyExc_KeyError, "value = gameOb[key]: KX_GameObject, key \"%s\" does not exist", attr_str);
2079                 else                    PyErr_SetString(PyExc_KeyError, "value = gameOb[key]: KX_GameObject, key does not exist");
2080                 return NULL;
2081         }
2082                 
2083 }
2084
2085
2086 static int Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val)
2087 {
2088         KX_GameObject* self = static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
2089         const char *attr_str= _PyUnicode_AsString(key);
2090         if (attr_str==NULL)
2091                 PyErr_Clear();
2092         
2093         if (self == NULL) {
2094                 PyErr_SetString(PyExc_SystemError, "gameOb[key] = value: KX_GameObject, " BGE_PROXY_ERROR_MSG);
2095                 return -1;
2096         }
2097         
2098         if (val==NULL) { /* del ob["key"] */
2099                 int del= 0;
2100                 
2101                 /* try remove both just in case */
2102                 if (attr_str)
2103                         del |= (self->RemoveProperty(attr_str)==true) ? 1:0;
2104                 
2105                 if (self->m_attr_dict)
2106                         del |= (PyDict_DelItem(self->m_attr_dict, key)==0) ? 1:0;
2107                 
2108                 if (del==0) {
2109                         if (attr_str)   PyErr_Format(PyExc_KeyError, "gameOb[key] = value: KX_GameObject, key \"%s\" could not be set", attr_str);
2110                         else                    PyErr_SetString(PyExc_KeyError, "del gameOb[key]: KX_GameObject, key could not be deleted");
2111                         return -1;
2112                 }
2113                 else if (self->m_attr_dict) {
2114                         PyErr_Clear(); /* PyDict_DelItem sets an error when it fails */
2115                 }
2116         }
2117         else { /* ob["key"] = value */
2118                 bool set = false;
2119                 
2120                 /* as CValue */
2121                 if (attr_str && PyObject_TypeCheck(val, &PyObjectPlus::Type)==0) /* don't allow GameObjects for eg to be assigned to CValue props */
2122                 {
2123                         CValue *vallie = self->ConvertPythonToValue(val, false, "gameOb[key] = value: ");
2124                         
2125                         if (vallie) {
2126                                 CValue* oldprop = self->GetProperty(attr_str);
2127                                 
2128                                 if (oldprop)
2129                                         oldprop->SetValue(vallie);
2130                                 else
2131                                         self->SetProperty(attr_str, vallie);
2132                                 
2133                                 vallie->Release();
2134                                 set = true;
2135                                 
2136                                 /* try remove dict value to avoid double ups */
2137                                 if (self->m_attr_dict) {
2138                                         if (PyDict_DelItem(self->m_attr_dict, key) != 0)
2139                                                 PyErr_Clear();
2140                                 }
2141                         }
2142                         else if (PyErr_Occurred()) {
2143                                 return -1;
2144                         }
2145                 }
2146                 
2147                 if (set == false) {
2148                         if (self->m_attr_dict==NULL) /* lazy init */
2149                                 self->m_attr_dict= PyDict_New();
2150                         
2151                         
2152                         if (PyDict_SetItem(self->m_attr_dict, key, val)==0)
2153                         {
2154                                 if (attr_str)
2155                                         self->RemoveProperty(attr_str); /* overwrite the CValue if it exists */
2156                                 set = true;
2157                         }
2158                         else {
2159                                 if (attr_str)   PyErr_Format(PyExc_KeyError, "gameOb[key] = value: KX_GameObject, key \"%s\" not be added to internal dictionary", attr_str);
2160                                 else                    PyErr_SetString(PyExc_KeyError, "gameOb[key] = value: KX_GameObject, key not be added to internal dictionary");
2161                         }
2162                 }
2163                 
2164                 if (set == false) {
2165                         return -1; /* pythons error value */
2166                 }
2167                 
2168         }
2169         
2170         return 0; /* success */
2171 }
2172
2173 static int Seq_Contains(PyObject *self_v, PyObject *value)
2174 {
2175         KX_GameObject* self = static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
2176         
2177         if (self == NULL) {
2178                 PyErr_SetString(PyExc_SystemError, "val in gameOb: KX_GameObject, " BGE_PROXY_ERROR_MSG);
2179                 return -1;
2180         }
2181         
2182         if (PyUnicode_Check(value) && self->GetProperty(_PyUnicode_AsString(value)))
2183                 return 1;
2184         
2185         if (self->m_attr_dict && PyDict_GetItem(self->m_attr_dict, value))
2186                 return 1;
2187         
2188         return 0;
2189 }
2190
2191
2192 PyMappingMethods KX_GameObject::Mapping = {
2193         (lenfunc)NULL                                   ,                       /*inquiry mp_length */
2194         (binaryfunc)Map_GetItem,                /*binaryfunc mp_subscript */
2195         (objobjargproc)Map_SetItem,     /*objobjargproc mp_ass_subscript */
2196 };
2197
2198 PySequenceMethods KX_GameObject::Sequence = {
2199         NULL,           /* Cant set the len otherwise it can evaluate as false */
2200         NULL,           /* sq_concat */
2201         NULL,           /* sq_repeat */
2202         NULL,           /* sq_item */
2203         NULL,           /* sq_slice */
2204         NULL,           /* sq_ass_item */
2205         NULL,           /* sq_ass_slice */
2206         (objobjproc)Seq_Contains,       /* sq_contains */
2207         (binaryfunc) NULL, /* sq_inplace_concat */
2208         (ssizeargfunc) NULL, /* sq_inplace_repeat */
2209 };
2210
2211 PyTypeObject KX_GameObject::Type = {
2212         PyVarObject_HEAD_INIT(NULL, 0)
2213         "KX_GameObject",
2214         sizeof(PyObjectPlus_Proxy),
2215         0,
2216         py_base_dealloc,
2217         0,
2218         0,
2219         0,
2220         0,
2221         py_base_repr,
2222         0,
2223         &Sequence,
2224         &Mapping,
2225         0,0,0,
2226         NULL,
2227         NULL,
2228         0,
2229         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
2230         0,0,0,0,0,0,0,
2231         Methods,
2232         0,
2233         0,
2234         &SCA_IObject::Type,
2235         0,0,0,0,0,0,
2236         py_base_new
2237 };
2238
2239 PyObject *KX_GameObject::pyattr_get_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2240 {
2241         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2242         return PyUnicode_From_STR_String(self->GetName());
2243 }
2244
2245 PyObject *KX_GameObject::pyattr_get_parent(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2246 {
2247         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2248         KX_GameObject* parent = self->GetParent();
2249         if (parent) {
2250                 return parent->GetProxy();
2251         }
2252         Py_RETURN_NONE;
2253 }
2254
2255 PyObject *KX_GameObject::pyattr_get_group_members(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2256 {
2257         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2258         CListValue* instances = self->GetInstanceObjects();
2259         if (instances) {
2260                 return instances->GetProxy();
2261         }
2262         Py_RETURN_NONE;
2263 }
2264
2265 PyObject* KX_GameObject::pyattr_get_collisionCallbacks(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2266 {
2267         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2268
2269         // Only objects with a physics controller should have collision callbacks
2270         if (!self->GetPhysicsController()) {
2271                 PyErr_SetString(PyExc_AttributeError, "KX_GameObject.collisionCallbacks: attribute only available for objects with collisions enabled");
2272                 return NULL;
2273         }
2274
2275         // Return the existing callbacks
2276         if (self->m_collisionCallbacks == NULL)
2277         {
2278                 self->m_collisionCallbacks = PyList_New(0);
2279                 // Subscribe to collision update from KX_TouchManager
2280                 self->RegisterCollisionCallbacks();
2281         }
2282         Py_INCREF(self->m_collisionCallbacks);
2283         return self->m_collisionCallbacks;
2284 }
2285
2286 int KX_GameObject::pyattr_set_collisionCallbacks(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
2287 {
2288         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2289
2290         // Only objects with a physics controller should have collision callbacks
2291         if (!self->GetPhysicsController()) {
2292                 PyErr_SetString(PyExc_AttributeError, "KX_GameObject.collisionCallbacks: attribute only available for objects with collisions enabled");
2293                 return PY_SET_ATTR_FAIL;
2294         }
2295
2296         if (!PyList_CheckExact(value))
2297         {
2298                 PyErr_SetString(PyExc_ValueError, "Expected a list");
2299                 return PY_SET_ATTR_FAIL;
2300         }
2301
2302         if (self->m_collisionCallbacks == NULL) {
2303                 self->RegisterCollisionCallbacks();
2304         } else {
2305                 Py_DECREF(self->m_collisionCallbacks);
2306         }
2307
2308         Py_INCREF(value);
2309
2310
2311         self->m_collisionCallbacks = value;
2312
2313         return PY_SET_ATTR_SUCCESS;
2314 }
2315
2316 PyObject *KX_GameObject::pyattr_get_collisionGroup(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2317 {
2318         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2319         return PyLong_FromLong(self->GetUserCollisionGroup());
2320 }
2321
2322 int KX_GameObject::pyattr_set_collisionGroup(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
2323 {
2324         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2325         int val = PyLong_AsLong(value);
2326
2327         if (val == -1 && PyErr_Occurred()) {
2328                 PyErr_SetString(PyExc_TypeError, "gameOb.collisionGroup = int: KX_GameObject, expected an int bit field");
2329                 return PY_SET_ATTR_FAIL;
2330         }
2331
2332         if (val < 0 || val > USHRT_MAX) {
2333                 PyErr_Format(PyExc_AttributeError, "gameOb.collisionGroup = int: KX_GameObject, expected a int bit field between 0 and %i", USHRT_MAX);
2334                 return PY_SET_ATTR_FAIL;
2335         }
2336
2337         self->SetUserCollisionGroup(val);
2338         return PY_SET_ATTR_SUCCESS;
2339 }
2340
2341 PyObject *KX_GameObject::pyattr_get_collisionMask(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2342 {
2343         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2344         return PyLong_FromLong(self->GetUserCollisionMask());
2345 }
2346
2347 int KX_GameObject::pyattr_set_collisionMask(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
2348 {
2349         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2350         int val = PyLong_AsLong(value);
2351
2352         if (val == -1 && PyErr_Occurred()) {
2353                 PyErr_SetString(PyExc_TypeError, "gameOb.collisionMask = int: KX_GameObject, expected an int bit field");
2354                 return PY_SET_ATTR_FAIL;
2355         }
2356
2357         if (val < 0 || val > USHRT_MAX) {
2358                 PyErr_Format(PyExc_AttributeError, "gameOb.collisionMask = int: KX_GameObject, expected a int bit field between 0 and %i", USHRT_MAX);
2359                 return PY_SET_ATTR_FAIL;
2360         }
2361
2362         self->SetUserCollisionMask(val);
2363         return PY_SET_ATTR_SUCCESS;
2364 }
2365
2366 PyObject* KX_GameObject::pyattr_get_scene(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2367 {
2368         KX_GameObject *self = static_cast<KX_GameObject*>(self_v);
2369         KX_Scene *scene = self->GetScene();
2370         if (scene) {
2371                 return scene->GetProxy();
2372         }
2373         Py_RETURN_NONE;
2374 }
2375
2376 PyObject *KX_GameObject::pyattr_get_group_object(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2377 {
2378         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2379         KX_GameObject* pivot = self->GetDupliGroupObject();
2380         if (pivot) {
2381                 return pivot->GetProxy();
2382         }
2383         Py_RETURN_NONE;
2384 }
2385
2386 PyObject *KX_GameObject::pyattr_get_life(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2387 {
2388         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2389
2390         CValue *life = self->GetProperty("::timebomb");
2391         if (life)
2392                 // this convert the timebomb seconds to frames, hard coded 50.0 (assuming 50fps)
2393                 // value hardcoded in KX_Scene::AddReplicaObject()
2394                 return PyFloat_FromDouble(life->GetNumber() * 50.0);
2395         else
2396                 Py_RETURN_NONE;
2397 }
2398
2399 PyObject *KX_GameObject::pyattr_get_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2400 {
2401         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2402         PHY_IPhysicsController *spc = self->GetPhysicsController();
2403         return PyFloat_FromDouble(spc ? spc->GetMass() : 0.0);
2404 }
2405
2406 int KX_GameObject::pyattr_set_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
2407 {
2408         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2409         PHY_IPhysicsController *spc = self->GetPhysicsController();
2410         MT_Scalar val = PyFloat_AsDouble(value);
2411         if (val < 0.0) { /* also accounts for non float */
2412                 PyErr_SetString(PyExc_AttributeError, "gameOb.mass = float: KX_GameObject, expected a float zero or above");
2413                 return PY_SET_ATTR_FAIL;
2414         }
2415
2416         if (spc)
2417                 spc->SetMass(val);
2418
2419         return PY_SET_ATTR_SUCCESS;
2420 }
2421
2422 PyObject *KX_GameObject::pyattr_get_is_suspend_dynamics(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2423 {
2424         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2425
2426         // Only objects with a physics controller can be suspended
2427         if (!self->GetPhysicsController()) {
2428                 PyErr_SetString(PyExc_AttributeError, "This object has not Physics Controller");
2429                 return NULL;
2430         }
2431
2432         return PyBool_FromLong(self->IsDynamicsSuspended());
2433 }
2434
2435 PyObject *KX_GameObject::pyattr_get_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2436 {
2437         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2438         PHY_IPhysicsController *spc = self->GetPhysicsController();
2439         return PyFloat_FromDouble(spc ? spc->GetLinVelocityMin() : 0.0f);
2440 }
2441
2442 int KX_GameObject::pyattr_set_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
2443 {
2444         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2445         PHY_IPhysicsController *spc = self->GetPhysicsController();
2446         MT_Scalar val = PyFloat_AsDouble(value);
2447         if (val < 0.0) { /* also accounts for non float */
2448                 PyErr_SetString(PyExc_AttributeError, "gameOb.linVelocityMin = float: KX_GameObject, expected a float zero or above");
2449                 return PY_SET_ATTR_FAIL;
2450         }
2451
2452         if (spc)
2453                 spc->SetLinVelocityMin(val);
2454
2455         return PY_SET_ATTR_SUCCESS;
2456 }
2457
2458 PyObject *KX_GameObject::pyattr_get_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2459 {
2460         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2461         PHY_IPhysicsController *spc = self->GetPhysicsController();
2462         return PyFloat_FromDouble(spc ? spc->GetLinVelocityMax() : 0.0f);
2463 }
2464
2465 int KX_GameObject::pyattr_set_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
2466 {
2467         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2468         PHY_IPhysicsController *spc = self->GetPhysicsController();
2469         MT_Scalar val = PyFloat_AsDouble(value);
2470         if (val < 0.0) { /* also accounts for non float */
2471                 PyErr_SetString(PyExc_AttributeError, "gameOb.linVelocityMax = float: KX_GameObject, expected a float zero or above");
2472                 return PY_SET_ATTR_FAIL;
2473         }
2474
2475         if (spc)
2476                 spc->SetLinVelocityMax(val);
2477
2478         return PY_SET_ATTR_SUCCESS;
2479 }
2480
2481
2482 PyObject *KX_GameObject::pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2483 {
2484         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2485         return PyBool_FromLong(self->GetVisible());
2486 }
2487
2488 int KX_GameObject::pyattr_set_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
2489 {
2490         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2491         int param = PyObject_IsTrue( value );
2492         if (param == -1) {
2493                 PyErr_SetString(PyExc_AttributeError, "gameOb.visible = bool: KX_GameObject, expected True or False");
2494                 return PY_SET_ATTR_FAIL;
2495         }
2496
2497         self->SetVisible(param, false);
2498         self->UpdateBuckets(false);
2499         return PY_SET_ATTR_SUCCESS;
2500 }
2501
2502 PyObject *KX_GameObject::pyattr_get_record_animation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2503 {
2504         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2505         return PyBool_FromLong(self->IsRecordAnimation());
2506 }
2507
2508 int KX_GameObject::pyattr_set_record_animation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
2509 {
2510         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2511         int param = PyObject_IsTrue(value);
2512         if (param == -1) {
2513                 PyErr_SetString(PyExc_AttributeError, "gameOb.record_animation = bool: KX_GameObject, expected boolean");
2514                 return PY_SET_ATTR_FAIL;
2515         }
2516
2517         self->SetRecordAnimation(param);
2518
2519         return PY_SET_ATTR_SUCCESS;
2520 }
2521
2522
2523
2524 PyObject *KX_GameObject::pyattr_get_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2525 {
2526 #ifdef USE_MATHUTILS
2527         return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_GLOBAL);
2528 #else
2529         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2530         return PyObjectFrom(self->NodeGetWorldPosition());
2531 #endif
2532 }
2533
2534 int KX_GameObject::pyattr_set_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
2535 {
2536         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2537         MT_Point3 pos;
2538         if (!PyVecTo(value, pos))
2539                 return PY_SET_ATTR_FAIL;
2540         
2541         self->NodeSetWorldPosition(pos);
2542         self->NodeUpdateGS(0.f);
2543         return PY_SET_ATTR_SUCCESS;
2544 }
2545
2546 PyObject *KX_GameObject::pyattr_get_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2547 {
2548 #ifdef USE_MATHUTILS
2549         return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_LOCAL);
2550 #else
2551         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2552         return PyObjectFrom(self->NodeGetLocalPosition());
2553 #endif
2554 }
2555
2556 int KX_GameObject::pyattr_set_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
2557 {
2558         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2559         MT_Point3 pos;
2560         if (!PyVecTo(value, pos))
2561                 return PY_SET_ATTR_FAIL;
2562         
2563         self->NodeSetLocalPosition(pos);
2564         self->NodeUpdateGS(0.f);
2565         return PY_SET_ATTR_SUCCESS;
2566 }
2567
2568 PyObject *KX_GameObject::pyattr_get_localInertia(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2569 {
2570 #ifdef USE_MATHUTILS
2571         return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_INERTIA_LOCAL);
2572 #else
2573         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2574         if (self->GetPhysicsController1())
2575                 return PyObjectFrom(self->GetPhysicsController1()->GetLocalInertia());
2576         return Py_BuildValue("fff", 0.0f, 0.0f, 0.0f);
2577 #endif
2578 }
2579
2580 PyObject *KX_GameObject::pyattr_get_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2581 {
2582 #ifdef USE_MATHUTILS
2583         return Matrix_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, 3, mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_GLOBAL);
2584 #else
2585         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2586         return PyObjectFrom(self->NodeGetWorldOrientation());
2587 #endif
2588 }
2589
2590 int KX_GameObject::pyattr_set_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
2591 {
2592         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2593         
2594         /* if value is not a sequence PyOrientationTo makes an error */
2595         MT_Matrix3x3 rot;
2596         if (!PyOrientationTo(value, rot, "gameOb.worldOrientation = sequence: KX_GameObject, "))
2597                 return PY_SET_ATTR_FAIL;
2598
2599         self->NodeSetGlobalOrientation(rot);
2600         
2601         self->NodeUpdateGS(0.f);
2602         return PY_SET_ATTR_SUCCESS;
2603 }
2604
2605 PyObject *KX_GameObject::pyattr_get_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2606 {
2607 #ifdef USE_MATHUTILS
2608         return Matrix_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, 3, mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_LOCAL);
2609 #else
2610         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2611         return PyObjectFrom(self->NodeGetLocalOrientation());
2612 #endif
2613 }
2614
2615 int KX_GameObject::pyattr_set_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
2616 {
2617         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2618         
2619         /* if value is not a sequence PyOrientationTo makes an error */
2620         MT_Matrix3x3 rot;
2621         if (!PyOrientationTo(value, rot, "gameOb.localOrientation = sequence: KX_GameObject, "))
2622                 return PY_SET_ATTR_FAIL;
2623
2624         self->NodeSetLocalOrientation(rot);
2625         self->NodeUpdateGS(0.f);
2626         return PY_SET_ATTR_SUCCESS;
2627 }
2628
2629 PyObject *KX_GameObject::pyattr_get_worldScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2630 {
2631 #ifdef USE_MATHUTILS
2632         return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_GLOBAL);
2633 #else
2634         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2635         return PyObjectFrom(self->NodeGetWorldScaling());
2636 #endif
2637 }
2638
2639 int KX_GameObject::pyattr_set_worldScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
2640 {
2641         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2642         MT_Vector3 scale;
2643         if (!PyVecTo(value, scale))
2644                 return PY_SET_ATTR_FAIL;
2645
2646         self->NodeSetWorldScale(scale);
2647         self->NodeUpdateGS(0.f);
2648         return PY_SET_ATTR_SUCCESS;
2649 }
2650
2651 PyObject *KX_GameObject::pyattr_get_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2652 {
2653 #ifdef USE_MATHUTILS
2654         return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_LOCAL);
2655 #else
2656         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2657         return PyObjectFrom(self->NodeGetLocalScaling());
2658 #endif
2659 }
2660
2661 int KX_GameObject::pyattr_set_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
2662 {
2663         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2664         MT_Vector3 scale;
2665         if (!PyVecTo(value, scale))
2666                 return PY_SET_ATTR_FAIL;
2667
2668         self->NodeSetLocalScale(scale);
2669         self->NodeUpdateGS(0.f);
2670         return PY_SET_ATTR_SUCCESS;
2671 }
2672
2673 PyObject *KX_GameObject::pyattr_get_localTransform(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2674 {
2675         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2676
2677         double mat[16];
2678
2679         MT_Transform trans;
2680         
2681         trans.setOrigin(self->GetSGNode()->GetLocalPosition());
2682         trans.setBasis(self->GetSGNode()->GetLocalOrientation());
2683         
2684         MT_Vector3 scaling = self->GetSGNode()->GetLocalScale();
2685         trans.scale(scaling[0], scaling[1], scaling[2]);
2686
2687         trans.getValue(mat);
2688
2689         return PyObjectFrom(MT_Matrix4x4(mat));
2690 }
2691
2692 int KX_GameObject::pyattr_set_localTransform(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
2693 {
2694         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2695         MT_Matrix4x4 temp;
2696         if (!PyMatTo(value, temp))
2697                 return PY_SET_ATTR_FAIL;
2698
2699         float transform[4][4];
2700         float loc[3], size[3];
2701         float rot[3][3];
2702         MT_Matrix3x3 orientation;
2703
2704         temp.getValue(*transform);
2705         mat4_to_loc_rot_size(loc, rot, size, transform);
2706
2707         self->NodeSetLocalPosition(MT_Point3(loc));
2708
2709         //MT_Matrix3x3's constructor expects a 4x4 matrix
2710         orientation = MT_Matrix3x3();
2711         orientation.setValue3x3(*rot);
2712         self->NodeSetLocalOrientation(orientation);
2713
2714         self->NodeSetLocalScale(MT_Vector3(size));
2715
2716         return PY_SET_ATTR_SUCCESS;
2717 }
2718
2719 PyObject *KX_GameObject::pyattr_get_worldTransform(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2720 {
2721         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2722
2723         return PyObjectFrom(MT_Matrix4x4(self->GetOpenGLMatrix()));
2724 }
2725
2726 int KX_GameObject::pyattr_set_worldTransform(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
2727 {
2728         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2729         MT_Matrix4x4 temp;
2730         if (!PyMatTo(value, temp))
2731                 return PY_SET_ATTR_FAIL;
2732
2733         float transform[4][4];
2734         float loc[3], size[3];
2735         float rot[3][3];
2736         MT_Matrix3x3 orientation;
2737
2738         temp.getValue(*transform);
2739         mat4_to_loc_rot_size(loc, rot, size, transform);
2740
2741         self->NodeSetWorldPosition(MT_Point3(loc));
2742
2743         //MT_Matrix3x3's constructor expects a 4x4 matrix
2744         orientation = MT_Matrix3x3();
2745         orientation.setValue3x3(*rot);
2746         self->NodeSetGlobalOrientation(orientation);
2747
2748         self->NodeSetWorldScale(MT_Vector3(size));
2749
2750         return PY_SET_ATTR_SUCCESS;
2751 }
2752
2753 PyObject *KX_GameObject::pyattr_get_worldLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2754 {
2755 #ifdef USE_MATHUTILS
2756         return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_LINVEL_GLOBAL);
2757 #else
2758         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2759         return PyObjectFrom(GetLinearVelocity(false));
2760 #endif
2761 }
2762
2763 int KX_GameObject::pyattr_set_worldLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
2764 {
2765         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2766         MT_Vector3 velocity;
2767         if (!PyVecTo(value, velocity))
2768                 return PY_SET_ATTR_FAIL;
2769
2770         self->setLinearVelocity(velocity, false);
2771
2772         return PY_SET_ATTR_SUCCESS;
2773 }
2774
2775 PyObject *KX_GameObject::pyattr_get_localLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2776 {
2777 #ifdef USE_MATHUTILS
2778         return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_LINVEL_LOCAL);
2779 #else
2780         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2781         return PyObjectFrom(GetLinearVelocity(true));
2782 #endif
2783 }
2784
2785 int KX_GameObject::pyattr_set_localLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
2786 {
2787         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2788         MT_Vector3 velocity;
2789         if (!PyVecTo(value, velocity))
2790                 return PY_SET_ATTR_FAIL;
2791
2792         self->setLinearVelocity(velocity, true);
2793
2794         return PY_SET_ATTR_SUCCESS;
2795 }
2796
2797 PyObject *KX_GameObject::pyattr_get_worldAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2798 {
2799 #ifdef USE_MATHUTILS
2800         return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_ANGVEL_GLOBAL);
2801 #else
2802         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2803         return PyObjectFrom(GetAngularVelocity(false));
2804 #endif
2805 }
2806
2807 int KX_GameObject::pyattr_set_worldAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
2808 {
2809         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2810         MT_Vector3 velocity;
2811         if (!PyVecTo(value, velocity))
2812                 return PY_SET_ATTR_FAIL;
2813
2814         self->setAngularVelocity(velocity, false);
2815
2816         return PY_SET_ATTR_SUCCESS;
2817 }
2818
2819 PyObject *KX_GameObject::pyattr_get_localAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2820 {
2821 #ifdef USE_MATHUTILS
2822         return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_ANGVEL_LOCAL);
2823 #else
2824         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2825         return PyObjectFrom(GetAngularVelocity(true));
2826 #endif
2827 }
2828
2829 int KX_GameObject::pyattr_set_localAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
2830 {
2831         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2832         MT_Vector3 velocity;
2833         if (!PyVecTo(value, velocity))
2834                 return PY_SET_ATTR_FAIL;
2835
2836         self->setAngularVelocity(velocity, true);
2837
2838         return PY_SET_ATTR_SUCCESS;
2839 }
2840
2841 PyObject *KX_GameObject::pyattr_get_linearDamping(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2842 {
2843         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2844         return PyFloat_FromDouble(self->getLinearDamping());
2845 }
2846
2847 int KX_GameObject::pyattr_set_linearDamping(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
2848 {
2849         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2850         float val = PyFloat_AsDouble(value);
2851         self->setLinearDamping(val);
2852         return PY_SET_ATTR_SUCCESS;
2853 }
2854
2855 PyObject *KX_GameObject::pyattr_get_angularDamping(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2856 {
2857         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2858         return PyFloat_FromDouble(self->getAngularDamping());
2859 }
2860
2861 int KX_GameObject::pyattr_set_angularDamping(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
2862 {
2863         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2864         float val = PyFloat_AsDouble(value);
2865         self->setAngularDamping(val);
2866         return PY_SET_ATTR_SUCCESS;
2867 }
2868
2869
2870 PyObject *KX_GameObject::pyattr_get_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2871 {
2872         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2873         SG_Node* sg_parent;
2874         if (self->GetSGNode() && (sg_parent = self->GetSGNode()->GetSGParent()) != NULL && sg_parent->IsSlowParent()) {
2875                 return PyFloat_FromDouble(static_cast<KX_SlowParentRelation *>(sg_parent->GetParentRelation())->GetTimeOffset());
2876         } else {
2877                 return PyFloat_FromDouble(0.0);
2878         }
2879 }
2880
2881 int KX_GameObject::pyattr_set_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
2882 {
2883         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2884         if (self->GetSGNode()) {
2885                 MT_Scalar val = PyFloat_AsDouble(value);
2886                 SG_Node *sg_parent= self->GetSGNode()->GetSGParent();
2887                 if (val < 0.0) { /* also accounts for non float */
2888                         PyErr_SetString(PyExc_AttributeError, "gameOb.timeOffset = float: KX_GameObject, expected a float zero or above");
2889                         return PY_SET_ATTR_FAIL;
2890                 }
2891                 if (sg_parent && sg_parent->IsSlowParent())
2892                         static_cast<KX_SlowParentRelation *>(sg_parent->GetParentRelation())->SetTimeOffset(val);
2893         }
2894         return PY_SET_ATTR_SUCCESS;
2895 }
2896
2897 PyObject *KX_GameObject::pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2898 {
2899         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2900         int state = 0;
2901         state |= self->GetState();
2902         return PyLong_FromLong(state);
2903 }
2904
2905 int KX_GameObject::pyattr_set_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
2906 {
2907         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2908         int state_i = PyLong_AsLong(value);
2909         unsigned int state = 0;
2910         
2911         if (state_i == -1 && PyErr_Occurred()) {
2912                 PyErr_SetString(PyExc_TypeError, "gameOb.state = int: KX_GameObject, expected an int bit field");
2913                 return PY_SET_ATTR_FAIL;
2914         }
2915         
2916         state |= state_i;
2917         if ((state & ((1<<30)-1)) == 0) {
2918                 PyErr_SetString(PyExc_AttributeError, "gameOb.state = int: KX_GameObject, state bitfield was not between 0 and 30 (1<<0 and 1<<29)");
2919                 return PY_SET_ATTR_FAIL;
2920         }
2921         self->SetState(state);
2922         return PY_SET_ATTR_SUCCESS;
2923 }
2924
2925 PyObject *KX_GameObject::pyattr_get_meshes(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2926 {
2927         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2928         PyObject *meshes= PyList_New(self->m_meshes.size());
2929         int i;
2930         
2931         for (i=0; i < (int)self->m_meshes.size(); i++)
2932         {
2933                 KX_MeshProxy* meshproxy = new KX_MeshProxy(self->m_meshes[i]);
2934                 PyList_SET_ITEM(meshes, i, meshproxy->NewProxy(true));
2935         }
2936         
2937         return meshes;
2938 }
2939
2940 PyObject *KX_GameObject::pyattr_get_obcolor(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2941 {
2942 #ifdef USE_MATHUTILS
2943         return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 4, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_OBJECT_COLOR);
2944 #else
2945         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2946         return PyObjectFrom(self->GetObjectColor());
2947 #endif
2948 }
2949
2950 int KX_GameObject::pyattr_set_obcolor(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
2951 {
2952         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2953         MT_Vector4 obcolor;
2954         if (!PyVecTo(value, obcolor))
2955                 return PY_SET_ATTR_FAIL;
2956
2957         self->SetObjectColor(obcolor);
2958         return PY_SET_ATTR_SUCCESS;
2959 }
2960
2961 /* These are experimental! */
2962 PyObject *KX_GameObject::pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2963 {
2964         return KX_PythonSeq_CreatePyObject((static_cast<KX_GameObject*>(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_SENSORS);
2965 }
2966
2967 PyObject *KX_GameObject::pyattr_get_controllers(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2968 {
2969         return KX_PythonSeq_CreatePyObject((static_cast<KX_GameObject*>(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_CONTROLLERS);
2970 }
2971
2972 PyObject *KX_GameObject::pyattr_get_actuators(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2973 {
2974         return KX_PythonSeq_CreatePyObject((static_cast<KX_GameObject*>(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_ACTUATORS);
2975 }
2976 /* End experimental */
2977
2978 PyObject *KX_GameObject::pyattr_get_children(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2979 {
2980         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2981         return self->GetChildren()->NewProxy(true);
2982 }
2983
2984 PyObject *KX_GameObject::pyattr_get_children_recursive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2985 {
2986         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2987         return self->GetChildrenRecursive()->NewProxy(true);
2988 }
2989
2990 PyObject *KX_GameObject::pyattr_get_attrDict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2991 {
2992         KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
2993         
2994         if (self->m_attr_dict==NULL)
2995                 self->m_attr_dict= PyDict_New();
2996         
2997         Py_INCREF(self->m_attr_dict);
2998         return self->m_attr_dict;
2999 }
3000
3001 PyObject *KX_GameObject::pyattr_get_debug(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
3002 {
3003         KX_Scene *scene = KX_GetActiveScene();
3004         KX_GameObject *self = static_cast<KX_GameObject*>(self_v);
3005
3006         return PyBool_FromLong(scene->ObjectInDebugList(self));
3007 }
3008
3009 int KX_GameObject::pyattr_set_debug(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
3010 {
3011         KX_GameObject *self = static_cast<KX_GameObject*>(self_v);
3012         int param = PyObject_IsTrue(value);
3013
3014         if (param == -1) {
3015                 PyErr_SetString(PyExc_AttributeError, "gameOb.debug = bool: KX_GameObject, expected True or False");
3016                 return PY_SET_ATTR_FAIL;
3017         }
3018
3019         self->SetUseDebugProperties(param, false);
3020
3021         return PY_SET_ATTR_SUCCESS;
3022 }
3023
3024 PyObject *KX_GameObject::pyattr_get_debugRecursive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
3025 {
3026         KX_Scene *scene = KX_GetActiveScene();
3027         KX_GameObject *self = static_cast<KX_GameObject*>(self_v);
3028
3029         return PyBool_FromLong(scene->ObjectInDebugList(self));
3030 }
3031
3032 int KX_GameObject::pyattr_set_debugRecursive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
3033 {
3034         KX_GameObject *self = static_cast<KX_GameObject*>(self_v);
3035         int param = PyObject_IsTrue(value);
3036
3037         if (param == -1) {
3038                 PyErr_SetString(PyExc_AttributeError, "gameOb.debugRecursive = bool: KX_GameObject, expected True or False");
3039                 return PY_SET_ATTR_FAIL;
3040         }
3041
3042         self->SetUseDebugProperties(param, true);
3043
3044         return PY_SET_ATTR_SUCCESS;
3045 }
3046
3047 PyObject *KX_GameObject::PyApplyForce(PyObject *args)
3048 {
3049         int local = 0;
3050         PyObject *pyvect;
3051
3052         if (PyArg_ParseTuple(args, "O|i:applyForce", &pyvect, &local)) {
3053                 MT_Vector3 force;
3054                 if (PyVecTo(pyvect, force)) {
3055                         ApplyForce(force, (local!=0));
3056                         Py_RETURN_NONE;
3057                 }
3058         }
3059         return NULL;
3060 }
3061
3062 PyObject *KX_GameObject::PyApplyTorque(PyObject *args)
3063 {
3064         int local = 0;
3065         PyObject *pyvect;
3066
3067         if (PyArg_ParseTuple(args, "O|i:applyTorque", &pyvect, &local)) {
3068                 MT_Vector3 torque;
3069                 if (PyVecTo(pyvect, torque)) {
3070                         ApplyTorque(torque, (local!=0));
3071                         Py_RETURN_NONE;
3072                 }
3073         }
3074         return NULL;
3075 }
3076
3077 PyObject *KX_GameObject::PyApplyRotation(PyObject *args)
3078 {
3079         int local = 0;
3080         PyObject *pyvect;
3081
3082         if (PyArg_ParseTuple(args, "O|i:applyRotation", &pyvect, &local)) {
3083                 MT_Vector3 rotation;
3084                 if (PyVecTo(pyvect, rotation)) {
3085                         ApplyRotation(rotation, (local!=0));
3086                         Py_RETURN_NONE;
3087                 }
3088         }
3089         return NULL;
3090 }
3091
3092 PyObject *KX_GameObject::PyApplyMovement(PyObject *args)
3093 {
3094         int local = 0;
3095         PyObject *pyvect;
3096
3097         if (PyArg_ParseTuple(args, "O|i:applyMovement", &pyvect, &local)) {
3098                 MT_Vector3 movement;
3099                 if (PyVecTo(pyvect, movement)) {
3100                         ApplyMovement(movement, (local!=0));
3101                         Py_RETURN_NONE;
3102                 }
3103         }
3104         return NULL;
3105 }
3106
3107 PyObject *KX_GameObject::PyGetLinearVelocity(PyObject *args)
3108 {
3109         // only can get the velocity if we have a physics object connected to us...
3110         int local = 0;
3111         if (PyArg_ParseTuple(args,"|i:getLinearVelocity",&local))
3112         {
3113                 return PyObjectFrom(GetLinearVelocity((local!=0)));
3114         }
3115         else
3116         {
3117                 return NULL;
3118         }
3119 }
3120
3121 PyObject *KX_GameObject::PySetLinearVelocity(PyObject *args)
3122 {
3123         int local = 0;
3124         PyObject *pyvect;
3125         
3126         if (PyArg_ParseTuple(args,"O|i:setLinearVelocity",&pyvect,&local)) {
3127                 MT_Vector3 velocity;
3128                 if (PyVecTo(pyvect, velocity)) {
3129                         setLinearVelocity(velocity, (local!=0));
3130                         Py_RETURN_NONE;
3131                 }
3132         }
3133         return NULL;
3134 }
3135
3136 PyObject *KX_GameObject::PyGetAngularVelocity(PyObject *args)
3137 {
3138         // only can get the velocity if we have a physics object connected to us...
3139         int local = 0;
3140         if (PyArg_ParseTuple(args,"|i:getAngularVelocity",&local))
3141         {
3142                 return PyObjectFrom(GetAngularVelocity((local!=0)));
3143         }
3144         else
3145         {
3146                 return NULL;
3147         }
3148 }
3149
3150 PyObject *KX_GameObject::PySetAngularVelocity(PyObject *args)
3151 {
3152         int local = 0;
3153         PyObject *pyvect;
3154         
3155         if (PyArg_ParseTuple(args,"O|i:setAngularVelocity",&pyvect,&local)) {
3156                 MT_Vector3 velocity;
3157                 if (PyVecTo(pyvect, velocity)) {
3158                         setAngularVelocity(velocity, (local!=0));
3159                         Py_RETURN_NONE;
3160                 }
3161         }
3162         return NULL;
3163 }
3164
3165 PyObject *KX_GameObject::PySetDamping(PyObject *args)
3166 {
3167         float linear;
3168         float angular;
3169
3170         if (!PyArg_ParseTuple(args,"ff|i:setDamping", &linear, &angular))
3171                 return NULL;
3172
3173         setDamping(linear, angular);
3174         Py_RETURN_NONE;
3175 }
3176
3177 PyObject *KX_GameObject::PySetVisible(PyObject *args)
3178 {
3179         int visible, recursive = 0;
3180         if (!PyArg_ParseTuple(args,"i|i:setVisible",&visible, &recursive))
3181                 return NULL;
3182         
3183         SetVisible(visible ? true:false, recursive ? true:false);
3184         UpdateBuckets(recursive ? true:false);
3185         Py_RETURN_NONE;
3186         
3187 }
3188
3189 PyObject *KX_GameObject::PySetOcclusion(PyObject *args)
3190 {
3191         int occlusion, recursive = 0;
3192         if (!PyArg_ParseTuple(args,"i|i:setOcclusion",&occlusion, &recursive))
3193                 return NULL;
3194         
3195         SetOccluder(occlusion ? true:false, recursive ? true:false);
3196         Py_RETURN_NONE;
3197 }
3198
3199 PyObject *KX_GameObject::PyGetVelocity(PyObject *args)
3200 {
3201         // only can get the velocity if we have a physics object connected to us...
3202         MT_Point3 point(0.0,0.0,0.0);
3203         PyObject *pypos = NULL;
3204         
3205         if (!PyArg_ParseTuple(args, "|O:getVelocity", &pypos) || (pypos && !PyVecTo(pypos, point)))
3206                 return NULL;
3207
3208         return PyObjectFrom(GetVelocity(point));
3209 }
3210
3211 PyObject *KX_GameObject::PyGetReactionForce()
3212 {
3213         // only can get the velocity if we have a physics object connected to us...
3214         
3215         // XXX - Currently not working with bullet intergration, see KX_BulletPhysicsController.cpp's getReactionForce
3216 #if 0
3217         if (GetPhysicsController1())
3218                 return PyObjectFrom(GetPhysicsController1()->getReactionForce());
3219         return PyObjectFrom(dummy_point);
3220 #endif
3221         
3222         return Py_BuildValue("fff", 0.0, 0.0, 0.0);
3223         
3224 }
3225
3226
3227
3228 PyObject *KX_GameObject::PyEnableRigidBody()
3229 {
3230         if (GetPhysicsController())
3231                 GetPhysicsController()->SetRigidBody(true);
3232
3233         Py_RETURN_NONE;
3234 }
3235
3236
3237
3238 PyObject *KX_GameObject::PyDisableRigidBody()
3239 {
3240         if (GetPhysicsController())
3241                 GetPhysicsController()->SetRigidBody(false);
3242
3243         Py_RETURN_NONE;
3244 }
3245
3246
3247 PyObject *KX_GameObject::PySetParent(PyObject *args)
3248 {
3249         KX_Scene *scene = KX_GetActiveScene();
3250         PyObject *pyobj;
3251         KX_GameObject *obj;
3252         int addToCompound=1, ghost=1;
3253         
3254         if (!PyArg_ParseTuple(args,"O|ii:setParent", &pyobj, &addToCompound, &ghost)) {
3255                 return NULL; // Python sets a simple error
3256         }
3257         if (!ConvertPythonToGameObject(pyobj, &obj, true, "gameOb.setParent(obj): KX_GameObject"))
3258                 return NULL;
3259         if (obj)
3260                 this->SetParent(scene, obj, addToCompound, ghost);
3261         Py_RETURN_NONE;
3262 }
3263
3264 PyObject *KX_GameObject::PyRemoveParent()
3265 {
3266         KX_Scene *scene = KX_GetActiveScene();
3267         
3268         this->RemoveParent(scene);
3269         Py_RETURN_NONE;
3270 }
3271
3272
3273 PyObject *KX_GameObject::PySetCollisionMargin(PyObject *value)
3274 {
3275         float collisionMargin = PyFloat_AsDouble(value);
3276         
3277         if (collisionMargin==-1 && PyErr_Occurred()) {
3278                 PyErr_SetString(PyExc_TypeError, "expected a float");
3279                 return NULL;
3280         }
3281         
3282         if (m_pPhysicsController)
3283         {
3284                 m_pPhysicsController->SetMargin(collisionMargin);
3285                 Py_RETURN_NONE;
3286         }
3287         PyErr_SetString(PyExc_RuntimeError, "This object has no physics controller");
3288         return NULL;
3289 }
3290
3291
3292
3293 PyObject *KX_GameObject::PyApplyImpulse(PyObject *args)
3294 {
3295         PyObject *pyattach;
3296         PyObject *pyimpulse;
3297         int local = 0;
3298         
3299         if (!m_pPhysicsController)      {
3300                 PyErr_SetString(PyExc_RuntimeError, "This object has no physics controller");
3301                 return NULL;
3302         }
3303         
3304         if (PyArg_ParseTuple(args, "OO|i:applyImpulse", &pyattach, &pyimpulse, &local))
3305         {
3306                 MT_Point3  attach;
3307                 MT_Vector3 impulse;
3308                 if (PyVecTo(pyattach, attach) && PyVecTo(pyimpulse, impulse))
3309                 {
3310                         m_pPhysicsController->ApplyImpulse(attach, impulse, (local!=0));
3311                         Py_RETURN_NONE;
3312                 }
3313
3314         }
3315         
3316         return NULL;
3317 }
3318
3319
3320
3321 PyObject *KX_GameObject::PySuspendDynamics(PyObject *args)
3322 {
3323         bool ghost = false;
3324
3325         if (!PyArg_ParseTuple(args, "|b", &ghost))
3326                 return NULL;
3327
3328         if (GetPhysicsController())
3329                 GetPhysicsController()->SuspendDynamics(ghost);
3330
3331         Py_RETURN_NONE;
3332 }
3333
3334
3335
3336 PyObject *KX_GameObject::PyRestoreDynamics()
3337 {
3338         if (GetPhysicsController())
3339                 GetPhysicsController()->RestoreDynamics();
3340         Py_RETURN_NONE;
3341 }
3342
3343
3344 PyObject *KX_GameObject::PyAlignAxisToVect(PyObject *args)
3345 {
3346         PyObject *pyvect;
3347         int axis = 2; //z axis is the default
3348         float fac = 1.0f;
3349         
3350         if (PyArg_ParseTuple(args,"O|if:alignAxisToVect",&pyvect,&axis, &fac))
3351         {
3352                 MT_Vector3 vect;
3353                 if (PyVecTo(pyvect, vect)) {
3354                         if (fac > 0.0f) {
3355                                 if (fac> 1.0f) fac = 1.0f;
3356
3357                                 AlignAxisToVect(vect, axis, fac);
3358                                 NodeUpdateGS(0.f);
3359                         }
3360                         Py_RETURN_NONE;
3361                 }
3362         }
3363         return NULL;
3364 }
3365
3366 PyObject *KX_GameObject::PyGetAxisVect(PyObject *value)
3367 {
3368         MT_Vector3 vect;
3369         if (PyVecTo(value, vect))
3370         {
3371                 return PyObjectFrom(NodeGetWorldOrientation() * vect);
3372         }
3373         return NULL;
3374 }
3375
3376
3377 PyObject *KX_GameObject::PyGetPhysicsId()
3378 {
3379         PHY_IPhysicsController* ctrl = GetPhysicsController();
3380         unsigned long long physid = 0;
3381         if (ctrl)
3382         {
3383                 physid = (unsigned long long)ctrl;
3384         }
3385         return PyLong_FromUnsignedLongLong(physid);
3386 }
3387
3388 PyObject *KX_GameObject::PyGetPropertyNames()
3389 {
3390         PyObject *list= ConvertKeysToPython();
3391         
3392         if (m_attr_dict) {
3393                 PyObject *key, *value;
3394                 Py_ssize_t pos = 0;
3395
3396                 while (PyDict_Next(m_attr_dict, &pos, &key, &value)) {
3397                         PyList_Append(list, key);
3398                 }
3399         }
3400         return list;
3401 }
3402
3403 KX_PYMETHODDEF_DOC_O(KX_GameObject, getDistanceTo,
3404 "getDistanceTo(other): get distance to another point/KX_GameObject")
3405 {
3406         MT_Point3 b;
3407         if (PyVecTo(value, b))
3408         {
3409                 return PyFloat_FromDouble(NodeGetWorldPosition().distance(b));
3410         }
3411         PyErr_Clear();
3412         
3413         KX_GameObject *other;
3414         if (ConvertPythonToGameObject(value, &other, false, "gameOb.getDistanceTo(value): KX_GameObject"))
3415         {
3416                 return PyFloat_FromDouble(NodeGetWorldPosition().distance(other->NodeGetWorldPosition()));
3417         }