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