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