BGE bug #18168: Get local orientation of object using game engine python script syste...
[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_attrlist(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_attrlist) {
150                 PyDict_Clear(m_attrlist); /* incase of circular refs or other weired cases */
151                 Py_DECREF(m_attrlist);
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_attrlist)
343                 replica->m_attrlist= PyDict_Copy(m_attrlist);
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
1043
1044
1045 /* ------- python stuff ---------------------------------------------------*/
1046
1047 PyMethodDef KX_GameObject::Methods[] = {
1048         {"setWorldPosition", (PyCFunction) KX_GameObject::sPySetWorldPosition, METH_O},
1049         {"applyForce", (PyCFunction)    KX_GameObject::sPyApplyForce, METH_VARARGS},
1050         {"applyTorque", (PyCFunction)   KX_GameObject::sPyApplyTorque, METH_VARARGS},
1051         {"applyRotation", (PyCFunction) KX_GameObject::sPyApplyRotation, METH_VARARGS},
1052         {"applyMovement", (PyCFunction) KX_GameObject::sPyApplyMovement, METH_VARARGS},
1053         {"getLinearVelocity", (PyCFunction) KX_GameObject::sPyGetLinearVelocity, METH_VARARGS},
1054         {"setLinearVelocity", (PyCFunction) KX_GameObject::sPySetLinearVelocity, METH_VARARGS},
1055         {"getAngularVelocity", (PyCFunction) KX_GameObject::sPyGetAngularVelocity, METH_VARARGS},
1056         {"setAngularVelocity", (PyCFunction) KX_GameObject::sPySetAngularVelocity, METH_VARARGS},
1057         {"getVelocity", (PyCFunction) KX_GameObject::sPyGetVelocity, METH_VARARGS},
1058         {"getReactionForce", (PyCFunction) KX_GameObject::sPyGetReactionForce, METH_NOARGS},
1059         {"alignAxisToVect",(PyCFunction) KX_GameObject::sPyAlignAxisToVect, METH_VARARGS},
1060         {"getAxisVect",(PyCFunction) KX_GameObject::sPyGetAxisVect, METH_O},
1061         {"suspendDynamics", (PyCFunction)KX_GameObject::sPySuspendDynamics,METH_NOARGS},
1062         {"restoreDynamics", (PyCFunction)KX_GameObject::sPyRestoreDynamics,METH_NOARGS},
1063         {"enableRigidBody", (PyCFunction)KX_GameObject::sPyEnableRigidBody,METH_NOARGS},
1064         {"disableRigidBody", (PyCFunction)KX_GameObject::sPyDisableRigidBody,METH_NOARGS},
1065         {"applyImpulse", (PyCFunction) KX_GameObject::sPyApplyImpulse, METH_VARARGS},
1066         {"setCollisionMargin", (PyCFunction) KX_GameObject::sPySetCollisionMargin, METH_O},
1067         {"setParent", (PyCFunction)KX_GameObject::sPySetParent,METH_O},
1068         {"setVisible",(PyCFunction) KX_GameObject::sPySetVisible, METH_VARARGS},
1069         {"setOcclusion",(PyCFunction) KX_GameObject::sPySetOcclusion, METH_VARARGS},
1070         {"removeParent", (PyCFunction)KX_GameObject::sPyRemoveParent,METH_NOARGS},
1071         {"getChildren", (PyCFunction)KX_GameObject::sPyGetChildren,METH_NOARGS},
1072         {"getChildrenRecursive", (PyCFunction)KX_GameObject::sPyGetChildrenRecursive,METH_NOARGS},
1073         {"getPhysicsId", (PyCFunction)KX_GameObject::sPyGetPhysicsId,METH_NOARGS},
1074         {"getPropertyNames", (PyCFunction)KX_GameObject::sPyGetPropertyNames,METH_NOARGS},
1075         {"replaceMesh",(PyCFunction) KX_GameObject::sPyReplaceMesh, METH_O},
1076         {"endObject",(PyCFunction) KX_GameObject::sPyEndObject, METH_NOARGS},
1077         
1078         KX_PYMETHODTABLE(KX_GameObject, rayCastTo),
1079         KX_PYMETHODTABLE(KX_GameObject, rayCast),
1080         KX_PYMETHODTABLE_O(KX_GameObject, getDistanceTo),
1081         KX_PYMETHODTABLE_O(KX_GameObject, getVectTo),
1082         KX_PYMETHODTABLE(KX_GameObject, sendMessage),
1083
1084         // deprecated
1085         {"getPosition", (PyCFunction) KX_GameObject::sPyGetPosition, METH_NOARGS},
1086         {"setPosition", (PyCFunction) KX_GameObject::sPySetPosition, METH_O},
1087         {"getOrientation", (PyCFunction) KX_GameObject::sPyGetOrientation, METH_NOARGS},
1088         {"setOrientation", (PyCFunction) KX_GameObject::sPySetOrientation, METH_O},
1089         {"getState",(PyCFunction) KX_GameObject::sPyGetState, METH_NOARGS},
1090         {"setState",(PyCFunction) KX_GameObject::sPySetState, METH_O},
1091         {"getParent", (PyCFunction)KX_GameObject::sPyGetParent,METH_NOARGS},
1092         {"getVisible",(PyCFunction) KX_GameObject::sPyGetVisible, METH_NOARGS},
1093         {"getMass", (PyCFunction) KX_GameObject::sPyGetMass, METH_NOARGS},
1094         {"getMesh", (PyCFunction)KX_GameObject::sPyGetMesh,METH_VARARGS},
1095         {NULL,NULL} //Sentinel
1096 };
1097
1098 PyAttributeDef KX_GameObject::Attributes[] = {
1099         KX_PYATTRIBUTE_RO_FUNCTION("name",              KX_GameObject, pyattr_get_name),
1100         KX_PYATTRIBUTE_RO_FUNCTION("parent",    KX_GameObject, pyattr_get_parent),
1101         KX_PYATTRIBUTE_RW_FUNCTION("mass",              KX_GameObject, pyattr_get_mass,         pyattr_set_mass),
1102         KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMin",            KX_GameObject, pyattr_get_lin_vel_min, pyattr_set_lin_vel_min),
1103         KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMax",            KX_GameObject, pyattr_get_lin_vel_max, pyattr_set_lin_vel_max),
1104         KX_PYATTRIBUTE_RW_FUNCTION("visible",   KX_GameObject, pyattr_get_visible,      pyattr_set_visible),
1105         KX_PYATTRIBUTE_BOOL_RW    ("occlusion", KX_GameObject, m_bOccluder),
1106         KX_PYATTRIBUTE_RW_FUNCTION("position",  KX_GameObject, pyattr_get_worldPosition,        pyattr_set_localPosition),
1107         KX_PYATTRIBUTE_RO_FUNCTION("localInertia",      KX_GameObject, pyattr_get_localInertia),
1108         KX_PYATTRIBUTE_RW_FUNCTION("orientation",KX_GameObject,pyattr_get_worldOrientation,pyattr_set_localOrientation),
1109         KX_PYATTRIBUTE_RW_FUNCTION("scaling",   KX_GameObject, pyattr_get_worldScaling, pyattr_set_localScaling),
1110         KX_PYATTRIBUTE_RW_FUNCTION("timeOffset",KX_GameObject, pyattr_get_timeOffset,pyattr_set_timeOffset),
1111         KX_PYATTRIBUTE_RW_FUNCTION("state",             KX_GameObject, pyattr_get_state,        pyattr_set_state),
1112         KX_PYATTRIBUTE_RO_FUNCTION("meshes",    KX_GameObject, pyattr_get_meshes),
1113         KX_PYATTRIBUTE_RW_FUNCTION("localOrientation",KX_GameObject,pyattr_get_localOrientation,pyattr_set_localOrientation),
1114         KX_PYATTRIBUTE_RO_FUNCTION("worldOrientation",KX_GameObject,pyattr_get_worldOrientation),
1115         KX_PYATTRIBUTE_RW_FUNCTION("localPosition",     KX_GameObject, pyattr_get_localPosition,        pyattr_set_localPosition),
1116         KX_PYATTRIBUTE_RW_FUNCTION("worldPosition",     KX_GameObject, pyattr_get_worldPosition,    pyattr_set_worldPosition),
1117         KX_PYATTRIBUTE_RW_FUNCTION("localScaling",      KX_GameObject, pyattr_get_localScaling, pyattr_set_localScaling),
1118         KX_PYATTRIBUTE_RO_FUNCTION("worldScaling",      KX_GameObject, pyattr_get_worldScaling),
1119         
1120         KX_PYATTRIBUTE_RO_FUNCTION("__dict__",  KX_GameObject, pyattr_get_dir_dict),
1121         
1122         /* Experemental, dont rely on these yet */
1123         KX_PYATTRIBUTE_RO_FUNCTION("sensors",           KX_GameObject, pyattr_get_sensors),
1124         KX_PYATTRIBUTE_RO_FUNCTION("controllers",       KX_GameObject, pyattr_get_controllers),
1125         KX_PYATTRIBUTE_RO_FUNCTION("actuators",         KX_GameObject, pyattr_get_actuators),
1126         
1127         KX_PYATTRIBUTE_RO_FUNCTION("isValid",           KX_GameObject, pyattr_get_is_valid),
1128         
1129         {NULL} //Sentinel
1130 };
1131
1132
1133 /*
1134 bool KX_GameObject::ConvertPythonVectorArgs(PyObject* args,
1135                                                                                         MT_Vector3& pos,
1136                                                                                         MT_Vector3& pos2)
1137 {
1138         PyObject* pylist;
1139         PyObject* pylist2;
1140         bool error = (PyArg_ParseTuple(args,"OO",&pylist,&pylist2)) != 0;
1141
1142         pos = ConvertPythonPylist(pylist);
1143         pos2 = ConvertPythonPylist(pylist2);
1144                 
1145         return error;
1146 }
1147 */
1148
1149 PyObject* KX_GameObject::PyReplaceMesh(PyObject* self, PyObject* value)
1150 {
1151         KX_Scene *scene = KX_GetActiveScene();
1152         char* meshname;
1153         void* mesh_pt;
1154
1155         meshname = PyString_AsString(value);
1156         if (meshname==NULL) {
1157                 PyErr_SetString(PyExc_ValueError, "Expected a mesh name");
1158                 return NULL;
1159         }
1160         mesh_pt = SCA_ILogicBrick::m_sCurrentLogicManager->GetMeshByName(STR_String(meshname));
1161         
1162         if (mesh_pt==NULL) {
1163                 PyErr_SetString(PyExc_ValueError, "The mesh name given does not exist");
1164                 return NULL;
1165         }
1166         scene->ReplaceMesh(this, (class RAS_MeshObject*)mesh_pt);
1167         
1168         Py_RETURN_NONE;
1169 }
1170
1171 PyObject* KX_GameObject::PyEndObject(PyObject* self)
1172 {
1173
1174         KX_Scene *scene = KX_GetActiveScene();
1175         scene->DelayedRemoveObject(this);
1176         
1177         Py_RETURN_NONE;
1178
1179 }
1180
1181
1182 PyObject* KX_GameObject::PyGetPosition(PyObject* self)
1183 {
1184         ShowDeprecationWarning("getPosition()", "the position property");
1185         return PyObjectFrom(NodeGetWorldPosition());
1186 }
1187
1188
1189 Py_ssize_t KX_GameObject::Map_Len(PyObject* self_v)
1190 {
1191         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1192         
1193         if (ValidPythonToGameObject(self)==false) {
1194                 PyErr_Clear();
1195                 return 0;
1196         }
1197         
1198         Py_ssize_t len= self->GetPropertyCount();
1199         if(self->m_attrlist)
1200                 len += PyDict_Size(self->m_attrlist);
1201         return len;
1202 }
1203
1204
1205 PyObject *KX_GameObject::Map_GetItem(PyObject *self_v, PyObject *item)
1206 {
1207         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1208         const char *attr_str= PyString_AsString(item);
1209         CValue* resultattr;
1210         PyObject* pyconvert;
1211         
1212         if (ValidPythonToGameObject(self)==false)
1213                 return NULL;
1214         
1215         /* first see if the attributes a string and try get the cvalue attribute */
1216         if(attr_str && (resultattr=self->GetProperty(attr_str))) {
1217                 pyconvert = resultattr->ConvertValueToPython();                 
1218                 return pyconvert ? pyconvert:resultattr;
1219         }
1220         /* no CValue attribute, try get the python only m_attrlist attribute */
1221         else if (self->m_attrlist && (pyconvert=PyDict_GetItem(self->m_attrlist, item))) {
1222                 
1223                 if (attr_str)
1224                         PyErr_Clear();
1225                 Py_INCREF(pyconvert);
1226                 return pyconvert;
1227         }
1228         else {
1229                 if(attr_str)    PyErr_Format(PyExc_KeyError, "KX_GameObject key \"%s\" does not exist", attr_str);
1230                 else                    PyErr_SetString(PyExc_KeyError, "KX_GameObject key does not exist");
1231                 return NULL;
1232         }
1233                 
1234 }
1235
1236
1237 int KX_GameObject::Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val)
1238 {
1239         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1240         const char *attr_str= PyString_AsString(key);
1241         if(attr_str==NULL)
1242                 PyErr_Clear();
1243         
1244         if (ValidPythonToGameObject(self)==false)
1245                 return -1;
1246         
1247         if (val==NULL) { /* del ob["key"] */
1248                 int del= 0;
1249                 
1250                 /* try remove both just incase */
1251                 if(attr_str)
1252                         del |= (self->RemoveProperty(attr_str)==true) ? 1:0;
1253                 
1254                 if(self->m_attrlist)
1255                         del |= (PyDict_DelItem(self->m_attrlist, key)==0) ? 1:0;
1256                 
1257                 if (del==0) {
1258                         if(attr_str)    PyErr_Format(PyExc_KeyError, "KX_GameObject key \"%s\" not found", attr_str);
1259                         else                    PyErr_SetString(PyExc_KeyError, "KX_GameObject key not found");
1260                         return -1;
1261                 }
1262                 else if (self->m_attrlist) {
1263                         PyErr_Clear(); /* PyDict_DelItem sets an error when it fails */
1264                 }
1265         }
1266         else { /* ob["key"] = value */
1267                 int set= 0;
1268                 
1269                 /* as CValue */
1270                 if(attr_str)
1271                 {
1272                         CValue* vallie = self->ConvertPythonToValue(val);
1273                         
1274                         if(vallie)
1275                         {
1276                                 CValue* oldprop = self->GetProperty(attr_str);
1277                                 
1278                                 if (oldprop)
1279                                         oldprop->SetValue(vallie);
1280                                 else
1281                                         self->SetProperty(attr_str, vallie);
1282                                 
1283                                 vallie->Release();
1284                                 set= 1;
1285                                 
1286                                 /* try remove dict value to avoid double ups */
1287                                 if (self->m_attrlist){
1288                                         if (PyDict_DelItem(self->m_attrlist, key) != 0)
1289                                                 PyErr_Clear();
1290                                 }
1291                         }
1292                         else {
1293                                 PyErr_Clear();
1294                         }
1295                 }
1296                 
1297                 if(set==0)
1298                 {
1299                         if (self->m_attrlist==NULL) /* lazy init */
1300                                 self->m_attrlist= PyDict_New();
1301                         
1302                         
1303                         if(PyDict_SetItem(self->m_attrlist, key, val)==0)
1304                         {
1305                                 if(attr_str)
1306                                         self->RemoveProperty(attr_str); /* overwrite the CValue if it exists */
1307                                 set= 1;
1308                         }
1309                         else {
1310                                 if(attr_str)    PyErr_Format(PyExc_KeyError, "KX_GameObject key \"%s\" not be added to internal dictionary", attr_str);
1311                                 else                    PyErr_SetString(PyExc_KeyError, "KX_GameObject key not be added to internal dictionary");
1312                         }
1313                 }
1314                 
1315                 if(set==0)
1316                         return -1; /* pythons error value */
1317                 
1318         }
1319         
1320         return 0; /* success */
1321 }
1322
1323
1324 PyMappingMethods KX_GameObject::Mapping = {
1325         (lenfunc)KX_GameObject::Map_Len,                        /*inquiry mp_length */
1326         (binaryfunc)KX_GameObject::Map_GetItem,         /*binaryfunc mp_subscript */
1327         (objobjargproc)KX_GameObject::Map_SetItem,      /*objobjargproc mp_ass_subscript */
1328 };
1329
1330
1331 PyTypeObject KX_GameObject::Type = {
1332         PyObject_HEAD_INIT(NULL)
1333                 0,
1334                 "KX_GameObject",
1335                 sizeof(KX_GameObject),
1336                 0,
1337                 PyDestructor,
1338                 0,
1339                 0,
1340                 0,
1341                 0,
1342                 py_base_repr,
1343                 0,0,
1344                 &Mapping,
1345                 0,0,0,
1346                 py_base_getattro_gameobject,
1347                 py_base_setattro_gameobject,
1348                 0,0,0,0,0,0,0,0,0,
1349                 Methods
1350 };
1351
1352
1353
1354
1355
1356
1357 PyParentObject KX_GameObject::Parents[] = {
1358         &KX_GameObject::Type,
1359                 &SCA_IObject::Type,
1360                 &CValue::Type,
1361                 NULL
1362 };
1363
1364 PyObject* KX_GameObject::pyattr_get_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1365 {
1366         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1367         return PyString_FromString(self->GetName().ReadPtr());
1368 }
1369
1370 PyObject* KX_GameObject::pyattr_get_parent(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1371 {
1372         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1373         KX_GameObject* parent = self->GetParent();
1374         if (parent)
1375                 return parent->AddRef();
1376         Py_RETURN_NONE;
1377 }
1378
1379 PyObject* KX_GameObject::pyattr_get_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1380 {
1381         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1382         KX_IPhysicsController *spc = self->GetPhysicsController();
1383         return PyFloat_FromDouble(spc ? spc->GetMass() : 0.0f);
1384 }
1385
1386 int KX_GameObject::pyattr_set_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1387 {
1388         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1389         KX_IPhysicsController *spc = self->GetPhysicsController();
1390         MT_Scalar val = PyFloat_AsDouble(value);
1391         if (val < 0.0f) { /* also accounts for non float */
1392                 PyErr_SetString(PyExc_AttributeError, "expected a float zero or above");
1393                 return 1;
1394         }
1395
1396         if (spc)
1397                 spc->SetMass(val);
1398
1399         return 0;
1400 }
1401
1402 PyObject* KX_GameObject::pyattr_get_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1403 {
1404         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1405         KX_IPhysicsController *spc = self->GetPhysicsController();
1406         return PyFloat_FromDouble(spc ? spc->GetLinVelocityMax() : 0.0f);
1407 }
1408
1409 int KX_GameObject::pyattr_set_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1410 {
1411         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1412         KX_IPhysicsController *spc = self->GetPhysicsController();
1413         MT_Scalar val = PyFloat_AsDouble(value);
1414         if (val < 0.0f) { /* also accounts for non float */
1415                 PyErr_SetString(PyExc_AttributeError, "expected a float zero or above");
1416                 return 1;
1417         }
1418
1419         if (spc)
1420                 spc->SetLinVelocityMin(val);
1421
1422         return 0;
1423 }
1424
1425 PyObject* KX_GameObject::pyattr_get_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1426 {
1427         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1428         KX_IPhysicsController *spc = self->GetPhysicsController();
1429         return PyFloat_FromDouble(spc ? spc->GetLinVelocityMax() : 0.0f);
1430 }
1431
1432 int KX_GameObject::pyattr_set_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1433 {
1434         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1435         KX_IPhysicsController *spc = self->GetPhysicsController();
1436         MT_Scalar val = PyFloat_AsDouble(value);
1437         if (val < 0.0f) { /* also accounts for non float */
1438                 PyErr_SetString(PyExc_AttributeError, "expected a float zero or above");
1439                 return 1;
1440         }
1441
1442         if (spc)
1443                 spc->SetLinVelocityMax(val);
1444
1445         return 0;
1446 }
1447
1448
1449 PyObject* KX_GameObject::pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1450 {
1451         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1452         return PyBool_FromLong(self->GetVisible());
1453 }
1454
1455 int KX_GameObject::pyattr_set_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1456 {
1457         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1458         int param = PyObject_IsTrue( value );
1459         if (param == -1) {
1460                 PyErr_SetString(PyExc_AttributeError, "expected True or False");
1461                 return 1;
1462         }
1463
1464         self->SetVisible(param, false);
1465         self->UpdateBuckets(false);
1466         return 0;
1467 }
1468
1469 PyObject* KX_GameObject::pyattr_get_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1470 {
1471         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1472         return PyObjectFrom(self->NodeGetWorldPosition());
1473 }
1474
1475 int KX_GameObject::pyattr_set_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1476 {
1477         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1478         MT_Point3 pos;
1479         if (!PyVecTo(value, pos))
1480                 return 1;
1481         
1482         self->NodeSetWorldPosition(pos);
1483         self->NodeUpdateGS(0.f);
1484         return 0;
1485 }
1486
1487 PyObject* KX_GameObject::pyattr_get_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1488 {
1489         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1490         if (self->GetSGNode())
1491                 return PyObjectFrom(self->GetSGNode()->GetLocalPosition());
1492         else
1493                 return PyObjectFrom(dummy_point);
1494 }
1495
1496 int KX_GameObject::pyattr_set_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1497 {
1498         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1499         MT_Point3 pos;
1500         if (!PyVecTo(value, pos))
1501                 return 1;
1502         
1503         self->NodeSetLocalPosition(pos);
1504         self->NodeUpdateGS(0.f);
1505         return 0;
1506 }
1507
1508 PyObject* KX_GameObject::pyattr_get_localInertia(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1509 {
1510         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1511         if (self->GetPhysicsController())
1512         {
1513                 return PyObjectFrom(self->GetPhysicsController()->GetLocalInertia());
1514         }
1515         return Py_BuildValue("fff", 0.0f, 0.0f, 0.0f);
1516 }
1517
1518 PyObject* KX_GameObject::pyattr_get_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1519 {
1520         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1521         return PyObjectFrom(self->NodeGetWorldOrientation());
1522 }
1523
1524 PyObject* KX_GameObject::pyattr_get_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1525 {
1526         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1527         if (self->GetSGNode())
1528                 return PyObjectFrom(self->GetSGNode()->GetLocalOrientation());
1529         else
1530                 return PyObjectFrom(dummy_orientation);
1531 }
1532
1533 int KX_GameObject::pyattr_set_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1534 {
1535         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1536         if (!PySequence_Check(value)) {
1537                 PyErr_SetString(PyExc_AttributeError, "'orientation' attribute needs to be a sequence");
1538                 return 1;
1539         }
1540
1541         MT_Matrix3x3 rot;
1542
1543         if (PyMatTo(value, rot))
1544         {
1545                 self->NodeSetLocalOrientation(rot);
1546                 self->NodeUpdateGS(0.f);
1547                 return 0;
1548         }
1549         PyErr_Clear();
1550
1551         if (PySequence_Size(value) == 4)
1552         {
1553                 MT_Quaternion qrot;
1554                 if (PyVecTo(value, qrot))
1555                 {
1556                         rot.setRotation(qrot);
1557                         self->NodeSetLocalOrientation(rot);
1558                         self->NodeUpdateGS(0.f);
1559                         return 0;
1560                 }
1561                 return 1;
1562         }
1563
1564         if (PySequence_Size(value) == 3)
1565         {
1566                 MT_Vector3 erot;
1567                 if (PyVecTo(value, erot))
1568                 {
1569                         rot.setEuler(erot);
1570                         self->NodeSetLocalOrientation(rot);
1571                         self->NodeUpdateGS(0.f);
1572                         return 0;
1573                 }
1574                 return 1;
1575         }
1576
1577         PyErr_SetString(PyExc_AttributeError, "could not set the orientation from a 3x3 matrix, quaternion or euler sequence");
1578         return 1;
1579 }
1580
1581 PyObject* KX_GameObject::pyattr_get_worldScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1582 {
1583         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1584         return PyObjectFrom(self->NodeGetWorldScaling());
1585 }
1586
1587 PyObject* KX_GameObject::pyattr_get_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1588 {
1589         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1590         if (self->GetSGNode())
1591                 return PyObjectFrom(self->GetSGNode()->GetLocalScale());
1592         else
1593                 return PyObjectFrom(dummy_scaling);
1594 }
1595
1596 int KX_GameObject::pyattr_set_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1597 {
1598         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1599         MT_Vector3 scale;
1600         if (!PyVecTo(value, scale))
1601                 return 1;
1602
1603         self->NodeSetLocalScale(scale);
1604         self->NodeUpdateGS(0.f);
1605         return 0;
1606 }
1607
1608 PyObject* KX_GameObject::pyattr_get_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1609 {
1610         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1611         SG_Node* sg_parent;
1612         if (self->GetSGNode() && (sg_parent = self->GetSGNode()->GetSGParent()) != NULL && sg_parent->IsSlowParent()) {
1613                 return PyFloat_FromDouble(static_cast<KX_SlowParentRelation *>(sg_parent->GetParentRelation())->GetTimeOffset());
1614         } else {
1615                 return PyFloat_FromDouble(0.0);
1616         }
1617 }
1618
1619 int KX_GameObject::pyattr_set_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1620 {
1621         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1622         if (self->GetSGNode()) {
1623                 MT_Scalar val = PyFloat_AsDouble(value);
1624                 SG_Node* sg_parent= self->GetSGNode()->GetSGParent();
1625                 if (val < 0.0f) { /* also accounts for non float */
1626                         PyErr_SetString(PyExc_AttributeError, "expected a float zero or above");
1627                         return 1;
1628                 }
1629                 if (sg_parent && sg_parent->IsSlowParent())
1630                         static_cast<KX_SlowParentRelation *>(sg_parent->GetParentRelation())->SetTimeOffset(val);
1631         }
1632         return 0;
1633 }
1634
1635 PyObject* KX_GameObject::pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1636 {
1637         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1638         int state = 0;
1639         state |= self->GetState();
1640         return PyInt_FromLong(state);
1641 }
1642
1643 int KX_GameObject::pyattr_set_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1644 {
1645         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1646         int state_i = PyInt_AsLong(value);
1647         unsigned int state = 0;
1648         
1649         if (state_i == -1 && PyErr_Occurred()) {
1650                 PyErr_SetString(PyExc_TypeError, "expected an int bit field");
1651                 return 1;
1652         }
1653         
1654         state |= state_i;
1655         if ((state & ((1<<30)-1)) == 0) {
1656                 PyErr_SetString(PyExc_AttributeError, "The state bitfield was not between 0 and 30 (1<<0 and 1<<29)");
1657                 return 1;
1658         }
1659         self->SetState(state);
1660         return 0;
1661 }
1662
1663 PyObject* KX_GameObject::pyattr_get_meshes(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1664 {
1665         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1666         PyObject *meshes= PyList_New(self->m_meshes.size());
1667         int i;
1668         
1669         for(i=0; i < self->m_meshes.size(); i++)
1670         {
1671                 KX_MeshProxy* meshproxy = new KX_MeshProxy(self->m_meshes[i]);
1672                 PyList_SET_ITEM(meshes, i, meshproxy);
1673         }
1674         
1675         return meshes;
1676 }
1677
1678 PyObject* KX_GameObject::pyattr_get_is_valid(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1679 {       
1680         Py_RETURN_TRUE;
1681 }
1682
1683 /* experemental! */
1684 PyObject* KX_GameObject::pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1685 {
1686         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1687         SCA_SensorList& sensors= self->GetSensors();
1688         PyObject* resultlist = PyList_New(sensors.size());
1689         
1690         for (unsigned int index=0;index<sensors.size();index++)
1691                 PyList_SET_ITEM(resultlist, index, sensors[index]->AddRef());
1692         
1693         return resultlist;
1694 }
1695
1696 PyObject* KX_GameObject::pyattr_get_controllers(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1697 {
1698         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1699         SCA_ControllerList& controllers= self->GetControllers();
1700         PyObject* resultlist = PyList_New(controllers.size());
1701         
1702         for (unsigned int index=0;index<controllers.size();index++)
1703                 PyList_SET_ITEM(resultlist, index, controllers[index]->AddRef());
1704         
1705         return resultlist;
1706 }
1707
1708 PyObject* KX_GameObject::pyattr_get_actuators(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1709 {
1710         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1711         SCA_ActuatorList& actuators= self->GetActuators();
1712         PyObject* resultlist = PyList_New(actuators.size());
1713         
1714         for (unsigned int index=0;index<actuators.size();index++)
1715                 PyList_SET_ITEM(resultlist, index, actuators[index]->AddRef());
1716         
1717         return resultlist;
1718 }
1719
1720 /* __dict__ only for the purpose of giving useful dir() results */
1721 PyObject* KX_GameObject::pyattr_get_dir_dict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1722 {
1723         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1724         PyObject *dict_str = PyString_FromString("__dict__");
1725         PyObject *dict= py_getattr_dict(self->SCA_IObject::py_getattro(dict_str), Type.tp_dict);
1726         Py_DECREF(dict_str);
1727         
1728         if(dict==NULL)
1729                 return NULL;
1730         
1731         /* Not super fast getting as a list then making into dict keys but its only for dir() */
1732         PyObject *list= self->ConvertKeysToPython();
1733         if(list)
1734         {
1735                 int i;
1736                 for(i=0; i<PyList_Size(list); i++)
1737                         PyDict_SetItem(dict, PyList_GET_ITEM(list, i), Py_None);
1738         }
1739         else
1740                 PyErr_Clear();
1741         
1742         Py_DECREF(list);
1743         
1744         /* Add m_attrlist if we have it */
1745         if(self->m_attrlist)
1746                 PyDict_Update(dict, self->m_attrlist);
1747         
1748         return dict;
1749 }
1750
1751 PyObject* KX_GameObject::py_getattro(PyObject *attr)
1752 {
1753         py_getattro_up(SCA_IObject);
1754 }
1755
1756 int KX_GameObject::py_setattro(PyObject *attr, PyObject *value) // py_setattro method
1757 {
1758         py_setattro_up(SCA_IObject);
1759 }
1760
1761
1762 /* we need our own getattr and setattr types */
1763 /* See m_attrlist definition for rules on how this works */
1764 PyObject *KX_GameObject::py_base_getattro_gameobject(PyObject * self, PyObject *attr)
1765 {
1766         if(((KX_GameObject *) self)->GetSGNode()==NULL) {
1767                 if (!strcmp(PyString_AsString(attr), "isValid")) {
1768                         PyErr_Clear();
1769                         Py_INCREF(Py_False);
1770                         return Py_False;
1771                 }
1772                 
1773                 ValidPythonToGameObject(((KX_GameObject *) self)); // we know its invalid, just get the error
1774                 return NULL;
1775         }
1776         
1777         PyObject *object= ((KX_GameObject *) self)->py_getattro(attr);
1778         
1779         if (object==NULL && ((KX_GameObject *) self)->m_attrlist) {
1780                 /* backup the exception incase the attr doesnt exist in the dict either */
1781                 PyObject *err_type, *err_value, *err_tb;
1782                 PyErr_Fetch(&err_type, &err_value, &err_tb);
1783                 
1784                 object= PyDict_GetItem(((KX_GameObject *) self)->m_attrlist, attr);
1785                 if (object) {
1786                         Py_INCREF(object);
1787                         
1788                         PyErr_Clear();
1789                         Py_XDECREF( err_type );
1790                         Py_XDECREF( err_value );
1791                         Py_XDECREF( err_tb );
1792                 }
1793                 else {
1794                         PyErr_Restore(err_type, err_value, err_tb); /* use the error from the parent function */
1795                 }
1796         }
1797         return object;
1798 }
1799
1800 int KX_GameObject::py_base_setattro_gameobject(PyObject * self, PyObject *attr, PyObject *value)
1801 {
1802         int ret;
1803         
1804         /* Delete the item */
1805         if (value==NULL)
1806         {
1807                 ret= ((PyObjectPlus*) self)->py_delattro(attr);
1808                 
1809                 if (ret != 0) /* CValue attribute failed, try KX_GameObject m_attrlist dict */
1810                 {
1811                         if (((KX_GameObject *) self)->m_attrlist)
1812                         {
1813                                 /* backup the exception incase the attr doesnt exist in the dict either */
1814                                 PyObject *err_type, *err_value, *err_tb;
1815                                 PyErr_Fetch(&err_type, &err_value, &err_tb);
1816                                 
1817                                 if (PyDict_DelItem(((KX_GameObject *) self)->m_attrlist, attr) == 0)
1818                                 {
1819                                         ret= 0;
1820                                         PyErr_Clear();
1821                                         Py_XDECREF( err_type );
1822                                         Py_XDECREF( err_value );
1823                                         Py_XDECREF( err_tb );
1824                                 }
1825                                 else { 
1826                                         PyErr_Restore(err_type, err_value, err_tb); /* use the error from the parent function */
1827                                 }
1828                         }
1829                 }
1830                 return ret;
1831         }
1832         
1833         
1834         ret= ((PyObjectPlus*) self)->py_setattro(attr, value);
1835         
1836         if (ret==PY_SET_ATTR_SUCCESS) {
1837                 /* remove attribute in our own dict to avoid double ups */
1838                 if (((KX_GameObject *) self)->m_attrlist) {
1839                         if (PyDict_DelItem(((KX_GameObject *) self)->m_attrlist, attr) != 0)
1840                                 PyErr_Clear();
1841                 }
1842         }
1843         
1844         if (ret==PY_SET_ATTR_COERCE_FAIL) {
1845                 /* CValue attribute exists, remove and add dict value */
1846                 ((KX_GameObject *) self)->RemoveProperty(STR_String(PyString_AsString(attr)));
1847                 ret= PY_SET_ATTR_MISSING;
1848         }
1849         
1850         if (ret==PY_SET_ATTR_MISSING) {
1851                 /* Lazy initialization */
1852                 if (((KX_GameObject *) self)->m_attrlist==NULL)
1853                         ((KX_GameObject *) self)->m_attrlist = PyDict_New();
1854                 
1855                 if (PyDict_SetItem(((KX_GameObject *) self)->m_attrlist, attr, value)==0) {
1856                         PyErr_Clear();
1857                         ret= PY_SET_ATTR_SUCCESS;
1858                 }
1859                 else {
1860                         PyErr_Format(PyExc_AttributeError, "failed assigning value to KX_GameObject internal dictionary");
1861                         ret= PY_SET_ATTR_FAIL;
1862                 }
1863         }
1864         
1865         return ret;
1866 }
1867
1868 PyObject* KX_GameObject::PyApplyForce(PyObject* self, PyObject* args)
1869 {
1870         int local = 0;
1871         PyObject* pyvect;
1872
1873         if (PyArg_ParseTuple(args, "O|i:applyForce", &pyvect, &local)) {
1874                 MT_Vector3 force;
1875                 if (PyVecTo(pyvect, force)) {
1876                         ApplyForce(force, (local!=0));
1877                         Py_RETURN_NONE;
1878                 }
1879         }
1880         return NULL;
1881 }
1882
1883 PyObject* KX_GameObject::PyApplyTorque(PyObject* self, PyObject* args)
1884 {
1885         int local = 0;
1886         PyObject* pyvect;
1887
1888         if (PyArg_ParseTuple(args, "O|i:applyTorque", &pyvect, &local)) {
1889                 MT_Vector3 torque;
1890                 if (PyVecTo(pyvect, torque)) {
1891                         ApplyTorque(torque, (local!=0));
1892                         Py_RETURN_NONE;
1893                 }
1894         }
1895         return NULL;
1896 }
1897
1898 PyObject* KX_GameObject::PyApplyRotation(PyObject* self, PyObject* args)
1899 {
1900         int local = 0;
1901         PyObject* pyvect;
1902
1903         if (PyArg_ParseTuple(args, "O|i:applyRotation", &pyvect, &local)) {
1904                 MT_Vector3 rotation;
1905                 if (PyVecTo(pyvect, rotation)) {
1906                         ApplyRotation(rotation, (local!=0));
1907                         Py_RETURN_NONE;
1908                 }
1909         }
1910         return NULL;
1911 }
1912
1913 PyObject* KX_GameObject::PyApplyMovement(PyObject* self, PyObject* args)
1914 {
1915         int local = 0;
1916         PyObject* pyvect;
1917
1918         if (PyArg_ParseTuple(args, "O|i:applyMovement", &pyvect, &local)) {
1919                 MT_Vector3 movement;
1920                 if (PyVecTo(pyvect, movement)) {
1921                         ApplyMovement(movement, (local!=0));
1922                         Py_RETURN_NONE;
1923                 }
1924         }
1925         return NULL;
1926 }
1927
1928 PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* self, PyObject* args)
1929 {
1930         // only can get the velocity if we have a physics object connected to us...
1931         int local = 0;
1932         if (PyArg_ParseTuple(args,"|i:getLinearVelocity",&local))
1933         {
1934                 return PyObjectFrom(GetLinearVelocity((local!=0)));
1935         }
1936         else
1937         {
1938                 return NULL;
1939         }
1940 }
1941
1942 PyObject* KX_GameObject::PySetLinearVelocity(PyObject* self, PyObject* args)
1943 {
1944         int local = 0;
1945         PyObject* pyvect;
1946         
1947         if (PyArg_ParseTuple(args,"O|i:setLinearVelocity",&pyvect,&local)) {
1948                 MT_Vector3 velocity;
1949                 if (PyVecTo(pyvect, velocity)) {
1950                         setLinearVelocity(velocity, (local!=0));
1951                         Py_RETURN_NONE;
1952                 }
1953         }
1954         return NULL;
1955 }
1956
1957 PyObject* KX_GameObject::PyGetAngularVelocity(PyObject* self, PyObject* args)
1958 {
1959         // only can get the velocity if we have a physics object connected to us...
1960         int local = 0;
1961         if (PyArg_ParseTuple(args,"|i:getAngularVelocity",&local))
1962         {
1963                 return PyObjectFrom(GetAngularVelocity((local!=0)));
1964         }
1965         else
1966         {
1967                 return NULL;
1968         }
1969 }
1970
1971 PyObject* KX_GameObject::PySetAngularVelocity(PyObject* self, PyObject* args)
1972 {
1973         int local = 0;
1974         PyObject* pyvect;
1975         
1976         if (PyArg_ParseTuple(args,"O|i:setAngularVelocity",&pyvect,&local)) {
1977                 MT_Vector3 velocity;
1978                 if (PyVecTo(pyvect, velocity)) {
1979                         setAngularVelocity(velocity, (local!=0));
1980                         Py_RETURN_NONE;
1981                 }
1982         }
1983         return NULL;
1984 }
1985
1986 PyObject* KX_GameObject::PySetVisible(PyObject* self, PyObject* args)
1987 {
1988         int visible, recursive = 0;
1989         if (!PyArg_ParseTuple(args,"i|i:setVisible",&visible, &recursive))
1990                 return NULL;
1991         
1992         SetVisible(visible ? true:false, recursive ? true:false);
1993         UpdateBuckets(recursive ? true:false);
1994         Py_RETURN_NONE;
1995         
1996 }
1997
1998 PyObject* KX_GameObject::PySetOcclusion(PyObject* self, PyObject* args)
1999 {
2000         int occlusion, recursive = 0;
2001         if (!PyArg_ParseTuple(args,"i|i:setOcclusion",&occlusion, &recursive))
2002                 return NULL;
2003         
2004         SetOccluder(occlusion ? true:false, recursive ? true:false);
2005         Py_RETURN_NONE;
2006 }
2007
2008 PyObject* KX_GameObject::PyGetVisible(PyObject* self)
2009 {
2010         ShowDeprecationWarning("getVisible()", "the visible property");
2011         return PyInt_FromLong(m_bVisible);      
2012 }
2013
2014 PyObject* KX_GameObject::PyGetState(PyObject* self)
2015 {
2016         ShowDeprecationWarning("getState()", "the state property");
2017         int state = 0;
2018         state |= GetState();
2019         return PyInt_FromLong(state);
2020 }
2021
2022 PyObject* KX_GameObject::PySetState(PyObject* self, PyObject* value)
2023 {
2024         ShowDeprecationWarning("setState()", "the state property");
2025         int state_i = PyInt_AsLong(value);
2026         unsigned int state = 0;
2027         
2028         if (state_i == -1 && PyErr_Occurred()) {
2029                 PyErr_SetString(PyExc_TypeError, "expected an int bit field");
2030                 return NULL;
2031         }
2032         
2033         state |= state_i;
2034         if ((state & ((1<<30)-1)) == 0) {
2035                 PyErr_SetString(PyExc_AttributeError, "The state bitfield was not between 0 and 30 (1<<0 and 1<<29)");
2036                 return NULL;
2037         }
2038         SetState(state);
2039         
2040         Py_RETURN_NONE;
2041 }
2042
2043 PyObject* KX_GameObject::PyGetVelocity(PyObject* self, PyObject* args)
2044 {
2045         // only can get the velocity if we have a physics object connected to us...
2046         MT_Point3 point(0.0,0.0,0.0);
2047         PyObject* pypos = NULL;
2048         
2049         if (PyArg_ParseTuple(args, "|O:getVelocity", &pypos))
2050         {
2051                 if (pypos)
2052                         PyVecTo(pypos, point);
2053         }
2054         else {
2055                 return NULL;
2056         }
2057         
2058         if (m_pPhysicsController1)
2059         {
2060                 return PyObjectFrom(m_pPhysicsController1->GetVelocity(point));
2061         }
2062         else {
2063                 return PyObjectFrom(MT_Vector3(0.0,0.0,0.0));
2064         }
2065 }
2066
2067
2068
2069 PyObject* KX_GameObject::PyGetMass(PyObject* self)
2070 {
2071         ShowDeprecationWarning("getMass()", "the mass property");
2072         return PyFloat_FromDouble((GetPhysicsController() != NULL) ? GetPhysicsController()->GetMass() : 0.0f);
2073 }
2074
2075 PyObject* KX_GameObject::PyGetReactionForce(PyObject* self)
2076 {
2077         // only can get the velocity if we have a physics object connected to us...
2078         
2079         // XXX - Currently not working with bullet intergration, see KX_BulletPhysicsController.cpp's getReactionForce
2080         /*
2081         if (GetPhysicsController())
2082                 return PyObjectFrom(GetPhysicsController()->getReactionForce());
2083         return PyObjectFrom(dummy_point);
2084         */
2085         
2086         return Py_BuildValue("fff", 0.0f, 0.0f, 0.0f);
2087         
2088 }
2089
2090
2091
2092 PyObject* KX_GameObject::PyEnableRigidBody(PyObject* self)
2093 {
2094         if(GetPhysicsController())
2095                 GetPhysicsController()->setRigidBody(true);
2096
2097         Py_RETURN_NONE;
2098 }
2099
2100
2101
2102 PyObject* KX_GameObject::PyDisableRigidBody(PyObject* self)
2103 {
2104         if(GetPhysicsController())
2105                 GetPhysicsController()->setRigidBody(false);
2106
2107         Py_RETURN_NONE;
2108 }
2109
2110
2111
2112 PyObject* KX_GameObject::PyGetParent(PyObject* self)
2113 {
2114         ShowDeprecationWarning("getParent()", "the parent property");
2115         KX_GameObject* parent = this->GetParent();
2116         if (parent)
2117                 return parent->AddRef();
2118         Py_RETURN_NONE;
2119 }
2120
2121 PyObject* KX_GameObject::PySetParent(PyObject* self, PyObject* value)
2122 {
2123         if (!PyObject_TypeCheck(value, &KX_GameObject::Type)) {
2124                 PyErr_SetString(PyExc_TypeError, "expected a KX_GameObject type");
2125                 return NULL;
2126         }
2127         if (self==value) {
2128                 PyErr_SetString(PyExc_ValueError, "cannot set the object to be its own parent!");
2129                 return NULL;
2130         }
2131         
2132         // The object we want to set as parent
2133         CValue *m_ob = (CValue*)value;
2134         KX_GameObject *obj = ((KX_GameObject*)m_ob);
2135         KX_Scene *scene = KX_GetActiveScene();
2136         
2137         this->SetParent(scene, obj);
2138                 
2139         Py_RETURN_NONE;
2140 }
2141
2142 PyObject* KX_GameObject::PyRemoveParent(PyObject* self)
2143 {
2144         KX_Scene *scene = KX_GetActiveScene();
2145         this->RemoveParent(scene);
2146         Py_RETURN_NONE;
2147 }
2148
2149
2150 static void walk_children(SG_Node* node, CListValue* list, bool recursive)
2151 {
2152         if (!node)
2153                 return;
2154         NodeList& children = node->GetSGChildren();
2155
2156         for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
2157         {
2158                 SG_Node* childnode = (*childit);
2159                 CValue* childobj = (CValue*)childnode->GetSGClientObject();
2160                 if (childobj != NULL) // This is a GameObject
2161                 {
2162                         // add to the list
2163                         list->Add(childobj->AddRef());
2164                 }
2165                 
2166                 // if the childobj is NULL then this may be an inverse parent link
2167                 // so a non recursive search should still look down this node.
2168                 if (recursive || childobj==NULL) {
2169                         walk_children(childnode, list, recursive);
2170                 }
2171         }
2172 }
2173
2174 PyObject* KX_GameObject::PyGetChildren(PyObject* self)
2175 {
2176         CListValue* list = new CListValue();
2177         walk_children(GetSGNode(), list, 0); /* GetSGNode() is always valid or it would have raised an exception before this */
2178         return list;
2179 }
2180
2181 PyObject* KX_GameObject::PyGetChildrenRecursive(PyObject* self)
2182 {
2183         CListValue* list = new CListValue();
2184         walk_children(GetSGNode(), list, 1);
2185         return list;
2186 }
2187
2188 PyObject* KX_GameObject::PyGetMesh(PyObject* self, PyObject* args)
2189 {
2190         ShowDeprecationWarning("getMesh()", "the meshes property");
2191         
2192         int mesh = 0;
2193
2194         if (!PyArg_ParseTuple(args, "|i:getMesh", &mesh))
2195                 return NULL; // python sets a simple error
2196         
2197         if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0)
2198         {
2199                 KX_MeshProxy* meshproxy = new KX_MeshProxy(m_meshes[mesh]);
2200                 return meshproxy;
2201         }
2202         
2203         Py_RETURN_NONE;
2204 }
2205
2206
2207
2208
2209
2210 PyObject* KX_GameObject::PySetCollisionMargin(PyObject* self, PyObject* value)
2211 {
2212         float collisionMargin = PyFloat_AsDouble(value);
2213         
2214         if (collisionMargin==-1 && PyErr_Occurred()) {
2215                 PyErr_SetString(PyExc_TypeError, "expected a float");
2216                 return NULL;
2217         }
2218         
2219         if (m_pPhysicsController1)
2220         {
2221                 m_pPhysicsController1->setMargin(collisionMargin);
2222                 Py_RETURN_NONE;
2223         }
2224         PyErr_SetString(PyExc_RuntimeError, "This object has no physics controller");
2225         return NULL;
2226 }
2227
2228
2229
2230 PyObject* KX_GameObject::PyApplyImpulse(PyObject* self, PyObject* args)
2231 {
2232         PyObject* pyattach;
2233         PyObject* pyimpulse;
2234         
2235         if (!m_pPhysicsController1)     {
2236                 PyErr_SetString(PyExc_RuntimeError, "This object has no physics controller");
2237                 return NULL;
2238         }
2239         
2240         if (PyArg_ParseTuple(args, "OO:applyImpulse", &pyattach, &pyimpulse))
2241         {
2242                 MT_Point3  attach;
2243                 MT_Vector3 impulse;
2244                 if (PyVecTo(pyattach, attach) && PyVecTo(pyimpulse, impulse))
2245                 {
2246                         m_pPhysicsController1->applyImpulse(attach, impulse);
2247                         Py_RETURN_NONE;
2248                 }
2249
2250         }
2251         
2252         return NULL;
2253 }
2254
2255
2256
2257 PyObject* KX_GameObject::PySuspendDynamics(PyObject* self)
2258 {
2259         SuspendDynamics();
2260         Py_RETURN_NONE;
2261 }
2262
2263
2264
2265 PyObject* KX_GameObject::PyRestoreDynamics(PyObject* self)
2266 {
2267         RestoreDynamics();
2268         Py_RETURN_NONE;
2269 }
2270
2271
2272
2273 PyObject* KX_GameObject::PyGetOrientation(PyObject* self) //keywords
2274 {
2275         ShowDeprecationWarning("getOrientation()", "the orientation property");
2276         return PyObjectFrom(NodeGetWorldOrientation());
2277 }
2278
2279
2280
2281 PyObject* KX_GameObject::PySetOrientation(PyObject* self, PyObject* value)
2282 {
2283         ShowDeprecationWarning("setOrientation()", "the orientation property");
2284         MT_Matrix3x3 matrix;
2285         if (PyObject_IsMT_Matrix(value, 3) && PyMatTo(value, matrix))
2286         {
2287                 NodeSetLocalOrientation(matrix);
2288                 NodeUpdateGS(0.f);
2289                 Py_RETURN_NONE;
2290         }
2291
2292         MT_Quaternion quat;
2293         if (PyVecTo(value, quat))
2294         {
2295                 matrix.setRotation(quat);
2296                 NodeSetLocalOrientation(matrix);
2297                 NodeUpdateGS(0.f);
2298                 Py_RETURN_NONE;
2299         }
2300         return NULL;
2301 }
2302
2303 PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* self, PyObject* args)
2304 {
2305         PyObject* pyvect;
2306         int axis = 2; //z axis is the default
2307         float fac = 1.0;
2308         
2309         if (PyArg_ParseTuple(args,"O|if:alignAxisToVect",&pyvect,&axis, &fac))
2310         {
2311                 MT_Vector3 vect;
2312                 if (PyVecTo(pyvect, vect))
2313                 {
2314                         if (fac<=0.0) Py_RETURN_NONE; // Nothing to do.
2315                         if (fac> 1.0) fac= 1.0;
2316                         
2317                         AlignAxisToVect(vect,axis,fac);
2318                         NodeUpdateGS(0.f);
2319                         Py_RETURN_NONE;
2320                 }
2321         }
2322         return NULL;
2323 }
2324
2325 PyObject* KX_GameObject::PyGetAxisVect(PyObject* self, PyObject* value)
2326 {
2327         MT_Vector3 vect;
2328         if (PyVecTo(value, vect))
2329         {
2330                 return PyObjectFrom(NodeGetWorldOrientation() * vect);
2331         }
2332         return NULL;
2333 }
2334
2335 PyObject* KX_GameObject::PySetPosition(PyObject* self, PyObject* value)
2336 {
2337         ShowDeprecationWarning("setPosition()", "the position property");
2338         MT_Point3 pos;
2339         if (PyVecTo(value, pos))
2340         {
2341                 NodeSetLocalPosition(pos);
2342                 NodeUpdateGS(0.f);
2343                 Py_RETURN_NONE;
2344         }
2345
2346         return NULL;
2347 }
2348
2349 PyObject* KX_GameObject::PySetWorldPosition(PyObject* self, PyObject* value)
2350 {
2351         MT_Point3 pos;
2352         if (PyVecTo(value, pos))
2353         {
2354                 NodeSetWorldPosition(pos);
2355                 NodeUpdateGS(0.f);
2356                 Py_RETURN_NONE;
2357         }
2358
2359         return NULL;
2360 }
2361
2362 PyObject* KX_GameObject::PyGetPhysicsId(PyObject* self)
2363 {
2364         KX_IPhysicsController* ctrl = GetPhysicsController();
2365         uint_ptr physid=0;
2366         if (ctrl)
2367         {
2368                 physid= (uint_ptr)ctrl->GetUserData();
2369         }
2370         return PyInt_FromLong((long)physid);
2371 }
2372
2373 PyObject* KX_GameObject::PyGetPropertyNames(PyObject* self)
2374 {
2375         PyObject *list=  ConvertKeysToPython();
2376         
2377         if(m_attrlist) {
2378                 PyObject *key, *value;
2379                 Py_ssize_t pos = 0;
2380
2381                 while (PyDict_Next(m_attrlist, &pos, &key, &value)) {
2382                         PyList_Append(list, key);
2383                 }
2384         }
2385         return list;
2386 }
2387
2388 KX_PYMETHODDEF_DOC_O(KX_GameObject, getDistanceTo,
2389 "getDistanceTo(other): get distance to another point/KX_GameObject")
2390 {
2391         MT_Point3 b;
2392         if (PyVecTo(value, b))
2393         {
2394                 return PyFloat_FromDouble(NodeGetWorldPosition().distance(b));
2395         }
2396         PyErr_Clear();
2397         
2398         KX_GameObject *other;
2399         if (ConvertPythonToGameObject(value, &other, false))
2400         {
2401                 return PyFloat_FromDouble(NodeGetWorldPosition().distance(other->NodeGetWorldPosition()));
2402         }
2403         
2404         return NULL;
2405 }
2406
2407 KX_PYMETHODDEF_DOC_O(KX_GameObject, getVectTo,
2408 "getVectTo(other): get vector and the distance to another point/KX_GameObject\n"
2409 "Returns a 3-tuple with (distance,worldVector,localVector)\n")
2410 {
2411         MT_Point3 toPoint, fromPoint;
2412         MT_Vector3 toDir, locToDir;
2413         MT_Scalar distance;
2414
2415         PyObject *returnValue;
2416
2417         if (!PyVecTo(value, toPoint))
2418         {
2419                 PyErr_Clear();
2420                 
2421                 KX_GameObject *other;
2422                 if (ConvertPythonToGameObject(value, &other, false))
2423                 {
2424                         toPoint = other->NodeGetWorldPosition();
2425                 } else
2426                 {
2427                         PyErr_SetString(PyExc_TypeError, "Expected a 3D Vector or GameObject type");
2428                         return NULL;
2429                 }
2430         }
2431
2432         fromPoint = NodeGetWorldPosition();
2433         toDir = toPoint-fromPoint;
2434         distance = toDir.length();
2435
2436         if (MT_fuzzyZero(distance))
2437         {
2438                 //cout << "getVectTo() Error: Null vector!\n";
2439                 locToDir = toDir = MT_Vector3(0.0,0.0,0.0);
2440                 distance = 0.0;
2441         } else {
2442                 toDir.normalize();
2443                 locToDir = toDir * NodeGetWorldOrientation();
2444         }
2445         
2446         returnValue = PyTuple_New(3);
2447         if (returnValue) { // very unlikely to fail, python sets a memory error here.
2448                 PyTuple_SET_ITEM(returnValue, 0, PyFloat_FromDouble(distance));
2449                 PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(toDir));
2450                 PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(locToDir));
2451         }
2452         return returnValue;
2453 }
2454
2455 bool KX_GameObject::RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data)
2456 {
2457         KX_GameObject* hitKXObj = client->m_gameobject;
2458         
2459         // if X-ray option is selected, the unwnted objects were not tested, so get here only with true hit
2460         // if not, all objects were tested and the front one may not be the correct one.
2461         if (m_xray || m_testPropName.Length() == 0 || hitKXObj->GetProperty(m_testPropName) != NULL)
2462         {
2463                 m_pHitObject = hitKXObj;
2464                 return true;
2465         }
2466         // return true to stop RayCast::RayTest from looping, the above test was decisive
2467         // We would want to loop only if we want to get more than one hit point
2468         return true;
2469 }
2470
2471 /* this function is used to pre-filter the object before casting the ray on them.
2472    This is useful for "X-Ray" option when we want to see "through" unwanted object.
2473  */
2474 bool KX_GameObject::NeedRayCast(KX_ClientObjectInfo* client)
2475 {
2476         KX_GameObject* hitKXObj = client->m_gameobject;
2477         
2478         if (client->m_type > KX_ClientObjectInfo::ACTOR)
2479         {
2480                 // Unknown type of object, skip it.
2481                 // Should not occur as the sensor objects are filtered in RayTest()
2482                 printf("Invalid client type %d found in ray casting\n", client->m_type);
2483                 return false;
2484         }
2485         
2486         // if X-Ray option is selected, skip object that don't match the criteria as we see through them
2487         // if not, test all objects because we don't know yet which one will be on front
2488         if (!m_xray || m_testPropName.Length() == 0 || hitKXObj->GetProperty(m_testPropName) != NULL)
2489         {
2490                 return true;
2491         }
2492         // skip the object
2493         return false;
2494 }
2495
2496 KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo,
2497 "rayCastTo(other,dist,prop): look towards another point/KX_GameObject and return first object hit within dist that matches prop\n"
2498 " prop = property name that object must have; can be omitted => detect any object\n"
2499 " dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to other\n"
2500 " other = 3-tuple or object reference")
2501 {
2502         MT_Point3 toPoint;
2503         PyObject* pyarg;
2504         float dist = 0.0f;
2505         char *propName = NULL;
2506
2507         if (!PyArg_ParseTuple(args,"O|fs:rayCastTo", &pyarg, &dist, &propName)) {
2508                 return NULL; // python sets simple error
2509         }
2510
2511         if (!PyVecTo(pyarg, toPoint))
2512         {
2513                 KX_GameObject *other;
2514                 PyErr_Clear();
2515                 
2516                 if (ConvertPythonToGameObject(pyarg, &other, false))
2517                 {
2518                         toPoint = other->NodeGetWorldPosition();
2519                 } else
2520                 {
2521                         PyErr_SetString(PyExc_TypeError, "the first argument to rayCastTo must be a vector or a KX_GameObject");
2522                         return NULL;
2523                 }
2524         }
2525         MT_Point3 fromPoint = NodeGetWorldPosition();
2526         if (dist != 0.0f)
2527         {
2528                 MT_Vector3 toDir = toPoint-fromPoint;
2529                 toDir.normalize();
2530                 toPoint = fromPoint + (dist) * toDir;
2531         }
2532
2533         PHY_IPhysicsEnvironment* pe = GetPhysicsEnvironment();
2534         KX_IPhysicsController *spc = GetPhysicsController();
2535         KX_GameObject *parent = GetParent();
2536         if (!spc && parent)
2537                 spc = parent->GetPhysicsController();
2538         if (parent)
2539                 parent->Release();
2540         
2541         m_pHitObject = NULL;
2542         if (propName)
2543                 m_testPropName = propName;
2544         else
2545                 m_testPropName.SetLength(0);
2546         KX_RayCast::Callback<KX_GameObject> callback(this,spc);
2547         KX_RayCast::RayTest(pe, fromPoint, toPoint, callback);
2548
2549     if (m_pHitObject)
2550                 return m_pHitObject->AddRef();
2551         
2552         Py_RETURN_NONE;
2553 }
2554
2555 KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
2556                                    "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"
2557                                    " If no hit, return (None,None,None) or (None,None,None,None).\n"
2558 " to   = 3-tuple or object reference for destination of ray (if object, use center of object)\n"
2559 " from = 3-tuple or object reference for origin of ray (if object, use center of object)\n"
2560 "        Can be None or omitted => start from self object center\n"
2561 " dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to to\n"
2562 " prop = property name that object must have; can be omitted => detect any object\n"
2563 " face = normal option: 1=>return face normal; 0 or omitted => normal is oriented towards origin\n"
2564 " xray = X-ray option: 1=>skip objects that don't match prop; 0 or omitted => stop on first object\n"
2565 " poly = polygon option: 1=>return value is a 4-tuple and the 4th element is a KX_PolyProxy object\n"
2566 "                           which can be None if hit object has no mesh or if there is no hit\n"
2567 "        If 0 or omitted, return value is a 3-tuple\n"
2568 "Note: The object on which you call this method matters: the ray will ignore it.\n"
2569 "      prop and xray option interact as follow:\n"
2570 "        prop off, xray off: return closest hit or no hit if there is no object on the full extend of the ray\n"
2571 "        prop off, xray on : idem\n"
2572 "        prop on,  xray off: return closest hit if it matches prop, no hit otherwise\n"
2573 "        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")
2574 {
2575         MT_Point3 toPoint;
2576         MT_Point3 fromPoint;
2577         PyObject* pyto;
2578         PyObject* pyfrom = NULL;
2579         float dist = 0.0f;
2580         char *propName = NULL;
2581         KX_GameObject *other;
2582         int face=0, xray=0, poly=0;
2583
2584         if (!PyArg_ParseTuple(args,"O|Ofsiii:rayCast", &pyto, &pyfrom, &dist, &propName, &face, &xray, &poly)) {
2585                 return NULL; // Python sets a simple error
2586         }
2587
2588         if (!PyVecTo(pyto, toPoint))
2589         {
2590                 PyErr_Clear();
2591                 
2592                 if (ConvertPythonToGameObject(pyto, &other, false))
2593                 {
2594                         toPoint = other->NodeGetWorldPosition();
2595                 } else
2596                 {
2597                         PyErr_SetString(PyExc_TypeError, "the first argument to rayCast must be a vector or a KX_GameObject");
2598                         return NULL;
2599                 }
2600         }
2601         if (!pyfrom || pyfrom == Py_None)
2602         {
2603                 fromPoint = NodeGetWorldPosition();
2604         }
2605         else if (!PyVecTo(pyfrom, fromPoint))
2606         {
2607                 PyErr_Clear();
2608                 
2609                 if (ConvertPythonToGameObject(pyfrom, &other, false))
2610                 {
2611                         fromPoint = other->NodeGetWorldPosition();
2612                 } else
2613                 {
2614                         PyErr_SetString(PyExc_TypeError, "the second optional argument to rayCast must be a vector or a KX_GameObject");
2615                         return NULL;
2616                 }
2617         }
2618         
2619         if (dist != 0.0f) {
2620                 MT_Vector3 toDir = toPoint-fromPoint;
2621                 if (MT_fuzzyZero(toDir.length2())) {
2622                         return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
2623                 }
2624                 toDir.normalize();
2625                 toPoint = fromPoint + (dist) * toDir;
2626         } else if (MT_fuzzyZero((toPoint-fromPoint).length2())) {
2627                 return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
2628         }
2629         
2630         PHY_IPhysicsEnvironment* pe = GetPhysicsEnvironment();
2631         KX_IPhysicsController *spc = GetPhysicsController();
2632         KX_GameObject *parent = GetParent();
2633         if (!spc && parent)
2634                 spc = parent->GetPhysicsController();
2635         if (parent)
2636                 parent->Release();
2637         
2638         m_pHitObject = NULL;
2639         if (propName)
2640                 m_testPropName = propName;
2641         else
2642                 m_testPropName.SetLength(0);
2643         m_xray = xray;
2644         // to get the hit results
2645         KX_RayCast::Callback<KX_GameObject> callback(this,spc,NULL,face);
2646         KX_RayCast::RayTest(pe, fromPoint, toPoint, callback);
2647
2648         if (m_pHitObject)
2649         {
2650                 PyObject* returnValue = (poly) ? PyTuple_New(4) : PyTuple_New(3);
2651                 if (returnValue) { // unlikely this would ever fail, if it does python sets an error
2652                         PyTuple_SET_ITEM(returnValue, 0, m_pHitObject->AddRef());
2653                         PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(callback.m_hitPoint));
2654                         PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(callback.m_hitNormal));
2655                         if (poly)
2656                         {
2657                                 if (callback.m_hitMesh)
2658                                 {
2659                                         // if this field is set, then we can trust that m_hitPolygon is a valid polygon
2660                                         RAS_Polygon* polygon = callback.m_hitMesh->GetPolygon(callback.m_hitPolygon);
2661                                         KX_PolyProxy* polyproxy = new KX_PolyProxy(callback.m_hitMesh, polygon);
2662                                         PyTuple_SET_ITEM(returnValue, 3, polyproxy);
2663                                 }
2664                                 else
2665                                 {
2666                                         Py_INCREF(Py_None);
2667                                         PyTuple_SET_ITEM(returnValue, 3, Py_None);
2668                                 }
2669                         }
2670                 }
2671                 return returnValue;
2672         }
2673         // no hit
2674         if (poly)
2675                 return Py_BuildValue("OOOO", Py_None, Py_None, Py_None, Py_None);
2676         else
2677                 return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
2678 }
2679
2680 KX_PYMETHODDEF_DOC_VARARGS(KX_GameObject, sendMessage, 
2681                                                    "sendMessage(subject, [body, to])\n"
2682 "sends a message in same manner as a message actuator"
2683 "subject = Subject of the message (string)"
2684 "body = Message body (string)"
2685 "to = Name of object to send the message to")
2686 {
2687         char* subject;
2688         char* body = "";
2689         char* to = "";
2690         const STR_String& from = GetName();
2691
2692         if (!PyArg_ParseTuple(args, "s|sss:sendMessage", &subject, &body, &to))
2693                 return NULL;
2694
2695         KX_GetActiveScene()->GetNetworkScene()->SendMessage(to, from, subject, body);
2696
2697         Py_RETURN_NONE;
2698 }
2699
2700 /* --------------------------------------------------------------------- 
2701  * Some stuff taken from the header
2702  * --------------------------------------------------------------------- */
2703 void KX_GameObject::Relink(GEN_Map<GEN_HashedPtr, void*> *map_parameter)        
2704 {
2705         // we will relink the sensors and actuators that use object references
2706         // if the object is part of the replicated hierarchy, use the new
2707         // object reference instead
2708         SCA_SensorList& sensorlist = GetSensors();
2709         SCA_SensorList::iterator sit;
2710         for (sit=sensorlist.begin(); sit != sensorlist.end(); sit++)
2711         {
2712                 (*sit)->Relink(map_parameter);
2713         }
2714         SCA_ActuatorList& actuatorlist = GetActuators();
2715         SCA_ActuatorList::iterator ait;
2716         for (ait=actuatorlist.begin(); ait != actuatorlist.end(); ait++)
2717         {
2718                 (*ait)->Relink(map_parameter);
2719         }
2720 }
2721
2722 bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py_none_ok)
2723 {
2724         if (value==NULL) {
2725                 PyErr_SetString(PyExc_TypeError, "Error in ConvertPythonToGameObject, python pointer NULL, should never happen");
2726                 *object = NULL;
2727                 return false;
2728         }
2729                 
2730         if (value==Py_None) {
2731                 *object = NULL;
2732                 
2733                 if (py_none_ok) {
2734                         return true;
2735                 } else {
2736                         PyErr_SetString(PyExc_TypeError, "Expected KX_GameObject or a string for a name of a KX_GameObject, None is invalid");
2737                         return false;
2738                 }
2739         }
2740         
2741         if (PyString_Check(value)) {
2742                 *object = (KX_GameObject *)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String( PyString_AsString(value) ));
2743                 
2744                 if (*object) {
2745                         return true;
2746                 } else {
2747                         PyErr_SetString(PyExc_ValueError, "Requested name did not match any KX_GameObject");
2748                         return false;
2749                 }
2750         }
2751         
2752         if (PyObject_TypeCheck(value, &KX_GameObject::Type)) {
2753                 *object = static_cast<KX_GameObject*>(value);
2754                 
2755                 /* sets the error */
2756                 if (ValidPythonToGameObject(*object)==false)
2757                         return false;
2758                 
2759                 return true;
2760         }
2761         
2762         *object = NULL;
2763         
2764         if (py_none_ok) {
2765                 PyErr_SetString(PyExc_TypeError, "Expect a KX_GameObject, a string or None");
2766         } else {
2767                 PyErr_SetString(PyExc_TypeError, "Expect a KX_GameObject or a string");
2768         }
2769         
2770         return false;
2771 }
2772
2773 bool ValidPythonToGameObject(KX_GameObject *object)
2774 {
2775         if (object->GetSGNode()==NULL) {
2776                 PyErr_Format(
2777                                 PyExc_RuntimeError,
2778                                 "KX_GameObject \"%s\" is not longer in a scene, "
2779                                 "check for this case with the \"isValid\" attribute",
2780                                 object->GetName().ReadPtr() );
2781                 return false;
2782         }
2783         
2784         return true;
2785 }