3d9c7aafd70f1183479b117b680e13f6a2157d52
[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 <stdio.h> // printf
55 #include "SG_Controller.h"
56 #include "KX_IPhysicsController.h"
57 #include "SG_Node.h"
58 #include "SG_Controller.h"
59 #include "KX_ClientObjectInfo.h"
60 #include "RAS_BucketManager.h"
61 #include "KX_RayCast.h"
62 #include "KX_PythonInit.h"
63 #include "KX_PyMath.h"
64 #include "SCA_IActuator.h"
65 #include "SCA_ISensor.h"
66
67 // This file defines relationships between parents and children
68 // in the game engine.
69
70 #include "KX_SG_NodeRelationships.h"
71
72 KX_GameObject::KX_GameObject(
73         void* sgReplicationInfo,
74         SG_Callbacks callbacks,
75         PyTypeObject* T
76 ) : 
77         SCA_IObject(T),
78         m_bDyna(false),
79         m_layer(0),
80         m_bSuspendDynamics(false),
81         m_bUseObjectColor(false),
82         m_bIsNegativeScaling(false),
83         m_pBlenderObject(NULL),
84         m_bVisible(true),
85         m_pPhysicsController1(NULL),
86         m_pPhysicsEnvironment(NULL),
87         m_pHitObject(NULL),
88         m_isDeformable(false)
89 {
90         m_ignore_activity_culling = false;
91         m_pClient_info = new KX_ClientObjectInfo(this, KX_ClientObjectInfo::ACTOR);
92         m_pSGNode = new SG_Node(this,sgReplicationInfo,callbacks);
93
94         // define the relationship between this node and it's parent.
95         
96         KX_NormalParentRelation * parent_relation = 
97                 KX_NormalParentRelation::New();
98         m_pSGNode->SetParentRelation(parent_relation);
99         
100
101 };
102
103
104
105 KX_GameObject::~KX_GameObject()
106 {
107         // is this delete somewhere ?
108         //if (m_sumoObj)
109         //      delete m_sumoObj;
110         delete m_pClient_info;
111         //if (m_pSGNode)
112         //      delete m_pSGNode;
113         if (m_pSGNode)
114         {
115                 // must go through controllers and make sure they will not use us anymore
116                 // This is important for KX_BulletPhysicsControllers that unregister themselves
117                 // from the object when they are deleted.
118                 SGControllerList::iterator contit;
119                 SGControllerList& controllers = m_pSGNode->GetSGControllerList();
120                 for (contit = controllers.begin();contit!=controllers.end();++contit)
121                 {
122                         (*contit)->ClearObject();
123                 }
124                 m_pSGNode->SetSGClientObject(NULL);
125         }
126 }
127
128
129
130 CValue* KX_GameObject:: Calc(VALUE_OPERATOR op, CValue *val) 
131 {
132         return NULL;
133 }
134
135
136
137 CValue* KX_GameObject::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val)
138 {
139         return NULL;
140 }
141
142
143
144 const STR_String & KX_GameObject::GetText()
145 {
146         return m_text;
147 }
148
149
150
151 float KX_GameObject::GetNumber()
152 {
153         return 0;
154 }
155
156
157
158 STR_String KX_GameObject::GetName()
159 {
160         return m_name;
161 }
162
163
164
165 void KX_GameObject::SetName(STR_String name)
166 {
167         m_name = name;
168 };                                                              // Set the name of the value
169
170
171
172 void KX_GameObject::ReplicaSetName(STR_String name)
173 {
174 }
175
176
177
178
179
180
181 KX_IPhysicsController* KX_GameObject::GetPhysicsController()
182 {
183         return m_pPhysicsController1;
184 }
185
186
187
188
189
190 KX_GameObject* KX_GameObject::GetParent()
191 {
192         KX_GameObject* result = NULL;
193         SG_Node* node = m_pSGNode;
194         
195         while (node && !result)
196         {
197                 node = node->GetSGParent();
198                 if (node)
199                         result = (KX_GameObject*)node->GetSGClientObject();
200         }
201         
202         if (result)
203                 result->AddRef();
204
205         return result;
206         
207 }
208
209 void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj)
210 {
211         if (obj && GetSGNode()->GetSGParent() != obj->GetSGNode())
212         {
213                 // Make sure the objects have some scale
214                 MT_Vector3 scale1 = NodeGetWorldScaling();
215                 MT_Vector3 scale2 = obj->NodeGetWorldScaling();
216                 if (fabs(scale2[0]) < FLT_EPSILON || 
217                         fabs(scale2[1]) < FLT_EPSILON || 
218                         fabs(scale2[2]) < FLT_EPSILON || 
219                         fabs(scale1[0]) < FLT_EPSILON || 
220                         fabs(scale1[1]) < FLT_EPSILON || 
221                         fabs(scale1[2]) < FLT_EPSILON) { return; }
222
223                 // Remove us from our old parent and set our new parent
224                 RemoveParent(scene);
225                 obj->GetSGNode()->AddChild(GetSGNode());
226
227                 if (m_pPhysicsController1) 
228                 {
229                         m_pPhysicsController1->SuspendDynamics(true);
230                 }
231                 // Set us to our new scale, position, and orientation
232                 scale1[0] = scale1[0]/scale2[0];
233                 scale1[1] = scale1[1]/scale2[1];
234                 scale1[2] = scale1[2]/scale2[2];
235                 MT_Matrix3x3 invori = obj->NodeGetWorldOrientation().inverse();
236                 MT_Vector3 newpos = invori*(NodeGetWorldPosition()-obj->NodeGetWorldPosition())*scale1;
237
238                 NodeSetLocalScale(scale1);
239                 NodeSetLocalPosition(MT_Point3(newpos[0],newpos[1],newpos[2]));
240                 NodeSetLocalOrientation(invori*NodeGetWorldOrientation());
241                 NodeUpdateGS(0.f,true);
242                 // object will now be a child, it must be removed from the parent list
243                 CListValue* rootlist = scene->GetRootParentList();
244                 if (rootlist->RemoveValue(this))
245                         // the object was in parent list, decrement ref count as it's now removed
246                         Release();
247         }
248 }
249
250 void KX_GameObject::RemoveParent(KX_Scene *scene)
251 {
252         if (GetSGNode()->GetSGParent())
253         {
254                 // Set us to the right spot 
255                 GetSGNode()->SetLocalScale(GetSGNode()->GetWorldScaling());
256                 GetSGNode()->SetLocalOrientation(GetSGNode()->GetWorldOrientation());
257                 GetSGNode()->SetLocalPosition(GetSGNode()->GetWorldPosition());
258
259                 // Remove us from our parent
260                 GetSGNode()->DisconnectFromParent();
261                 NodeUpdateGS(0.f,true);
262                 // the object is now a root object, add it to the parentlist
263                 CListValue* rootlist = scene->GetRootParentList();
264                 if (!rootlist->SearchValue(this))
265                         // object was not in root list, add it now and increment ref count
266                         rootlist->Add(AddRef());
267                 if (m_pPhysicsController1) 
268                 {
269                         m_pPhysicsController1->RestoreDynamics();
270                 }
271         }
272 }
273
274 void KX_GameObject::ProcessReplica(KX_GameObject* replica)
275 {
276         replica->m_pPhysicsController1 = NULL;
277         replica->m_pSGNode = NULL;
278         replica->m_pClient_info = new KX_ClientObjectInfo(*m_pClient_info);
279         replica->m_pClient_info->m_gameobject = replica;
280 }
281
282
283
284 CValue* KX_GameObject::GetReplica()
285 {
286         KX_GameObject* replica = new KX_GameObject(*this);
287         
288         // this will copy properties and so on...
289         CValue::AddDataToReplica(replica);
290         ProcessReplica(replica);
291         
292         return replica;
293 }
294
295
296
297 void KX_GameObject::ApplyForce(const MT_Vector3& force,bool local)
298 {
299         if (m_pPhysicsController1)
300                 m_pPhysicsController1->ApplyForce(force,local);
301 }
302
303
304
305 void KX_GameObject::ApplyTorque(const MT_Vector3& torque,bool local)
306 {
307         if (m_pPhysicsController1)
308                 m_pPhysicsController1->ApplyTorque(torque,local);
309 }
310
311
312
313 void KX_GameObject::ApplyMovement(const MT_Vector3& dloc,bool local)
314 {
315         if (m_pPhysicsController1) // (IsDynamic())
316         {
317                 m_pPhysicsController1->RelativeTranslate(dloc,local);
318         }
319         GetSGNode()->RelativeTranslate(dloc,GetSGNode()->GetSGParent(),local);
320 }
321
322
323
324 void KX_GameObject::ApplyRotation(const MT_Vector3& drot,bool local)
325 {
326         MT_Matrix3x3 rotmat(drot);
327
328         GetSGNode()->RelativeRotate(rotmat,local);
329
330         if (m_pPhysicsController1) { // (IsDynamic())
331                 m_pPhysicsController1->RelativeRotate(rotmat,local); 
332         }
333 }
334
335
336
337 /**
338 GetOpenGL Matrix, returns an OpenGL 'compatible' matrix
339 */
340 double* KX_GameObject::GetOpenGLMatrix()
341 {
342         // todo: optimize and only update if necessary
343         double* fl = m_OpenGL_4x4Matrix.getPointer();
344         MT_Transform trans;
345         
346         trans.setOrigin(GetSGNode()->GetWorldPosition());
347         trans.setBasis(GetSGNode()->GetWorldOrientation());
348         
349         MT_Vector3 scaling = GetSGNode()->GetWorldScaling();
350         m_bIsNegativeScaling = ((scaling[0] < 0.0) ^ (scaling[1] < 0.0) ^ (scaling[2] < 0.0)) ? true : false;
351         trans.scale(scaling[0], scaling[1], scaling[2]);
352         trans.getValue(fl);
353
354         return fl;
355 }
356
357
358
359 void KX_GameObject::Bucketize()
360 {
361         double* fl = GetOpenGLMatrix();
362
363         for (size_t i=0;i<m_meshes.size();i++)
364                 m_meshes[i]->Bucketize(fl, this, m_bUseObjectColor, m_objectColor);
365 }
366
367
368
369 void KX_GameObject::RemoveMeshes()
370 {
371         double* fl = GetOpenGLMatrix();
372
373         for (size_t i=0;i<m_meshes.size();i++)
374                 m_meshes[i]->RemoveFromBuckets(fl, this);
375
376         //note: meshes can be shared, and are deleted by KX_BlenderSceneConverter
377
378         m_meshes.clear();
379 }
380
381
382
383 void KX_GameObject::UpdateNonDynas()
384 {
385         if (m_pPhysicsController1)
386         {
387                 m_pPhysicsController1->SetSumoTransform(true);
388         }
389 }
390
391
392
393 void KX_GameObject::UpdateTransform()
394 {
395         if (m_pPhysicsController1)
396                 m_pPhysicsController1->SetSumoTransform(false);
397 }
398
399 void KX_GameObject::UpdateTransformFunc(SG_IObject* node, void* gameobj, void* scene)
400 {
401         ((KX_GameObject*)gameobj)->UpdateTransform();
402 }
403
404
405 void KX_GameObject::SetDebugColor(unsigned int bgra)
406 {
407         for (size_t i=0;i<m_meshes.size();i++)
408                 m_meshes[i]->DebugColor(bgra);  
409 }
410
411
412
413 void KX_GameObject::ResetDebugColor()
414 {
415         SetDebugColor(0xff000000);
416 }
417
418 void KX_GameObject::InitIPO(bool ipo_as_force,
419                                                         bool ipo_add,
420                                                         bool ipo_local)
421 {
422         SGControllerList::iterator it = GetSGNode()->GetSGControllerList().begin();
423
424         while (it != GetSGNode()->GetSGControllerList().end()) {
425                 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_RESET, true);
426                 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_AS_FORCE, ipo_as_force);
427                 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_ADD, ipo_add);
428                 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_LOCAL, ipo_local);
429                 it++;
430         }
431
432
433 void KX_GameObject::UpdateIPO(float curframetime,
434                                                           bool recurse) 
435 {
436         // just the 'normal' update procedure.
437         GetSGNode()->SetSimulatedTime(curframetime,recurse);
438         GetSGNode()->UpdateWorldData(curframetime);
439         UpdateTransform();
440 }
441
442 // IPO update
443 void 
444 KX_GameObject::UpdateMaterialData(
445                 dword matname_hash,
446                 MT_Vector4 rgba,
447                 MT_Vector3 specrgb,
448                 MT_Scalar hard,
449                 MT_Scalar spec,
450                 MT_Scalar ref,
451                 MT_Scalar emit,
452                 MT_Scalar alpha
453
454         )
455 {
456         int mesh = 0;
457         if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0) {
458                 RAS_MaterialBucket::Set::iterator mit = m_meshes[mesh]->GetFirstMaterial();
459                 for(; mit != m_meshes[mesh]->GetLastMaterial(); ++mit)
460                 {
461                         RAS_IPolyMaterial* poly = (*mit)->GetPolyMaterial();
462                         if(poly->GetFlag() & RAS_BLENDERMAT )
463                         {
464                                 KX_BlenderMaterial *m =  static_cast<KX_BlenderMaterial*>(poly);
465                                 
466                                 if (matname_hash == NULL)
467                                 {
468                                         m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha);
469                                         // if mesh has only one material attached to it then use original hack with no need to edit vertices (better performance)
470                                         SetObjectColor(rgba);
471                                 }
472                                 else
473                                 {
474                                         if (matname_hash == poly->GetMaterialNameHash())
475                                         {
476                                                 m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha);
477                                                 m_meshes[mesh]->SetVertexColor(poly,rgba);
478                                                 
479                                                 // no break here, because one blender material can be split into several game engine materials
480                                                 // (e.g. one uvsphere material is split into one material at poles with ras_mode TRIANGLE and one material for the body
481                                                 // if here was a break then would miss some vertices if material was split
482                                         }
483                                 }
484                         }
485                 }
486         }
487 }
488 bool
489 KX_GameObject::GetVisible(
490         void
491         )
492 {
493         return m_bVisible;
494 }
495
496 void
497 KX_GameObject::SetVisible(
498         bool v
499         )
500 {
501         m_bVisible = v;
502 }
503
504 void
505 KX_GameObject::SetLayer(
506         int l
507         )
508 {
509         m_layer = l;
510 }
511
512 int
513 KX_GameObject::GetLayer(
514         void
515         )
516 {
517         return m_layer;
518 }
519
520 // used by Python, and the actuatorshould _not_ be misused by the
521 // scene!
522 void 
523 KX_GameObject::MarkVisible(
524         bool visible
525         )
526 {
527         /* If explicit visibility settings are used, this is
528          * determined on this level. Maybe change this to mesh level
529          * later on? */
530         
531         double* fl = GetOpenGLMatrixPtr()->getPointer();
532         for (size_t i=0;i<m_meshes.size();i++)
533         {
534                 m_meshes[i]->MarkVisible(fl,this,visible,m_bUseObjectColor,m_objectColor);
535         }
536 }
537
538
539 // Always use the flag?
540 void 
541 KX_GameObject::MarkVisible(
542         void
543         )
544 {
545         double* fl = GetOpenGLMatrixPtr()->getPointer();
546         for (size_t i=0;i<m_meshes.size();i++)
547         {
548                 m_meshes[i]->MarkVisible(fl,
549                                          this,
550                                          m_bVisible,
551                                          m_bUseObjectColor,
552                                          m_objectColor
553                         );
554         }
555 }
556
557
558 void KX_GameObject::addLinearVelocity(const MT_Vector3& lin_vel,bool local)
559 {
560         if (m_pPhysicsController1)
561                 m_pPhysicsController1->SetLinearVelocity(lin_vel + m_pPhysicsController1->GetLinearVelocity(),local);
562 }
563
564
565
566 void KX_GameObject::setLinearVelocity(const MT_Vector3& lin_vel,bool local)
567 {
568         if (m_pPhysicsController1)
569                 m_pPhysicsController1->SetLinearVelocity(lin_vel,local);
570 }
571
572
573
574 void KX_GameObject::setAngularVelocity(const MT_Vector3& ang_vel,bool local)
575 {
576         if (m_pPhysicsController1)
577                 m_pPhysicsController1->SetAngularVelocity(ang_vel,local);
578 }
579
580 void KX_GameObject::ResolveCombinedVelocities(
581         const MT_Vector3 & lin_vel,
582         const MT_Vector3 & ang_vel,
583         bool lin_vel_local,
584         bool ang_vel_local
585 ){
586         if (m_pPhysicsController1)
587         {
588
589                 MT_Vector3 lv = lin_vel_local ? NodeGetWorldOrientation() * lin_vel : lin_vel;
590                 MT_Vector3 av = ang_vel_local ? NodeGetWorldOrientation() * ang_vel : ang_vel;
591                 m_pPhysicsController1->resolveCombinedVelocities(
592                         lv.x(),lv.y(),lv.z(),av.x(),av.y(),av.z());
593         }
594 }
595
596
597 void KX_GameObject::SetObjectColor(const MT_Vector4& rgbavec)
598 {
599         m_bUseObjectColor = true;
600         m_objectColor = rgbavec;
601 }
602
603 void KX_GameObject::AlignAxisToVect(const MT_Vector3& dir, int axis, float fac)
604 {
605         MT_Matrix3x3 orimat;
606         MT_Vector3 vect,ori,z,x,y;
607         MT_Scalar len;
608
609         vect = dir;
610         len = vect.length();
611         if (MT_fuzzyZero(len))
612         {
613                 cout << "alignAxisToVect() Error: Null vector!\n";
614                 return;
615         }
616         
617         if (fac<=0.0) {
618                 return;
619         }
620         
621         // normalize
622         vect /= len;
623         orimat = GetSGNode()->GetWorldOrientation();
624         switch (axis)
625         {       
626                 case 0: //x axis
627                         ori = MT_Vector3(orimat[0][2], orimat[1][2], orimat[2][2]); //pivot axis
628                         if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON) //is the vector paralell to the pivot?
629                                 ori = MT_Vector3(orimat[0][1], orimat[1][1], orimat[2][1]); //change the pivot!
630                         if (fac == 1.0) {
631                                 x = vect;
632                         } else {
633                                 x = (vect * fac) + ((orimat * MT_Vector3(1.0, 0.0, 0.0)) * (1-fac));
634                                 len = x.length();
635                                 if (MT_fuzzyZero(len)) x = vect;
636                                 else x /= len;
637                         }
638                         y = ori.cross(x);
639                         z = x.cross(y);
640                         break;
641                 case 1: //y axis
642                         ori = MT_Vector3(orimat[0][0], orimat[1][0], orimat[2][0]);
643                         if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON)
644                                 ori = MT_Vector3(orimat[0][2], orimat[1][2], orimat[2][2]);
645                         if (fac == 1.0) {
646                                 y = vect;
647                         } else {
648                                 y = (vect * fac) + ((orimat * MT_Vector3(0.0, 1.0, 0.0)) * (1-fac));
649                                 len = y.length();
650                                 if (MT_fuzzyZero(len)) y = vect;
651                                 else y /= len;
652                         }
653                         z = ori.cross(y);
654                         x = y.cross(z);
655                         break;
656                 case 2: //z axis
657                         ori = MT_Vector3(orimat[0][1], orimat[1][1], orimat[2][1]);
658                         if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON)
659                                 ori = MT_Vector3(orimat[0][0], orimat[1][0], orimat[2][0]);
660                         if (fac == 1.0) {
661                                 z = vect;
662                         } else {
663                                 z = (vect * fac) + ((orimat * MT_Vector3(0.0, 0.0, 1.0)) * (1-fac));
664                                 len = z.length();
665                                 if (MT_fuzzyZero(len)) z = vect;
666                                 else z /= len;
667                         }
668                         x = ori.cross(z);
669                         y = z.cross(x);
670                         break;
671                 default: //wrong input?
672                         cout << "alignAxisToVect(): Wrong axis '" << axis <<"'\n";
673                         return;
674         }
675         x.normalize(); //normalize the vectors
676         y.normalize();
677         z.normalize();
678         orimat = MT_Matrix3x3(  x[0],y[0],z[0],
679                                                         x[1],y[1],z[1],
680                                                         x[2],y[2],z[2]);
681         if (GetSGNode()->GetSGParent() != NULL)
682         {
683                 // the object is a child, adapt its local orientation so that 
684                 // the global orientation is aligned as we want.
685                 MT_Matrix3x3 invori = GetSGNode()->GetSGParent()->GetWorldOrientation().inverse();
686                 NodeSetLocalOrientation(invori*orimat);
687         }
688         else
689                 NodeSetLocalOrientation(orimat);
690 }
691
692 MT_Scalar KX_GameObject::GetMass()
693 {
694         if (m_pPhysicsController1)
695         {
696                 return m_pPhysicsController1->GetMass();
697         }
698         return 0.0;
699 }
700
701 MT_Vector3 KX_GameObject::GetLinearVelocity(bool local)
702 {
703         MT_Vector3 velocity(0.0,0.0,0.0), locvel;
704         MT_Matrix3x3 ori;
705         if (m_pPhysicsController1)
706         {
707                 velocity = m_pPhysicsController1->GetLinearVelocity();
708                 
709                 if (local)
710                 {
711                         ori = GetSGNode()->GetWorldOrientation();
712                         
713                         locvel = velocity * ori;
714                         return locvel;
715                 }
716         }
717         return velocity;        
718 }
719
720 MT_Vector3 KX_GameObject::GetAngularVelocity(bool local)
721 {
722         MT_Vector3 velocity(0.0,0.0,0.0), locvel;
723         MT_Matrix3x3 ori;
724         if (m_pPhysicsController1)
725         {
726                 velocity = m_pPhysicsController1->GetAngularVelocity();
727                 
728                 if (local)
729                 {
730                         ori = GetSGNode()->GetWorldOrientation();
731                         
732                         locvel = velocity * ori;
733                         return locvel;
734                 }
735         }
736         return velocity;        
737 }
738
739
740
741 // scenegraph node stuff
742
743 void KX_GameObject::NodeSetLocalPosition(const MT_Point3& trans)
744 {
745         if (m_pPhysicsController1 && (!GetSGNode() || !GetSGNode()->GetSGParent()))
746         {
747                 // don't update physic controller if the object is a child:
748                 // 1) the transformation will not be right
749                 // 2) in this case, the physic controller is necessarily a static object
750                 //    that is updated from the normal kinematic synchronization
751                 m_pPhysicsController1->setPosition(trans);
752         }
753
754         if (GetSGNode())
755                 GetSGNode()->SetLocalPosition(trans);
756 }
757
758
759
760 void KX_GameObject::NodeSetLocalOrientation(const MT_Matrix3x3& rot)
761 {
762         if (m_pPhysicsController1 && (!GetSGNode() || !GetSGNode()->GetSGParent()))
763         {
764                 // see note above
765                 m_pPhysicsController1->setOrientation(rot);
766         }
767         if (GetSGNode())
768                 GetSGNode()->SetLocalOrientation(rot);
769 }
770
771
772
773 void KX_GameObject::NodeSetLocalScale(const MT_Vector3& scale)
774 {
775         if (m_pPhysicsController1 && (!GetSGNode() || !GetSGNode()->GetSGParent()))
776         {
777                 // see note above
778                 m_pPhysicsController1->setScaling(scale);
779         }
780         
781         if (GetSGNode())
782                 GetSGNode()->SetLocalScale(scale);
783 }
784
785
786
787 void KX_GameObject::NodeSetRelativeScale(const MT_Vector3& scale)
788 {
789         if (GetSGNode())
790                 GetSGNode()->RelativeScale(scale);
791 }
792
793 void KX_GameObject::NodeSetWorldPosition(const MT_Point3& trans)
794 {
795         SG_Node* parent = m_pSGNode->GetSGParent();
796         if (parent != NULL)
797         {
798                 // Make sure the objects have some scale
799                 MT_Vector3 scale = parent->GetWorldScaling();
800                 if (fabs(scale[0]) < FLT_EPSILON || 
801                         fabs(scale[1]) < FLT_EPSILON || 
802                         fabs(scale[2]) < FLT_EPSILON)
803                 { 
804                         return; 
805                 }
806                 scale[0] = 1.0/scale[0];
807                 scale[1] = 1.0/scale[1];
808                 scale[2] = 1.0/scale[2];
809                 MT_Matrix3x3 invori = parent->GetWorldOrientation().inverse();
810                 MT_Vector3 newpos = invori*(trans-parent->GetWorldPosition())*scale;
811                 NodeSetLocalPosition(MT_Point3(newpos[0],newpos[1],newpos[2]));
812         }
813         else 
814         {
815                 NodeSetLocalPosition(trans);
816         }
817 }
818
819
820 void KX_GameObject::NodeUpdateGS(double time,bool bInitiator)
821 {
822         if (GetSGNode())
823                 GetSGNode()->UpdateWorldData(time);
824 }
825
826
827
828 const MT_Matrix3x3& KX_GameObject::NodeGetWorldOrientation() const
829 {
830         return GetSGNode()->GetWorldOrientation();
831 }
832
833
834
835 const MT_Vector3& KX_GameObject::NodeGetWorldScaling() const
836 {
837         return GetSGNode()->GetWorldScaling();
838 }
839
840
841
842 const MT_Point3& KX_GameObject::NodeGetWorldPosition() const
843 {
844         return GetSGNode()->GetWorldPosition();
845 }
846
847 /* Suspend/ resume: for the dynamic behaviour, there is a simple
848  * method. For the residual motion, there is not. I wonder what the
849  * correct solution is for Sumo. Remove from the motion-update tree?
850  *
851  * So far, only switch the physics and logic.
852  * */
853
854 void KX_GameObject::Resume(void)
855 {
856         if (m_suspended) {
857                 SCA_IObject::Resume();
858                 GetPhysicsController()->RestoreDynamics();
859
860                 m_suspended = false;
861         }
862 }
863
864 void KX_GameObject::Suspend()
865 {
866         if ((!m_ignore_activity_culling) 
867                 && (!m_suspended))  {
868                 SCA_IObject::Suspend();
869                 GetPhysicsController()->SuspendDynamics();
870                 m_suspended = true;
871         }
872 }
873
874
875
876
877 /* ------- python stuff ---------------------------------------------------*/
878
879
880
881
882 PyMethodDef KX_GameObject::Methods[] = {
883         {"getPosition", (PyCFunction) KX_GameObject::sPyGetPosition, METH_NOARGS},
884         {"setPosition", (PyCFunction) KX_GameObject::sPySetPosition, METH_O},
885         {"getLinearVelocity", (PyCFunction) KX_GameObject::sPyGetLinearVelocity, METH_VARARGS},
886         {"setLinearVelocity", (PyCFunction) KX_GameObject::sPySetLinearVelocity, METH_VARARGS},
887         {"getVelocity", (PyCFunction) KX_GameObject::sPyGetVelocity, METH_VARARGS},
888         {"getMass", (PyCFunction) KX_GameObject::sPyGetMass, METH_NOARGS},
889         {"getReactionForce", (PyCFunction) KX_GameObject::sPyGetReactionForce, METH_NOARGS},
890         {"getOrientation", (PyCFunction) KX_GameObject::sPyGetOrientation, METH_NOARGS},
891         {"setOrientation", (PyCFunction) KX_GameObject::sPySetOrientation, METH_O},
892         {"getVisible",(PyCFunction) KX_GameObject::sPyGetVisible, METH_NOARGS},
893         {"setVisible",(PyCFunction) KX_GameObject::sPySetVisible, METH_O},
894         {"getState",(PyCFunction) KX_GameObject::sPyGetState, METH_NOARGS},
895         {"setState",(PyCFunction) KX_GameObject::sPySetState, METH_O},
896         {"alignAxisToVect",(PyCFunction) KX_GameObject::sPyAlignAxisToVect, METH_VARARGS},
897         {"getAxisVect",(PyCFunction) KX_GameObject::sPyGetAxisVect, METH_O},
898         {"suspendDynamics", (PyCFunction)KX_GameObject::sPySuspendDynamics,METH_NOARGS},
899         {"restoreDynamics", (PyCFunction)KX_GameObject::sPyRestoreDynamics,METH_NOARGS},
900         {"enableRigidBody", (PyCFunction)KX_GameObject::sPyEnableRigidBody,METH_NOARGS},
901         {"disableRigidBody", (PyCFunction)KX_GameObject::sPyDisableRigidBody,METH_NOARGS},
902         {"applyImpulse", (PyCFunction) KX_GameObject::sPyApplyImpulse, METH_VARARGS},
903         {"setCollisionMargin", (PyCFunction) KX_GameObject::sPySetCollisionMargin, METH_O},
904         {"getParent", (PyCFunction)KX_GameObject::sPyGetParent,METH_NOARGS},
905         {"setParent", (PyCFunction)KX_GameObject::sPySetParent,METH_O},
906         {"removeParent", (PyCFunction)KX_GameObject::sPyRemoveParent,METH_NOARGS},
907         {"getChildren", (PyCFunction)KX_GameObject::sPyGetChildren,METH_NOARGS},
908         {"getChildrenRecursive", (PyCFunction)KX_GameObject::sPyGetChildrenRecursive,METH_NOARGS},
909         {"getMesh", (PyCFunction)KX_GameObject::sPyGetMesh,METH_VARARGS},
910         {"getPhysicsId", (PyCFunction)KX_GameObject::sPyGetPhysicsId,METH_NOARGS},
911         {"getPropertyNames", (PyCFunction)KX_GameObject::sPyGetPropertyNames,METH_NOARGS},
912         {"endObject",(PyCFunction) KX_GameObject::sPyEndObject, METH_NOARGS},
913         KX_PYMETHODTABLE(KX_GameObject, rayCastTo),
914         KX_PYMETHODTABLE(KX_GameObject, rayCast),
915         KX_PYMETHODTABLE(KX_GameObject, getDistanceTo),
916         {NULL,NULL} //Sentinel
917 };
918
919
920
921 /*
922 bool KX_GameObject::ConvertPythonVectorArgs(PyObject* args,
923                                                                                         MT_Vector3& pos,
924                                                                                         MT_Vector3& pos2)
925 {
926         PyObject* pylist;
927         PyObject* pylist2;
928         bool error = (PyArg_ParseTuple(args,"OO",&pylist,&pylist2)) != 0;
929
930         pos = ConvertPythonPylist(pylist);
931         pos2 = ConvertPythonPylist(pylist2);
932                 
933         return error;
934 }
935 */
936
937 PyObject* KX_GameObject::PyEndObject(PyObject* self)
938 {
939
940         KX_Scene *scene = PHY_GetActiveScene();
941         scene->DelayedRemoveObject(this);
942         
943         return Py_None;
944
945 }
946
947
948 PyObject* KX_GameObject::PyGetPosition(PyObject* self)
949 {
950         return PyObjectFrom(NodeGetWorldPosition());
951 }
952
953
954
955 PyTypeObject KX_GameObject::Type = {
956         PyObject_HEAD_INIT(&PyType_Type)
957                 0,
958                 "KX_GameObject",
959                 sizeof(KX_GameObject),
960                 0,
961                 PyDestructor,
962                 0,
963                 __getattr,
964                 __setattr,
965                 0, //&MyPyCompare,
966                 __repr,
967                 0, //&cvalue_as_number,
968                 0,
969                 0,
970                 0,
971                 0
972 };
973
974
975
976 PyParentObject KX_GameObject::Parents[] = {
977         &KX_GameObject::Type,
978                 &SCA_IObject::Type,
979                 &CValue::Type,
980                 NULL
981 };
982
983
984
985
986 PyObject* KX_GameObject::_getattr(const STR_String& attr)
987 {
988         if (m_pPhysicsController1)
989         {
990                 if (attr == "mass")
991                         return PyFloat_FromDouble(GetPhysicsController()->GetMass());
992         }
993
994         if (attr == "parent")
995         {       
996                 KX_GameObject* parent = GetParent();
997                 if (parent)
998                 {
999                         parent->AddRef();
1000                         return parent;
1001                 }
1002                 Py_RETURN_NONE;
1003         }
1004
1005         if (attr == "visible")
1006                 return PyInt_FromLong(m_bVisible);
1007         
1008         if (attr == "position")
1009                 return PyObjectFrom(NodeGetWorldPosition());
1010         
1011         if (attr == "orientation")
1012                 return PyObjectFrom(NodeGetWorldOrientation());
1013         
1014         if (attr == "scaling")
1015                 return PyObjectFrom(NodeGetWorldScaling());
1016                 
1017         if (attr == "name")
1018                 return PyString_FromString(m_name.ReadPtr());
1019         if (attr == "timeOffset") {
1020                 if (m_pSGNode->GetSGParent()->IsSlowParent()) {
1021                         return PyFloat_FromDouble(static_cast<KX_SlowParentRelation *>(m_pSGNode->GetSGParent()->GetParentRelation())->GetTimeOffset());
1022                 } else {
1023                         return PyFloat_FromDouble(0.0);
1024                 }
1025         }
1026         
1027         
1028         _getattr_up(SCA_IObject);
1029 }
1030
1031 int KX_GameObject::_setattr(const STR_String& attr, PyObject *value)    // _setattr method
1032 {
1033         if (attr == "mass")
1034                 return 1;
1035         
1036         if (attr == "parent")
1037                 return 1;
1038                 
1039         if (PyInt_Check(value))
1040         {
1041                 int val = PyInt_AsLong(value);
1042                 if (attr == "visible")
1043                 {
1044                         SetVisible(val != 0);
1045                         return 0;
1046                 }
1047         }
1048
1049         if (PyFloat_Check(value))
1050         {
1051                 MT_Scalar val = PyFloat_AsDouble(value);
1052                 if (attr == "timeOffset") {
1053                         if (m_pSGNode->GetSGParent() && m_pSGNode->GetSGParent()->IsSlowParent()) {
1054                                 static_cast<KX_SlowParentRelation *>(m_pSGNode->GetSGParent()->GetParentRelation())->SetTimeOffset(val);
1055                                 return 0;
1056                         } else {
1057                                 return 0;
1058                         }               
1059                 }
1060         }
1061         
1062         if (PySequence_Check(value))
1063         {
1064                 if (attr == "orientation")
1065                 {
1066                         MT_Matrix3x3 rot;
1067                         if (PyObject_IsMT_Matrix(value, 3))
1068                         {
1069                                 if (PyMatTo(value, rot))
1070                                 {
1071                                         NodeSetLocalOrientation(rot);
1072                                         NodeUpdateGS(0.f,true);
1073                                         return 0;
1074                                 }
1075                                 return 1;
1076                         }
1077                         
1078                         if (PySequence_Size(value) == 4)
1079                         {
1080                                 MT_Quaternion qrot;
1081                                 if (PyVecTo(value, qrot))
1082                                 {
1083                                         rot.setRotation(qrot);
1084                                         NodeSetLocalOrientation(rot);
1085                                         NodeUpdateGS(0.f,true);
1086                                         return 0;
1087                                 }
1088                                 return 1;
1089                         }
1090                         
1091                         if (PySequence_Size(value) == 3)
1092                         {
1093                                 MT_Vector3 erot;
1094                                 if (PyVecTo(value, erot))
1095                                 {
1096                                         rot.setEuler(erot);
1097                                         NodeSetLocalOrientation(rot);
1098                                         NodeUpdateGS(0.f,true);
1099                                         return 0;
1100                                 }
1101                                 return 1;
1102                         }
1103                         
1104                         return 1;
1105                 }
1106                 
1107                 if (attr == "position")
1108                 {
1109                         MT_Point3 pos;
1110                         if (PyVecTo(value, pos))
1111                         {
1112                                 NodeSetLocalPosition(pos);
1113                                 NodeUpdateGS(0.f,true);
1114                                 return 0;
1115                         }
1116                         return 1;
1117                 }
1118                 
1119                 if (attr == "scaling")
1120                 {
1121                         MT_Vector3 scale;
1122                         if (PyVecTo(value, scale))
1123                         {
1124                                 NodeSetLocalScale(scale);
1125                                 NodeUpdateGS(0.f,true);
1126                                 return 0;
1127                         }
1128                         return 1;
1129                 }
1130         }
1131         
1132         if (PyString_Check(value))
1133         {
1134                 if (attr == "name")
1135                 {
1136                         m_name = PyString_AsString(value);
1137                         return 0;
1138                 }
1139         }
1140         
1141         /* Need to have parent settable here too */
1142         
1143         return SCA_IObject::_setattr(attr, value);
1144 }
1145
1146
1147 PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* self, 
1148                                                                                          PyObject* args, 
1149                                                                                          PyObject* kwds)
1150 {
1151         // only can get the velocity if we have a physics object connected to us...
1152         int local = 0;
1153         if (PyArg_ParseTuple(args,"|i",&local))
1154         {
1155                 return PyObjectFrom(GetLinearVelocity((local!=0)));
1156         }
1157         else
1158         {
1159                 return NULL;
1160         }
1161 }
1162
1163 PyObject* KX_GameObject::PySetLinearVelocity(PyObject* self, 
1164                                                                                          PyObject* args, 
1165                                                                                          PyObject* kwds)
1166 {
1167         int local = 0;
1168         PyObject* pyvect;
1169         
1170         if (PyArg_ParseTuple(args,"O|i",&pyvect,&local)) {
1171                 MT_Vector3 velocity;
1172                 if (PyVecTo(pyvect, velocity)) {
1173                         setLinearVelocity(velocity, (local!=0));
1174                         Py_RETURN_NONE;
1175                 }
1176         }
1177         return NULL;
1178 }
1179
1180 PyObject* KX_GameObject::PySetVisible(PyObject* self, PyObject* value)
1181 {
1182         int visible = PyInt_AsLong(value);
1183         
1184         if (visible==-1 && PyErr_Occurred()) {
1185                 PyErr_SetString(PyExc_TypeError, "expected 0 or 1");
1186                 return NULL;
1187         }
1188         
1189         MarkVisible(visible!=0);
1190         m_bVisible = (visible!=0);
1191         Py_RETURN_NONE;
1192         
1193 }
1194
1195 PyObject* KX_GameObject::PyGetVisible(PyObject* self)
1196 {
1197         return PyInt_FromLong(m_bVisible);      
1198 }
1199
1200 PyObject* KX_GameObject::PyGetState(PyObject* self)
1201 {
1202         int state = 0;
1203         state |= GetState();
1204         return PyInt_FromLong(state);
1205 }
1206
1207 PyObject* KX_GameObject::PySetState(PyObject* self, PyObject* value)
1208 {
1209         int state_i = PyInt_AsLong(value);
1210         unsigned int state = 0;
1211         
1212         if (state_i == -1 && PyErr_Occurred()) {
1213                 PyErr_SetString(PyExc_TypeError, "expected an int bit field");
1214                 return NULL;
1215         }
1216         
1217         state |= state_i;
1218         if ((state & ((1<<30)-1)) == 0) {
1219                 PyErr_SetString(PyExc_AttributeError, "The state bitfield was not between 0 and 30 (1<<0 and 1<<29)");
1220                 return NULL;
1221         }
1222         SetState(state);
1223         
1224         Py_RETURN_NONE;
1225 }
1226
1227
1228
1229 PyObject* KX_GameObject::PyGetVelocity(PyObject* self, 
1230                                                                            PyObject* args, 
1231                                                                            PyObject* kwds)
1232 {
1233         // only can get the velocity if we have a physics object connected to us...
1234         MT_Vector3 velocity(0.0,0.0,0.0);
1235         MT_Point3 point(0.0,0.0,0.0);
1236         
1237         
1238         PyObject* pypos = NULL;
1239         if (PyArg_ParseTuple(args, "|O", &pypos))
1240         {
1241                 if (pypos)
1242                         PyVecTo(pypos, point);
1243         }
1244         else {
1245                 return NULL;
1246         }
1247         
1248         if (m_pPhysicsController1)
1249         {
1250                 velocity = m_pPhysicsController1->GetVelocity(point);
1251         }
1252         
1253         return PyObjectFrom(velocity);
1254 }
1255
1256
1257
1258 PyObject* KX_GameObject::PyGetMass(PyObject* self)
1259 {
1260         return PyFloat_FromDouble(GetPhysicsController()->GetMass());
1261 }
1262
1263
1264
1265 PyObject* KX_GameObject::PyGetReactionForce(PyObject* self)
1266 {
1267         // only can get the velocity if we have a physics object connected to us...
1268         return PyObjectFrom(GetPhysicsController()->getReactionForce());
1269 }
1270
1271
1272
1273 PyObject* KX_GameObject::PyEnableRigidBody(PyObject* self)
1274 {
1275         GetPhysicsController()->setRigidBody(true);
1276
1277         Py_RETURN_NONE;
1278 }
1279
1280
1281
1282 PyObject* KX_GameObject::PyDisableRigidBody(PyObject* self)
1283 {
1284         GetPhysicsController()->setRigidBody(false);
1285
1286         Py_RETURN_NONE;
1287 }
1288
1289
1290
1291 PyObject* KX_GameObject::PyGetParent(PyObject* self)
1292 {
1293         KX_GameObject* parent = this->GetParent();
1294         if (parent)
1295         {
1296                 parent->AddRef();
1297                 return parent;
1298         }
1299         Py_RETURN_NONE;
1300 }
1301
1302 PyObject* KX_GameObject::PySetParent(PyObject* self, PyObject* value)
1303 {
1304         if (!PyObject_TypeCheck(value, &KX_GameObject::Type)) {
1305                 PyErr_SetString(PyExc_TypeError, "expected a KX_GameObject type");
1306                 return NULL;
1307         }
1308         
1309         // The object we want to set as parent
1310         CValue *m_ob = (CValue*)value;
1311         KX_GameObject *obj = ((KX_GameObject*)m_ob);
1312         KX_Scene *scene = PHY_GetActiveScene();
1313         
1314         this->SetParent(scene, obj);
1315                 
1316         Py_RETURN_NONE;
1317 }
1318
1319 PyObject* KX_GameObject::PyRemoveParent(PyObject* self)
1320 {
1321         KX_Scene *scene = PHY_GetActiveScene();
1322         this->RemoveParent(scene);
1323         Py_RETURN_NONE;
1324 }
1325
1326
1327 static void walk_children(SG_Node* node, CListValue* list, bool recursive)
1328 {
1329         NodeList& children = node->GetSGChildren();
1330
1331         for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
1332         {
1333                 SG_Node* childnode = (*childit);
1334                 CValue* childobj = (CValue*)childnode->GetSGClientObject();
1335                 if (childobj != NULL) // This is a GameObject
1336                 {
1337                         // add to the list
1338                         list->Add(childobj->AddRef());
1339                 }
1340                 
1341                 // if the childobj is NULL then this may be an inverse parent link
1342                 // so a non recursive search should still look down this node.
1343                 if (recursive || childobj==NULL) {
1344                         walk_children(childnode, list, recursive);
1345                 }
1346         }
1347 }
1348
1349 PyObject* KX_GameObject::PyGetChildren(PyObject* self)
1350 {
1351         CListValue* list = new CListValue();
1352         walk_children(m_pSGNode, list, 0);
1353         return list;
1354 }
1355
1356 PyObject* KX_GameObject::PyGetChildrenRecursive(PyObject* self)
1357 {
1358         CListValue* list = new CListValue();
1359         walk_children(m_pSGNode, list, 1);
1360         return list;
1361 }
1362
1363 PyObject* KX_GameObject::PyGetMesh(PyObject* self, 
1364                                                                    PyObject* args, 
1365                                                                    PyObject* kwds)
1366 {
1367         int mesh = 0;
1368
1369         if (PyArg_ParseTuple(args, "|i", &mesh))
1370         {
1371                 if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0)
1372                 {
1373                         KX_MeshProxy* meshproxy = new KX_MeshProxy(m_meshes[mesh]);
1374                         return meshproxy;
1375                 }
1376         }
1377         Py_RETURN_NONE;
1378 }
1379
1380
1381
1382
1383
1384 PyObject* KX_GameObject::PySetCollisionMargin(PyObject* self, PyObject* value)
1385 {
1386         float collisionMargin = PyFloat_AsDouble(value);
1387         
1388         if (collisionMargin==-1 && PyErr_Occurred()) {
1389                 PyErr_SetString(PyExc_TypeError, "expected a float");
1390                 return NULL;
1391         }
1392         
1393         if (m_pPhysicsController1)
1394         {
1395                 m_pPhysicsController1->setMargin(collisionMargin);
1396                 Py_RETURN_NONE;
1397         }
1398         PyErr_SetString(PyExc_RuntimeError, "This object has no physics controller");
1399         return NULL;
1400 }
1401
1402
1403
1404 PyObject* KX_GameObject::PyApplyImpulse(PyObject* self, 
1405                                                                                 PyObject* args, 
1406                                                                                 PyObject* kwds)
1407 {
1408         PyObject* pyattach;
1409         PyObject* pyimpulse;
1410         
1411         if (!m_pPhysicsController1)     {
1412                 PyErr_SetString(PyExc_RuntimeError, "This object has no physics controller");
1413                 return NULL;
1414         }
1415         
1416         if (PyArg_ParseTuple(args, "OO", &pyattach, &pyimpulse))
1417         {
1418                 MT_Point3  attach;
1419                 MT_Vector3 impulse;
1420                 if (PyVecTo(pyattach, attach) && PyVecTo(pyimpulse, impulse))
1421                 {
1422                         m_pPhysicsController1->applyImpulse(attach, impulse);
1423                         Py_RETURN_NONE;
1424                 }
1425
1426         }
1427         
1428         return NULL;
1429 }
1430
1431
1432
1433 PyObject* KX_GameObject::PySuspendDynamics(PyObject* self)
1434 {
1435         SuspendDynamics();
1436         Py_RETURN_NONE;
1437 }
1438
1439
1440
1441 PyObject* KX_GameObject::PyRestoreDynamics(PyObject* self)
1442 {
1443         RestoreDynamics();
1444         Py_RETURN_NONE;
1445 }
1446
1447
1448
1449 PyObject* KX_GameObject::PyGetOrientation(PyObject* self) //keywords
1450 {
1451         return PyObjectFrom(NodeGetWorldOrientation());
1452 }
1453
1454
1455
1456 PyObject* KX_GameObject::PySetOrientation(PyObject* self, PyObject* value)
1457 {
1458         MT_Matrix3x3 matrix;
1459         if (PyObject_IsMT_Matrix(value, 3) && PyMatTo(value, matrix))
1460         {
1461                 NodeSetLocalOrientation(matrix);
1462                 NodeUpdateGS(0.f,true);
1463                 Py_RETURN_NONE;
1464         }
1465
1466         MT_Quaternion quat;
1467         if (PyVecTo(value, quat))
1468         {
1469                 matrix.setRotation(quat);
1470                 NodeSetLocalOrientation(matrix);
1471                 NodeUpdateGS(0.f,true);
1472                 Py_RETURN_NONE;
1473         }
1474         return NULL;
1475 }
1476
1477 PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* self, 
1478                                                                                   PyObject* args, 
1479                                                                                   PyObject* kwds)
1480 {
1481         PyObject* pyvect;
1482         int axis = 2; //z axis is the default
1483         float fac = 1.0;
1484         
1485         if (PyArg_ParseTuple(args,"O|if",&pyvect,&axis, &fac))
1486         {
1487                 MT_Vector3 vect;
1488                 if (PyVecTo(pyvect, vect))
1489                 {
1490                         AlignAxisToVect(vect,axis,fac);
1491                         NodeUpdateGS(0.f,true);
1492                         Py_RETURN_NONE;
1493                 }
1494         }
1495         return NULL;
1496 }
1497
1498 PyObject* KX_GameObject::PyGetAxisVect(PyObject* self, PyObject* value)
1499 {
1500         MT_Vector3 vect;
1501         if (PyVecTo(value, vect))
1502         {
1503                 return PyObjectFrom(NodeGetWorldOrientation() * vect);
1504         }
1505         return NULL;
1506 }
1507
1508 PyObject* KX_GameObject::PySetPosition(PyObject* self, PyObject* value)
1509 {
1510         MT_Point3 pos;
1511         if (PyVecTo(value, pos))
1512         {
1513                 NodeSetLocalPosition(pos);
1514                 NodeUpdateGS(0.f,true);
1515                 Py_RETURN_NONE;
1516         }
1517
1518         return NULL;
1519 }
1520
1521 PyObject* KX_GameObject::PyGetPhysicsId(PyObject* self)
1522 {
1523         KX_IPhysicsController* ctrl = GetPhysicsController();
1524         uint_ptr physid=0;
1525         if (ctrl)
1526         {
1527                 physid= (uint_ptr)ctrl->GetUserData();
1528         }
1529         return PyInt_FromLong((long)physid);
1530 }
1531
1532 PyObject* KX_GameObject::PyGetPropertyNames(PyObject* self)
1533 {
1534         return ConvertKeysToPython();
1535 }
1536
1537 KX_PYMETHODDEF_DOC(KX_GameObject, getDistanceTo,
1538 "getDistanceTo(other): get distance to another point/KX_GameObject")
1539 {
1540         MT_Point3 b;
1541         if (PyVecArgTo(args, b))
1542         {
1543                 return PyFloat_FromDouble(NodeGetWorldPosition().distance(b));
1544         }
1545         PyErr_Clear();
1546         
1547         PyObject *pyother;
1548         if (PyArg_ParseTuple(args, "O!", &KX_GameObject::Type, &pyother))
1549         {
1550                 KX_GameObject *other = static_cast<KX_GameObject*>(pyother);
1551                 return PyFloat_FromDouble(NodeGetWorldPosition().distance(other->NodeGetWorldPosition()));
1552         }
1553         
1554         return NULL;
1555 }
1556
1557 bool KX_GameObject::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data)
1558 {
1559
1560         KX_GameObject* hitKXObj = client->m_gameobject;
1561         
1562         if (client->m_type > KX_ClientObjectInfo::ACTOR)
1563         {
1564                 // false hit
1565                 return false;
1566         }
1567
1568         if (m_testPropName.Length() == 0 || hitKXObj->GetProperty(m_testPropName) != NULL)
1569         {
1570                 m_pHitObject = hitKXObj;
1571                 return true;
1572         }
1573
1574         return false;
1575         
1576 }
1577
1578 KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo,
1579 "rayCastTo(other,dist,prop): look towards another point/KX_GameObject and return first object hit within dist that matches prop\n"
1580 " prop = property name that object must have; can be omitted => detect any object\n"
1581 " dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to other\n"
1582 " other = 3-tuple or object reference")
1583 {
1584         MT_Point3 toPoint;
1585         PyObject* pyarg;
1586         float dist = 0.0f;
1587         char *propName = NULL;
1588
1589         if (!PyArg_ParseTuple(args,"O|fs", &pyarg, &dist, &propName)) {
1590                 PyErr_SetString(PyExc_TypeError, "Invalid arguments");
1591                 return NULL;
1592         }
1593
1594         if (!PyVecTo(pyarg, toPoint))
1595         {
1596                 KX_GameObject *other;
1597                 PyErr_Clear();
1598                 if (!PyType_IsSubtype(pyarg->ob_type, &KX_GameObject::Type)) {
1599                         PyErr_SetString(PyExc_TypeError, "the first argument to rayCastTo must be a vector or a KX_GameObject");
1600                         return NULL;
1601                 }
1602                 other = static_cast<KX_GameObject*>(pyarg);
1603                 toPoint = other->NodeGetWorldPosition();
1604         }
1605         MT_Point3 fromPoint = NodeGetWorldPosition();
1606         if (dist != 0.0f)
1607         {
1608                 MT_Vector3 toDir = toPoint-fromPoint;
1609                 toDir.normalize();
1610                 toPoint = fromPoint + (dist) * toDir;
1611         }
1612
1613         MT_Point3 resultPoint;
1614         MT_Vector3 resultNormal;
1615         PHY_IPhysicsEnvironment* pe = GetPhysicsEnvironment();
1616         KX_IPhysicsController *spc = GetPhysicsController();
1617         KX_GameObject *parent = GetParent();
1618         if (!spc && parent)
1619                 spc = parent->GetPhysicsController();
1620         if (parent)
1621                 parent->Release();
1622         
1623         m_pHitObject = NULL;
1624         if (propName)
1625                 m_testPropName = propName;
1626         else
1627                 m_testPropName.SetLength(0);
1628         KX_RayCast::RayTest(spc, pe, fromPoint, toPoint, resultPoint, resultNormal, KX_RayCast::Callback<KX_GameObject>(this));
1629
1630     if (m_pHitObject)
1631         {
1632                 m_pHitObject->AddRef();
1633                 return m_pHitObject;
1634         }
1635         Py_RETURN_NONE;
1636 }
1637
1638 KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
1639                                    "rayCast(to,from,dist,prop): cast a ray and return tuple (object,hit,normal) of contact point with object within dist that matches prop or (None,None,None) tuple if no hit\n"
1640 " prop = property name that object must have; can be omitted => detect any object\n"
1641 " dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to to\n"
1642 " from = 3-tuple or object reference for origin of ray (if object, use center of object)\n"
1643 "        Can be None or omitted => start from self object center\n"
1644 " to = 3-tuple or object reference for destination of ray (if object, use center of object)\n"
1645 "Note: the object on which you call this method matters: the ray will ignore it if it goes through it\n")
1646 {
1647         MT_Point3 toPoint;
1648         MT_Point3 fromPoint;
1649         PyObject* pyto;
1650         PyObject* pyfrom = NULL;
1651         float dist = 0.0f;
1652         char *propName = NULL;
1653         KX_GameObject *other;
1654
1655         if (!PyArg_ParseTuple(args,"O|Ofs", &pyto, &pyfrom, &dist, &propName)) {
1656                 PyErr_SetString(PyExc_TypeError, "Invalid arguments");
1657                 return NULL;
1658         }
1659
1660         if (!PyVecTo(pyto, toPoint))
1661         {
1662                 PyErr_Clear();
1663                 if (!PyType_IsSubtype(pyto->ob_type, &KX_GameObject::Type)) {
1664                         PyErr_SetString(PyExc_TypeError, "the first argument to rayCast must be a vector or a KX_GameObject");
1665                         return NULL;
1666                 }
1667                 other = static_cast<KX_GameObject*>(pyto);
1668                 toPoint = other->NodeGetWorldPosition();
1669         }
1670         if (!pyfrom || pyfrom == Py_None)
1671         {
1672                 fromPoint = NodeGetWorldPosition();
1673         }
1674         else if (!PyVecTo(pyfrom, fromPoint))
1675         {
1676                 PyErr_Clear();
1677                 if (!PyType_IsSubtype(pyfrom->ob_type, &KX_GameObject::Type)) {
1678                         PyErr_SetString(PyExc_TypeError, "the second optional argument to rayCast must be a vector or a KX_GameObject");
1679                         return NULL;
1680                 }
1681                 other = static_cast<KX_GameObject*>(pyfrom);
1682                 fromPoint = other->NodeGetWorldPosition();
1683         }
1684         
1685         if (dist != 0.0f) {
1686                 MT_Vector3 toDir = toPoint-fromPoint;
1687                 if (MT_fuzzyZero(toDir.length2())) {
1688                         return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
1689                 }
1690                 toDir.normalize();
1691                 toPoint = fromPoint + (dist) * toDir;
1692         } else if (MT_fuzzyZero((toPoint-fromPoint).length2())) {
1693                 return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
1694         }
1695         
1696         MT_Point3 resultPoint;
1697         MT_Vector3 resultNormal;
1698         PHY_IPhysicsEnvironment* pe = GetPhysicsEnvironment();
1699         KX_IPhysicsController *spc = GetPhysicsController();
1700         KX_GameObject *parent = GetParent();
1701         if (!spc && parent)
1702                 spc = parent->GetPhysicsController();
1703         if (parent)
1704                 parent->Release();
1705         
1706         m_pHitObject = NULL;
1707         if (propName)
1708                 m_testPropName = propName;
1709         else
1710                 m_testPropName.SetLength(0);
1711         KX_RayCast::RayTest(spc, pe, fromPoint, toPoint, resultPoint, resultNormal, KX_RayCast::Callback<KX_GameObject>(this));
1712
1713     if (m_pHitObject)
1714         {
1715                 PyObject* returnValue = PyTuple_New(3);
1716                 if (!returnValue) {
1717                         PyErr_SetString(PyExc_TypeError, "PyTuple_New() failed");
1718                         return NULL;
1719                 }
1720                 PyTuple_SET_ITEM(returnValue, 0, m_pHitObject->AddRef());
1721                 PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(resultPoint));
1722                 PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(resultNormal));
1723                 return returnValue;
1724         }
1725         return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
1726         //Py_RETURN_NONE;
1727 }
1728
1729 /* --------------------------------------------------------------------- 
1730  * Some stuff taken from the header
1731  * --------------------------------------------------------------------- */
1732 void KX_GameObject::Relink(GEN_Map<GEN_HashedPtr, void*> *map_parameter)        
1733 {
1734         // we will relink the sensors and actuators that use object references
1735         // if the object is part of the replicated hierarchy, use the new
1736         // object reference instead
1737         SCA_SensorList& sensorlist = GetSensors();
1738         SCA_SensorList::iterator sit;
1739         for (sit=sensorlist.begin(); sit != sensorlist.end(); sit++)
1740         {
1741                 (*sit)->Relink(map_parameter);
1742         }
1743         SCA_ActuatorList& actuatorlist = GetActuators();
1744         SCA_ActuatorList::iterator ait;
1745         for (ait=actuatorlist.begin(); ait != actuatorlist.end(); ait++)
1746         {
1747                 (*ait)->Relink(map_parameter);
1748         }
1749 }
1750