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