BGE bug #17688 fixed: Near Sensor Reset not working (for Gamekit)
[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 MT_Vector3 KX_GameObject::GetVelocity(const MT_Point3& point)
776 {
777         if (m_pPhysicsController1)
778         {
779                 return m_pPhysicsController1->GetVelocity(point);
780         }
781         return MT_Vector3(0.0,0.0,0.0);
782 }
783
784 // scenegraph node stuff
785
786 void KX_GameObject::NodeSetLocalPosition(const MT_Point3& trans)
787 {
788         if (m_pPhysicsController1 && (!GetSGNode() || !GetSGNode()->GetSGParent()))
789         {
790                 // don't update physic controller if the object is a child:
791                 // 1) the transformation will not be right
792                 // 2) in this case, the physic controller is necessarily a static object
793                 //    that is updated from the normal kinematic synchronization
794                 m_pPhysicsController1->setPosition(trans);
795         }
796
797         if (GetSGNode())
798                 GetSGNode()->SetLocalPosition(trans);
799 }
800
801
802
803 void KX_GameObject::NodeSetLocalOrientation(const MT_Matrix3x3& rot)
804 {
805         if (m_pPhysicsController1 && (!GetSGNode() || !GetSGNode()->GetSGParent()))
806         {
807                 // see note above
808                 m_pPhysicsController1->setOrientation(rot);
809         }
810         if (GetSGNode())
811                 GetSGNode()->SetLocalOrientation(rot);
812 }
813
814
815
816 void KX_GameObject::NodeSetLocalScale(const MT_Vector3& scale)
817 {
818         if (m_pPhysicsController1 && (!GetSGNode() || !GetSGNode()->GetSGParent()))
819         {
820                 // see note above
821                 m_pPhysicsController1->setScaling(scale);
822         }
823         
824         if (GetSGNode())
825                 GetSGNode()->SetLocalScale(scale);
826 }
827
828
829
830 void KX_GameObject::NodeSetRelativeScale(const MT_Vector3& scale)
831 {
832         if (GetSGNode())
833         {
834                 GetSGNode()->RelativeScale(scale);
835                 if (m_pPhysicsController1 && (!GetSGNode()->GetSGParent()))
836                 {
837                         // see note above
838                         // we can use the local scale: it's the same thing for a root object 
839                         // and the world scale is not yet updated
840                         MT_Vector3 newscale = GetSGNode()->GetLocalScale();
841                         m_pPhysicsController1->setScaling(newscale);
842                 }
843         }
844 }
845
846 void KX_GameObject::NodeSetWorldPosition(const MT_Point3& trans)
847 {
848         SG_Node* parent = m_pSGNode->GetSGParent();
849         if (parent != NULL)
850         {
851                 // Make sure the objects have some scale
852                 MT_Vector3 scale = parent->GetWorldScaling();
853                 if (fabs(scale[0]) < FLT_EPSILON || 
854                         fabs(scale[1]) < FLT_EPSILON || 
855                         fabs(scale[2]) < FLT_EPSILON)
856                 { 
857                         return; 
858                 }
859                 scale[0] = 1.0/scale[0];
860                 scale[1] = 1.0/scale[1];
861                 scale[2] = 1.0/scale[2];
862                 MT_Matrix3x3 invori = parent->GetWorldOrientation().inverse();
863                 MT_Vector3 newpos = invori*(trans-parent->GetWorldPosition())*scale;
864                 NodeSetLocalPosition(MT_Point3(newpos[0],newpos[1],newpos[2]));
865         }
866         else 
867         {
868                 NodeSetLocalPosition(trans);
869         }
870 }
871
872
873 void KX_GameObject::NodeUpdateGS(double time,bool bInitiator)
874 {
875         if (GetSGNode())
876                 GetSGNode()->UpdateWorldData(time);
877 }
878
879
880
881 const MT_Matrix3x3& KX_GameObject::NodeGetWorldOrientation() const
882 {
883         return GetSGNode()->GetWorldOrientation();
884 }
885
886
887
888 const MT_Vector3& KX_GameObject::NodeGetWorldScaling() const
889 {
890         return GetSGNode()->GetWorldScaling();
891 }
892
893
894
895 const MT_Point3& KX_GameObject::NodeGetWorldPosition() const
896 {
897         return GetSGNode()->GetWorldPosition();
898 }
899
900 /* Suspend/ resume: for the dynamic behaviour, there is a simple
901  * method. For the residual motion, there is not. I wonder what the
902  * correct solution is for Sumo. Remove from the motion-update tree?
903  *
904  * So far, only switch the physics and logic.
905  * */
906
907 void KX_GameObject::Resume(void)
908 {
909         if (m_suspended) {
910                 SCA_IObject::Resume();
911                 GetPhysicsController()->RestoreDynamics();
912
913                 m_suspended = false;
914         }
915 }
916
917 void KX_GameObject::Suspend()
918 {
919         if ((!m_ignore_activity_culling) 
920                 && (!m_suspended))  {
921                 SCA_IObject::Suspend();
922                 GetPhysicsController()->SuspendDynamics();
923                 m_suspended = true;
924         }
925 }
926
927
928
929
930 /* ------- python stuff ---------------------------------------------------*/
931
932
933
934
935 PyMethodDef KX_GameObject::Methods[] = {
936         {"getPosition", (PyCFunction) KX_GameObject::sPyGetPosition, METH_NOARGS},
937         {"setPosition", (PyCFunction) KX_GameObject::sPySetPosition, METH_O},
938         {"setWorldPosition", (PyCFunction) KX_GameObject::sPySetWorldPosition, METH_O},
939         {"getLinearVelocity", (PyCFunction) KX_GameObject::sPyGetLinearVelocity, METH_VARARGS},
940         {"setLinearVelocity", (PyCFunction) KX_GameObject::sPySetLinearVelocity, METH_VARARGS},
941         {"getAngularVelocity", (PyCFunction) KX_GameObject::sPyGetAngularVelocity, METH_VARARGS},
942         {"setAngularVelocity", (PyCFunction) KX_GameObject::sPySetAngularVelocity, METH_VARARGS},
943         {"getVelocity", (PyCFunction) KX_GameObject::sPyGetVelocity, METH_VARARGS},
944         {"getMass", (PyCFunction) KX_GameObject::sPyGetMass, METH_NOARGS},
945         {"getReactionForce", (PyCFunction) KX_GameObject::sPyGetReactionForce, METH_NOARGS},
946         {"getOrientation", (PyCFunction) KX_GameObject::sPyGetOrientation, METH_NOARGS},
947         {"setOrientation", (PyCFunction) KX_GameObject::sPySetOrientation, METH_O},
948         {"getVisible",(PyCFunction) KX_GameObject::sPyGetVisible, METH_NOARGS},
949         {"setVisible",(PyCFunction) KX_GameObject::sPySetVisible, METH_VARARGS},
950         {"getState",(PyCFunction) KX_GameObject::sPyGetState, METH_NOARGS},
951         {"setState",(PyCFunction) KX_GameObject::sPySetState, METH_O},
952         {"alignAxisToVect",(PyCFunction) KX_GameObject::sPyAlignAxisToVect, METH_VARARGS},
953         {"getAxisVect",(PyCFunction) KX_GameObject::sPyGetAxisVect, METH_O},
954         {"suspendDynamics", (PyCFunction)KX_GameObject::sPySuspendDynamics,METH_NOARGS},
955         {"restoreDynamics", (PyCFunction)KX_GameObject::sPyRestoreDynamics,METH_NOARGS},
956         {"enableRigidBody", (PyCFunction)KX_GameObject::sPyEnableRigidBody,METH_NOARGS},
957         {"disableRigidBody", (PyCFunction)KX_GameObject::sPyDisableRigidBody,METH_NOARGS},
958         {"applyImpulse", (PyCFunction) KX_GameObject::sPyApplyImpulse, METH_VARARGS},
959         {"setCollisionMargin", (PyCFunction) KX_GameObject::sPySetCollisionMargin, METH_O},
960         {"getParent", (PyCFunction)KX_GameObject::sPyGetParent,METH_NOARGS},
961         {"setParent", (PyCFunction)KX_GameObject::sPySetParent,METH_O},
962         {"removeParent", (PyCFunction)KX_GameObject::sPyRemoveParent,METH_NOARGS},
963         {"getChildren", (PyCFunction)KX_GameObject::sPyGetChildren,METH_NOARGS},
964         {"getChildrenRecursive", (PyCFunction)KX_GameObject::sPyGetChildrenRecursive,METH_NOARGS},
965         {"getMesh", (PyCFunction)KX_GameObject::sPyGetMesh,METH_VARARGS},
966         {"getPhysicsId", (PyCFunction)KX_GameObject::sPyGetPhysicsId,METH_NOARGS},
967         {"getPropertyNames", (PyCFunction)KX_GameObject::sPyGetPropertyNames,METH_NOARGS},
968         {"endObject",(PyCFunction) KX_GameObject::sPyEndObject, METH_NOARGS},
969         KX_PYMETHODTABLE(KX_GameObject, rayCastTo),
970         KX_PYMETHODTABLE(KX_GameObject, rayCast),
971         KX_PYMETHODTABLE(KX_GameObject, getDistanceTo),
972         KX_PYMETHODTABLE(KX_GameObject, getVectTo),
973         {NULL,NULL} //Sentinel
974 };
975
976
977
978 /*
979 bool KX_GameObject::ConvertPythonVectorArgs(PyObject* args,
980                                                                                         MT_Vector3& pos,
981                                                                                         MT_Vector3& pos2)
982 {
983         PyObject* pylist;
984         PyObject* pylist2;
985         bool error = (PyArg_ParseTuple(args,"OO",&pylist,&pylist2)) != 0;
986
987         pos = ConvertPythonPylist(pylist);
988         pos2 = ConvertPythonPylist(pylist2);
989                 
990         return error;
991 }
992 */
993
994 PyObject* KX_GameObject::PyEndObject(PyObject* self)
995 {
996
997         KX_Scene *scene = PHY_GetActiveScene();
998         scene->DelayedRemoveObject(this);
999         
1000         Py_RETURN_NONE;
1001
1002 }
1003
1004
1005 PyObject* KX_GameObject::PyGetPosition(PyObject* self)
1006 {
1007         return PyObjectFrom(NodeGetWorldPosition());
1008 }
1009
1010
1011
1012 PyTypeObject KX_GameObject::Type = {
1013         PyObject_HEAD_INIT(&PyType_Type)
1014                 0,
1015                 "KX_GameObject",
1016                 sizeof(KX_GameObject),
1017                 0,
1018                 PyDestructor,
1019                 0,
1020                 __getattr,
1021                 __setattr,
1022                 0, //&MyPyCompare,
1023                 __repr,
1024                 0, //&cvalue_as_number,
1025                 0,
1026                 0,
1027                 0,
1028                 0
1029 };
1030
1031
1032
1033 PyParentObject KX_GameObject::Parents[] = {
1034         &KX_GameObject::Type,
1035                 &SCA_IObject::Type,
1036                 &CValue::Type,
1037                 NULL
1038 };
1039
1040
1041
1042
1043 PyObject* KX_GameObject::_getattr(const STR_String& attr)
1044 {
1045         if (m_pPhysicsController1)
1046         {
1047                 if (attr == "mass")
1048                         return PyFloat_FromDouble(GetPhysicsController()->GetMass());
1049         }
1050
1051         if (attr == "parent")
1052         {       
1053                 KX_GameObject* parent = GetParent();
1054                 if (parent)
1055                 {
1056                         parent->AddRef();
1057                         return parent;
1058                 }
1059                 Py_RETURN_NONE;
1060         }
1061
1062         if (attr == "visible")
1063                 return PyInt_FromLong(m_bVisible);
1064         
1065         if (attr == "position")
1066                 return PyObjectFrom(NodeGetWorldPosition());
1067         
1068         if (attr == "orientation")
1069                 return PyObjectFrom(NodeGetWorldOrientation());
1070         
1071         if (attr == "scaling")
1072                 return PyObjectFrom(NodeGetWorldScaling());
1073                 
1074         if (attr == "name")
1075                 return PyString_FromString(m_name.ReadPtr());
1076         if (attr == "timeOffset") {
1077                 if (m_pSGNode->GetSGParent()->IsSlowParent()) {
1078                         return PyFloat_FromDouble(static_cast<KX_SlowParentRelation *>(m_pSGNode->GetSGParent()->GetParentRelation())->GetTimeOffset());
1079                 } else {
1080                         return PyFloat_FromDouble(0.0);
1081                 }
1082         }
1083         
1084         
1085         _getattr_up(SCA_IObject);
1086 }
1087
1088 int KX_GameObject::_setattr(const STR_String& attr, PyObject *value)    // _setattr method
1089 {
1090         if (attr == "mass") {
1091                 PyErr_SetString(PyExc_AttributeError, "attribute \"mass\" is read only");
1092                 return 1;
1093         }
1094         
1095         if (attr == "parent") {
1096                 PyErr_SetString(PyExc_AttributeError, "attribute \"mass\" is read only\nUse setParent()");
1097                 return 1;
1098         }
1099                 
1100         if (PyInt_Check(value))
1101         {
1102                 int val = PyInt_AsLong(value);
1103                 if (attr == "visible")
1104                 {
1105                         SetVisible(val != 0, false);
1106                         UpdateBuckets(false);
1107                         return 0;
1108                 }
1109         }
1110
1111         if (PyFloat_Check(value))
1112         {
1113                 MT_Scalar val = PyFloat_AsDouble(value);
1114                 if (attr == "timeOffset") {
1115                         if (m_pSGNode->GetSGParent() && m_pSGNode->GetSGParent()->IsSlowParent()) {
1116                                 static_cast<KX_SlowParentRelation *>(m_pSGNode->GetSGParent()->GetParentRelation())->SetTimeOffset(val);
1117                                 return 0;
1118                         } else {
1119                                 return 0;
1120                         }               
1121                 }
1122         }
1123         
1124         if (PySequence_Check(value))
1125         {
1126                 if (attr == "orientation")
1127                 {
1128                         MT_Matrix3x3 rot;
1129                         if (PyObject_IsMT_Matrix(value, 3))
1130                         {
1131                                 if (PyMatTo(value, rot))
1132                                 {
1133                                         NodeSetLocalOrientation(rot);
1134                                         NodeUpdateGS(0.f,true);
1135                                         return 0;
1136                                 }
1137                                 return 1;
1138                         }
1139                         
1140                         if (PySequence_Size(value) == 4)
1141                         {
1142                                 MT_Quaternion qrot;
1143                                 if (PyVecTo(value, qrot))
1144                                 {
1145                                         rot.setRotation(qrot);
1146                                         NodeSetLocalOrientation(rot);
1147                                         NodeUpdateGS(0.f,true);
1148                                         return 0;
1149                                 }
1150                                 return 1;
1151                         }
1152                         
1153                         if (PySequence_Size(value) == 3)
1154                         {
1155                                 MT_Vector3 erot;
1156                                 if (PyVecTo(value, erot))
1157                                 {
1158                                         rot.setEuler(erot);
1159                                         NodeSetLocalOrientation(rot);
1160                                         NodeUpdateGS(0.f,true);
1161                                         return 0;
1162                                 }
1163                                 return 1;
1164                         }
1165                         PyErr_SetString(PyExc_AttributeError, "could not set the orientation from a 3x3 matrix, quaternion or euler sequence");
1166                         return 1;
1167                 }
1168                 
1169                 if (attr == "position")
1170                 {
1171                         MT_Point3 pos;
1172                         if (PyVecTo(value, pos))
1173                         {
1174                                 NodeSetLocalPosition(pos);
1175                                 NodeUpdateGS(0.f,true);
1176                                 return 0;
1177                         }
1178                         return 1;
1179                 }
1180                 
1181                 if (attr == "scaling")
1182                 {
1183                         MT_Vector3 scale;
1184                         if (PyVecTo(value, scale))
1185                         {
1186                                 NodeSetLocalScale(scale);
1187                                 NodeUpdateGS(0.f,true);
1188                                 return 0;
1189                         }
1190                         return 1;
1191                 }
1192         }
1193         
1194         if (PyString_Check(value))
1195         {
1196                 if (attr == "name")
1197                 {
1198                         m_name = PyString_AsString(value);
1199                         return 0;
1200                 }
1201         }
1202         
1203         /* Need to have parent settable here too */
1204         
1205         return SCA_IObject::_setattr(attr, value);
1206 }
1207
1208
1209 PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* self, PyObject* args)
1210 {
1211         // only can get the velocity if we have a physics object connected to us...
1212         int local = 0;
1213         if (PyArg_ParseTuple(args,"|i",&local))
1214         {
1215                 return PyObjectFrom(GetLinearVelocity((local!=0)));
1216         }
1217         else
1218         {
1219                 return NULL;
1220         }
1221 }
1222
1223 PyObject* KX_GameObject::PySetLinearVelocity(PyObject* self, PyObject* args)
1224 {
1225         int local = 0;
1226         PyObject* pyvect;
1227         
1228         if (PyArg_ParseTuple(args,"O|i",&pyvect,&local)) {
1229                 MT_Vector3 velocity;
1230                 if (PyVecTo(pyvect, velocity)) {
1231                         setLinearVelocity(velocity, (local!=0));
1232                         Py_RETURN_NONE;
1233                 }
1234         }
1235         return NULL;
1236 }
1237
1238 PyObject* KX_GameObject::PyGetAngularVelocity(PyObject* self, PyObject* args)
1239 {
1240         // only can get the velocity if we have a physics object connected to us...
1241         int local = 0;
1242         if (PyArg_ParseTuple(args,"|i",&local))
1243         {
1244                 return PyObjectFrom(GetAngularVelocity((local!=0)));
1245         }
1246         else
1247         {
1248                 return NULL;
1249         }
1250 }
1251
1252 PyObject* KX_GameObject::PySetAngularVelocity(PyObject* self, PyObject* args)
1253 {
1254         int local = 0;
1255         PyObject* pyvect;
1256         
1257         if (PyArg_ParseTuple(args,"O|i",&pyvect,&local)) {
1258                 MT_Vector3 velocity;
1259                 if (PyVecTo(pyvect, velocity)) {
1260                         setAngularVelocity(velocity, (local!=0));
1261                         Py_RETURN_NONE;
1262                 }
1263         }
1264         return NULL;
1265 }
1266
1267 PyObject* KX_GameObject::PySetVisible(PyObject* self, PyObject* args)
1268 {
1269         int visible, recursive = 0;
1270         if (!PyArg_ParseTuple(args,"i|i",&visible, &recursive))
1271                 return NULL;
1272         
1273         SetVisible(visible ? true:false, recursive ? true:false);
1274         UpdateBuckets(recursive ? true:false);
1275         Py_RETURN_NONE;
1276         
1277 }
1278
1279 PyObject* KX_GameObject::PyGetVisible(PyObject* self)
1280 {
1281         return PyInt_FromLong(m_bVisible);      
1282 }
1283
1284 PyObject* KX_GameObject::PyGetState(PyObject* self)
1285 {
1286         int state = 0;
1287         state |= GetState();
1288         return PyInt_FromLong(state);
1289 }
1290
1291 PyObject* KX_GameObject::PySetState(PyObject* self, PyObject* value)
1292 {
1293         int state_i = PyInt_AsLong(value);
1294         unsigned int state = 0;
1295         
1296         if (state_i == -1 && PyErr_Occurred()) {
1297                 PyErr_SetString(PyExc_TypeError, "expected an int bit field");
1298                 return NULL;
1299         }
1300         
1301         state |= state_i;
1302         if ((state & ((1<<30)-1)) == 0) {
1303                 PyErr_SetString(PyExc_AttributeError, "The state bitfield was not between 0 and 30 (1<<0 and 1<<29)");
1304                 return NULL;
1305         }
1306         SetState(state);
1307         
1308         Py_RETURN_NONE;
1309 }
1310
1311
1312
1313 PyObject* KX_GameObject::PyGetVelocity(PyObject* self, PyObject* args)
1314 {
1315         // only can get the velocity if we have a physics object connected to us...
1316         MT_Vector3 velocity(0.0,0.0,0.0);
1317         MT_Point3 point(0.0,0.0,0.0);
1318         
1319         
1320         PyObject* pypos = NULL;
1321         if (PyArg_ParseTuple(args, "|O", &pypos))
1322         {
1323                 if (pypos)
1324                         PyVecTo(pypos, point);
1325         }
1326         else {
1327                 return NULL;
1328         }
1329         
1330         if (m_pPhysicsController1)
1331         {
1332                 velocity = m_pPhysicsController1->GetVelocity(point);
1333         }
1334         
1335         return PyObjectFrom(velocity);
1336 }
1337
1338
1339
1340 PyObject* KX_GameObject::PyGetMass(PyObject* self)
1341 {
1342         return PyFloat_FromDouble(GetPhysicsController()->GetMass());
1343 }
1344
1345
1346
1347 PyObject* KX_GameObject::PyGetReactionForce(PyObject* self)
1348 {
1349         // only can get the velocity if we have a physics object connected to us...
1350         return PyObjectFrom(GetPhysicsController()->getReactionForce());
1351 }
1352
1353
1354
1355 PyObject* KX_GameObject::PyEnableRigidBody(PyObject* self)
1356 {
1357         GetPhysicsController()->setRigidBody(true);
1358
1359         Py_RETURN_NONE;
1360 }
1361
1362
1363
1364 PyObject* KX_GameObject::PyDisableRigidBody(PyObject* self)
1365 {
1366         GetPhysicsController()->setRigidBody(false);
1367
1368         Py_RETURN_NONE;
1369 }
1370
1371
1372
1373 PyObject* KX_GameObject::PyGetParent(PyObject* self)
1374 {
1375         KX_GameObject* parent = this->GetParent();
1376         if (parent)
1377         {
1378                 parent->AddRef();
1379                 return parent;
1380         }
1381         Py_RETURN_NONE;
1382 }
1383
1384 PyObject* KX_GameObject::PySetParent(PyObject* self, PyObject* value)
1385 {
1386         if (!PyObject_TypeCheck(value, &KX_GameObject::Type)) {
1387                 PyErr_SetString(PyExc_TypeError, "expected a KX_GameObject type");
1388                 return NULL;
1389         }
1390         
1391         // The object we want to set as parent
1392         CValue *m_ob = (CValue*)value;
1393         KX_GameObject *obj = ((KX_GameObject*)m_ob);
1394         KX_Scene *scene = PHY_GetActiveScene();
1395         
1396         this->SetParent(scene, obj);
1397                 
1398         Py_RETURN_NONE;
1399 }
1400
1401 PyObject* KX_GameObject::PyRemoveParent(PyObject* self)
1402 {
1403         KX_Scene *scene = PHY_GetActiveScene();
1404         this->RemoveParent(scene);
1405         Py_RETURN_NONE;
1406 }
1407
1408
1409 static void walk_children(SG_Node* node, CListValue* list, bool recursive)
1410 {
1411         NodeList& children = node->GetSGChildren();
1412
1413         for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
1414         {
1415                 SG_Node* childnode = (*childit);
1416                 CValue* childobj = (CValue*)childnode->GetSGClientObject();
1417                 if (childobj != NULL) // This is a GameObject
1418                 {
1419                         // add to the list
1420                         list->Add(childobj->AddRef());
1421                 }
1422                 
1423                 // if the childobj is NULL then this may be an inverse parent link
1424                 // so a non recursive search should still look down this node.
1425                 if (recursive || childobj==NULL) {
1426                         walk_children(childnode, list, recursive);
1427                 }
1428         }
1429 }
1430
1431 PyObject* KX_GameObject::PyGetChildren(PyObject* self)
1432 {
1433         CListValue* list = new CListValue();
1434         walk_children(m_pSGNode, list, 0);
1435         return list;
1436 }
1437
1438 PyObject* KX_GameObject::PyGetChildrenRecursive(PyObject* self)
1439 {
1440         CListValue* list = new CListValue();
1441         walk_children(m_pSGNode, list, 1);
1442         return list;
1443 }
1444
1445 PyObject* KX_GameObject::PyGetMesh(PyObject* self, PyObject* args)
1446 {
1447         int mesh = 0;
1448
1449         if (!PyArg_ParseTuple(args, "|i", &mesh))
1450                 return NULL; // python sets a simple error
1451         
1452         if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0)
1453         {
1454                 KX_MeshProxy* meshproxy = new KX_MeshProxy(m_meshes[mesh]);
1455                 return meshproxy;
1456         }
1457         
1458         Py_RETURN_NONE;
1459 }
1460
1461
1462
1463
1464
1465 PyObject* KX_GameObject::PySetCollisionMargin(PyObject* self, PyObject* value)
1466 {
1467         float collisionMargin = PyFloat_AsDouble(value);
1468         
1469         if (collisionMargin==-1 && PyErr_Occurred()) {
1470                 PyErr_SetString(PyExc_TypeError, "expected a float");
1471                 return NULL;
1472         }
1473         
1474         if (m_pPhysicsController1)
1475         {
1476                 m_pPhysicsController1->setMargin(collisionMargin);
1477                 Py_RETURN_NONE;
1478         }
1479         PyErr_SetString(PyExc_RuntimeError, "This object has no physics controller");
1480         return NULL;
1481 }
1482
1483
1484
1485 PyObject* KX_GameObject::PyApplyImpulse(PyObject* self, PyObject* args)
1486 {
1487         PyObject* pyattach;
1488         PyObject* pyimpulse;
1489         
1490         if (!m_pPhysicsController1)     {
1491                 PyErr_SetString(PyExc_RuntimeError, "This object has no physics controller");
1492                 return NULL;
1493         }
1494         
1495         if (PyArg_ParseTuple(args, "OO", &pyattach, &pyimpulse))
1496         {
1497                 MT_Point3  attach;
1498                 MT_Vector3 impulse;
1499                 if (PyVecTo(pyattach, attach) && PyVecTo(pyimpulse, impulse))
1500                 {
1501                         m_pPhysicsController1->applyImpulse(attach, impulse);
1502                         Py_RETURN_NONE;
1503                 }
1504
1505         }
1506         
1507         return NULL;
1508 }
1509
1510
1511
1512 PyObject* KX_GameObject::PySuspendDynamics(PyObject* self)
1513 {
1514         SuspendDynamics();
1515         Py_RETURN_NONE;
1516 }
1517
1518
1519
1520 PyObject* KX_GameObject::PyRestoreDynamics(PyObject* self)
1521 {
1522         RestoreDynamics();
1523         Py_RETURN_NONE;
1524 }
1525
1526
1527
1528 PyObject* KX_GameObject::PyGetOrientation(PyObject* self) //keywords
1529 {
1530         return PyObjectFrom(NodeGetWorldOrientation());
1531 }
1532
1533
1534
1535 PyObject* KX_GameObject::PySetOrientation(PyObject* self, PyObject* value)
1536 {
1537         MT_Matrix3x3 matrix;
1538         if (PyObject_IsMT_Matrix(value, 3) && PyMatTo(value, matrix))
1539         {
1540                 NodeSetLocalOrientation(matrix);
1541                 NodeUpdateGS(0.f,true);
1542                 Py_RETURN_NONE;
1543         }
1544
1545         MT_Quaternion quat;
1546         if (PyVecTo(value, quat))
1547         {
1548                 matrix.setRotation(quat);
1549                 NodeSetLocalOrientation(matrix);
1550                 NodeUpdateGS(0.f,true);
1551                 Py_RETURN_NONE;
1552         }
1553         return NULL;
1554 }
1555
1556 PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* self, PyObject* args)
1557 {
1558         PyObject* pyvect;
1559         int axis = 2; //z axis is the default
1560         float fac = 1.0;
1561         
1562         if (PyArg_ParseTuple(args,"O|if",&pyvect,&axis, &fac))
1563         {
1564                 MT_Vector3 vect;
1565                 if (PyVecTo(pyvect, vect))
1566                 {
1567                         if (fac<=0.0) Py_RETURN_NONE; // Nothing to do.
1568                         if (fac> 1.0) fac= 1.0;
1569                         
1570                         AlignAxisToVect(vect,axis,fac);
1571                         NodeUpdateGS(0.f,true);
1572                         Py_RETURN_NONE;
1573                 }
1574         }
1575         return NULL;
1576 }
1577
1578 PyObject* KX_GameObject::PyGetAxisVect(PyObject* self, PyObject* value)
1579 {
1580         MT_Vector3 vect;
1581         if (PyVecTo(value, vect))
1582         {
1583                 return PyObjectFrom(NodeGetWorldOrientation() * vect);
1584         }
1585         return NULL;
1586 }
1587
1588 PyObject* KX_GameObject::PySetPosition(PyObject* self, PyObject* value)
1589 {
1590         MT_Point3 pos;
1591         if (PyVecTo(value, pos))
1592         {
1593                 NodeSetLocalPosition(pos);
1594                 NodeUpdateGS(0.f,true);
1595                 Py_RETURN_NONE;
1596         }
1597
1598         return NULL;
1599 }
1600
1601 PyObject* KX_GameObject::PySetWorldPosition(PyObject* self, PyObject* value)
1602 {
1603         MT_Point3 pos;
1604         if (PyVecTo(value, pos))
1605         {
1606                 NodeSetWorldPosition(pos);
1607                 NodeUpdateGS(0.f,true);
1608                 Py_RETURN_NONE;
1609         }
1610
1611         return NULL;
1612 }
1613
1614 PyObject* KX_GameObject::PyGetPhysicsId(PyObject* self)
1615 {
1616         KX_IPhysicsController* ctrl = GetPhysicsController();
1617         uint_ptr physid=0;
1618         if (ctrl)
1619         {
1620                 physid= (uint_ptr)ctrl->GetUserData();
1621         }
1622         return PyInt_FromLong((long)physid);
1623 }
1624
1625 PyObject* KX_GameObject::PyGetPropertyNames(PyObject* self)
1626 {
1627         return ConvertKeysToPython();
1628 }
1629
1630 KX_PYMETHODDEF_DOC(KX_GameObject, getDistanceTo,
1631 "getDistanceTo(other): get distance to another point/KX_GameObject")
1632 {
1633         MT_Point3 b;
1634         if (PyVecArgTo(args, b))
1635         {
1636                 return PyFloat_FromDouble(NodeGetWorldPosition().distance(b));
1637         }
1638         PyErr_Clear();
1639         
1640         PyObject *pyother;
1641         KX_GameObject *other;
1642         if (PyArg_ParseTuple(args, "O", &pyother) && ConvertPythonToGameObject(pyother, &other, false))
1643         {
1644                 return PyFloat_FromDouble(NodeGetWorldPosition().distance(other->NodeGetWorldPosition()));
1645         }
1646         
1647         return NULL;
1648 }
1649
1650 KX_PYMETHODDEF_DOC(KX_GameObject, getVectTo,
1651 "getVectTo(other): get vector and the distance to another point/KX_GameObject\n"
1652 "Returns a 3-tuple with (distance,worldVector,localVector)\n")
1653 {
1654         MT_Point3 toPoint, fromPoint;
1655         MT_Vector3 toDir, locToDir;
1656         MT_Scalar distance;
1657
1658         PyObject *returnValue;
1659         PyObject *pyother;
1660
1661         if (!PyVecArgTo(args, toPoint))
1662         {
1663                 PyErr_Clear();
1664                 
1665                 KX_GameObject *other;
1666                 if (PyArg_ParseTuple(args, "O", &pyother) && ConvertPythonToGameObject(pyother, &other, false))
1667                 {
1668                         toPoint = other->NodeGetWorldPosition();
1669                 } else
1670                 {
1671                         PyErr_SetString(PyExc_TypeError, "Expected a 3D Vector or GameObject type");
1672                         return NULL;
1673                 }
1674         }
1675
1676         fromPoint = NodeGetWorldPosition();
1677         toDir = toPoint-fromPoint;
1678         distance = toDir.length();
1679
1680         if (MT_fuzzyZero(distance))
1681         {
1682                 //cout << "getVectTo() Error: Null vector!\n";
1683                 locToDir = toDir = MT_Vector3(0.0,0.0,0.0);
1684                 distance = 0.0;
1685         } else {
1686                 toDir.normalize();
1687                 locToDir = toDir * NodeGetWorldOrientation();
1688         }
1689         
1690         returnValue = PyTuple_New(3);
1691         if (returnValue) { // very unlikely to fail, python sets a memory error here.
1692                 PyTuple_SET_ITEM(returnValue, 0, PyFloat_FromDouble(distance));
1693                 PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(toDir));
1694                 PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(locToDir));
1695         }
1696         return returnValue;
1697 }
1698
1699 bool KX_GameObject::RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data)
1700 {
1701         KX_GameObject* hitKXObj = client->m_gameobject;
1702         
1703         // if X-ray option is selected, the unwnted objects were not tested, so get here only with true hit
1704         // if not, all objects were tested and the front one may not be the correct one.
1705         if (m_xray || m_testPropName.Length() == 0 || hitKXObj->GetProperty(m_testPropName) != NULL)
1706         {
1707                 m_pHitObject = hitKXObj;
1708                 return true;
1709         }
1710         // return true to stop RayCast::RayTest from looping, the above test was decisive
1711         // We would want to loop only if we want to get more than one hit point
1712         return true;
1713 }
1714
1715 /* this function is used to pre-filter the object before casting the ray on them.
1716    This is useful for "X-Ray" option when we want to see "through" unwanted object.
1717  */
1718 bool KX_GameObject::NeedRayCast(KX_ClientObjectInfo* client)
1719 {
1720         KX_GameObject* hitKXObj = client->m_gameobject;
1721         
1722         if (client->m_type > KX_ClientObjectInfo::ACTOR)
1723         {
1724                 // Unknown type of object, skip it.
1725                 // Should not occur as the sensor objects are filtered in RayTest()
1726                 printf("Invalid client type %d found in ray casting\n", client->m_type);
1727                 return false;
1728         }
1729         
1730         // if X-Ray option is selected, skip object that don't match the criteria as we see through them
1731         // if not, test all objects because we don't know yet which one will be on front
1732         if (!m_xray || m_testPropName.Length() == 0 || hitKXObj->GetProperty(m_testPropName) != NULL)
1733         {
1734                 return true;
1735         }
1736         // skip the object
1737         return false;
1738 }
1739
1740 KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo,
1741 "rayCastTo(other,dist,prop): look towards another point/KX_GameObject and return first object hit within dist that matches prop\n"
1742 " prop = property name that object must have; can be omitted => detect any object\n"
1743 " dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to other\n"
1744 " other = 3-tuple or object reference")
1745 {
1746         MT_Point3 toPoint;
1747         PyObject* pyarg;
1748         float dist = 0.0f;
1749         char *propName = NULL;
1750
1751         if (!PyArg_ParseTuple(args,"O|fs", &pyarg, &dist, &propName)) {
1752                 return NULL; // python sets simple error
1753         }
1754
1755         if (!PyVecTo(pyarg, toPoint))
1756         {
1757                 KX_GameObject *other;
1758                 PyErr_Clear();
1759                 
1760                 if (ConvertPythonToGameObject(pyarg, &other, false))
1761                 {
1762                         toPoint = other->NodeGetWorldPosition();
1763                 } else
1764                 {
1765                         PyErr_SetString(PyExc_TypeError, "the first argument to rayCastTo must be a vector or a KX_GameObject");
1766                         return NULL;
1767                 }
1768         }
1769         MT_Point3 fromPoint = NodeGetWorldPosition();
1770         if (dist != 0.0f)
1771         {
1772                 MT_Vector3 toDir = toPoint-fromPoint;
1773                 toDir.normalize();
1774                 toPoint = fromPoint + (dist) * toDir;
1775         }
1776
1777         PHY_IPhysicsEnvironment* pe = GetPhysicsEnvironment();
1778         KX_IPhysicsController *spc = GetPhysicsController();
1779         KX_GameObject *parent = GetParent();
1780         if (!spc && parent)
1781                 spc = parent->GetPhysicsController();
1782         if (parent)
1783                 parent->Release();
1784         
1785         m_pHitObject = NULL;
1786         if (propName)
1787                 m_testPropName = propName;
1788         else
1789                 m_testPropName.SetLength(0);
1790         KX_RayCast::Callback<KX_GameObject> callback(this,spc);
1791         KX_RayCast::RayTest(pe, fromPoint, toPoint, callback);
1792
1793     if (m_pHitObject)
1794         {
1795                 m_pHitObject->AddRef();
1796                 return m_pHitObject;
1797         }
1798         Py_RETURN_NONE;
1799 }
1800
1801 KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
1802                                    "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"
1803                                    " If no hit, return (None,None,None) or (None,None,None,None).\n"
1804 " to   = 3-tuple or object reference for destination of ray (if object, use center of object)\n"
1805 " from = 3-tuple or object reference for origin of ray (if object, use center of object)\n"
1806 "        Can be None or omitted => start from self object center\n"
1807 " dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to to\n"
1808 " prop = property name that object must have; can be omitted => detect any object\n"
1809 " face = normal option: 1=>return face normal; 0 or omitted => normal is oriented towards origin\n"
1810 " xray = X-ray option: 1=>skip objects that don't match prop; 0 or omitted => stop on first object\n"
1811 " poly = polygon option: 1=>return value is a 4-tuple and the 4th element is a KX_PolyProxy object\n"
1812 "                           which can be None if hit object has no mesh or if there is no hit\n"
1813 "        If 0 or omitted, return value is a 3-tuple\n"
1814 "Note: The object on which you call this method matters: the ray will ignore it.\n"
1815 "      prop and xray option interact as follow:\n"
1816 "        prop off, xray off: return closest hit or no hit if there is no object on the full extend of the ray\n"
1817 "        prop off, xray on : idem\n"
1818 "        prop on,  xray off: return closest hit if it matches prop, no hit otherwise\n"
1819 "        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")
1820 {
1821         MT_Point3 toPoint;
1822         MT_Point3 fromPoint;
1823         PyObject* pyto;
1824         PyObject* pyfrom = NULL;
1825         float dist = 0.0f;
1826         char *propName = NULL;
1827         KX_GameObject *other;
1828         int face=0, xray=0, poly=0;
1829
1830         if (!PyArg_ParseTuple(args,"O|Ofsiii", &pyto, &pyfrom, &dist, &propName, &face, &xray, &poly)) {
1831                 return NULL; // Python sets a simple error
1832         }
1833
1834         if (!PyVecTo(pyto, toPoint))
1835         {
1836                 PyErr_Clear();
1837                 
1838                 if (ConvertPythonToGameObject(pyto, &other, false))
1839                 {
1840                         toPoint = other->NodeGetWorldPosition();
1841                 } else
1842                 {
1843                         PyErr_SetString(PyExc_TypeError, "the first argument to rayCast must be a vector or a KX_GameObject");
1844                         return NULL;
1845                 }
1846         }
1847         if (!pyfrom || pyfrom == Py_None)
1848         {
1849                 fromPoint = NodeGetWorldPosition();
1850         }
1851         else if (!PyVecTo(pyfrom, fromPoint))
1852         {
1853                 PyErr_Clear();
1854                 
1855                 if (ConvertPythonToGameObject(pyfrom, &other, false))
1856                 {
1857                         fromPoint = other->NodeGetWorldPosition();
1858                 } else
1859                 {
1860                         PyErr_SetString(PyExc_TypeError, "the second optional argument to rayCast must be a vector or a KX_GameObject");
1861                         return NULL;
1862                 }
1863         }
1864         
1865         if (dist != 0.0f) {
1866                 MT_Vector3 toDir = toPoint-fromPoint;
1867                 if (MT_fuzzyZero(toDir.length2())) {
1868                         return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
1869                 }
1870                 toDir.normalize();
1871                 toPoint = fromPoint + (dist) * toDir;
1872         } else if (MT_fuzzyZero((toPoint-fromPoint).length2())) {
1873                 return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
1874         }
1875         
1876         PHY_IPhysicsEnvironment* pe = GetPhysicsEnvironment();
1877         KX_IPhysicsController *spc = GetPhysicsController();
1878         KX_GameObject *parent = GetParent();
1879         if (!spc && parent)
1880                 spc = parent->GetPhysicsController();
1881         if (parent)
1882                 parent->Release();
1883         
1884         m_pHitObject = NULL;
1885         if (propName)
1886                 m_testPropName = propName;
1887         else
1888                 m_testPropName.SetLength(0);
1889         m_xray = xray;
1890         // to get the hit results
1891         KX_RayCast::Callback<KX_GameObject> callback(this,spc,NULL,face);
1892         KX_RayCast::RayTest(pe, fromPoint, toPoint, callback);
1893
1894         if (m_pHitObject)
1895         {
1896                 PyObject* returnValue = (poly) ? PyTuple_New(4) : PyTuple_New(3);
1897                 if (returnValue) { // unlikely this would ever fail, if it does python sets an error
1898                         PyTuple_SET_ITEM(returnValue, 0, m_pHitObject->AddRef());
1899                         PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(callback.m_hitPoint));
1900                         PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(callback.m_hitNormal));
1901                         if (poly)
1902                         {
1903                                 if (callback.m_hitMesh)
1904                                 {
1905                                         // if this field is set, then we can trust that m_hitPolygon is a valid polygon
1906                                         RAS_Polygon* poly = callback.m_hitMesh->GetPolygon(callback.m_hitPolygon);
1907                                         KX_PolyProxy* polyproxy = new KX_PolyProxy(callback.m_hitMesh, poly);
1908                                         PyTuple_SET_ITEM(returnValue, 3, polyproxy);
1909                                 }
1910                                 else
1911                                 {
1912                                         Py_INCREF(Py_None);
1913                                         PyTuple_SET_ITEM(returnValue, 3, Py_None);
1914                                 }
1915                         }
1916                 }
1917                 return returnValue;
1918         }
1919         // no hit
1920         if (poly)
1921                 return Py_BuildValue("OOOO", Py_None, Py_None, Py_None, Py_None);
1922         else
1923                 return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
1924 }
1925
1926 /* --------------------------------------------------------------------- 
1927  * Some stuff taken from the header
1928  * --------------------------------------------------------------------- */
1929 void KX_GameObject::Relink(GEN_Map<GEN_HashedPtr, void*> *map_parameter)        
1930 {
1931         // we will relink the sensors and actuators that use object references
1932         // if the object is part of the replicated hierarchy, use the new
1933         // object reference instead
1934         SCA_SensorList& sensorlist = GetSensors();
1935         SCA_SensorList::iterator sit;
1936         for (sit=sensorlist.begin(); sit != sensorlist.end(); sit++)
1937         {
1938                 (*sit)->Relink(map_parameter);
1939         }
1940         SCA_ActuatorList& actuatorlist = GetActuators();
1941         SCA_ActuatorList::iterator ait;
1942         for (ait=actuatorlist.begin(); ait != actuatorlist.end(); ait++)
1943         {
1944                 (*ait)->Relink(map_parameter);
1945         }
1946 }
1947
1948 bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py_none_ok)
1949 {
1950         if (value==NULL) {
1951                 PyErr_SetString(PyExc_TypeError, "Error in ConvertPythonToGameObject, python pointer NULL, should never happen");
1952                 *object = NULL;
1953                 return false;
1954         }
1955                 
1956         if (value==Py_None) {
1957                 *object = NULL;
1958                 
1959                 if (py_none_ok) {
1960                         return true;
1961                 } else {
1962                         PyErr_SetString(PyExc_TypeError, "Expected KX_GameObject or a string for a name of a KX_GameObject, None is invalid");
1963                         return false;
1964                 }
1965                 return (py_none_ok ? true : false);
1966         }
1967         
1968         if (PyString_Check(value)) {
1969                 *object = (KX_GameObject *)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String( PyString_AsString(value) ));
1970                 
1971                 if (*object) {
1972                         return true;
1973                 } else {
1974                         PyErr_SetString(PyExc_ValueError, "Requested name did not match any KX_GameObject");
1975                         return false;
1976                 }
1977         }
1978         
1979         if (PyObject_TypeCheck(value, &KX_GameObject::Type)) {
1980                 *object = static_cast<KX_GameObject*>(value);
1981                 return true;
1982         }
1983         
1984         *object = NULL;
1985         
1986         if (py_none_ok) {
1987                 PyErr_SetString(PyExc_TypeError, "Expect a KX_GameObject, a string or None");
1988         } else {
1989                 PyErr_SetString(PyExc_TypeError, "Expect a KX_GameObject or a string");
1990         }
1991         
1992         return false;
1993 }