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