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