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