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