get/set Angular velocity for KX_GameObjects python api and for the AddObject actuator.
[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 #include "SCA_IActuator.h"
65 #include "SCA_ISensor.h"
66
67 // This file defines relationships between parents and children
68 // in the game engine.
69
70 #include "KX_SG_NodeRelationships.h"
71
72 KX_GameObject::KX_GameObject(
73         void* sgReplicationInfo,
74         SG_Callbacks callbacks,
75         PyTypeObject* T
76 ) : 
77         SCA_IObject(T),
78         m_bDyna(false),
79         m_layer(0),
80         m_pBlenderObject(NULL),
81         m_bSuspendDynamics(false),
82         m_bUseObjectColor(false),
83         m_bIsNegativeScaling(false),
84         m_bVisible(true),
85         m_pPhysicsController1(NULL),
86         m_pPhysicsEnvironment(NULL),
87         m_pHitObject(NULL),
88         m_isDeformable(false)
89 {
90         m_ignore_activity_culling = false;
91         m_pClient_info = new KX_ClientObjectInfo(this, KX_ClientObjectInfo::ACTOR);
92         m_pSGNode = new SG_Node(this,sgReplicationInfo,callbacks);
93
94         // define the relationship between this node and it's parent.
95         
96         KX_NormalParentRelation * parent_relation = 
97                 KX_NormalParentRelation::New();
98         m_pSGNode->SetParentRelation(parent_relation);
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
166 };                                                              // Set the name of the value
167
168
169
170 void KX_GameObject::ReplicaSetName(STR_String name)
171 {
172 }
173
174
175
176
177
178
179 KX_IPhysicsController* KX_GameObject::GetPhysicsController()
180 {
181         return m_pPhysicsController1;
182 }
183
184
185
186
187
188 KX_GameObject* KX_GameObject::GetParent()
189 {
190         KX_GameObject* result = NULL;
191         SG_Node* node = m_pSGNode;
192         
193         while (node && !result)
194         {
195                 node = node->GetSGParent();
196                 if (node)
197                         result = (KX_GameObject*)node->GetSGClientObject();
198         }
199         
200         if (result)
201                 result->AddRef();
202
203         return result;
204         
205 }
206
207 void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj)
208 {
209         if (obj && GetSGNode()->GetSGParent() != obj->GetSGNode())
210         {
211                 // Make sure the objects have some scale
212                 MT_Vector3 scale1 = NodeGetWorldScaling();
213                 MT_Vector3 scale2 = obj->NodeGetWorldScaling();
214                 if (fabs(scale2[0]) < FLT_EPSILON || 
215                         fabs(scale2[1]) < FLT_EPSILON || 
216                         fabs(scale2[2]) < FLT_EPSILON || 
217                         fabs(scale1[0]) < FLT_EPSILON || 
218                         fabs(scale1[1]) < FLT_EPSILON || 
219                         fabs(scale1[2]) < FLT_EPSILON) { return; }
220
221                 // Remove us from our old parent and set our new parent
222                 RemoveParent(scene);
223                 obj->GetSGNode()->AddChild(GetSGNode());
224
225                 if (m_pPhysicsController1) 
226                 {
227                         m_pPhysicsController1->SuspendDynamics(true);
228                 }
229                 // Set us to our new scale, position, and orientation
230                 scale1[0] = scale1[0]/scale2[0];
231                 scale1[1] = scale1[1]/scale2[1];
232                 scale1[2] = scale1[2]/scale2[2];
233                 MT_Matrix3x3 invori = obj->NodeGetWorldOrientation().inverse();
234                 MT_Vector3 newpos = invori*(NodeGetWorldPosition()-obj->NodeGetWorldPosition())*scale1;
235
236                 NodeSetLocalScale(scale1);
237                 NodeSetLocalPosition(MT_Point3(newpos[0],newpos[1],newpos[2]));
238                 NodeSetLocalOrientation(invori*NodeGetWorldOrientation());
239                 NodeUpdateGS(0.f,true);
240                 // object will now be a child, it must be removed from the parent list
241                 CListValue* rootlist = scene->GetRootParentList();
242                 if (rootlist->RemoveValue(this))
243                         // the object was in parent list, decrement ref count as it's now removed
244                         Release();
245         }
246 }
247
248 void KX_GameObject::RemoveParent(KX_Scene *scene)
249 {
250         if (GetSGNode()->GetSGParent())
251         {
252                 // Set us to the right spot 
253                 GetSGNode()->SetLocalScale(GetSGNode()->GetWorldScaling());
254                 GetSGNode()->SetLocalOrientation(GetSGNode()->GetWorldOrientation());
255                 GetSGNode()->SetLocalPosition(GetSGNode()->GetWorldPosition());
256
257                 // Remove us from our parent
258                 GetSGNode()->DisconnectFromParent();
259                 NodeUpdateGS(0.f,true);
260                 // the object is now a root object, add it to the parentlist
261                 CListValue* rootlist = scene->GetRootParentList();
262                 if (!rootlist->SearchValue(this))
263                         // object was not in root list, add it now and increment ref count
264                         rootlist->Add(AddRef());
265                 if (m_pPhysicsController1) 
266                 {
267                         m_pPhysicsController1->RestoreDynamics();
268                 }
269         }
270 }
271
272 void KX_GameObject::ProcessReplica(KX_GameObject* replica)
273 {
274         replica->m_pPhysicsController1 = NULL;
275         replica->m_pSGNode = NULL;
276         replica->m_pClient_info = new KX_ClientObjectInfo(*m_pClient_info);
277         replica->m_pClient_info->m_gameobject = replica;
278         replica->m_state = 0;
279 }
280
281
282
283 CValue* KX_GameObject::GetReplica()
284 {
285         KX_GameObject* replica = new KX_GameObject(*this);
286         
287         // this will copy properties and so on...
288         CValue::AddDataToReplica(replica);
289         ProcessReplica(replica);
290         
291         return replica;
292 }
293
294
295
296 void KX_GameObject::ApplyForce(const MT_Vector3& force,bool local)
297 {
298         if (m_pPhysicsController1)
299                 m_pPhysicsController1->ApplyForce(force,local);
300 }
301
302
303
304 void KX_GameObject::ApplyTorque(const MT_Vector3& torque,bool local)
305 {
306         if (m_pPhysicsController1)
307                 m_pPhysicsController1->ApplyTorque(torque,local);
308 }
309
310
311
312 void KX_GameObject::ApplyMovement(const MT_Vector3& dloc,bool local)
313 {
314         if (m_pPhysicsController1) // (IsDynamic())
315         {
316                 m_pPhysicsController1->RelativeTranslate(dloc,local);
317         }
318         GetSGNode()->RelativeTranslate(dloc,GetSGNode()->GetSGParent(),local);
319 }
320
321
322
323 void KX_GameObject::ApplyRotation(const MT_Vector3& drot,bool local)
324 {
325         MT_Matrix3x3 rotmat(drot);
326
327         GetSGNode()->RelativeRotate(rotmat,local);
328
329         if (m_pPhysicsController1) { // (IsDynamic())
330                 m_pPhysicsController1->RelativeRotate(rotmat,local); 
331         }
332 }
333
334
335
336 /**
337 GetOpenGL Matrix, returns an OpenGL 'compatible' matrix
338 */
339 double* KX_GameObject::GetOpenGLMatrix()
340 {
341         // todo: optimize and only update if necessary
342         double* fl = m_OpenGL_4x4Matrix.getPointer();
343         MT_Transform trans;
344         
345         trans.setOrigin(GetSGNode()->GetWorldPosition());
346         trans.setBasis(GetSGNode()->GetWorldOrientation());
347         
348         MT_Vector3 scaling = GetSGNode()->GetWorldScaling();
349         m_bIsNegativeScaling = ((scaling[0] < 0.0) ^ (scaling[1] < 0.0) ^ (scaling[2] < 0.0)) ? true : false;
350         trans.scale(scaling[0], scaling[1], scaling[2]);
351         trans.getValue(fl);
352
353         return fl;
354 }
355
356
357
358 void KX_GameObject::Bucketize()
359 {
360         double* fl = GetOpenGLMatrix();
361
362         for (size_t i=0;i<m_meshes.size();i++)
363                 m_meshes[i]->Bucketize(fl, this, m_bUseObjectColor, m_objectColor);
364 }
365
366
367
368 void KX_GameObject::RemoveMeshes()
369 {
370         double* fl = GetOpenGLMatrix();
371
372         for (size_t i=0;i<m_meshes.size();i++)
373                 m_meshes[i]->RemoveFromBuckets(fl, this);
374
375         //note: meshes can be shared, and are deleted by KX_BlenderSceneConverter
376
377         m_meshes.clear();
378 }
379
380
381
382 void KX_GameObject::UpdateNonDynas()
383 {
384         if (m_pPhysicsController1)
385         {
386                 m_pPhysicsController1->SetSumoTransform(true);
387         }
388 }
389
390
391
392 void KX_GameObject::UpdateTransform()
393 {
394         if (m_pPhysicsController1)
395                 m_pPhysicsController1->SetSumoTransform(false);
396 }
397
398 void KX_GameObject::UpdateTransformFunc(SG_IObject* node, void* gameobj, void* scene)
399 {
400         ((KX_GameObject*)gameobj)->UpdateTransform();
401 }
402
403
404 void KX_GameObject::SetDebugColor(unsigned int bgra)
405 {
406         for (size_t i=0;i<m_meshes.size();i++)
407                 m_meshes[i]->DebugColor(bgra);  
408 }
409
410
411
412 void KX_GameObject::ResetDebugColor()
413 {
414         SetDebugColor(0xff000000);
415 }
416
417 void KX_GameObject::InitIPO(bool ipo_as_force,
418                                                         bool ipo_add,
419                                                         bool ipo_local)
420 {
421         SGControllerList::iterator it = GetSGNode()->GetSGControllerList().begin();
422
423         while (it != GetSGNode()->GetSGControllerList().end()) {
424                 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_RESET, true);
425                 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_AS_FORCE, ipo_as_force);
426                 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_ADD, ipo_add);
427                 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_LOCAL, ipo_local);
428                 it++;
429         }
430
431
432 void KX_GameObject::UpdateIPO(float curframetime,
433                                                           bool recurse) 
434 {
435         // just the 'normal' update procedure.
436         GetSGNode()->SetSimulatedTime(curframetime,recurse);
437         GetSGNode()->UpdateWorldData(curframetime);
438         UpdateTransform();
439 }
440
441 // IPO update
442 void 
443 KX_GameObject::UpdateMaterialData(
444                 dword matname_hash,
445                 MT_Vector4 rgba,
446                 MT_Vector3 specrgb,
447                 MT_Scalar hard,
448                 MT_Scalar spec,
449                 MT_Scalar ref,
450                 MT_Scalar emit,
451                 MT_Scalar alpha
452
453         )
454 {
455         int mesh = 0;
456
457         if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0) {
458                 RAS_MaterialBucket::Set::iterator mit = m_meshes[mesh]->GetFirstMaterial();
459                 for(; mit != m_meshes[mesh]->GetLastMaterial(); ++mit)
460                 {
461                         RAS_IPolyMaterial* poly = (*mit)->GetPolyMaterial();
462                         if(poly->GetFlag() & RAS_BLENDERMAT)
463                         {
464                                 KX_BlenderMaterial *m =  static_cast<KX_BlenderMaterial*>(poly);
465                                 
466                                 if (matname_hash == NULL)
467                                 {
468                                         m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha);
469                                         // if mesh has only one material attached to it then use original hack with no need to edit vertices (better performance)
470                                         if(!(poly->GetFlag() & RAS_BLENDERGLSL))
471                                                 SetObjectColor(rgba);
472                                 }
473                                 else
474                                 {
475                                         if (matname_hash == poly->GetMaterialNameHash())
476                                         {
477                                                 m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha);
478                                                 m_meshes[mesh]->SetVertexColor(poly,rgba);
479                                                 
480                                                 // no break here, because one blender material can be split into several game engine materials
481                                                 // (e.g. one uvsphere material is split into one material at poles with ras_mode TRIANGLE and one material for the body
482                                                 // if here was a break then would miss some vertices if material was split
483                                         }
484                                 }
485                         }
486                 }
487         }
488 }
489 bool
490 KX_GameObject::GetVisible(
491         void
492         )
493 {
494         return m_bVisible;
495 }
496
497 void
498 KX_GameObject::SetVisible(
499         bool v
500         )
501 {
502         m_bVisible = v;
503 }
504
505 void
506 KX_GameObject::SetLayer(
507         int l
508         )
509 {
510         m_layer = l;
511 }
512
513 int
514 KX_GameObject::GetLayer(
515         void
516         )
517 {
518         return m_layer;
519 }
520
521 // used by Python, and the actuatorshould _not_ be misused by the
522 // scene!
523 void 
524 KX_GameObject::MarkVisible(
525         bool visible
526         )
527 {
528         /* If explicit visibility settings are used, this is
529          * determined on this level. Maybe change this to mesh level
530          * later on? */
531         
532         double* fl = GetOpenGLMatrixPtr()->getPointer();
533         for (size_t i=0;i<m_meshes.size();i++)
534         {
535                 m_meshes[i]->MarkVisible(fl,this,visible,m_bUseObjectColor,m_objectColor);
536         }
537 }
538
539
540 // Always use the flag?
541 void 
542 KX_GameObject::MarkVisible(
543         void
544         )
545 {
546         double* fl = GetOpenGLMatrixPtr()->getPointer();
547         for (size_t i=0;i<m_meshes.size();i++)
548         {
549                 m_meshes[i]->MarkVisible(fl,
550                                          this,
551                                          m_bVisible,
552                                          m_bUseObjectColor,
553                                          m_objectColor
554                         );
555         }
556 }
557
558
559 void KX_GameObject::addLinearVelocity(const MT_Vector3& lin_vel,bool local)
560 {
561         if (m_pPhysicsController1)
562                 m_pPhysicsController1->SetLinearVelocity(lin_vel + m_pPhysicsController1->GetLinearVelocity(),local);
563 }
564
565
566
567 void KX_GameObject::setLinearVelocity(const MT_Vector3& lin_vel,bool local)
568 {
569         if (m_pPhysicsController1)
570                 m_pPhysicsController1->SetLinearVelocity(lin_vel,local);
571 }
572
573
574
575 void KX_GameObject::setAngularVelocity(const MT_Vector3& ang_vel,bool local)
576 {
577         if (m_pPhysicsController1)
578                 m_pPhysicsController1->SetAngularVelocity(ang_vel,local);
579 }
580
581 void KX_GameObject::ResolveCombinedVelocities(
582         const MT_Vector3 & lin_vel,
583         const MT_Vector3 & ang_vel,
584         bool lin_vel_local,
585         bool ang_vel_local
586 ){
587         if (m_pPhysicsController1)
588         {
589
590                 MT_Vector3 lv = lin_vel_local ? NodeGetWorldOrientation() * lin_vel : lin_vel;
591                 MT_Vector3 av = ang_vel_local ? NodeGetWorldOrientation() * ang_vel : ang_vel;
592                 m_pPhysicsController1->resolveCombinedVelocities(
593                         lv.x(),lv.y(),lv.z(),av.x(),av.y(),av.z());
594         }
595 }
596
597
598 void KX_GameObject::SetObjectColor(const MT_Vector4& rgbavec)
599 {
600         m_bUseObjectColor = true;
601         m_objectColor = rgbavec;
602 }
603
604 void KX_GameObject::AlignAxisToVect(const MT_Vector3& dir, int axis, float fac)
605 {
606         MT_Matrix3x3 orimat;
607         MT_Vector3 vect,ori,z,x,y;
608         MT_Scalar len;
609
610         vect = dir;
611         len = vect.length();
612         if (MT_fuzzyZero(len))
613         {
614                 cout << "alignAxisToVect() Error: Null vector!\n";
615                 return;
616         }
617         
618         if (fac<=0.0) {
619                 return;
620         }
621         
622         // normalize
623         vect /= len;
624         orimat = GetSGNode()->GetWorldOrientation();
625         switch (axis)
626         {       
627                 case 0: //x axis
628                         ori = MT_Vector3(orimat[0][2], orimat[1][2], orimat[2][2]); //pivot axis
629                         if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON) //is the vector paralell to the pivot?
630                                 ori = MT_Vector3(orimat[0][1], orimat[1][1], orimat[2][1]); //change the pivot!
631                         if (fac == 1.0) {
632                                 x = vect;
633                         } else {
634                                 x = (vect * fac) + ((orimat * MT_Vector3(1.0, 0.0, 0.0)) * (1-fac));
635                                 len = x.length();
636                                 if (MT_fuzzyZero(len)) x = vect;
637                                 else x /= len;
638                         }
639                         y = ori.cross(x);
640                         z = x.cross(y);
641                         break;
642                 case 1: //y axis
643                         ori = MT_Vector3(orimat[0][0], orimat[1][0], orimat[2][0]);
644                         if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON)
645                                 ori = MT_Vector3(orimat[0][2], orimat[1][2], orimat[2][2]);
646                         if (fac == 1.0) {
647                                 y = vect;
648                         } else {
649                                 y = (vect * fac) + ((orimat * MT_Vector3(0.0, 1.0, 0.0)) * (1-fac));
650                                 len = y.length();
651                                 if (MT_fuzzyZero(len)) y = vect;
652                                 else y /= len;
653                         }
654                         z = ori.cross(y);
655                         x = y.cross(z);
656                         break;
657                 case 2: //z axis
658                         ori = MT_Vector3(orimat[0][1], orimat[1][1], orimat[2][1]);
659                         if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON)
660                                 ori = MT_Vector3(orimat[0][0], orimat[1][0], orimat[2][0]);
661                         if (fac == 1.0) {
662                                 z = vect;
663                         } else {
664                                 z = (vect * fac) + ((orimat * MT_Vector3(0.0, 0.0, 1.0)) * (1-fac));
665                                 len = z.length();
666                                 if (MT_fuzzyZero(len)) z = vect;
667                                 else z /= len;
668                         }
669                         x = ori.cross(z);
670                         y = z.cross(x);
671                         break;
672                 default: //wrong input?
673                         cout << "alignAxisToVect(): Wrong axis '" << axis <<"'\n";
674                         return;
675         }
676         x.normalize(); //normalize the vectors
677         y.normalize();
678         z.normalize();
679         orimat = MT_Matrix3x3(  x[0],y[0],z[0],
680                                                         x[1],y[1],z[1],
681                                                         x[2],y[2],z[2]);
682         if (GetSGNode()->GetSGParent() != NULL)
683         {
684                 // the object is a child, adapt its local orientation so that 
685                 // the global orientation is aligned as we want.
686                 MT_Matrix3x3 invori = GetSGNode()->GetSGParent()->GetWorldOrientation().inverse();
687                 NodeSetLocalOrientation(invori*orimat);
688         }
689         else
690                 NodeSetLocalOrientation(orimat);
691 }
692
693 MT_Scalar KX_GameObject::GetMass()
694 {
695         if (m_pPhysicsController1)
696         {
697                 return m_pPhysicsController1->GetMass();
698         }
699         return 0.0;
700 }
701
702 MT_Vector3 KX_GameObject::GetLinearVelocity(bool local)
703 {
704         MT_Vector3 velocity(0.0,0.0,0.0), locvel;
705         MT_Matrix3x3 ori;
706         if (m_pPhysicsController1)
707         {
708                 velocity = m_pPhysicsController1->GetLinearVelocity();
709                 
710                 if (local)
711                 {
712                         ori = GetSGNode()->GetWorldOrientation();
713                         
714                         locvel = velocity * ori;
715                         return locvel;
716                 }
717         }
718         return velocity;        
719 }
720
721 MT_Vector3 KX_GameObject::GetAngularVelocity(bool local)
722 {
723         MT_Vector3 velocity(0.0,0.0,0.0), locvel;
724         MT_Matrix3x3 ori;
725         if (m_pPhysicsController1)
726         {
727                 velocity = m_pPhysicsController1->GetAngularVelocity();
728                 
729                 if (local)
730                 {
731                         ori = GetSGNode()->GetWorldOrientation();
732                         
733                         locvel = velocity * ori;
734                         return locvel;
735                 }
736         }
737         return velocity;        
738 }
739
740
741
742 // scenegraph node stuff
743
744 void KX_GameObject::NodeSetLocalPosition(const MT_Point3& trans)
745 {
746         if (m_pPhysicsController1 && (!GetSGNode() || !GetSGNode()->GetSGParent()))
747         {
748                 // don't update physic controller if the object is a child:
749                 // 1) the transformation will not be right
750                 // 2) in this case, the physic controller is necessarily a static object
751                 //    that is updated from the normal kinematic synchronization
752                 m_pPhysicsController1->setPosition(trans);
753         }
754
755         if (GetSGNode())
756                 GetSGNode()->SetLocalPosition(trans);
757 }
758
759
760
761 void KX_GameObject::NodeSetLocalOrientation(const MT_Matrix3x3& rot)
762 {
763         if (m_pPhysicsController1 && (!GetSGNode() || !GetSGNode()->GetSGParent()))
764         {
765                 // see note above
766                 m_pPhysicsController1->setOrientation(rot);
767         }
768         if (GetSGNode())
769                 GetSGNode()->SetLocalOrientation(rot);
770 }
771
772
773
774 void KX_GameObject::NodeSetLocalScale(const MT_Vector3& scale)
775 {
776         if (m_pPhysicsController1 && (!GetSGNode() || !GetSGNode()->GetSGParent()))
777         {
778                 // see note above
779                 m_pPhysicsController1->setScaling(scale);
780         }
781         
782         if (GetSGNode())
783                 GetSGNode()->SetLocalScale(scale);
784 }
785
786
787
788 void KX_GameObject::NodeSetRelativeScale(const MT_Vector3& scale)
789 {
790         if (GetSGNode())
791                 GetSGNode()->RelativeScale(scale);
792 }
793
794 void KX_GameObject::NodeSetWorldPosition(const MT_Point3& trans)
795 {
796         SG_Node* parent = m_pSGNode->GetSGParent();
797         if (parent != NULL)
798         {
799                 // Make sure the objects have some scale
800                 MT_Vector3 scale = parent->GetWorldScaling();
801                 if (fabs(scale[0]) < FLT_EPSILON || 
802                         fabs(scale[1]) < FLT_EPSILON || 
803                         fabs(scale[2]) < FLT_EPSILON)
804                 { 
805                         return; 
806                 }
807                 scale[0] = 1.0/scale[0];
808                 scale[1] = 1.0/scale[1];
809                 scale[2] = 1.0/scale[2];
810                 MT_Matrix3x3 invori = parent->GetWorldOrientation().inverse();
811                 MT_Vector3 newpos = invori*(trans-parent->GetWorldPosition())*scale;
812                 NodeSetLocalPosition(MT_Point3(newpos[0],newpos[1],newpos[2]));
813         }
814         else 
815         {
816                 NodeSetLocalPosition(trans);
817         }
818 }
819
820
821 void KX_GameObject::NodeUpdateGS(double time,bool bInitiator)
822 {
823         if (GetSGNode())
824                 GetSGNode()->UpdateWorldData(time);
825 }
826
827
828
829 const MT_Matrix3x3& KX_GameObject::NodeGetWorldOrientation() const
830 {
831         return GetSGNode()->GetWorldOrientation();
832 }
833
834
835
836 const MT_Vector3& KX_GameObject::NodeGetWorldScaling() const
837 {
838         return GetSGNode()->GetWorldScaling();
839 }
840
841
842
843 const MT_Point3& KX_GameObject::NodeGetWorldPosition() const
844 {
845         return GetSGNode()->GetWorldPosition();
846 }
847
848 /* Suspend/ resume: for the dynamic behaviour, there is a simple
849  * method. For the residual motion, there is not. I wonder what the
850  * correct solution is for Sumo. Remove from the motion-update tree?
851  *
852  * So far, only switch the physics and logic.
853  * */
854
855 void KX_GameObject::Resume(void)
856 {
857         if (m_suspended) {
858                 SCA_IObject::Resume();
859                 GetPhysicsController()->RestoreDynamics();
860
861                 m_suspended = false;
862         }
863 }
864
865 void KX_GameObject::Suspend()
866 {
867         if ((!m_ignore_activity_culling) 
868                 && (!m_suspended))  {
869                 SCA_IObject::Suspend();
870                 GetPhysicsController()->SuspendDynamics();
871                 m_suspended = true;
872         }
873 }
874
875
876
877
878 /* ------- python stuff ---------------------------------------------------*/
879
880
881
882
883 PyMethodDef KX_GameObject::Methods[] = {
884         {"getPosition", (PyCFunction) KX_GameObject::sPyGetPosition, METH_NOARGS},
885         {"setPosition", (PyCFunction) KX_GameObject::sPySetPosition, METH_O},
886         {"getLinearVelocity", (PyCFunction) KX_GameObject::sPyGetLinearVelocity, METH_VARARGS},
887         {"setLinearVelocity", (PyCFunction) KX_GameObject::sPySetLinearVelocity, METH_VARARGS},
888         {"getAngularVelocity", (PyCFunction) KX_GameObject::sPyGetAngularVelocity, METH_VARARGS},
889         {"setAngularVelocity", (PyCFunction) KX_GameObject::sPySetAngularVelocity, METH_VARARGS},
890         {"getVelocity", (PyCFunction) KX_GameObject::sPyGetVelocity, METH_VARARGS},
891         {"getMass", (PyCFunction) KX_GameObject::sPyGetMass, METH_NOARGS},
892         {"getReactionForce", (PyCFunction) KX_GameObject::sPyGetReactionForce, METH_NOARGS},
893         {"getOrientation", (PyCFunction) KX_GameObject::sPyGetOrientation, METH_NOARGS},
894         {"setOrientation", (PyCFunction) KX_GameObject::sPySetOrientation, METH_O},
895         {"getVisible",(PyCFunction) KX_GameObject::sPyGetVisible, METH_NOARGS},
896         {"setVisible",(PyCFunction) KX_GameObject::sPySetVisible, METH_O},
897         {"getState",(PyCFunction) KX_GameObject::sPyGetState, METH_NOARGS},
898         {"setState",(PyCFunction) KX_GameObject::sPySetState, METH_O},
899         {"alignAxisToVect",(PyCFunction) KX_GameObject::sPyAlignAxisToVect, METH_VARARGS},
900         {"getAxisVect",(PyCFunction) KX_GameObject::sPyGetAxisVect, METH_O},
901         {"suspendDynamics", (PyCFunction)KX_GameObject::sPySuspendDynamics,METH_NOARGS},
902         {"restoreDynamics", (PyCFunction)KX_GameObject::sPyRestoreDynamics,METH_NOARGS},
903         {"enableRigidBody", (PyCFunction)KX_GameObject::sPyEnableRigidBody,METH_NOARGS},
904         {"disableRigidBody", (PyCFunction)KX_GameObject::sPyDisableRigidBody,METH_NOARGS},
905         {"applyImpulse", (PyCFunction) KX_GameObject::sPyApplyImpulse, METH_VARARGS},
906         {"setCollisionMargin", (PyCFunction) KX_GameObject::sPySetCollisionMargin, METH_O},
907         {"getParent", (PyCFunction)KX_GameObject::sPyGetParent,METH_NOARGS},
908         {"setParent", (PyCFunction)KX_GameObject::sPySetParent,METH_O},
909         {"removeParent", (PyCFunction)KX_GameObject::sPyRemoveParent,METH_NOARGS},
910         {"getChildren", (PyCFunction)KX_GameObject::sPyGetChildren,METH_NOARGS},
911         {"getChildrenRecursive", (PyCFunction)KX_GameObject::sPyGetChildrenRecursive,METH_NOARGS},
912         {"getMesh", (PyCFunction)KX_GameObject::sPyGetMesh,METH_VARARGS},
913         {"getPhysicsId", (PyCFunction)KX_GameObject::sPyGetPhysicsId,METH_NOARGS},
914         {"getPropertyNames", (PyCFunction)KX_GameObject::sPyGetPropertyNames,METH_NOARGS},
915         {"endObject",(PyCFunction) KX_GameObject::sPyEndObject, METH_NOARGS},
916         KX_PYMETHODTABLE(KX_GameObject, rayCastTo),
917         KX_PYMETHODTABLE(KX_GameObject, rayCast),
918         KX_PYMETHODTABLE(KX_GameObject, getDistanceTo),
919         KX_PYMETHODTABLE(KX_GameObject, getVectTo),
920         {NULL,NULL} //Sentinel
921 };
922
923
924
925 /*
926 bool KX_GameObject::ConvertPythonVectorArgs(PyObject* args,
927                                                                                         MT_Vector3& pos,
928                                                                                         MT_Vector3& pos2)
929 {
930         PyObject* pylist;
931         PyObject* pylist2;
932         bool error = (PyArg_ParseTuple(args,"OO",&pylist,&pylist2)) != 0;
933
934         pos = ConvertPythonPylist(pylist);
935         pos2 = ConvertPythonPylist(pylist2);
936                 
937         return error;
938 }
939 */
940
941 PyObject* KX_GameObject::PyEndObject(PyObject* self)
942 {
943
944         KX_Scene *scene = PHY_GetActiveScene();
945         scene->DelayedRemoveObject(this);
946         
947         Py_RETURN_NONE;
948
949 }
950
951
952 PyObject* KX_GameObject::PyGetPosition(PyObject* self)
953 {
954         return PyObjectFrom(NodeGetWorldPosition());
955 }
956
957
958
959 PyTypeObject KX_GameObject::Type = {
960         PyObject_HEAD_INIT(&PyType_Type)
961                 0,
962                 "KX_GameObject",
963                 sizeof(KX_GameObject),
964                 0,
965                 PyDestructor,
966                 0,
967                 __getattr,
968                 __setattr,
969                 0, //&MyPyCompare,
970                 __repr,
971                 0, //&cvalue_as_number,
972                 0,
973                 0,
974                 0,
975                 0
976 };
977
978
979
980 PyParentObject KX_GameObject::Parents[] = {
981         &KX_GameObject::Type,
982                 &SCA_IObject::Type,
983                 &CValue::Type,
984                 NULL
985 };
986
987
988
989
990 PyObject* KX_GameObject::_getattr(const STR_String& attr)
991 {
992         if (m_pPhysicsController1)
993         {
994                 if (attr == "mass")
995                         return PyFloat_FromDouble(GetPhysicsController()->GetMass());
996         }
997
998         if (attr == "parent")
999         {       
1000                 KX_GameObject* parent = GetParent();
1001                 if (parent)
1002                 {
1003                         parent->AddRef();
1004                         return parent;
1005                 }
1006                 Py_RETURN_NONE;
1007         }
1008
1009         if (attr == "visible")
1010                 return PyInt_FromLong(m_bVisible);
1011         
1012         if (attr == "position")
1013                 return PyObjectFrom(NodeGetWorldPosition());
1014         
1015         if (attr == "orientation")
1016                 return PyObjectFrom(NodeGetWorldOrientation());
1017         
1018         if (attr == "scaling")
1019                 return PyObjectFrom(NodeGetWorldScaling());
1020                 
1021         if (attr == "name")
1022                 return PyString_FromString(m_name.ReadPtr());
1023         if (attr == "timeOffset") {
1024                 if (m_pSGNode->GetSGParent()->IsSlowParent()) {
1025                         return PyFloat_FromDouble(static_cast<KX_SlowParentRelation *>(m_pSGNode->GetSGParent()->GetParentRelation())->GetTimeOffset());
1026                 } else {
1027                         return PyFloat_FromDouble(0.0);
1028                 }
1029         }
1030         
1031         
1032         _getattr_up(SCA_IObject);
1033 }
1034
1035 int KX_GameObject::_setattr(const STR_String& attr, PyObject *value)    // _setattr method
1036 {
1037         if (attr == "mass")
1038                 return 1;
1039         
1040         if (attr == "parent")
1041                 return 1;
1042                 
1043         if (PyInt_Check(value))
1044         {
1045                 int val = PyInt_AsLong(value);
1046                 if (attr == "visible")
1047                 {
1048                         SetVisible(val != 0);
1049                         return 0;
1050                 }
1051         }
1052
1053         if (PyFloat_Check(value))
1054         {
1055                 MT_Scalar val = PyFloat_AsDouble(value);
1056                 if (attr == "timeOffset") {
1057                         if (m_pSGNode->GetSGParent() && m_pSGNode->GetSGParent()->IsSlowParent()) {
1058                                 static_cast<KX_SlowParentRelation *>(m_pSGNode->GetSGParent()->GetParentRelation())->SetTimeOffset(val);
1059                                 return 0;
1060                         } else {
1061                                 return 0;
1062                         }               
1063                 }
1064         }
1065         
1066         if (PySequence_Check(value))
1067         {
1068                 if (attr == "orientation")
1069                 {
1070                         MT_Matrix3x3 rot;
1071                         if (PyObject_IsMT_Matrix(value, 3))
1072                         {
1073                                 if (PyMatTo(value, rot))
1074                                 {
1075                                         NodeSetLocalOrientation(rot);
1076                                         NodeUpdateGS(0.f,true);
1077                                         return 0;
1078                                 }
1079                                 return 1;
1080                         }
1081                         
1082                         if (PySequence_Size(value) == 4)
1083                         {
1084                                 MT_Quaternion qrot;
1085                                 if (PyVecTo(value, qrot))
1086                                 {
1087                                         rot.setRotation(qrot);
1088                                         NodeSetLocalOrientation(rot);
1089                                         NodeUpdateGS(0.f,true);
1090                                         return 0;
1091                                 }
1092                                 return 1;
1093                         }
1094                         
1095                         if (PySequence_Size(value) == 3)
1096                         {
1097                                 MT_Vector3 erot;
1098                                 if (PyVecTo(value, erot))
1099                                 {
1100                                         rot.setEuler(erot);
1101                                         NodeSetLocalOrientation(rot);
1102                                         NodeUpdateGS(0.f,true);
1103                                         return 0;
1104                                 }
1105                                 return 1;
1106                         }
1107                         
1108                         return 1;
1109                 }
1110                 
1111                 if (attr == "position")
1112                 {
1113                         MT_Point3 pos;
1114                         if (PyVecTo(value, pos))
1115                         {
1116                                 NodeSetLocalPosition(pos);
1117                                 NodeUpdateGS(0.f,true);
1118                                 return 0;
1119                         }
1120                         return 1;
1121                 }
1122                 
1123                 if (attr == "scaling")
1124                 {
1125                         MT_Vector3 scale;
1126                         if (PyVecTo(value, scale))
1127                         {
1128                                 NodeSetLocalScale(scale);
1129                                 NodeUpdateGS(0.f,true);
1130                                 return 0;
1131                         }
1132                         return 1;
1133                 }
1134         }
1135         
1136         if (PyString_Check(value))
1137         {
1138                 if (attr == "name")
1139                 {
1140                         m_name = PyString_AsString(value);
1141                         return 0;
1142                 }
1143         }
1144         
1145         /* Need to have parent settable here too */
1146         
1147         return SCA_IObject::_setattr(attr, value);
1148 }
1149
1150
1151 PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* self, PyObject* args)
1152 {
1153         // only can get the velocity if we have a physics object connected to us...
1154         int local = 0;
1155         if (PyArg_ParseTuple(args,"|i",&local))
1156         {
1157                 return PyObjectFrom(GetLinearVelocity((local!=0)));
1158         }
1159         else
1160         {
1161                 return NULL;
1162         }
1163 }
1164
1165 PyObject* KX_GameObject::PySetLinearVelocity(PyObject* self, PyObject* args)
1166 {
1167         int local = 0;
1168         PyObject* pyvect;
1169         
1170         if (PyArg_ParseTuple(args,"O|i",&pyvect,&local)) {
1171                 MT_Vector3 velocity;
1172                 if (PyVecTo(pyvect, velocity)) {
1173                         setLinearVelocity(velocity, (local!=0));
1174                         Py_RETURN_NONE;
1175                 }
1176         }
1177         return NULL;
1178 }
1179
1180 PyObject* KX_GameObject::PyGetAngularVelocity(PyObject* self, PyObject* args)
1181 {
1182         // only can get the velocity if we have a physics object connected to us...
1183         int local = 0;
1184         if (PyArg_ParseTuple(args,"|i",&local))
1185         {
1186                 return PyObjectFrom(GetAngularVelocity((local!=0)));
1187         }
1188         else
1189         {
1190                 return NULL;
1191         }
1192 }
1193
1194 PyObject* KX_GameObject::PySetAngularVelocity(PyObject* self, PyObject* args)
1195 {
1196         int local = 0;
1197         PyObject* pyvect;
1198         
1199         if (PyArg_ParseTuple(args,"O|i",&pyvect,&local)) {
1200                 MT_Vector3 velocity;
1201                 if (PyVecTo(pyvect, velocity)) {
1202                         setAngularVelocity(velocity, (local!=0));
1203                         Py_RETURN_NONE;
1204                 }
1205         }
1206         return NULL;
1207 }
1208
1209 PyObject* KX_GameObject::PySetVisible(PyObject* self, PyObject* value)
1210 {
1211         int visible = PyInt_AsLong(value);
1212         
1213         if (visible==-1 && PyErr_Occurred()) {
1214                 PyErr_SetString(PyExc_TypeError, "expected 0 or 1");
1215                 return NULL;
1216         }
1217         
1218         MarkVisible(visible!=0);
1219         m_bVisible = (visible!=0);
1220         Py_RETURN_NONE;
1221         
1222 }
1223
1224 PyObject* KX_GameObject::PyGetVisible(PyObject* self)
1225 {
1226         return PyInt_FromLong(m_bVisible);      
1227 }
1228
1229 PyObject* KX_GameObject::PyGetState(PyObject* self)
1230 {
1231         int state = 0;
1232         state |= GetState();
1233         return PyInt_FromLong(state);
1234 }
1235
1236 PyObject* KX_GameObject::PySetState(PyObject* self, PyObject* value)
1237 {
1238         int state_i = PyInt_AsLong(value);
1239         unsigned int state = 0;
1240         
1241         if (state_i == -1 && PyErr_Occurred()) {
1242                 PyErr_SetString(PyExc_TypeError, "expected an int bit field");
1243                 return NULL;
1244         }
1245         
1246         state |= state_i;
1247         if ((state & ((1<<30)-1)) == 0) {
1248                 PyErr_SetString(PyExc_AttributeError, "The state bitfield was not between 0 and 30 (1<<0 and 1<<29)");
1249                 return NULL;
1250         }
1251         SetState(state);
1252         
1253         Py_RETURN_NONE;
1254 }
1255
1256
1257
1258 PyObject* KX_GameObject::PyGetVelocity(PyObject* self, PyObject* args)
1259 {
1260         // only can get the velocity if we have a physics object connected to us...
1261         MT_Vector3 velocity(0.0,0.0,0.0);
1262         MT_Point3 point(0.0,0.0,0.0);
1263         
1264         
1265         PyObject* pypos = NULL;
1266         if (PyArg_ParseTuple(args, "|O", &pypos))
1267         {
1268                 if (pypos)
1269                         PyVecTo(pypos, point);
1270         }
1271         else {
1272                 return NULL;
1273         }
1274         
1275         if (m_pPhysicsController1)
1276         {
1277                 velocity = m_pPhysicsController1->GetVelocity(point);
1278         }
1279         
1280         return PyObjectFrom(velocity);
1281 }
1282
1283
1284
1285 PyObject* KX_GameObject::PyGetMass(PyObject* self)
1286 {
1287         return PyFloat_FromDouble(GetPhysicsController()->GetMass());
1288 }
1289
1290
1291
1292 PyObject* KX_GameObject::PyGetReactionForce(PyObject* self)
1293 {
1294         // only can get the velocity if we have a physics object connected to us...
1295         return PyObjectFrom(GetPhysicsController()->getReactionForce());
1296 }
1297
1298
1299
1300 PyObject* KX_GameObject::PyEnableRigidBody(PyObject* self)
1301 {
1302         GetPhysicsController()->setRigidBody(true);
1303
1304         Py_RETURN_NONE;
1305 }
1306
1307
1308
1309 PyObject* KX_GameObject::PyDisableRigidBody(PyObject* self)
1310 {
1311         GetPhysicsController()->setRigidBody(false);
1312
1313         Py_RETURN_NONE;
1314 }
1315
1316
1317
1318 PyObject* KX_GameObject::PyGetParent(PyObject* self)
1319 {
1320         KX_GameObject* parent = this->GetParent();
1321         if (parent)
1322         {
1323                 parent->AddRef();
1324                 return parent;
1325         }
1326         Py_RETURN_NONE;
1327 }
1328
1329 PyObject* KX_GameObject::PySetParent(PyObject* self, PyObject* value)
1330 {
1331         if (!PyObject_TypeCheck(value, &KX_GameObject::Type)) {
1332                 PyErr_SetString(PyExc_TypeError, "expected a KX_GameObject type");
1333                 return NULL;
1334         }
1335         
1336         // The object we want to set as parent
1337         CValue *m_ob = (CValue*)value;
1338         KX_GameObject *obj = ((KX_GameObject*)m_ob);
1339         KX_Scene *scene = PHY_GetActiveScene();
1340         
1341         this->SetParent(scene, obj);
1342                 
1343         Py_RETURN_NONE;
1344 }
1345
1346 PyObject* KX_GameObject::PyRemoveParent(PyObject* self)
1347 {
1348         KX_Scene *scene = PHY_GetActiveScene();
1349         this->RemoveParent(scene);
1350         Py_RETURN_NONE;
1351 }
1352
1353
1354 static void walk_children(SG_Node* node, CListValue* list, bool recursive)
1355 {
1356         NodeList& children = node->GetSGChildren();
1357
1358         for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
1359         {
1360                 SG_Node* childnode = (*childit);
1361                 CValue* childobj = (CValue*)childnode->GetSGClientObject();
1362                 if (childobj != NULL) // This is a GameObject
1363                 {
1364                         // add to the list
1365                         list->Add(childobj->AddRef());
1366                 }
1367                 
1368                 // if the childobj is NULL then this may be an inverse parent link
1369                 // so a non recursive search should still look down this node.
1370                 if (recursive || childobj==NULL) {
1371                         walk_children(childnode, list, recursive);
1372                 }
1373         }
1374 }
1375
1376 PyObject* KX_GameObject::PyGetChildren(PyObject* self)
1377 {
1378         CListValue* list = new CListValue();
1379         walk_children(m_pSGNode, list, 0);
1380         return list;
1381 }
1382
1383 PyObject* KX_GameObject::PyGetChildrenRecursive(PyObject* self)
1384 {
1385         CListValue* list = new CListValue();
1386         walk_children(m_pSGNode, list, 1);
1387         return list;
1388 }
1389
1390 PyObject* KX_GameObject::PyGetMesh(PyObject* self, PyObject* args)
1391 {
1392         int mesh = 0;
1393
1394         if (!PyArg_ParseTuple(args, "|i", &mesh))
1395                 return NULL; // python sets a simple error
1396         
1397         if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0)
1398         {
1399                 KX_MeshProxy* meshproxy = new KX_MeshProxy(m_meshes[mesh]);
1400                 return meshproxy;
1401         }
1402         
1403         Py_RETURN_NONE;
1404 }
1405
1406
1407
1408
1409
1410 PyObject* KX_GameObject::PySetCollisionMargin(PyObject* self, PyObject* value)
1411 {
1412         float collisionMargin = PyFloat_AsDouble(value);
1413         
1414         if (collisionMargin==-1 && PyErr_Occurred()) {
1415                 PyErr_SetString(PyExc_TypeError, "expected a float");
1416                 return NULL;
1417         }
1418         
1419         if (m_pPhysicsController1)
1420         {
1421                 m_pPhysicsController1->setMargin(collisionMargin);
1422                 Py_RETURN_NONE;
1423         }
1424         PyErr_SetString(PyExc_RuntimeError, "This object has no physics controller");
1425         return NULL;
1426 }
1427
1428
1429
1430 PyObject* KX_GameObject::PyApplyImpulse(PyObject* self, PyObject* args)
1431 {
1432         PyObject* pyattach;
1433         PyObject* pyimpulse;
1434         
1435         if (!m_pPhysicsController1)     {
1436                 PyErr_SetString(PyExc_RuntimeError, "This object has no physics controller");
1437                 return NULL;
1438         }
1439         
1440         if (PyArg_ParseTuple(args, "OO", &pyattach, &pyimpulse))
1441         {
1442                 MT_Point3  attach;
1443                 MT_Vector3 impulse;
1444                 if (PyVecTo(pyattach, attach) && PyVecTo(pyimpulse, impulse))
1445                 {
1446                         m_pPhysicsController1->applyImpulse(attach, impulse);
1447                         Py_RETURN_NONE;
1448                 }
1449
1450         }
1451         
1452         return NULL;
1453 }
1454
1455
1456
1457 PyObject* KX_GameObject::PySuspendDynamics(PyObject* self)
1458 {
1459         SuspendDynamics();
1460         Py_RETURN_NONE;
1461 }
1462
1463
1464
1465 PyObject* KX_GameObject::PyRestoreDynamics(PyObject* self)
1466 {
1467         RestoreDynamics();
1468         Py_RETURN_NONE;
1469 }
1470
1471
1472
1473 PyObject* KX_GameObject::PyGetOrientation(PyObject* self) //keywords
1474 {
1475         return PyObjectFrom(NodeGetWorldOrientation());
1476 }
1477
1478
1479
1480 PyObject* KX_GameObject::PySetOrientation(PyObject* self, PyObject* value)
1481 {
1482         MT_Matrix3x3 matrix;
1483         if (PyObject_IsMT_Matrix(value, 3) && PyMatTo(value, matrix))
1484         {
1485                 NodeSetLocalOrientation(matrix);
1486                 NodeUpdateGS(0.f,true);
1487                 Py_RETURN_NONE;
1488         }
1489
1490         MT_Quaternion quat;
1491         if (PyVecTo(value, quat))
1492         {
1493                 matrix.setRotation(quat);
1494                 NodeSetLocalOrientation(matrix);
1495                 NodeUpdateGS(0.f,true);
1496                 Py_RETURN_NONE;
1497         }
1498         return NULL;
1499 }
1500
1501 PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* self, PyObject* args)
1502 {
1503         PyObject* pyvect;
1504         int axis = 2; //z axis is the default
1505         float fac = 1.0;
1506         
1507         if (PyArg_ParseTuple(args,"O|if",&pyvect,&axis, &fac))
1508         {
1509                 MT_Vector3 vect;
1510                 if (PyVecTo(pyvect, vect))
1511                 {
1512                         if (fac<=0.0) Py_RETURN_NONE; // Nothing to do.
1513                         if (fac> 1.0) fac= 1.0;
1514                         
1515                         AlignAxisToVect(vect,axis,fac);
1516                         NodeUpdateGS(0.f,true);
1517                         Py_RETURN_NONE;
1518                 }
1519         }
1520         return NULL;
1521 }
1522
1523 PyObject* KX_GameObject::PyGetAxisVect(PyObject* self, PyObject* value)
1524 {
1525         MT_Vector3 vect;
1526         if (PyVecTo(value, vect))
1527         {
1528                 return PyObjectFrom(NodeGetWorldOrientation() * vect);
1529         }
1530         return NULL;
1531 }
1532
1533 PyObject* KX_GameObject::PySetPosition(PyObject* self, PyObject* value)
1534 {
1535         MT_Point3 pos;
1536         if (PyVecTo(value, pos))
1537         {
1538                 NodeSetLocalPosition(pos);
1539                 NodeUpdateGS(0.f,true);
1540                 Py_RETURN_NONE;
1541         }
1542
1543         return NULL;
1544 }
1545
1546 PyObject* KX_GameObject::PyGetPhysicsId(PyObject* self)
1547 {
1548         KX_IPhysicsController* ctrl = GetPhysicsController();
1549         uint_ptr physid=0;
1550         if (ctrl)
1551         {
1552                 physid= (uint_ptr)ctrl->GetUserData();
1553         }
1554         return PyInt_FromLong((long)physid);
1555 }
1556
1557 PyObject* KX_GameObject::PyGetPropertyNames(PyObject* self)
1558 {
1559         return ConvertKeysToPython();
1560 }
1561
1562 KX_PYMETHODDEF_DOC(KX_GameObject, getDistanceTo,
1563 "getDistanceTo(other): get distance to another point/KX_GameObject")
1564 {
1565         MT_Point3 b;
1566         if (PyVecArgTo(args, b))
1567         {
1568                 return PyFloat_FromDouble(NodeGetWorldPosition().distance(b));
1569         }
1570         PyErr_Clear();
1571         
1572         PyObject *pyother;
1573         KX_GameObject *other;
1574         if (PyArg_ParseTuple(args, "O", &pyother) && ConvertPythonToGameObject(pyother, &other, false))
1575         {
1576                 return PyFloat_FromDouble(NodeGetWorldPosition().distance(other->NodeGetWorldPosition()));
1577         }
1578         
1579         return NULL;
1580 }
1581
1582 KX_PYMETHODDEF_DOC(KX_GameObject, getVectTo,
1583 "getVectTo(other): get vector and the distance to another point/KX_GameObject\n"
1584 "Returns a 3-tuple with (distance,worldVector,localVector)\n")
1585 {
1586         MT_Point3 toPoint, fromPoint;
1587         MT_Vector3 toDir, locToDir;
1588         MT_Scalar distance;
1589
1590         PyObject *returnValue;
1591         PyObject *pyother;
1592
1593         if (!PyVecArgTo(args, toPoint))
1594         {
1595                 PyErr_Clear();
1596                 
1597                 KX_GameObject *other;
1598                 if (PyArg_ParseTuple(args, "O", &pyother) && ConvertPythonToGameObject(pyother, &other, false))
1599                 {
1600                         toPoint = other->NodeGetWorldPosition();
1601                 } else
1602                 {
1603                         PyErr_SetString(PyExc_TypeError, "Expected a 3D Vector or GameObject type");
1604                         return NULL;
1605                 }
1606         }
1607
1608         fromPoint = NodeGetWorldPosition();
1609         toDir = toPoint-fromPoint;
1610         distance = toDir.length();
1611
1612         if (MT_fuzzyZero(distance))
1613         {
1614                 //cout << "getVectTo() Error: Null vector!\n";
1615                 locToDir = toDir = MT_Vector3(0.0,0.0,0.0);
1616                 distance = 0.0;
1617         } else {
1618                 toDir.normalize();
1619                 locToDir = toDir * NodeGetWorldOrientation();
1620         }
1621         
1622         returnValue = PyTuple_New(3);
1623         if (returnValue) { // very unlikely to fail, python sets a memory error here.
1624                 PyTuple_SET_ITEM(returnValue, 0, PyFloat_FromDouble(distance));
1625                 PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(toDir));
1626                 PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(locToDir));
1627         }
1628         return returnValue;
1629 }
1630
1631 bool KX_GameObject::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data)
1632 {
1633
1634         KX_GameObject* hitKXObj = client->m_gameobject;
1635         
1636         if (client->m_type > KX_ClientObjectInfo::ACTOR)
1637         {
1638                 // false hit
1639                 return false;
1640         }
1641
1642         if (m_testPropName.Length() == 0 || hitKXObj->GetProperty(m_testPropName) != NULL)
1643         {
1644                 m_pHitObject = hitKXObj;
1645                 return true;
1646         }
1647
1648         return false;
1649         
1650 }
1651
1652 KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo,
1653 "rayCastTo(other,dist,prop): look towards another point/KX_GameObject and return first object hit within dist that matches prop\n"
1654 " prop = property name that object must have; can be omitted => detect any object\n"
1655 " dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to other\n"
1656 " other = 3-tuple or object reference")
1657 {
1658         MT_Point3 toPoint;
1659         PyObject* pyarg;
1660         float dist = 0.0f;
1661         char *propName = NULL;
1662
1663         if (!PyArg_ParseTuple(args,"O|fs", &pyarg, &dist, &propName)) {
1664                 return NULL; // python sets simple error
1665         }
1666
1667         if (!PyVecTo(pyarg, toPoint))
1668         {
1669                 KX_GameObject *other;
1670                 PyErr_Clear();
1671                 
1672                 if (ConvertPythonToGameObject(pyarg, &other, false))
1673                 {
1674                         toPoint = other->NodeGetWorldPosition();
1675                 } else
1676                 {
1677                         PyErr_SetString(PyExc_TypeError, "the first argument to rayCastTo must be a vector or a KX_GameObject");
1678                         return NULL;
1679                 }
1680         }
1681         MT_Point3 fromPoint = NodeGetWorldPosition();
1682         if (dist != 0.0f)
1683         {
1684                 MT_Vector3 toDir = toPoint-fromPoint;
1685                 toDir.normalize();
1686                 toPoint = fromPoint + (dist) * toDir;
1687         }
1688
1689         MT_Point3 resultPoint;
1690         MT_Vector3 resultNormal;
1691         PHY_IPhysicsEnvironment* pe = GetPhysicsEnvironment();
1692         KX_IPhysicsController *spc = GetPhysicsController();
1693         KX_GameObject *parent = GetParent();
1694         if (!spc && parent)
1695                 spc = parent->GetPhysicsController();
1696         if (parent)
1697                 parent->Release();
1698         
1699         m_pHitObject = NULL;
1700         if (propName)
1701                 m_testPropName = propName;
1702         else
1703                 m_testPropName.SetLength(0);
1704         KX_RayCast::RayTest(spc, pe, fromPoint, toPoint, resultPoint, resultNormal, KX_RayCast::Callback<KX_GameObject>(this));
1705
1706     if (m_pHitObject)
1707         {
1708                 m_pHitObject->AddRef();
1709                 return m_pHitObject;
1710         }
1711         Py_RETURN_NONE;
1712 }
1713
1714 KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
1715                                    "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,None,None) tuple if no hit\n"
1716 " prop = property name that object must have; can be omitted => detect any object\n"
1717 " dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to to\n"
1718 " from = 3-tuple or object reference for origin of ray (if object, use center of object)\n"
1719 "        Can be None or omitted => start from self object center\n"
1720 " to = 3-tuple or object reference for destination of ray (if object, use center of object)\n"
1721 "Note: the object on which you call this method matters: the ray will ignore it if it goes through it\n")
1722 {
1723         MT_Point3 toPoint;
1724         MT_Point3 fromPoint;
1725         PyObject* pyto;
1726         PyObject* pyfrom = NULL;
1727         float dist = 0.0f;
1728         char *propName = NULL;
1729         KX_GameObject *other;
1730
1731         if (!PyArg_ParseTuple(args,"O|Ofs", &pyto, &pyfrom, &dist, &propName)) {
1732                 return NULL; // Python sets a simple error
1733         }
1734
1735         if (!PyVecTo(pyto, toPoint))
1736         {
1737                 PyErr_Clear();
1738                 
1739                 if (ConvertPythonToGameObject(pyto, &other, false))
1740                 {
1741                         toPoint = other->NodeGetWorldPosition();
1742                 } else
1743                 {
1744                         PyErr_SetString(PyExc_TypeError, "the first argument to rayCast must be a vector or a KX_GameObject");
1745                         return NULL;
1746                 }
1747         }
1748         if (!pyfrom || pyfrom == Py_None)
1749         {
1750                 fromPoint = NodeGetWorldPosition();
1751         }
1752         else if (!PyVecTo(pyfrom, fromPoint))
1753         {
1754                 PyErr_Clear();
1755                 
1756                 if (ConvertPythonToGameObject(pyfrom, &other, false))
1757                 {
1758                         fromPoint = other->NodeGetWorldPosition();
1759                 } else
1760                 {
1761                         PyErr_SetString(PyExc_TypeError, "the second optional argument to rayCast must be a vector or a KX_GameObject");
1762                         return NULL;
1763                 }
1764         }
1765         
1766         if (dist != 0.0f) {
1767                 MT_Vector3 toDir = toPoint-fromPoint;
1768                 if (MT_fuzzyZero(toDir.length2())) {
1769                         return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
1770                 }
1771                 toDir.normalize();
1772                 toPoint = fromPoint + (dist) * toDir;
1773         } else if (MT_fuzzyZero((toPoint-fromPoint).length2())) {
1774                 return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
1775         }
1776         
1777         MT_Point3 resultPoint;
1778         MT_Vector3 resultNormal;
1779         PHY_IPhysicsEnvironment* pe = GetPhysicsEnvironment();
1780         KX_IPhysicsController *spc = GetPhysicsController();
1781         KX_GameObject *parent = GetParent();
1782         if (!spc && parent)
1783                 spc = parent->GetPhysicsController();
1784         if (parent)
1785                 parent->Release();
1786         
1787         m_pHitObject = NULL;
1788         if (propName)
1789                 m_testPropName = propName;
1790         else
1791                 m_testPropName.SetLength(0);
1792         KX_RayCast::RayTest(spc, pe, fromPoint, toPoint, resultPoint, resultNormal, KX_RayCast::Callback<KX_GameObject>(this));
1793
1794     if (m_pHitObject)
1795         {
1796                 PyObject* returnValue = PyTuple_New(3);
1797                 if (returnValue) { // unlikely this would ever fail, if it does python sets an error
1798                         PyTuple_SET_ITEM(returnValue, 0, m_pHitObject->AddRef());
1799                         PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(resultPoint));
1800                         PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(resultNormal));
1801                 }
1802                 return returnValue;
1803         }
1804         return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
1805         //Py_RETURN_NONE;
1806 }
1807
1808 /* --------------------------------------------------------------------- 
1809  * Some stuff taken from the header
1810  * --------------------------------------------------------------------- */
1811 void KX_GameObject::Relink(GEN_Map<GEN_HashedPtr, void*> *map_parameter)        
1812 {
1813         // we will relink the sensors and actuators that use object references
1814         // if the object is part of the replicated hierarchy, use the new
1815         // object reference instead
1816         SCA_SensorList& sensorlist = GetSensors();
1817         SCA_SensorList::iterator sit;
1818         for (sit=sensorlist.begin(); sit != sensorlist.end(); sit++)
1819         {
1820                 (*sit)->Relink(map_parameter);
1821         }
1822         SCA_ActuatorList& actuatorlist = GetActuators();
1823         SCA_ActuatorList::iterator ait;
1824         for (ait=actuatorlist.begin(); ait != actuatorlist.end(); ait++)
1825         {
1826                 (*ait)->Relink(map_parameter);
1827         }
1828 }
1829
1830 bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py_none_ok)
1831 {
1832         if (value==NULL) {
1833                 PyErr_SetString(PyExc_TypeError, "Error in ConvertPythonToGameObject, python pointer NULL, should never happen");
1834                 *object = NULL;
1835                 return false;
1836         }
1837                 
1838         if (value==Py_None) {
1839                 *object = NULL;
1840                 
1841                 if (py_none_ok) {
1842                         return true;
1843                 } else {
1844                         PyErr_SetString(PyExc_TypeError, "Expected KX_GameObject or a string for a name of a KX_GameObject, None is invalid");
1845                         return false;
1846                 }
1847                 return (py_none_ok ? true : false);
1848         }
1849         
1850         if (PyString_Check(value)) {
1851                 *object = (KX_GameObject *)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String( PyString_AsString(value) ));
1852                 
1853                 if (*object) {
1854                         return true;
1855                 } else {
1856                         PyErr_SetString(PyExc_ValueError, "Requested name did not match any KX_GameObject");
1857                         return false;
1858                 }
1859         }
1860         
1861         if (PyObject_TypeCheck(value, &KX_GameObject::Type)) {
1862                 *object = static_cast<KX_GameObject*>(value);
1863                 return true;
1864         }
1865         
1866         *object = NULL;
1867         
1868         if (py_none_ok) {
1869                 PyErr_SetString(PyExc_TypeError, "Expect a KX_GameObject, a string or None");
1870         } else {
1871                 PyErr_SetString(PyExc_TypeError, "Expect a KX_GameObject or a string");
1872         }
1873         
1874         return false;
1875 }