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