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