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