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