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