Merged 15170:15635 from trunk (no conflicts or even merges)
[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 <stdio.h> // printf
55 #include "SG_Controller.h"
56 #include "KX_IPhysicsController.h"
57 #include "SG_Node.h"
58 #include "SG_Controller.h"
59 #include "KX_ClientObjectInfo.h"
60 #include "RAS_BucketManager.h"
61 #include "KX_RayCast.h"
62 #include "KX_PythonInit.h"
63 #include "KX_PyMath.h"
64
65 // This file defines relationships between parents and children
66 // in the game engine.
67
68 #include "KX_SG_NodeRelationships.h"
69
70 KX_GameObject::KX_GameObject(
71         void* sgReplicationInfo,
72         SG_Callbacks callbacks,
73         PyTypeObject* T
74 ) : 
75         SCA_IObject(T),
76         m_bDyna(false),
77         m_layer(0),
78         m_bSuspendDynamics(false),
79         m_bUseObjectColor(false),
80         m_bIsNegativeScaling(false),
81         m_pBlenderObject(NULL),
82         m_bVisible(true),
83         m_pPhysicsController1(NULL),
84         m_pPhysicsEnvironment(NULL),
85         m_pHitObject(NULL),
86         m_isDeformable(false)
87 {
88         m_ignore_activity_culling = false;
89         m_pClient_info = new KX_ClientObjectInfo(this, KX_ClientObjectInfo::ACTOR);
90         m_pSGNode = new SG_Node(this,sgReplicationInfo,callbacks);
91
92         // define the relationship between this node and it's parent.
93         
94         KX_NormalParentRelation * parent_relation = 
95                 KX_NormalParentRelation::New();
96         m_pSGNode->SetParentRelation(parent_relation);
97         
98
99 };
100
101
102
103 KX_GameObject::~KX_GameObject()
104 {
105         // is this delete somewhere ?
106         //if (m_sumoObj)
107         //      delete m_sumoObj;
108         delete m_pClient_info;
109         //if (m_pSGNode)
110         //      delete m_pSGNode;
111         if (m_pSGNode)
112         {
113                 // must go through controllers and make sure they will not use us anymore
114                 // This is important for KX_BulletPhysicsControllers that unregister themselves
115                 // from the object when they are deleted.
116                 SGControllerList::iterator contit;
117                 SGControllerList& controllers = m_pSGNode->GetSGControllerList();
118                 for (contit = controllers.begin();contit!=controllers.end();++contit)
119                 {
120                         (*contit)->ClearObject();
121                 }
122                 m_pSGNode->SetSGClientObject(NULL);
123         }
124 }
125
126
127
128 CValue* KX_GameObject:: Calc(VALUE_OPERATOR op, CValue *val) 
129 {
130         return NULL;
131 }
132
133
134
135 CValue* KX_GameObject::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val)
136 {
137         return NULL;
138 }
139
140
141
142 const STR_String & KX_GameObject::GetText()
143 {
144         return m_text;
145 }
146
147
148
149 float KX_GameObject::GetNumber()
150 {
151         return 0;
152 }
153
154
155
156 STR_String KX_GameObject::GetName()
157 {
158         return m_name;
159 }
160
161
162
163 void KX_GameObject::SetName(STR_String name)
164 {
165         m_name = name;
166 };                                                              // Set the name of the value
167
168
169
170 void KX_GameObject::ReplicaSetName(STR_String name)
171 {
172 }
173
174
175
176
177
178
179 KX_IPhysicsController* KX_GameObject::GetPhysicsController()
180 {
181         return m_pPhysicsController1;
182 }
183
184
185
186
187
188 KX_GameObject* KX_GameObject::GetParent()
189 {
190         KX_GameObject* result = NULL;
191         SG_Node* node = m_pSGNode;
192         
193         while (node && !result)
194         {
195                 node = node->GetSGParent();
196                 if (node)
197                         result = (KX_GameObject*)node->GetSGClientObject();
198         }
199         
200         if (result)
201                 result->AddRef();
202
203         return result;
204         
205 }
206
207 void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj)
208 {
209         if (obj && GetSGNode()->GetSGParent() != obj->GetSGNode())
210         {
211                 // Make sure the objects have some scale
212                 MT_Vector3 scale1 = NodeGetWorldScaling();
213                 MT_Vector3 scale2 = obj->NodeGetWorldScaling();
214                 if (fabs(scale2[0]) < FLT_EPSILON || 
215                         fabs(scale2[1]) < FLT_EPSILON || 
216                         fabs(scale2[2]) < FLT_EPSILON || 
217                         fabs(scale1[0]) < FLT_EPSILON || 
218                         fabs(scale1[1]) < FLT_EPSILON || 
219                         fabs(scale1[2]) < FLT_EPSILON) { return; }
220
221                 // Remove us from our old parent and set our new parent
222                 RemoveParent(scene);
223                 obj->GetSGNode()->AddChild(GetSGNode());
224
225                 // Set us to our new scale, position, and orientation
226                 scale1[0] = scale1[0]/scale2[0];
227                 scale1[1] = scale1[1]/scale2[1];
228                 scale1[2] = scale1[2]/scale2[2];
229                 MT_Matrix3x3 invori = obj->NodeGetWorldOrientation().inverse();
230                 MT_Vector3 newpos = invori*(NodeGetWorldPosition()-obj->NodeGetWorldPosition())*scale1;
231
232                 NodeSetLocalScale(scale1);
233                 NodeSetLocalPosition(MT_Point3(newpos[0],newpos[1],newpos[2]));
234                 NodeSetLocalOrientation(invori*NodeGetWorldOrientation());
235                 NodeUpdateGS(0.f,true);
236                 // object will now be a child, it must be removed from the parent list
237                 CListValue* rootlist = scene->GetRootParentList();
238                 if (rootlist->RemoveValue(this))
239                         // the object was in parent list, decrement ref count as it's now removed
240                         Release();
241                 if (m_pPhysicsController1) 
242                 {
243                         m_pPhysicsController1->SuspendDynamics(true);
244                 }
245         }
246 }
247
248 void KX_GameObject::RemoveParent(KX_Scene *scene)
249 {
250         if (GetSGNode()->GetSGParent())
251         {
252                 // Set us to the right spot 
253                 GetSGNode()->SetLocalScale(GetSGNode()->GetWorldScaling());
254                 GetSGNode()->SetLocalOrientation(GetSGNode()->GetWorldOrientation());
255                 GetSGNode()->SetLocalPosition(GetSGNode()->GetWorldPosition());
256
257                 // Remove us from our parent
258                 GetSGNode()->DisconnectFromParent();
259                 NodeUpdateGS(0.f,true);
260                 // the object is now a root object, add it to the parentlist
261                 CListValue* rootlist = scene->GetRootParentList();
262                 if (!rootlist->SearchValue(this))
263                         // object was not in root list, add it now and increment ref count
264                         rootlist->Add(AddRef());
265                 if (m_pPhysicsController1) 
266                 {
267                         m_pPhysicsController1->RestoreDynamics();
268                 }
269         }
270 }
271
272 void KX_GameObject::ProcessReplica(KX_GameObject* replica)
273 {
274         replica->m_pPhysicsController1 = NULL;
275         replica->m_pSGNode = NULL;
276         replica->m_pClient_info = new KX_ClientObjectInfo(*m_pClient_info);
277         replica->m_pClient_info->m_gameobject = replica;
278 }
279
280
281
282 CValue* KX_GameObject::GetReplica()
283 {
284         KX_GameObject* replica = new KX_GameObject(*this);
285         
286         // this will copy properties and so on...
287         CValue::AddDataToReplica(replica);
288         ProcessReplica(replica);
289         
290         return replica;
291 }
292
293
294
295 void KX_GameObject::ApplyForce(const MT_Vector3& force,bool local)
296 {
297         if (m_pPhysicsController1)
298                 m_pPhysicsController1->ApplyForce(force,local);
299 }
300
301
302
303 void KX_GameObject::ApplyTorque(const MT_Vector3& torque,bool local)
304 {
305         if (m_pPhysicsController1)
306                 m_pPhysicsController1->ApplyTorque(torque,local);
307 }
308
309
310
311 void KX_GameObject::ApplyMovement(const MT_Vector3& dloc,bool local)
312 {
313         if (m_pPhysicsController1) // (IsDynamic())
314         {
315                 m_pPhysicsController1->RelativeTranslate(dloc,local);
316         }
317         GetSGNode()->RelativeTranslate(dloc,GetSGNode()->GetSGParent(),local);
318 }
319
320
321
322 void KX_GameObject::ApplyRotation(const MT_Vector3& drot,bool local)
323 {
324         MT_Matrix3x3 rotmat(drot);
325
326         GetSGNode()->RelativeRotate(rotmat,local);
327
328         if (m_pPhysicsController1) { // (IsDynamic())
329                 m_pPhysicsController1->RelativeRotate(rotmat,local); 
330         }
331 }
332
333
334
335 /**
336 GetOpenGL Matrix, returns an OpenGL 'compatible' matrix
337 */
338 double* KX_GameObject::GetOpenGLMatrix()
339 {
340         // todo: optimize and only update if necessary
341         double* fl = m_OpenGL_4x4Matrix.getPointer();
342         MT_Transform trans;
343         
344         trans.setOrigin(GetSGNode()->GetWorldPosition());
345         trans.setBasis(GetSGNode()->GetWorldOrientation());
346         
347         MT_Vector3 scaling = GetSGNode()->GetWorldScaling();
348         m_bIsNegativeScaling = ((scaling[0] < 0.0) ^ (scaling[1] < 0.0) ^ (scaling[2] < 0.0)) ? true : false;
349         trans.scale(scaling[0], scaling[1], scaling[2]);
350         trans.getValue(fl);
351
352         return fl;
353 }
354
355
356
357 void KX_GameObject::Bucketize()
358 {
359         double* fl = GetOpenGLMatrix();
360
361         for (size_t i=0;i<m_meshes.size();i++)
362                 m_meshes[i]->Bucketize(fl, this, m_bUseObjectColor, m_objectColor);
363 }
364
365
366
367 void KX_GameObject::RemoveMeshes()
368 {
369         double* fl = GetOpenGLMatrix();
370
371         for (size_t i=0;i<m_meshes.size();i++)
372                 m_meshes[i]->RemoveFromBuckets(fl, this);
373
374         //note: meshes can be shared, and are deleted by KX_BlenderSceneConverter
375
376         m_meshes.clear();
377 }
378
379
380
381 void KX_GameObject::UpdateNonDynas()
382 {
383         if (m_pPhysicsController1)
384         {
385                 m_pPhysicsController1->SetSumoTransform(true);
386         }
387 }
388
389
390
391 void KX_GameObject::UpdateTransform()
392 {
393         if (m_pPhysicsController1)
394                 m_pPhysicsController1->SetSumoTransform(false);
395 }
396
397 void KX_GameObject::UpdateTransformFunc(SG_IObject* node, void* gameobj, void* scene)
398 {
399         ((KX_GameObject*)gameobj)->UpdateTransform();
400 }
401
402
403 void KX_GameObject::SetDebugColor(unsigned int bgra)
404 {
405         for (size_t i=0;i<m_meshes.size();i++)
406                 m_meshes[i]->DebugColor(bgra);  
407 }
408
409
410
411 void KX_GameObject::ResetDebugColor()
412 {
413         SetDebugColor(0xff000000);
414 }
415
416 void KX_GameObject::InitIPO(bool ipo_as_force,
417                                                         bool ipo_add,
418                                                         bool ipo_local)
419 {
420         SGControllerList::iterator it = GetSGNode()->GetSGControllerList().begin();
421
422         while (it != GetSGNode()->GetSGControllerList().end()) {
423                 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_RESET, true);
424                 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_AS_FORCE, ipo_as_force);
425                 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_ADD, ipo_add);
426                 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_LOCAL, ipo_local);
427                 it++;
428         }
429
430
431 void KX_GameObject::UpdateIPO(float curframetime,
432                                                           bool recurse) 
433 {
434         // just the 'normal' update procedure.
435         GetSGNode()->SetSimulatedTime(curframetime,recurse);
436         GetSGNode()->UpdateWorldData(curframetime);
437         UpdateTransform();
438 }
439
440 // IPO update
441 void 
442 KX_GameObject::UpdateMaterialData(
443                 MT_Vector4 rgba,
444                 MT_Vector3 specrgb,
445                 MT_Scalar hard,
446                 MT_Scalar spec,
447                 MT_Scalar ref,
448                 MT_Scalar emit,
449                 MT_Scalar alpha
450
451         )
452 {
453         int mesh = 0;
454         if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0) {
455                 RAS_MaterialBucket::Set::iterator mit = m_meshes[mesh]->GetFirstMaterial();
456                 for(; mit != m_meshes[mesh]->GetLastMaterial(); ++mit)
457                 {
458                         RAS_IPolyMaterial* poly = (*mit)->GetPolyMaterial();
459                         if(poly->GetFlag() & RAS_BLENDERMAT )
460                         {
461                                 SetObjectColor(rgba);
462                                 KX_BlenderMaterial *m =  static_cast<KX_BlenderMaterial*>(poly);
463                                 m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha);
464                         }
465                 }
466         }
467 }
468 bool
469 KX_GameObject::GetVisible(
470         void
471         )
472 {
473         return m_bVisible;
474 }
475
476 void
477 KX_GameObject::SetVisible(
478         bool v
479         )
480 {
481         m_bVisible = v;
482 }
483
484 void
485 KX_GameObject::SetLayer(
486         int l
487         )
488 {
489         m_layer = l;
490 }
491
492 int
493 KX_GameObject::GetLayer(
494         void
495         )
496 {
497         return m_layer;
498 }
499
500 // used by Python, and the actuatorshould _not_ be misused by the
501 // scene!
502 void 
503 KX_GameObject::MarkVisible(
504         bool visible
505         )
506 {
507         /* If explicit visibility settings are used, this is
508          * determined on this level. Maybe change this to mesh level
509          * later on? */
510         
511         double* fl = GetOpenGLMatrixPtr()->getPointer();
512         for (size_t i=0;i<m_meshes.size();i++)
513         {
514                 m_meshes[i]->MarkVisible(fl,this,visible,m_bUseObjectColor,m_objectColor);
515         }
516 }
517
518
519 // Always use the flag?
520 void 
521 KX_GameObject::MarkVisible(
522         void
523         )
524 {
525         double* fl = GetOpenGLMatrixPtr()->getPointer();
526         for (size_t i=0;i<m_meshes.size();i++)
527         {
528                 m_meshes[i]->MarkVisible(fl,
529                                          this,
530                                          m_bVisible,
531                                          m_bUseObjectColor,
532                                          m_objectColor
533                         );
534         }
535 }
536
537
538 void KX_GameObject::addLinearVelocity(const MT_Vector3& lin_vel,bool local)
539 {
540         if (m_pPhysicsController1)
541                 m_pPhysicsController1->SetLinearVelocity(lin_vel + m_pPhysicsController1->GetLinearVelocity(),local);
542 }
543
544
545
546 void KX_GameObject::setLinearVelocity(const MT_Vector3& lin_vel,bool local)
547 {
548         if (m_pPhysicsController1)
549                 m_pPhysicsController1->SetLinearVelocity(lin_vel,local);
550 }
551
552
553
554 void KX_GameObject::setAngularVelocity(const MT_Vector3& ang_vel,bool local)
555 {
556         if (m_pPhysicsController1)
557                 m_pPhysicsController1->SetAngularVelocity(ang_vel,local);
558 }
559
560 void KX_GameObject::ResolveCombinedVelocities(
561         const MT_Vector3 & lin_vel,
562         const MT_Vector3 & ang_vel,
563         bool lin_vel_local,
564         bool ang_vel_local
565 ){
566         if (m_pPhysicsController1)
567         {
568
569                 MT_Vector3 lv = lin_vel_local ? NodeGetWorldOrientation() * lin_vel : lin_vel;
570                 MT_Vector3 av = ang_vel_local ? NodeGetWorldOrientation() * ang_vel : ang_vel;
571                 m_pPhysicsController1->resolveCombinedVelocities(
572                         lv.x(),lv.y(),lv.z(),av.x(),av.y(),av.z());
573         }
574 }
575
576
577 void KX_GameObject::SetObjectColor(const MT_Vector4& rgbavec)
578 {
579         m_bUseObjectColor = true;
580         m_objectColor = rgbavec;
581 }
582
583 void KX_GameObject::AlignAxisToVect(const MT_Vector3& dir, int axis, float fac)
584 {
585         MT_Matrix3x3 orimat;
586         MT_Vector3 vect,ori,z,x,y;
587         MT_Scalar len;
588
589         vect = dir;
590         len = vect.length();
591         if (MT_fuzzyZero(len))
592         {
593                 cout << "alignAxisToVect() Error: Null vector!\n";
594                 return;
595         }
596         
597         if (fac<=0.0) {
598                 return;
599         }
600         
601         // normalize
602         vect /= len;
603         orimat = GetSGNode()->GetWorldOrientation();
604         switch (axis)
605         {       
606                 case 0: //x axis
607                         ori = MT_Vector3(orimat[0][2], orimat[1][2], orimat[2][2]); //pivot axis
608                         if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON) //is the vector paralell to the pivot?
609                                 ori = MT_Vector3(orimat[0][1], orimat[1][1], orimat[2][1]); //change the pivot!
610                         if (fac == 1.0) {
611                                 x = vect;
612                         } else {
613                                 x = (vect * fac) + ((orimat * MT_Vector3(1.0, 0.0, 0.0)) * (1-fac));
614                                 len = x.length();
615                                 if (MT_fuzzyZero(len)) x = vect;
616                                 else x /= len;
617                         }
618                         y = ori.cross(x);
619                         z = x.cross(y);
620                         break;
621                 case 1: //y axis
622                         ori = MT_Vector3(orimat[0][0], orimat[1][0], orimat[2][0]);
623                         if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON)
624                                 ori = MT_Vector3(orimat[0][2], orimat[1][2], orimat[2][2]);
625                         if (fac == 1.0) {
626                                 y = vect;
627                         } else {
628                                 y = (vect * fac) + ((orimat * MT_Vector3(0.0, 1.0, 0.0)) * (1-fac));
629                                 len = y.length();
630                                 if (MT_fuzzyZero(len)) y = vect;
631                                 else y /= len;
632                         }
633                         z = ori.cross(y);
634                         x = y.cross(z);
635                         break;
636                 case 2: //z axis
637                         ori = MT_Vector3(orimat[0][1], orimat[1][1], orimat[2][1]);
638                         if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON)
639                                 ori = MT_Vector3(orimat[0][0], orimat[1][0], orimat[2][0]);
640                         if (fac == 1.0) {
641                                 z = vect;
642                         } else {
643                                 z = (vect * fac) + ((orimat * MT_Vector3(0.0, 0.0, 1.0)) * (1-fac));
644                                 len = z.length();
645                                 if (MT_fuzzyZero(len)) z = vect;
646                                 else z /= len;
647                         }
648                         x = ori.cross(z);
649                         y = z.cross(x);
650                         break;
651                 default: //wrong input?
652                         cout << "alignAxisToVect(): Wrong axis '" << axis <<"'\n";
653                         return;
654         }
655         x.normalize(); //normalize the vectors
656         y.normalize();
657         z.normalize();
658         orimat = MT_Matrix3x3(  x[0],y[0],z[0],
659                                                         x[1],y[1],z[1],
660                                                         x[2],y[2],z[2]);
661         if (GetSGNode()->GetSGParent() != NULL)
662         {
663                 // the object is a child, adapt its local orientation so that 
664                 // the global orientation is aligned as we want.
665                 MT_Matrix3x3 invori = GetSGNode()->GetSGParent()->GetWorldOrientation().inverse();
666                 NodeSetLocalOrientation(invori*orimat);
667         }
668         else
669                 NodeSetLocalOrientation(orimat);
670 }
671
672 MT_Scalar KX_GameObject::GetMass()
673 {
674         if (m_pPhysicsController1)
675         {
676                 return m_pPhysicsController1->GetMass();
677         }
678         return 0.0;
679 }
680
681 MT_Vector3 KX_GameObject::GetLinearVelocity(bool local)
682 {
683         MT_Vector3 velocity(0.0,0.0,0.0), locvel;
684         MT_Matrix3x3 ori;
685         if (m_pPhysicsController1)
686         {
687                 velocity = m_pPhysicsController1->GetLinearVelocity();
688                 
689                 if (local)
690                 {
691                         ori = GetSGNode()->GetWorldOrientation();
692                         
693                         locvel = velocity * ori;
694                         return locvel;
695                 }
696         }
697         return velocity;        
698 }
699
700 MT_Vector3 KX_GameObject::GetAngularVelocity(bool local)
701 {
702         MT_Vector3 velocity(0.0,0.0,0.0), locvel;
703         MT_Matrix3x3 ori;
704         if (m_pPhysicsController1)
705         {
706                 velocity = m_pPhysicsController1->GetAngularVelocity();
707                 
708                 if (local)
709                 {
710                         ori = GetSGNode()->GetWorldOrientation();
711                         
712                         locvel = velocity * ori;
713                         return locvel;
714                 }
715         }
716         return velocity;        
717 }
718
719
720
721 // scenegraph node stuff
722
723 void KX_GameObject::NodeSetLocalPosition(const MT_Point3& trans)
724 {
725         if (m_pPhysicsController1)
726         {
727                 m_pPhysicsController1->setPosition(trans);
728         }
729
730         if (GetSGNode())
731                 GetSGNode()->SetLocalPosition(trans);
732 }
733
734
735
736 void KX_GameObject::NodeSetLocalOrientation(const MT_Matrix3x3& rot)
737 {
738         if (m_pPhysicsController1)
739         {
740                 m_pPhysicsController1->setOrientation(rot.getRotation());
741         }
742         if (GetSGNode())
743                 GetSGNode()->SetLocalOrientation(rot);
744         else
745         {
746                 int i;
747                 i=0;
748         }
749 }
750
751
752
753 void KX_GameObject::NodeSetLocalScale(const MT_Vector3& scale)
754 {
755         if (m_pPhysicsController1)
756         {
757                 m_pPhysicsController1->setScaling(scale);
758         }
759         
760         if (GetSGNode())
761                 GetSGNode()->SetLocalScale(scale);
762 }
763
764
765
766 void KX_GameObject::NodeSetRelativeScale(const MT_Vector3& scale)
767 {
768         if (GetSGNode())
769                 GetSGNode()->RelativeScale(scale);
770 }
771
772 void KX_GameObject::NodeSetWorldPosition(const MT_Point3& trans)
773 {
774         SG_Node* parent = m_pSGNode->GetSGParent();
775         if (parent != NULL)
776         {
777                 // Make sure the objects have some scale
778                 MT_Vector3 scale = parent->GetWorldScaling();
779                 if (fabs(scale[0]) < FLT_EPSILON || 
780                         fabs(scale[1]) < FLT_EPSILON || 
781                         fabs(scale[2]) < FLT_EPSILON)
782                 { 
783                         return; 
784                 }
785                 scale[0] = 1.0/scale[0];
786                 scale[1] = 1.0/scale[1];
787                 scale[2] = 1.0/scale[2];
788                 MT_Matrix3x3 invori = parent->GetWorldOrientation().inverse();
789                 MT_Vector3 newpos = invori*(trans-parent->GetWorldPosition())*scale;
790                 NodeSetLocalPosition(MT_Point3(newpos[0],newpos[1],newpos[2]));
791         }
792         else 
793         {
794                 NodeSetLocalPosition(trans);
795         }
796 }
797
798
799 void KX_GameObject::NodeUpdateGS(double time,bool bInitiator)
800 {
801         if (GetSGNode())
802                 GetSGNode()->UpdateWorldData(time);
803 }
804
805
806
807 const MT_Matrix3x3& KX_GameObject::NodeGetWorldOrientation() const
808 {
809         return GetSGNode()->GetWorldOrientation();
810 }
811
812
813
814 const MT_Vector3& KX_GameObject::NodeGetWorldScaling() const
815 {
816         return GetSGNode()->GetWorldScaling();
817 }
818
819
820
821 const MT_Point3& KX_GameObject::NodeGetWorldPosition() const
822 {
823         return GetSGNode()->GetWorldPosition();
824 }
825
826 /* Suspend/ resume: for the dynamic behaviour, there is a simple
827  * method. For the residual motion, there is not. I wonder what the
828  * correct solution is for Sumo. Remove from the motion-update tree?
829  *
830  * So far, only switch the physics and logic.
831  * */
832
833 void KX_GameObject::Resume(void)
834 {
835         if (m_suspended) {
836                 SCA_IObject::Resume();
837                 GetPhysicsController()->RestoreDynamics();
838
839                 m_suspended = false;
840         }
841 }
842
843 void KX_GameObject::Suspend()
844 {
845         if ((!m_ignore_activity_culling) 
846                 && (!m_suspended))  {
847                 SCA_IObject::Suspend();
848                 GetPhysicsController()->SuspendDynamics();
849                 m_suspended = true;
850         }
851 }
852
853
854
855
856 /* ------- python stuff ---------------------------------------------------*/
857
858
859
860
861 PyMethodDef KX_GameObject::Methods[] = {
862         {"getPosition", (PyCFunction) KX_GameObject::sPyGetPosition, METH_NOARGS},
863         {"setPosition", (PyCFunction) KX_GameObject::sPySetPosition, METH_O},
864         {"getLinearVelocity", (PyCFunction) KX_GameObject::sPyGetLinearVelocity, METH_VARARGS},
865         {"setLinearVelocity", (PyCFunction) KX_GameObject::sPySetLinearVelocity, METH_VARARGS},
866         {"getVelocity", (PyCFunction) KX_GameObject::sPyGetVelocity, METH_VARARGS},
867         {"getMass", (PyCFunction) KX_GameObject::sPyGetMass, METH_NOARGS},
868         {"getReactionForce", (PyCFunction) KX_GameObject::sPyGetReactionForce, METH_NOARGS},
869         {"getOrientation", (PyCFunction) KX_GameObject::sPyGetOrientation, METH_NOARGS},
870         {"setOrientation", (PyCFunction) KX_GameObject::sPySetOrientation, METH_O},
871         {"getVisible",(PyCFunction) KX_GameObject::sPyGetVisible, METH_NOARGS},
872         {"setVisible",(PyCFunction) KX_GameObject::sPySetVisible, METH_O},
873         {"getState",(PyCFunction) KX_GameObject::sPyGetState, METH_NOARGS},
874         {"setState",(PyCFunction) KX_GameObject::sPySetState, METH_O},
875         {"alignAxisToVect",(PyCFunction) KX_GameObject::sPyAlignAxisToVect, METH_VARARGS},
876         {"getAxisVect",(PyCFunction) KX_GameObject::sPyGetAxisVect, METH_O},
877         {"suspendDynamics", (PyCFunction)KX_GameObject::sPySuspendDynamics,METH_NOARGS},
878         {"restoreDynamics", (PyCFunction)KX_GameObject::sPyRestoreDynamics,METH_NOARGS},
879         {"enableRigidBody", (PyCFunction)KX_GameObject::sPyEnableRigidBody,METH_NOARGS},
880         {"disableRigidBody", (PyCFunction)KX_GameObject::sPyDisableRigidBody,METH_NOARGS},
881         {"applyImpulse", (PyCFunction) KX_GameObject::sPyApplyImpulse, METH_VARARGS},
882         {"setCollisionMargin", (PyCFunction) KX_GameObject::sPySetCollisionMargin, METH_O},
883         {"getParent", (PyCFunction)KX_GameObject::sPyGetParent,METH_NOARGS},
884         {"setParent", (PyCFunction)KX_GameObject::sPySetParent,METH_O},
885         {"removeParent", (PyCFunction)KX_GameObject::sPyRemoveParent,METH_NOARGS},
886         {"getMesh", (PyCFunction)KX_GameObject::sPyGetMesh,METH_VARARGS},
887         {"getPhysicsId", (PyCFunction)KX_GameObject::sPyGetPhysicsId,METH_NOARGS},
888         {"getPropertyNames", (PyCFunction)KX_GameObject::sPyGetPropertyNames,METH_NOARGS},
889         {"endObject",(PyCFunction) KX_GameObject::sPyEndObject, METH_NOARGS},
890         KX_PYMETHODTABLE(KX_GameObject, rayCastTo),
891         KX_PYMETHODTABLE(KX_GameObject, rayCast),
892         KX_PYMETHODTABLE(KX_GameObject, getDistanceTo),
893         {NULL,NULL} //Sentinel
894 };
895
896
897
898 /*
899 bool KX_GameObject::ConvertPythonVectorArgs(PyObject* args,
900                                                                                         MT_Vector3& pos,
901                                                                                         MT_Vector3& pos2)
902 {
903         PyObject* pylist;
904         PyObject* pylist2;
905         bool error = (PyArg_ParseTuple(args,"OO",&pylist,&pylist2)) != 0;
906
907         pos = ConvertPythonPylist(pylist);
908         pos2 = ConvertPythonPylist(pylist2);
909                 
910         return error;
911 }
912 */
913
914 PyObject* KX_GameObject::PyEndObject(PyObject* self)
915 {
916
917         KX_Scene *scene = PHY_GetActiveScene();
918         scene->DelayedRemoveObject(this);
919         
920         return Py_None;
921
922 }
923
924
925 PyObject* KX_GameObject::PyGetPosition(PyObject* self)
926 {
927         return PyObjectFrom(NodeGetWorldPosition());
928 }
929
930
931
932 PyTypeObject KX_GameObject::Type = {
933         PyObject_HEAD_INIT(&PyType_Type)
934                 0,
935                 "KX_GameObject",
936                 sizeof(KX_GameObject),
937                 0,
938                 PyDestructor,
939                 0,
940                 __getattr,
941                 __setattr,
942                 0, //&MyPyCompare,
943                 __repr,
944                 0, //&cvalue_as_number,
945                 0,
946                 0,
947                 0,
948                 0
949 };
950
951
952
953 PyParentObject KX_GameObject::Parents[] = {
954         &KX_GameObject::Type,
955                 &SCA_IObject::Type,
956                 &CValue::Type,
957                 NULL
958 };
959
960
961
962
963 PyObject* KX_GameObject::_getattr(const STR_String& attr)
964 {
965         if (m_pPhysicsController1)
966         {
967                 if (attr == "mass")
968                         return PyFloat_FromDouble(GetPhysicsController()->GetMass());
969         }
970
971         if (attr == "parent")
972         {       
973                 KX_GameObject* parent = GetParent();
974                 if (parent)
975                 {
976                         parent->AddRef();
977                         return parent;
978                 }
979                 Py_RETURN_NONE;
980         }
981
982         if (attr == "visible")
983                 return PyInt_FromLong(m_bVisible);
984         
985         if (attr == "position")
986                 return PyObjectFrom(NodeGetWorldPosition());
987         
988         if (attr == "orientation")
989                 return PyObjectFrom(NodeGetWorldOrientation());
990         
991         if (attr == "scaling")
992                 return PyObjectFrom(NodeGetWorldScaling());
993                 
994         if (attr == "name")
995                 return PyString_FromString(m_name.ReadPtr());
996         if (attr == "timeOffset") {
997                 if (m_pSGNode->GetSGParent()->IsSlowParent()) {
998                         return PyFloat_FromDouble(static_cast<KX_SlowParentRelation *>(m_pSGNode->GetSGParent()->GetParentRelation())->GetTimeOffset());
999                 } else {
1000                         return PyFloat_FromDouble(0.0);
1001                 }
1002         }
1003         
1004         
1005         _getattr_up(SCA_IObject);
1006 }
1007
1008 int KX_GameObject::_setattr(const STR_String& attr, PyObject *value)    // _setattr method
1009 {
1010         if (attr == "mass")
1011                 return 1;
1012         
1013         if (attr == "parent")
1014                 return 1;
1015                 
1016         if (PyInt_Check(value))
1017         {
1018                 int val = PyInt_AsLong(value);
1019                 if (attr == "visible")
1020                 {
1021                         SetVisible(val != 0);
1022                         return 0;
1023                 }
1024         }
1025
1026         if (PyFloat_Check(value))
1027         {
1028                 MT_Scalar val = PyFloat_AsDouble(value);
1029                 if (attr == "timeOffset") {
1030                         if (m_pSGNode->GetSGParent() && m_pSGNode->GetSGParent()->IsSlowParent()) {
1031                                 static_cast<KX_SlowParentRelation *>(m_pSGNode->GetSGParent()->GetParentRelation())->SetTimeOffset(val);
1032                                 return 0;
1033                         } else {
1034                                 return 0;
1035                         }               
1036                 }
1037         }
1038         
1039         if (PySequence_Check(value))
1040         {
1041                 if (attr == "orientation")
1042                 {
1043                         MT_Matrix3x3 rot;
1044                         if (PyObject_IsMT_Matrix(value, 3))
1045                         {
1046                                 if (PyMatTo(value, rot))
1047                                 {
1048                                         NodeSetLocalOrientation(rot);
1049                                         NodeUpdateGS(0.f,true);
1050                                         return 0;
1051                                 }
1052                                 return 1;
1053                         }
1054                         
1055                         if (PySequence_Size(value) == 4)
1056                         {
1057                                 MT_Quaternion qrot;
1058                                 if (PyVecTo(value, qrot))
1059                                 {
1060                                         rot.setRotation(qrot);
1061                                         NodeSetLocalOrientation(rot);
1062                                         NodeUpdateGS(0.f,true);
1063                                         return 0;
1064                                 }
1065                                 return 1;
1066                         }
1067                         
1068                         if (PySequence_Size(value) == 3)
1069                         {
1070                                 MT_Vector3 erot;
1071                                 if (PyVecTo(value, erot))
1072                                 {
1073                                         rot.setEuler(erot);
1074                                         NodeSetLocalOrientation(rot);
1075                                         NodeUpdateGS(0.f,true);
1076                                         return 0;
1077                                 }
1078                                 return 1;
1079                         }
1080                         
1081                         return 1;
1082                 }
1083                 
1084                 if (attr == "position")
1085                 {
1086                         MT_Point3 pos;
1087                         if (PyVecTo(value, pos))
1088                         {
1089                                 NodeSetLocalPosition(pos);
1090                                 NodeUpdateGS(0.f,true);
1091                                 return 0;
1092                         }
1093                         return 1;
1094                 }
1095                 
1096                 if (attr == "scaling")
1097                 {
1098                         MT_Vector3 scale;
1099                         if (PyVecTo(value, scale))
1100                         {
1101                                 NodeSetLocalScale(scale);
1102                                 NodeUpdateGS(0.f,true);
1103                                 return 0;
1104                         }
1105                         return 1;
1106                 }
1107         }
1108         
1109         if (PyString_Check(value))
1110         {
1111                 if (attr == "name")
1112                 {
1113                         m_name = PyString_AsString(value);
1114                         return 0;
1115                 }
1116         }
1117         
1118         /* Need to have parent settable here too */
1119         
1120         return SCA_IObject::_setattr(attr, value);
1121 }
1122
1123
1124 PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* self, 
1125                                                                                          PyObject* args, 
1126                                                                                          PyObject* kwds)
1127 {
1128         // only can get the velocity if we have a physics object connected to us...
1129         int local = 0;
1130         if (PyArg_ParseTuple(args,"|i",&local))
1131         {
1132                 return PyObjectFrom(GetLinearVelocity((local!=0)));
1133         }
1134         else
1135         {
1136                 return NULL;
1137         }
1138 }
1139
1140 PyObject* KX_GameObject::PySetLinearVelocity(PyObject* self, 
1141                                                                                          PyObject* args, 
1142                                                                                          PyObject* kwds)
1143 {
1144         int local = 0;
1145         PyObject* pyvect;
1146         
1147         if (PyArg_ParseTuple(args,"O|i",&pyvect,&local)) {
1148                 MT_Vector3 velocity;
1149                 if (PyVecTo(pyvect, velocity)) {
1150                         setLinearVelocity(velocity, (local!=0));
1151                         Py_RETURN_NONE;
1152                 }
1153         }
1154         return NULL;
1155 }
1156
1157 PyObject* KX_GameObject::PySetVisible(PyObject* self, PyObject* value)
1158 {
1159         int visible = PyInt_AsLong(value);
1160         
1161         if (visible==-1 && PyErr_Occurred()) {
1162                 PyErr_SetString(PyExc_TypeError, "expected 0 or 1");
1163                 return NULL;
1164         }
1165         
1166         MarkVisible(visible!=0);
1167         m_bVisible = (visible!=0);
1168         Py_RETURN_NONE;
1169         
1170 }
1171
1172 PyObject* KX_GameObject::PyGetVisible(PyObject* self)
1173 {
1174         return PyInt_FromLong(m_bVisible);      
1175 }
1176
1177 PyObject* KX_GameObject::PyGetState(PyObject* self)
1178 {
1179         int state = 0;
1180         state |= GetState();
1181         return PyInt_FromLong(state);
1182 }
1183
1184 PyObject* KX_GameObject::PySetState(PyObject* self, PyObject* value)
1185 {
1186         int state_i = PyInt_AsLong(value);
1187         unsigned int state = 0;
1188         
1189         if (state_i == -1 && PyErr_Occurred()) {
1190                 PyErr_SetString(PyExc_TypeError, "expected an int bit field");
1191                 return NULL;
1192         }
1193         
1194         state |= state_i;
1195         if ((state & ((1<<30)-1)) == 0) {
1196                 PyErr_SetString(PyExc_AttributeError, "The state bitfield was not between 0 and 30 (1<<0 and 1<<29)");
1197                 return NULL;
1198         }
1199         SetState(state);
1200         
1201         Py_RETURN_NONE;
1202 }
1203
1204
1205
1206 PyObject* KX_GameObject::PyGetVelocity(PyObject* self, 
1207                                                                            PyObject* args, 
1208                                                                            PyObject* kwds)
1209 {
1210         // only can get the velocity if we have a physics object connected to us...
1211         MT_Vector3 velocity(0.0,0.0,0.0);
1212         MT_Point3 point(0.0,0.0,0.0);
1213         
1214         
1215         PyObject* pypos = NULL;
1216         if (PyArg_ParseTuple(args, "|O", &pypos))
1217         {
1218                 if (pypos)
1219                         PyVecTo(pypos, point);
1220         }
1221         else {
1222                 return NULL;
1223         }
1224         
1225         if (m_pPhysicsController1)
1226         {
1227                 velocity = m_pPhysicsController1->GetVelocity(point);
1228         }
1229         
1230         return PyObjectFrom(velocity);
1231 }
1232
1233
1234
1235 PyObject* KX_GameObject::PyGetMass(PyObject* self)
1236 {
1237         return PyFloat_FromDouble(GetPhysicsController()->GetMass());
1238 }
1239
1240
1241
1242 PyObject* KX_GameObject::PyGetReactionForce(PyObject* self)
1243 {
1244         // only can get the velocity if we have a physics object connected to us...
1245         return PyObjectFrom(GetPhysicsController()->getReactionForce());
1246 }
1247
1248
1249
1250 PyObject* KX_GameObject::PyEnableRigidBody(PyObject* self)
1251 {
1252         GetPhysicsController()->setRigidBody(true);
1253
1254         Py_RETURN_NONE;
1255 }
1256
1257
1258
1259 PyObject* KX_GameObject::PyDisableRigidBody(PyObject* self)
1260 {
1261         GetPhysicsController()->setRigidBody(false);
1262
1263         Py_RETURN_NONE;
1264 }
1265
1266
1267
1268 PyObject* KX_GameObject::PyGetParent(PyObject* self)
1269 {
1270         KX_GameObject* parent = this->GetParent();
1271         if (parent)
1272         {
1273                 parent->AddRef();
1274                 return parent;
1275         }
1276         Py_RETURN_NONE;
1277 }
1278
1279 PyObject* KX_GameObject::PySetParent(PyObject* self, PyObject* value)
1280 {
1281         if (!PyObject_TypeCheck(value, &KX_GameObject::Type)) {
1282                 PyErr_SetString(PyExc_TypeError, "expected a KX_GameObject type");
1283                 return NULL;
1284         }
1285         
1286         // The object we want to set as parent
1287         CValue *m_ob = (CValue*)value;
1288         KX_GameObject *obj = ((KX_GameObject*)m_ob);
1289         KX_Scene *scene = PHY_GetActiveScene();
1290         
1291         this->SetParent(scene, obj);
1292                 
1293         Py_RETURN_NONE;
1294 }
1295
1296 PyObject* KX_GameObject::PyRemoveParent(PyObject* self)
1297 {
1298         KX_Scene *scene = PHY_GetActiveScene();
1299         this->RemoveParent(scene);
1300         Py_RETURN_NONE;
1301 }
1302
1303 PyObject* KX_GameObject::PyGetMesh(PyObject* self, 
1304                                                                    PyObject* args, 
1305                                                                    PyObject* kwds)
1306 {
1307         int mesh = 0;
1308
1309         if (PyArg_ParseTuple(args, "|i", &mesh))
1310         {
1311                 if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0)
1312                 {
1313                         KX_MeshProxy* meshproxy = new KX_MeshProxy(m_meshes[mesh]);
1314                         return meshproxy;
1315                 }
1316         }
1317         Py_RETURN_NONE;
1318 }
1319
1320
1321
1322
1323
1324 PyObject* KX_GameObject::PySetCollisionMargin(PyObject* self, PyObject* value)
1325 {
1326         float collisionMargin = PyFloat_AsDouble(value);
1327         
1328         if (collisionMargin==-1 && PyErr_Occurred()) {
1329                 PyErr_SetString(PyExc_TypeError, "expected a float");
1330                 return NULL;
1331         }
1332         
1333         if (m_pPhysicsController1)
1334         {
1335                 m_pPhysicsController1->setMargin(collisionMargin);
1336                 Py_RETURN_NONE;
1337         }
1338         PyErr_SetString(PyExc_RuntimeError, "This object has no physics controller");
1339         return NULL;
1340 }
1341
1342
1343
1344 PyObject* KX_GameObject::PyApplyImpulse(PyObject* self, 
1345                                                                                 PyObject* args, 
1346                                                                                 PyObject* kwds)
1347 {
1348         PyObject* pyattach;
1349         PyObject* pyimpulse;
1350         
1351         if (!m_pPhysicsController1)     {
1352                 PyErr_SetString(PyExc_RuntimeError, "This object has no physics controller");
1353                 return NULL;
1354         }
1355         
1356         if (PyArg_ParseTuple(args, "OO", &pyattach, &pyimpulse))
1357         {
1358                 MT_Point3  attach;
1359                 MT_Vector3 impulse;
1360                 if (PyVecTo(pyattach, attach) && PyVecTo(pyimpulse, impulse))
1361                 {
1362                         m_pPhysicsController1->applyImpulse(attach, impulse);
1363                         Py_RETURN_NONE;
1364                 }
1365
1366         }
1367         
1368         return NULL;
1369 }
1370
1371
1372
1373 PyObject* KX_GameObject::PySuspendDynamics(PyObject* self)
1374 {
1375         SuspendDynamics();
1376         Py_RETURN_NONE;
1377 }
1378
1379
1380
1381 PyObject* KX_GameObject::PyRestoreDynamics(PyObject* self)
1382 {
1383         RestoreDynamics();
1384         Py_RETURN_NONE;
1385 }
1386
1387
1388
1389 PyObject* KX_GameObject::PyGetOrientation(PyObject* self) //keywords
1390 {
1391         return PyObjectFrom(NodeGetWorldOrientation());
1392 }
1393
1394
1395
1396 PyObject* KX_GameObject::PySetOrientation(PyObject* self, PyObject* value)
1397 {
1398         MT_Matrix3x3 matrix;
1399         if (PyObject_IsMT_Matrix(value, 3) && PyMatTo(value, matrix))
1400         {
1401                 NodeSetLocalOrientation(matrix);
1402                 NodeUpdateGS(0.f,true);
1403                 Py_RETURN_NONE;
1404         }
1405
1406         MT_Quaternion quat;
1407         if (PyVecTo(value, quat))
1408         {
1409                 matrix.setRotation(quat);
1410                 NodeSetLocalOrientation(matrix);
1411                 NodeUpdateGS(0.f,true);
1412                 Py_RETURN_NONE;
1413         }
1414         return NULL;
1415 }
1416
1417 PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* self, 
1418                                                                                   PyObject* args, 
1419                                                                                   PyObject* kwds)
1420 {
1421         PyObject* pyvect;
1422         int axis = 2; //z axis is the default
1423         float fac = 1.0;
1424         
1425         if (PyArg_ParseTuple(args,"O|if",&pyvect,&axis, &fac))
1426         {
1427                 MT_Vector3 vect;
1428                 if (PyVecTo(pyvect, vect))
1429                 {
1430                         AlignAxisToVect(vect,axis,fac);
1431                         Py_RETURN_NONE;
1432                 }
1433         }
1434         return NULL;
1435 }
1436
1437 PyObject* KX_GameObject::PyGetAxisVect(PyObject* self, PyObject* value)
1438 {
1439         MT_Vector3 vect;
1440         if (PyVecTo(value, vect))
1441         {
1442                 return PyObjectFrom(NodeGetWorldOrientation() * vect);
1443         }
1444         return NULL;
1445 }
1446
1447 PyObject* KX_GameObject::PySetPosition(PyObject* self, PyObject* value)
1448 {
1449         MT_Point3 pos;
1450         if (PyVecTo(value, pos))
1451         {
1452                 NodeSetLocalPosition(pos);
1453                 NodeUpdateGS(0.f,true);
1454                 Py_RETURN_NONE;
1455         }
1456
1457         return NULL;
1458 }
1459
1460 PyObject* KX_GameObject::PyGetPhysicsId(PyObject* self)
1461 {
1462         KX_IPhysicsController* ctrl = GetPhysicsController();
1463         uint_ptr physid=0;
1464         if (ctrl)
1465         {
1466                 physid= (uint_ptr)ctrl->GetUserData();
1467         }
1468         return PyInt_FromLong((long)physid);
1469 }
1470
1471 PyObject* KX_GameObject::PyGetPropertyNames(PyObject* self)
1472 {
1473         return ConvertKeysToPython();
1474 }
1475
1476 KX_PYMETHODDEF_DOC(KX_GameObject, getDistanceTo,
1477 "getDistanceTo(other): get distance to another point/KX_GameObject")
1478 {
1479         MT_Point3 b;
1480         if (PyVecArgTo(args, b))
1481         {
1482                 return PyFloat_FromDouble(NodeGetWorldPosition().distance(b));
1483         }
1484         PyErr_Clear();
1485         
1486         PyObject *pyother;
1487         if (PyArg_ParseTuple(args, "O!", &KX_GameObject::Type, &pyother))
1488         {
1489                 KX_GameObject *other = static_cast<KX_GameObject*>(pyother);
1490                 return PyFloat_FromDouble(NodeGetWorldPosition().distance(other->NodeGetWorldPosition()));
1491         }
1492         
1493         return NULL;
1494 }
1495
1496 bool KX_GameObject::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data)
1497 {
1498
1499         KX_GameObject* hitKXObj = client->m_gameobject;
1500         
1501         if (client->m_type > KX_ClientObjectInfo::ACTOR)
1502         {
1503                 // false hit
1504                 return false;
1505         }
1506
1507         if (m_testPropName.Length() == 0 || hitKXObj->GetProperty(m_testPropName) != NULL)
1508         {
1509                 m_pHitObject = hitKXObj;
1510                 return true;
1511         }
1512
1513         return false;
1514         
1515 }
1516
1517 KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo,
1518 "rayCastTo(other,dist,prop): look towards another point/KX_GameObject and return first object hit within dist that matches prop\n"
1519 " prop = property name that object must have; can be omitted => detect any object\n"
1520 " dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to other\n"
1521 " other = 3-tuple or object reference")
1522 {
1523         MT_Point3 toPoint;
1524         PyObject* pyarg;
1525         float dist = 0.0f;
1526         char *propName = NULL;
1527
1528         if (!PyArg_ParseTuple(args,"O|fs", &pyarg, &dist, &propName))
1529                 return NULL;
1530
1531         if (!PyVecTo(pyarg, toPoint))
1532         {
1533                 KX_GameObject *other;
1534                 PyErr_Clear();
1535                 if (!PyType_IsSubtype(pyarg->ob_type, &KX_GameObject::Type)) {
1536                         PyErr_SetString(PyExc_TypeError, "the first argument to rayCastTo must be a vector or a KX_GameObject");
1537                         return NULL;
1538                 }
1539                 other = static_cast<KX_GameObject*>(pyarg);
1540                 toPoint = other->NodeGetWorldPosition();
1541         }
1542         MT_Point3 fromPoint = NodeGetWorldPosition();
1543         if (dist != 0.0f)
1544         {
1545                 MT_Vector3 toDir = toPoint-fromPoint;
1546                 toDir.normalize();
1547                 toPoint = fromPoint + (dist) * toDir;
1548         }
1549
1550         MT_Point3 resultPoint;
1551         MT_Vector3 resultNormal;
1552         PHY_IPhysicsEnvironment* pe = GetPhysicsEnvironment();
1553         KX_IPhysicsController *spc = GetPhysicsController();
1554         KX_GameObject *parent = GetParent();
1555         if (!spc && parent)
1556                 spc = parent->GetPhysicsController();
1557         if (parent)
1558                 parent->Release();
1559         
1560         m_pHitObject = NULL;
1561         if (propName)
1562                 m_testPropName = propName;
1563         else
1564                 m_testPropName.SetLength(0);
1565         KX_RayCast::RayTest(spc, pe, fromPoint, toPoint, resultPoint, resultNormal, KX_RayCast::Callback<KX_GameObject>(this));
1566
1567     if (m_pHitObject)
1568         {
1569                 m_pHitObject->AddRef();
1570                 return m_pHitObject;
1571         }
1572         Py_RETURN_NONE;
1573 }
1574
1575 KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
1576 "rayCast(to,from,dist,prop): cast a ray and return tuple (object,hit,normal) of contact point with object within dist that matches prop or None if no hit\n"
1577 " prop = property name that object must have; can be omitted => detect any object\n"
1578 " dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to to\n"
1579 " from = 3-tuple or object reference for origin of ray (if object, use center of object)\n"
1580 "        Can None or omitted => start from self object center\n"
1581 " to = 3-tuple or object reference for destination of ray (if object, use center of object)\n"
1582 "Note: the object on which you call this method matters: the ray will ignore it if it goes through it\n")
1583 {
1584         MT_Point3 toPoint;
1585         MT_Point3 fromPoint;
1586         PyObject* pyto;
1587         PyObject* pyfrom = NULL;
1588         float dist = 0.0f;
1589         char *propName = NULL;
1590         KX_GameObject *other;
1591
1592         if (!PyArg_ParseTuple(args,"O|Ofs", &pyto, &pyfrom, &dist, &propName))
1593                 return NULL;
1594
1595         if (!PyVecTo(pyto, toPoint))
1596         {
1597                 PyErr_Clear();
1598                 if (!PyType_IsSubtype(pyto->ob_type, &KX_GameObject::Type)) {
1599                         PyErr_SetString(PyExc_TypeError, "the first argument to rayCast must be a vector or a KX_GameObject");
1600                         return NULL;
1601                 }
1602                 other = static_cast<KX_GameObject*>(pyto);
1603                 toPoint = other->NodeGetWorldPosition();
1604         }
1605         if (!pyfrom || pyfrom == Py_None)
1606         {
1607                 fromPoint = NodeGetWorldPosition();
1608         }
1609         else if (!PyVecTo(pyfrom, fromPoint))
1610         {
1611                 PyErr_Clear();
1612                 if (!PyType_IsSubtype(pyfrom->ob_type, &KX_GameObject::Type)) {
1613                         PyErr_SetString(PyExc_TypeError, "the second optional argument to rayCast must be a vector or a KX_GameObject");
1614                         return NULL;
1615                 }
1616                 other = static_cast<KX_GameObject*>(pyfrom);
1617                 fromPoint = other->NodeGetWorldPosition();
1618         }
1619         
1620         if (dist != 0.0f) {
1621                 MT_Vector3 toDir = toPoint-fromPoint;
1622                 if (MT_fuzzyZero(toDir.length2())) {
1623                         return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
1624                 }
1625                 toDir.normalize();
1626                 toPoint = fromPoint + (dist) * toDir;
1627         } else if (MT_fuzzyZero((toPoint-fromPoint).length2())) {
1628                 return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
1629         }
1630         
1631         MT_Point3 resultPoint;
1632         MT_Vector3 resultNormal;
1633         PHY_IPhysicsEnvironment* pe = GetPhysicsEnvironment();
1634         KX_IPhysicsController *spc = GetPhysicsController();
1635         KX_GameObject *parent = GetParent();
1636         if (!spc && parent)
1637                 spc = parent->GetPhysicsController();
1638         if (parent)
1639                 parent->Release();
1640         
1641         m_pHitObject = NULL;
1642         if (propName)
1643                 m_testPropName = propName;
1644         else
1645                 m_testPropName.SetLength(0);
1646         KX_RayCast::RayTest(spc, pe, fromPoint, toPoint, resultPoint, resultNormal, KX_RayCast::Callback<KX_GameObject>(this));
1647
1648     if (m_pHitObject)
1649         {
1650                 PyObject* returnValue = PyTuple_New(3);
1651                 if (!returnValue)
1652                         return NULL;
1653                 PyTuple_SET_ITEM(returnValue, 0, m_pHitObject->AddRef());
1654                 PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(resultPoint));
1655                 PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(resultNormal));
1656                 return returnValue;
1657                 //return Py_BuildValue("(O,(fff),(fff))", 
1658                 //      m_pHitObject->AddRef(),         // trick: KX_GameObject are not true Python object, they use a difference reference count system
1659                 //      resultPoint[0], resultPoint[1], resultPoint[2],
1660                 //      resultNormal[0], resultNormal[1], resultNormal[2]);
1661         }
1662         return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
1663         //Py_RETURN_NONE;
1664 }
1665
1666 /* --------------------------------------------------------------------- 
1667  * Some stuff taken from the header
1668  * --------------------------------------------------------------------- */
1669 void KX_GameObject::Relink(GEN_Map<GEN_HashedPtr, void*> *map_parameter)        
1670 {
1671         /* intentionally empty ? */
1672 }
1673