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