BGE patch: add rayCastToEx(), an extended version of rayCastTo() for use in game...
[blender.git] / source / gameengine / Ketsji / KX_GameObject.cpp
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL 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.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  * Game object wrapper
29  */
30
31 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
34
35 #if defined(_WIN64)
36 typedef unsigned __int64 uint_ptr;
37 #else
38 typedef unsigned long uint_ptr;
39 #endif
40
41 #ifdef WIN32
42 // This warning tells us about truncation of __long__ stl-generated names.
43 // It can occasionally cause DevStudio to have internal compiler warnings.
44 #pragma warning( disable : 4786 )     
45 #endif
46
47
48 #define KX_INERTIA_INFINITE 10000
49 #include "RAS_IPolygonMaterial.h"
50 #include "KX_BlenderMaterial.h"
51 #include "KX_GameObject.h"
52 #include "RAS_MeshObject.h"
53 #include "KX_MeshProxy.h"
54 #include <stdio.h> // printf
55 #include "SG_Controller.h"
56 #include "KX_IPhysicsController.h"
57 #include "SG_Node.h"
58 #include "SG_Controller.h"
59 #include "KX_ClientObjectInfo.h"
60 #include "RAS_BucketManager.h"
61 #include "KX_RayCast.h"
62 #include "KX_PythonInit.h"
63 #include "KX_PyMath.h"
64
65 // This file defines relationships between parents and children
66 // in the game engine.
67
68 #include "KX_SG_NodeRelationships.h"
69
70 KX_GameObject::KX_GameObject(
71         void* sgReplicationInfo,
72         SG_Callbacks callbacks,
73         PyTypeObject* T
74 ) : 
75         SCA_IObject(T),
76         m_bDyna(false),
77         m_layer(0),
78         m_bSuspendDynamics(false),
79         m_bUseObjectColor(false),
80         m_bVisible(true),
81         m_pPhysicsController1(NULL),
82         m_pPhysicsEnvironment(NULL),
83         m_isDeformable(false),
84         m_pHitObject(NULL)
85 {
86         m_ignore_activity_culling = false;
87         m_pClient_info = new KX_ClientObjectInfo(this, KX_ClientObjectInfo::ACTOR);
88         m_pSGNode = new SG_Node(this,sgReplicationInfo,callbacks);
89
90         // define the relationship between this node and it's parent.
91         
92         KX_NormalParentRelation * parent_relation = 
93                 KX_NormalParentRelation::New();
94         m_pSGNode->SetParentRelation(parent_relation);
95         
96
97 };
98
99
100
101 KX_GameObject::~KX_GameObject()
102 {
103         // is this delete somewhere ?
104         //if (m_sumoObj)
105         //      delete m_sumoObj;
106         delete m_pClient_info;
107         //if (m_pSGNode)
108         //      delete m_pSGNode;
109         if (m_pSGNode)
110         {
111                 // must go through controllers and make sure they will not use us anymore
112                 // This is important for KX_BulletPhysicsControllers that unregister themselves
113                 // from the object when they are deleted.
114                 SGControllerList::iterator contit;
115                 SGControllerList& controllers = m_pSGNode->GetSGControllerList();
116                 for (contit = controllers.begin();contit!=controllers.end();++contit)
117                 {
118                         (*contit)->ClearObject();
119                 }
120                 m_pSGNode->SetSGClientObject(NULL);
121         }
122 }
123
124
125
126 CValue* KX_GameObject:: Calc(VALUE_OPERATOR op, CValue *val) 
127 {
128         return NULL;
129 }
130
131
132
133 CValue* KX_GameObject::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val)
134 {
135         return NULL;
136 }
137
138
139
140 const STR_String & KX_GameObject::GetText()
141 {
142         return m_text;
143 }
144
145
146
147 float KX_GameObject::GetNumber()
148 {
149         return 0;
150 }
151
152
153
154 STR_String KX_GameObject::GetName()
155 {
156         return m_name;
157 }
158
159
160
161 void KX_GameObject::SetName(STR_String name)
162 {
163         m_name = name;
164 };                                                              // Set the name of the value
165
166
167
168 void KX_GameObject::ReplicaSetName(STR_String name)
169 {
170 }
171
172
173
174
175
176
177 KX_IPhysicsController* KX_GameObject::GetPhysicsController()
178 {
179         return m_pPhysicsController1;
180 }
181
182
183
184
185
186 KX_GameObject* KX_GameObject::GetParent()
187 {
188         KX_GameObject* result = NULL;
189         SG_Node* node = m_pSGNode;
190         
191         while (node && !result)
192         {
193                 node = node->GetSGParent();
194                 if (node)
195                         result = (KX_GameObject*)node->GetSGClientObject();
196         }
197         
198         if (result)
199                 result->AddRef();
200
201         return result;
202         
203 }
204
205 void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj)
206 {
207         if (obj && GetSGNode()->GetSGParent() != obj->GetSGNode())
208         {
209                 // Make sure the objects have some scale
210                 MT_Vector3 scale1 = NodeGetWorldScaling();
211                 MT_Vector3 scale2 = obj->NodeGetWorldScaling();
212                 if (fabs(scale2[0]) < FLT_EPSILON || 
213                         fabs(scale2[1]) < FLT_EPSILON || 
214                         fabs(scale2[2]) < FLT_EPSILON || 
215                         fabs(scale1[0]) < FLT_EPSILON || 
216                         fabs(scale1[1]) < FLT_EPSILON || 
217                         fabs(scale1[2]) < FLT_EPSILON) { return; }
218
219                 // Remove us from our old parent and set our new parent
220                 RemoveParent(scene);
221                 obj->GetSGNode()->AddChild(GetSGNode());
222
223                 // Set us to our new scale, position, and orientation
224                 scale1[0] = scale1[0]/scale2[0];
225                 scale1[1] = scale1[1]/scale2[1];
226                 scale1[2] = scale1[2]/scale2[2];
227                 MT_Matrix3x3 invori = obj->NodeGetWorldOrientation().inverse();
228                 MT_Vector3 newpos = invori*(NodeGetWorldPosition()-obj->NodeGetWorldPosition())*scale1;
229
230                 NodeSetLocalScale(scale1);
231                 NodeSetLocalPosition(MT_Point3(newpos[0],newpos[1],newpos[2]));
232                 NodeSetLocalOrientation(invori*NodeGetWorldOrientation());
233                 NodeUpdateGS(0.f,true);
234                 // object will now be a child, it must be removed from the parent list
235                 CListValue* rootlist = scene->GetRootParentList();
236                 if (rootlist->RemoveValue(this))
237                         // the object was in parent list, decrement ref count as it's now removed
238                         Release();
239         }
240 }
241
242 void KX_GameObject::RemoveParent(KX_Scene *scene)
243 {
244         if (GetSGNode()->GetSGParent())
245         {
246                 // Set us to the right spot 
247                 GetSGNode()->SetLocalScale(GetSGNode()->GetWorldScaling());
248                 GetSGNode()->SetLocalOrientation(GetSGNode()->GetWorldOrientation());
249                 GetSGNode()->SetLocalPosition(GetSGNode()->GetWorldPosition());
250
251                 // Remove us from our parent
252                 GetSGNode()->DisconnectFromParent();
253                 NodeUpdateGS(0.f,true);
254                 // the object is now a root object, add it to the parentlist
255                 CListValue* rootlist = scene->GetRootParentList();
256                 if (!rootlist->SearchValue(this))
257                         // object was not in root list, add it now and increment ref count
258                         rootlist->Add(AddRef());
259         }
260 }
261
262 void KX_GameObject::ProcessReplica(KX_GameObject* replica)
263 {
264         replica->m_pPhysicsController1 = NULL;
265         replica->m_pSGNode = NULL;
266         replica->m_pClient_info = new KX_ClientObjectInfo(*m_pClient_info);
267         replica->m_pClient_info->m_gameobject = replica;
268 }
269
270
271
272 CValue* KX_GameObject::GetReplica()
273 {
274         KX_GameObject* replica = new KX_GameObject(*this);
275         
276         // this will copy properties and so on...
277         CValue::AddDataToReplica(replica);
278         ProcessReplica(replica);
279         
280         return replica;
281 }
282
283
284
285 void KX_GameObject::ApplyForce(const MT_Vector3& force,bool local)
286 {
287         if (m_pPhysicsController1)
288                 m_pPhysicsController1->ApplyForce(force,local);
289 }
290
291
292
293 void KX_GameObject::ApplyTorque(const MT_Vector3& torque,bool local)
294 {
295         if (m_pPhysicsController1)
296                 m_pPhysicsController1->ApplyTorque(torque,local);
297 }
298
299
300
301 void KX_GameObject::ApplyMovement(const MT_Vector3& dloc,bool local)
302 {
303         if (m_pPhysicsController1) // (IsDynamic())
304         {
305                 m_pPhysicsController1->RelativeTranslate(dloc,local);
306         }
307         GetSGNode()->RelativeTranslate(dloc,GetSGNode()->GetSGParent(),local);
308 }
309
310
311
312 void KX_GameObject::ApplyRotation(const MT_Vector3& drot,bool local)
313 {
314         MT_Matrix3x3 rotmat(drot);
315
316         GetSGNode()->RelativeRotate(rotmat,local);
317
318         if (m_pPhysicsController1) { // (IsDynamic())
319                 m_pPhysicsController1->RelativeRotate(rotmat,local); 
320         }
321 }
322
323
324
325 /**
326 GetOpenGL Matrix, returns an OpenGL 'compatible' matrix
327 */
328 double* KX_GameObject::GetOpenGLMatrix()
329 {
330         // todo: optimize and only update if necessary
331         double* fl = m_OpenGL_4x4Matrix.getPointer();
332         MT_Transform trans;
333         
334         trans.setOrigin(GetSGNode()->GetWorldPosition());
335         trans.setBasis(GetSGNode()->GetWorldOrientation());
336         
337         MT_Vector3 scaling = GetSGNode()->GetWorldScaling();
338         
339         trans.scale(scaling[0], scaling[1], scaling[2]);
340         trans.getValue(fl);
341
342         return fl;
343 }
344
345
346
347 void KX_GameObject::Bucketize()
348 {
349         double* fl = GetOpenGLMatrix();
350
351         for (size_t i=0;i<m_meshes.size();i++)
352                 m_meshes[i]->Bucketize(fl, this, m_bUseObjectColor, m_objectColor);
353 }
354
355
356
357 void KX_GameObject::RemoveMeshes()
358 {
359         double* fl = GetOpenGLMatrix();
360
361         for (size_t i=0;i<m_meshes.size();i++)
362                 m_meshes[i]->RemoveFromBuckets(fl, this);
363
364         //note: meshes can be shared, and are deleted by KX_BlenderSceneConverter
365
366         m_meshes.clear();
367 }
368
369
370
371 void KX_GameObject::UpdateNonDynas()
372 {
373         if (m_pPhysicsController1)
374         {
375                 m_pPhysicsController1->SetSumoTransform(true);
376         }
377 }
378
379
380
381 void KX_GameObject::UpdateTransform()
382 {
383         if (m_pPhysicsController1)
384                 m_pPhysicsController1->SetSumoTransform(false);
385 }
386
387 void KX_GameObject::UpdateTransformFunc(SG_IObject* node, void* gameobj, void* scene)
388 {
389         ((KX_GameObject*)gameobj)->UpdateTransform();
390 }
391
392
393 void KX_GameObject::SetDebugColor(unsigned int bgra)
394 {
395         for (size_t i=0;i<m_meshes.size();i++)
396                 m_meshes[i]->DebugColor(bgra);  
397 }
398
399
400
401 void KX_GameObject::ResetDebugColor()
402 {
403         SetDebugColor(0xff000000);
404 }
405
406
407
408 void KX_GameObject::UpdateIPO(float curframetime,
409                                                           bool recurse,
410                                                           bool ipo_as_force,
411                                                           bool force_local) 
412 {
413
414         // The ipo-actuator needs a sumo reference... this is retrieved (unfortunately)
415         // by the iposgcontr itself...
416 //              ipocontr->SetSumoReference(gameobj->GetSumoScene(), 
417 //                                                                 gameobj->GetSumoObject());
418
419
420         // The ipo has to be treated as a force, and not a displacement!
421         // For this case, we send some settings to the controller. This
422         // may need some caching...
423         if (ipo_as_force) {
424                 SGControllerList::iterator it = GetSGNode()->GetSGControllerList().begin();
425
426                 while (it != GetSGNode()->GetSGControllerList().end()) {
427                         (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_AS_FORCE, ipo_as_force);
428                         (*it)->SetOption(SG_Controller::SG_CONTR_IPO_FORCES_ACT_LOCAL, force_local);
429                         it++;
430                 }
431         } 
432
433         // The rest is the 'normal' update procedure.
434         GetSGNode()->SetSimulatedTime(curframetime,recurse);
435         GetSGNode()->UpdateWorldData(curframetime);
436         UpdateTransform();
437 }
438
439 // IPO update
440 void 
441 KX_GameObject::UpdateMaterialData(
442                 MT_Vector4 rgba,
443                 MT_Vector3 specrgb,
444                 MT_Scalar hard,
445                 MT_Scalar spec,
446                 MT_Scalar ref,
447                 MT_Scalar emit,
448                 MT_Scalar alpha
449
450         )
451 {
452         int mesh = 0;
453         if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0) {
454                 RAS_MaterialBucket::Set::iterator mit = m_meshes[mesh]->GetFirstMaterial();
455                 for(; mit != m_meshes[mesh]->GetLastMaterial(); ++mit)
456                 {
457                         RAS_IPolyMaterial* poly = (*mit)->GetPolyMaterial();
458                         if(poly->GetFlag() & RAS_BLENDERMAT )
459                         {
460                                 SetObjectColor(rgba);
461                                 KX_BlenderMaterial *m =  static_cast<KX_BlenderMaterial*>(poly);
462                                 m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha);
463                         }
464                 }
465         }
466 }
467 bool
468 KX_GameObject::GetVisible(
469         void
470         )
471 {
472         return m_bVisible;
473 }
474
475 void
476 KX_GameObject::SetVisible(
477         bool v
478         )
479 {
480         m_bVisible = v;
481 }
482
483 void
484 KX_GameObject::SetLayer(
485         int l
486         )
487 {
488         m_layer = l;
489 }
490
491 int
492 KX_GameObject::GetLayer(
493         void
494         )
495 {
496         return m_layer;
497 }
498
499 // used by Python, and the actuatorshould _not_ be misused by the
500 // scene!
501 void 
502 KX_GameObject::MarkVisible(
503         bool visible
504         )
505 {
506         /* If explicit visibility settings are used, this is
507          * determined on this level. Maybe change this to mesh level
508          * later on? */
509         
510         double* fl = GetOpenGLMatrixPtr()->getPointer();
511         for (size_t i=0;i<m_meshes.size();i++)
512         {
513                 m_meshes[i]->MarkVisible(fl,this,visible,m_bUseObjectColor,m_objectColor);
514         }
515 }
516
517
518 // Always use the flag?
519 void 
520 KX_GameObject::MarkVisible(
521         void
522         )
523 {
524         double* fl = GetOpenGLMatrixPtr()->getPointer();
525         for (size_t i=0;i<m_meshes.size();i++)
526         {
527                 m_meshes[i]->MarkVisible(fl,
528                                          this,
529                                          m_bVisible,
530                                          m_bUseObjectColor,
531                                          m_objectColor
532                         );
533         }
534 }
535
536
537 void KX_GameObject::addLinearVelocity(const MT_Vector3& lin_vel,bool local)
538 {
539         if (m_pPhysicsController1)
540                 m_pPhysicsController1->SetLinearVelocity(lin_vel + m_pPhysicsController1->GetLinearVelocity(),local);
541 }
542
543
544
545 void KX_GameObject::setLinearVelocity(const MT_Vector3& lin_vel,bool local)
546 {
547         if (m_pPhysicsController1)
548                 m_pPhysicsController1->SetLinearVelocity(lin_vel,local);
549 }
550
551
552
553 void KX_GameObject::setAngularVelocity(const MT_Vector3& ang_vel,bool local)
554 {
555         if (m_pPhysicsController1)
556                 m_pPhysicsController1->SetAngularVelocity(ang_vel,local);
557 }
558
559 void KX_GameObject::ResolveCombinedVelocities(
560         const MT_Vector3 & lin_vel,
561         const MT_Vector3 & ang_vel,
562         bool lin_vel_local,
563         bool ang_vel_local
564 ){
565         if (m_pPhysicsController1)
566         {
567
568                 MT_Vector3 lv = lin_vel_local ? NodeGetWorldOrientation() * lin_vel : lin_vel;
569                 MT_Vector3 av = ang_vel_local ? NodeGetWorldOrientation() * ang_vel : ang_vel;
570                 m_pPhysicsController1->resolveCombinedVelocities(
571                         lv.x(),lv.y(),lv.z(),av.x(),av.y(),av.z());
572         }
573 }
574
575
576 void KX_GameObject::SetObjectColor(const MT_Vector4& rgbavec)
577 {
578         m_bUseObjectColor = true;
579         m_objectColor = rgbavec;
580 }
581
582
583
584 MT_Vector3 KX_GameObject::GetLinearVelocity(bool local)
585 {
586         MT_Vector3 velocity(0.0,0.0,0.0);
587         MT_Matrix3x3 ori, locvel;
588         int i, j; 
589         if (m_pPhysicsController1)
590         {
591                 velocity = m_pPhysicsController1->GetLinearVelocity();
592                 
593                 if (local)
594                 {
595                         ori = GetSGNode()->GetWorldOrientation();
596                         
597                         for(i=0; i < 3; i++)
598                                 for(j=0; j < 3; j++)
599                                         locvel[i][j]= velocity[i]*ori[i][j];
600                         for(i=0; i < 3; i++)
601                                 velocity[i] = locvel[0][i] + locvel[1][i] + locvel[2][i];
602                 }
603         }
604         return velocity;        
605 }
606
607
608 // scenegraph node stuff
609
610 void KX_GameObject::NodeSetLocalPosition(const MT_Point3& trans)
611 {
612         if (m_pPhysicsController1)
613         {
614                 m_pPhysicsController1->setPosition(trans);
615         }
616
617         if (GetSGNode())
618                 GetSGNode()->SetLocalPosition(trans);
619 }
620
621
622
623 void KX_GameObject::NodeSetLocalOrientation(const MT_Matrix3x3& rot)
624 {
625         if (m_pPhysicsController1)
626         {
627                 m_pPhysicsController1->setOrientation(rot.getRotation());
628         }
629         if (GetSGNode())
630                 GetSGNode()->SetLocalOrientation(rot);
631         else
632         {
633                 int i;
634                 i=0;
635         }
636 }
637
638
639
640 void KX_GameObject::NodeSetLocalScale(const MT_Vector3& scale)
641 {
642         if (m_pPhysicsController1)
643         {
644                 m_pPhysicsController1->setScaling(scale);
645         }
646         
647         if (GetSGNode())
648                 GetSGNode()->SetLocalScale(scale);
649 }
650
651
652
653 void KX_GameObject::NodeSetRelativeScale(const MT_Vector3& scale)
654 {
655         if (GetSGNode())
656                 GetSGNode()->RelativeScale(scale);
657 }
658
659
660
661 void KX_GameObject::NodeUpdateGS(double time,bool bInitiator)
662 {
663         if (GetSGNode())
664                 GetSGNode()->UpdateWorldData(time);
665 }
666
667
668
669 const MT_Matrix3x3& KX_GameObject::NodeGetWorldOrientation() const
670 {
671         return GetSGNode()->GetWorldOrientation();
672 }
673
674
675
676 const MT_Vector3& KX_GameObject::NodeGetWorldScaling() const
677 {
678         return GetSGNode()->GetWorldScaling();
679 }
680
681
682
683 const MT_Point3& KX_GameObject::NodeGetWorldPosition() const
684 {
685         return GetSGNode()->GetWorldPosition();
686 }
687
688 /* Suspend/ resume: for the dynamic behaviour, there is a simple
689  * method. For the residual motion, there is not. I wonder what the
690  * correct solution is for Sumo. Remove from the motion-update tree?
691  *
692  * So far, only switch the physics and logic.
693  * */
694
695 void KX_GameObject::Resume(void)
696 {
697         if (m_suspended) {
698                 SCA_IObject::Resume();
699                 GetPhysicsController()->RestoreDynamics();
700
701                 m_suspended = false;
702         }
703 }
704
705 void KX_GameObject::Suspend(void)
706 {
707         if ((!m_ignore_activity_culling) 
708                 && (!m_suspended))  {
709                 SCA_IObject::Suspend();
710                 GetPhysicsController()->SuspendDynamics();
711                 m_suspended = true;
712         }
713 }
714
715
716
717
718 /* ------- python stuff ---------------------------------------------------*/
719
720
721
722
723 PyMethodDef KX_GameObject::Methods[] = {
724         {"setVisible",(PyCFunction) KX_GameObject::sPySetVisible, METH_VARARGS},  
725         {"setPosition", (PyCFunction) KX_GameObject::sPySetPosition, METH_VARARGS},
726         {"getPosition", (PyCFunction) KX_GameObject::sPyGetPosition, METH_VARARGS},
727         {"getOrientation", (PyCFunction) KX_GameObject::sPyGetOrientation, METH_VARARGS},
728         {"setOrientation", (PyCFunction) KX_GameObject::sPySetOrientation, METH_VARARGS},
729         {"getLinearVelocity", (PyCFunction) KX_GameObject::sPyGetLinearVelocity, METH_VARARGS},
730         {"getVelocity", (PyCFunction) KX_GameObject::sPyGetVelocity, METH_VARARGS},
731         {"getMass", (PyCFunction) KX_GameObject::sPyGetMass, METH_VARARGS},
732         {"getReactionForce", (PyCFunction) KX_GameObject::sPyGetReactionForce, METH_VARARGS},
733         {"applyImpulse", (PyCFunction) KX_GameObject::sPyApplyImpulse, METH_VARARGS},
734         {"setCollisionMargin", (PyCFunction) KX_GameObject::sPySetCollisionMargin, METH_VARARGS},
735         {"suspendDynamics", (PyCFunction)KX_GameObject::sPySuspendDynamics,METH_VARARGS},
736         {"restoreDynamics", (PyCFunction)KX_GameObject::sPyRestoreDynamics,METH_VARARGS},
737         {"enableRigidBody", (PyCFunction)KX_GameObject::sPyEnableRigidBody,METH_VARARGS},
738         {"disableRigidBody", (PyCFunction)KX_GameObject::sPyDisableRigidBody,METH_VARARGS},
739         {"getParent", (PyCFunction)KX_GameObject::sPyGetParent,METH_VARARGS},
740         {"setParent", (PyCFunction)KX_GameObject::sPySetParent,METH_VARARGS},
741         {"removeParent", (PyCFunction)KX_GameObject::sPyRemoveParent,METH_VARARGS},
742         {"getMesh", (PyCFunction)KX_GameObject::sPyGetMesh,METH_VARARGS},
743         {"getPhysicsId", (PyCFunction)KX_GameObject::sPyGetPhysicsId,METH_VARARGS},
744         KX_PYMETHODTABLE(KX_GameObject, getDistanceTo),
745         KX_PYMETHODTABLE(KX_GameObject, rayCastTo),
746         KX_PYMETHODTABLE(KX_GameObject, rayCastToEx),
747         {NULL,NULL} //Sentinel
748 };
749
750
751
752 /*
753 bool KX_GameObject::ConvertPythonVectorArgs(PyObject* args,
754                                                                                         MT_Vector3& pos,
755                                                                                         MT_Vector3& pos2)
756 {
757         PyObject* pylist;
758         PyObject* pylist2;
759         bool error = (PyArg_ParseTuple(args,"OO",&pylist,&pylist2)) != 0;
760
761         pos = ConvertPythonPylist(pylist);
762         pos2 = ConvertPythonPylist(pylist2);
763                 
764         return error;
765 }
766 */
767
768
769 PyObject* KX_GameObject::sPySetPosition(PyObject* self,
770                                                                                 PyObject* args,
771                                                                                 PyObject* kwds)
772 {
773         return ((KX_GameObject*) self)->PySetPosition(self, args, kwds);
774 }
775         
776
777
778 PyObject* KX_GameObject::PyGetPosition(PyObject* self,
779                                                                            PyObject* args, 
780                                                                            PyObject* kwds)
781 {
782         return PyObjectFrom(NodeGetWorldPosition());
783 }
784
785
786
787 PyTypeObject KX_GameObject::Type = {
788         PyObject_HEAD_INIT(&PyType_Type)
789                 0,
790                 "KX_GameObject",
791                 sizeof(KX_GameObject),
792                 0,
793                 PyDestructor,
794                 0,
795                 __getattr,
796                 __setattr,
797                 0, //&MyPyCompare,
798                 __repr,
799                 0, //&cvalue_as_number,
800                 0,
801                 0,
802                 0,
803                 0
804 };
805
806
807
808 PyParentObject KX_GameObject::Parents[] = {
809         &KX_GameObject::Type,
810                 &SCA_IObject::Type,
811                 &CValue::Type,
812                 NULL
813 };
814
815
816
817
818 PyObject* KX_GameObject::_getattr(const STR_String& attr)
819 {
820         if (m_pPhysicsController1)
821         {
822                 if (attr == "mass")
823                         return PyFloat_FromDouble(GetPhysicsController()->GetMass());
824         }
825
826         if (attr == "parent")
827         {       
828                 KX_GameObject* parent = GetParent();
829                 if (parent)
830                 {
831                         parent->AddRef();
832                         return parent;
833                 }
834                 Py_Return;
835         }
836
837         if (attr == "visible")
838                 return PyInt_FromLong(m_bVisible);
839         
840         if (attr == "position")
841                 return PyObjectFrom(NodeGetWorldPosition());
842         
843         if (attr == "orientation")
844                 return PyObjectFrom(NodeGetWorldOrientation());
845         
846         if (attr == "scaling")
847                 return PyObjectFrom(NodeGetWorldScaling());
848                 
849         if (attr == "name")
850                 return PyString_FromString(m_name.ReadPtr());
851         
852         _getattr_up(SCA_IObject);
853 }
854
855 int KX_GameObject::_setattr(const STR_String& attr, PyObject *value)    // _setattr method
856 {
857         if (attr == "mass")
858                 return 1;
859         
860         if (attr == "parent")
861                 return 1;
862                 
863         if (PyInt_Check(value))
864         {
865                 int val = PyInt_AsLong(value);
866                 if (attr == "visible")
867                 {
868                         SetVisible(val != 0);
869                         return 0;
870                 }
871         }
872         
873         if (PySequence_Check(value))
874         {
875                 if (attr == "orientation")
876                 {
877                         MT_Matrix3x3 rot;
878                         if (PyObject_IsMT_Matrix(value, 3))
879                         {
880                                 if (PyMatTo(value, rot))
881                                 {
882                                         NodeSetLocalOrientation(rot);
883                                         NodeUpdateGS(0.f,true);
884                                         return 0;
885                                 }
886                                 return 1;
887                         }
888                         
889                         if (PySequence_Size(value) == 4)
890                         {
891                                 MT_Quaternion qrot;
892                                 if (PyVecTo(value, qrot))
893                                 {
894                                         rot.setRotation(qrot);
895                                         NodeSetLocalOrientation(rot);
896                                         NodeUpdateGS(0.f,true);
897                                         return 0;
898                                 }
899                                 return 1;
900                         }
901                         
902                         if (PySequence_Size(value) == 3)
903                         {
904                                 MT_Vector3 erot;
905                                 if (PyVecTo(value, erot))
906                                 {
907                                         rot.setEuler(erot);
908                                         NodeSetLocalOrientation(rot);
909                                         NodeUpdateGS(0.f,true);
910                                         return 0;
911                                 }
912                                 return 1;
913                         }
914                         
915                         return 1;
916                 }
917                 
918                 if (attr == "position")
919                 {
920                         MT_Point3 pos;
921                         if (PyVecTo(value, pos))
922                         {
923                                 NodeSetLocalPosition(pos);
924                                 NodeUpdateGS(0.f,true);
925                                 return 0;
926                         }
927                         return 1;
928                 }
929                 
930                 if (attr == "scaling")
931                 {
932                         MT_Vector3 scale;
933                         if (PyVecTo(value, scale))
934                         {
935                                 NodeSetLocalScale(scale);
936                                 NodeUpdateGS(0.f,true);
937                                 return 0;
938                         }
939                         return 1;
940                 }
941         }
942         
943         if (PyString_Check(value))
944         {
945                 if (attr == "name")
946                 {
947                         m_name = PyString_AsString(value);
948                         return 0;
949                 }
950         }
951         
952         /* Need to have parent settable here too */
953         
954         return SCA_IObject::_setattr(attr, value);
955 }
956
957
958 PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* self, 
959                                                                                          PyObject* args, 
960                                                                                          PyObject* kwds)
961 {
962         // only can get the velocity if we have a physics object connected to us...
963         int local = 0;
964         if (PyArg_ParseTuple(args,"|i",&local))
965         {
966                 return PyObjectFrom(GetLinearVelocity((local!=0)));
967         }
968         else
969         {
970                 return NULL;
971         }
972 }
973
974
975
976 PyObject* KX_GameObject::PySetVisible(PyObject* self,
977                                                                           PyObject* args,
978                                                                           PyObject* kwds)
979 {
980         int visible = 1;
981         
982         if (PyArg_ParseTuple(args,"i",&visible))
983         {
984                 MarkVisible(visible!=0);
985                 m_bVisible = (visible!=0);
986         }
987         else
988         {
989                 return NULL;         
990         }
991         Py_Return;
992         
993 }
994
995
996
997 PyObject* KX_GameObject::PyGetVelocity(PyObject* self, 
998                                                                            PyObject* args, 
999                                                                            PyObject* kwds)
1000 {
1001         // only can get the velocity if we have a physics object connected to us...
1002         MT_Vector3 velocity(0.0,0.0,0.0);
1003         MT_Point3 point(0.0,0.0,0.0);
1004         
1005         
1006         PyObject* pypos = NULL;
1007         if (PyArg_ParseTuple(args, "|O", &pypos))
1008         {
1009                 if (pypos)
1010                         PyVecTo(pypos, point);
1011         }
1012         
1013         if (m_pPhysicsController1)
1014         {
1015                 velocity = m_pPhysicsController1->GetVelocity(point);
1016         }
1017         
1018         return PyObjectFrom(velocity);
1019 }
1020
1021
1022
1023 PyObject* KX_GameObject::PyGetMass(PyObject* self, 
1024                                                                    PyObject* args, 
1025                                                                    PyObject* kwds)
1026 {
1027         PyObject* pymass = NULL;
1028         
1029         float mass = GetPhysicsController()->GetMass();
1030         pymass = PyFloat_FromDouble(mass);
1031
1032         if (pymass)
1033                 return pymass;
1034         
1035         Py_Return;
1036 }
1037
1038
1039
1040 PyObject* KX_GameObject::PyGetReactionForce(PyObject* self, 
1041                                                                                         PyObject* args, 
1042                                                                                         PyObject* kwds)
1043 {
1044         // only can get the velocity if we have a physics object connected to us...
1045         return PyObjectFrom(GetPhysicsController()->getReactionForce());
1046 }
1047
1048
1049
1050 PyObject* KX_GameObject::PyEnableRigidBody(PyObject* self, 
1051                                                                                    PyObject* args, 
1052                                                                                    PyObject* kwds)
1053 {
1054         
1055         GetPhysicsController()->setRigidBody(true);
1056
1057         Py_Return;
1058 }
1059
1060
1061
1062 PyObject* KX_GameObject::PyDisableRigidBody(PyObject* self, 
1063                                                                                         PyObject* args, 
1064                                                                                         PyObject* kwds)
1065 {
1066         GetPhysicsController()->setRigidBody(false);
1067
1068         Py_Return;
1069 }
1070
1071
1072
1073 PyObject* KX_GameObject::PyGetParent(PyObject* self, 
1074                                                                          PyObject* args, 
1075                                                                          PyObject* kwds)
1076 {
1077         KX_GameObject* parent = this->GetParent();
1078         if (parent)
1079         {
1080                 parent->AddRef();
1081                 return parent;
1082         }
1083         Py_Return;
1084 }
1085
1086 PyObject* KX_GameObject::PySetParent(PyObject* self, 
1087                                                                          PyObject* args, 
1088                                                                          PyObject* kwds)
1089 {
1090         PyObject* gameobj;
1091         if (PyArg_ParseTuple(args, "O!", &KX_GameObject::Type, &gameobj))
1092         {
1093                 // The object we want to set as parent
1094                 CValue *m_ob = (CValue*)gameobj;
1095                 KX_GameObject *obj = ((KX_GameObject*)m_ob);
1096                 KX_Scene *scene = PHY_GetActiveScene();
1097                 
1098                 this->SetParent(scene, obj);
1099         }
1100         Py_Return;
1101 }
1102
1103 PyObject* KX_GameObject::PyRemoveParent(PyObject* self, 
1104                                                                          PyObject* args, 
1105                                                                          PyObject* kwds)
1106 {
1107         KX_Scene *scene = PHY_GetActiveScene();
1108         this->RemoveParent(scene);
1109         Py_Return;
1110 }
1111
1112 PyObject* KX_GameObject::PyGetMesh(PyObject* self, 
1113                                                                    PyObject* args, 
1114                                                                    PyObject* kwds)
1115 {
1116         int mesh = 0;
1117
1118         if (PyArg_ParseTuple(args, "|i", &mesh))
1119         {
1120                 if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0)
1121                 {
1122                         KX_MeshProxy* meshproxy = new KX_MeshProxy(m_meshes[mesh]);
1123                         return meshproxy;
1124                 }
1125         }
1126         Py_Return;
1127 }
1128
1129
1130
1131
1132
1133 PyObject* KX_GameObject::PySetCollisionMargin(PyObject* self, 
1134                                                                                 PyObject* args, 
1135                                                                                 PyObject* kwds)
1136 {
1137         float collisionMargin;
1138         if (PyArg_ParseTuple(args, "f", &collisionMargin))
1139         {
1140                 if (m_pPhysicsController1)
1141                 {
1142                         m_pPhysicsController1->setMargin(collisionMargin);
1143                         Py_Return;
1144                 }
1145
1146         }
1147         
1148         return NULL;
1149 }
1150
1151
1152
1153 PyObject* KX_GameObject::PyApplyImpulse(PyObject* self, 
1154                                                                                 PyObject* args, 
1155                                                                                 PyObject* kwds)
1156 {
1157         PyObject* pyattach;
1158         PyObject* pyimpulse;
1159         if (PyArg_ParseTuple(args, "OO", &pyattach, &pyimpulse))
1160         {
1161                 MT_Point3  attach;
1162                 MT_Vector3 impulse;
1163                 if (m_pPhysicsController1)
1164                 {
1165                         if (PyVecTo(pyattach, attach) && PyVecTo(pyimpulse, impulse))
1166                         {
1167                                 m_pPhysicsController1->applyImpulse(attach, impulse);
1168                                 Py_Return;
1169                         }
1170                 }
1171
1172         }
1173         
1174         return NULL;
1175 }
1176
1177
1178
1179 PyObject* KX_GameObject::PySuspendDynamics(PyObject* self, 
1180                                                                                    PyObject* args, 
1181                                                                                    PyObject* kwds)
1182 {
1183         if (m_bSuspendDynamics)
1184         {
1185                 Py_Return;
1186         }
1187         
1188         if (m_pPhysicsController1)
1189         {
1190                 m_pPhysicsController1->SuspendDynamics();
1191         }
1192         m_bSuspendDynamics = true;
1193         
1194         Py_Return;
1195 }
1196
1197
1198
1199 PyObject* KX_GameObject::PyRestoreDynamics(PyObject* self, 
1200                                                                                    PyObject* args, 
1201                                                                                    PyObject* kwds)
1202 {
1203         
1204         if (!m_bSuspendDynamics)
1205         {
1206                 Py_Return;
1207         }
1208         
1209         if (m_pPhysicsController1)
1210         {
1211                 m_pPhysicsController1->RestoreDynamics();
1212         }
1213         m_bSuspendDynamics = false;
1214         
1215         Py_Return;
1216 }
1217
1218
1219
1220 PyObject* KX_GameObject::PyGetOrientation(PyObject* self,
1221                                                                                   PyObject* args,
1222                                                                                   PyObject* kwds) //keywords
1223 {
1224         return PyObjectFrom(NodeGetWorldOrientation());
1225 }
1226
1227
1228
1229 PyObject* KX_GameObject::PySetOrientation(PyObject* self, 
1230                                                                                   PyObject* args, 
1231                                                                                   PyObject* kwds)
1232 {
1233         PyObject* pylist;
1234         
1235         if (PyArg_ParseTuple(args,"O",&pylist))
1236         {
1237                 MT_Matrix3x3 matrix;
1238                 if (PyObject_IsMT_Matrix(pylist, 3) && PyMatTo(pylist, matrix))
1239                 {
1240                         NodeSetLocalOrientation(matrix);
1241                         NodeUpdateGS(0.f,true);
1242                         Py_Return;
1243                 }
1244         
1245                 MT_Quaternion quat;
1246                 if (PyVecTo(pylist, quat))
1247                 {
1248                         matrix.setRotation(quat);
1249                         NodeSetLocalOrientation(matrix);
1250                         NodeUpdateGS(0.f,true);
1251                         Py_Return;
1252                 }
1253         }
1254         return NULL;
1255 }
1256
1257
1258
1259 PyObject* KX_GameObject::PySetPosition(PyObject* self, 
1260                                                                            PyObject* args, 
1261                                                                            PyObject* kwds)
1262 {
1263         MT_Point3 pos;
1264         if (PyVecArgTo(args, pos))
1265         {
1266                 NodeSetLocalPosition(pos);
1267                 NodeUpdateGS(0.f,true);
1268                 Py_Return;
1269         }
1270         
1271         return NULL;
1272 }
1273
1274 PyObject* KX_GameObject::PyGetPhysicsId(PyObject* self,
1275                                                                                            PyObject* args,
1276                                                                                            PyObject* kwds)
1277 {
1278         KX_IPhysicsController* ctrl = GetPhysicsController();
1279         uint_ptr physid=0;
1280         if (ctrl)
1281         {
1282                 physid= (uint_ptr)ctrl->GetUserData();
1283         }
1284         return PyInt_FromLong((long)physid);
1285 }
1286
1287 KX_PYMETHODDEF_DOC(KX_GameObject, getDistanceTo,
1288 "getDistanceTo(other): get distance to another point/KX_GameObject")
1289 {
1290         MT_Point3 b;
1291         if (PyVecArgTo(args, b))
1292         {
1293                 return PyFloat_FromDouble(NodeGetWorldPosition().distance(b));
1294         }
1295         PyErr_Clear();
1296         
1297         PyObject *pyother;
1298         if (PyArg_ParseTuple(args, "O!", &KX_GameObject::Type, &pyother))
1299         {
1300                 KX_GameObject *other = static_cast<KX_GameObject*>(pyother);
1301                 return PyFloat_FromDouble(NodeGetWorldPosition().distance(other->NodeGetWorldPosition()));
1302         }
1303         
1304         return NULL;
1305 }
1306
1307 bool KX_GameObject::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data)
1308 {
1309
1310         KX_GameObject* hitKXObj = client->m_gameobject;
1311         
1312         if (client->m_type > KX_ClientObjectInfo::ACTOR)
1313         {
1314                 // false hit
1315                 return false;
1316         }
1317
1318         if (m_testPropName.Length() == 0 || hitKXObj->GetProperty(m_testPropName) != NULL)
1319         {
1320                 m_pHitObject = hitKXObj;
1321                 return true;
1322         }
1323
1324         return false;
1325         
1326 }
1327
1328 KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo,
1329 "rayCastTo(other,dist,prop): look towards another point/KX_GameObject and return first object hit within dist that matches prop\n"
1330 " prop = property name that object must have; can be omitted => detect any object\n"
1331 " dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to other\n"
1332 " other = 3-tuple or object reference")
1333 {
1334         MT_Point3 toPoint;
1335         PyObject* pyarg;
1336         float dist = 0.0f;
1337         char *propName = NULL;
1338
1339         if (!PyArg_ParseTuple(args,"O|fs", &pyarg, &dist, &propName))
1340                 return NULL;
1341
1342         if (!PyVecTo(pyarg, toPoint))
1343         {
1344                 KX_GameObject *other;
1345                 PyErr_Clear();
1346                 if (!PyType_IsSubtype(pyarg->ob_type, &KX_GameObject::Type))
1347                         return NULL;
1348                 other = static_cast<KX_GameObject*>(pyarg);
1349                 toPoint = other->NodeGetWorldPosition();
1350         }
1351         MT_Point3 fromPoint = NodeGetWorldPosition();
1352         if (dist != 0.0f)
1353         {
1354                 MT_Vector3 toDir = toPoint-fromPoint;
1355                 toDir.normalize();
1356                 toPoint = fromPoint + (dist) * toDir;
1357         }
1358
1359         MT_Point3 resultPoint;
1360         MT_Vector3 resultNormal;
1361         PHY_IPhysicsEnvironment* pe = GetPhysicsEnvironment();
1362         KX_IPhysicsController *spc = GetPhysicsController();
1363         KX_GameObject *parent = GetParent();
1364         if (!spc && parent)
1365                 spc = parent->GetPhysicsController();
1366         if (parent)
1367                 parent->Release();
1368         
1369         m_pHitObject = NULL;
1370         if (propName)
1371                 m_testPropName = propName;
1372         else
1373                 m_testPropName.SetLength(0);
1374         KX_RayCast::RayTest(spc, pe, fromPoint, toPoint, resultPoint, resultNormal, KX_RayCast::Callback<KX_GameObject>(this));
1375
1376     if (m_pHitObject)
1377         {
1378                 m_pHitObject->AddRef();
1379                 return m_pHitObject;
1380         }
1381         Py_Return;
1382 }
1383
1384 KX_PYMETHODDEF_DOC(KX_GameObject, rayCastToEx,
1385 "rayCastToEx(to,from,dist,prop): cast a ray and return tuple (object,hit,normal) of contact point with object within dist that matches prop or None if no hit\n"
1386 " prop = property name that object must have; can be omitted => detect any object\n"
1387 " dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to to\n"
1388 " from = 3-tuple or object reference for origin of ray (if object, use center of object)\n"
1389 "        Can None or omitted => start from self object center\n"
1390 " to = 3-tuple or object reference for destination of ray (if object, use center of object)\n"
1391 "Note: the object on which you call this method matters: the ray will ignore it if it goes through it\n")
1392 {
1393         MT_Point3 toPoint;
1394         MT_Point3 fromPoint;
1395         PyObject* pyto;
1396         PyObject* pyfrom = NULL;
1397         float dist = 0.0f;
1398         char *propName = NULL;
1399         KX_GameObject *other;
1400
1401         if (!PyArg_ParseTuple(args,"O|Ofs", &pyto, &pyfrom, &dist, &propName))
1402                 return NULL;
1403
1404         if (!PyVecTo(pyto, toPoint))
1405         {
1406                 PyErr_Clear();
1407                 if (!PyType_IsSubtype(pyto->ob_type, &KX_GameObject::Type))
1408                         return NULL;
1409                 other = static_cast<KX_GameObject*>(pyto);
1410                 toPoint = other->NodeGetWorldPosition();
1411         }
1412         if (!pyfrom || pyfrom == Py_None)
1413         {
1414                 fromPoint = NodeGetWorldPosition();
1415         }
1416         else if (!PyVecTo(pyfrom, fromPoint))
1417         {
1418                 PyErr_Clear();
1419                 if (!PyType_IsSubtype(pyfrom->ob_type, &KX_GameObject::Type))
1420                         return NULL;
1421                 other = static_cast<KX_GameObject*>(pyfrom);
1422                 fromPoint = other->NodeGetWorldPosition();
1423         }
1424
1425         if (dist != 0.0f)
1426         {
1427                 MT_Vector3 toDir = toPoint-fromPoint;
1428                 toDir.normalize();
1429                 toPoint = fromPoint + (dist) * toDir;
1430         }
1431
1432         MT_Point3 resultPoint;
1433         MT_Vector3 resultNormal;
1434         PHY_IPhysicsEnvironment* pe = GetPhysicsEnvironment();
1435         KX_IPhysicsController *spc = GetPhysicsController();
1436         KX_GameObject *parent = GetParent();
1437         if (!spc && parent)
1438                 spc = parent->GetPhysicsController();
1439         if (parent)
1440                 parent->Release();
1441         
1442         m_pHitObject = NULL;
1443         if (propName)
1444                 m_testPropName = propName;
1445         else
1446                 m_testPropName.SetLength(0);
1447         KX_RayCast::RayTest(spc, pe, fromPoint, toPoint, resultPoint, resultNormal, KX_RayCast::Callback<KX_GameObject>(this));
1448
1449     if (m_pHitObject)
1450         {
1451                 PyObject* returnValue = PyTuple_New(3);
1452                 if (!returnValue)
1453                         return NULL;
1454                 PyTuple_SET_ITEM(returnValue, 0, m_pHitObject->AddRef());
1455                 PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(resultPoint));
1456                 PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(resultNormal));
1457                 return returnValue;
1458                 //return Py_BuildValue("(O,(fff),(fff))", 
1459                 //      m_pHitObject->AddRef(),         // trick: KX_GameObject are not true Python object, they use a difference reference count system
1460                 //      resultPoint[0], resultPoint[1], resultPoint[2],
1461                 //      resultNormal[0], resultNormal[1], resultNormal[2]);
1462         }
1463         return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
1464         //Py_Return;
1465 }
1466
1467 /* --------------------------------------------------------------------- 
1468  * Some stuff taken from the header
1469  * --------------------------------------------------------------------- */
1470 void KX_GameObject::Relink(GEN_Map<GEN_HashedPtr, void*> *map_parameter)        
1471 {
1472         /* intentionally empty ? */
1473 }
1474