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