Added resolveCombinedVelocities()
[blender.git] / source / gameengine / Ketsji / KX_GameObject.cpp
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL 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. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  * Game object wrapper
32  */
33
34 #ifdef HAVE_CONFIG_H
35 #include <config.h>
36 #endif
37
38 #ifdef WIN32
39 // This warning tells us about truncation of __long__ stl-generated names.
40 // It can occasionally cause DevStudio to have internal compiler warnings.
41 #pragma warning( disable : 4786 )     
42 #endif
43
44
45 #define KX_INERTIA_INFINITE 10000
46 #include "RAS_IPolygonMaterial.h"
47 #include "KX_GameObject.h"
48 #include "RAS_MeshObject.h"
49 #include "KX_MeshProxy.h"
50 #include <stdio.h> // printf
51 #include "SG_Controller.h"
52 #include "KX_IPhysicsController.h"
53 #include "SG_Node.h"
54 #include "SG_Controller.h"
55 #include "KX_ClientObjectInfo.h"
56 #include "RAS_BucketManager.h"
57
58 // This file defines relationships between parents and children
59 // in the game engine.
60
61 #include "KX_SG_NodeRelationships.h"
62
63 KX_GameObject::KX_GameObject(
64         void* sgReplicationInfo,
65         SG_Callbacks callbacks,
66         PyTypeObject* T
67 ) : 
68         SCA_IObject(T),
69         m_bDyna(false),
70         m_bSuspendDynamics(false),
71         m_bUseObjectColor(false),
72         m_bVisible(true),
73         m_pPhysicsController1(NULL)
74 {
75         m_ignore_activity_culling = false;
76         m_pClient_info = new KX_ClientObjectInfo(this);
77         m_pClient_info->m_type = KX_ClientObjectInfo::ACTOR;
78         m_pSGNode = new SG_Node(this,sgReplicationInfo,callbacks);
79         
80         // define the relationship between this node and it's parent.
81
82         KX_NormalParentRelation * parent_relation = 
83                 KX_NormalParentRelation::New();
84         m_pSGNode->SetParentRelation(parent_relation);
85
86
87 };
88
89
90
91 KX_GameObject::~KX_GameObject()
92 {
93         // is this delete somewhere ?
94         //if (m_sumoObj)
95         //      delete m_sumoObj;
96         delete m_pClient_info;
97         //if (m_pSGNode)
98         //      delete m_pSGNode;
99         
100 }
101
102
103
104 CValue* KX_GameObject:: Calc(VALUE_OPERATOR op, CValue *val) 
105 {
106         return NULL;
107 }
108
109
110
111 CValue* KX_GameObject::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val)
112 {
113         return NULL;
114 }
115
116
117
118 const STR_String & KX_GameObject::GetText()
119 {
120         return m_text;
121 }
122
123
124
125 float KX_GameObject::GetNumber()
126 {
127         return 0;
128 }
129
130
131
132 STR_String KX_GameObject::GetName()
133 {
134         return m_name;
135 }
136
137
138
139 void KX_GameObject::SetName(STR_String name)
140 {
141         m_name = name;
142 };                                                              // Set the name of the value
143
144
145
146 void KX_GameObject::ReplicaSetName(STR_String name)
147 {
148 }
149
150
151
152
153
154
155 KX_IPhysicsController* KX_GameObject::GetPhysicsController()
156 {
157         return m_pPhysicsController1;
158 }
159
160
161
162
163
164 KX_GameObject* KX_GameObject::GetParent()
165 {
166         KX_GameObject* result = NULL;
167         SG_Node* node = m_pSGNode;
168         
169         while (node && !result)
170         {
171                 node = node->GetSGParent();
172                 if (node)
173                         result = (KX_GameObject*)node->GetSGClientObject();
174         }
175         
176         if (result)
177                 result->AddRef();
178
179         return result;
180         
181 }
182
183
184
185 void KX_GameObject::ProcessReplica(KX_GameObject* replica)
186 {
187         replica->m_pPhysicsController1 = NULL;
188         replica->m_pSGNode = NULL;
189         replica->m_pClient_info = new KX_ClientObjectInfo(*m_pClient_info);
190         replica->m_pClient_info->m_clientobject = replica;
191 }
192
193
194
195 CValue* KX_GameObject::GetReplica()
196 {
197         KX_GameObject* replica = new KX_GameObject(*this);
198         
199         // this will copy properties and so on...
200         CValue::AddDataToReplica(replica);
201         ProcessReplica(replica);
202         
203         return replica;
204 }
205
206
207
208 void KX_GameObject::ApplyForce(const MT_Vector3& force,bool local)
209 {
210         if (m_pPhysicsController1)
211                 m_pPhysicsController1->ApplyForce(force,local);
212 }
213
214
215
216 void KX_GameObject::ApplyTorque(const MT_Vector3& torque,bool local)
217 {
218         if (m_pPhysicsController1)
219                 m_pPhysicsController1->ApplyTorque(torque,local);
220 }
221
222
223
224 void KX_GameObject::ApplyMovement(const MT_Vector3& dloc,bool local)
225 {
226         if (m_pPhysicsController1) // (IsDynamic())
227         {
228                 m_pPhysicsController1->RelativeTranslate(dloc,local);
229         }
230         GetSGNode()->RelativeTranslate(dloc,GetSGNode()->GetSGParent(),local);
231 }
232
233
234
235 void KX_GameObject::ApplyRotation(const MT_Vector3& drot,bool local)
236 {
237         MT_Matrix3x3 rotmat(drot);
238         rotmat.transpose();
239         
240         if (m_pPhysicsController1) // (IsDynamic())
241                 m_pPhysicsController1->RelativeRotate(rotmat,local); 
242         // in worldspace
243         GetSGNode()->RelativeRotate(rotmat,local);
244 }
245
246
247
248 /**
249 GetOpenGL Matrix, returns an OpenGL 'compatible' matrix
250 */
251 double* KX_GameObject::GetOpenGLMatrix()
252 {
253         // todo: optimize and only update if necessary
254         double* fl = m_OpenGL_4x4Matrix.getPointer();
255         MT_Transform trans;
256         
257         trans.setOrigin(GetSGNode()->GetWorldPosition());
258         trans.setBasis(GetSGNode()->GetWorldOrientation());
259         
260         MT_Vector3 scaling = GetSGNode()->GetWorldScaling();
261         
262         trans.scale(scaling[0], scaling[1], scaling[2]);
263         trans.getValue(fl);
264
265         return fl;
266 }
267
268
269
270 void KX_GameObject::Bucketize()
271 {
272         double* fl = GetOpenGLMatrix();
273
274         for (size_t i=0;i<m_meshes.size();i++)
275                 m_meshes[i]->Bucketize(fl, this, m_bUseObjectColor, m_objectColor);
276 }
277
278
279
280 void KX_GameObject::RemoveMeshes()
281 {
282         double* fl = GetOpenGLMatrix();
283
284         for (size_t i=0;i<m_meshes.size();i++)
285                 m_meshes[i]->RemoveFromBuckets(fl, this);
286
287         //note: meshes can be shared, and are deleted by KX_BlenderSceneConverter
288
289         m_meshes.clear();
290 }
291
292
293
294 void KX_GameObject::UpdateNonDynas()
295 {
296         if (m_pPhysicsController1)
297         {
298                 m_pPhysicsController1->SetSumoTransform(true);
299         }
300 }
301
302
303
304 void KX_GameObject::UpdateTransform()
305 {
306         if (m_pPhysicsController1)
307         {
308                 m_pPhysicsController1->SetSumoTransform(false);
309         }
310 }
311
312
313
314 void KX_GameObject::SetDebugColor(unsigned int bgra)
315 {
316         for (size_t i=0;i<m_meshes.size();i++)
317                 m_meshes[i]->DebugColor(bgra);  
318 }
319
320
321
322 void KX_GameObject::ResetDebugColor()
323 {
324         SetDebugColor(0xff000000);
325 }
326
327
328
329 void KX_GameObject::UpdateIPO(float curframetime,
330                                                           bool recurse,
331                                                           bool ipo_as_force,
332                                                           bool force_local) 
333 {
334
335         // The ipo-actuator needs a sumo reference... this is retrieved (unfortunately)
336         // by the iposgcontr itself...
337 //              ipocontr->SetSumoReference(gameobj->GetSumoScene(), 
338 //                                                                 gameobj->GetSumoObject());
339
340
341         // The ipo has to be treated as a force, and not a displacement!
342         // For this case, we send some settings to the controller. This
343         // may need some caching...
344         if (ipo_as_force) {
345                 SGControllerList::iterator it = GetSGNode()->GetSGControllerList().begin();
346
347                 while (it != GetSGNode()->GetSGControllerList().end()) {
348                         (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_AS_FORCE, ipo_as_force);
349                         (*it)->SetOption(SG_Controller::SG_CONTR_IPO_FORCES_ACT_LOCAL, force_local);
350                         it++;
351                 }
352         } 
353
354         // The rest is the 'normal' update procedure.
355         GetSGNode()->SetSimulatedTime(curframetime,recurse);
356         GetSGNode()->UpdateWorldData(curframetime);
357         UpdateTransform();
358 }
359
360
361 /*
362 void KX_GameObject::RegisterSumoObject(class SM_Scene* sumoScene,
363                                                                            DT_SceneHandle solidscene,
364                                                                            class SM_Object* sumoObj,
365                                                                            const char* matname,
366                                                                            bool isDynamic,
367                                                                            bool isActor)
368 {
369         m_bDyna = isDynamic;
370
371         // need easy access, not via 'node' etc.
372         m_pPhysicsController = new KX_PhysicsController(sumoScene,solidscene,sumoObj,isDynamic);
373                                 
374         GetSGNode()->AddSGController(m_pPhysicsController);
375         
376         m_pClient_info->m_type = (isActor ? 1 : 0);
377         m_pClient_info->m_clientobject = this;
378
379         // store materialname in auxinfo, needed for touchsensors
380         m_pClient_info->m_auxilary_info = (matname? (void*)(matname+2) : NULL);
381         m_pPhysicsController->SetObject(this->GetSGNode());
382 }
383 */
384
385 bool
386 KX_GameObject::GetVisible(
387         void
388         )
389 {
390         return m_bVisible;
391 }
392
393 void
394 KX_GameObject::SetVisible(
395         bool v
396         )
397 {
398         m_bVisible = v;
399 }
400
401 // used by Python, and the actuatorshould _not_ be misused by the
402 // scene!
403 void 
404 KX_GameObject::MarkVisible(
405         bool visible
406         )
407 {
408         /* If explicit visibility settings are used, this is
409          * determined on this level. Maybe change this to mesh level
410          * later on? */
411         
412         double* fl = GetOpenGLMatrix();
413         for (size_t i=0;i<m_meshes.size();i++)
414         {
415                 m_meshes[i]->MarkVisible(fl,this,visible,m_bUseObjectColor,m_objectColor);
416         }
417 }
418
419
420 // Always use the flag?
421 void 
422 KX_GameObject::MarkVisible(
423         void
424         )
425 {
426         double* fl = GetOpenGLMatrix();
427         for (size_t i=0;i<m_meshes.size();i++)
428         {
429                 m_meshes[i]->MarkVisible(fl,
430                                          this,
431                                          m_bVisible,
432                                          m_bUseObjectColor,
433                                          m_objectColor
434                         );
435         }
436 }
437
438 void KX_GameObject::addLinearVelocity(const MT_Vector3& lin_vel,bool local)
439 {
440         if (m_pPhysicsController1)
441                 m_pPhysicsController1->SetLinearVelocity(lin_vel + m_pPhysicsController1->GetLinearVelocity(),local);
442 }
443
444
445
446 void KX_GameObject::setLinearVelocity(const MT_Vector3& lin_vel,bool local)
447 {
448         if (m_pPhysicsController1)
449                 m_pPhysicsController1->SetLinearVelocity(lin_vel,local);
450 }
451
452
453
454 void KX_GameObject::setAngularVelocity(const MT_Vector3& ang_vel,bool local)
455 {
456         if (m_pPhysicsController1)
457                 m_pPhysicsController1->SetAngularVelocity(ang_vel,local);
458 }
459
460 void KX_GameObject::ResolveCombinedVelocities(
461         const MT_Vector3 & lin_vel,
462         const MT_Vector3 & ang_vel,
463         bool lin_vel_local,
464         bool ang_vel_local
465 ){
466         if (m_pPhysicsController1)
467         {
468                 m_pPhysicsController1->resolveCombinedVelocities(
469                         lin_vel_local ? NodeGetWorldOrientation() * lin_vel : lin_vel,
470                         ang_vel_local ? NodeGetWorldOrientation() * ang_vel : ang_vel                   
471                 );              
472         }
473 }
474
475
476 void KX_GameObject::SetObjectColor(const MT_Vector4& rgbavec)
477 {
478         m_bUseObjectColor = true;
479         m_objectColor = rgbavec;
480 }
481
482
483
484 MT_Vector3 KX_GameObject::GetLinearVelocity()
485 {
486         MT_Vector3 velocity(0.0,0.0,0.0);
487         
488         if (m_pPhysicsController1)
489         {
490                 velocity = m_pPhysicsController1->GetLinearVelocity();
491         }
492         return velocity;
493         
494 }
495
496
497 // scenegraph node stuff
498
499 void KX_GameObject::NodeSetLocalPosition(const MT_Point3& trans)
500 {
501         if (m_pPhysicsController1)
502         {
503                 m_pPhysicsController1->setPosition(trans);
504         }
505
506         GetSGNode()->SetLocalPosition(trans);
507 }
508
509
510
511 void KX_GameObject::NodeSetLocalOrientation(const MT_Matrix3x3& rot)
512 {
513         if (m_pPhysicsController1)
514         {
515                 m_pPhysicsController1->setOrientation(rot.getRotation());
516         }
517         
518         GetSGNode()->SetLocalOrientation(rot);
519 }
520
521
522
523 void KX_GameObject::NodeSetLocalScale(const MT_Vector3& scale)
524 {
525         if (m_pPhysicsController1)
526         {
527                 m_pPhysicsController1->setScaling(scale);
528         }
529         
530         GetSGNode()->SetLocalScale(scale);
531 }
532
533
534
535 void KX_GameObject::NodeSetRelativeScale(const MT_Vector3& scale)
536 {
537         GetSGNode()->RelativeScale(scale);
538 }
539
540
541
542 void KX_GameObject::NodeUpdateGS(double time,bool bInitiator)
543 {
544         GetSGNode()->UpdateWorldData(time);
545 }
546
547
548
549 const MT_Matrix3x3& KX_GameObject::NodeGetWorldOrientation() const
550 {
551         return GetSGNode()->GetWorldOrientation();
552 }
553
554
555
556 const MT_Vector3& KX_GameObject::NodeGetWorldScaling() const
557 {
558         return GetSGNode()->GetWorldScaling();
559 }
560
561
562
563 const MT_Point3& KX_GameObject::NodeGetWorldPosition() const
564 {
565         return GetSGNode()->GetWorldPosition();
566 }
567
568 /* Suspend/ resume: for the dynamic behaviour, there is a simple
569  * method. For the residual motion, there is not. I wonder what the
570  * correct solution is for Sumo. Remove from the motion-update tree?
571  *
572  * So far, only switch the physics and logic.
573  * */
574
575 void KX_GameObject::Resume(void)
576 {
577         if (m_suspended) {
578                 SCA_IObject::Resume();
579                 GetPhysicsController()->RestoreDynamics();
580
581                 m_suspended = false;
582         }
583 }
584
585 void KX_GameObject::Suspend(void)
586 {
587         if ((!m_ignore_activity_culling) 
588                 && (!m_suspended))  {
589                 SCA_IObject::Suspend();
590                 GetPhysicsController()->SuspendDynamics();
591                 m_suspended = true;
592         }
593 }
594
595
596
597
598 /* ------- python stuff ---------------------------------------------------*/
599
600
601
602
603 PyMethodDef KX_GameObject::Methods[] = {
604         {"setVisible",(PyCFunction) KX_GameObject::sPySetVisible, METH_VARARGS},  
605         {"setPosition", (PyCFunction) KX_GameObject::sPySetPosition, METH_VARARGS},
606         {"getPosition", (PyCFunction) KX_GameObject::sPyGetPosition, METH_VARARGS},
607         {"getLinearVelocity", (PyCFunction) KX_GameObject::sPyGetLinearVelocity, METH_VARARGS},
608         {"getVelocity", (PyCFunction) KX_GameObject::sPyGetVelocity, METH_VARARGS},
609         {"getOrientation", (PyCFunction) KX_GameObject::sPyGetOrientation, METH_VARARGS},
610         {"setOrientation", (PyCFunction) KX_GameObject::sPySetOrientation, METH_VARARGS},
611         {"getMass", (PyCFunction) KX_GameObject::sPyGetMass, METH_VARARGS},
612         {"getReactionForce", (PyCFunction) KX_GameObject::sPyGetReactionForce, METH_VARARGS},
613         {"applyImpulse", (PyCFunction) KX_GameObject::sPyApplyImpulse, METH_VARARGS},
614         {"suspendDynamics", (PyCFunction)KX_GameObject::sPySuspendDynamics,METH_VARARGS},
615         {"restoreDynamics", (PyCFunction)KX_GameObject::sPyRestoreDynamics,METH_VARARGS},
616         {"enableRigidBody", (PyCFunction)KX_GameObject::sPyEnableRigidBody,METH_VARARGS},
617         {"disableRigidBody", (PyCFunction)KX_GameObject::sPyDisableRigidBody,METH_VARARGS},
618         {"getParent", (PyCFunction)KX_GameObject::sPyGetParent,METH_VARARGS},
619         {"getMesh", (PyCFunction)KX_GameObject::sPyGetMesh,METH_VARARGS},
620         {"getPhysicsId", (PyCFunction)KX_GameObject::sPyGetPhysicsId,METH_VARARGS},
621         
622         
623         {NULL,NULL} //Sentinel
624 };
625
626
627
628
629 bool KX_GameObject::ConvertPythonVectorArgs(PyObject* args,
630                                                                                         MT_Vector3& pos,
631                                                                                         MT_Vector3& pos2)
632 {
633         PyObject* pylist;
634         PyObject* pylist2;
635         bool error = (PyArg_ParseTuple(args,"OO",&pylist,&pylist2)) != 0;
636
637         pos = ConvertPythonPylist(pylist);
638         pos2 = ConvertPythonPylist(pylist2);
639                 
640         return error;
641 }
642
643
644
645 PyObject* KX_GameObject::sPySetPosition(PyObject* self,
646                                                                                 PyObject* args,
647                                                                                 PyObject* kwds)
648 {
649         return ((KX_GameObject*) self)->PySetPosition(self, args, kwds);
650 }
651         
652
653
654 PyObject* KX_GameObject::PyGetPosition(PyObject* self,
655                                                                            PyObject* args, 
656                                                                            PyObject* kwds)
657 {
658         MT_Point3 pos = NodeGetWorldPosition();
659         
660         PyObject* resultlist = PyList_New(3);
661         int index;
662         for (index=0;index<3;index++)
663         {
664                 PyList_SetItem(resultlist,index,PyFloat_FromDouble(pos[index]));
665         }
666         
667         return resultlist;
668         
669 }
670
671
672
673 PyTypeObject KX_GameObject::Type = {
674         PyObject_HEAD_INIT(&PyType_Type)
675                 0,
676                 "KX_GameObject",
677                 sizeof(KX_GameObject),
678                 0,
679                 PyDestructor,
680                 0,
681                 __getattr,
682                 __setattr,
683                 0, //&MyPyCompare,
684                 __repr,
685                 0, //&cvalue_as_number,
686                 0,
687                 0,
688                 0,
689                 0
690 };
691
692
693
694 PyParentObject KX_GameObject::Parents[] = {
695         &KX_GameObject::Type,
696                 &SCA_IObject::Type,
697                 &CValue::Type,
698                 NULL
699 };
700
701
702
703
704 PyObject* KX_GameObject::_getattr(char* attr)
705 {
706         _getattr_up(SCA_IObject);
707 }
708
709
710
711 PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* self, 
712                                                                                          PyObject* args, 
713                                                                                          PyObject* kwds)
714 {
715         // only can get the velocity if we have a physics object connected to us...
716         MT_Vector3 velocity = GetLinearVelocity();
717         
718         PyObject* resultlist = PyList_New(3);
719         int index;
720         for (index=0;index<3;index++)
721         {
722                 PyList_SetItem(resultlist,index,PyFloat_FromDouble(velocity[index]));
723         }
724
725         return resultlist;
726 }
727
728
729
730 PyObject* KX_GameObject::PySetVisible(PyObject* self,
731                                                                           PyObject* args,
732                                                                           PyObject* kwds)
733 {
734         int visible = 1;
735         
736         if (PyArg_ParseTuple(args,"i",&visible))
737         {
738                 MarkVisible(visible!=0);
739                 m_bVisible = (visible!=0);
740         }
741         else
742         {
743                 return NULL;         
744         }
745         Py_Return;
746         
747 }
748
749
750
751 PyObject* KX_GameObject::PyGetVelocity(PyObject* self, 
752                                                                            PyObject* args, 
753                                                                            PyObject* kwds)
754 {
755         // only can get the velocity if we have a physics object connected to us...
756         MT_Vector3 velocity(0.0,0.0,0.0);
757         MT_Point3 point(0.0,0.0,0.0);
758         
759         
760         MT_Point3 pos;
761         PyObject* pylist;
762         bool    error = false;
763         
764         int len = PyTuple_Size(args);
765         
766         if ((len > 0) && PyArg_ParseTuple(args,"O",&pylist))
767         {
768                 if (pylist->ob_type == &CListValue::Type)
769                 {
770                         CListValue* listval = (CListValue*) pylist;
771                         if (listval->GetCount() == 3)
772                         {
773                                 int index;
774                                 for (index=0;index<3;index++)
775                                 {
776                                         pos[index] = listval->GetValue(index)->GetNumber();
777                                 }
778                         }       else
779                         {
780                                 error = true;
781                         }
782                         
783                 } else
784                 {
785                         
786                         // assert the list is long enough...
787                         int numitems = PyList_Size(pylist);
788                         if (numitems == 3)
789                         {
790                                 int index;
791                                 for (index=0;index<3;index++)
792                                 {
793                                         pos[index] = PyFloat_AsDouble(PyList_GetItem(pylist,index));
794                                 }
795                         }
796                         else
797                         {
798                                 error = true;
799                         }
800                 }
801                 
802                 if (!error)
803                         point = pos;    
804         }
805         
806         
807         if (m_pPhysicsController1)
808         {
809                 velocity = m_pPhysicsController1->GetVelocity(point);
810         }
811         
812         PyObject* resultlist = PyList_New(3);
813         int index;
814         for (index=0;index<3;index++)
815         {
816                 PyList_SetItem(resultlist,index,PyFloat_FromDouble(velocity[index]));
817         }
818
819         return resultlist;
820 }
821
822
823
824 PyObject* KX_GameObject::PyGetMass(PyObject* self, 
825                                                                    PyObject* args, 
826                                                                    PyObject* kwds)
827 {
828         PyObject* pymass = NULL;
829         
830         float mass = GetPhysicsController()->GetMass();
831         pymass = PyFloat_FromDouble(mass);
832
833         if (pymass)
834                 return pymass;
835         
836         Py_Return;
837 }
838
839
840
841 PyObject* KX_GameObject::PyGetReactionForce(PyObject* self, 
842                                                                                         PyObject* args, 
843                                                                                         PyObject* kwds)
844 {
845         // only can get the velocity if we have a physics object connected to us...
846         
847         MT_Vector3 reaction_force = GetPhysicsController()->getReactionForce();
848         
849         PyObject* resultlist = PyList_New(3);
850         int index;
851         for (index=0;index<3;index++)
852         {
853                 PyList_SetItem(resultlist,index,
854                         PyFloat_FromDouble(reaction_force[index]));
855         }
856
857         return resultlist;
858 }
859
860
861
862 PyObject* KX_GameObject::PyEnableRigidBody(PyObject* self, 
863                                                                                    PyObject* args, 
864                                                                                    PyObject* kwds)
865 {
866         
867         GetPhysicsController()->setRigidBody(true);
868
869         Py_Return;
870 }
871
872
873
874 PyObject* KX_GameObject::PyDisableRigidBody(PyObject* self, 
875                                                                                         PyObject* args, 
876                                                                                         PyObject* kwds)
877 {
878         GetPhysicsController()->setRigidBody(false);
879
880         Py_Return;
881 }
882
883
884
885 PyObject* KX_GameObject::PyGetParent(PyObject* self, 
886                                                                          PyObject* args, 
887                                                                          PyObject* kwds)
888 {
889         KX_GameObject* parent = this->GetParent();
890         if (parent)
891                 return parent;
892         Py_Return;
893 }
894
895
896
897 PyObject* KX_GameObject::PyGetMesh(PyObject* self, 
898                                                                    PyObject* args, 
899                                                                    PyObject* kwds)
900 {
901         if (m_meshes.size() > 0)
902         {
903                 KX_MeshProxy* meshproxy = new KX_MeshProxy(m_meshes[0]);
904                 return meshproxy;
905         }
906         
907         Py_Return;
908 }
909
910
911
912 PyObject* KX_GameObject::PyApplyImpulse(PyObject* self, 
913                                                                                 PyObject* args, 
914                                                                                 PyObject* kwds)
915 {
916         
917         MT_Point3  attach(0, 1, 0);
918         MT_Vector3 impulse(1, 0, 0);
919         
920         if (ConvertPythonVectorArgs(args,attach,impulse))
921         {
922                 if (m_pPhysicsController1)
923                 {
924                         m_pPhysicsController1->applyImpulse(attach, impulse);
925                 }
926                 
927         }
928         
929         Py_Return;
930 }
931
932
933
934 PyObject* KX_GameObject::PySuspendDynamics(PyObject* self, 
935                                                                                    PyObject* args, 
936                                                                                    PyObject* kwds)
937 {
938         if (m_bSuspendDynamics)
939         {
940                 Py_Return;
941         }
942         
943         if (m_pPhysicsController1)
944         {
945                 m_pPhysicsController1->SuspendDynamics();
946         }
947         m_bSuspendDynamics = true;
948         
949         Py_Return;
950 }
951
952
953
954 PyObject* KX_GameObject::PyRestoreDynamics(PyObject* self, 
955                                                                                    PyObject* args, 
956                                                                                    PyObject* kwds)
957 {
958         
959         if (!m_bSuspendDynamics)
960         {
961                 Py_Return;
962         }
963         
964         if (m_pPhysicsController1)
965         {
966                 m_pPhysicsController1->RestoreDynamics();
967         }
968         m_bSuspendDynamics = false;
969         
970         Py_Return;
971 }
972
973
974
975 PyObject* KX_GameObject::PyGetOrientation(PyObject* self,
976                                                                                   PyObject* args,
977                                                                                   PyObject* kwds) //keywords
978 {
979         // do the conversion of a C++ matrix to a python list
980         
981         PyObject* resultlist = PyList_New(3);
982         
983         
984         int row,col;
985         const MT_Matrix3x3& orient = NodeGetWorldOrientation();
986         
987         for (row=0;row<3;row++)
988         {
989                 PyObject* veclist = PyList_New(3);
990                 
991                 for (col=0;col<3;col++)
992                 {
993                         const MT_Scalar fl = orient[row][col];
994                         PyList_SetItem(veclist,col,PyFloat_FromDouble(fl));
995                 }
996                 PyList_SetItem(resultlist,row,veclist);
997                 
998         }
999         return resultlist;
1000 }
1001
1002
1003
1004 PyObject* KX_GameObject::PySetOrientation(PyObject* self, 
1005                                                                                   PyObject* args, 
1006                                                                                   PyObject* kwds)
1007 {
1008         MT_Matrix3x3 matrix;
1009         
1010         PyObject* pylist;
1011         bool    error = false;
1012         int row,col;
1013         
1014         PyArg_ParseTuple(args,"O",&pylist);
1015         
1016         if (pylist->ob_type == &CListValue::Type)
1017         {
1018                 CListValue* listval = (CListValue*) pylist;
1019                 if (listval->GetCount() == 3)
1020                 {
1021                         for (row=0;row<3;row++) // each row has a 3-vector [x,y,z]
1022                         {
1023                                 CListValue* vecval = (CListValue*)listval->GetValue(row);
1024                                 for (col=0;col<3;col++)
1025                                 {
1026                                         matrix[row][col] = vecval->GetValue(col)->GetNumber();
1027                                         
1028                                 }
1029                         }
1030                 }
1031                 else
1032                 {
1033                         error = true;
1034                 }
1035         }
1036         else
1037         {
1038                 // assert the list is long enough...
1039                 int numitems = PyList_Size(pylist);
1040                 if (numitems == 3)
1041                 {
1042                         for (row=0;row<3;row++) // each row has a 3-vector [x,y,z]
1043                         {
1044                                 
1045                                 PyObject* veclist = PyList_GetItem(pylist,row); // here we have a vector3 list
1046                                 for (col=0;col<3;col++)
1047                                 {
1048                                         matrix[row][col] =  PyFloat_AsDouble(PyList_GetItem(veclist,col));
1049                                         
1050                                 }
1051                         }
1052                 }
1053                 else
1054                 {
1055                         error = true;
1056                 }
1057         }
1058         
1059         if (!error)
1060         {
1061                 if (m_pPhysicsController1)
1062                 {
1063                         m_pPhysicsController1->setOrientation(matrix.getRotation());
1064                 }
1065                 NodeSetLocalOrientation(matrix);
1066         }
1067         
1068         Py_INCREF(Py_None);
1069         return Py_None;
1070 }
1071
1072
1073
1074 PyObject* KX_GameObject::PySetPosition(PyObject* self, 
1075                                                                            PyObject* args, 
1076                                                                            PyObject* kwds)
1077 {
1078         // make a general function for this, it's needed many times
1079         
1080         MT_Point3 pos = ConvertPythonVectorArg(args);
1081         if (this->m_pPhysicsController1)
1082         {
1083                 this->m_pPhysicsController1->setPosition(pos);
1084         }
1085         NodeSetLocalPosition(pos);
1086         
1087         Py_INCREF(Py_None);
1088         return Py_None;
1089 }
1090
1091 PyObject* KX_GameObject::PyGetPhysicsId(PyObject* self,
1092                                                                                            PyObject* args,
1093                                                                                            PyObject* kwds)
1094 {
1095         KX_IPhysicsController* ctrl = GetPhysicsController();
1096         int physid=0;
1097         if (ctrl)
1098         {
1099                 physid= (int)ctrl->GetUserData();
1100         }
1101         return PyInt_FromLong(physid);
1102 }
1103
1104 /* --------------------------------------------------------------------- 
1105  * Some stuff taken from the header
1106  * --------------------------------------------------------------------- */
1107 void KX_GameObject::Relink(GEN_Map<GEN_HashedPtr, void*> *map_parameter)        
1108 {
1109         /* intentionally empty ? */
1110 }
1111