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