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