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