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