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