BGE Animations: The return type for KX_GameObject.getActionFrame() was an integer...
[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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 /** \file gameengine/Ketsji/KX_GameObject.cpp
32  *  \ingroup ketsji
33  */
34
35
36 #if defined(_WIN64)
37 typedef unsigned __int64 uint_ptr;
38 #else
39 typedef unsigned long uint_ptr;
40 #endif
41
42 #if defined(WIN32) && !defined(FREE_WINDOWS)
43 // This warning tells us about truncation of __long__ stl-generated names.
44 // It can occasionally cause DevStudio to have internal compiler warnings.
45 #pragma warning( disable : 4786 )     
46 #endif
47
48
49 #define KX_INERTIA_INFINITE 10000
50 #include "RAS_IPolygonMaterial.h"
51 #include "KX_BlenderMaterial.h"
52 #include "KX_GameObject.h"
53 #include "KX_Camera.h" // only for their ::Type
54 #include "KX_Light.h"  // only for their ::Type
55 #include "KX_FontObject.h"  // only for their ::Type
56 #include "RAS_MeshObject.h"
57 #include "KX_MeshProxy.h"
58 #include "KX_PolyProxy.h"
59 #include <stdio.h> // printf
60 #include "SG_Controller.h"
61 #include "KX_IPhysicsController.h"
62 #include "PHY_IGraphicController.h"
63 #include "SG_Node.h"
64 #include "SG_Controller.h"
65 #include "KX_ClientObjectInfo.h"
66 #include "RAS_BucketManager.h"
67 #include "KX_RayCast.h"
68 #include "KX_PythonInit.h"
69 #include "KX_PyMath.h"
70 #include "KX_PythonSeq.h"
71 #include "KX_ConvertPhysicsObject.h"
72 #include "SCA_IActuator.h"
73 #include "SCA_ISensor.h"
74 #include "SCA_IController.h"
75 #include "NG_NetworkScene.h" //Needed for sendMessage()
76
77 #include "BL_ActionManager.h"
78
79 #include "PyObjectPlus.h" /* python stuff */
80
81 // This file defines relationships between parents and children
82 // in the game engine.
83
84 #include "KX_SG_NodeRelationships.h"
85
86 #include "BLI_math.h"
87
88 static MT_Point3 dummy_point= MT_Point3(0.0, 0.0, 0.0);
89 static MT_Vector3 dummy_scaling = MT_Vector3(1.0, 1.0, 1.0);
90 static MT_Matrix3x3 dummy_orientation = MT_Matrix3x3(   1.0, 0.0, 0.0,
91                                                                                                                 0.0, 1.0, 0.0,
92                                                                                                                 0.0, 0.0, 1.0);
93
94 KX_GameObject::KX_GameObject(
95         void* sgReplicationInfo,
96         SG_Callbacks callbacks)
97         : SCA_IObject(),
98         m_bDyna(false),
99         m_layer(0),
100         m_pBlenderObject(NULL),
101         m_pBlenderGroupObject(NULL),
102         m_bSuspendDynamics(false),
103         m_bUseObjectColor(false),
104         m_bIsNegativeScaling(false),
105         m_bVisible(true),
106         m_bCulled(true),
107         m_bOccluder(false),
108         m_pPhysicsController1(NULL),
109         m_pGraphicController(NULL),
110         m_xray(false),
111         m_pHitObject(NULL),
112     m_actionManager(NULL),
113         m_isDeformable(false)
114 #ifdef WITH_PYTHON
115         , m_attr_dict(NULL)
116 #endif
117 {
118         m_ignore_activity_culling = false;
119         m_pClient_info = new KX_ClientObjectInfo(this, KX_ClientObjectInfo::ACTOR);
120         m_pSGNode = new SG_Node(this,sgReplicationInfo,callbacks);
121
122         // define the relationship between this node and it's parent.
123         
124         KX_NormalParentRelation * parent_relation = 
125                 KX_NormalParentRelation::New();
126         m_pSGNode->SetParentRelation(parent_relation);
127 };
128
129
130
131 KX_GameObject::~KX_GameObject()
132 {
133         RemoveMeshes();
134
135         // is this delete somewhere ?
136         //if (m_sumoObj)
137         //      delete m_sumoObj;
138         delete m_pClient_info;
139         //if (m_pSGNode)
140         //      delete m_pSGNode;
141         if (m_pSGNode)
142         {
143                 // must go through controllers and make sure they will not use us anymore
144                 // This is important for KX_BulletPhysicsControllers that unregister themselves
145                 // from the object when they are deleted.
146                 SGControllerList::iterator contit;
147                 SGControllerList& controllers = m_pSGNode->GetSGControllerList();
148                 for (contit = controllers.begin();contit!=controllers.end();++contit)
149                 {
150                         (*contit)->ClearObject();
151                 }
152                 m_pSGNode->SetSGClientObject(NULL);
153
154                 /* m_pSGNode is freed in KX_Scene::RemoveNodeDestructObject */
155         }
156         if (m_pGraphicController)
157         {
158                 delete m_pGraphicController;
159         }
160         if (m_actionManager)
161         {
162                 delete m_actionManager;
163         }
164 #ifdef WITH_PYTHON
165         if (m_attr_dict) {
166                 PyDict_Clear(m_attr_dict); /* incase of circular refs or other weird cases */
167                 /* Py_CLEAR: Py_DECREF's and NULL's */
168                 Py_CLEAR(m_attr_dict);
169         }
170 #endif // WITH_PYTHON
171 }
172
173 KX_GameObject* KX_GameObject::GetClientObject(KX_ClientObjectInfo* info)
174 {
175         if (!info)
176                 return NULL;
177         return info->m_gameobject;
178 }
179
180 CValue* KX_GameObject:: Calc(VALUE_OPERATOR op, CValue *val) 
181 {
182         return NULL;
183 }
184
185
186
187 CValue* KX_GameObject::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val)
188 {
189         return NULL;
190 }
191
192
193
194 const STR_String & KX_GameObject::GetText()
195 {
196         return m_text;
197 }
198
199
200
201 double KX_GameObject::GetNumber()
202 {
203         return 0;
204 }
205
206
207
208 STR_String& KX_GameObject::GetName()
209 {
210         return m_name;
211 }
212
213
214
215 void KX_GameObject::SetName(const char *name)
216 {
217         m_name = name;
218 };                                                              // Set the name of the value
219
220 KX_IPhysicsController* KX_GameObject::GetPhysicsController()
221 {
222         return m_pPhysicsController1;
223 }
224
225 KX_GameObject* KX_GameObject::GetParent()
226 {
227         KX_GameObject* result = NULL;
228         SG_Node* node = m_pSGNode;
229         
230         while (node && !result)
231         {
232                 node = node->GetSGParent();
233                 if (node)
234                         result = (KX_GameObject*)node->GetSGClientObject();
235         }
236         
237         if (result)
238                 result->AddRef();
239
240         return result;
241         
242 }
243
244 void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj, bool addToCompound, bool ghost)
245 {
246         // check on valid node in case a python controller holds a reference to a deleted object
247         if (obj && 
248                 GetSGNode() &&                  // object is not zombi
249                 obj->GetSGNode() &&             // object is not zombi
250                 GetSGNode()->GetSGParent() != obj->GetSGNode() &&       // not already parented to same object
251                 !GetSGNode()->IsAncessor(obj->GetSGNode()) &&           // no parenting loop
252                 this != obj)                                                                            // not the object itself
253         {
254                 // Make sure the objects have some scale
255                 MT_Vector3 scale1 = NodeGetWorldScaling();
256                 MT_Vector3 scale2 = obj->NodeGetWorldScaling();
257                 if (fabs(scale2[0]) < FLT_EPSILON || 
258                         fabs(scale2[1]) < FLT_EPSILON || 
259                         fabs(scale2[2]) < FLT_EPSILON || 
260                         fabs(scale1[0]) < FLT_EPSILON || 
261                         fabs(scale1[1]) < FLT_EPSILON || 
262                         fabs(scale1[2]) < FLT_EPSILON) { return; }
263
264                 // Remove us from our old parent and set our new parent
265                 RemoveParent(scene);
266                 obj->GetSGNode()->AddChild(GetSGNode());
267
268                 if (m_pPhysicsController1) 
269                 {
270                         m_pPhysicsController1->SuspendDynamics(ghost);
271                 }
272                 // Set us to our new scale, position, and orientation
273                 scale2[0] = 1.0/scale2[0];
274                 scale2[1] = 1.0/scale2[1];
275                 scale2[2] = 1.0/scale2[2];
276                 scale1 = scale1 * scale2;
277                 MT_Matrix3x3 invori = obj->NodeGetWorldOrientation().inverse();
278                 MT_Vector3 newpos = invori*(NodeGetWorldPosition()-obj->NodeGetWorldPosition())*scale2;
279
280                 NodeSetLocalScale(scale1);
281                 NodeSetLocalPosition(MT_Point3(newpos[0],newpos[1],newpos[2]));
282                 NodeSetLocalOrientation(invori*NodeGetWorldOrientation());
283                 NodeUpdateGS(0.f);
284                 // object will now be a child, it must be removed from the parent list
285                 CListValue* rootlist = scene->GetRootParentList();
286                 if (rootlist->RemoveValue(this))
287                         // the object was in parent list, decrement ref count as it's now removed
288                         Release();
289                 // if the new parent is a compound object, add this object shape to the compound shape.
290                 // step 0: verify this object has physical controller
291                 if (m_pPhysicsController1 && addToCompound)
292                 {
293                         // step 1: find the top parent (not necessarily obj)
294                         KX_GameObject* rootobj = (KX_GameObject*)obj->GetSGNode()->GetRootSGParent()->GetSGClientObject();
295                         // step 2: verify it has a physical controller and compound shape
296                         if (rootobj != NULL && 
297                                 rootobj->m_pPhysicsController1 != NULL &&
298                                 rootobj->m_pPhysicsController1->IsCompound())
299                         {
300                                 rootobj->m_pPhysicsController1->AddCompoundChild(m_pPhysicsController1);
301                         }
302                 }
303                 // graphically, the object hasn't change place, no need to update m_pGraphicController
304         }
305 }
306
307 void KX_GameObject::RemoveParent(KX_Scene *scene)
308 {
309         // check on valid node in case a python controller holds a reference to a deleted object
310         if (GetSGNode() && GetSGNode()->GetSGParent())
311         {
312                 // get the root object to remove us from compound object if needed
313                 KX_GameObject* rootobj = (KX_GameObject*)GetSGNode()->GetRootSGParent()->GetSGClientObject();
314                 // Set us to the right spot 
315                 GetSGNode()->SetLocalScale(GetSGNode()->GetWorldScaling());
316                 GetSGNode()->SetLocalOrientation(GetSGNode()->GetWorldOrientation());
317                 GetSGNode()->SetLocalPosition(GetSGNode()->GetWorldPosition());
318
319                 // Remove us from our parent
320                 GetSGNode()->DisconnectFromParent();
321                 NodeUpdateGS(0.f);
322                 // the object is now a root object, add it to the parentlist
323                 CListValue* rootlist = scene->GetRootParentList();
324                 if (!rootlist->SearchValue(this))
325                         // object was not in root list, add it now and increment ref count
326                         rootlist->Add(AddRef());
327                 if (m_pPhysicsController1) 
328                 {
329                         // in case this controller was added as a child shape to the parent
330                         if (rootobj != NULL && 
331                                 rootobj->m_pPhysicsController1 != NULL &&
332                                 rootobj->m_pPhysicsController1->IsCompound())
333                         {
334                                 rootobj->m_pPhysicsController1->RemoveCompoundChild(m_pPhysicsController1);
335                         }
336                         m_pPhysicsController1->RestoreDynamics();
337                         if (m_pPhysicsController1->IsDyna() && (rootobj != NULL && rootobj->m_pPhysicsController1))
338                         {
339                                 // dynamic object should remember the velocity they had while being parented
340                                 MT_Point3 childPoint = GetSGNode()->GetWorldPosition();
341                                 MT_Point3 rootPoint = rootobj->GetSGNode()->GetWorldPosition();
342                                 MT_Point3 relPoint;
343                                 relPoint = (childPoint-rootPoint);
344                                 MT_Vector3 linVel = rootobj->m_pPhysicsController1->GetVelocity(relPoint);
345                                 MT_Vector3 angVel = rootobj->m_pPhysicsController1->GetAngularVelocity();
346                                 m_pPhysicsController1->SetLinearVelocity(linVel, false);
347                                 m_pPhysicsController1->SetAngularVelocity(angVel, false);
348                         }
349                 }
350                 // graphically, the object hasn't change place, no need to update m_pGraphicController
351         }
352 }
353
354 BL_ActionManager* KX_GameObject::GetActionManager()
355 {
356         // We only want to create an action manager if we need it
357         if (!m_actionManager)
358                 m_actionManager = new BL_ActionManager(this);
359
360         return m_actionManager;
361 }
362
363 bool KX_GameObject::PlayAction(const char* name,
364                                                                 float start,
365                                                                 float end,
366                                                                 short layer,
367                                                                 short priority,
368                                                                 float blendin,
369                                                                 short play_mode,
370                                                                 float layer_weight,
371                                                                 short ipo_flags,
372                                                                 float playback_speed)
373 {
374         return GetActionManager()->PlayAction(name, start, end, layer, priority, blendin, play_mode, layer_weight, ipo_flags, playback_speed);
375 }
376
377 void KX_GameObject::StopAction(short layer)
378 {
379         GetActionManager()->StopAction(layer);
380 }
381
382 bool KX_GameObject::IsActionDone(short layer)
383 {
384         return GetActionManager()->IsActionDone(layer);
385 }
386
387 void KX_GameObject::UpdateActionManager(float curtime)
388 {
389         GetActionManager()->Update(curtime);
390 }
391
392 float KX_GameObject::GetActionFrame(short layer)
393 {
394         return GetActionManager()->GetActionFrame(layer);
395 }
396
397 void KX_GameObject::SetActionFrame(short layer, float frame)
398 {
399         GetActionManager()->SetActionFrame(layer, frame);
400 }
401
402 bAction *KX_GameObject::GetCurrentAction(short layer)
403 {
404         return GetActionManager()->GetCurrentAction(layer);
405 }
406
407 void KX_GameObject::SetPlayMode(short layer, short mode)
408 {
409         GetActionManager()->SetPlayMode(layer, mode);
410 }
411
412 void KX_GameObject::SetTimes(short layer, float start, float end)
413 {
414         GetActionManager()->SetTimes(layer, start, end);
415 }
416
417 void KX_GameObject::ProcessReplica()
418 {
419         SCA_IObject::ProcessReplica();
420         
421         m_pPhysicsController1 = NULL;
422         m_pGraphicController = NULL;
423         m_pSGNode = NULL;
424         m_pClient_info = new KX_ClientObjectInfo(*m_pClient_info);
425         m_pClient_info->m_gameobject = this;
426         if (m_actionManager)
427                 m_actionManager = new BL_ActionManager(this);
428         m_state = 0;
429
430 #ifdef WITH_PYTHON
431         if(m_attr_dict)
432                 m_attr_dict= PyDict_Copy(m_attr_dict);
433 #endif
434                 
435 }
436
437 static void setGraphicController_recursive(SG_Node* node)
438 {
439         NodeList& children = node->GetSGChildren();
440
441         for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
442         {
443                 SG_Node* childnode = (*childit);
444                 KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject());
445                 if (clientgameobj != NULL) // This is a GameObject
446                         clientgameobj->ActivateGraphicController(false);
447                 
448                 // if the childobj is NULL then this may be an inverse parent link
449                 // so a non recursive search should still look down this node.
450                 setGraphicController_recursive(childnode);
451         }
452 }
453
454
455 void KX_GameObject::ActivateGraphicController(bool recurse)
456 {
457         if (m_pGraphicController)
458         {
459                 m_pGraphicController->Activate(m_bVisible);
460         }
461         if (recurse)
462         {
463                 setGraphicController_recursive(GetSGNode());
464         }
465 }
466
467
468 CValue* KX_GameObject::GetReplica()
469 {
470         KX_GameObject* replica = new KX_GameObject(*this);
471
472         // this will copy properties and so on...
473         replica->ProcessReplica();
474
475         return replica;
476 }
477
478
479
480 void KX_GameObject::ApplyForce(const MT_Vector3& force,bool local)
481 {
482         if (m_pPhysicsController1)
483                 m_pPhysicsController1->ApplyForce(force,local);
484 }
485
486
487
488 void KX_GameObject::ApplyTorque(const MT_Vector3& torque,bool local)
489 {
490         if (m_pPhysicsController1)
491                 m_pPhysicsController1->ApplyTorque(torque,local);
492 }
493
494
495
496 void KX_GameObject::ApplyMovement(const MT_Vector3& dloc,bool local)
497 {
498         if (GetSGNode()) 
499         {
500                 if (m_pPhysicsController1) // (IsDynamic())
501                 {
502                         m_pPhysicsController1->RelativeTranslate(dloc,local);
503                 }
504                 GetSGNode()->RelativeTranslate(dloc,GetSGNode()->GetSGParent(),local);
505         }
506 }
507
508
509
510 void KX_GameObject::ApplyRotation(const MT_Vector3& drot,bool local)
511 {
512         MT_Matrix3x3 rotmat(drot);
513         
514         if (GetSGNode()) {
515                 GetSGNode()->RelativeRotate(rotmat,local);
516
517                 if (m_pPhysicsController1) { // (IsDynamic())
518                         m_pPhysicsController1->RelativeRotate(rotmat,local); 
519                 }
520         }
521 }
522
523
524
525 /**
526 GetOpenGL Matrix, returns an OpenGL 'compatible' matrix
527 */
528 double* KX_GameObject::GetOpenGLMatrix()
529 {
530         // todo: optimize and only update if necessary
531         double* fl = m_OpenGL_4x4Matrix.getPointer();
532         if (GetSGNode()) {
533                 MT_Transform trans;
534         
535                 trans.setOrigin(GetSGNode()->GetWorldPosition());
536                 trans.setBasis(GetSGNode()->GetWorldOrientation());
537         
538                 MT_Vector3 scaling = GetSGNode()->GetWorldScaling();
539                 m_bIsNegativeScaling = ((scaling[0] < 0.0) ^ (scaling[1] < 0.0) ^ (scaling[2] < 0.0)) ? true : false;
540                 trans.scale(scaling[0], scaling[1], scaling[2]);
541                 trans.getValue(fl);
542                 GetSGNode()->ClearDirty();
543         }
544         return fl;
545 }
546
547 void KX_GameObject::UpdateBlenderObjectMatrix(Object* blendobj)
548 {
549         if (!blendobj)
550                 blendobj = m_pBlenderObject;
551         if (blendobj) {
552                 const MT_Matrix3x3& rot = NodeGetWorldOrientation();
553                 const MT_Vector3& scale = NodeGetWorldScaling();
554                 const MT_Vector3& pos = NodeGetWorldPosition();
555                 rot.getValue(blendobj->obmat[0]);
556                 pos.getValue(blendobj->obmat[3]);
557                 mul_v3_fl(blendobj->obmat[0], scale[0]);
558                 mul_v3_fl(blendobj->obmat[1], scale[1]);
559                 mul_v3_fl(blendobj->obmat[2], scale[2]);
560         }
561 }
562
563 void KX_GameObject::AddMeshUser()
564 {
565         for (size_t i=0;i<m_meshes.size();i++)
566         {
567                 m_meshes[i]->AddMeshUser(this, &m_meshSlots, GetDeformer());
568         }
569         // set the part of the mesh slot that never change
570         double* fl = GetOpenGLMatrixPtr()->getPointer();
571
572         SG_QList::iterator<RAS_MeshSlot> mit(m_meshSlots);
573 //      RAS_MeshSlot* ms;
574         for(mit.begin(); !mit.end(); ++mit)
575         {
576                 (*mit)->m_OpenGLMatrix = fl;
577         }
578         UpdateBuckets(false);
579 }
580
581 static void UpdateBuckets_recursive(SG_Node* node)
582 {
583         NodeList& children = node->GetSGChildren();
584
585         for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
586         {
587                 SG_Node* childnode = (*childit);
588                 KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject());
589                 if (clientgameobj != NULL) // This is a GameObject
590                         clientgameobj->UpdateBuckets(0);
591                 
592                 // if the childobj is NULL then this may be an inverse parent link
593                 // so a non recursive search should still look down this node.
594                 UpdateBuckets_recursive(childnode);
595         }
596 }
597
598 void KX_GameObject::UpdateBuckets( bool recursive )
599 {
600         if (GetSGNode()) {
601                 RAS_MeshSlot *ms;
602
603                 if (GetSGNode()->IsDirty())
604                         GetOpenGLMatrix();
605
606                 SG_QList::iterator<RAS_MeshSlot> mit(m_meshSlots);
607                 for(mit.begin(); !mit.end(); ++mit)
608                 {
609                         ms = *mit;
610                         ms->m_bObjectColor = m_bUseObjectColor;
611                         ms->m_RGBAcolor = m_objectColor;
612                         ms->m_bVisible = m_bVisible;
613                         ms->m_bCulled = m_bCulled || !m_bVisible;
614                         if (!ms->m_bCulled) 
615                                 ms->m_bucket->ActivateMesh(ms);
616                         
617                         /* split if necessary */
618 #ifdef USE_SPLIT
619                         ms->Split();
620 #endif
621                 }
622         
623                 if (recursive) {
624                         UpdateBuckets_recursive(GetSGNode());
625                 }
626         }
627 }
628
629 void KX_GameObject::RemoveMeshes()
630 {
631         for (size_t i=0;i<m_meshes.size();i++)
632                 m_meshes[i]->RemoveFromBuckets(this);
633
634         //note: meshes can be shared, and are deleted by KX_BlenderSceneConverter
635
636         m_meshes.clear();
637 }
638
639 void KX_GameObject::UpdateTransform()
640 {
641         // HACK: saves function call for dynamic object, they are handled differently
642         if (m_pPhysicsController1 && !m_pPhysicsController1->IsDyna())
643                 // Note that for Bullet, this does not even update the transform of static object
644                 // but merely sets there collision flag to "kinematic" because the synchronization is 
645                 // done during physics simulation
646                 m_pPhysicsController1->SetSumoTransform(true);
647         if (m_pGraphicController)
648                 // update the culling tree
649                 m_pGraphicController->SetGraphicTransform();
650
651 }
652
653 void KX_GameObject::UpdateTransformFunc(SG_IObject* node, void* gameobj, void* scene)
654 {
655         ((KX_GameObject*)gameobj)->UpdateTransform();
656 }
657
658 void KX_GameObject::SynchronizeTransform()
659 {
660         // only used for sensor object, do full synchronization as bullet doesn't do it
661         if (m_pPhysicsController1)
662                 m_pPhysicsController1->SetTransform();
663         if (m_pGraphicController)
664                 m_pGraphicController->SetGraphicTransform();
665 }
666
667 void KX_GameObject::SynchronizeTransformFunc(SG_IObject* node, void* gameobj, void* scene)
668 {
669         ((KX_GameObject*)gameobj)->SynchronizeTransform();
670 }
671
672
673 void KX_GameObject::SetDebugColor(unsigned int bgra)
674 {
675         for (size_t i=0;i<m_meshes.size();i++)
676                 m_meshes[i]->DebugColor(bgra);  
677 }
678
679
680
681 void KX_GameObject::ResetDebugColor()
682 {
683         SetDebugColor(0xff000000);
684 }
685
686 void KX_GameObject::InitIPO(bool ipo_as_force,
687                                                         bool ipo_add,
688                                                         bool ipo_local)
689 {
690         SGControllerList::iterator it = GetSGNode()->GetSGControllerList().begin();
691
692         while (it != GetSGNode()->GetSGControllerList().end()) {
693                 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_RESET, true);
694                 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_AS_FORCE, ipo_as_force);
695                 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_ADD, ipo_add);
696                 (*it)->SetOption(SG_Controller::SG_CONTR_IPO_LOCAL, ipo_local);
697                 it++;
698         }
699
700
701 void KX_GameObject::UpdateIPO(float curframetime,
702                                                           bool recurse) 
703 {
704         // just the 'normal' update procedure.
705         GetSGNode()->SetSimulatedTime(curframetime,recurse);
706         GetSGNode()->UpdateWorldData(curframetime);
707         UpdateTransform();
708 }
709
710 // IPO update
711 void 
712 KX_GameObject::UpdateMaterialData(
713                 dword matname_hash,
714                 MT_Vector4 rgba,
715                 MT_Vector3 specrgb,
716                 MT_Scalar hard,
717                 MT_Scalar spec,
718                 MT_Scalar ref,
719                 MT_Scalar emit,
720                 MT_Scalar alpha
721
722         )
723 {
724         int mesh = 0;
725         if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0) {
726                 list<RAS_MeshMaterial>::iterator mit = m_meshes[mesh]->GetFirstMaterial();
727
728                 for(; mit != m_meshes[mesh]->GetLastMaterial(); ++mit)
729                 {
730                         RAS_IPolyMaterial* poly = mit->m_bucket->GetPolyMaterial();
731
732                         if(poly->GetFlag() & RAS_BLENDERMAT )
733                         {
734                                 KX_BlenderMaterial *m =  static_cast<KX_BlenderMaterial*>(poly);
735                                 
736                                 if (matname_hash == 0)
737                                 {
738                                         m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha);
739                                         // if mesh has only one material attached to it then use original hack with no need to edit vertices (better performance)
740                                         SetObjectColor(rgba);
741                                 }
742                                 else
743                                 {
744                                         if (matname_hash == poly->GetMaterialNameHash())
745                                         {
746                                                 m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha);
747                                                 m_meshes[mesh]->SetVertexColor(poly,rgba);
748                                                 
749                                                 // no break here, because one blender material can be split into several game engine materials
750                                                 // (e.g. one uvsphere material is split into one material at poles with ras_mode TRIANGLE and one material for the body
751                                                 // if here was a break then would miss some vertices if material was split
752                                         }
753                                 }
754                         }
755                 }
756         }
757 }
758 bool
759 KX_GameObject::GetVisible(
760         void
761         )
762 {
763         return m_bVisible;
764 }
765
766 static void setVisible_recursive(SG_Node* node, bool v)
767 {
768         NodeList& children = node->GetSGChildren();
769
770         for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
771         {
772                 SG_Node* childnode = (*childit);
773                 KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject());
774                 if (clientgameobj != NULL) // This is a GameObject
775                         clientgameobj->SetVisible(v, 0);
776                 
777                 // if the childobj is NULL then this may be an inverse parent link
778                 // so a non recursive search should still look down this node.
779                 setVisible_recursive(childnode, v);
780         }
781 }
782
783
784 void
785 KX_GameObject::SetVisible(
786         bool v,
787         bool recursive
788         )
789 {
790         if (GetSGNode()) {
791                 m_bVisible = v;
792                 if (m_pGraphicController)
793                         m_pGraphicController->Activate(m_bVisible);
794                 if (recursive)
795                         setVisible_recursive(GetSGNode(), v);
796         }
797 }
798
799 static void setOccluder_recursive(SG_Node* node, bool v)
800 {
801         NodeList& children = node->GetSGChildren();
802
803         for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
804         {
805                 SG_Node* childnode = (*childit);
806                 KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject());
807                 if (clientgameobj != NULL) // This is a GameObject
808                         clientgameobj->SetOccluder(v, false);
809                 
810                 // if the childobj is NULL then this may be an inverse parent link
811                 // so a non recursive search should still look down this node.
812                 setOccluder_recursive(childnode, v);
813         }
814 }
815
816 void
817 KX_GameObject::SetOccluder(
818         bool v,
819         bool recursive
820         )
821 {
822         if (GetSGNode()) {
823                 m_bOccluder = v;
824                 if (recursive)
825                         setOccluder_recursive(GetSGNode(), v);
826         }
827 }
828
829 void
830 KX_GameObject::SetLayer(
831         int l
832         )
833 {
834         m_layer = l;
835 }
836
837 int
838 KX_GameObject::GetLayer(
839         void
840         )
841 {
842         return m_layer;
843 }
844
845 void KX_GameObject::addLinearVelocity(const MT_Vector3& lin_vel,bool local)
846 {
847         if (m_pPhysicsController1) 
848         {
849                 MT_Vector3 lv = local ? NodeGetWorldOrientation() * lin_vel : lin_vel;
850                 m_pPhysicsController1->SetLinearVelocity(lv + m_pPhysicsController1->GetLinearVelocity(), 0);
851         }
852 }
853
854
855
856 void KX_GameObject::setLinearVelocity(const MT_Vector3& lin_vel,bool local)
857 {
858         if (m_pPhysicsController1)
859                 m_pPhysicsController1->SetLinearVelocity(lin_vel,local);
860 }
861
862
863
864 void KX_GameObject::setAngularVelocity(const MT_Vector3& ang_vel,bool local)
865 {
866         if (m_pPhysicsController1)
867                 m_pPhysicsController1->SetAngularVelocity(ang_vel,local);
868 }
869
870
871 void KX_GameObject::ResolveCombinedVelocities(
872         const MT_Vector3 & lin_vel,
873         const MT_Vector3 & ang_vel,
874         bool lin_vel_local,
875         bool ang_vel_local
876 ){
877         if (m_pPhysicsController1)
878         {
879
880                 MT_Vector3 lv = lin_vel_local ? NodeGetWorldOrientation() * lin_vel : lin_vel;
881                 MT_Vector3 av = ang_vel_local ? NodeGetWorldOrientation() * ang_vel : ang_vel;
882                 m_pPhysicsController1->resolveCombinedVelocities(
883                         lv.x(),lv.y(),lv.z(),av.x(),av.y(),av.z());
884         }
885 }
886
887
888 void KX_GameObject::SetObjectColor(const MT_Vector4& rgbavec)
889 {
890         m_bUseObjectColor = true;
891         m_objectColor = rgbavec;
892 }
893
894 const MT_Vector4& KX_GameObject::GetObjectColor()
895 {
896         return m_objectColor;
897 }
898
899 void KX_GameObject::AlignAxisToVect(const MT_Vector3& dir, int axis, float fac)
900 {
901         MT_Matrix3x3 orimat;
902         MT_Vector3 vect,ori,z,x,y;
903         MT_Scalar len;
904
905         // check on valid node in case a python controller holds a reference to a deleted object
906         if (!GetSGNode())
907                 return;
908
909         vect = dir;
910         len = vect.length();
911         if (MT_fuzzyZero(len))
912         {
913                 cout << "alignAxisToVect() Error: Null vector!\n";
914                 return;
915         }
916         
917         if (fac<=0.0) {
918                 return;
919         }
920         
921         // normalize
922         vect /= len;
923         orimat = GetSGNode()->GetWorldOrientation();
924         switch (axis)
925         {       
926                 case 0: //x axis
927                         ori.setValue(orimat[0][2], orimat[1][2], orimat[2][2]); //pivot axis
928                         if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON) //is the vector parallel to the pivot?
929                                 ori.setValue(orimat[0][1], orimat[1][1], orimat[2][1]); //change the pivot!
930                         if (fac == 1.0) {
931                                 x = vect;
932                         } else {
933                                 x = (vect * fac) + ((orimat * MT_Vector3(1.0, 0.0, 0.0)) * (1-fac));
934                                 len = x.length();
935                                 if (MT_fuzzyZero(len)) x = vect;
936                                 else x /= len;
937                         }
938                         y = ori.cross(x);
939                         z = x.cross(y);
940                         break;
941                 case 1: //y axis
942                         ori.setValue(orimat[0][0], orimat[1][0], orimat[2][0]);
943                         if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON)
944                                 ori.setValue(orimat[0][2], orimat[1][2], orimat[2][2]);
945                         if (fac == 1.0) {
946                                 y = vect;
947                         } else {
948                                 y = (vect * fac) + ((orimat * MT_Vector3(0.0, 1.0, 0.0)) * (1-fac));
949                                 len = y.length();
950                                 if (MT_fuzzyZero(len)) y = vect;
951                                 else y /= len;
952                         }
953                         z = ori.cross(y);
954                         x = y.cross(z);
955                         break;
956                 case 2: //z axis
957                         ori.setValue(orimat[0][1], orimat[1][1], orimat[2][1]);
958                         if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON)
959                                 ori.setValue(orimat[0][0], orimat[1][0], orimat[2][0]);
960                         if (fac == 1.0) {
961                                 z = vect;
962                         } else {
963                                 z = (vect * fac) + ((orimat * MT_Vector3(0.0, 0.0, 1.0)) * (1-fac));
964                                 len = z.length();
965                                 if (MT_fuzzyZero(len)) z = vect;
966                                 else z /= len;
967                         }
968                         x = ori.cross(z);
969                         y = z.cross(x);
970                         break;
971                 default: //wrong input?
972                         cout << "alignAxisToVect(): Wrong axis '" << axis <<"'\n";
973                         return;
974         }
975         x.normalize(); //normalize the vectors
976         y.normalize();
977         z.normalize();
978         orimat.setValue(        x[0],y[0],z[0],
979                                                 x[1],y[1],z[1],
980                                                 x[2],y[2],z[2]);
981         if (GetSGNode()->GetSGParent() != NULL)
982         {
983                 // the object is a child, adapt its local orientation so that 
984                 // the global orientation is aligned as we want.
985                 MT_Matrix3x3 invori = GetSGNode()->GetSGParent()->GetWorldOrientation().inverse();
986                 NodeSetLocalOrientation(invori*orimat);
987         }
988         else
989                 NodeSetLocalOrientation(orimat);
990 }
991
992 MT_Scalar KX_GameObject::GetMass()
993 {
994         if (m_pPhysicsController1)
995         {
996                 return m_pPhysicsController1->GetMass();
997         }
998         return 0.0;
999 }
1000
1001 MT_Vector3 KX_GameObject::GetLocalInertia()
1002 {
1003         MT_Vector3 local_inertia(0.0,0.0,0.0);
1004         if (m_pPhysicsController1)
1005         {
1006                 local_inertia = m_pPhysicsController1->GetLocalInertia();
1007         }
1008         return local_inertia;
1009 }
1010
1011 MT_Vector3 KX_GameObject::GetLinearVelocity(bool local)
1012 {
1013         MT_Vector3 velocity(0.0,0.0,0.0), locvel;
1014         MT_Matrix3x3 ori;
1015         if (m_pPhysicsController1)
1016         {
1017                 velocity = m_pPhysicsController1->GetLinearVelocity();
1018                 
1019                 if (local)
1020                 {
1021                         ori = GetSGNode()->GetWorldOrientation();
1022                         
1023                         locvel = velocity * ori;
1024                         return locvel;
1025                 }
1026         }
1027         return velocity;        
1028 }
1029
1030 MT_Vector3 KX_GameObject::GetAngularVelocity(bool local)
1031 {
1032         MT_Vector3 velocity(0.0,0.0,0.0), locvel;
1033         MT_Matrix3x3 ori;
1034         if (m_pPhysicsController1)
1035         {
1036                 velocity = m_pPhysicsController1->GetAngularVelocity();
1037                 
1038                 if (local)
1039                 {
1040                         ori = GetSGNode()->GetWorldOrientation();
1041                         
1042                         locvel = velocity * ori;
1043                         return locvel;
1044                 }
1045         }
1046         return velocity;        
1047 }
1048
1049 MT_Vector3 KX_GameObject::GetVelocity(const MT_Point3& point)
1050 {
1051         if (m_pPhysicsController1)
1052         {
1053                 return m_pPhysicsController1->GetVelocity(point);
1054         }
1055         return MT_Vector3(0.0,0.0,0.0);
1056 }
1057
1058 // scenegraph node stuff
1059
1060 void KX_GameObject::NodeSetLocalPosition(const MT_Point3& trans)
1061 {
1062         // check on valid node in case a python controller holds a reference to a deleted object
1063         if (!GetSGNode())
1064                 return;
1065
1066         if (m_pPhysicsController1 && !GetSGNode()->GetSGParent())
1067         {
1068                 // don't update physic controller if the object is a child:
1069                 // 1) the transformation will not be right
1070                 // 2) in this case, the physic controller is necessarily a static object
1071                 //    that is updated from the normal kinematic synchronization
1072                 m_pPhysicsController1->setPosition(trans);
1073         }
1074
1075         GetSGNode()->SetLocalPosition(trans);
1076
1077 }
1078
1079
1080
1081 void KX_GameObject::NodeSetLocalOrientation(const MT_Matrix3x3& rot)
1082 {
1083         // check on valid node in case a python controller holds a reference to a deleted object
1084         if (!GetSGNode())
1085                 return;
1086
1087         if (m_pPhysicsController1 && !GetSGNode()->GetSGParent())
1088         {
1089                 // see note above
1090                 m_pPhysicsController1->setOrientation(rot);
1091         }
1092         GetSGNode()->SetLocalOrientation(rot);
1093 }
1094
1095 void KX_GameObject::NodeSetGlobalOrientation(const MT_Matrix3x3& rot)
1096 {
1097         // check on valid node in case a python controller holds a reference to a deleted object
1098         if (!GetSGNode())
1099                 return;
1100
1101         if (GetSGNode()->GetSGParent())
1102                 GetSGNode()->SetLocalOrientation(GetSGNode()->GetSGParent()->GetWorldOrientation().inverse()*rot);
1103         else
1104                 NodeSetLocalOrientation(rot);
1105 }
1106
1107 void KX_GameObject::NodeSetLocalScale(const MT_Vector3& scale)
1108 {
1109         // check on valid node in case a python controller holds a reference to a deleted object
1110         if (!GetSGNode())
1111                 return;
1112
1113         if (m_pPhysicsController1 && !GetSGNode()->GetSGParent())
1114         {
1115                 // see note above
1116                 m_pPhysicsController1->setScaling(scale);
1117         }
1118         GetSGNode()->SetLocalScale(scale);
1119 }
1120
1121
1122
1123 void KX_GameObject::NodeSetRelativeScale(const MT_Vector3& scale)
1124 {
1125         if (GetSGNode())
1126         {
1127                 GetSGNode()->RelativeScale(scale);
1128                 if (m_pPhysicsController1 && (!GetSGNode()->GetSGParent()))
1129                 {
1130                         // see note above
1131                         // we can use the local scale: it's the same thing for a root object 
1132                         // and the world scale is not yet updated
1133                         MT_Vector3 newscale = GetSGNode()->GetLocalScale();
1134                         m_pPhysicsController1->setScaling(newscale);
1135                 }
1136         }
1137 }
1138
1139 void KX_GameObject::NodeSetWorldPosition(const MT_Point3& trans)
1140 {
1141         if (!GetSGNode())
1142                 return;
1143         SG_Node* parent = GetSGNode()->GetSGParent();
1144         if (parent != NULL)
1145         {
1146                 // Make sure the objects have some scale
1147                 MT_Vector3 scale = parent->GetWorldScaling();
1148                 if (fabs(scale[0]) < FLT_EPSILON || 
1149                         fabs(scale[1]) < FLT_EPSILON || 
1150                         fabs(scale[2]) < FLT_EPSILON)
1151                 { 
1152                         return; 
1153                 }
1154                 scale[0] = 1.0/scale[0];
1155                 scale[1] = 1.0/scale[1];
1156                 scale[2] = 1.0/scale[2];
1157                 MT_Matrix3x3 invori = parent->GetWorldOrientation().inverse();
1158                 MT_Vector3 newpos = invori*(trans-parent->GetWorldPosition())*scale;
1159                 NodeSetLocalPosition(MT_Point3(newpos[0],newpos[1],newpos[2]));
1160         }
1161         else 
1162         {
1163                 NodeSetLocalPosition(trans);
1164         }
1165 }
1166
1167
1168 void KX_GameObject::NodeUpdateGS(double time)
1169 {
1170         if (GetSGNode())
1171                 GetSGNode()->UpdateWorldData(time);
1172 }
1173
1174
1175
1176 const MT_Matrix3x3& KX_GameObject::NodeGetWorldOrientation() const
1177 {
1178         // check on valid node in case a python controller holds a reference to a deleted object
1179         if (!GetSGNode())
1180                 return dummy_orientation;
1181         return GetSGNode()->GetWorldOrientation();
1182 }
1183
1184 const MT_Matrix3x3& KX_GameObject::NodeGetLocalOrientation() const
1185 {
1186         // check on valid node in case a python controller holds a reference to a deleted object
1187         if (!GetSGNode())
1188                 return dummy_orientation;
1189         return GetSGNode()->GetLocalOrientation();
1190 }
1191
1192 const MT_Vector3& KX_GameObject::NodeGetWorldScaling() const
1193 {
1194         // check on valid node in case a python controller holds a reference to a deleted object
1195         if (!GetSGNode())
1196                 return dummy_scaling;
1197
1198         return GetSGNode()->GetWorldScaling();
1199 }
1200
1201 const MT_Vector3& KX_GameObject::NodeGetLocalScaling() const
1202 {
1203         // check on valid node in case a python controller holds a reference to a deleted object
1204         if (!GetSGNode())
1205                 return dummy_scaling;
1206
1207         return GetSGNode()->GetLocalScale();
1208 }
1209
1210 const MT_Point3& KX_GameObject::NodeGetWorldPosition() const
1211 {
1212         // check on valid node in case a python controller holds a reference to a deleted object
1213         if (GetSGNode())
1214                 return GetSGNode()->GetWorldPosition();
1215         else
1216                 return dummy_point;
1217 }
1218
1219 const MT_Point3& KX_GameObject::NodeGetLocalPosition() const
1220 {
1221         // check on valid node in case a python controller holds a reference to a deleted object
1222         if (GetSGNode())
1223                 return GetSGNode()->GetLocalPosition();
1224         else
1225                 return dummy_point;
1226 }
1227
1228
1229 /* Suspend/ resume: for the dynamic behaviour, there is a simple
1230  * method. For the residual motion, there is not. I wonder what the
1231  * correct solution is for Sumo. Remove from the motion-update tree?
1232  *
1233  * So far, only switch the physics and logic.
1234  * */
1235
1236 void KX_GameObject::Resume(void)
1237 {
1238         if (m_suspended) {
1239                 SCA_IObject::Resume();
1240                 if(GetPhysicsController())
1241                         GetPhysicsController()->RestoreDynamics();
1242
1243                 m_suspended = false;
1244         }
1245 }
1246
1247 void KX_GameObject::Suspend()
1248 {
1249         if ((!m_ignore_activity_culling) 
1250                 && (!m_suspended))  {
1251                 SCA_IObject::Suspend();
1252                 if(GetPhysicsController())
1253                         GetPhysicsController()->SuspendDynamics();
1254                 m_suspended = true;
1255         }
1256 }
1257
1258 static void walk_children(SG_Node* node, CListValue* list, bool recursive)
1259 {
1260         if (!node)
1261                 return;
1262         NodeList& children = node->GetSGChildren();
1263
1264         for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
1265         {
1266                 SG_Node* childnode = (*childit);
1267                 CValue* childobj = (CValue*)childnode->GetSGClientObject();
1268                 if (childobj != NULL) // This is a GameObject
1269                 {
1270                         // add to the list
1271                         list->Add(childobj->AddRef());
1272                 }
1273                 
1274                 // if the childobj is NULL then this may be an inverse parent link
1275                 // so a non recursive search should still look down this node.
1276                 if (recursive || childobj==NULL) {
1277                         walk_children(childnode, list, recursive);
1278                 }
1279         }
1280 }
1281
1282 CListValue* KX_GameObject::GetChildren()
1283 {
1284         CListValue* list = new CListValue();
1285         walk_children(GetSGNode(), list, 0); /* GetSGNode() is always valid or it would have raised an exception before this */
1286         return list;
1287 }
1288
1289 CListValue* KX_GameObject::GetChildrenRecursive()
1290 {
1291         CListValue* list = new CListValue();
1292         walk_children(GetSGNode(), list, 1);
1293         return list;
1294 }
1295
1296 /* ---------------------------------------------------------------------
1297  * Some stuff taken from the header
1298  * --------------------------------------------------------------------- */
1299 void KX_GameObject::Relink(CTR_Map<CTR_HashedPtr, void*> *map_parameter)
1300 {
1301         // we will relink the sensors and actuators that use object references
1302         // if the object is part of the replicated hierarchy, use the new
1303         // object reference instead
1304         SCA_SensorList& sensorlist = GetSensors();
1305         SCA_SensorList::iterator sit;
1306         for (sit=sensorlist.begin(); sit != sensorlist.end(); sit++)
1307         {
1308                 (*sit)->Relink(map_parameter);
1309         }
1310         SCA_ActuatorList& actuatorlist = GetActuators();
1311         SCA_ActuatorList::iterator ait;
1312         for (ait=actuatorlist.begin(); ait != actuatorlist.end(); ait++)
1313         {
1314                 (*ait)->Relink(map_parameter);
1315         }
1316 }
1317
1318 #ifdef USE_MATHUTILS
1319
1320 /* These require an SGNode */
1321 #define MATHUTILS_VEC_CB_POS_LOCAL 1
1322 #define MATHUTILS_VEC_CB_POS_GLOBAL 2
1323 #define MATHUTILS_VEC_CB_SCALE_LOCAL 3
1324 #define MATHUTILS_VEC_CB_SCALE_GLOBAL 4
1325 #define MATHUTILS_VEC_CB_INERTIA_LOCAL 5
1326 #define MATHUTILS_VEC_CB_OBJECT_COLOR 6
1327 #define MATHUTILS_VEC_CB_LINVEL_LOCAL 7
1328 #define MATHUTILS_VEC_CB_LINVEL_GLOBAL 8
1329 #define MATHUTILS_VEC_CB_ANGVEL_LOCAL 9
1330 #define MATHUTILS_VEC_CB_ANGVEL_GLOBAL 10
1331
1332 static int mathutils_kxgameob_vector_cb_index= -1; /* index for our callbacks */
1333
1334 static int mathutils_kxgameob_generic_check(BaseMathObject *bmo)
1335 {
1336         KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(bmo->cb_user);
1337         if(self==NULL)
1338                 return -1;
1339         
1340         return 0;
1341 }
1342
1343 static int mathutils_kxgameob_vector_get(BaseMathObject *bmo, int subtype)
1344 {
1345         KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(bmo->cb_user);
1346         if(self==NULL)
1347                 return -1;
1348
1349 #define PHYS_ERR(attr) PyErr_SetString(PyExc_AttributeError, "KX_GameObject." attr ", is missing a physics controller")
1350
1351         switch(subtype) {
1352                 case MATHUTILS_VEC_CB_POS_LOCAL:
1353                         self->NodeGetLocalPosition().getValue(bmo->data);
1354                         break;
1355                 case MATHUTILS_VEC_CB_POS_GLOBAL:
1356                         self->NodeGetWorldPosition().getValue(bmo->data);
1357                         break;
1358                 case MATHUTILS_VEC_CB_SCALE_LOCAL:
1359                         self->NodeGetLocalScaling().getValue(bmo->data);
1360                         break;
1361                 case MATHUTILS_VEC_CB_SCALE_GLOBAL:
1362                         self->NodeGetWorldScaling().getValue(bmo->data);
1363                         break;
1364                 case MATHUTILS_VEC_CB_INERTIA_LOCAL:
1365                         if(!self->GetPhysicsController()) return PHYS_ERR("localInertia"), -1;
1366                         self->GetPhysicsController()->GetLocalInertia().getValue(bmo->data);
1367                         break;
1368                 case MATHUTILS_VEC_CB_OBJECT_COLOR:
1369                         self->GetObjectColor().getValue(bmo->data);
1370                         break;
1371                 case MATHUTILS_VEC_CB_LINVEL_LOCAL:
1372                         if(!self->GetPhysicsController()) return PHYS_ERR("localLinearVelocity"), -1;
1373                         self->GetLinearVelocity(true).getValue(bmo->data);
1374                         break;
1375                 case MATHUTILS_VEC_CB_LINVEL_GLOBAL:
1376                         if(!self->GetPhysicsController()) return PHYS_ERR("worldLinearVelocity"), -1;
1377                         self->GetLinearVelocity(false).getValue(bmo->data);
1378                         break;
1379                 case MATHUTILS_VEC_CB_ANGVEL_LOCAL:
1380                         if(!self->GetPhysicsController()) return PHYS_ERR("localLinearVelocity"), -1;
1381                         self->GetAngularVelocity(true).getValue(bmo->data);
1382                         break;
1383                 case MATHUTILS_VEC_CB_ANGVEL_GLOBAL:
1384                         if(!self->GetPhysicsController()) return PHYS_ERR("worldLinearVelocity"), -1;
1385                         self->GetAngularVelocity(false).getValue(bmo->data);
1386                         break;
1387                         
1388         }
1389         
1390 #undef PHYS_ERR
1391         
1392         return 0;
1393 }
1394
1395 static int mathutils_kxgameob_vector_set(BaseMathObject *bmo, int subtype)
1396 {
1397         KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(bmo->cb_user);
1398         if(self==NULL)
1399                 return -1;
1400         
1401         switch(subtype) {
1402                 case MATHUTILS_VEC_CB_POS_LOCAL:
1403                         self->NodeSetLocalPosition(MT_Point3(bmo->data));
1404                         self->NodeUpdateGS(0.f);
1405                         break;
1406                 case MATHUTILS_VEC_CB_POS_GLOBAL:
1407                         self->NodeSetWorldPosition(MT_Point3(bmo->data));
1408                         self->NodeUpdateGS(0.f);
1409                         break;
1410                 case MATHUTILS_VEC_CB_SCALE_LOCAL:
1411                         self->NodeSetLocalScale(MT_Point3(bmo->data));
1412                         self->NodeUpdateGS(0.f);
1413                         break;
1414                 case MATHUTILS_VEC_CB_SCALE_GLOBAL:
1415                         PyErr_SetString(PyExc_AttributeError, "KX_GameObject.worldScale is read-only");
1416                         return -1;
1417                 case MATHUTILS_VEC_CB_INERTIA_LOCAL:
1418                         /* read only */
1419                         break;
1420                 case MATHUTILS_VEC_CB_OBJECT_COLOR:
1421                         self->SetObjectColor(MT_Vector4(bmo->data));
1422                         break;
1423                 case MATHUTILS_VEC_CB_LINVEL_LOCAL:
1424                         self->setLinearVelocity(MT_Point3(bmo->data),true);
1425                         break;
1426                 case MATHUTILS_VEC_CB_LINVEL_GLOBAL:
1427                         self->setLinearVelocity(MT_Point3(bmo->data),false);
1428                         break;
1429                 case MATHUTILS_VEC_CB_ANGVEL_LOCAL:
1430                         self->setAngularVelocity(MT_Point3(bmo->data),true);
1431                         break;
1432                 case MATHUTILS_VEC_CB_ANGVEL_GLOBAL:
1433                         self->setAngularVelocity(MT_Point3(bmo->data),false);
1434                         break;
1435         }
1436         
1437         return 0;
1438 }
1439
1440 static int mathutils_kxgameob_vector_get_index(BaseMathObject *bmo, int subtype, int index)
1441 {
1442         /* lazy, avoid repeteing the case statement */
1443         if(mathutils_kxgameob_vector_get(bmo, subtype) == -1)
1444                 return -1;
1445         return 0;
1446 }
1447
1448 static int mathutils_kxgameob_vector_set_index(BaseMathObject *bmo, int subtype, int index)
1449 {
1450         float f= bmo->data[index];
1451         
1452         /* lazy, avoid repeteing the case statement */
1453         if(mathutils_kxgameob_vector_get(bmo, subtype) == -1)
1454                 return -1;
1455         
1456         bmo->data[index]= f;
1457         return mathutils_kxgameob_vector_set(bmo, subtype);
1458 }
1459
1460 Mathutils_Callback mathutils_kxgameob_vector_cb = {
1461         mathutils_kxgameob_generic_check,
1462         mathutils_kxgameob_vector_get,
1463         mathutils_kxgameob_vector_set,
1464         mathutils_kxgameob_vector_get_index,
1465         mathutils_kxgameob_vector_set_index
1466 };
1467
1468 /* Matrix */
1469 #define MATHUTILS_MAT_CB_ORI_LOCAL 1
1470 #define MATHUTILS_MAT_CB_ORI_GLOBAL 2
1471
1472 static int mathutils_kxgameob_matrix_cb_index= -1; /* index for our callbacks */
1473
1474 static int mathutils_kxgameob_matrix_get(BaseMathObject *bmo, int subtype)
1475 {
1476         KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(bmo->cb_user);
1477         if(self==NULL)
1478                 return -1;
1479
1480         switch(subtype) {
1481                 case MATHUTILS_MAT_CB_ORI_LOCAL:
1482                         self->NodeGetLocalOrientation().getValue3x3(bmo->data);
1483                         break;
1484                 case MATHUTILS_MAT_CB_ORI_GLOBAL:
1485                         self->NodeGetWorldOrientation().getValue3x3(bmo->data);
1486                         break;
1487         }
1488         
1489         return 0;
1490 }
1491
1492
1493 static int mathutils_kxgameob_matrix_set(BaseMathObject *bmo, int subtype)
1494 {
1495         KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(bmo->cb_user);
1496         if(self==NULL)
1497                 return -1;
1498         
1499         MT_Matrix3x3 mat3x3;
1500         switch(subtype) {
1501                 case MATHUTILS_MAT_CB_ORI_LOCAL:
1502                         mat3x3.setValue3x3(bmo->data);
1503                         self->NodeSetLocalOrientation(mat3x3);
1504                         self->NodeUpdateGS(0.f);
1505                         break;
1506                 case MATHUTILS_MAT_CB_ORI_GLOBAL:
1507                         mat3x3.setValue3x3(bmo->data);
1508                         self->NodeSetLocalOrientation(mat3x3);
1509                         self->NodeUpdateGS(0.f);
1510                         break;
1511         }
1512         
1513         return 0;
1514 }
1515
1516 Mathutils_Callback mathutils_kxgameob_matrix_cb = {
1517         mathutils_kxgameob_generic_check,
1518         mathutils_kxgameob_matrix_get,
1519         mathutils_kxgameob_matrix_set,
1520         NULL,
1521         NULL
1522 };
1523
1524
1525 void KX_GameObject_Mathutils_Callback_Init(void)
1526 {
1527         // register mathutils callbacks, ok to run more then once.
1528         mathutils_kxgameob_vector_cb_index= Mathutils_RegisterCallback(&mathutils_kxgameob_vector_cb);
1529         mathutils_kxgameob_matrix_cb_index= Mathutils_RegisterCallback(&mathutils_kxgameob_matrix_cb);
1530 }
1531
1532 #endif // USE_MATHUTILS
1533
1534 #ifdef WITH_PYTHON
1535 /* ------- python stuff ---------------------------------------------------*/
1536 PyMethodDef KX_GameObject::Methods[] = {
1537         {"applyForce", (PyCFunction)    KX_GameObject::sPyApplyForce, METH_VARARGS},
1538         {"applyTorque", (PyCFunction)   KX_GameObject::sPyApplyTorque, METH_VARARGS},
1539         {"applyRotation", (PyCFunction) KX_GameObject::sPyApplyRotation, METH_VARARGS},
1540         {"applyMovement", (PyCFunction) KX_GameObject::sPyApplyMovement, METH_VARARGS},
1541         {"getLinearVelocity", (PyCFunction) KX_GameObject::sPyGetLinearVelocity, METH_VARARGS},
1542         {"setLinearVelocity", (PyCFunction) KX_GameObject::sPySetLinearVelocity, METH_VARARGS},
1543         {"getAngularVelocity", (PyCFunction) KX_GameObject::sPyGetAngularVelocity, METH_VARARGS},
1544         {"setAngularVelocity", (PyCFunction) KX_GameObject::sPySetAngularVelocity, METH_VARARGS},
1545         {"getVelocity", (PyCFunction) KX_GameObject::sPyGetVelocity, METH_VARARGS},
1546         {"getReactionForce", (PyCFunction) KX_GameObject::sPyGetReactionForce, METH_NOARGS},
1547         {"alignAxisToVect",(PyCFunction) KX_GameObject::sPyAlignAxisToVect, METH_VARARGS},
1548         {"getAxisVect",(PyCFunction) KX_GameObject::sPyGetAxisVect, METH_O},
1549         {"suspendDynamics", (PyCFunction)KX_GameObject::sPySuspendDynamics,METH_NOARGS},
1550         {"restoreDynamics", (PyCFunction)KX_GameObject::sPyRestoreDynamics,METH_NOARGS},
1551         {"enableRigidBody", (PyCFunction)KX_GameObject::sPyEnableRigidBody,METH_NOARGS},
1552         {"disableRigidBody", (PyCFunction)KX_GameObject::sPyDisableRigidBody,METH_NOARGS},
1553         {"applyImpulse", (PyCFunction) KX_GameObject::sPyApplyImpulse, METH_VARARGS},
1554         {"setCollisionMargin", (PyCFunction) KX_GameObject::sPySetCollisionMargin, METH_O},
1555         {"setParent", (PyCFunction)KX_GameObject::sPySetParent,METH_VARARGS},
1556         {"setVisible",(PyCFunction) KX_GameObject::sPySetVisible, METH_VARARGS},
1557         {"setOcclusion",(PyCFunction) KX_GameObject::sPySetOcclusion, METH_VARARGS},
1558         {"removeParent", (PyCFunction)KX_GameObject::sPyRemoveParent,METH_NOARGS},
1559
1560
1561         {"getPhysicsId", (PyCFunction)KX_GameObject::sPyGetPhysicsId,METH_NOARGS},
1562         {"getPropertyNames", (PyCFunction)KX_GameObject::sPyGetPropertyNames,METH_NOARGS},
1563         {"replaceMesh",(PyCFunction) KX_GameObject::sPyReplaceMesh, METH_VARARGS},
1564         {"endObject",(PyCFunction) KX_GameObject::sPyEndObject, METH_NOARGS},
1565         {"reinstancePhysicsMesh", (PyCFunction)KX_GameObject::sPyReinstancePhysicsMesh,METH_VARARGS},
1566         
1567         KX_PYMETHODTABLE(KX_GameObject, rayCastTo),
1568         KX_PYMETHODTABLE(KX_GameObject, rayCast),
1569         KX_PYMETHODTABLE_O(KX_GameObject, getDistanceTo),
1570         KX_PYMETHODTABLE_O(KX_GameObject, getVectTo),
1571         KX_PYMETHODTABLE(KX_GameObject, sendMessage),
1572
1573         KX_PYMETHODTABLE_KEYWORDS(KX_GameObject, playAction),
1574         KX_PYMETHODTABLE(KX_GameObject, stopAction),
1575         KX_PYMETHODTABLE(KX_GameObject, getActionFrame),
1576         KX_PYMETHODTABLE(KX_GameObject, setActionFrame),
1577         KX_PYMETHODTABLE(KX_GameObject, isPlayingAction),
1578         
1579         // dict style access for props
1580         {"get",(PyCFunction) KX_GameObject::sPyget, METH_VARARGS},
1581         
1582         {NULL,NULL} //Sentinel
1583 };
1584
1585 PyAttributeDef KX_GameObject::Attributes[] = {
1586         KX_PYATTRIBUTE_RO_FUNCTION("name",              KX_GameObject, pyattr_get_name),
1587         KX_PYATTRIBUTE_RO_FUNCTION("parent",    KX_GameObject, pyattr_get_parent),
1588         KX_PYATTRIBUTE_RO_FUNCTION("life",              KX_GameObject, pyattr_get_life),
1589         KX_PYATTRIBUTE_RW_FUNCTION("mass",              KX_GameObject, pyattr_get_mass,         pyattr_set_mass),
1590         KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMin",            KX_GameObject, pyattr_get_lin_vel_min, pyattr_set_lin_vel_min),
1591         KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMax",            KX_GameObject, pyattr_get_lin_vel_max, pyattr_set_lin_vel_max),
1592         KX_PYATTRIBUTE_RW_FUNCTION("visible",   KX_GameObject, pyattr_get_visible,      pyattr_set_visible),
1593         KX_PYATTRIBUTE_BOOL_RW    ("occlusion", KX_GameObject, m_bOccluder),
1594         KX_PYATTRIBUTE_RW_FUNCTION("position",  KX_GameObject, pyattr_get_worldPosition,        pyattr_set_localPosition),
1595         KX_PYATTRIBUTE_RO_FUNCTION("localInertia",      KX_GameObject, pyattr_get_localInertia),
1596         KX_PYATTRIBUTE_RW_FUNCTION("orientation",KX_GameObject,pyattr_get_worldOrientation,pyattr_set_localOrientation),
1597         KX_PYATTRIBUTE_RW_FUNCTION("scaling",   KX_GameObject, pyattr_get_worldScaling, pyattr_set_localScaling),
1598         KX_PYATTRIBUTE_RW_FUNCTION("timeOffset",KX_GameObject, pyattr_get_timeOffset,pyattr_set_timeOffset),
1599         KX_PYATTRIBUTE_RW_FUNCTION("state",             KX_GameObject, pyattr_get_state,        pyattr_set_state),
1600         KX_PYATTRIBUTE_RO_FUNCTION("meshes",    KX_GameObject, pyattr_get_meshes),
1601         KX_PYATTRIBUTE_RW_FUNCTION("localOrientation",KX_GameObject,pyattr_get_localOrientation,pyattr_set_localOrientation),
1602         KX_PYATTRIBUTE_RW_FUNCTION("worldOrientation",KX_GameObject,pyattr_get_worldOrientation,pyattr_set_worldOrientation),
1603         KX_PYATTRIBUTE_RW_FUNCTION("localPosition",     KX_GameObject, pyattr_get_localPosition,        pyattr_set_localPosition),
1604         KX_PYATTRIBUTE_RW_FUNCTION("worldPosition",     KX_GameObject, pyattr_get_worldPosition,    pyattr_set_worldPosition),
1605         KX_PYATTRIBUTE_RW_FUNCTION("localScale",        KX_GameObject, pyattr_get_localScaling, pyattr_set_localScaling),
1606         KX_PYATTRIBUTE_RO_FUNCTION("worldScale",        KX_GameObject, pyattr_get_worldScaling),
1607         KX_PYATTRIBUTE_RW_FUNCTION("linearVelocity", KX_GameObject, pyattr_get_localLinearVelocity, pyattr_set_worldLinearVelocity),
1608         KX_PYATTRIBUTE_RW_FUNCTION("localLinearVelocity", KX_GameObject, pyattr_get_localLinearVelocity, pyattr_set_localLinearVelocity),
1609         KX_PYATTRIBUTE_RW_FUNCTION("worldLinearVelocity", KX_GameObject, pyattr_get_worldLinearVelocity, pyattr_set_worldLinearVelocity),
1610         KX_PYATTRIBUTE_RW_FUNCTION("angularVelocity", KX_GameObject, pyattr_get_localAngularVelocity, pyattr_set_worldAngularVelocity),
1611         KX_PYATTRIBUTE_RW_FUNCTION("localAngularVelocity", KX_GameObject, pyattr_get_localAngularVelocity, pyattr_set_localAngularVelocity),
1612         KX_PYATTRIBUTE_RW_FUNCTION("worldAngularVelocity", KX_GameObject, pyattr_get_worldAngularVelocity, pyattr_set_worldAngularVelocity),
1613         KX_PYATTRIBUTE_RO_FUNCTION("children",  KX_GameObject, pyattr_get_children),
1614         KX_PYATTRIBUTE_RO_FUNCTION("childrenRecursive", KX_GameObject, pyattr_get_children_recursive),
1615         KX_PYATTRIBUTE_RO_FUNCTION("attrDict",  KX_GameObject, pyattr_get_attrDict),
1616         KX_PYATTRIBUTE_RW_FUNCTION("color", KX_GameObject, pyattr_get_obcolor, pyattr_set_obcolor),
1617         
1618         /* Experemental, dont rely on these yet */
1619         KX_PYATTRIBUTE_RO_FUNCTION("sensors",           KX_GameObject, pyattr_get_sensors),
1620         KX_PYATTRIBUTE_RO_FUNCTION("controllers",       KX_GameObject, pyattr_get_controllers),
1621         KX_PYATTRIBUTE_RO_FUNCTION("actuators",         KX_GameObject, pyattr_get_actuators),
1622         {NULL} //Sentinel
1623 };
1624
1625 PyObject* KX_GameObject::PyReplaceMesh(PyObject* args)
1626 {
1627         KX_Scene *scene = KX_GetActiveScene();
1628         
1629         PyObject *value;
1630         int use_gfx= 1, use_phys= 0;
1631         RAS_MeshObject *new_mesh;
1632         
1633         if (!PyArg_ParseTuple(args,"O|ii:replaceMesh", &value, &use_gfx, &use_phys))
1634                 return NULL;
1635         
1636         if (!ConvertPythonToMesh(value, &new_mesh, false, "gameOb.replaceMesh(value): KX_GameObject"))
1637                 return NULL;
1638         
1639         scene->ReplaceMesh(this, new_mesh, (bool)use_gfx, (bool)use_phys);
1640         Py_RETURN_NONE;
1641 }
1642
1643 PyObject* KX_GameObject::PyEndObject()
1644 {
1645         KX_Scene *scene = KX_GetActiveScene();
1646         
1647         scene->DelayedRemoveObject(this);
1648         
1649         Py_RETURN_NONE;
1650
1651 }
1652
1653 PyObject* KX_GameObject::PyReinstancePhysicsMesh(PyObject* args)
1654 {
1655         KX_GameObject *gameobj= NULL;
1656         RAS_MeshObject *mesh= NULL;
1657         
1658         PyObject *gameobj_py= NULL;
1659         PyObject *mesh_py= NULL;
1660
1661         if (    !PyArg_ParseTuple(args,"|OO:reinstancePhysicsMesh",&gameobj_py, &mesh_py) ||
1662                         (gameobj_py && !ConvertPythonToGameObject(gameobj_py, &gameobj, true, "gameOb.reinstancePhysicsMesh(obj, mesh): KX_GameObject")) || 
1663                         (mesh_py && !ConvertPythonToMesh(mesh_py, &mesh, true, "gameOb.reinstancePhysicsMesh(obj, mesh): KX_GameObject"))
1664                 ) {
1665                 return NULL;
1666         }
1667 #ifdef USE_BULLET
1668         /* gameobj and mesh can be NULL */
1669         if(KX_ReInstanceBulletShapeFromMesh(this, gameobj, mesh))
1670                 Py_RETURN_TRUE;
1671 #endif
1672         Py_RETURN_FALSE;
1673 }
1674
1675 static PyObject *Map_GetItem(PyObject *self_v, PyObject *item)
1676 {
1677         KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
1678         const char *attr_str= _PyUnicode_AsString(item);
1679         CValue* resultattr;
1680         PyObject* pyconvert;
1681         
1682         if (self==NULL) {
1683                 PyErr_SetString(PyExc_SystemError, "val = gameOb[key]: KX_GameObject, "BGE_PROXY_ERROR_MSG);
1684                 return NULL;
1685         }
1686         
1687         /* first see if the attributes a string and try get the cvalue attribute */
1688         if(attr_str && (resultattr=self->GetProperty(attr_str))) {
1689                 pyconvert = resultattr->ConvertValueToPython();                 
1690                 return pyconvert ? pyconvert:resultattr->GetProxy();
1691         }
1692         /* no CValue attribute, try get the python only m_attr_dict attribute */
1693         else if (self->m_attr_dict && (pyconvert=PyDict_GetItem(self->m_attr_dict, item))) {
1694                 
1695                 if (attr_str)
1696                         PyErr_Clear();
1697                 Py_INCREF(pyconvert);
1698                 return pyconvert;
1699         }
1700         else {
1701                 if(attr_str)    PyErr_Format(PyExc_KeyError, "value = gameOb[key]: KX_GameObject, key \"%s\" does not exist", attr_str);
1702                 else                    PyErr_SetString(PyExc_KeyError, "value = gameOb[key]: KX_GameObject, key does not exist");
1703                 return NULL;
1704         }
1705                 
1706 }
1707
1708
1709 static int Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val)
1710 {
1711         KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
1712         const char *attr_str= _PyUnicode_AsString(key);
1713         if(attr_str==NULL)
1714                 PyErr_Clear();
1715         
1716         if (self==NULL) {
1717                 PyErr_SetString(PyExc_SystemError, "gameOb[key] = value: KX_GameObject, "BGE_PROXY_ERROR_MSG);
1718                 return -1;
1719         }
1720         
1721         if (val==NULL) { /* del ob["key"] */
1722                 int del= 0;
1723                 
1724                 /* try remove both just incase */
1725                 if(attr_str)
1726                         del |= (self->RemoveProperty(attr_str)==true) ? 1:0;
1727                 
1728                 if(self->m_attr_dict)
1729                         del |= (PyDict_DelItem(self->m_attr_dict, key)==0) ? 1:0;
1730                 
1731                 if (del==0) {
1732                         if(attr_str)    PyErr_Format(PyExc_KeyError, "gameOb[key] = value: KX_GameObject, key \"%s\" could not be set", attr_str);
1733                         else                    PyErr_SetString(PyExc_KeyError, "del gameOb[key]: KX_GameObject, key could not be deleted");
1734                         return -1;
1735                 }
1736                 else if (self->m_attr_dict) {
1737                         PyErr_Clear(); /* PyDict_DelItem sets an error when it fails */
1738                 }
1739         }
1740         else { /* ob["key"] = value */
1741                 int set= 0;
1742                 
1743                 /* as CValue */
1744                 if(attr_str && PyObject_TypeCheck(val, &PyObjectPlus::Type)==0) /* dont allow GameObjects for eg to be assigned to CValue props */
1745                 {
1746                         CValue* vallie = self->ConvertPythonToValue(val, ""); /* error unused */
1747                         
1748                         if(vallie)
1749                         {
1750                                 CValue* oldprop = self->GetProperty(attr_str);
1751                                 
1752                                 if (oldprop)
1753                                         oldprop->SetValue(vallie);
1754                                 else
1755                                         self->SetProperty(attr_str, vallie);
1756                                 
1757                                 vallie->Release();
1758                                 set= 1;
1759                                 
1760                                 /* try remove dict value to avoid double ups */
1761                                 if (self->m_attr_dict){
1762                                         if (PyDict_DelItem(self->m_attr_dict, key) != 0)
1763                                                 PyErr_Clear();
1764                                 }
1765                         }
1766                         else {
1767                                 PyErr_Clear();
1768                         }
1769                 }
1770                 
1771                 if(set==0)
1772                 {
1773                         if (self->m_attr_dict==NULL) /* lazy init */
1774                                 self->m_attr_dict= PyDict_New();
1775                         
1776                         
1777                         if(PyDict_SetItem(self->m_attr_dict, key, val)==0)
1778                         {
1779                                 if(attr_str)
1780                                         self->RemoveProperty(attr_str); /* overwrite the CValue if it exists */
1781                                 set= 1;
1782                         }
1783                         else {
1784                                 if(attr_str)    PyErr_Format(PyExc_KeyError, "gameOb[key] = value: KX_GameObject, key \"%s\" not be added to internal dictionary", attr_str);
1785                                 else                    PyErr_SetString(PyExc_KeyError, "gameOb[key] = value: KX_GameObject, key not be added to internal dictionary");
1786                         }
1787                 }
1788                 
1789                 if(set==0)
1790                         return -1; /* pythons error value */
1791                 
1792         }
1793         
1794         return 0; /* success */
1795 }
1796
1797 static int Seq_Contains(PyObject *self_v, PyObject *value)
1798 {
1799         KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
1800         
1801         if (self==NULL) {
1802                 PyErr_SetString(PyExc_SystemError, "val in gameOb: KX_GameObject, "BGE_PROXY_ERROR_MSG);
1803                 return -1;
1804         }
1805         
1806         if(PyUnicode_Check(value) && self->GetProperty(_PyUnicode_AsString(value)))
1807                 return 1;
1808         
1809         if (self->m_attr_dict && PyDict_GetItem(self->m_attr_dict, value))
1810                 return 1;
1811         
1812         return 0;
1813 }
1814
1815
1816 PyMappingMethods KX_GameObject::Mapping = {
1817         (lenfunc)NULL                                   ,                       /*inquiry mp_length */
1818         (binaryfunc)Map_GetItem,                /*binaryfunc mp_subscript */
1819         (objobjargproc)Map_SetItem,     /*objobjargproc mp_ass_subscript */
1820 };
1821
1822 PySequenceMethods KX_GameObject::Sequence = {
1823         NULL,           /* Cant set the len otherwise it can evaluate as false */
1824         NULL,           /* sq_concat */
1825         NULL,           /* sq_repeat */
1826         NULL,           /* sq_item */
1827         NULL,           /* sq_slice */
1828         NULL,           /* sq_ass_item */
1829         NULL,           /* sq_ass_slice */
1830         (objobjproc)Seq_Contains,       /* sq_contains */
1831         (binaryfunc) NULL, /* sq_inplace_concat */
1832         (ssizeargfunc) NULL, /* sq_inplace_repeat */
1833 };
1834
1835 PyTypeObject KX_GameObject::Type = {
1836         PyVarObject_HEAD_INIT(NULL, 0)
1837         "KX_GameObject",
1838         sizeof(PyObjectPlus_Proxy),
1839         0,
1840         py_base_dealloc,
1841         0,
1842         0,
1843         0,
1844         0,
1845         py_base_repr,
1846         0,
1847         &Sequence,
1848         &Mapping,
1849         0,0,0,
1850         NULL,
1851         NULL,
1852         0,
1853         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
1854         0,0,0,0,0,0,0,
1855         Methods,
1856         0,
1857         0,
1858         &SCA_IObject::Type,
1859         0,0,0,0,0,0,
1860         py_base_new
1861 };
1862
1863 PyObject* KX_GameObject::pyattr_get_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1864 {
1865         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1866         return PyUnicode_FromString(self->GetName().ReadPtr());
1867 }
1868
1869 PyObject* KX_GameObject::pyattr_get_parent(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1870 {
1871         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1872         KX_GameObject* parent = self->GetParent();
1873         if (parent) {
1874                 parent->Release(); /* self->GetParent() AddRef's */
1875                 return parent->GetProxy();
1876         }
1877         Py_RETURN_NONE;
1878 }
1879
1880 PyObject* KX_GameObject::pyattr_get_life(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1881 {
1882         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1883
1884         CValue *life = self->GetProperty("::timebomb");
1885         if (life)
1886                 // this convert the timebomb seconds to frames, hard coded 50.0 (assuming 50fps)
1887                 // value hardcoded in KX_Scene::AddReplicaObject()
1888                 return PyFloat_FromDouble(life->GetNumber() * 50.0);
1889         else
1890                 Py_RETURN_NONE;
1891 }
1892
1893 PyObject* KX_GameObject::pyattr_get_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1894 {
1895         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1896         KX_IPhysicsController *spc = self->GetPhysicsController();
1897         return PyFloat_FromDouble(spc ? spc->GetMass() : 0.0f);
1898 }
1899
1900 int KX_GameObject::pyattr_set_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1901 {
1902         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1903         KX_IPhysicsController *spc = self->GetPhysicsController();
1904         MT_Scalar val = PyFloat_AsDouble(value);
1905         if (val < 0.0f) { /* also accounts for non float */
1906                 PyErr_SetString(PyExc_AttributeError, "gameOb.mass = float: KX_GameObject, expected a float zero or above");
1907                 return PY_SET_ATTR_FAIL;
1908         }
1909
1910         if (spc)
1911                 spc->SetMass(val);
1912
1913         return PY_SET_ATTR_SUCCESS;
1914 }
1915
1916 PyObject* KX_GameObject::pyattr_get_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1917 {
1918         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1919         KX_IPhysicsController *spc = self->GetPhysicsController();
1920         return PyFloat_FromDouble(spc ? spc->GetLinVelocityMin() : 0.0f);
1921 }
1922
1923 int KX_GameObject::pyattr_set_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1924 {
1925         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1926         KX_IPhysicsController *spc = self->GetPhysicsController();
1927         MT_Scalar val = PyFloat_AsDouble(value);
1928         if (val < 0.0f) { /* also accounts for non float */
1929                 PyErr_SetString(PyExc_AttributeError, "gameOb.linVelocityMin = float: KX_GameObject, expected a float zero or above");
1930                 return PY_SET_ATTR_FAIL;
1931         }
1932
1933         if (spc)
1934                 spc->SetLinVelocityMin(val);
1935
1936         return PY_SET_ATTR_SUCCESS;
1937 }
1938
1939 PyObject* KX_GameObject::pyattr_get_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1940 {
1941         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1942         KX_IPhysicsController *spc = self->GetPhysicsController();
1943         return PyFloat_FromDouble(spc ? spc->GetLinVelocityMax() : 0.0f);
1944 }
1945
1946 int KX_GameObject::pyattr_set_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1947 {
1948         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1949         KX_IPhysicsController *spc = self->GetPhysicsController();
1950         MT_Scalar val = PyFloat_AsDouble(value);
1951         if (val < 0.0f) { /* also accounts for non float */
1952                 PyErr_SetString(PyExc_AttributeError, "gameOb.linVelocityMax = float: KX_GameObject, expected a float zero or above");
1953                 return PY_SET_ATTR_FAIL;
1954         }
1955
1956         if (spc)
1957                 spc->SetLinVelocityMax(val);
1958
1959         return PY_SET_ATTR_SUCCESS;
1960 }
1961
1962
1963 PyObject* KX_GameObject::pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1964 {
1965         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1966         return PyBool_FromLong(self->GetVisible());
1967 }
1968
1969 int KX_GameObject::pyattr_set_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1970 {
1971         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1972         int param = PyObject_IsTrue( value );
1973         if (param == -1) {
1974                 PyErr_SetString(PyExc_AttributeError, "gameOb.visible = bool: KX_GameObject, expected True or False");
1975                 return PY_SET_ATTR_FAIL;
1976         }
1977
1978         self->SetVisible(param, false);
1979         self->UpdateBuckets(false);
1980         return PY_SET_ATTR_SUCCESS;
1981 }
1982
1983 PyObject* KX_GameObject::pyattr_get_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
1984 {
1985 #ifdef USE_MATHUTILS
1986         return newVectorObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_GLOBAL);
1987 #else
1988         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1989         return PyObjectFrom(self->NodeGetWorldPosition());
1990 #endif
1991 }
1992
1993 int KX_GameObject::pyattr_set_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
1994 {
1995         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
1996         MT_Point3 pos;
1997         if (!PyVecTo(value, pos))
1998                 return PY_SET_ATTR_FAIL;
1999         
2000         self->NodeSetWorldPosition(pos);
2001         self->NodeUpdateGS(0.f);
2002         return PY_SET_ATTR_SUCCESS;
2003 }
2004
2005 PyObject* KX_GameObject::pyattr_get_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2006 {
2007 #ifdef USE_MATHUTILS    
2008         return newVectorObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_LOCAL);
2009 #else   
2010         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
2011         return PyObjectFrom(self->NodeGetLocalPosition());
2012 #endif
2013 }
2014
2015 int KX_GameObject::pyattr_set_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
2016 {
2017         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
2018         MT_Point3 pos;
2019         if (!PyVecTo(value, pos))
2020                 return PY_SET_ATTR_FAIL;
2021         
2022         self->NodeSetLocalPosition(pos);
2023         self->NodeUpdateGS(0.f);
2024         return PY_SET_ATTR_SUCCESS;
2025 }
2026
2027 PyObject* KX_GameObject::pyattr_get_localInertia(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2028 {
2029 #ifdef USE_MATHUTILS
2030         return newVectorObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_INERTIA_LOCAL);
2031 #else
2032         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
2033         if (self->GetPhysicsController())
2034                 return PyObjectFrom(self->GetPhysicsController()->GetLocalInertia());
2035         return Py_BuildValue("fff", 0.0f, 0.0f, 0.0f);
2036 #endif
2037 }
2038
2039 PyObject* KX_GameObject::pyattr_get_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2040 {
2041 #ifdef USE_MATHUTILS
2042         return newMatrixObject_cb(BGE_PROXY_FROM_REF(self_v), 3, 3, mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_GLOBAL);
2043 #else
2044         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
2045         return PyObjectFrom(self->NodeGetWorldOrientation());
2046 #endif
2047 }
2048
2049 int KX_GameObject::pyattr_set_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
2050 {
2051         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
2052         
2053         /* if value is not a sequence PyOrientationTo makes an error */
2054         MT_Matrix3x3 rot;
2055         if (!PyOrientationTo(value, rot, "gameOb.worldOrientation = sequence: KX_GameObject, "))
2056                 return PY_SET_ATTR_FAIL;
2057
2058         self->NodeSetGlobalOrientation(rot);
2059         
2060         self->NodeUpdateGS(0.f);
2061         return PY_SET_ATTR_SUCCESS;
2062 }
2063
2064 PyObject* KX_GameObject::pyattr_get_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2065 {
2066 #ifdef USE_MATHUTILS
2067         return newMatrixObject_cb(BGE_PROXY_FROM_REF(self_v), 3, 3, mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_LOCAL);
2068 #else
2069         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
2070         return PyObjectFrom(self->NodeGetLocalOrientation());
2071 #endif
2072 }
2073
2074 int KX_GameObject::pyattr_set_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
2075 {
2076         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
2077         
2078         /* if value is not a sequence PyOrientationTo makes an error */
2079         MT_Matrix3x3 rot;
2080         if (!PyOrientationTo(value, rot, "gameOb.localOrientation = sequence: KX_GameObject, "))
2081                 return PY_SET_ATTR_FAIL;
2082
2083         self->NodeSetLocalOrientation(rot);
2084         self->NodeUpdateGS(0.f);
2085         return PY_SET_ATTR_SUCCESS;
2086 }
2087
2088 PyObject* KX_GameObject::pyattr_get_worldScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2089 {
2090 #ifdef USE_MATHUTILS
2091         return newVectorObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_GLOBAL);
2092 #else
2093         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
2094         return PyObjectFrom(self->NodeGetWorldScaling());
2095 #endif
2096 }
2097
2098 PyObject* KX_GameObject::pyattr_get_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2099 {
2100 #ifdef USE_MATHUTILS
2101         return newVectorObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_LOCAL);
2102 #else
2103         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
2104         return PyObjectFrom(self->NodeGetLocalScaling());
2105 #endif
2106 }
2107
2108 int KX_GameObject::pyattr_set_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
2109 {
2110         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
2111         MT_Vector3 scale;
2112         if (!PyVecTo(value, scale))
2113                 return PY_SET_ATTR_FAIL;
2114
2115         self->NodeSetLocalScale(scale);
2116         self->NodeUpdateGS(0.f);
2117         return PY_SET_ATTR_SUCCESS;
2118 }
2119
2120
2121 PyObject* KX_GameObject::pyattr_get_worldLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2122 {
2123 #ifdef USE_MATHUTILS
2124         return newVectorObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_LINVEL_GLOBAL);
2125 #else
2126         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
2127         return PyObjectFrom(GetLinearVelocity(false));
2128 #endif
2129 }
2130
2131 int KX_GameObject::pyattr_set_worldLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
2132 {
2133         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
2134         MT_Vector3 velocity;
2135         if (!PyVecTo(value, velocity))
2136                 return PY_SET_ATTR_FAIL;
2137
2138         self->setLinearVelocity(velocity, false);
2139
2140         return PY_SET_ATTR_SUCCESS;
2141 }
2142
2143 PyObject* KX_GameObject::pyattr_get_localLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2144 {
2145 #ifdef USE_MATHUTILS
2146         return newVectorObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_LINVEL_LOCAL);
2147 #else
2148         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
2149         return PyObjectFrom(GetLinearVelocity(true));
2150 #endif
2151 }
2152
2153 int KX_GameObject::pyattr_set_localLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
2154 {
2155         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
2156         MT_Vector3 velocity;
2157         if (!PyVecTo(value, velocity))
2158                 return PY_SET_ATTR_FAIL;
2159
2160         self->setLinearVelocity(velocity, true);
2161
2162         return PY_SET_ATTR_SUCCESS;
2163 }
2164
2165 PyObject* KX_GameObject::pyattr_get_worldAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2166 {
2167 #ifdef USE_MATHUTILS
2168         return newVectorObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_ANGVEL_GLOBAL);
2169 #else
2170         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
2171         return PyObjectFrom(GetAngularVelocity(false));
2172 #endif
2173 }
2174
2175 int KX_GameObject::pyattr_set_worldAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
2176 {
2177         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
2178         MT_Vector3 velocity;
2179         if (!PyVecTo(value, velocity))
2180                 return PY_SET_ATTR_FAIL;
2181
2182         self->setAngularVelocity(velocity, false);
2183
2184         return PY_SET_ATTR_SUCCESS;
2185 }
2186
2187 PyObject* KX_GameObject::pyattr_get_localAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2188 {
2189 #ifdef USE_MATHUTILS
2190         return newVectorObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_ANGVEL_LOCAL);
2191 #else
2192         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
2193         return PyObjectFrom(GetAngularVelocity(true));
2194 #endif
2195 }
2196
2197 int KX_GameObject::pyattr_set_localAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
2198 {
2199         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
2200         MT_Vector3 velocity;
2201         if (!PyVecTo(value, velocity))
2202                 return PY_SET_ATTR_FAIL;
2203
2204         self->setAngularVelocity(velocity, true);
2205
2206         return PY_SET_ATTR_SUCCESS;
2207 }
2208
2209
2210 PyObject* KX_GameObject::pyattr_get_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2211 {
2212         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
2213         SG_Node* sg_parent;
2214         if (self->GetSGNode() && (sg_parent = self->GetSGNode()->GetSGParent()) != NULL && sg_parent->IsSlowParent()) {
2215                 return PyFloat_FromDouble(static_cast<KX_SlowParentRelation *>(sg_parent->GetParentRelation())->GetTimeOffset());
2216         } else {
2217                 return PyFloat_FromDouble(0.0);
2218         }
2219 }
2220
2221 int KX_GameObject::pyattr_set_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
2222 {
2223         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
2224         if (self->GetSGNode()) {
2225                 MT_Scalar val = PyFloat_AsDouble(value);
2226                 SG_Node* sg_parent= self->GetSGNode()->GetSGParent();
2227                 if (val < 0.0f) { /* also accounts for non float */
2228                         PyErr_SetString(PyExc_AttributeError, "gameOb.timeOffset = float: KX_GameObject, expected a float zero or above");
2229                         return PY_SET_ATTR_FAIL;
2230                 }
2231                 if (sg_parent && sg_parent->IsSlowParent())
2232                         static_cast<KX_SlowParentRelation *>(sg_parent->GetParentRelation())->SetTimeOffset(val);
2233         }
2234         return PY_SET_ATTR_SUCCESS;
2235 }
2236
2237 PyObject* KX_GameObject::pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2238 {
2239         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
2240         int state = 0;
2241         state |= self->GetState();
2242         return PyLong_FromSsize_t(state);
2243 }
2244
2245 int KX_GameObject::pyattr_set_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
2246 {
2247         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
2248         int state_i = PyLong_AsSsize_t(value);
2249         unsigned int state = 0;
2250         
2251         if (state_i == -1 && PyErr_Occurred()) {
2252                 PyErr_SetString(PyExc_TypeError, "gameOb.state = int: KX_GameObject, expected an int bit field");
2253                 return PY_SET_ATTR_FAIL;
2254         }
2255         
2256         state |= state_i;
2257         if ((state & ((1<<30)-1)) == 0) {
2258                 PyErr_SetString(PyExc_AttributeError, "gameOb.state = int: KX_GameObject, state bitfield was not between 0 and 30 (1<<0 and 1<<29)");
2259                 return PY_SET_ATTR_FAIL;
2260         }
2261         self->SetState(state);
2262         return PY_SET_ATTR_SUCCESS;
2263 }
2264
2265 PyObject* KX_GameObject::pyattr_get_meshes(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2266 {
2267         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
2268         PyObject *meshes= PyList_New(self->m_meshes.size());
2269         int i;
2270         
2271         for(i=0; i < (int)self->m_meshes.size(); i++)
2272         {
2273                 KX_MeshProxy* meshproxy = new KX_MeshProxy(self->m_meshes[i]);
2274                 PyList_SET_ITEM(meshes, i, meshproxy->NewProxy(true));
2275         }
2276         
2277         return meshes;
2278 }
2279
2280 PyObject* KX_GameObject::pyattr_get_obcolor(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2281 {
2282 #ifdef USE_MATHUTILS
2283         return newVectorObject_cb(BGE_PROXY_FROM_REF(self_v), 4, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_OBJECT_COLOR);
2284 #else
2285         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
2286         return PyObjectFrom(self->GetObjectColor());
2287 #endif
2288 }
2289
2290 int KX_GameObject::pyattr_set_obcolor(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
2291 {
2292         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
2293         MT_Vector4 obcolor;
2294         if (!PyVecTo(value, obcolor))
2295                 return PY_SET_ATTR_FAIL;
2296
2297         self->SetObjectColor(obcolor);
2298         return PY_SET_ATTR_SUCCESS;
2299 }
2300
2301 /* These are experimental! */
2302 PyObject* KX_GameObject::pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2303 {
2304         return KX_PythonSeq_CreatePyObject((static_cast<KX_GameObject*>(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_SENSORS);
2305 }
2306
2307 PyObject* KX_GameObject::pyattr_get_controllers(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2308 {
2309         return KX_PythonSeq_CreatePyObject((static_cast<KX_GameObject*>(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_CONTROLLERS);
2310 }
2311
2312 PyObject* KX_GameObject::pyattr_get_actuators(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2313 {
2314         return KX_PythonSeq_CreatePyObject((static_cast<KX_GameObject*>(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_ACTUATORS);
2315 }
2316 /* End experimental */
2317
2318 PyObject* KX_GameObject::pyattr_get_children(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2319 {
2320         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
2321         return self->GetChildren()->NewProxy(true);
2322 }
2323
2324 PyObject* KX_GameObject::pyattr_get_children_recursive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2325 {
2326         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
2327         return self->GetChildrenRecursive()->NewProxy(true);
2328 }
2329
2330 PyObject* KX_GameObject::pyattr_get_attrDict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
2331 {
2332         KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
2333         
2334         if(self->m_attr_dict==NULL)
2335                 self->m_attr_dict= PyDict_New();
2336         
2337         Py_INCREF(self->m_attr_dict);
2338         return self->m_attr_dict;
2339 }
2340
2341 PyObject* KX_GameObject::PyApplyForce(PyObject* args)
2342 {
2343         int local = 0;
2344         PyObject* pyvect;
2345
2346         if (PyArg_ParseTuple(args, "O|i:applyForce", &pyvect, &local)) {
2347                 MT_Vector3 force;
2348                 if (PyVecTo(pyvect, force)) {
2349                         ApplyForce(force, (local!=0));
2350                         Py_RETURN_NONE;
2351                 }
2352         }
2353         return NULL;
2354 }
2355
2356 PyObject* KX_GameObject::PyApplyTorque(PyObject* args)
2357 {
2358         int local = 0;
2359         PyObject* pyvect;
2360
2361         if (PyArg_ParseTuple(args, "O|i:applyTorque", &pyvect, &local)) {
2362                 MT_Vector3 torque;
2363                 if (PyVecTo(pyvect, torque)) {
2364                         ApplyTorque(torque, (local!=0));
2365                         Py_RETURN_NONE;
2366                 }
2367         }
2368         return NULL;
2369 }
2370
2371 PyObject* KX_GameObject::PyApplyRotation(PyObject* args)
2372 {
2373         int local = 0;
2374         PyObject* pyvect;
2375
2376         if (PyArg_ParseTuple(args, "O|i:applyRotation", &pyvect, &local)) {
2377                 MT_Vector3 rotation;
2378                 if (PyVecTo(pyvect, rotation)) {
2379                         ApplyRotation(rotation, (local!=0));
2380                         Py_RETURN_NONE;
2381                 }
2382         }
2383         return NULL;
2384 }
2385
2386 PyObject* KX_GameObject::PyApplyMovement(PyObject* args)
2387 {
2388         int local = 0;
2389         PyObject* pyvect;
2390
2391         if (PyArg_ParseTuple(args, "O|i:applyMovement", &pyvect, &local)) {
2392                 MT_Vector3 movement;
2393                 if (PyVecTo(pyvect, movement)) {
2394                         ApplyMovement(movement, (local!=0));
2395                         Py_RETURN_NONE;
2396                 }
2397         }
2398         return NULL;
2399 }
2400
2401 PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* args)
2402 {
2403         // only can get the velocity if we have a physics object connected to us...
2404         int local = 0;
2405         if (PyArg_ParseTuple(args,"|i:getLinearVelocity",&local))
2406         {
2407                 return PyObjectFrom(GetLinearVelocity((local!=0)));
2408         }
2409         else
2410         {
2411                 return NULL;
2412         }
2413 }
2414
2415 PyObject* KX_GameObject::PySetLinearVelocity(PyObject* args)
2416 {
2417         int local = 0;
2418         PyObject* pyvect;
2419         
2420         if (PyArg_ParseTuple(args,"O|i:setLinearVelocity",&pyvect,&local)) {
2421                 MT_Vector3 velocity;
2422                 if (PyVecTo(pyvect, velocity)) {
2423                         setLinearVelocity(velocity, (local!=0));
2424                         Py_RETURN_NONE;
2425                 }
2426         }
2427         return NULL;
2428 }
2429
2430 PyObject* KX_GameObject::PyGetAngularVelocity(PyObject* args)
2431 {
2432         // only can get the velocity if we have a physics object connected to us...
2433         int local = 0;
2434         if (PyArg_ParseTuple(args,"|i:getAngularVelocity",&local))
2435         {
2436                 return PyObjectFrom(GetAngularVelocity((local!=0)));
2437         }
2438         else
2439         {
2440                 return NULL;
2441         }
2442 }
2443
2444 PyObject* KX_GameObject::PySetAngularVelocity(PyObject* args)
2445 {
2446         int local = 0;
2447         PyObject* pyvect;
2448         
2449         if (PyArg_ParseTuple(args,"O|i:setAngularVelocity",&pyvect,&local)) {
2450                 MT_Vector3 velocity;
2451                 if (PyVecTo(pyvect, velocity)) {
2452                         setAngularVelocity(velocity, (local!=0));
2453                         Py_RETURN_NONE;
2454                 }
2455         }
2456         return NULL;
2457 }
2458
2459 PyObject* KX_GameObject::PySetVisible(PyObject* args)
2460 {
2461         int visible, recursive = 0;
2462         if (!PyArg_ParseTuple(args,"i|i:setVisible",&visible, &recursive))
2463                 return NULL;
2464         
2465         SetVisible(visible ? true:false, recursive ? true:false);
2466         UpdateBuckets(recursive ? true:false);
2467         Py_RETURN_NONE;
2468         
2469 }
2470
2471 PyObject* KX_GameObject::PySetOcclusion(PyObject* args)
2472 {
2473         int occlusion, recursive = 0;
2474         if (!PyArg_ParseTuple(args,"i|i:setOcclusion",&occlusion, &recursive))
2475                 return NULL;
2476         
2477         SetOccluder(occlusion ? true:false, recursive ? true:false);
2478         Py_RETURN_NONE;
2479 }
2480
2481 PyObject* KX_GameObject::PyGetVelocity(PyObject* args)
2482 {
2483         // only can get the velocity if we have a physics object connected to us...
2484         MT_Point3 point(0.0,0.0,0.0);
2485         PyObject* pypos = NULL;
2486         
2487         if (!PyArg_ParseTuple(args, "|O:getVelocity", &pypos) || (pypos && !PyVecTo(pypos, point)))
2488                 return NULL;
2489         
2490         if (m_pPhysicsController1)
2491         {
2492                 return PyObjectFrom(m_pPhysicsController1->GetVelocity(point));
2493         }
2494         else {
2495                 return PyObjectFrom(MT_Vector3(0.0,0.0,0.0));
2496         }
2497 }
2498
2499 PyObject* KX_GameObject::PyGetReactionForce()
2500 {
2501         // only can get the velocity if we have a physics object connected to us...
2502         
2503         // XXX - Currently not working with bullet intergration, see KX_BulletPhysicsController.cpp's getReactionForce
2504         /*
2505         if (GetPhysicsController())
2506                 return PyObjectFrom(GetPhysicsController()->getReactionForce());
2507         return PyObjectFrom(dummy_point);
2508         */
2509         
2510         return Py_BuildValue("fff", 0.0f, 0.0f, 0.0f);
2511         
2512 }
2513
2514
2515
2516 PyObject* KX_GameObject::PyEnableRigidBody()
2517 {
2518         if(GetPhysicsController())
2519                 GetPhysicsController()->setRigidBody(true);
2520
2521         Py_RETURN_NONE;
2522 }
2523
2524
2525
2526 PyObject* KX_GameObject::PyDisableRigidBody()
2527 {
2528         if(GetPhysicsController())
2529                 GetPhysicsController()->setRigidBody(false);
2530
2531         Py_RETURN_NONE;
2532 }
2533
2534
2535 PyObject* KX_GameObject::PySetParent(PyObject* args)
2536 {
2537         KX_Scene *scene = KX_GetActiveScene();
2538         PyObject* pyobj;
2539         KX_GameObject *obj;
2540         int addToCompound=1, ghost=1;
2541         
2542         if (!PyArg_ParseTuple(args,"O|ii:setParent", &pyobj, &addToCompound, &ghost)) {
2543                 return NULL; // Python sets a simple error
2544         }
2545         if (!ConvertPythonToGameObject(pyobj, &obj, true, "gameOb.setParent(obj): KX_GameObject"))
2546                 return NULL;
2547         if (obj)
2548                 this->SetParent(scene, obj, addToCompound, ghost);
2549         Py_RETURN_NONE;
2550 }
2551
2552 PyObject* KX_GameObject::PyRemoveParent()
2553 {
2554         KX_Scene *scene = KX_GetActiveScene();
2555         
2556         this->RemoveParent(scene);
2557         Py_RETURN_NONE;
2558 }
2559
2560
2561 PyObject* KX_GameObject::PySetCollisionMargin(PyObject* value)
2562 {
2563         float collisionMargin = PyFloat_AsDouble(value);
2564         
2565         if (collisionMargin==-1 && PyErr_Occurred()) {
2566                 PyErr_SetString(PyExc_TypeError, "expected a float");
2567                 return NULL;
2568         }
2569         
2570         if (m_pPhysicsController1)
2571         {
2572                 m_pPhysicsController1->setMargin(collisionMargin);
2573                 Py_RETURN_NONE;
2574         }
2575         PyErr_SetString(PyExc_RuntimeError, "This object has no physics controller");
2576         return NULL;
2577 }
2578
2579
2580
2581 PyObject* KX_GameObject::PyApplyImpulse(PyObject* args)
2582 {
2583         PyObject* pyattach;
2584         PyObject* pyimpulse;
2585         
2586         if (!m_pPhysicsController1)     {
2587                 PyErr_SetString(PyExc_RuntimeError, "This object has no physics controller");
2588                 return NULL;
2589         }
2590         
2591         if (PyArg_ParseTuple(args, "OO:applyImpulse", &pyattach, &pyimpulse))
2592         {
2593                 MT_Point3  attach;
2594                 MT_Vector3 impulse;
2595                 if (PyVecTo(pyattach, attach) && PyVecTo(pyimpulse, impulse))
2596                 {
2597                         m_pPhysicsController1->applyImpulse(attach, impulse);
2598                         Py_RETURN_NONE;
2599                 }
2600
2601         }
2602         
2603         return NULL;
2604 }
2605
2606
2607
2608 PyObject* KX_GameObject::PySuspendDynamics()
2609 {
2610         SuspendDynamics();
2611         Py_RETURN_NONE;
2612 }
2613
2614
2615
2616 PyObject* KX_GameObject::PyRestoreDynamics()
2617 {
2618         RestoreDynamics();
2619         Py_RETURN_NONE;
2620 }
2621
2622
2623 PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* args)
2624 {
2625         PyObject* pyvect;
2626         int axis = 2; //z axis is the default
2627         float fac = 1.0;
2628         
2629         if (PyArg_ParseTuple(args,"O|if:alignAxisToVect",&pyvect,&axis, &fac))
2630         {
2631                 MT_Vector3 vect;
2632                 if (PyVecTo(pyvect, vect))
2633                 {
2634                         if (fac<=0.0) Py_RETURN_NONE; // Nothing to do.
2635                         if (fac> 1.0) fac= 1.0;
2636                         
2637                         AlignAxisToVect(vect,axis,fac);
2638                         NodeUpdateGS(0.f);
2639                         Py_RETURN_NONE;
2640                 }
2641         }
2642         return NULL;
2643 }
2644
2645 PyObject* KX_GameObject::PyGetAxisVect(PyObject* value)
2646 {
2647         MT_Vector3 vect;
2648         if (PyVecTo(value, vect))
2649         {
2650                 return PyObjectFrom(NodeGetWorldOrientation() * vect);
2651         }
2652         return NULL;
2653 }
2654
2655
2656 PyObject* KX_GameObject::PyGetPhysicsId()
2657 {
2658         KX_IPhysicsController* ctrl = GetPhysicsController();
2659         uint_ptr physid=0;
2660         if (ctrl)
2661         {
2662                 physid= (uint_ptr)ctrl->GetUserData();
2663         }
2664         return PyLong_FromSsize_t((long)physid);
2665 }
2666
2667 PyObject* KX_GameObject::PyGetPropertyNames()
2668 {
2669         PyObject *list=  ConvertKeysToPython();
2670         
2671         if(m_attr_dict) {
2672                 PyObject *key, *value;
2673                 Py_ssize_t pos = 0;
2674
2675                 while (PyDict_Next(m_attr_dict, &pos, &key, &value)) {
2676                         PyList_Append(list, key);
2677                 }
2678         }
2679         return list;
2680 }
2681
2682 KX_PYMETHODDEF_DOC_O(KX_GameObject, getDistanceTo,
2683 "getDistanceTo(other): get distance to another point/KX_GameObject")
2684 {
2685         MT_Point3 b;
2686         if (PyVecTo(value, b))
2687         {
2688                 return PyFloat_FromDouble(NodeGetWorldPosition().distance(b));
2689         }
2690         PyErr_Clear();
2691         
2692         KX_GameObject *other;
2693         if (ConvertPythonToGameObject(value, &other, false, "gameOb.getDistanceTo(value): KX_GameObject"))
2694         {
2695                 return PyFloat_FromDouble(NodeGetWorldPosition().distance(other->NodeGetWorldPosition()));
2696         }
2697         
2698         return NULL;
2699 }
2700
2701 KX_PYMETHODDEF_DOC_O(KX_GameObject, getVectTo,
2702 "getVectTo(other): get vector and the distance to another point/KX_GameObject\n"
2703 "Returns a 3-tuple with (distance,worldVector,localVector)\n")
2704 {
2705         MT_Point3 toPoint, fromPoint;
2706         MT_Vector3 toDir, locToDir;
2707         MT_Scalar distance;
2708
2709         PyObject *returnValue;
2710
2711         if (!PyVecTo(value, toPoint))
2712         {
2713                 PyErr_Clear();
2714                 
2715                 KX_GameObject *other;
2716                 if (ConvertPythonToGameObject(value, &other, false, "")) /* error will be overwritten */
2717                 {
2718                         toPoint = other->NodeGetWorldPosition();
2719                 } else
2720                 {
2721                         PyErr_SetString(PyExc_TypeError, "gameOb.getVectTo(other): KX_GameObject, expected a 3D Vector or KX_GameObject type");
2722                         return NULL;
2723                 }
2724         }
2725
2726         fromPoint = NodeGetWorldPosition();
2727         toDir = toPoint-fromPoint;
2728         distance = toDir.length();
2729
2730         if (MT_fuzzyZero(distance))
2731         {
2732                 //cout << "getVectTo() Error: Null vector!\n";
2733                 locToDir = toDir = MT_Vector3(0.0,0.0,0.0);
2734                 distance = 0.0;
2735         } else {
2736                 toDir.normalize();
2737                 locToDir = toDir * NodeGetWorldOrientation();
2738         }
2739         
2740         returnValue = PyTuple_New(3);
2741         if (returnValue) { // very unlikely to fail, python sets a memory error here.
2742                 PyTuple_SET_ITEM(returnValue, 0, PyFloat_FromDouble(distance));
2743                 PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(toDir));
2744                 PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(locToDir));
2745         }
2746         return returnValue;
2747 }
2748
2749 bool KX_GameObject::RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data)
2750 {
2751         KX_GameObject* hitKXObj = client->m_gameobject;
2752         
2753         // if X-ray option is selected, the unwnted objects were not tested, so get here only with true hit
2754         // if not, all objects were tested and the front one may not be the correct one.
2755         if (m_xray || m_testPropName.Length() == 0 || hitKXObj->GetProperty(m_testPropName) != NULL)
2756         {
2757                 m_pHitObject = hitKXObj;
2758                 return true;
2759         }
2760         // return true to stop RayCast::RayTest from looping, the above test was decisive
2761         // We would want to loop only if we want to get more than one hit point
2762         return true;
2763 }
2764
2765 /* this function is used to pre-filter the object before casting the ray on them.
2766    This is useful for "X-Ray" option when we want to see "through" unwanted object.
2767  */
2768 bool KX_GameObject::NeedRayCast(KX_ClientObjectInfo* client)
2769 {
2770         KX_GameObject* hitKXObj = client->m_gameobject;
2771         
2772         if (client->m_type > KX_ClientObjectInfo::ACTOR)
2773         {
2774                 // Unknown type of object, skip it.
2775                 // Should not occur as the sensor objects are filtered in RayTest()
2776                 printf("Invalid client type %d found in ray casting\n", client->m_type);
2777                 return false;
2778         }
2779         
2780         // if X-Ray option is selected, skip object that don't match the criteria as we see through them
2781         // if not, test all objects because we don't know yet which one will be on front
2782         if (!m_xray || m_testPropName.Length() == 0 || hitKXObj->GetProperty(m_testPropName) != NULL)
2783         {
2784                 return true;
2785         }
2786         // skip the object
2787         return false;
2788 }
2789
2790 KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo,
2791 "rayCastTo(other,dist,prop): look towards another point/KX_GameObject and return first object hit within dist that matches prop\n"
2792 " prop = property name that object must have; can be omitted => detect any object\n"
2793 " dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to other\n"
2794 " other = 3-tuple or object reference")
2795 {
2796         MT_Point3 toPoint;
2797         PyObject* pyarg;
2798         float dist = 0.0f;
2799         char *propName = NULL;
2800
2801         if (!PyArg_ParseTuple(args,"O|fs:rayCastTo", &pyarg, &dist, &propName)) {
2802                 return NULL; // python sets simple error
2803         }
2804
2805         if (!PyVecTo(pyarg, toPoint))
2806         {
2807                 KX_GameObject *other;
2808                 PyErr_Clear();
2809                 
2810                 if (ConvertPythonToGameObject(pyarg, &other, false, "")) /* error will be overwritten */
2811                 {
2812                         toPoint = other->NodeGetWorldPosition();
2813                 } else
2814                 {
2815                         PyErr_SetString(PyExc_TypeError, "gameOb.rayCastTo(other,dist,prop): KX_GameObject, the first argument to rayCastTo must be a vector or a KX_GameObject");
2816                         return NULL;
2817                 }
2818         }
2819         MT_Point3 fromPoint = NodeGetWorldPosition();
2820         
2821         if (dist != 0.0f)
2822                 toPoint = fromPoint + dist * (toPoint-fromPoint).safe_normalized();
2823         
2824         PHY_IPhysicsEnvironment* pe = KX_GetActiveScene()->GetPhysicsEnvironment();
2825         KX_IPhysicsController *spc = GetPhysicsController();
2826         KX_GameObject *parent = GetParent();
2827         if (!spc && parent)
2828                 spc = parent->GetPhysicsController();
2829         if (parent)
2830                 parent->Release();
2831         
2832         m_pHitObject = NULL;
2833         if (propName)
2834                 m_testPropName = propName;
2835         else
2836                 m_testPropName.SetLength(0);
2837         KX_RayCast::Callback<KX_GameObject> callback(this,spc);
2838         KX_RayCast::RayTest(pe, fromPoint, toPoint, callback);
2839
2840         if (m_pHitObject)
2841                 return m_pHitObject->GetProxy();
2842         
2843         Py_RETURN_NONE;
2844 }
2845
2846 /* faster then Py_BuildValue since some scripts call raycast a lot */
2847 static PyObject *none_tuple_3()
2848 {
2849         PyObject *ret= PyTuple_New(3);
2850         PyTuple_SET_ITEM(ret, 0, Py_None);
2851         PyTuple_SET_ITEM(ret, 1, Py_None);
2852         PyTuple_SET_ITEM(ret, 2, Py_None);
2853         
2854         Py_INCREF(Py_None);
2855         Py_INCREF(Py_None);
2856         Py_INCREF(Py_None);
2857         return ret;
2858 }
2859 static PyObject *none_tuple_4()
2860 {
2861         PyObject *ret= PyTuple_New(4);
2862         PyTuple_SET_ITEM(ret, 0, Py_None);
2863         PyTuple_SET_ITEM(ret, 1, Py_None);
2864         PyTuple_SET_ITEM(ret, 2, Py_None);
2865         PyTuple_SET_ITEM(ret, 3, Py_None);
2866         
2867         Py_INCREF(Py_None);
2868         Py_INCREF(Py_None);
2869         Py_INCREF(Py_None);
2870         Py_INCREF(Py_None);
2871         return ret;
2872 }
2873
2874 static PyObject *none_tuple_5()
2875 {
2876         PyObject *ret= PyTuple_New(5);
2877         PyTuple_SET_ITEM(ret, 0, Py_None);
2878         PyTuple_SET_ITEM(ret, 1, Py_None);
2879         PyTuple_SET_ITEM(ret, 2, Py_None);
2880         PyTuple_SET_ITEM(ret, 3, Py_None);
2881         PyTuple_SET_ITEM(ret, 4, Py_None);
2882         
2883         Py_INCREF(Py_None);
2884         Py_INCREF(Py_None);
2885         Py_INCREF(Py_None);
2886         Py_INCREF(Py_None);
2887         Py_INCREF(Py_None);
2888         return ret;
2889 }
2890
2891 KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
2892                                    "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) or 4-tuple (object,hit,normal,polygon,hituv) of contact point with object within dist that matches prop.\n"
2893                                    " If no hit, return (None,None,None) or (None,None,None,None) or (None,None,None,None,None).\n"
2894 " to   = 3-tuple or object reference for destination of ray (if object, use center of object)\n"
2895 " from = 3-tuple or object reference for origin of ray (if object, use center of object)\n"
2896 "        Can be None or omitted => start from self object center\n"
2897 " dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to to\n"
2898 " prop = property name that object must have; can be omitted => detect any object\n"
2899 " face = normal option: 1=>return face normal; 0 or omitted => normal is oriented towards origin\n"
2900 " xray = X-ray option: 1=>skip objects that don't match prop; 0 or omitted => stop on first object\n"
2901 " poly = polygon option: 1=>return value is a 4-tuple and the 4th element is a KX_PolyProxy object\n"
2902 "                           which can be None if hit object has no mesh or if there is no hit\n"
2903 "                        2=>return value is a 5-tuple, the 4th element is the KX_PolyProxy object\n"
2904 "                           and the 5th element is the vector of UV coordinates at the hit point of the None if there is no UV mapping\n"
2905 "        If 0 or omitted, return value is a 3-tuple\n"
2906 "Note: The object on which you call this method matters: the ray will ignore it.\n"
2907 "      prop and xray option interact as follow:\n"
2908 "        prop off, xray off: return closest hit or no hit if there is no object on the full extend of the ray\n"
2909 "        prop off, xray on : idem\n"
2910 "        prop on,  xray off: return closest hit if it matches prop, no hit otherwise\n"
2911 "        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")
2912 {
2913         MT_Point3 toPoint;
2914         MT_Point3 fromPoint;
2915         PyObject* pyto;
2916         PyObject* pyfrom = NULL;
2917         float dist = 0.0f;
2918         char *propName = NULL;
2919         KX_GameObject *other;
2920         int face=0, xray=0, poly=0;
2921
2922         if (!PyArg_ParseTuple(args,"O|Ofsiii:rayCast", &pyto, &pyfrom, &dist, &propName, &face, &xray, &poly)) {
2923                 return NULL; // Python sets a simple error
2924         }
2925
2926         if (!PyVecTo(pyto, toPoint))
2927         {
2928                 PyErr_Clear();
2929                 
2930                 if (ConvertPythonToGameObject(pyto, &other, false, ""))  /* error will be overwritten */
2931                 {
2932                         toPoint = other->NodeGetWorldPosition();
2933                 } else
2934                 {
2935                         PyErr_SetString(PyExc_TypeError, "the first argument to rayCast must be a vector or a KX_GameObject");
2936                         return NULL;
2937                 }
2938         }
2939         if (!pyfrom || pyfrom == Py_None)
2940         {
2941                 fromPoint = NodeGetWorldPosition();
2942         }
2943         else if (!PyVecTo(pyfrom, fromPoint))
2944         {
2945                 PyErr_Clear();
2946                 
2947                 if (ConvertPythonToGameObject(pyfrom, &other, false, "")) /* error will be overwritten */
2948                 {
2949                         fromPoint = other->NodeGetWorldPosition();
2950                 } else
2951                 {
2952                         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");
2953                         return NULL;
2954                 }
2955         }
2956         
2957         if (dist != 0.0f) {
2958                 MT_Vector3 toDir = toPoint-fromPoint;
2959                 if (MT_fuzzyZero(toDir.length2())) {
2960                         //return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
2961                         return none_tuple_3();
2962                 }
2963                 toDir.normalize();
2964                 toPoint = fromPoint + (dist) * toDir;
2965         } else if (MT_fuzzyZero((toPoint-fromPoint).length2())) {
2966                 //return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
2967                 return none_tuple_3();
2968         }
2969         
2970         PHY_IPhysicsEnvironment* pe = KX_GetActiveScene()->GetPhysicsEnvironment();
2971         KX_IPhysicsController *spc = GetPhysicsController();
2972         KX_GameObject *parent = GetParent();
2973         if (!spc && parent)
2974                 spc = parent->GetPhysicsController();
2975         if (parent)
2976                 parent->Release();
2977         
2978         m_pHitObject = NULL;
2979         if (propName)
2980                 m_testPropName = propName;
2981         else
2982                 m_testPropName.SetLength(0);
2983         m_xray = xray;
2984         // to get the hit results
2985         KX_RayCast::Callback<KX_GameObject> callback(this,spc,NULL,face,(poly==2));
2986         KX_RayCast::RayTest(pe, fromPoint, toPoint, callback);
2987
2988         if (m_pHitObject)
2989         {
2990                 PyObject* returnValue = (poly==2) ? PyTuple_New(5) : (poly) ? PyTuple_New(4) : PyTuple_New(3);
2991                 if (returnValue) { // unlikely this would ever fail, if it does python sets an error
2992                         PyTuple_SET_ITEM(returnValue, 0, m_pHitObject->GetProxy());
2993                         PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(callback.m_hitPoint));
2994                         PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(callback.m_hitNormal));
2995                         if (poly)
2996                         {
2997                                 if (callback.m_hitMesh)
2998                                 {
2999                                         // if this field is set, then we can trust that m_hitPolygon is a valid polygon
3000                                         RAS_Polygon* polygon = callback.m_hitMesh->GetPolygon(callback.m_hitPolygon);
3001                                         KX_PolyProxy* polyproxy = new KX_PolyProxy(callback.m_hitMesh, polygon);
3002                                         PyTuple_SET_ITEM(returnValue, 3, polyproxy->NewProxy(true));
3003                                         if (poly == 2)
3004                                         {
3005                                                 if (callback.m_hitUVOK)
3006                                                         PyTuple_SET_ITEM(returnValue, 4, PyObjectFrom(callback.m_hitUV));
3007                                                 else {
3008                                                         Py_INCREF(Py_None);
3009                                                         PyTuple_SET_ITEM(returnValue, 4, Py_None);
3010                                                 }
3011                                         }
3012                                 }
3013                                 else
3014                                 {
3015                                         Py_INCREF(Py_None);
3016                                         PyTuple_SET_ITEM(returnValue, 3, Py_None);
3017                                         if (poly==2)
3018                                         {
3019                                                 Py_INCREF(Py_None);
3020                                                 PyTuple_SET_ITEM(returnValue, 4, Py_None);
3021                                         }
3022                                 }
3023                         }
3024                 }
3025                 return returnValue;
3026         }
3027         // no hit
3028         if (poly == 2)
3029                 return none_tuple_5();
3030         else if (poly)
3031                 return none_tuple_4();
3032         else
3033                 return none_tuple_3();
3034 }
3035
3036 KX_PYMETHODDEF_DOC_VARARGS(KX_GameObject, sendMessage, 
3037                                                    "sendMessage(subject, [body, to])\n"
3038 "sends a message in same manner as a message actuator"
3039 "subject = Subject of the message (string)"
3040 "body = Message body (string)"
3041 "to = Name of object to send the message to")
3042 {
3043         KX_Scene *scene = KX_GetActiveScene();
3044         char* subject;
3045         char* body = (char *)"";
3046         char* to = (char *)"";
3047         const STR_String& from = GetName();
3048
3049         if (!PyArg_ParseTuple(args, "s|ss:sendMessage", &subject, &body, &to))
3050                 return NULL;
3051         
3052         scene->GetNetworkScene()->SendMessage(to, from, subject, body);
3053         Py_RETURN_NONE;
3054 }
3055
3056 static void layer_check(short &layer, const char *method_name)
3057 {
3058         if (layer < 0 || layer >= MAX_ACTION_LAYERS)
3059         {
3060                 printf("KX_GameObject.%s(): given layer (%d) is out of range (0 - %d), setting to 0.\n", method_name, layer, MAX_ACTION_LAYERS-1);
3061                 layer = 0;
3062         }
3063 }
3064
3065 KX_PYMETHODDEF_DOC(KX_GameObject, playAction,
3066         "playAction(name, start_frame, end_frame, layer=0, priority=0 blendin=0, play_mode=ACT_MODE_PLAY, layer_weight=0.0, ipo_flags=0, speed=1.0)\n"
3067         "Plays an action\n")
3068 {
3069         const char* name;
3070         float start, end, blendin=0.f, speed=1.f, layer_weight=0.f;
3071         short layer=0, priority=0;
3072         short ipo_flags=0;
3073         short play_mode=0;
3074
3075         static const char *kwlist[] = {"name", "start_frame", "end_frame", "layer", "priority", "blendin", "play_mode", "layer_weight", "ipo_flags", "speed", NULL};
3076
3077         if (!PyArg_ParseTupleAndKeywords(args, kwds, "sff|hhfhfhf:playAction", const_cast<char**>(kwlist),
3078                                                                         &name, &start, &end, &layer, &priority, &blendin, &play_mode, &layer_weight, &ipo_flags, &speed))
3079                 return NULL;
3080
3081         layer_check(layer, "playAction");
3082
3083         if (play_mode < 0 || play_mode > BL_Action::ACT_MODE_MAX)
3084         {
3085                 printf("KX_GameObject.playAction(): given play_mode (%d) is out of range (0 - %d), setting to ACT_MODE_PLAY", play_mode, BL_Action::ACT_MODE_MAX-1);
3086                 play_mode = BL_Action::ACT_MODE_MAX;
3087         }
3088
3089         if (layer_weight < 0.f || layer_weight > 1.f)
3090         {
3091                 printf("KX_GameObject.playAction(): given layer_weight (%f) is out of range (0.0 - 1.0), setting to 0.0", layer_weight);
3092                 layer_weight = 0.f;
3093         }
3094
3095         PlayAction(name, start, end, layer, priority, blendin, play_mode, layer_weight, ipo_flags, speed);
3096
3097         Py_RETURN_NONE;
3098 }
3099
3100 KX_PYMETHODDEF_DOC(KX_GameObject, stopAction,
3101         "stopAction(layer=0)\n"
3102         "Stop playing the action on the given layer\n")
3103 {
3104         short layer=0;
3105
3106         if (!PyArg_ParseTuple(args, "|h:stopAction", &layer))
3107                 return NULL;
3108
3109         layer_check(layer, "stopAction");
3110
3111         StopAction(layer);
3112
3113         Py_RETURN_NONE;
3114 }
3115
3116 KX_PYMETHODDEF_DOC(KX_GameObject, getActionFrame,
3117         "getActionFrame(layer=0)\n"
3118         "Gets the current frame of the action playing in the supplied layer\n")
3119 {
3120         short layer=0;
3121
3122         if (!PyArg_ParseTuple(args, "|h:getActionFrame", &layer))
3123                 return NULL;
3124
3125         layer_check(layer, "getActionFrame");
3126
3127         return PyFloat_FromDouble(GetActionFrame(layer));
3128 }
3129
3130 KX_PYMETHODDEF_DOC(KX_GameObject, setActionFrame,
3131         "setActionFrame(frame, layer=0)\n"
3132         "Set the current frame of the action playing in the supplied layer\n")
3133 {
3134         short layer=0;
3135         float frame;
3136
3137         if (!PyArg_ParseTuple(args, "f|h:setActionFrame", &frame, &layer))
3138                 return NULL;
3139
3140         layer_check(layer, "setActionFrame");
3141
3142         SetActionFrame(layer, frame);
3143
3144         Py_RETURN_NONE;
3145 }
3146
3147 KX_PYMETHODDEF_DOC(KX_GameObject, isPlayingAction,
3148         "isPlayingAction(layer=0)\n"
3149         "Checks to see if there is an action playing in the given layer\n")
3150 {
3151         short layer=0;
3152
3153         if (!PyArg_ParseTuple(args, "|h:isPlayingAction", &layer))
3154                 return NULL;
3155
3156         layer_check(layer, "isPlayingAction");
3157
3158         return PyBool_FromLong(!IsActionDone(layer));
3159 }
3160
3161
3162 /* dict style access */
3163
3164
3165 /* Matches python dict.get(key, [default]) */
3166 PyObject* KX_GameObject::Pyget(PyObject *args)
3167 {
3168         PyObject *key;
3169         PyObject* def = Py_None;
3170         PyObject* ret;
3171
3172         if (!PyArg_ParseTuple(args, "O|O:get", &key, &def))
3173                 return NULL;
3174         
3175         
3176         if(PyUnicode_Check(key)) {
3177                 CValue *item = GetProperty(_PyUnicode_AsString(key));
3178                 if (item) {
3179                         ret = item->ConvertValueToPython();
3180                         if(ret)
3181                                 return ret;
3182                         else
3183                                 return item->GetProxy();
3184                 }
3185         }
3186         
3187         if (m_attr_dict && (ret=PyDict_GetItem(m_attr_dict, key))) {
3188                 Py_INCREF(ret);
3189                 return ret;
3190         }
3191         
3192         Py_INCREF(def);
3193         return def;
3194 }
3195
3196 bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py_none_ok, const char *error_prefix)
3197 {
3198         if (value==NULL) {
3199                 PyErr_Format(PyExc_TypeError, "%s, python pointer NULL, should never happen", error_prefix);
3200                 *object = NULL;
3201                 return false;
3202         }
3203                 
3204         if (value==Py_None) {
3205                 *object = NULL;
3206                 
3207                 if (py_none_ok) {
3208                         return true;
3209                 } else {
3210                         PyErr_Format(PyExc_TypeError, "%s, expected KX_GameObject or a KX_GameObject name, None is invalid", error_prefix);
3211                         return false;
3212                 }
3213         }
3214         
3215         if (PyUnicode_Check(value)) {
3216                 *object = (KX_GameObject*)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String( _PyUnicode_AsString(value) ));
3217                 
3218                 if (*object) {
3219                         return true;
3220                 } else {
3221                         PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_GameObject in this scene", error_prefix, _PyUnicode_AsString(value));
3222                         return false;
3223                 }
3224         }
3225         
3226         if (    PyObject_TypeCheck(value, &KX_GameObject::Type) ||
3227                         PyObject_TypeCheck(value, &KX_LightObject::Type)        ||
3228                         PyObject_TypeCheck(value, &KX_Camera::Type)                     ||
3229                         PyObject_TypeCheck(value, &KX_FontObject::Type))
3230         {
3231                 *object = static_cast<KX_GameObject*>BGE_PROXY_REF(value);
3232                 
3233                 /* sets the error */
3234                 if (*object==NULL) {
3235                         PyErr_Format(PyExc_SystemError, "%s, " BGE_PROXY_ERROR_MSG, error_prefix);
3236                         return false;
3237                 }
3238                 
3239                 return true;
3240         }
3241         
3242         *object = NULL;
3243         
3244         if (py_none_ok) {
3245                 PyErr_Format(PyExc_TypeError, "%s, expect a KX_GameObject, a string or None", error_prefix);
3246         } else {
3247                 PyErr_Format(PyExc_TypeError, "%s, expect a KX_GameObject or a string", error_prefix);
3248         }
3249         
3250         return false;
3251 }
3252 #endif // WITH_PYTHON