deprecate controller.getActuator(name) and controller.getSensor(name) for
[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 "KX_PolyProxy.h"
55 #include <stdio.h> // printf
56 #include "SG_Controller.h"
57 #include "KX_IPhysicsController.h"
58 #include "PHY_IGraphicController.h"
59 #include "SG_Node.h"
60 #include "SG_Controller.h"
61 #include "KX_ClientObjectInfo.h"
62 #include "RAS_BucketManager.h"
63 #include "KX_RayCast.h"
64 #include "KX_PythonInit.h"
65 #include "KX_PyMath.h"
66 #include "KX_PythonSeq.h"
67 #include "SCA_IActuator.h"
68 #include "SCA_ISensor.h"
69 #include "SCA_IController.h"
70 #include "NG_NetworkScene.h" //Needed for sendMessage()
71
72 #include "PyObjectPlus.h" /* python stuff */
73
74 // This file defines relationships between parents and children
75 // in the game engine.
76
77 #include "KX_SG_NodeRelationships.h"
78
79 static MT_Point3 dummy_point= MT_Point3(0.0, 0.0, 0.0);
80 static MT_Vector3 dummy_scaling = MT_Vector3(1.0, 1.0, 1.0);
81 static MT_Matrix3x3 dummy_orientation = MT_Matrix3x3(   1.0, 0.0, 0.0,
82                                                                                                                 0.0, 1.0, 0.0,
83                                                                                                                 0.0, 0.0, 1.0);
84
85 KX_GameObject::KX_GameObject(
86         void* sgReplicationInfo,
87         SG_Callbacks callbacks,
88         PyTypeObject* T
89 ) : 
90         SCA_IObject(T),
91         m_bDyna(false),
92         m_layer(0),
93         m_pBlenderObject(NULL),
94         m_pBlenderGroupObject(NULL),
95         m_bSuspendDynamics(false),
96         m_bUseObjectColor(false),
97         m_bIsNegativeScaling(false),
98         m_bVisible(true),
99         m_bCulled(true),
100         m_bOccluder(false),
101         m_pPhysicsController1(NULL),
102         m_pGraphicController(NULL),
103         m_pPhysicsEnvironment(NULL),
104         m_xray(false),
105         m_pHitObject(NULL),
106         m_isDeformable(false),
107         m_attr_dict(NULL)
108 {
109         m_ignore_activity_culling = false;
110         m_pClient_info = new KX_ClientObjectInfo(this, KX_ClientObjectInfo::ACTOR);
111         m_pSGNode = new SG_Node(this,sgReplicationInfo,callbacks);
112
113         // define the relationship between this node and it's parent.
114         
115         KX_NormalParentRelation * parent_relation = 
116                 KX_NormalParentRelation::New();
117         m_pSGNode->SetParentRelation(parent_relation);
118 };
119
120
121
122 KX_GameObject::~KX_GameObject()
123 {
124         RemoveMeshes();
125
126         // is this delete somewhere ?
127         //if (m_sumoObj)
128         //      delete m_sumoObj;
129         delete m_pClient_info;
130         //if (m_pSGNode)
131         //      delete m_pSGNode;
132         if (m_pSGNode)
133         {
134                 // must go through controllers and make sure they will not use us anymore
135                 // This is important for KX_BulletPhysicsControllers that unregister themselves
136                 // from the object when they are deleted.
137                 SGControllerList::iterator contit;
138                 SGControllerList& controllers = m_pSGNode->GetSGControllerList();
139                 for (contit = controllers.begin();contit!=controllers.end();++contit)
140                 {
141                         (*contit)->ClearObject();
142                 }
143                 m_pSGNode->SetSGClientObject(NULL);
144         }
145         if (m_pGraphicController)
146         {
147                 delete m_pGraphicController;
148         }
149         
150         if (m_attr_dict) {
151                 PyDict_Clear(m_attr_dict); /* incase of circular refs or other weired cases */
152                 Py_DECREF(m_attr_dict);
153         }
154 }
155
156 KX_GameObject* KX_GameObject::GetClientObject(KX_ClientObjectInfo* info)
157 {
158         if (!info)
159                 return NULL;
160         return info->m_gameobject;
161 }
162
163 CValue* KX_GameObject:: Calc(VALUE_OPERATOR op, CValue *val) 
164 {
165         return NULL;
166 }
167
168
169
170 CValue* KX_GameObject::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val)
171 {
172         return NULL;
173 }
174
175
176
177 const STR_String & KX_GameObject::GetText()
178 {
179         return m_text;
180 }
181
182
183
184 double KX_GameObject::GetNumber()
185 {
186         return 0;
187 }
188
189
190
191 STR_String KX_GameObject::GetName()
192 {
193         return m_name;
194 }
195
196
197
198 void KX_GameObject::SetName(STR_String name)
199 {
200         m_name = name;
201 };                                                              // Set the name of the value
202
203 KX_IPhysicsController* KX_GameObject::GetPhysicsController()
204 {
205         return m_pPhysicsController1;
206 }
207
208 KX_GameObject* KX_GameObject::GetParent()
209 {
210         KX_GameObject* result = NULL;
211         SG_Node* node = m_pSGNode;
212         
213         while (node && !result)
214         {
215                 node = node->GetSGParent();
216                 if (node)
217                         result = (KX_GameObject*)node->GetSGClientObject();
218         }
219         
220         if (result)
221                 result->AddRef();
222
223         return result;
224         
225 }
226
227 void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj)
228 {
229         // check on valid node in case a python controller holds a reference to a deleted object
230         if (obj && GetSGNode() && obj->GetSGNode() && GetSGNode()->GetSGParent() != obj->GetSGNode())
231         {
232                 // Make sure the objects have some scale
233                 MT_Vector3 scale1 = NodeGetWorldScaling();
234                 MT_Vector3 scale2 = obj->NodeGetWorldScaling();
235                 if (fabs(scale2[0]) < FLT_EPSILON || 
236                         fabs(scale2[1]) < FLT_EPSILON || 
237                         fabs(scale2[2]) < FLT_EPSILON || 
238                         fabs(scale1[0]) < FLT_EPSILON || 
239                         fabs(scale1[1]) < FLT_EPSILON || 
240                         fabs(scale1[2]) < FLT_EPSILON) { return; }
241
242                 // Remove us from our old parent and set our new parent
243                 RemoveParent(scene);
244                 obj->GetSGNode()->AddChild(GetSGNode());
245
246                 if (m_pPhysicsController1) 
247                 {
248                         m_pPhysicsController1->SuspendDynamics(true);
249                 }
250                 // Set us to our new scale, position, and orientation
251                 scale2[0] = 1.0/scale2[0];
252                 scale2[1] = 1.0/scale2[1];
253                 scale2[2] = 1.0/scale2[2];
254                 scale1 = scale1 * scale2;
255                 MT_Matrix3x3 invori = obj->NodeGetWorldOrientation().inverse();
256                 MT_Vector3 newpos = invori*(NodeGetWorldPosition()-obj->NodeGetWorldPosition())*scale2;
257
258                 NodeSetLocalScale(scale1);
259                 NodeSetLocalPosition(MT_Point3(newpos[0],newpos[1],newpos[2]));
260                 NodeSetLocalOrientation(invori*NodeGetWorldOrientation());
261                 NodeUpdateGS(0.f);
262                 // object will now be a child, it must be removed from the parent list
263                 CListValue* rootlist = scene->GetRootParentList();
264                 if (rootlist->RemoveValue(this))
265                         // the object was in parent list, decrement ref count as it's now removed
266                         Release();
267                 // if the new parent is a compound object, add this object shape to the compound shape.
268                 // step 0: verify this object has physical controller
269                 if (m_pPhysicsController1)
270                 {
271                         // step 1: find the top parent (not necessarily obj)
272                         KX_GameObject* rootobj = (KX_GameObject*)obj->GetSGNode()->GetRootSGParent()->GetSGClientObject();
273                         // step 2: verify it has a physical controller and compound shape
274                         if (rootobj != NULL && 
275                                 rootobj->m_pPhysicsController1 != NULL &&
276                                 rootobj->m_pPhysicsController1->IsCompound())
277                         {
278                                 rootobj->m_pPhysicsController1->AddCompoundChild(m_pPhysicsController1);
279                         }
280                 }
281                 // graphically, the object hasn't change place, no need to update m_pGraphicController
282         }
283 }
284
285 void KX_GameObject::RemoveParent(KX_Scene *scene)
286 {
287         // check on valid node in case a python controller holds a reference to a deleted object
288         if (GetSGNode() && GetSGNode()->GetSGParent())
289         {
290                 // get the root object to remove us from compound object if needed
291                 KX_GameObject* rootobj = (KX_GameObject*)GetSGNode()->GetRootSGParent()->GetSGClientObject();
292                 // Set us to the right spot 
293                 GetSGNode()->SetLocalScale(GetSGNode()->GetWorldScaling());
294                 GetSGNode()->SetLocalOrientation(GetSGNode()->GetWorldOrientation());
295                 GetSGNode()->SetLocalPosition(GetSGNode()->GetWorldPosition());
296
297                 // Remove us from our parent
298                 GetSGNode()->DisconnectFromParent();
299                 NodeUpdateGS(0.f);
300                 // the object is now a root object, add it to the parentlist
301                 CListValue* rootlist = scene->GetRootParentList();
302                 if (!rootlist->SearchValue(this))
303                         // object was not in root list, add it now and increment ref count
304                         rootlist->Add(AddRef());
305                 if (m_pPhysicsController1) 
306                 {
307                         // in case this controller was added as a child shape to the parent
308                         if (rootobj != NULL && 
309                                 rootobj->m_pPhysicsController1 != NULL &&
310                                 rootobj->m_pPhysicsController1->IsCompound())
311                         {
312                                 rootobj->m_pPhysicsController1->RemoveCompoundChild(m_pPhysicsController1);
313                         }
314                         m_pPhysicsController1->RestoreDynamics();
315                 }
316                 // graphically, the object hasn't change place, no need to update m_pGraphicController
317         }
318 }
319
320 void KX_GameObject::ProcessReplica()
321 {
322         SCA_IObject::ProcessReplica();
323         
324         m_pPhysicsController1 = NULL;
325         m_pGraphicController = NULL;
326         m_pSGNode = NULL;
327         m_pClient_info = new KX_ClientObjectInfo(*m_pClient_info);
328         m_pClient_info->m_gameobject = this;
329         m_state = 0;
330         if(m_attr_dict)
331                 m_attr_dict= PyDict_Copy(m_attr_dict);
332                 
333 }
334
335 static void setGraphicController_recursive(SG_Node* node, bool v)
336 {
337         NodeList& children = node->GetSGChildren();
338
339         for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
340         {
341                 SG_Node* childnode = (*childit);
342                 KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject());
343                 if (clientgameobj != NULL) // This is a GameObject
344                         clientgameobj->ActivateGraphicController(v, false);
345                 
346                 // if the childobj is NULL then this may be an inverse parent link
347                 // so a non recursive search should still look down this node.
348                 setGraphicController_recursive(childnode, v);
349         }
350 }
351
352
353 void KX_GameObject::ActivateGraphicController(bool active, bool recurse)
354 {
355         if (m_pGraphicController)
356         {
357                 m_pGraphicController->Activate(active);
358         }
359         if (recurse)
360         {
361                 setGraphicController_recursive(GetSGNode(), active);
362         }
363 }
364
365
366 CValue* KX_GameObject::GetReplica()
367 {
368         KX_GameObject* replica = new KX_GameObject(*this);
369
370         // this will copy properties and so on...
371         replica->ProcessReplica();
372
373         return replica;
374 }
375
376
377
378 void KX_GameObject::ApplyForce(const MT_Vector3& force,bool local)
379 {
380         if (m_pPhysicsController1)
381                 m_pPhysicsController1->ApplyForce(force,local);
382 }
383
384
385
386 void KX_GameObject::ApplyTorque(const MT_Vector3& torque,bool local)
387 {
388         if (m_pPhysicsController1)
389                 m_pPhysicsController1->ApplyTorque(torque,local);
390 }
391
392
393
394 void KX_GameObject::ApplyMovement(const MT_Vector3& dloc,bool local)
395 {
396         if (GetSGNode()) 
397         {
398                 if (m_pPhysicsController1) // (IsDynamic())
399                 {
400                         m_pPhysicsController1->RelativeTranslate(dloc,local);
401                 }
402                 GetSGNode()->RelativeTranslate(dloc,GetSGNode()->GetSGParent(),local);
403         }
404 }
405
406
407
408 void KX_GameObject::ApplyRotation(const MT_Vector3& drot,bool local)
409 {
410         MT_Matrix3x3 rotmat(drot);
411         
412         if (GetSGNode()) {
413                 GetSGNode()->RelativeRotate(rotmat,local);
414
415                 if (m_pPhysicsController1) { // (IsDynamic())
416                         m_pPhysicsController1->RelativeRotate(rotmat,local); 
417                 }
418         }
419 }
420
421
422
423 /**
424 GetOpenGL Matrix, returns an OpenGL 'compatible' matrix
425 */
426 double* KX_GameObject::GetOpenGLMatrix()
427 {
428         // todo: optimize and only update if necessary
429         double* fl = m_OpenGL_4x4Matrix.getPointer();
430         if (GetSGNode()) {
431                 MT_Transform trans;
432         
433                 trans.setOrigin(GetSGNode()->GetWorldPosition());
434                 trans.setBasis(GetSGNode()->GetWorldOrientation());
435         
436                 MT_Vector3 scaling = GetSGNode()->GetWorldScaling();
437                 m_bIsNegativeScaling = ((scaling[0] < 0.0) ^ (scaling[1] < 0.0) ^ (scaling[2] < 0.0)) ? true : false;
438                 trans.scale(scaling[0], scaling[1], scaling[2]);
439                 trans.getValue(fl);
440                 GetSGNode()->ClearDirty();
441         }
442         return fl;
443 }
444
445 void KX_GameObject::AddMeshUser()
446 {
447         for (size_t i=0;i<m_meshes.size();i++)
448         {
449                 m_meshes[i]->AddMeshUser(this, &m_meshSlots);
450         }
451         // set the part of the mesh slot that never change
452         double* fl = GetOpenGLMatrixPtr()->getPointer();
453         RAS_Deformer *deformer = GetDeformer();
454
455         //RAS_MeshSlot *ms;
456         //for(ms =static_cast<RAS_MeshSlot*>(m_meshSlots.QPeek());
457         //      ms!=static_cast<RAS_MeshSlot*>(m_meshSlots.Self());
458         //      ms =static_cast<RAS_MeshSlot*>(ms->QPeek()))
459         //{
460         //      ms->m_OpenGLMatrix = fl;
461         //      ms->SetDeformer(deformer);
462         //}
463         SG_QList::iterator<RAS_MeshSlot> mit(m_meshSlots);
464         for(mit.begin(); !mit.end(); ++mit)
465         {
466                 (*mit)->m_OpenGLMatrix = fl;
467                 (*mit)->SetDeformer(deformer);
468         }
469         UpdateBuckets(false);
470 }
471
472 static void UpdateBuckets_recursive(SG_Node* node)
473 {
474         NodeList& children = node->GetSGChildren();
475
476         for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
477         {
478                 SG_Node* childnode = (*childit);
479                 KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject());
480                 if (clientgameobj != NULL) // This is a GameObject
481                         clientgameobj->UpdateBuckets(0);
482                 
483                 // if the childobj is NULL then this may be an inverse parent link
484                 // so a non recursive search should still look down this node.
485                 UpdateBuckets_recursive(childnode);
486         }
487 }
488
489 void KX_GameObject::UpdateBuckets( bool recursive )
490 {
491         if (GetSGNode()) {
492                 RAS_MeshSlot *ms;
493
494                 if (GetSGNode()->IsDirty())
495                         GetOpenGLMatrix();
496                 //for(ms =static_cast<RAS_MeshSlot*>(m_meshSlots.QPeek());
497                 //    ms!=static_cast<RAS_MeshSlot*>(m_meshSlots.Self());
498                 //    ms =static_cast<RAS_MeshSlot*>(ms->QPeek()))
499                 SG_QList::iterator<RAS_MeshSlot> mit(m_meshSlots);
500                 for(mit.begin(); !mit.end(); ++mit)
501                 {
502                         ms = *mit;
503                         ms->m_bObjectColor = m_bUseObjectColor;
504                         ms->m_RGBAcolor = m_objectColor;
505                         ms->m_bVisible = m_bVisible;
506                         ms->m_bCulled = m_bCulled || !m_bVisible;
507                         if (!ms->m_bCulled) 
508                                 ms->m_bucket->ActivateMesh(ms);
509                         
510                         /* split if necessary */
511 #ifdef USE_SPLIT
512                         ms->Split();
513 #endif
514                 }
515         
516                 if (recursive) {
517                         UpdateBuckets_recursive(GetSGNode());
518                 }
519         }
520 }
521
522 void KX_GameObject::RemoveMeshes()
523 {
524         for (size_t i=0;i<m_meshes.size();i++)
525                 m_meshes[i]->RemoveFromBuckets(this);
526
527         //note: meshes can be shared, and are deleted by KX_BlenderSceneConverter
528
529         m_meshes.clear();
530 }
531
532 void KX_GameObject::UpdateTransform()
533 {
534         // HACK: saves function call for dynamic object, they are handled differently
535         if (m_pPhysicsController1 && !m_pPhysicsController1->IsDyna())
536                 // Note that for Bullet, this does not even update the transform of static object
537                 // but merely sets there collision flag to "kinematic" because the synchronization is 
538                 // done during physics simulation
539                 m_pPhysicsController1->SetSumoTransform(true);
540         if (m_pGraphicController)
541                 // update the culling tree
542                 m_pGraphicController->SetGraphicTransform();
543
544 }
545
546 void KX_GameObject::UpdateTransformFunc(SG_IObject* node, void* gameobj, void* scene)
547 {
548         ((KX_GameObject*)gameobj)->UpdateTransform();
549 }
550
551
552 void KX_GameObject::SetDebugColor(unsigned int bgra)
553 {
554         for (size_t i=0;i<m_meshes.size();i++)
555                 m_meshes[i]->DebugColor(bgra);  
556 }
557
558
559
560 void KX_GameObject::ResetDebugColor()
561 {
562         SetDebugColor(0xff000000);
563 }
564
565 void KX_GameObject::InitIPO(bool ipo_as_force,
566                                                         bool ipo_add,
567                                                         bool ipo_local)
568 {
569         SGControllerList::iterator it = GetSGNode()->GetSGControllerList().begin();
570
571         while (it != GetSGNode()->GetSGControllerList().end()) {
572                 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_RESET, true);
573                 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_AS_FORCE, ipo_as_force);
574                 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_ADD, ipo_add);
575                 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_LOCAL, ipo_local);
576                 it++;
577         }
578
579
580 void KX_GameObject::UpdateIPO(float curframetime,
581                                                           bool recurse) 
582 {
583         // just the 'normal' update procedure.
584         GetSGNode()->SetSimulatedTime(curframetime,recurse);
585         GetSGNode()->UpdateWorldData(curframetime);
586         UpdateTransform();
587 }
588
589 // IPO update
590 void 
591 KX_GameObject::UpdateMaterialData(
592                 dword matname_hash,
593                 MT_Vector4 rgba,
594                 MT_Vector3 specrgb,
595                 MT_Scalar hard,
596                 MT_Scalar spec,
597                 MT_Scalar ref,
598                 MT_Scalar emit,
599                 MT_Scalar alpha
600
601         )
602 {
603         int mesh = 0;
604         if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0) {
605                 list<RAS_MeshMaterial>::iterator mit = m_meshes[mesh]->GetFirstMaterial();
606
607                 for(; mit != m_meshes[mesh]->GetLastMaterial(); ++mit)
608                 {
609                         RAS_IPolyMaterial* poly = mit->m_bucket->GetPolyMaterial();
610
611                         if(poly->GetFlag() & RAS_BLENDERMAT )
612                         {
613                                 KX_BlenderMaterial *m =  static_cast<KX_BlenderMaterial*>(poly);
614                                 
615                                 if (matname_hash == 0)
616                                 {
617                                         m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha);
618                                         // if mesh has only one material attached to it then use original hack with no need to edit vertices (better performance)
619                                         SetObjectColor(rgba);
620                                 }
621                                 else
622                                 {
623                                         if (matname_hash == poly->GetMaterialNameHash())
624                                         {
625                                                 m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha);
626                                                 m_meshes[mesh]->SetVertexColor(poly,rgba);
627                                                 
628                                                 // no break here, because one blender material can be split into several game engine materials
629                                                 // (e.g. one uvsphere material is split into one material at poles with ras_mode TRIANGLE and one material for the body
630                                                 // if here was a break then would miss some vertices if material was split
631                                         }
632                                 }
633                         }
634                 }
635         }
636 }
637 bool
638 KX_GameObject::GetVisible(
639         void
640         )
641 {
642         return m_bVisible;
643 }
644
645 static void setVisible_recursive(SG_Node* node, bool v)
646 {
647         NodeList& children = node->GetSGChildren();
648
649         for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
650         {
651                 SG_Node* childnode = (*childit);
652                 KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject());
653                 if (clientgameobj != NULL) // This is a GameObject
654                         clientgameobj->SetVisible(v, 0);
655                 
656                 // if the childobj is NULL then this may be an inverse parent link
657                 // so a non recursive search should still look down this node.
658                 setVisible_recursive(childnode, v);
659         }
660 }
661
662
663 void
664 KX_GameObject::SetVisible(
665         bool v,
666         bool recursive
667         )
668 {
669         if (GetSGNode()) {
670                 m_bVisible = v;
671                 if (m_pGraphicController)
672                         m_pGraphicController->Activate(m_bVisible);
673                 if (recursive)
674                         setVisible_recursive(GetSGNode(), v);
675         }
676 }
677
678 static void setOccluder_recursive(SG_Node* node, bool v)
679 {
680         NodeList& children = node->GetSGChildren();
681
682         for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
683         {
684                 SG_Node* childnode = (*childit);
685                 KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject());
686                 if (clientgameobj != NULL) // This is a GameObject
687                         clientgameobj->SetOccluder(v, false);
688                 
689                 // if the childobj is NULL then this may be an inverse parent link
690                 // so a non recursive search should still look down this node.
691                 setOccluder_recursive(childnode, v);
692         }
693 }
694
695 void
696 KX_GameObject::SetOccluder(
697         bool v,
698         bool recursive
699         )
700 {
701         if (GetSGNode()) {
702                 m_bOccluder = v;
703                 if (recursive)
704                         setOccluder_recursive(GetSGNode(), v);
705         }
706 }
707
708 void
709 KX_GameObject::SetLayer(
710         int l
711         )
712 {
713         m_layer = l;
714 }
715
716 int
717 KX_GameObject::GetLayer(
718         void
719         )
720 {
721         return m_layer;
722 }
723
724 void KX_GameObject::addLinearVelocity(const MT_Vector3& lin_vel,bool local)
725 {
726         if (m_pPhysicsController1) 
727         {
728                 MT_Vector3 lv = local ? NodeGetWorldOrientation() * lin_vel : lin_vel;
729                 m_pPhysicsController1->SetLinearVelocity(lv + m_pPhysicsController1->GetLinearVelocity(), 0);
730         }
731 }
732
733
734
735 void KX_GameObject::setLinearVelocity(const MT_Vector3& lin_vel,bool local)
736 {
737         if (m_pPhysicsController1)
738                 m_pPhysicsController1->SetLinearVelocity(lin_vel,local);
739 }
740
741
742
743 void KX_GameObject::setAngularVelocity(const MT_Vector3& ang_vel,bool local)
744 {
745         if (m_pPhysicsController1)
746                 m_pPhysicsController1->SetAngularVelocity(ang_vel,local);
747 }
748
749
750 void KX_GameObject::ResolveCombinedVelocities(
751         const MT_Vector3 & lin_vel,
752         const MT_Vector3 & ang_vel,
753         bool lin_vel_local,
754         bool ang_vel_local
755 ){
756         if (m_pPhysicsController1)
757         {
758
759                 MT_Vector3 lv = lin_vel_local ? NodeGetWorldOrientation() * lin_vel : lin_vel;
760                 MT_Vector3 av = ang_vel_local ? NodeGetWorldOrientation() * ang_vel : ang_vel;
761                 m_pPhysicsController1->resolveCombinedVelocities(
762                         lv.x(),lv.y(),lv.z(),av.x(),av.y(),av.z());
763         }
764 }
765
766
767 void KX_GameObject::SetObjectColor(const MT_Vector4& rgbavec)
768 {
769         m_bUseObjectColor = true;
770         m_objectColor = rgbavec;
771 }
772
773 void KX_GameObject::AlignAxisToVect(const MT_Vector3& dir, int axis, float fac)
774 {
775         MT_Matrix3x3 orimat;
776         MT_Vector3 vect,ori,z,x,y;
777         MT_Scalar len;
778
779         // check on valid node in case a python controller holds a reference to a deleted object
780         if (!GetSGNode())
781                 return;
782
783         vect = dir;
784         len = vect.length();
785         if (MT_fuzzyZero(len))
786         {
787                 cout << "alignAxisToVect() Error: Null vector!\n";
788                 return;
789         }
790         
791         if (fac<=0.0) {
792                 return;
793         }
794         
795         // normalize
796         vect /= len;
797         orimat = GetSGNode()->GetWorldOrientation();
798         switch (axis)
799         {       
800                 case 0: //x axis
801                         ori.setValue(orimat[0][2], orimat[1][2], orimat[2][2]); //pivot axis
802                         if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON) //is the vector paralell to the pivot?
803                                 ori.setValue(orimat[0][1], orimat[1][1], orimat[2][1]); //change the pivot!
804                         if (fac == 1.0) {
805                                 x = vect;
806                         } else {
807                                 x = (vect * fac) + ((orimat * MT_Vector3(1.0, 0.0, 0.0)) * (1-fac));
808                                 len = x.length();
809                                 if (MT_fuzzyZero(len)) x = vect;
810                                 else x /= len;
811                         }
812                         y = ori.cross(x);
813                         z = x.cross(y);
814                         break;
815                 case 1: //y axis
816                         ori.setValue(orimat[0][0], orimat[1][0], orimat[2][0]);
817                         if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON)
818                                 ori.setValue(orimat[0][2], orimat[1][2], orimat[2][2]);
819                         if (fac == 1.0) {
820                                 y = vect;
821                         } else {
822                                 y = (vect * fac) + ((orimat * MT_Vector3(0.0, 1.0, 0.0)) * (1-fac));
823                                 len = y.length();
824                                 if (MT_fuzzyZero(len)) y = vect;
825                                 else y /= len;
826                         }
827                         z = ori.cross(y);
828                         x = y.cross(z);
829                         break;
830                 case 2: //z axis
831                         ori.setValue(orimat[0][1], orimat[1][1], orimat[2][1]);
832                         if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON)
833                                 ori.setValue(orimat[0][0], orimat[1][0], orimat[2][0]);
834                         if (fac == 1.0) {
835                                 z = vect;
836                         } else {
837                                 z = (vect * fac) + ((orimat * MT_Vector3(0.0, 0.0, 1.0)) * (1-fac));
838                                 len = z.length();
839                                 if (MT_fuzzyZero(len)) z = vect;
840                                 else z /= len;
841                         }
842                         x = ori.cross(z);
843                         y = z.cross(x);
844                         break;
845                 default: //wrong input?
846                         cout << "alignAxisToVect(): Wrong axis '" << axis <<"'\n";
847                         return;
848         }
849         x.normalize(); //normalize the vectors
850         y.normalize();
851         z.normalize();
852         orimat.setValue(        x[0],y[0],z[0],
853                                                 x[1],y[1],z[1],
854                                                 x[2],y[2],z[2]);
855         if (GetSGNode()->GetSGParent() != NULL)
856         {
857                 // the object is a child, adapt its local orientation so that 
858                 // the global orientation is aligned as we want.
859                 MT_Matrix3x3 invori = GetSGNode()->GetSGParent()->GetWorldOrientation().inverse();
860                 NodeSetLocalOrientation(invori*orimat);
861         }
862         else
863                 NodeSetLocalOrientation(orimat);
864 }
865
866 MT_Scalar KX_GameObject::GetMass()
867 {
868         if (m_pPhysicsController1)
869         {
870                 return m_pPhysicsController1->GetMass();
871         }
872         return 0.0;
873 }
874
875 MT_Vector3 KX_GameObject::GetLocalInertia()
876 {
877         MT_Vector3 local_inertia(0.0,0.0,0.0);
878         if (m_pPhysicsController1)
879         {
880                 local_inertia = m_pPhysicsController1->GetLocalInertia();
881         }
882         return local_inertia;
883 }
884
885 MT_Vector3 KX_GameObject::GetLinearVelocity(bool local)
886 {
887         MT_Vector3 velocity(0.0,0.0,0.0), locvel;
888         MT_Matrix3x3 ori;
889         if (m_pPhysicsController1)
890         {
891                 velocity = m_pPhysicsController1->GetLinearVelocity();
892                 
893                 if (local)
894                 {
895                         ori = GetSGNode()->GetWorldOrientation();
896                         
897                         locvel = velocity * ori;
898                         return locvel;
899                 }
900         }
901         return velocity;        
902 }
903
904 MT_Vector3 KX_GameObject::GetAngularVelocity(bool local)
905 {
906         MT_Vector3 velocity(0.0,0.0,0.0), locvel;
907         MT_Matrix3x3 ori;
908         if (m_pPhysicsController1)
909         {
910                 velocity = m_pPhysicsController1->GetAngularVelocity();
911                 
912                 if (local)
913                 {
914                         ori = GetSGNode()->GetWorldOrientation();
915                         
916                         locvel = velocity * ori;
917                         return locvel;
918                 }
919         }
920         return velocity;        
921 }
922
923 MT_Vector3 KX_GameObject::GetVelocity(const MT_Point3& point)
924 {
925         if (m_pPhysicsController1)
926         {
927                 return m_pPhysicsController1->GetVelocity(point);
928         }
929         return MT_Vector3(0.0,0.0,0.0);
930 }
931
932 // scenegraph node stuff
933
934 void KX_GameObject::NodeSetLocalPosition(const MT_Point3& trans)
935 {
936         // check on valid node in case a python controller holds a reference to a deleted object
937         if (!GetSGNode())
938                 return;
939
940         if (m_pPhysicsController1 && !GetSGNode()->GetSGParent())
941         {
942                 // don't update physic controller if the object is a child:
943                 // 1) the transformation will not be right
944                 // 2) in this case, the physic controller is necessarily a static object
945                 //    that is updated from the normal kinematic synchronization
946                 m_pPhysicsController1->setPosition(trans);
947         }
948
949         GetSGNode()->SetLocalPosition(trans);
950
951 }
952
953
954
955 void KX_GameObject::NodeSetLocalOrientation(const MT_Matrix3x3& rot)
956 {
957         // check on valid node in case a python controller holds a reference to a deleted object
958         if (!GetSGNode())
959                 return;
960
961         if (m_pPhysicsController1 && !GetSGNode()->GetSGParent())
962         {
963                 // see note above
964                 m_pPhysicsController1->setOrientation(rot);
965         }
966         GetSGNode()->SetLocalOrientation(rot);
967 }
968
969
970
971 void KX_GameObject::NodeSetLocalScale(const MT_Vector3& scale)
972 {
973         // check on valid node in case a python controller holds a reference to a deleted object
974         if (!GetSGNode())
975                 return;
976
977         if (m_pPhysicsController1 && !GetSGNode()->GetSGParent())
978         {
979                 // see note above
980                 m_pPhysicsController1->setScaling(scale);
981         }
982         GetSGNode()->SetLocalScale(scale);
983 }
984
985
986
987 void KX_GameObject::NodeSetRelativeScale(const MT_Vector3& scale)
988 {
989         if (GetSGNode())
990         {
991                 GetSGNode()->RelativeScale(scale);
992                 if (m_pPhysicsController1 && (!GetSGNode()->GetSGParent()))
993                 {
994                         // see note above
995                         // we can use the local scale: it's the same thing for a root object 
996                         // and the world scale is not yet updated
997                         MT_Vector3 newscale = GetSGNode()->GetLocalScale();
998                         m_pPhysicsController1->setScaling(newscale);
999                 }
1000         }
1001 }
1002
1003 void KX_GameObject::NodeSetWorldPosition(const MT_Point3& trans)
1004 {
1005         if (!GetSGNode())
1006                 return;
1007         SG_Node* parent = GetSGNode()->GetSGParent();
1008         if (parent != NULL)
1009         {
1010                 // Make sure the objects have some scale
1011                 MT_Vector3 scale = parent->GetWorldScaling();
1012                 if (fabs(scale[0]) < FLT_EPSILON || 
1013                         fabs(scale[1]) < FLT_EPSILON || 
1014                         fabs(scale[2]) < FLT_EPSILON)
1015                 { 
1016                         return; 
1017                 }
1018                 scale[0] = 1.0/scale[0];
1019                 scale[1] = 1.0/scale[1];
1020                 scale[2] = 1.0/scale[2];
1021                 MT_Matrix3x3 invori = parent->GetWorldOrientation().inverse();
1022                 MT_Vector3 newpos = invori*(trans-parent->GetWorldPosition())*scale;
1023                 NodeSetLocalPosition(MT_Point3(newpos[0],newpos[1],newpos[2]));
1024         }
1025         else 
1026         {
1027                 NodeSetLocalPosition(trans);
1028         }
1029 }
1030
1031
1032 void KX_GameObject::NodeUpdateGS(double time)
1033 {
1034         if (GetSGNode())
1035                 GetSGNode()->UpdateWorldData(time);
1036 }
1037
1038
1039
1040 const MT_Matrix3x3& KX_GameObject::NodeGetWorldOrientation() const
1041 {
1042         // check on valid node in case a python controller holds a reference to a deleted object
1043         if (!GetSGNode())
1044                 return dummy_orientation;
1045         return GetSGNode()->GetWorldOrientation();
1046 }
1047
1048
1049
1050 const MT_Vector3& KX_GameObject::NodeGetWorldScaling() const
1051 {
1052         // check on valid node in case a python controller holds a reference to a deleted object
1053         if (!GetSGNode())
1054                 return dummy_scaling;
1055
1056         return GetSGNode()->GetWorldScaling();
1057 }
1058
1059
1060
1061 const MT_Point3& KX_GameObject::NodeGetWorldPosition() const
1062 {
1063         // check on valid node in case a python controller holds a reference to a deleted object
1064         if (GetSGNode())
1065                 return GetSGNode()->GetWorldPosition();
1066         else
1067                 return dummy_point;
1068 }
1069
1070 /* Suspend/ resume: for the dynamic behaviour, there is a simple
1071  * method. For the residual motion, there is not. I wonder what the
1072  * correct solution is for Sumo. Remove from the motion-update tree?
1073  *
1074  * So far, only switch the physics and logic.
1075  * */
1076
1077 void KX_GameObject::Resume(void)
1078 {
1079         if (m_suspended) {
1080                 SCA_IObject::Resume();
1081                 if(GetPhysicsController())
1082                         GetPhysicsController()->RestoreDynamics();
1083
1084                 m_suspended = false;
1085         }
1086 }
1087
1088 void KX_GameObject::Suspend()
1089 {
1090         if ((!m_ignore_activity_culling) 
1091                 && (!m_suspended))  {
1092                 SCA_IObject::Suspend();
1093                 if(GetPhysicsController())
1094                         GetPhysicsController()->SuspendDynamics();
1095                 m_suspended = true;
1096         }
1097 }
1098
1099 static void walk_children(SG_Node* node, CListValue* list, bool recursive)
1100 {
1101         if (!node)
1102                 return;
1103         NodeList& children = node->GetSGChildren();
1104
1105         for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
1106         {
1107                 SG_Node* childnode = (*childit);
1108                 CValue* childobj = (CValue*)childnode->GetSGClientObject();
1109                 if (childobj != NULL) // This is a GameObject
1110                 {
1111                         // add to the list
1112                         list->Add(childobj->AddRef());
1113                 }
1114                 
1115                 // if the childobj is NULL then this may be an inverse parent link
1116                 // so a non recursive search should still look down this node.
1117                 if (recursive || childobj==NULL) {
1118                         walk_children(childnode, list, recursive);
1119                 }
1120         }
1121 }
1122
1123 CListValue* KX_GameObject::GetChildren()
1124 {
1125         CListValue* list = new CListValue();
1126         walk_children(GetSGNode(), list, 0); /* GetSGNode() is always valid or it would have raised an exception before this */
1127         return list;
1128 }
1129
1130 CListValue* KX_GameObject::GetChildrenRecursive()
1131 {
1132         CListValue* list = new CListValue();
1133         walk_children(GetSGNode(), list, 1);
1134         return list;
1135 }
1136
1137
1138 /* ------- python stuff ---------------------------------------------------*/
1139
1140 PyMethodDef KX_GameObject::Methods[] = {
1141         {"applyForce", (PyCFunction)    KX_GameObject::sPyApplyForce, METH_VARARGS},
1142         {"applyTorque", (PyCFunction)   KX_GameObject::sPyApplyTorque, METH_VARARGS},
1143         {"applyRotation", (PyCFunction) KX_GameObject::sPyApplyRotation, METH_VARARGS},
1144         {"applyMovement", (PyCFunction) KX_GameObject::sPyApplyMovement, METH_VARARGS},
1145         {"getLinearVelocity", (PyCFunction) KX_GameObject::sPyGetLinearVelocity, METH_VARARGS},
1146         {"setLinearVelocity", (PyCFunction) KX_GameObject::sPySetLinearVelocity, METH_VARARGS},
1147         {"getAngularVelocity", (PyCFunction) KX_GameObject::sPyGetAngularVelocity, METH_VARARGS},
1148         {"setAngularVelocity", (PyCFunction) KX_GameObject::sPySetAngularVelocity, METH_VARARGS},
1149         {"getVelocity", (PyCFunction) KX_GameObject::sPyGetVelocity, METH_VARARGS},
1150         {"getReactionForce", (PyCFunction) KX_GameObject::sPyGetReactionForce, METH_NOARGS},
1151         {"alignAxisToVect",(PyCFunction) KX_GameObject::sPyAlignAxisToVect, METH_VARARGS},
1152         {"getAxisVect",(PyCFunction) KX_GameObject::sPyGetAxisVect, METH_O},
1153         {"suspendDynamics", (PyCFunction)KX_GameObject::sPySuspendDynamics,METH_NOARGS},
1154         {"restoreDynamics", (PyCFunction)KX_GameObject::sPyRestoreDynamics,METH_NOARGS},
1155         {"enableRigidBody", (PyCFunction)KX_GameObject::sPyEnableRigidBody,METH_NOARGS},
1156         {"disableRigidBody", (PyCFunction)KX_GameObject::sPyDisableRigidBody,METH_NOARGS},
1157         {"applyImpulse", (PyCFunction) KX_GameObject::sPyApplyImpulse, METH_VARARGS},
1158         {"setCollisionMargin", (PyCFunction) KX_GameObject::sPySetCollisionMargin, METH_O},
1159         {"setParent", (PyCFunction)KX_GameObject::sPySetParent,METH_O},
1160         {"setVisible",(PyCFunction) KX_GameObject::sPySetVisible, METH_VARARGS},
1161         {"setOcclusion",(PyCFunction) KX_GameObject::sPySetOcclusion, METH_VARARGS},
1162         {"removeParent", (PyCFunction)KX_GameObject::sPyRemoveParent,METH_NOARGS},
1163         {"getChildren", (PyCFunction)KX_GameObject::sPyGetChildren,METH_NOARGS},
1164         {"getChildrenRecursive", (PyCFunction)KX_GameObject::sPyGetChildrenRecursive,METH_NOARGS},
1165         {"getPhysicsId", (PyCFunction)KX_GameObject::sPyGetPhysicsId,METH_NOARGS},
1166         {"getPropertyNames", (PyCFunction)KX_GameObject::sPyGetPropertyNames,METH_NOARGS},
1167         {"replaceMesh",(PyCFunction) KX_GameObject::sPyReplaceMesh, METH_O},
1168         {"endObject",(PyCFunction) KX_GameObject::sPyEndObject, METH_NOARGS},
1169         
1170         KX_PYMETHODTABLE(KX_GameObject, rayCastTo),
1171         KX_PYMETHODTABLE(KX_GameObject, rayCast),
1172         KX_PYMETHODTABLE_O(KX_GameObject, getDistanceTo),
1173         KX_PYMETHODTABLE_O(KX_GameObject, getVectTo),
1174         KX_PYMETHODTABLE(KX_GameObject, sendMessage),
1175
1176         // deprecated
1177         {"getPosition", (PyCFunction) KX_GameObject::sPyGetPosition, METH_NOARGS},
1178         {"setPosition", (PyCFunction) KX_GameObject::sPySetPosition, METH_O},
1179         {"setWorldPosition", (PyCFunction) KX_GameObject::sPySetWorldPosition, METH_O},
1180         {"getOrientation", (PyCFunction) KX_GameObject::sPyGetOrientation, METH_NOARGS},
1181         {"setOrientation", (PyCFunction) KX_GameObject::sPySetOrientation, METH_O},
1182         {"getState",(PyCFunction) KX_GameObject::sPyGetState, METH_NOARGS},
1183         {"setState",(PyCFunction) KX_GameObject::sPySetState, METH_O},
1184         {"getParent", (PyCFunction)KX_GameObject::sPyGetParent,METH_NOARGS},
1185         {"getVisible",(PyCFunction) KX_GameObject::sPyGetVisible, METH_NOARGS},
1186         {"getMass", (PyCFunction) KX_GameObject::sPyGetMass, METH_NOARGS},
1187         {"getMesh", (PyCFunction)KX_GameObject::sPyGetMesh,METH_VARARGS},
1188         {NULL,NULL} //Sentinel
1189 };
1190
1191 PyAttributeDef KX_GameObject::Attributes[] = {
1192         KX_PYATTRIBUTE_RO_FUNCTION("name",              KX_GameObject, pyattr_get_name),
1193         KX_PYATTRIBUTE_RO_FUNCTION("parent",    KX_GameObject, pyattr_get_parent),
1194         KX_PYATTRIBUTE_RW_FUNCTION("mass",              KX_GameObject, pyattr_get_mass,         pyattr_set_mass),
1195         KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMin",            KX_GameObject, pyattr_get_lin_vel_min, pyattr_set_lin_vel_min),
1196         KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMax",            KX_GameObject, pyattr_get_lin_vel_max, pyattr_set_lin_vel_max),
1197         KX_PYATTRIBUTE_RW_FUNCTION("visible",   KX_GameObject, pyattr_get_visible,      pyattr_set_visible),
1198         KX_PYATTRIBUTE_BOOL_RW    ("occlusion", KX_GameObject, m_bOccluder),
1199         KX_PYATTRIBUTE_RW_FUNCTION("position",  KX_GameObject, pyattr_get_worldPosition,        pyattr_set_localPosition),
1200         KX_PYATTRIBUTE_RO_FUNCTION("localInertia",      KX_GameObject, pyattr_get_localInertia),
1201         KX_PYATTRIBUTE_RW_FUNCTION("orientation",KX_GameObject,pyattr_get_worldOrientation,pyattr_set_localOrientation),
1202         KX_PYATTRIBUTE_RW_FUNCTION("scaling",   KX_GameObject, pyattr_get_worldScaling, pyattr_set_localScaling),
1203         KX_PYATTRIBUTE_RW_FUNCTION("timeOffset",KX_GameObject, pyattr_get_timeOffset,pyattr_set_timeOffset),
1204         KX_PYATTRIBUTE_RW_FUNCTION("state",             KX_GameObject, pyattr_get_state,        pyattr_set_state),
1205         KX_PYATTRIBUTE_RO_FUNCTION("meshes",    KX_GameObject, pyattr_get_meshes),
1206         KX_PYATTRIBUTE_RW_FUNCTION("localOrientation",KX_GameObject,pyattr_get_localOrientation,pyattr_set_localOrientation),
1207         KX_PYATTRIBUTE_RW_FUNCTION("worldOrientation",KX_GameObject,pyattr_get_worldOrientation,pyattr_set_worldOrientation),
1208         KX_PYATTRIBUTE_RW_FUNCTION("localPosition",     KX_GameObject, pyattr_get_localPosition,        pyattr_set_localPosition),
1209         KX_PYATTRIBUTE_RW_FUNCTION("worldPosition",     KX_GameObject, pyattr_get_worldPosition,    pyattr_set_worldPosition),
1210         KX_PYATTRIBUTE_RW_FUNCTION("localScaling",      KX_GameObject, pyattr_get_localScaling, pyattr_set_localScaling),
1211         KX_PYATTRIBUTE_RO_FUNCTION("worldScaling",      KX_GameObject, pyattr_get_worldScaling),
1212         KX_PYATTRIBUTE_RO_FUNCTION("attrDict",  KX_GameObject, pyattr_get_attrDict),
1213         
1214         /* Experemental, dont rely on these yet */
1215         KX_PYATTRIBUTE_RO_FUNCTION("sensors",           KX_GameObject, pyattr_get_sensors),
1216         KX_PYATTRIBUTE_RO_FUNCTION("controllers",       KX_GameObject, pyattr_get_controllers),
1217         KX_PYATTRIBUTE_RO_FUNCTION("actuators",         KX_GameObject, pyattr_get_actuators),
1218         {NULL} //Sentinel
1219 };
1220
1221
1222 /*
1223 bool KX_GameObject::ConvertPythonVectorArgs(PyObject* args,
1224                                                                                         MT_Vector3& pos,
1225                                                                                         MT_Vector3& pos2)
1226 {
1227         PyObject* pylist;
1228         PyObject* pylist2;
1229         bool error = (PyArg_ParseTuple(args,"OO",&pylist,&pylist2)) != 0;
1230
1231         pos = ConvertPythonPylist(pylist);
1232         pos2 = ConvertPythonPylist(pylist2);
1233                 
1234         return error;
1235 }
1236 */
1237
1238 PyObject* KX_GameObject::PyReplaceMesh(PyObject* value)
1239 {
1240         KX_Scene *scene = KX_GetActiveScene();
1241         RAS_MeshObject* new_mesh;
1242         
1243         if (!ConvertPythonToMesh(value, &new_mesh, false, "gameOb.replaceMesh(value): KX_GameObject"))
1244                 return NULL;
1245         
1246         scene->ReplaceMesh(this, new_mesh);
1247         Py_RETURN_NONE;
1248 }
1249
1250 PyObject* KX_GameObject::PyEndObject()
1251 {
1252         KX_Scene *scene = KX_GetActiveScene();
1253         
1254         scene->DelayedRemoveObject(this);
1255         
1256         Py_RETURN_NONE;
1257
1258 }
1259
1260
1261 PyObject* KX_GameObject::PyGetPosition()
1262 {
1263         ShowDeprecationWarning("getPosition()", "the position property");
1264         return PyObjectFrom(NodeGetWorldPosition());
1265 }
1266
1267 PyObject *KX_GameObject::Map_GetItem(PyObject *self_v, PyObject *item)
1268 {
1269         KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
1270         const char *attr_str= PyString_AsString(item);
1271         CValue* resultattr;
1272         PyObject* pyconvert;
1273         
1274         if (self==NULL) {
1275                 PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
1276                 return NULL;
1277         }
1278         
1279         /* first see if the attributes a string and try get the cvalue attribute */
1280         if(attr_str && (resultattr=self->GetProperty(attr_str))) {
1281                 pyconvert = resultattr->ConvertValueToPython();                 
1282                 return pyconvert ? pyconvert:resultattr->GetProxy();
1283         }
1284         /* no CValue attribute, try get the python only m_attr_dict attribute */
1285         else if (self->m_attr_dict && (pyconvert=PyDict_GetItem(self->m_attr_dict, item))) {
1286                 
1287                 if (attr_str)
1288                         PyErr_Clear();
1289                 Py_INCREF(pyconvert);
1290                 return pyconvert;
1291         }
1292         else {
1293                 if(attr_str)    PyErr_Format(PyExc_KeyError, "value = gameOb[key]: KX_GameObject, key \"%s\" does not exist", attr_str);
1294                 else                    PyErr_SetString(PyExc_KeyError, "value = gameOb[key]: KX_GameObject, key does not exist");
1295                 return NULL;
1296         }
1297                 
1298 }
1299
1300
1301 int KX_GameObject::Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val)
1302 {
1303         KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
1304         const char *attr_str= PyString_AsString(key);
1305         if(attr_str==NULL)
1306                 PyErr_Clear();
1307         
1308         if (self==NULL) {
1309                 PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
1310                 return -1;
1311         }
1312         
1313         if (val==NULL) { /* del ob["key"] */
1314                 int del= 0;
1315                 
1316                 /* try remove both just incase */
1317                 if(attr_str)
1318                         del |= (self->RemoveProperty(attr_str)==true) ? 1:0;
1319                 
1320                 if(self->m_attr_dict)
1321                         del |= (PyDict_DelItem(self->m_attr_dict, key)==0) ? 1:0;
1322                 
1323                 if (del==0) {
1324                         if(attr_str)    PyErr_Format(PyExc_KeyError, "gameOb[key] = value: KX_GameObject, key \"%s\" could not be set", attr_str);
1325                         else                    PyErr_SetString(PyExc_KeyError, "gameOb[key] = value: KX_GameObject, key could not be set");
1326                         return -1;
1327                 }
1328                 else if (self->m_attr_dict) {
1329                         PyErr_Clear(); /* PyDict_DelItem sets an error when it fails */
1330                 }
1331         }
1332         else { /* ob["key"] = value */
1333                 int set= 0;
1334                 
1335                 /* as CValue */
1336                 if(attr_str && BGE_PROXY_CHECK_TYPE(val)==0) /* dont allow GameObjects for eg to be assigned to CValue props */
1337                 {
1338                         CValue* vallie = self->ConvertPythonToValue(val, ""); /* error unused */
1339                         
1340                         if(vallie)
1341                         {
1342                                 CValue* oldprop = self->GetProperty(attr_str);
1343                                 
1344                                 if (oldprop)
1345                                         oldprop->SetValue(vallie);
1346                                 else
1347                                         self->SetProperty(attr_str, vallie);
1348                                 
1349                                 vallie->Release();
1350                                 set= 1;
1351                                 
1352                                 /* try remove dict value to avoid double ups */
1353                                 if (self->m_attr_dict){
1354                                         if (PyDict_DelItem(self->m_attr_dict, key) != 0)
1355                                                 PyErr_Clear();
1356                                 }
1357                         }
1358                         else {
1359                                 PyErr_Clear();
1360                         }
1361                 }
1362                 
1363                 if(set==0)
1364                 {
1365                         if (self->m_attr_dict==NULL) /* lazy init */
1366                                 self->m_attr_dict= PyDict_New();
1367                         
1368                         
1369                         if(PyDict_SetItem(self->m_attr_dict, key, val)==0)
1370                         {
1371                                 if(attr_str)
1372                                         self->RemoveProperty(attr_str); /* overwrite the CValue if it exists */
1373                                 set= 1;
1374                         }
1375                         else {
1376                                 if(attr_str)    PyErr_Format(PyExc_KeyError, "gameOb[key] = value: KX_GameObject, key \"%s\" not be added to internal dictionary", attr_str);
1377                                 else                    PyErr_SetString(PyExc_KeyError, "gameOb[key] = value: KX_GameObject, key not be added to internal dictionary");
1378                         }
1379                 }
1380                 
1381                 if(set==0)
1382                         return -1; /* pythons error value */
1383                 
1384         }
1385         
1386         return 0; /* success */
1387 }
1388
1389 /* Cant set the len otherwise it can evaluate as false */
1390 PyMappingMethods KX_GameObject::Mapping = {
1391         (lenfunc)NULL                                   ,                       /*inquiry mp_length */
1392         (binaryfunc)KX_GameObject::Map_GetItem,         /*binaryfunc mp_subscript */
1393         (objobjargproc)KX_GameObject::Map_SetItem,      /*objobjargproc mp_ass_subscript */
1394 };
1395
1396 PyTypeObject KX_GameObject::Type = {
1397 #if (PY_VERSION_HEX >= 0x02060000)
1398         PyVarObject_HEAD_INIT(NULL, 0)
1399 #else
1400         /* python 2.5 and below */
1401         PyObject_HEAD_INIT( NULL )  /* required py macro */
1402         0,                          /* ob_size */
1403 #endif
1404                 "KX_GameObject",
1405                 sizeof(PyObjectPlus_Proxy),
1406                 0,
1407                 py_base_dealloc,
1408                 0,
1409                 0,
1410                 0,
1411                 0,
1412                 py_base_repr,
1413                 0,0,
1414                 &Mapping,
1415                 0,0,0,
1416                 py_base_getattro,
1417                 py_base_setattro,
1418                 0,0,0,0,0,0,0,0,0,
1419                 Methods
1420 };
1421
1422
1423
1424
1425
1426
1427 PyParentObject KX_GameObject::Parents[] = {
1428         &KX_GameObject::Type,
1429                 &SCA_IObject::Type,
1430                 &CValue::Type,
1431                 NULL
1432 };
1433
1434 PyObject* KX_GameObject::pyattr_get_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1435 {
1436         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1437         return PyString_FromString(self->GetName().ReadPtr());
1438 }
1439
1440 PyObject* KX_GameObject::pyattr_get_parent(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1441 {
1442         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1443         KX_GameObject* parent = self->GetParent();
1444         if (parent) {
1445                 parent->Release(); /* self->GetParent() AddRef's */
1446                 return parent->GetProxy();
1447         }
1448         Py_RETURN_NONE;
1449 }
1450
1451 PyObject* KX_GameObject::pyattr_get_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1452 {
1453         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1454         KX_IPhysicsController *spc = self->GetPhysicsController();
1455         return PyFloat_FromDouble(spc ? spc->GetMass() : 0.0f);
1456 }
1457
1458 int KX_GameObject::pyattr_set_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1459 {
1460         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1461         KX_IPhysicsController *spc = self->GetPhysicsController();
1462         MT_Scalar val = PyFloat_AsDouble(value);
1463         if (val < 0.0f) { /* also accounts for non float */
1464                 PyErr_SetString(PyExc_AttributeError, "gameOb.mass = float: KX_GameObject, expected a float zero or above");
1465                 return 1;
1466         }
1467
1468         if (spc)
1469                 spc->SetMass(val);
1470
1471         return 0;
1472 }
1473
1474 PyObject* KX_GameObject::pyattr_get_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1475 {
1476         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1477         KX_IPhysicsController *spc = self->GetPhysicsController();
1478         return PyFloat_FromDouble(spc ? spc->GetLinVelocityMax() : 0.0f);
1479 }
1480
1481 int KX_GameObject::pyattr_set_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1482 {
1483         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1484         KX_IPhysicsController *spc = self->GetPhysicsController();
1485         MT_Scalar val = PyFloat_AsDouble(value);
1486         if (val < 0.0f) { /* also accounts for non float */
1487                 PyErr_SetString(PyExc_AttributeError, "gameOb.linVelocityMin = float: KX_GameObject, expected a float zero or above");
1488                 return 1;
1489         }
1490
1491         if (spc)
1492                 spc->SetLinVelocityMin(val);
1493
1494         return 0;
1495 }
1496
1497 PyObject* KX_GameObject::pyattr_get_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1498 {
1499         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1500         KX_IPhysicsController *spc = self->GetPhysicsController();
1501         return PyFloat_FromDouble(spc ? spc->GetLinVelocityMax() : 0.0f);
1502 }
1503
1504 int KX_GameObject::pyattr_set_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1505 {
1506         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1507         KX_IPhysicsController *spc = self->GetPhysicsController();
1508         MT_Scalar val = PyFloat_AsDouble(value);
1509         if (val < 0.0f) { /* also accounts for non float */
1510                 PyErr_SetString(PyExc_AttributeError, "gameOb.linVelocityMax = float: KX_GameObject, expected a float zero or above");
1511                 return 1;
1512         }
1513
1514         if (spc)
1515                 spc->SetLinVelocityMax(val);
1516
1517         return 0;
1518 }
1519
1520
1521 PyObject* KX_GameObject::pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1522 {
1523         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1524         return PyBool_FromLong(self->GetVisible());
1525 }
1526
1527 int KX_GameObject::pyattr_set_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1528 {
1529         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1530         int param = PyObject_IsTrue( value );
1531         if (param == -1) {
1532                 PyErr_SetString(PyExc_AttributeError, "gameOb.visible = bool: KX_GameObject, expected True or False");
1533                 return 1;
1534         }
1535
1536         self->SetVisible(param, false);
1537         self->UpdateBuckets(false);
1538         return 0;
1539 }
1540
1541 PyObject* KX_GameObject::pyattr_get_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1542 {
1543         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1544         return PyObjectFrom(self->NodeGetWorldPosition());
1545 }
1546
1547 int KX_GameObject::pyattr_set_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1548 {
1549         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1550         MT_Point3 pos;
1551         if (!PyVecTo(value, pos))
1552                 return 1;
1553         
1554         self->NodeSetWorldPosition(pos);
1555         self->NodeUpdateGS(0.f);
1556         return 0;
1557 }
1558
1559 PyObject* KX_GameObject::pyattr_get_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1560 {
1561         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1562         if (self->GetSGNode())
1563                 return PyObjectFrom(self->GetSGNode()->GetLocalPosition());
1564         else
1565                 return PyObjectFrom(dummy_point);
1566 }
1567
1568 int KX_GameObject::pyattr_set_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1569 {
1570         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1571         MT_Point3 pos;
1572         if (!PyVecTo(value, pos))
1573                 return 1;
1574         
1575         self->NodeSetLocalPosition(pos);
1576         self->NodeUpdateGS(0.f);
1577         return 0;
1578 }
1579
1580 PyObject* KX_GameObject::pyattr_get_localInertia(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1581 {
1582         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1583         if (self->GetPhysicsController())
1584         {
1585                 return PyObjectFrom(self->GetPhysicsController()->GetLocalInertia());
1586         }
1587         return Py_BuildValue("fff", 0.0f, 0.0f, 0.0f);
1588 }
1589
1590 PyObject* KX_GameObject::pyattr_get_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1591 {
1592         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1593         return PyObjectFrom(self->NodeGetWorldOrientation());
1594 }
1595
1596 int KX_GameObject::pyattr_set_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1597 {
1598         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1599         
1600         /* if value is not a sequence PyOrientationTo makes an error */
1601         MT_Matrix3x3 rot;
1602         if (!PyOrientationTo(value, rot, "gameOb.worldOrientation = sequence: KX_GameObject, "))
1603                 return NULL;
1604
1605         if (self->GetSGNode() && self->GetSGNode()->GetSGParent()) {
1606                 self->NodeSetLocalOrientation(self->GetSGNode()->GetSGParent()->GetWorldOrientation().inverse()*rot);
1607         }
1608         else {
1609                 self->NodeSetLocalOrientation(rot);
1610         }
1611         
1612         self->NodeUpdateGS(0.f);
1613         return 0;
1614 }
1615
1616 PyObject* KX_GameObject::pyattr_get_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1617 {
1618         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1619         if (self->GetSGNode())
1620                 return PyObjectFrom(self->GetSGNode()->GetLocalOrientation());
1621         else
1622                 return PyObjectFrom(dummy_orientation);
1623 }
1624
1625 int KX_GameObject::pyattr_set_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1626 {
1627         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1628         
1629         /* if value is not a sequence PyOrientationTo makes an error */
1630         MT_Matrix3x3 rot;
1631         if (!PyOrientationTo(value, rot, "gameOb.localOrientation = sequence: KX_GameObject, "))
1632                 return NULL;
1633
1634         self->NodeSetLocalOrientation(rot);
1635         self->NodeUpdateGS(0.f);
1636         return 0;
1637 }
1638
1639 PyObject* KX_GameObject::pyattr_get_worldScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1640 {
1641         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1642         return PyObjectFrom(self->NodeGetWorldScaling());
1643 }
1644
1645 PyObject* KX_GameObject::pyattr_get_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1646 {
1647         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1648         if (self->GetSGNode())
1649                 return PyObjectFrom(self->GetSGNode()->GetLocalScale());
1650         else
1651                 return PyObjectFrom(dummy_scaling);
1652 }
1653
1654 int KX_GameObject::pyattr_set_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1655 {
1656         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1657         MT_Vector3 scale;
1658         if (!PyVecTo(value, scale))
1659                 return 1;
1660
1661         self->NodeSetLocalScale(scale);
1662         self->NodeUpdateGS(0.f);
1663         return 0;
1664 }
1665
1666 PyObject* KX_GameObject::pyattr_get_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1667 {
1668         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1669         SG_Node* sg_parent;
1670         if (self->GetSGNode() && (sg_parent = self->GetSGNode()->GetSGParent()) != NULL && sg_parent->IsSlowParent()) {
1671                 return PyFloat_FromDouble(static_cast<KX_SlowParentRelation *>(sg_parent->GetParentRelation())->GetTimeOffset());
1672         } else {
1673                 return PyFloat_FromDouble(0.0);
1674         }
1675 }
1676
1677 int KX_GameObject::pyattr_set_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1678 {
1679         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1680         if (self->GetSGNode()) {
1681                 MT_Scalar val = PyFloat_AsDouble(value);
1682                 SG_Node* sg_parent= self->GetSGNode()->GetSGParent();
1683                 if (val < 0.0f) { /* also accounts for non float */
1684                         PyErr_SetString(PyExc_AttributeError, "gameOb.timeOffset = float: KX_GameObject, expected a float zero or above");
1685                         return 1;
1686                 }
1687                 if (sg_parent && sg_parent->IsSlowParent())
1688                         static_cast<KX_SlowParentRelation *>(sg_parent->GetParentRelation())->SetTimeOffset(val);
1689         }
1690         return 0;
1691 }
1692
1693 PyObject* KX_GameObject::pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1694 {
1695         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1696         int state = 0;
1697         state |= self->GetState();
1698         return PyInt_FromLong(state);
1699 }
1700
1701 int KX_GameObject::pyattr_set_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1702 {
1703         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1704         int state_i = PyInt_AsLong(value);
1705         unsigned int state = 0;
1706         
1707         if (state_i == -1 && PyErr_Occurred()) {
1708                 PyErr_SetString(PyExc_TypeError, "gameOb.state = int: KX_GameObject, expected an int bit field");
1709                 return 1;
1710         }
1711         
1712         state |= state_i;
1713         if ((state & ((1<<30)-1)) == 0) {
1714                 PyErr_SetString(PyExc_AttributeError, "gameOb.state = int: KX_GameObject, state bitfield was not between 0 and 30 (1<<0 and 1<<29)");
1715                 return 1;
1716         }
1717         self->SetState(state);
1718         return 0;
1719 }
1720
1721 PyObject* KX_GameObject::pyattr_get_meshes(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1722 {
1723         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1724         PyObject *meshes= PyList_New(self->m_meshes.size());
1725         int i;
1726         
1727         for(i=0; i < (int)self->m_meshes.size(); i++)
1728         {
1729                 KX_MeshProxy* meshproxy = new KX_MeshProxy(self->m_meshes[i]);
1730                 PyList_SET_ITEM(meshes, i, meshproxy->NewProxy(true));
1731         }
1732         
1733         return meshes;
1734 }
1735
1736 /* experemental! */
1737 PyObject* KX_GameObject::pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1738 {
1739         return KX_PythonSeq_CreatePyObject((static_cast<KX_GameObject*>(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_SENSORS);
1740 }
1741
1742 PyObject* KX_GameObject::pyattr_get_controllers(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1743 {
1744         return KX_PythonSeq_CreatePyObject((static_cast<KX_GameObject*>(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_CONTROLLERS);
1745 }
1746
1747 PyObject* KX_GameObject::pyattr_get_actuators(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1748 {
1749         return KX_PythonSeq_CreatePyObject((static_cast<KX_GameObject*>(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_ACTUATORS);
1750 }
1751
1752 PyObject* KX_GameObject::pyattr_get_attrDict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1753 {
1754         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1755         
1756         if(self->m_attr_dict==NULL)
1757                 self->m_attr_dict= PyDict_New();
1758         
1759         Py_INCREF(self->m_attr_dict);
1760         return self->m_attr_dict;
1761 }
1762
1763 /* We need these because the macros have a return in them */
1764 PyObject* KX_GameObject::py_getattro__internal(PyObject *attr)
1765 {
1766         py_getattro_up(SCA_IObject);
1767 }
1768
1769 int KX_GameObject::py_setattro__internal(PyObject *attr, PyObject *value)       // py_setattro method
1770 {
1771         py_setattro_up(SCA_IObject);
1772 }
1773
1774
1775 PyObject* KX_GameObject::py_getattro(PyObject *attr)
1776 {
1777         PyObject *object= py_getattro__internal(attr);
1778         
1779         if (object==NULL && m_attr_dict)
1780         {
1781                 /* backup the exception incase the attr doesnt exist in the dict either */
1782                 PyObject *err_type, *err_value, *err_tb;
1783                 PyErr_Fetch(&err_type, &err_value, &err_tb);
1784                 
1785                 object= PyDict_GetItem(m_attr_dict, attr);
1786                 if (object) {
1787                         Py_INCREF(object);
1788                         
1789                         PyErr_Clear();
1790                         Py_XDECREF( err_type );
1791                         Py_XDECREF( err_value );
1792                         Py_XDECREF( err_tb );
1793                 }
1794                 else {
1795                         PyErr_Restore(err_type, err_value, err_tb); /* use the error from the parent function */
1796                 }
1797         }
1798         return object;
1799 }
1800
1801 PyObject* KX_GameObject::py_getattro_dict() {
1802         //py_getattro_dict_up(SCA_IObject);
1803         PyObject *dict= py_getattr_dict(SCA_IObject::py_getattro_dict(), Type.tp_dict);
1804         if(dict==NULL)
1805                 return NULL;
1806         
1807         /* normally just return this but KX_GameObject has some more items */
1808
1809         
1810         /* Not super fast getting as a list then making into dict keys but its only for dir() */
1811         PyObject *list= ConvertKeysToPython();
1812         if(list)
1813         {
1814                 int i;
1815                 for(i=0; i<PyList_Size(list); i++)
1816                         PyDict_SetItem(dict, PyList_GET_ITEM(list, i), Py_None);
1817         }
1818         else
1819                 PyErr_Clear();
1820         
1821         Py_DECREF(list);
1822         
1823         /* Add m_attr_dict if we have it */
1824         if(m_attr_dict)
1825                 PyDict_Update(dict, m_attr_dict);
1826         
1827         return dict;
1828 }
1829
1830 int KX_GameObject::py_setattro(PyObject *attr, PyObject *value) // py_setattro method
1831 {
1832         int ret;
1833         
1834         ret= py_setattro__internal(attr, value);
1835         
1836         if (ret==PY_SET_ATTR_SUCCESS) {
1837                 /* remove attribute in our own dict to avoid double ups */
1838                 /* NOTE: Annoying that we also do this for setting builtin attributes like mass and visibility :/ */
1839                 if (m_attr_dict) {
1840                         if (PyDict_DelItem(m_attr_dict, attr) != 0)
1841                                 PyErr_Clear();
1842                 }
1843         }
1844         
1845         if (ret==PY_SET_ATTR_COERCE_FAIL) {
1846                 /* CValue attribute exists, remove CValue and add PyDict value */
1847                 RemoveProperty(STR_String(PyString_AsString(attr)));
1848                 ret= PY_SET_ATTR_MISSING;
1849         }
1850         
1851         if (ret==PY_SET_ATTR_MISSING) {
1852                 /* Lazy initialization */
1853                 if (m_attr_dict==NULL)
1854                         m_attr_dict = PyDict_New();
1855                 
1856                 if (PyDict_SetItem(m_attr_dict, attr, value)==0) {
1857                         PyErr_Clear();
1858                         ret= PY_SET_ATTR_SUCCESS;
1859                 }
1860                 else {
1861                         PyErr_Format(PyExc_AttributeError, "gameOb.myAttr = value: KX_GameObject, failed assigning value to internal dictionary");
1862                         ret= PY_SET_ATTR_FAIL;
1863                 }
1864         }
1865         
1866         return ret;     
1867 }
1868
1869
1870 int     KX_GameObject::py_delattro(PyObject *attr)
1871 {
1872         char *attr_str= PyString_AsString(attr); 
1873         
1874         if (RemoveProperty(STR_String(attr_str))) // XXX - should call CValues instead but its only 2 lines here
1875                 return 0;
1876         
1877         if (m_attr_dict && (PyDict_DelItem(m_attr_dict, attr) == 0))
1878                 return 0;
1879         
1880         PyErr_Format(PyExc_AttributeError, "del gameOb.myAttr: KX_GameObject, attribute \"%s\" dosnt exist", attr_str);
1881         return 1;
1882 }
1883
1884
1885 PyObject* KX_GameObject::PyApplyForce(PyObject* args)
1886 {
1887         int local = 0;
1888         PyObject* pyvect;
1889
1890         if (PyArg_ParseTuple(args, "O|i:applyForce", &pyvect, &local)) {
1891                 MT_Vector3 force;
1892                 if (PyVecTo(pyvect, force)) {
1893                         ApplyForce(force, (local!=0));
1894                         Py_RETURN_NONE;
1895                 }
1896         }
1897         return NULL;
1898 }
1899
1900 PyObject* KX_GameObject::PyApplyTorque(PyObject* args)
1901 {
1902         int local = 0;
1903         PyObject* pyvect;
1904
1905         if (PyArg_ParseTuple(args, "O|i:applyTorque", &pyvect, &local)) {
1906                 MT_Vector3 torque;
1907                 if (PyVecTo(pyvect, torque)) {
1908                         ApplyTorque(torque, (local!=0));
1909                         Py_RETURN_NONE;
1910                 }
1911         }
1912         return NULL;
1913 }
1914
1915 PyObject* KX_GameObject::PyApplyRotation(PyObject* args)
1916 {
1917         int local = 0;
1918         PyObject* pyvect;
1919
1920         if (PyArg_ParseTuple(args, "O|i:applyRotation", &pyvect, &local)) {
1921                 MT_Vector3 rotation;
1922                 if (PyVecTo(pyvect, rotation)) {
1923                         ApplyRotation(rotation, (local!=0));
1924                         Py_RETURN_NONE;
1925                 }
1926         }
1927         return NULL;
1928 }
1929
1930 PyObject* KX_GameObject::PyApplyMovement(PyObject* args)
1931 {
1932         int local = 0;
1933         PyObject* pyvect;
1934
1935         if (PyArg_ParseTuple(args, "O|i:applyMovement", &pyvect, &local)) {
1936                 MT_Vector3 movement;
1937                 if (PyVecTo(pyvect, movement)) {
1938                         ApplyMovement(movement, (local!=0));
1939                         Py_RETURN_NONE;
1940                 }
1941         }
1942         return NULL;
1943 }
1944
1945 PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* args)
1946 {
1947         // only can get the velocity if we have a physics object connected to us...
1948         int local = 0;
1949         if (PyArg_ParseTuple(args,"|i:getLinearVelocity",&local))
1950         {
1951                 return PyObjectFrom(GetLinearVelocity((local!=0)));
1952         }
1953         else
1954         {
1955                 return NULL;
1956         }
1957 }
1958
1959 PyObject* KX_GameObject::PySetLinearVelocity(PyObject* args)
1960 {
1961         int local = 0;
1962         PyObject* pyvect;
1963         
1964         if (PyArg_ParseTuple(args,"O|i:setLinearVelocity",&pyvect,&local)) {
1965                 MT_Vector3 velocity;
1966                 if (PyVecTo(pyvect, velocity)) {
1967                         setLinearVelocity(velocity, (local!=0));
1968                         Py_RETURN_NONE;
1969                 }
1970         }
1971         return NULL;
1972 }
1973
1974 PyObject* KX_GameObject::PyGetAngularVelocity(PyObject* args)
1975 {
1976         // only can get the velocity if we have a physics object connected to us...
1977         int local = 0;
1978         if (PyArg_ParseTuple(args,"|i:getAngularVelocity",&local))
1979         {
1980                 return PyObjectFrom(GetAngularVelocity((local!=0)));
1981         }
1982         else
1983         {
1984                 return NULL;
1985         }
1986 }
1987
1988 PyObject* KX_GameObject::PySetAngularVelocity(PyObject* args)
1989 {
1990         int local = 0;
1991         PyObject* pyvect;
1992         
1993         if (PyArg_ParseTuple(args,"O|i:setAngularVelocity",&pyvect,&local)) {
1994                 MT_Vector3 velocity;
1995                 if (PyVecTo(pyvect, velocity)) {
1996                         setAngularVelocity(velocity, (local!=0));
1997                         Py_RETURN_NONE;
1998                 }
1999         }
2000         return NULL;
2001 }
2002
2003 PyObject* KX_GameObject::PySetVisible(PyObject* args)
2004 {
2005         int visible, recursive = 0;
2006         if (!PyArg_ParseTuple(args,"i|i:setVisible",&visible, &recursive))
2007                 return NULL;
2008         
2009         SetVisible(visible ? true:false, recursive ? true:false);
2010         UpdateBuckets(recursive ? true:false);
2011         Py_RETURN_NONE;
2012         
2013 }
2014
2015 PyObject* KX_GameObject::PySetOcclusion(PyObject* args)
2016 {
2017         int occlusion, recursive = 0;
2018         if (!PyArg_ParseTuple(args,"i|i:setOcclusion",&occlusion, &recursive))
2019                 return NULL;
2020         
2021         SetOccluder(occlusion ? true:false, recursive ? true:false);
2022         Py_RETURN_NONE;
2023 }
2024
2025 PyObject* KX_GameObject::PyGetVisible()
2026 {
2027         ShowDeprecationWarning("getVisible()", "the visible property");
2028         return PyInt_FromLong(m_bVisible);      
2029 }
2030
2031 PyObject* KX_GameObject::PyGetState()
2032 {
2033         ShowDeprecationWarning("getState()", "the state property");
2034         int state = 0;
2035         state |= GetState();
2036         return PyInt_FromLong(state);
2037 }
2038
2039 PyObject* KX_GameObject::PySetState(PyObject* value)
2040 {
2041         ShowDeprecationWarning("setState()", "the state property");
2042         int state_i = PyInt_AsLong(value);
2043         unsigned int state = 0;
2044         
2045         if (state_i == -1 && PyErr_Occurred()) {
2046                 PyErr_SetString(PyExc_TypeError, "expected an int bit field");
2047                 return NULL;
2048         }
2049         
2050         state |= state_i;
2051         if ((state & ((1<<30)-1)) == 0) {
2052                 PyErr_SetString(PyExc_AttributeError, "The state bitfield was not between 0 and 30 (1<<0 and 1<<29)");
2053                 return NULL;
2054         }
2055         SetState(state);
2056         
2057         Py_RETURN_NONE;
2058 }
2059
2060 PyObject* KX_GameObject::PyGetVelocity(PyObject* args)
2061 {
2062         // only can get the velocity if we have a physics object connected to us...
2063         MT_Point3 point(0.0,0.0,0.0);
2064         PyObject* pypos = NULL;
2065         
2066         if (PyArg_ParseTuple(args, "|O:getVelocity", &pypos))
2067         {
2068                 if (pypos)
2069                         PyVecTo(pypos, point);
2070         }
2071         else {
2072                 return NULL;
2073         }
2074         
2075         if (m_pPhysicsController1)
2076         {
2077                 return PyObjectFrom(m_pPhysicsController1->GetVelocity(point));
2078         }
2079         else {
2080                 return PyObjectFrom(MT_Vector3(0.0,0.0,0.0));
2081         }
2082 }
2083
2084
2085
2086 PyObject* KX_GameObject::PyGetMass()
2087 {
2088         ShowDeprecationWarning("getMass()", "the mass property");
2089         return PyFloat_FromDouble((GetPhysicsController() != NULL) ? GetPhysicsController()->GetMass() : 0.0f);
2090 }
2091
2092 PyObject* KX_GameObject::PyGetReactionForce()
2093 {
2094         // only can get the velocity if we have a physics object connected to us...
2095         
2096         // XXX - Currently not working with bullet intergration, see KX_BulletPhysicsController.cpp's getReactionForce
2097         /*
2098         if (GetPhysicsController())
2099                 return PyObjectFrom(GetPhysicsController()->getReactionForce());
2100         return PyObjectFrom(dummy_point);
2101         */
2102         
2103         return Py_BuildValue("fff", 0.0f, 0.0f, 0.0f);
2104         
2105 }
2106
2107
2108
2109 PyObject* KX_GameObject::PyEnableRigidBody()
2110 {
2111         if(GetPhysicsController())
2112                 GetPhysicsController()->setRigidBody(true);
2113
2114         Py_RETURN_NONE;
2115 }
2116
2117
2118
2119 PyObject* KX_GameObject::PyDisableRigidBody()
2120 {
2121         if(GetPhysicsController())
2122                 GetPhysicsController()->setRigidBody(false);
2123
2124         Py_RETURN_NONE;
2125 }
2126
2127
2128
2129 PyObject* KX_GameObject::PyGetParent()
2130 {
2131         ShowDeprecationWarning("getParent()", "the parent property");
2132         KX_GameObject* parent = this->GetParent();
2133         if (parent) {
2134                 parent->Release(); /* self->GetParent() AddRef's */
2135                 return parent->GetProxy();
2136         }
2137         Py_RETURN_NONE;
2138 }
2139
2140 PyObject* KX_GameObject::PySetParent(PyObject* value)
2141 {
2142         KX_Scene *scene = KX_GetActiveScene();
2143         KX_GameObject *obj;
2144         
2145         if (!ConvertPythonToGameObject(value, &obj, false, "gameOb.setParent(value): KX_GameObject"))
2146                 return NULL;
2147         
2148         this->SetParent(scene, obj);
2149         Py_RETURN_NONE;
2150 }
2151
2152 PyObject* KX_GameObject::PyRemoveParent()
2153 {
2154         KX_Scene *scene = KX_GetActiveScene();
2155         
2156         this->RemoveParent(scene);
2157         Py_RETURN_NONE;
2158 }
2159
2160 PyObject* KX_GameObject::PyGetChildren()
2161 {
2162         return GetChildren()->NewProxy(true);
2163 }
2164
2165 PyObject* KX_GameObject::PyGetChildrenRecursive()
2166 {
2167         return GetChildrenRecursive()->NewProxy(true);
2168 }
2169
2170 PyObject* KX_GameObject::PyGetMesh(PyObject* args)
2171 {
2172         ShowDeprecationWarning("getMesh()", "the meshes property");
2173         
2174         int mesh = 0;
2175
2176         if (!PyArg_ParseTuple(args, "|i:getMesh", &mesh))
2177                 return NULL; // python sets a simple error
2178         
2179         if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0)
2180         {
2181                 KX_MeshProxy* meshproxy = new KX_MeshProxy(m_meshes[mesh]);
2182                 return meshproxy->NewProxy(true); // XXX Todo Python own.
2183         }
2184         
2185         Py_RETURN_NONE;
2186 }
2187
2188
2189
2190
2191
2192 PyObject* KX_GameObject::PySetCollisionMargin(PyObject* value)
2193 {
2194         float collisionMargin = PyFloat_AsDouble(value);
2195         
2196         if (collisionMargin==-1 && PyErr_Occurred()) {
2197                 PyErr_SetString(PyExc_TypeError, "expected a float");
2198                 return NULL;
2199         }
2200         
2201         if (m_pPhysicsController1)
2202         {
2203                 m_pPhysicsController1->setMargin(collisionMargin);
2204                 Py_RETURN_NONE;
2205         }
2206         PyErr_SetString(PyExc_RuntimeError, "This object has no physics controller");
2207         return NULL;
2208 }
2209
2210
2211
2212 PyObject* KX_GameObject::PyApplyImpulse(PyObject* args)
2213 {
2214         PyObject* pyattach;
2215         PyObject* pyimpulse;
2216         
2217         if (!m_pPhysicsController1)     {
2218                 PyErr_SetString(PyExc_RuntimeError, "This object has no physics controller");
2219                 return NULL;
2220         }
2221         
2222         if (PyArg_ParseTuple(args, "OO:applyImpulse", &pyattach, &pyimpulse))
2223         {
2224                 MT_Point3  attach;
2225                 MT_Vector3 impulse;
2226                 if (PyVecTo(pyattach, attach) && PyVecTo(pyimpulse, impulse))
2227                 {
2228                         m_pPhysicsController1->applyImpulse(attach, impulse);
2229                         Py_RETURN_NONE;
2230                 }
2231
2232         }
2233         
2234         return NULL;
2235 }
2236
2237
2238
2239 PyObject* KX_GameObject::PySuspendDynamics()
2240 {
2241         SuspendDynamics();
2242         Py_RETURN_NONE;
2243 }
2244
2245
2246
2247 PyObject* KX_GameObject::PyRestoreDynamics()
2248 {
2249         RestoreDynamics();
2250         Py_RETURN_NONE;
2251 }
2252
2253
2254
2255 PyObject* KX_GameObject::PyGetOrientation() //keywords
2256 {
2257         ShowDeprecationWarning("getOrientation()", "the orientation property");
2258         return PyObjectFrom(NodeGetWorldOrientation());
2259 }
2260
2261
2262
2263 PyObject* KX_GameObject::PySetOrientation(PyObject* value)
2264 {
2265         ShowDeprecationWarning("setOrientation()", "the orientation property");
2266         MT_Matrix3x3 rot;
2267         
2268         /* if value is not a sequence PyOrientationTo makes an error */
2269         if (!PyOrientationTo(value, rot, "gameOb.setOrientation(sequence): KX_GameObject, "))
2270                 return NULL;
2271
2272         NodeSetLocalOrientation(rot);
2273         NodeUpdateGS(0.f);
2274         Py_RETURN_NONE;
2275 }
2276
2277 PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* args)
2278 {
2279         PyObject* pyvect;
2280         int axis = 2; //z axis is the default
2281         float fac = 1.0;
2282         
2283         if (PyArg_ParseTuple(args,"O|if:alignAxisToVect",&pyvect,&axis, &fac))
2284         {
2285                 MT_Vector3 vect;
2286                 if (PyVecTo(pyvect, vect))
2287                 {
2288                         if (fac<=0.0) Py_RETURN_NONE; // Nothing to do.
2289                         if (fac> 1.0) fac= 1.0;
2290                         
2291                         AlignAxisToVect(vect,axis,fac);
2292                         NodeUpdateGS(0.f);
2293                         Py_RETURN_NONE;
2294                 }
2295         }
2296         return NULL;
2297 }
2298
2299 PyObject* KX_GameObject::PyGetAxisVect(PyObject* value)
2300 {
2301         MT_Vector3 vect;
2302         if (PyVecTo(value, vect))
2303         {
2304                 return PyObjectFrom(NodeGetWorldOrientation() * vect);
2305         }
2306         return NULL;
2307 }
2308
2309 PyObject* KX_GameObject::PySetPosition(PyObject* value)
2310 {
2311         ShowDeprecationWarning("setPosition()", "the position property");
2312         MT_Point3 pos;
2313         if (PyVecTo(value, pos))
2314         {
2315                 NodeSetLocalPosition(pos);
2316                 NodeUpdateGS(0.f);
2317                 Py_RETURN_NONE;
2318         }
2319
2320         return NULL;
2321 }
2322
2323 PyObject* KX_GameObject::PySetWorldPosition(PyObject* value)
2324 {
2325         ShowDeprecationWarning("setWorldPosition()", "the worldPosition property");
2326         MT_Point3 pos;
2327         if (PyVecTo(value, pos))
2328         {
2329                 NodeSetWorldPosition(pos);
2330                 NodeUpdateGS(0.f);
2331                 Py_RETURN_NONE;
2332         }
2333
2334         return NULL;
2335 }
2336
2337 PyObject* KX_GameObject::PyGetPhysicsId()
2338 {
2339         KX_IPhysicsController* ctrl = GetPhysicsController();
2340         uint_ptr physid=0;
2341         if (ctrl)
2342         {
2343                 physid= (uint_ptr)ctrl->GetUserData();
2344         }
2345         return PyInt_FromLong((long)physid);
2346 }
2347
2348 PyObject* KX_GameObject::PyGetPropertyNames()
2349 {
2350         PyObject *list=  ConvertKeysToPython();
2351         
2352         if(m_attr_dict) {
2353                 PyObject *key, *value;
2354                 Py_ssize_t pos = 0;
2355
2356                 while (PyDict_Next(m_attr_dict, &pos, &key, &value)) {
2357                         PyList_Append(list, key);
2358                 }
2359         }
2360         return list;
2361 }
2362
2363 KX_PYMETHODDEF_DOC_O(KX_GameObject, getDistanceTo,
2364 "getDistanceTo(other): get distance to another point/KX_GameObject")
2365 {
2366         MT_Point3 b;
2367         if (PyVecTo(value, b))
2368         {
2369                 return PyFloat_FromDouble(NodeGetWorldPosition().distance(b));
2370         }
2371         PyErr_Clear();
2372         
2373         KX_GameObject *other;
2374         if (ConvertPythonToGameObject(value, &other, false, "gameOb.getDistanceTo(value): KX_GameObject"))
2375         {
2376                 return PyFloat_FromDouble(NodeGetWorldPosition().distance(other->NodeGetWorldPosition()));
2377         }
2378         
2379         return NULL;
2380 }
2381
2382 KX_PYMETHODDEF_DOC_O(KX_GameObject, getVectTo,
2383 "getVectTo(other): get vector and the distance to another point/KX_GameObject\n"
2384 "Returns a 3-tuple with (distance,worldVector,localVector)\n")
2385 {
2386         MT_Point3 toPoint, fromPoint;
2387         MT_Vector3 toDir, locToDir;
2388         MT_Scalar distance;
2389
2390         PyObject *returnValue;
2391
2392         if (!PyVecTo(value, toPoint))
2393         {
2394                 PyErr_Clear();
2395                 
2396                 KX_GameObject *other;
2397                 if (ConvertPythonToGameObject(value, &other, false, "")) /* error will be overwritten */
2398                 {
2399                         toPoint = other->NodeGetWorldPosition();
2400                 } else
2401                 {
2402                         PyErr_SetString(PyExc_TypeError, "gameOb.getVectTo(other): KX_GameObject, expected a 3D Vector or KX_GameObject type");
2403                         return NULL;
2404                 }
2405         }
2406
2407         fromPoint = NodeGetWorldPosition();
2408         toDir = toPoint-fromPoint;
2409         distance = toDir.length();
2410
2411         if (MT_fuzzyZero(distance))
2412         {
2413                 //cout << "getVectTo() Error: Null vector!\n";
2414                 locToDir = toDir = MT_Vector3(0.0,0.0,0.0);
2415                 distance = 0.0;
2416         } else {
2417                 toDir.normalize();
2418                 locToDir = toDir * NodeGetWorldOrientation();
2419         }
2420         
2421         returnValue = PyTuple_New(3);
2422         if (returnValue) { // very unlikely to fail, python sets a memory error here.
2423                 PyTuple_SET_ITEM(returnValue, 0, PyFloat_FromDouble(distance));
2424                 PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(toDir));
2425                 PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(locToDir));
2426         }
2427         return returnValue;
2428 }
2429
2430 bool KX_GameObject::RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data)
2431 {
2432         KX_GameObject* hitKXObj = client->m_gameobject;
2433         
2434         // if X-ray option is selected, the unwnted objects were not tested, so get here only with true hit
2435         // if not, all objects were tested and the front one may not be the correct one.
2436         if (m_xray || m_testPropName.Length() == 0 || hitKXObj->GetProperty(m_testPropName) != NULL)
2437         {
2438                 m_pHitObject = hitKXObj;
2439                 return true;
2440         }
2441         // return true to stop RayCast::RayTest from looping, the above test was decisive
2442         // We would want to loop only if we want to get more than one hit point
2443         return true;
2444 }
2445
2446 /* this function is used to pre-filter the object before casting the ray on them.
2447    This is useful for "X-Ray" option when we want to see "through" unwanted object.
2448  */
2449 bool KX_GameObject::NeedRayCast(KX_ClientObjectInfo* client)
2450 {
2451         KX_GameObject* hitKXObj = client->m_gameobject;
2452         
2453         if (client->m_type > KX_ClientObjectInfo::ACTOR)
2454         {
2455                 // Unknown type of object, skip it.
2456                 // Should not occur as the sensor objects are filtered in RayTest()
2457                 printf("Invalid client type %d found in ray casting\n", client->m_type);
2458                 return false;
2459         }
2460         
2461         // if X-Ray option is selected, skip object that don't match the criteria as we see through them
2462         // if not, test all objects because we don't know yet which one will be on front
2463         if (!m_xray || m_testPropName.Length() == 0 || hitKXObj->GetProperty(m_testPropName) != NULL)
2464         {
2465                 return true;
2466         }
2467         // skip the object
2468         return false;
2469 }
2470
2471 KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo,
2472 "rayCastTo(other,dist,prop): look towards another point/KX_GameObject and return first object hit within dist that matches prop\n"
2473 " prop = property name that object must have; can be omitted => detect any object\n"
2474 " dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to other\n"
2475 " other = 3-tuple or object reference")
2476 {
2477         MT_Point3 toPoint;
2478         PyObject* pyarg;
2479         float dist = 0.0f;
2480         char *propName = NULL;
2481
2482         if (!PyArg_ParseTuple(args,"O|fs:rayCastTo", &pyarg, &dist, &propName)) {
2483                 return NULL; // python sets simple error
2484         }
2485
2486         if (!PyVecTo(pyarg, toPoint))
2487         {
2488                 KX_GameObject *other;
2489                 PyErr_Clear();
2490                 
2491                 if (ConvertPythonToGameObject(pyarg, &other, false, "")) /* error will be overwritten */
2492                 {
2493                         toPoint = other->NodeGetWorldPosition();
2494                 } else
2495                 {
2496                         PyErr_SetString(PyExc_TypeError, "gameOb.rayCastTo(other,dist,prop): KX_GameObject, the first argument to rayCastTo must be a vector or a KX_GameObject");
2497                         return NULL;
2498                 }
2499         }
2500         MT_Point3 fromPoint = NodeGetWorldPosition();
2501         if (dist != 0.0f)
2502         {
2503                 MT_Vector3 toDir = toPoint-fromPoint;
2504                 toDir.normalize();
2505                 toPoint = fromPoint + (dist) * toDir;
2506         }
2507
2508         PHY_IPhysicsEnvironment* pe = GetPhysicsEnvironment();
2509         KX_IPhysicsController *spc = GetPhysicsController();
2510         KX_GameObject *parent = GetParent();
2511         if (!spc && parent)
2512                 spc = parent->GetPhysicsController();
2513         if (parent)
2514                 parent->Release();
2515         
2516         m_pHitObject = NULL;
2517         if (propName)
2518                 m_testPropName = propName;
2519         else
2520                 m_testPropName.SetLength(0);
2521         KX_RayCast::Callback<KX_GameObject> callback(this,spc);
2522         KX_RayCast::RayTest(pe, fromPoint, toPoint, callback);
2523
2524     if (m_pHitObject)
2525                 return m_pHitObject->GetProxy();
2526         
2527         Py_RETURN_NONE;
2528 }
2529
2530 KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
2531                                    "rayCast(to,from,dist,prop,face,xray,poly): cast a ray and return 3-tuple (object,hit,normal) or 4-tuple (object,hit,normal,polygon) of contact point with object within dist that matches prop.\n"
2532                                    " If no hit, return (None,None,None) or (None,None,None,None).\n"
2533 " to   = 3-tuple or object reference for destination of ray (if object, use center of object)\n"
2534 " from = 3-tuple or object reference for origin of ray (if object, use center of object)\n"
2535 "        Can be None or omitted => start from self object center\n"
2536 " dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to to\n"
2537 " prop = property name that object must have; can be omitted => detect any object\n"
2538 " face = normal option: 1=>return face normal; 0 or omitted => normal is oriented towards origin\n"
2539 " xray = X-ray option: 1=>skip objects that don't match prop; 0 or omitted => stop on first object\n"
2540 " poly = polygon option: 1=>return value is a 4-tuple and the 4th element is a KX_PolyProxy object\n"
2541 "                           which can be None if hit object has no mesh or if there is no hit\n"
2542 "        If 0 or omitted, return value is a 3-tuple\n"
2543 "Note: The object on which you call this method matters: the ray will ignore it.\n"
2544 "      prop and xray option interact as follow:\n"
2545 "        prop off, xray off: return closest hit or no hit if there is no object on the full extend of the ray\n"
2546 "        prop off, xray on : idem\n"
2547 "        prop on,  xray off: return closest hit if it matches prop, no hit otherwise\n"
2548 "        prop on,  xray on : return closest hit matching prop or no hit if there is no object matching prop on the full extend of the ray\n")
2549 {
2550         MT_Point3 toPoint;
2551         MT_Point3 fromPoint;
2552         PyObject* pyto;
2553         PyObject* pyfrom = NULL;
2554         float dist = 0.0f;
2555         char *propName = NULL;
2556         KX_GameObject *other;
2557         int face=0, xray=0, poly=0;
2558
2559         if (!PyArg_ParseTuple(args,"O|Ofsiii:rayCast", &pyto, &pyfrom, &dist, &propName, &face, &xray, &poly)) {
2560                 return NULL; // Python sets a simple error
2561         }
2562
2563         if (!PyVecTo(pyto, toPoint))
2564         {
2565                 PyErr_Clear();
2566                 
2567                 if (ConvertPythonToGameObject(pyto, &other, false, ""))  /* error will be overwritten */
2568                 {
2569                         toPoint = other->NodeGetWorldPosition();
2570                 } else
2571                 {
2572                         PyErr_SetString(PyExc_TypeError, "the first argument to rayCast must be a vector or a KX_GameObject");
2573                         return NULL;
2574                 }
2575         }
2576         if (!pyfrom || pyfrom == Py_None)
2577         {
2578                 fromPoint = NodeGetWorldPosition();
2579         }
2580         else if (!PyVecTo(pyfrom, fromPoint))
2581         {
2582                 PyErr_Clear();
2583                 
2584                 if (ConvertPythonToGameObject(pyfrom, &other, false, "")) /* error will be overwritten */
2585                 {
2586                         fromPoint = other->NodeGetWorldPosition();
2587                 } else
2588                 {
2589                         PyErr_SetString(PyExc_TypeError, "gameOb.rayCast(to,from,dist,prop,face,xray,poly): KX_GameObject, the second optional argument to rayCast must be a vector or a KX_GameObject");
2590                         return NULL;
2591                 }
2592         }
2593         
2594         if (dist != 0.0f) {
2595                 MT_Vector3 toDir = toPoint-fromPoint;
2596                 if (MT_fuzzyZero(toDir.length2())) {
2597                         return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
2598                 }
2599                 toDir.normalize();
2600                 toPoint = fromPoint + (dist) * toDir;
2601         } else if (MT_fuzzyZero((toPoint-fromPoint).length2())) {
2602                 return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
2603         }
2604         
2605         PHY_IPhysicsEnvironment* pe = GetPhysicsEnvironment();
2606         KX_IPhysicsController *spc = GetPhysicsController();
2607         KX_GameObject *parent = GetParent();
2608         if (!spc && parent)
2609                 spc = parent->GetPhysicsController();
2610         if (parent)
2611                 parent->Release();
2612         
2613         m_pHitObject = NULL;
2614         if (propName)
2615                 m_testPropName = propName;
2616         else
2617                 m_testPropName.SetLength(0);
2618         m_xray = xray;
2619         // to get the hit results
2620         KX_RayCast::Callback<KX_GameObject> callback(this,spc,NULL,face);
2621         KX_RayCast::RayTest(pe, fromPoint, toPoint, callback);
2622
2623         if (m_pHitObject)
2624         {
2625                 PyObject* returnValue = (poly) ? PyTuple_New(4) : PyTuple_New(3);
2626                 if (returnValue) { // unlikely this would ever fail, if it does python sets an error
2627                         PyTuple_SET_ITEM(returnValue, 0, m_pHitObject->GetProxy());
2628                         PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(callback.m_hitPoint));
2629                         PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(callback.m_hitNormal));
2630                         if (poly)
2631                         {
2632                                 if (callback.m_hitMesh)
2633                                 {
2634                                         // if this field is set, then we can trust that m_hitPolygon is a valid polygon
2635                                         RAS_Polygon* polygon = callback.m_hitMesh->GetPolygon(callback.m_hitPolygon);
2636                                         KX_PolyProxy* polyproxy = new KX_PolyProxy(callback.m_hitMesh, polygon);
2637                                         PyTuple_SET_ITEM(returnValue, 3, polyproxy->NewProxy(true));
2638                                 }
2639                                 else
2640                                 {
2641                                         Py_INCREF(Py_None);
2642                                         PyTuple_SET_ITEM(returnValue, 3, Py_None);
2643                                 }
2644                         }
2645                 }
2646                 return returnValue;
2647         }
2648         // no hit
2649         if (poly)
2650                 return Py_BuildValue("OOOO", Py_None, Py_None, Py_None, Py_None);
2651         else
2652                 return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
2653 }
2654
2655 KX_PYMETHODDEF_DOC_VARARGS(KX_GameObject, sendMessage, 
2656                                                    "sendMessage(subject, [body, to])\n"
2657 "sends a message in same manner as a message actuator"
2658 "subject = Subject of the message (string)"
2659 "body = Message body (string)"
2660 "to = Name of object to send the message to")
2661 {
2662         KX_Scene *scene = KX_GetActiveScene();
2663         char* subject;
2664         char* body = (char *)"";
2665         char* to = (char *)"";
2666         const STR_String& from = GetName();
2667
2668         if (!PyArg_ParseTuple(args, "s|sss:sendMessage", &subject, &body, &to))
2669                 return NULL;
2670         
2671         scene->GetNetworkScene()->SendMessage(to, from, subject, body);
2672         Py_RETURN_NONE;
2673 }
2674
2675 /* --------------------------------------------------------------------- 
2676  * Some stuff taken from the header
2677  * --------------------------------------------------------------------- */
2678 void KX_GameObject::Relink(GEN_Map<GEN_HashedPtr, void*> *map_parameter)        
2679 {
2680         // we will relink the sensors and actuators that use object references
2681         // if the object is part of the replicated hierarchy, use the new
2682         // object reference instead
2683         SCA_SensorList& sensorlist = GetSensors();
2684         SCA_SensorList::iterator sit;
2685         for (sit=sensorlist.begin(); sit != sensorlist.end(); sit++)
2686         {
2687                 (*sit)->Relink(map_parameter);
2688         }
2689         SCA_ActuatorList& actuatorlist = GetActuators();
2690         SCA_ActuatorList::iterator ait;
2691         for (ait=actuatorlist.begin(); ait != actuatorlist.end(); ait++)
2692         {
2693                 (*ait)->Relink(map_parameter);
2694         }
2695 }
2696
2697 bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py_none_ok, const char *error_prefix)
2698 {
2699         if (value==NULL) {
2700                 PyErr_Format(PyExc_TypeError, "%s, python pointer NULL, should never happen", error_prefix);
2701                 *object = NULL;
2702                 return false;
2703         }
2704                 
2705         if (value==Py_None) {
2706                 *object = NULL;
2707                 
2708                 if (py_none_ok) {
2709                         return true;
2710                 } else {
2711                         PyErr_Format(PyExc_TypeError, "%s, expected KX_GameObject or a KX_GameObject name, None is invalid", error_prefix);
2712                         return false;
2713                 }
2714         }
2715         
2716         if (PyString_Check(value)) {
2717                 *object = (KX_GameObject*)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String( PyString_AsString(value) ));
2718                 
2719                 if (*object) {
2720                         return true;
2721                 } else {
2722                         PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_GameObject in this scene", error_prefix, PyString_AsString(value));
2723                         return false;
2724                 }
2725         }
2726         
2727         if (PyObject_TypeCheck(value, &KX_GameObject::Type)) {
2728                 *object = static_cast<KX_GameObject*>BGE_PROXY_REF(value);
2729                 
2730                 /* sets the error */
2731                 if (*object==NULL) {
2732                         PyErr_Format(PyExc_SystemError, "%s, " BGE_PROXY_ERROR_MSG, error_prefix);
2733                         return false;
2734                 }
2735                 
2736                 return true;
2737         }
2738         
2739         *object = NULL;
2740         
2741         if (py_none_ok) {
2742                 PyErr_Format(PyExc_TypeError, "%s, expect a KX_GameObject, a string or None", error_prefix);
2743         } else {
2744                 PyErr_Format(PyExc_TypeError, "%s, expect a KX_GameObject or a string", error_prefix);
2745         }
2746         
2747         return false;
2748 }