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