Blender  V2.59
KX_Scene.cpp
Go to the documentation of this file.
00001 /*
00002  * $Id: KX_Scene.cpp 36523 2011-05-06 20:18:42Z blendix $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  *
00020  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00021  * All rights reserved.
00022  *
00023  * The Original Code is: all of this file.
00024  *
00025  * Contributor(s): none yet.
00026  *
00027  * ***** END GPL LICENSE BLOCK *****
00028  * Ketsji scene. Holds references to all scene data.
00029  */
00030 
00036 #if defined(WIN32) && !defined(FREE_WINDOWS)
00037 #pragma warning (disable : 4786)
00038 #endif //WIN32
00039 
00040 #include "KX_Scene.h"
00041 #include "KX_PythonInit.h"
00042 #include "MT_assert.h"
00043 #include "KX_KetsjiEngine.h"
00044 #include "KX_BlenderMaterial.h"
00045 #include "RAS_IPolygonMaterial.h"
00046 #include "ListValue.h"
00047 #include "SCA_LogicManager.h"
00048 #include "SCA_TimeEventManager.h"
00049 //#include "SCA_AlwaysEventManager.h"
00050 //#include "SCA_RandomEventManager.h"
00051 //#include "KX_RayEventManager.h"
00052 #include "KX_TouchEventManager.h"
00053 #include "SCA_KeyboardManager.h"
00054 #include "SCA_MouseManager.h"
00055 //#include "SCA_PropertyEventManager.h"
00056 #include "SCA_ActuatorEventManager.h"
00057 #include "SCA_BasicEventManager.h"
00058 #include "KX_Camera.h"
00059 #include "SCA_JoystickManager.h"
00060 
00061 #include "RAS_MeshObject.h"
00062 
00063 #include "RAS_IRasterizer.h"
00064 #include "RAS_BucketManager.h"
00065 
00066 #include "FloatValue.h"
00067 #include "SCA_IController.h"
00068 #include "SCA_IActuator.h"
00069 #include "SG_Node.h"
00070 #include "BL_System.h"
00071 #include "SG_Controller.h"
00072 #include "SG_IObject.h"
00073 #include "SG_Tree.h"
00074 #include "DNA_group_types.h"
00075 #include "DNA_scene_types.h"
00076 
00077 #include "KX_SG_NodeRelationships.h"
00078 
00079 #include "KX_NetworkEventManager.h"
00080 #include "NG_NetworkScene.h"
00081 #include "PHY_IPhysicsEnvironment.h"
00082 #include "KX_IPhysicsController.h"
00083 #include "PHY_IGraphicController.h"
00084 #include "KX_BlenderSceneConverter.h"
00085 #include "KX_MotionState.h"
00086 
00087 #include "BL_ModifierDeformer.h"
00088 #include "BL_ShapeDeformer.h"
00089 #include "BL_DeformableGameObject.h"
00090 
00091 #ifdef USE_BULLET
00092 #include "KX_SoftBodyDeformer.h"
00093 #include "KX_ConvertPhysicsObject.h"
00094 #include "CcdPhysicsEnvironment.h"
00095 #include "CcdPhysicsController.h"
00096 #endif
00097 
00098 #include "KX_Light.h"
00099 
00100 #include <stdio.h>
00101 
00102 void* KX_SceneReplicationFunc(SG_IObject* node,void* gameobj,void* scene)
00103 {
00104         KX_GameObject* replica = ((KX_Scene*)scene)->AddNodeReplicaObject(node,(KX_GameObject*)gameobj);
00105 
00106         if(replica)
00107                 replica->Release();
00108 
00109         return (void*)replica;
00110 }
00111 
00112 void* KX_SceneDestructionFunc(SG_IObject* node,void* gameobj,void* scene)
00113 {
00114         ((KX_Scene*)scene)->RemoveNodeDestructObject(node,(KX_GameObject*)gameobj);
00115 
00116         return NULL;
00117 };
00118 
00119 bool KX_Scene::KX_ScenegraphUpdateFunc(SG_IObject* node,void* gameobj,void* scene)
00120 {
00121         return ((SG_Node*)node)->Schedule(((KX_Scene*)scene)->m_sghead);
00122 }
00123 
00124 bool KX_Scene::KX_ScenegraphRescheduleFunc(SG_IObject* node,void* gameobj,void* scene)
00125 {
00126         return ((SG_Node*)node)->Reschedule(((KX_Scene*)scene)->m_sghead);
00127 }
00128 
00129 SG_Callbacks KX_Scene::m_callbacks = SG_Callbacks(
00130         KX_SceneReplicationFunc,
00131         KX_SceneDestructionFunc,
00132         KX_GameObject::UpdateTransformFunc,
00133         KX_Scene::KX_ScenegraphUpdateFunc,
00134         KX_Scene::KX_ScenegraphRescheduleFunc);
00135 
00136 // temporarily var until there is a button in the userinterface
00137 // (defined in KX_PythonInit.cpp)
00138 extern bool gUseVisibilityTemp;
00139 
00140 KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice,
00141                                    class SCA_IInputDevice* mousedevice,
00142                                    class NG_NetworkDeviceInterface *ndi,
00143                                    const STR_String& sceneName,
00144                                    Scene *scene,
00145                                    class RAS_ICanvas* canvas): 
00146         PyObjectPlus(),
00147         m_keyboardmgr(NULL),
00148         m_mousemgr(NULL),
00149         m_sceneConverter(NULL),
00150         m_physicsEnvironment(0),
00151         m_sceneName(sceneName),
00152         m_networkDeviceInterface(ndi),
00153         m_active_camera(NULL),
00154         m_ueberExecutionPriority(0),
00155         m_blenderScene(scene)
00156 {
00157         m_suspendedtime = 0.0;
00158         m_suspendeddelta = 0.0;
00159 
00160         m_dbvt_culling = false;
00161         m_dbvt_occlusion_res = 0;
00162         m_activity_culling = false;
00163         m_suspend = false;
00164         m_isclearingZbuffer = true;
00165         m_tempObjectList = new CListValue();
00166         m_objectlist = new CListValue();
00167         m_parentlist = new CListValue();
00168         m_lightlist= new CListValue();
00169         m_inactivelist = new CListValue();
00170         m_euthanasyobjects = new CListValue();
00171 
00172         m_logicmgr = new SCA_LogicManager();
00173         
00174         m_timemgr = new SCA_TimeEventManager(m_logicmgr);
00175         m_keyboardmgr = new SCA_KeyboardManager(m_logicmgr,keyboarddevice);
00176         m_mousemgr = new SCA_MouseManager(m_logicmgr,mousedevice, canvas);
00177         
00178         //SCA_AlwaysEventManager* alwaysmgr = new SCA_AlwaysEventManager(m_logicmgr);
00179         //SCA_PropertyEventManager* propmgr = new SCA_PropertyEventManager(m_logicmgr);
00180         SCA_ActuatorEventManager* actmgr = new SCA_ActuatorEventManager(m_logicmgr);
00181         //SCA_RandomEventManager* rndmgr = new SCA_RandomEventManager(m_logicmgr);
00182         SCA_BasicEventManager* basicmgr = new SCA_BasicEventManager(m_logicmgr);
00183         //KX_RayEventManager* raymgr = new KX_RayEventManager(m_logicmgr);
00184 
00185         KX_NetworkEventManager* netmgr = new KX_NetworkEventManager(m_logicmgr, ndi);
00186         
00187         
00188 
00189         //m_logicmgr->RegisterEventManager(alwaysmgr);
00190         //m_logicmgr->RegisterEventManager(propmgr);
00191         m_logicmgr->RegisterEventManager(actmgr);
00192         m_logicmgr->RegisterEventManager(m_keyboardmgr);
00193         m_logicmgr->RegisterEventManager(m_mousemgr);
00194         m_logicmgr->RegisterEventManager(m_timemgr);
00195         //m_logicmgr->RegisterEventManager(rndmgr);
00196         //m_logicmgr->RegisterEventManager(raymgr);
00197         m_logicmgr->RegisterEventManager(netmgr);
00198         m_logicmgr->RegisterEventManager(basicmgr);
00199 
00200 
00201         SYS_SystemHandle hSystem = SYS_GetSystem();
00202         bool nojoystick= SYS_GetCommandLineInt(hSystem,"nojoystick",0);
00203         if (!nojoystick)
00204         {
00205                 SCA_JoystickManager *joymgr     = new SCA_JoystickManager(m_logicmgr);
00206                 m_logicmgr->RegisterEventManager(joymgr);
00207         }
00208 
00209         MT_assert (m_networkDeviceInterface != NULL);
00210         m_networkScene = new NG_NetworkScene(m_networkDeviceInterface);
00211         
00212         m_rootnode = NULL;
00213 
00214         m_bucketmanager=new RAS_BucketManager();
00215         
00216 #ifdef WITH_PYTHON
00217         m_attr_dict = PyDict_New(); /* new ref */
00218         m_draw_call_pre = NULL;
00219         m_draw_call_post = NULL;
00220 #endif
00221 }
00222 
00223 
00224 
00225 KX_Scene::~KX_Scene()
00226 {
00227         // The release of debug properties used to be in SCA_IScene::~SCA_IScene
00228         // It's still there but we remove all properties here otherwise some
00229         // reference might be hanging and causing late release of objects
00230         RemoveAllDebugProperties();
00231 
00232         while (GetRootParentList()->GetCount() > 0) 
00233         {
00234                 KX_GameObject* parentobj = (KX_GameObject*) GetRootParentList()->GetValue(0);
00235                 this->RemoveObject(parentobj);
00236         }
00237 
00238         if(m_objectlist)
00239                 m_objectlist->Release();
00240 
00241         if (m_parentlist)
00242                 m_parentlist->Release();
00243         
00244         if (m_inactivelist)
00245                 m_inactivelist->Release();
00246 
00247         if (m_lightlist)
00248                 m_lightlist->Release();
00249         
00250         if (m_tempObjectList)
00251                 m_tempObjectList->Release();
00252 
00253         if (m_euthanasyobjects)
00254                 m_euthanasyobjects->Release();
00255 
00256         if (m_logicmgr)
00257                 delete m_logicmgr;
00258 
00259         if (m_physicsEnvironment)
00260                 delete m_physicsEnvironment;
00261 
00262         if (m_networkScene)
00263                 delete m_networkScene;
00264         
00265         if (m_bucketmanager)
00266         {
00267                 delete m_bucketmanager;
00268         }
00269 
00270 #ifdef WITH_PYTHON
00271         PyDict_Clear(m_attr_dict);
00272         /* Py_CLEAR: Py_DECREF's and NULL's */
00273         Py_CLEAR(m_attr_dict);
00274 
00275         /* these may be NULL but the macro checks */
00276         Py_CLEAR(m_draw_call_pre);
00277         Py_CLEAR(m_draw_call_post);
00278 #endif
00279 }
00280 
00281 RAS_BucketManager* KX_Scene::GetBucketManager()
00282 {
00283         return m_bucketmanager;
00284 }
00285 
00286 
00287 CListValue* KX_Scene::GetTempObjectList()
00288 {
00289         return m_tempObjectList;
00290 }
00291 
00292 CListValue* KX_Scene::GetObjectList()
00293 {
00294         return m_objectlist;
00295 }
00296 
00297 
00298 CListValue* KX_Scene::GetRootParentList()
00299 {
00300         return m_parentlist;
00301 }
00302 
00303 CListValue* KX_Scene::GetInactiveList()
00304 {
00305         return m_inactivelist;
00306 }
00307 
00308 
00309 
00310 CListValue* KX_Scene::GetLightList()
00311 {
00312         return m_lightlist;
00313 }
00314 
00315 SCA_LogicManager* KX_Scene::GetLogicManager()
00316 {
00317         return m_logicmgr;
00318 }
00319 
00320 SCA_TimeEventManager* KX_Scene::GetTimeEventManager()
00321 {
00322         return m_timemgr;
00323 }
00324 
00325 
00326 
00327  
00328 list<class KX_Camera*>* KX_Scene::GetCameras()
00329 {
00330         return &m_cameras;
00331 }
00332 
00333 list<class KX_FontObject*>* KX_Scene::GetFonts()
00334 {
00335         return &m_fonts;
00336 }
00337 
00338 void KX_Scene::SetFramingType(RAS_FrameSettings & frame_settings)
00339 {
00340         m_frame_settings = frame_settings;
00341 };
00342 
00349 const RAS_FrameSettings& KX_Scene::GetFramingType() const 
00350 {
00351         return m_frame_settings;
00352 };      
00353 
00354 
00355 
00360 void KX_Scene::SetSceneViewport(const RAS_Rect &viewport)
00361 {
00362         m_viewport = viewport;
00363 }
00364 
00365 
00366 
00367 const RAS_Rect& KX_Scene::GetSceneViewport() const 
00368 {
00369         return m_viewport;
00370 }
00371 
00372 
00373 
00374 void KX_Scene::SetWorldInfo(class KX_WorldInfo* worldinfo)
00375 {
00376         m_worldinfo = worldinfo;
00377 }
00378 
00379 
00380 
00381 class KX_WorldInfo* KX_Scene::GetWorldInfo()
00382 {
00383         return m_worldinfo;
00384 }
00385 
00386 
00387 const STR_String& KX_Scene::GetName()
00388 {
00389         return m_sceneName;
00390 }
00391 
00392 
00393 void KX_Scene::Suspend()
00394 {
00395         m_suspend = true;
00396 }
00397 
00398 void KX_Scene::Resume()
00399 {
00400         m_suspend = false;
00401 }
00402 
00403 void KX_Scene::SetActivityCulling(bool b)
00404 {
00405         m_activity_culling = b;
00406 }
00407 
00408 bool KX_Scene::IsSuspended()
00409 {
00410         return m_suspend;
00411 }
00412 
00413 bool KX_Scene::IsClearingZBuffer()
00414 {
00415         return m_isclearingZbuffer;
00416 }
00417 
00418 void KX_Scene::EnableZBufferClearing(bool isclearingZbuffer)
00419 {
00420         m_isclearingZbuffer = isclearingZbuffer;
00421 }
00422 
00423 void KX_Scene::RemoveNodeDestructObject(class SG_IObject* node,class CValue* gameobj)
00424 {
00425         KX_GameObject* orgobj = (KX_GameObject*)gameobj;        
00426         if (NewRemoveObject(orgobj) != 0)
00427         {
00428                 // object is not yet deleted because a reference is hanging somewhere.
00429                 // This should not happen anymore since we use proxy object for Python
00430                 // confident enough to put an assert?
00431                 //assert(false);
00432                 printf("Zombie object! name=%s\n", orgobj->GetName().ReadPtr());
00433                 orgobj->SetSGNode(NULL);
00434                 PHY_IGraphicController* ctrl = orgobj->GetGraphicController();
00435                 if (ctrl)
00436                 {
00437                         // a graphic controller is set, we must delete it as the node will be deleted
00438                         delete ctrl;
00439                         orgobj->SetGraphicController(NULL);
00440                 }
00441         }
00442         if (node)
00443                 delete node;
00444 }
00445 
00446 KX_GameObject* KX_Scene::AddNodeReplicaObject(class SG_IObject* node, class CValue* gameobj)
00447 {
00448         // for group duplication, limit the duplication of the hierarchy to the
00449         // objects that are part of the group. 
00450         if (!IsObjectInGroup(gameobj))
00451                 return NULL;
00452         
00453         KX_GameObject* orgobj = (KX_GameObject*)gameobj;
00454         KX_GameObject* newobj = (KX_GameObject*)orgobj->GetReplica();
00455         m_map_gameobject_to_replica.insert(orgobj, newobj);
00456 
00457         // also register 'timers' (time properties) of the replica
00458         int numprops = newobj->GetPropertyCount();
00459 
00460         for (int i = 0; i < numprops; i++)
00461         {
00462                 CValue* prop = newobj->GetProperty(i);
00463 
00464                 if (prop->GetProperty("timer"))
00465                         this->m_timemgr->AddTimeProperty(prop);
00466         }
00467 
00468         if (node)
00469         {
00470                 newobj->SetSGNode((SG_Node*)node);
00471         }
00472         else
00473         {
00474                 m_rootnode = new SG_Node(newobj,this,KX_Scene::m_callbacks);
00475         
00476                 // this fixes part of the scaling-added object bug
00477                 SG_Node* orgnode = orgobj->GetSGNode();
00478                 m_rootnode->SetLocalScale(orgnode->GetLocalScale());
00479                 m_rootnode->SetLocalPosition(orgnode->GetLocalPosition());
00480                 m_rootnode->SetLocalOrientation(orgnode->GetLocalOrientation());
00481 
00482                 // define the relationship between this node and it's parent.
00483                 KX_NormalParentRelation * parent_relation = 
00484                         KX_NormalParentRelation::New();
00485                 m_rootnode->SetParentRelation(parent_relation);
00486 
00487                 newobj->SetSGNode(m_rootnode);
00488         }
00489         
00490         SG_IObject* replicanode = newobj->GetSGNode();
00491 //      SG_Node* rootnode = (replicanode == m_rootnode ? NULL : m_rootnode);
00492 
00493         replicanode->SetSGClientObject(newobj);
00494 
00495         // this is the list of object that are send to the graphics pipeline
00496         m_objectlist->Add(newobj->AddRef());
00497         if (newobj->GetGameObjectType()==SCA_IObject::OBJ_LIGHT)
00498                 m_lightlist->Add(newobj->AddRef());
00499         newobj->AddMeshUser();
00500 
00501         // logic cannot be replicated, until the whole hierarchy is replicated.
00502         m_logicHierarchicalGameObjects.push_back(newobj);
00503         //replicate controllers of this node
00504         SGControllerList        scenegraphcontrollers = orgobj->GetSGNode()->GetSGControllerList();
00505         replicanode->RemoveAllControllers();
00506         SGControllerList::iterator cit;
00507         //int numcont = scenegraphcontrollers.size();
00508         
00509         for (cit = scenegraphcontrollers.begin();!(cit==scenegraphcontrollers.end());++cit)
00510         {
00511                 // controller replication is quite complicated
00512                 // only replicate ipo and physics controller for now
00513 
00514                 SG_Controller* replicacontroller = (*cit)->GetReplica((SG_Node*) replicanode);
00515                 if (replicacontroller)
00516                 {
00517                         replicacontroller->SetObject(replicanode);
00518                         replicanode->AddSGController(replicacontroller);
00519                 }
00520         }
00521         // replicate graphic controller
00522         if (orgobj->GetGraphicController())
00523         {
00524                 PHY_IMotionState* motionstate = new KX_MotionState(newobj->GetSGNode());
00525                 PHY_IGraphicController* newctrl = orgobj->GetGraphicController()->GetReplica(motionstate);
00526                 newctrl->setNewClientInfo(newobj->getClientInfo());
00527                 newobj->SetGraphicController(newctrl);
00528         }
00529         return newobj;
00530 }
00531 
00532 
00533 
00534 // before calling this method KX_Scene::ReplicateLogic(), make sure to
00535 // have called 'GameObject::ReParentLogic' for each object this
00536 // hierarchy that's because first ALL bricks must exist in the new
00537 // replica of the hierarchy in order to make cross-links work properly
00538 // !
00539 // It is VERY important that the order of sensors and actuators in
00540 // the replicated object is preserved: it is used to reconnect the logic.
00541 // This method is more robust then using the bricks name in case of complex 
00542 // group replication. The replication of logic bricks is done in 
00543 // SCA_IObject::ReParentLogic(), make sure it preserves the order of the bricks.
00544 void KX_Scene::ReplicateLogic(KX_GameObject* newobj)
00545 {
00546         // also relink the controller to sensors/actuators
00547         SCA_ControllerList& controllers = newobj->GetControllers();
00548         //SCA_SensorList&     sensors     = newobj->GetSensors();
00549         //SCA_ActuatorList&   actuators   = newobj->GetActuators();
00550 
00551         for (SCA_ControllerList::iterator itc = controllers.begin(); !(itc==controllers.end());itc++)
00552         {
00553                 SCA_IController* cont = (*itc);
00554                 cont->SetUeberExecutePriority(m_ueberExecutionPriority);
00555                 vector<SCA_ISensor*> linkedsensors = cont->GetLinkedSensors();
00556                 vector<SCA_IActuator*> linkedactuators = cont->GetLinkedActuators();
00557 
00558                 // disconnect the sensors and actuators
00559                 // do it directly on the list at this controller is not connected to anything at this stage
00560                 cont->GetLinkedSensors().clear();
00561                 cont->GetLinkedActuators().clear();
00562                 
00563                 // now relink each sensor
00564                 for (vector<SCA_ISensor*>::iterator its = linkedsensors.begin();!(its==linkedsensors.end());its++)
00565                 {
00566                         SCA_ISensor* oldsensor = (*its);
00567                         SCA_IObject* oldsensorobj = oldsensor->GetParent();
00568                         SCA_IObject* newsensorobj = NULL;
00569                 
00570                         // the original owner of the sensor has been replicated?
00571                         void **h_obj = m_map_gameobject_to_replica[oldsensorobj];
00572                         if (h_obj)
00573                                 newsensorobj = (SCA_IObject*)(*h_obj);
00574                         if (!newsensorobj)
00575                         {
00576                                 // no, then the sensor points outside the hierachy, keep it the same
00577                                 if (m_objectlist->SearchValue(oldsensorobj))
00578                                         // only replicate links that points to active objects
00579                                         m_logicmgr->RegisterToSensor(cont,oldsensor);
00580                         }
00581                         else
00582                         {
00583                                 // yes, then the new sensor has the same position
00584                                 SCA_SensorList& sensorlist = oldsensorobj->GetSensors();
00585                                 SCA_SensorList::iterator sit;
00586                                 SCA_ISensor* newsensor = NULL;
00587                                 int sensorpos;
00588 
00589                                 for (sensorpos=0, sit=sensorlist.begin(); sit!=sensorlist.end(); sit++, sensorpos++)
00590                                 {
00591                                         if ((*sit) == oldsensor) 
00592                                         {
00593                                                 newsensor = newsensorobj->GetSensors().at(sensorpos);
00594                                                 break;
00595                                         }
00596                                 }
00597                                 assert(newsensor != NULL);
00598                                 m_logicmgr->RegisterToSensor(cont,newsensor);
00599                         }
00600                 }
00601                 
00602                 // now relink each actuator
00603                 for (vector<SCA_IActuator*>::iterator ita = linkedactuators.begin();!(ita==linkedactuators.end());ita++)
00604                 {
00605                         SCA_IActuator* oldactuator = (*ita);
00606                         SCA_IObject* oldactuatorobj = oldactuator->GetParent();
00607                         SCA_IObject* newactuatorobj = NULL;
00608 
00609                         // the original owner of the sensor has been replicated?
00610                         void **h_obj = m_map_gameobject_to_replica[oldactuatorobj];
00611                         if (h_obj)
00612                                 newactuatorobj = (SCA_IObject*)(*h_obj);
00613 
00614                         if (!newactuatorobj)
00615                         {
00616                                 // no, then the sensor points outside the hierachy, keep it the same
00617                                 if (m_objectlist->SearchValue(oldactuatorobj))
00618                                         // only replicate links that points to active objects
00619                                         m_logicmgr->RegisterToActuator(cont,oldactuator);
00620                         }
00621                         else
00622                         {
00623                                 // yes, then the new sensor has the same position
00624                                 SCA_ActuatorList& actuatorlist = oldactuatorobj->GetActuators();
00625                                 SCA_ActuatorList::iterator ait;
00626                                 SCA_IActuator* newactuator = NULL;
00627                                 int actuatorpos;
00628 
00629                                 for (actuatorpos=0, ait=actuatorlist.begin(); ait!=actuatorlist.end(); ait++, actuatorpos++)
00630                                 {
00631                                         if ((*ait) == oldactuator) 
00632                                         {
00633                                                 newactuator = newactuatorobj->GetActuators().at(actuatorpos);
00634                                                 break;
00635                                         }
00636                                 }
00637                                 assert(newactuator != NULL);
00638                                 m_logicmgr->RegisterToActuator(cont,newactuator);
00639                                 newactuator->SetUeberExecutePriority(m_ueberExecutionPriority);
00640                         }
00641                 }
00642         }
00643         // ready to set initial state
00644         newobj->ResetState();
00645 }
00646 
00647 void KX_Scene::DupliGroupRecurse(CValue* obj, int level)
00648 {
00649         KX_GameObject* groupobj = (KX_GameObject*) obj;
00650         KX_GameObject* replica;
00651         KX_GameObject* gameobj;
00652         Object* blgroupobj = groupobj->GetBlenderObject();
00653         Group* group;
00654         GroupObject *go;
00655         vector<KX_GameObject*> duplilist;
00656 
00657         if (!groupobj->GetSGNode() ||
00658                 !groupobj->IsDupliGroup() ||
00659                 level>MAX_DUPLI_RECUR)
00660                 return;
00661 
00662         // we will add one group at a time
00663         m_logicHierarchicalGameObjects.clear();
00664         m_map_gameobject_to_replica.clear();
00665         m_ueberExecutionPriority++;
00666         // for groups will do something special: 
00667         // we will force the creation of objects to those in the group only
00668         // Again, this is match what Blender is doing (it doesn't care of parent relationship)
00669         m_groupGameObjects.clear();
00670 
00671         group = blgroupobj->dup_group;
00672         for(go=(GroupObject*)group->gobject.first; go; go=(GroupObject*)go->next) 
00673         {
00674                 Object* blenderobj = go->ob;
00675                 if (blgroupobj == blenderobj)
00676                         // this check is also in group_duplilist()
00677                         continue;
00678 
00679                 gameobj = (KX_GameObject*)m_logicmgr->FindGameObjByBlendObj(blenderobj);
00680                 if (gameobj == NULL) 
00681                 {
00682                         // this object has not been converted!!!
00683                         // Should not happen as dupli group are created automatically 
00684                         continue;
00685                 }
00686 
00687                 gameobj->SetBlenderGroupObject(blgroupobj);
00688 
00689                 if ((blenderobj->lay & group->layer)==0)
00690                 {
00691                         // object is not visible in the 3D view, will not be instantiated
00692                         continue;
00693                 }
00694                 m_groupGameObjects.insert(gameobj);
00695         }
00696 
00697         set<CValue*>::iterator oit;
00698         for (oit=m_groupGameObjects.begin(); oit != m_groupGameObjects.end(); oit++)
00699         {
00700                 gameobj = (KX_GameObject*)(*oit);
00701 
00702                 KX_GameObject *parent = gameobj->GetParent();
00703                 if (parent != NULL)
00704                 {
00705                         parent->Release(); // GetParent() increased the refcount
00706 
00707                         // this object is not a top parent. Either it is the child of another
00708                         // object in the group and it will be added automatically when the parent
00709                         // is added. Or it is the child of an object outside the group and the group
00710                         // is inconsistent, skip it anyway
00711                         continue;
00712                 }
00713                 replica = (KX_GameObject*) AddNodeReplicaObject(NULL,gameobj);
00714                 // add to 'rootparent' list (this is the list of top hierarchy objects, updated each frame)
00715                 m_parentlist->Add(replica->AddRef());
00716 
00717                 // recurse replication into children nodes
00718                 NodeList& children = gameobj->GetSGNode()->GetSGChildren();
00719 
00720                 replica->GetSGNode()->ClearSGChildren();
00721                 for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
00722                 {
00723                         SG_Node* orgnode = (*childit);
00724                         SG_Node* childreplicanode = orgnode->GetSGReplica();
00725                         if (childreplicanode)
00726                                 replica->GetSGNode()->AddChild(childreplicanode);
00727                 }
00728                 // don't replicate logic now: we assume that the objects in the group can have
00729                 // logic relationship, even outside parent relationship
00730                 // In order to match 3D view, the position of groupobj is used as a 
00731                 // transformation matrix instead of the new position. This means that 
00732                 // the group reference point is 0,0,0
00733 
00734                 // get the rootnode's scale
00735                 MT_Vector3 newscale = groupobj->NodeGetWorldScaling();
00736                 // set the replica's relative scale with the rootnode's scale
00737                 replica->NodeSetRelativeScale(newscale);
00738 
00739                 MT_Point3 offset(group->dupli_ofs);
00740                 MT_Point3 newpos = groupobj->NodeGetWorldPosition() + 
00741                         newscale*(groupobj->NodeGetWorldOrientation() * (gameobj->NodeGetWorldPosition()-offset));
00742                 replica->NodeSetLocalPosition(newpos);
00743                 // set the orientation after position for softbody!
00744                 MT_Matrix3x3 newori = groupobj->NodeGetWorldOrientation() * gameobj->NodeGetWorldOrientation();
00745                 replica->NodeSetLocalOrientation(newori);
00746                 // update scenegraph for entire tree of children
00747                 replica->GetSGNode()->UpdateWorldData(0);
00748                 replica->GetSGNode()->SetBBox(gameobj->GetSGNode()->BBox());
00749                 replica->GetSGNode()->SetRadius(gameobj->GetSGNode()->Radius());
00750                 // we can now add the graphic controller to the physic engine
00751                 replica->ActivateGraphicController(true);
00752 
00753                 // done with replica
00754                 replica->Release();
00755         }
00756 
00757         // the logic must be replicated first because we need
00758         // the new logic bricks before relinking
00759         vector<KX_GameObject*>::iterator git;
00760         for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git)
00761         {
00762                 (*git)->ReParentLogic();
00763         }
00764         
00765         //      relink any pointers as necessary, sort of a temporary solution
00766         for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git)
00767         {
00768                 // this will also relink the actuator to objects within the hierarchy
00769                 (*git)->Relink(&m_map_gameobject_to_replica);
00770                 // add the object in the layer of the parent
00771                 (*git)->SetLayer(groupobj->GetLayer());
00772                 // If the object was a light, we need to update it's RAS_LightObject as well
00773                 if ((*git)->GetGameObjectType()==SCA_IObject::OBJ_LIGHT)
00774                 {
00775                         KX_LightObject* lightobj = static_cast<KX_LightObject*>(*git);
00776                         lightobj->GetLightData()->m_layer = groupobj->GetLayer();
00777                 }
00778         }
00779 
00780         // replicate crosslinks etc. between logic bricks
00781         for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git)
00782         {
00783                 ReplicateLogic((*git));
00784         }
00785         
00786         // now look if object in the hierarchy have dupli group and recurse
00787         for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git)
00788         {
00789                 if ((*git) != groupobj && (*git)->IsDupliGroup())
00790                         // can't instantiate group immediately as it destroys m_logicHierarchicalGameObjects
00791                         duplilist.push_back((*git));
00792         }
00793 
00794         for (git = duplilist.begin(); !(git == duplilist.end()); ++git)
00795         {
00796                 DupliGroupRecurse((*git), level+1);
00797         }
00798 }
00799 
00800 
00801 SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject,
00802                                                                                 class CValue* parentobject,
00803                                                                                 int lifespan)
00804 {
00805 
00806         m_logicHierarchicalGameObjects.clear();
00807         m_map_gameobject_to_replica.clear();
00808         m_groupGameObjects.clear();
00809 
00810         // todo: place a timebomb in the object, for temporarily objects :)
00811         // lifespan of zero means 'this object lives forever'
00812         KX_GameObject* originalobj = (KX_GameObject*) originalobject;
00813         KX_GameObject* parentobj = (KX_GameObject*) parentobject;
00814 
00815         m_ueberExecutionPriority++;
00816 
00817         // lets create a replica
00818         KX_GameObject* replica = (KX_GameObject*) AddNodeReplicaObject(NULL,originalobj);
00819 
00820         if (lifespan > 0)
00821         {
00822                 // add a timebomb to this object
00823                 // for now, convert between so called frames and realtime
00824                 m_tempObjectList->Add(replica->AddRef());
00825                 // this convert the life from frames to sort-of seconds, hard coded 0.02 that assumes we have 50 frames per second
00826                 // if you change this value, make sure you change it in KX_GameObject::pyattr_get_life property too
00827                 CValue *fval = new CFloatValue(lifespan*0.02);
00828                 replica->SetProperty("::timebomb",fval);
00829                 fval->Release();
00830         }
00831 
00832         // add to 'rootparent' list (this is the list of top hierarchy objects, updated each frame)
00833         m_parentlist->Add(replica->AddRef());
00834 
00835         // recurse replication into children nodes
00836 
00837         NodeList& children = originalobj->GetSGNode()->GetSGChildren();
00838 
00839         replica->GetSGNode()->ClearSGChildren();
00840         for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
00841         {
00842                 SG_Node* orgnode = (*childit);
00843                 SG_Node* childreplicanode = orgnode->GetSGReplica();
00844                 if (childreplicanode)
00845                         replica->GetSGNode()->AddChild(childreplicanode);
00846         }
00847 
00848         // At this stage all the objects in the hierarchy have been duplicated,
00849         // we can update the scenegraph, we need it for the duplication of logic
00850         MT_Point3 newpos = ((KX_GameObject*) parentobject)->NodeGetWorldPosition();
00851         replica->NodeSetLocalPosition(newpos);
00852 
00853         MT_Matrix3x3 newori = ((KX_GameObject*) parentobject)->NodeGetWorldOrientation();
00854         replica->NodeSetLocalOrientation(newori);
00855         
00856         // get the rootnode's scale
00857         MT_Vector3 newscale = parentobj->GetSGNode()->GetRootSGParent()->GetLocalScale();
00858 
00859         // set the replica's relative scale with the rootnode's scale
00860         replica->NodeSetRelativeScale(newscale);
00861 
00862         replica->GetSGNode()->UpdateWorldData(0);
00863         replica->GetSGNode()->SetBBox(originalobj->GetSGNode()->BBox());
00864         replica->GetSGNode()->SetRadius(originalobj->GetSGNode()->Radius());
00865         // the size is correct, we can add the graphic controller to the physic engine
00866         replica->ActivateGraphicController(true);
00867 
00868         // now replicate logic
00869         vector<KX_GameObject*>::iterator git;
00870         for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git)
00871         {
00872                 (*git)->ReParentLogic();
00873         }
00874         
00875         //      relink any pointers as necessary, sort of a temporary solution
00876         for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git)
00877         {
00878                 // this will also relink the actuators in the hierarchy
00879                 (*git)->Relink(&m_map_gameobject_to_replica);
00880                 // add the object in the layer of the parent
00881                 (*git)->SetLayer(parentobj->GetLayer());
00882                 // If the object was a light, we need to update it's RAS_LightObject as well
00883                 if ((*git)->GetGameObjectType()==SCA_IObject::OBJ_LIGHT)
00884                 {
00885                         KX_LightObject* lightobj = static_cast<KX_LightObject*>(*git);
00886                         lightobj->GetLightData()->m_layer = parentobj->GetLayer();
00887                 }
00888         }
00889 
00890         // replicate crosslinks etc. between logic bricks
00891         for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git)
00892         {
00893                 ReplicateLogic((*git));
00894         }
00895         
00896         // check if there are objects with dupligroup in the hierarchy
00897         vector<KX_GameObject*> duplilist;
00898         for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git)
00899         {
00900                 if ((*git)->IsDupliGroup())
00901                 {
00902                         // separate list as m_logicHierarchicalGameObjects is also used by DupliGroupRecurse()
00903                         duplilist.push_back(*git);
00904                 }
00905         }
00906         for (git = duplilist.begin();!(git==duplilist.end());++git)
00907         {
00908                 DupliGroupRecurse(*git, 0);
00909         }
00910         //      don't release replica here because we are returning it, not done with it...
00911         return replica;
00912 }
00913 
00914 
00915 
00916 void KX_Scene::RemoveObject(class CValue* gameobj)
00917 {
00918         KX_GameObject* newobj = (KX_GameObject*) gameobj;
00919 
00920         // disconnect child from parent
00921         SG_Node* node = newobj->GetSGNode();
00922 
00923         if (node)
00924         {
00925                 node->DisconnectFromParent();
00926 
00927                 // recursively destruct
00928                 node->Destruct();
00929         }
00930         //no need to do that: the object is destroyed and memory released 
00931         //newobj->SetSGNode(0);
00932 }
00933 
00934 void KX_Scene::DelayedRemoveObject(class CValue* gameobj)
00935 {
00936         //KX_GameObject* newobj = (KX_GameObject*) gameobj;
00937         if (!m_euthanasyobjects->SearchValue(gameobj))
00938         {
00939                 m_euthanasyobjects->Add(gameobj->AddRef());
00940         } 
00941 }
00942 
00943 
00944 
00945 int KX_Scene::NewRemoveObject(class CValue* gameobj)
00946 {
00947         int ret;
00948         KX_GameObject* newobj = (KX_GameObject*) gameobj;
00949 
00950         /* Invalidate the python reference, since the object may exist in script lists
00951          * its possible that it wont be automatically invalidated, so do it manually here,
00952          * 
00953          * if for some reason the object is added back into the scene python can always get a new Proxy
00954          */
00955         newobj->InvalidateProxy();
00956 
00957         // keep the blender->game object association up to date
00958         // note that all the replicas of an object will have the same
00959         // blender object, that's why we need to check the game object
00960         // as only the deletion of the original object must be recorded
00961         m_logicmgr->UnregisterGameObj(newobj->GetBlenderObject(), gameobj);
00962 
00963         //todo: look at this
00964         //GetPhysicsEnvironment()->RemovePhysicsController(gameobj->getPhysicsController());
00965 
00966         // remove all sensors/controllers/actuators from logicsystem...
00967         
00968         SCA_SensorList& sensors = newobj->GetSensors();
00969         for (SCA_SensorList::iterator its = sensors.begin();
00970                  !(its==sensors.end());its++)
00971         {
00972                 m_logicmgr->RemoveSensor(*its);
00973         }
00974 
00975         SCA_ControllerList& controllers = newobj->GetControllers();
00976         for (SCA_ControllerList::iterator itc = controllers.begin();
00977                  !(itc==controllers.end());itc++)
00978         {
00979                 m_logicmgr->RemoveController(*itc);
00980         }
00981 
00982         SCA_ActuatorList& actuators = newobj->GetActuators();
00983         for (SCA_ActuatorList::iterator ita = actuators.begin();
00984                  !(ita==actuators.end());ita++)
00985         {
00986                 m_logicmgr->RemoveActuator(*ita);
00987         }
00988         // the sensors/controllers/actuators must also be released, this is done in ~SCA_IObject
00989 
00990         // now remove the timer properties from the time manager
00991         int numprops = newobj->GetPropertyCount();
00992 
00993         for (int i = 0; i < numprops; i++)
00994         {
00995                 CValue* propval = newobj->GetProperty(i);
00996                 if (propval->GetProperty("timer"))
00997                 {
00998                         m_timemgr->RemoveTimeProperty(propval);
00999                 }
01000         }
01001         
01002         newobj->RemoveMeshes();
01003         ret = 1;
01004         if (newobj->GetGameObjectType()==SCA_IObject::OBJ_LIGHT && m_lightlist->RemoveValue(newobj))
01005                 ret = newobj->Release();
01006         if (m_objectlist->RemoveValue(newobj))
01007                 ret = newobj->Release();
01008         if (m_tempObjectList->RemoveValue(newobj))
01009                 ret = newobj->Release();
01010         if (m_parentlist->RemoveValue(newobj))
01011                 ret = newobj->Release();
01012         if (m_inactivelist->RemoveValue(newobj))
01013                 ret = newobj->Release();
01014         if (m_euthanasyobjects->RemoveValue(newobj))
01015                 ret = newobj->Release();
01016                 
01017         if (newobj == m_active_camera)
01018         {
01019                 //no AddRef done on m_active_camera so no Release
01020                 //m_active_camera->Release();
01021                 m_active_camera = NULL;
01022         }
01023 
01024         // in case this is a camera
01025         m_cameras.remove((KX_Camera*)newobj);
01026 
01027         // in case this is a font
01028         m_fonts.remove((KX_FontObject*)newobj);
01029 
01030         /* currently does nothing, keep incase we need to Unregister something */
01031 #if 0
01032         if (m_sceneConverter)
01033                 m_sceneConverter->UnregisterGameObject(newobj);
01034 #endif
01035         
01036         // return value will be 0 if the object is actually deleted (all reference gone)
01037         
01038         return ret;
01039 }
01040 
01041 
01042 
01043 void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj, bool use_gfx, bool use_phys)
01044 {
01045         KX_GameObject* gameobj = static_cast<KX_GameObject*>(obj);
01046         RAS_MeshObject* mesh = static_cast<RAS_MeshObject*>(meshobj);
01047 
01048         if(!gameobj) {
01049                 std::cout << "KX_Scene::ReplaceMesh Warning: invalid object, doing nothing" << std::endl;
01050                 return;
01051         }
01052 
01053         if(use_gfx && mesh != NULL)
01054         {               
01055         gameobj->RemoveMeshes();
01056         gameobj->AddMesh(mesh);
01057         
01058         if (gameobj->m_isDeformable)
01059         {
01060                 BL_DeformableGameObject* newobj = static_cast<BL_DeformableGameObject*>( gameobj );
01061                 
01062                 if (newobj->GetDeformer())
01063                 {
01064                         delete newobj->GetDeformer();
01065                         newobj->SetDeformer(NULL);
01066                 }
01067 
01068                 if (mesh->GetMesh()) 
01069                 {
01070                         // we must create a new deformer but which one?
01071                         KX_GameObject* parentobj = newobj->GetParent();
01072                         // this always return the original game object (also for replicate)
01073                         Object* blendobj = newobj->GetBlenderObject();
01074                         // object that owns the new mesh
01075                         Object* oldblendobj = static_cast<struct Object*>(m_logicmgr->FindBlendObjByGameMeshName(mesh->GetName()));
01076                         Mesh* blendmesh = mesh->GetMesh();
01077 
01078                         bool bHasModifier = BL_ModifierDeformer::HasCompatibleDeformer(blendobj);
01079                         bool bHasShapeKey = blendmesh->key != NULL && blendmesh->key->type==KEY_RELATIVE;
01080                         bool bHasDvert = blendmesh->dvert != NULL;
01081                         bool bHasArmature = 
01082                                 BL_ModifierDeformer::HasArmatureDeformer(blendobj) &&
01083                                 parentobj &&                                                            // current parent is armature
01084                                 parentobj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE &&
01085                                 oldblendobj &&                                                          // needed for mesh deform
01086                                 blendobj->parent &&                                                     // original object had armature (not sure this test is needed)
01087                                 blendobj->parent->type == OB_ARMATURE &&
01088                                 blendmesh->dvert!=NULL;                                         // mesh has vertex group
01089 #ifdef USE_BULLET
01090                         bool bHasSoftBody = (!parentobj && (blendobj->gameflag & OB_SOFT_BODY));
01091 #endif
01092                         bool releaseParent = true;
01093 
01094                         
01095                         if (oldblendobj==NULL) {
01096                                 if (bHasModifier || bHasShapeKey || bHasDvert || bHasArmature) {
01097                                         std::cout << "warning: ReplaceMesh() new mesh is not used in an object from the current scene, you will get incorrect behavior" << std::endl;
01098                                         bHasShapeKey= bHasDvert= bHasArmature=bHasModifier= false;
01099                                 }
01100                         }
01101                         
01102                         if (bHasModifier)
01103                         {
01104                                 BL_ModifierDeformer* modifierDeformer;
01105                                 if (bHasShapeKey || bHasArmature)
01106                                 {
01107                                         modifierDeformer = new BL_ModifierDeformer(
01108                                                 newobj,
01109                                                 m_blenderScene,
01110                                                 oldblendobj, blendobj,
01111                                                 mesh,
01112                                                 true,
01113                                                 static_cast<BL_ArmatureObject*>( parentobj )
01114                                         );
01115                                         releaseParent= false;
01116                                         modifierDeformer->LoadShapeDrivers(blendobj->parent);
01117                                 }
01118                                 else
01119                                 {
01120                                         modifierDeformer = new BL_ModifierDeformer(
01121                                                 newobj,
01122                                                 m_blenderScene,
01123                                                 oldblendobj, blendobj,
01124                                                 mesh,
01125                                                 false,
01126                                                 NULL
01127                                         );
01128                                 }
01129                                 newobj->SetDeformer(modifierDeformer);
01130                         } 
01131                         else    if (bHasShapeKey)
01132                         {
01133                                 BL_ShapeDeformer* shapeDeformer;
01134                                 if (bHasArmature) 
01135                                 {
01136                                         shapeDeformer = new BL_ShapeDeformer(
01137                                                 newobj,
01138                                                 oldblendobj, blendobj,
01139                                                 mesh,
01140                                                 true,
01141                                                 true,
01142                                                 static_cast<BL_ArmatureObject*>( parentobj )
01143                                         );
01144                                         releaseParent= false;
01145                                         shapeDeformer->LoadShapeDrivers(blendobj->parent);
01146                                 }
01147                                 else
01148                                 {
01149                                         shapeDeformer = new BL_ShapeDeformer(
01150                                                 newobj,
01151                                                 oldblendobj, blendobj,
01152                                                 mesh,
01153                                                 false,
01154                                                 true,
01155                                                 NULL
01156                                         );
01157                                 }
01158                                 newobj->SetDeformer( shapeDeformer);
01159                         }
01160                         else if (bHasArmature) 
01161                         {
01162                                 BL_SkinDeformer* skinDeformer = new BL_SkinDeformer(
01163                                         newobj,
01164                                         oldblendobj, blendobj,
01165                                         mesh,
01166                                         true,
01167                                         true,
01168                                         static_cast<BL_ArmatureObject*>( parentobj )
01169                                 );
01170                                 releaseParent= false;
01171                                 newobj->SetDeformer(skinDeformer);
01172                         }
01173                         else if (bHasDvert)
01174                         {
01175                                 BL_MeshDeformer* meshdeformer = new BL_MeshDeformer(
01176                                         newobj, oldblendobj, mesh
01177                                 );
01178                                 newobj->SetDeformer(meshdeformer);
01179                         }
01180 #ifdef USE_BULLET
01181                         else if (bHasSoftBody)
01182                         {
01183                                 KX_SoftBodyDeformer *softdeformer = new KX_SoftBodyDeformer(mesh, newobj);
01184                                 newobj->SetDeformer(softdeformer);
01185                         }
01186 #endif
01187 
01188                         // release parent reference if its not being used 
01189                         if( releaseParent && parentobj)
01190                                 parentobj->Release();
01191                 }
01192         }
01193 
01194         gameobj->AddMeshUser();
01195         }
01196 
01197 #ifdef USE_BULLET
01198         if(use_phys) { /* update the new assigned mesh with the physics mesh */
01199                 KX_ReInstanceBulletShapeFromMesh(gameobj, NULL, use_gfx?NULL:mesh);
01200         }
01201 #endif
01202 }
01203 
01204 /* Font Object routines */
01205 void KX_Scene::AddFont(KX_FontObject* font)
01206 {
01207         if (!FindFont(font))
01208                 m_fonts.push_back(font);
01209 }
01210 
01211 KX_FontObject* KX_Scene::FindFont(KX_FontObject* font)
01212 {
01213         list<KX_FontObject*>::iterator it = m_fonts.begin();
01214 
01215         while ( (it != m_fonts.end()) 
01216                         && ((*it) != font) ) {
01217           ++it;
01218         }
01219 
01220         return ((it == m_fonts.end()) ? NULL : (*it));
01221 }
01222 
01223 
01224 /* Camera Object routines */
01225 KX_Camera* KX_Scene::FindCamera(KX_Camera* cam)
01226 {
01227         list<KX_Camera*>::iterator it = m_cameras.begin();
01228 
01229         while ( (it != m_cameras.end()) 
01230                         && ((*it) != cam) ) {
01231           it++;
01232         }
01233 
01234         return ((it == m_cameras.end()) ? NULL : (*it));
01235 }
01236 
01237 
01238 KX_Camera* KX_Scene::FindCamera(STR_String& name)
01239 {
01240         list<KX_Camera*>::iterator it = m_cameras.begin();
01241 
01242         while ( (it != m_cameras.end()) 
01243                         && ((*it)->GetName() != name) ) {
01244           it++;
01245         }
01246 
01247         return ((it == m_cameras.end()) ? NULL : (*it));
01248 }
01249 
01250 void KX_Scene::AddCamera(KX_Camera* cam)
01251 {
01252         if (!FindCamera(cam))
01253                 m_cameras.push_back(cam);
01254 }
01255 
01256 
01257 KX_Camera* KX_Scene::GetActiveCamera()
01258 {       
01259         // NULL if not defined
01260         return m_active_camera;
01261 }
01262 
01263 
01264 void KX_Scene::SetActiveCamera(KX_Camera* cam)
01265 {
01266         // only set if the cam is in the active list? Or add it otherwise?
01267         if (!FindCamera(cam)){
01268                 AddCamera(cam);
01269                 if (cam) std::cout << "Added cam " << cam->GetName() << std::endl;
01270         } 
01271 
01272         m_active_camera = cam;
01273 }
01274 
01275 void KX_Scene::SetCameraOnTop(KX_Camera* cam)
01276 {
01277         if (!FindCamera(cam)){
01278                 // adding is always done at the back, so that's all that needs to be done
01279                 AddCamera(cam);
01280                 if (cam) std::cout << "Added cam " << cam->GetName() << std::endl;
01281         } else {
01282                 m_cameras.remove(cam);
01283                 m_cameras.push_back(cam);
01284         }
01285 }
01286 
01287 
01288 void KX_Scene::UpdateMeshTransformations()
01289 {
01290         // do this incrementally in the future
01291         for (int i = 0; i < m_objectlist->GetCount(); i++)
01292         {
01293                 KX_GameObject* gameobj = (KX_GameObject*)m_objectlist->GetValue(i);
01294                 gameobj->GetOpenGLMatrix();
01295         }
01296 }
01297 
01298 void KX_Scene::MarkVisible(SG_Tree *node, RAS_IRasterizer* rasty, KX_Camera* cam, int layer)
01299 {
01300         int intersect = KX_Camera::INTERSECT;
01301         KX_GameObject *gameobj = node->Client()?(KX_GameObject*) node->Client()->GetSGClientObject():NULL;
01302         bool visible = (gameobj && gameobj->GetVisible() && (!layer || (gameobj->GetLayer() & layer)));
01303         bool dotest = visible || node->Left() || node->Right();
01304 
01305         /* If the camera is inside the box, assume intersect. */
01306         if (dotest && !node->inside( cam->NodeGetWorldPosition()))
01307         {
01308                 MT_Scalar radius = node->Radius();
01309                 MT_Point3 center = node->Center();
01310                 
01311                 intersect =  cam->SphereInsideFrustum(center, radius); 
01312                 
01313                 if (intersect == KX_Camera::INTERSECT)
01314                 {
01315                         MT_Point3 box[8];
01316                         node->get(box);
01317                         intersect = cam->BoxInsideFrustum(box);
01318                 }
01319         }
01320 
01321         switch (intersect)
01322         {
01323                 case KX_Camera::OUTSIDE:
01324                         MarkSubTreeVisible(node, rasty, false, cam);
01325                         break;
01326                 case KX_Camera::INTERSECT:
01327                         if (gameobj)
01328                                 MarkVisible(rasty, gameobj, cam, layer);
01329                         if (node->Left())
01330                                 MarkVisible(node->Left(), rasty, cam, layer);
01331                         if (node->Right())
01332                                 MarkVisible(node->Right(), rasty, cam, layer);
01333                         break;
01334                 case KX_Camera::INSIDE:
01335                         MarkSubTreeVisible(node, rasty, true, cam, layer);
01336                         break;
01337         }
01338 }
01339 
01340 void KX_Scene::MarkSubTreeVisible(SG_Tree *node, RAS_IRasterizer* rasty, bool visible, KX_Camera* cam, int layer)
01341 {
01342         if (node->Client())
01343         {
01344                 KX_GameObject *gameobj = (KX_GameObject*) node->Client()->GetSGClientObject();
01345                 if (gameobj->GetVisible())
01346                 {
01347                         if (visible)
01348                         {
01349                                 int nummeshes = gameobj->GetMeshCount();
01350                                 
01351                                 // this adds the vertices to the display list
01352                                 for (int m=0;m<nummeshes;m++)
01353                                         (gameobj->GetMesh(m))->SchedulePolygons(rasty->GetDrawingMode());
01354                         }
01355 
01356                         gameobj->SetCulled(!visible);
01357                         gameobj->UpdateBuckets(false);
01358                 }
01359         }
01360         if (node->Left())
01361                 MarkSubTreeVisible(node->Left(), rasty, visible, cam, layer);
01362         if (node->Right())
01363                 MarkSubTreeVisible(node->Right(), rasty, visible, cam, layer);
01364 }
01365 
01366 void KX_Scene::MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj,KX_Camera*  cam,int layer)
01367 {
01368         // User (Python/Actuator) has forced object invisible...
01369         if (!gameobj->GetSGNode() || !gameobj->GetVisible())
01370                 return;
01371         
01372         // Shadow lamp layers
01373         if(layer && !(gameobj->GetLayer() & layer)) {
01374                 gameobj->SetCulled(true);
01375                 gameobj->UpdateBuckets(false);
01376                 return;
01377         }
01378 
01379         // If Frustum culling is off, the object is always visible.
01380         bool vis = !cam->GetFrustumCulling();
01381         
01382         // If the camera is inside this node, then the object is visible.
01383         if (!vis)
01384         {
01385                 vis = gameobj->GetSGNode()->inside( cam->GetCameraLocation() );
01386         }
01387                 
01388         // Test the object's bound sphere against the view frustum.
01389         if (!vis)
01390         {
01391                 MT_Vector3 scale = gameobj->GetSGNode()->GetWorldScaling();
01392                 MT_Scalar radius = fabs(scale[scale.closestAxis()] * gameobj->GetSGNode()->Radius());
01393                 switch (cam->SphereInsideFrustum(gameobj->NodeGetWorldPosition(), radius))
01394                 {
01395                         case KX_Camera::INSIDE:
01396                                 vis = true;
01397                                 break;
01398                         case KX_Camera::OUTSIDE:
01399                                 vis = false;
01400                                 break;
01401                         case KX_Camera::INTERSECT:
01402                                 // Test the object's bound box against the view frustum.
01403                                 MT_Point3 box[8];
01404                                 gameobj->GetSGNode()->getBBox(box); 
01405                                 vis = cam->BoxInsideFrustum(box) != KX_Camera::OUTSIDE;
01406                                 break;
01407                 }
01408         }
01409         
01410         if (vis)
01411         {
01412                 int nummeshes = gameobj->GetMeshCount();
01413                 
01414                 for (int m=0;m<nummeshes;m++)
01415                 {
01416                         // this adds the vertices to the display list
01417                         (gameobj->GetMesh(m))->SchedulePolygons(rasty->GetDrawingMode());
01418                 }
01419                 // Visibility/ non-visibility are marked
01420                 // elsewhere now.
01421                 gameobj->SetCulled(false);
01422                 gameobj->UpdateBuckets(false);
01423         } else {
01424                 gameobj->SetCulled(true);
01425                 gameobj->UpdateBuckets(false);
01426         }
01427 }
01428 
01429 void KX_Scene::PhysicsCullingCallback(KX_ClientObjectInfo* objectInfo, void* cullingInfo)
01430 {
01431         KX_GameObject* gameobj = objectInfo->m_gameobject;
01432         if (!gameobj->GetVisible())
01433                 // ideally, invisible objects should be removed from the culling tree temporarily
01434                 return;
01435         if(((CullingInfo*)cullingInfo)->m_layer && !(gameobj->GetLayer() & ((CullingInfo*)cullingInfo)->m_layer))
01436                 // used for shadow: object is not in shadow layer
01437                 return;
01438 
01439         // make object visible
01440         gameobj->SetCulled(false);
01441         gameobj->UpdateBuckets(false);
01442 }
01443 
01444 void KX_Scene::CalculateVisibleMeshes(RAS_IRasterizer* rasty,KX_Camera* cam, int layer)
01445 {
01446         bool dbvt_culling = false;
01447         if (m_dbvt_culling) 
01448         {
01449                 // test culling through Bullet
01450                 PHY__Vector4 planes[6];
01451                 // get the clip planes
01452                 MT_Vector4* cplanes = cam->GetNormalizedClipPlanes();
01453                 // and convert
01454                 planes[0].setValue(cplanes[4].getValue());      // near
01455                 planes[1].setValue(cplanes[5].getValue());      // far
01456                 planes[2].setValue(cplanes[0].getValue());      // left
01457                 planes[3].setValue(cplanes[1].getValue());      // right
01458                 planes[4].setValue(cplanes[2].getValue());      // top
01459                 planes[5].setValue(cplanes[3].getValue());      // bottom
01460                 CullingInfo info(layer);
01461                 dbvt_culling = m_physicsEnvironment->cullingTest(PhysicsCullingCallback,&info,planes,5,m_dbvt_occlusion_res);
01462         }
01463         if (!dbvt_culling) {
01464                 // the physics engine couldn't help us, do it the hard way
01465                 for (int i = 0; i < m_objectlist->GetCount(); i++)
01466                 {
01467                         MarkVisible(rasty, static_cast<KX_GameObject*>(m_objectlist->GetValue(i)), cam, layer);
01468                 }
01469         }
01470 }
01471 
01472 // logic stuff
01473 void KX_Scene::LogicBeginFrame(double curtime)
01474 {
01475         // have a look at temp objects ...
01476         int lastobj = m_tempObjectList->GetCount() - 1;
01477         
01478         for (int i = lastobj; i >= 0; i--)
01479         {
01480                 CValue* objval = m_tempObjectList->GetValue(i);
01481                 CFloatValue* propval = (CFloatValue*) objval->GetProperty("::timebomb");
01482                 
01483                 if (propval)
01484                 {
01485                         float timeleft = propval->GetNumber() - 1.0/KX_KetsjiEngine::GetTicRate();
01486                         
01487                         if (timeleft > 0)
01488                         {
01489                                 propval->SetFloat(timeleft);
01490                         }
01491                         else
01492                         {
01493                                 DelayedRemoveObject(objval);
01494                                 // remove obj
01495                         }
01496                 }
01497                 else
01498                 {
01499                         // all object is the tempObjectList should have a clock
01500                 }
01501         }
01502         m_logicmgr->BeginFrame(curtime, 1.0/KX_KetsjiEngine::GetTicRate());
01503 }
01504 
01505 
01506 
01507 void KX_Scene::LogicUpdateFrame(double curtime, bool frame)
01508 {
01509         m_logicmgr->UpdateFrame(curtime, frame);
01510 }
01511 
01512 
01513 
01514 void KX_Scene::LogicEndFrame()
01515 {
01516         m_logicmgr->EndFrame();
01517         int numobj;
01518 
01519         KX_GameObject* obj;
01520 
01521         while ((numobj = m_euthanasyobjects->GetCount()) > 0)
01522         {
01523                 // remove the object from this list to make sure we will not hit it again
01524                 obj = (KX_GameObject*)m_euthanasyobjects->GetValue(numobj-1);
01525                 m_euthanasyobjects->Remove(numobj-1);
01526                 obj->Release();
01527                 RemoveObject(obj);
01528         }
01529 }
01530 
01531 
01532 
01536 void KX_Scene::UpdateParents(double curtime)
01537 {
01538         // we use the SG dynamic list
01539         SG_Node* node;
01540 
01541         while ((node = SG_Node::GetNextScheduled(m_sghead)) != NULL)
01542         {
01543                 node->UpdateWorldData(curtime);
01544         }
01545 
01546         //for (int i=0; i<GetRootParentList()->GetCount(); i++)
01547         //{
01548         //      KX_GameObject* parentobj = (KX_GameObject*)GetRootParentList()->GetValue(i);
01549         //      parentobj->NodeUpdateGS(curtime);
01550         //}
01551 
01552         // the list must be empty here
01553         assert(m_sghead.Empty());
01554         // some nodes may be ready for reschedule, move them to schedule list for next time
01555         while ((node = SG_Node::GetNextRescheduled(m_sghead)) != NULL)
01556         {
01557                 node->Schedule(m_sghead);
01558         }
01559 }
01560 
01561 
01562 RAS_MaterialBucket* KX_Scene::FindBucket(class RAS_IPolyMaterial* polymat, bool &bucketCreated)
01563 {
01564         return m_bucketmanager->FindBucket(polymat, bucketCreated);
01565 }
01566 
01567 
01568 
01569 void KX_Scene::RenderBuckets(const MT_Transform & cameratransform,
01570                                                          class RAS_IRasterizer* rasty,
01571                                                          class RAS_IRenderTools* rendertools)
01572 {
01573         m_bucketmanager->Renderbuckets(cameratransform,rasty,rendertools);
01574         KX_BlenderMaterial::EndFrame();
01575 }
01576 
01577 void KX_Scene::UpdateObjectActivity(void) 
01578 {
01579         if (m_activity_culling) {
01580                 /* determine the activity criterium and set objects accordingly */
01581                 int i=0;
01582                 
01583                 MT_Point3 camloc = GetActiveCamera()->NodeGetWorldPosition(); //GetCameraLocation();
01584                 
01585                 for (i=0;i<GetObjectList()->GetCount();i++)
01586                 {
01587                         KX_GameObject* ob = (KX_GameObject*) GetObjectList()->GetValue(i);
01588                         
01589                         if (!ob->GetIgnoreActivityCulling()) {
01590                                 /* Simple test: more than 10 away from the camera, count
01591                                  * Manhattan distance. */
01592                                 MT_Point3 obpos = ob->NodeGetWorldPosition();
01593                                 
01594                                 if ( (fabs(camloc[0] - obpos[0]) > m_activity_box_radius)
01595                                          || (fabs(camloc[1] - obpos[1]) > m_activity_box_radius)
01596                                          || (fabs(camloc[2] - obpos[2]) > m_activity_box_radius) )
01597                                 {                       
01598                                         ob->Suspend();
01599                                 } else {
01600                                         ob->Resume();
01601                                 }
01602                         }
01603                 }               
01604         }
01605 }
01606 
01607 void KX_Scene::SetActivityCullingRadius(float f)
01608 {
01609         if (f < 0.5)
01610                 f = 0.5;
01611         m_activity_box_radius = f;
01612 }
01613         
01614 NG_NetworkDeviceInterface* KX_Scene::GetNetworkDeviceInterface()
01615 {
01616         return m_networkDeviceInterface;
01617 }
01618 
01619 NG_NetworkScene* KX_Scene::GetNetworkScene()
01620 {
01621         return m_networkScene;
01622 }
01623 
01624 void KX_Scene::SetNetworkDeviceInterface(NG_NetworkDeviceInterface* newInterface)
01625 {
01626         m_networkDeviceInterface = newInterface;
01627 }
01628 
01629 void KX_Scene::SetNetworkScene(NG_NetworkScene *newScene)
01630 {
01631         m_networkScene = newScene;
01632 }
01633 
01634 
01635 void    KX_Scene::SetGravity(const MT_Vector3& gravity)
01636 {
01637         GetPhysicsEnvironment()->setGravity(gravity[0],gravity[1],gravity[2]);
01638 }
01639 
01640 void KX_Scene::SetSceneConverter(class KX_BlenderSceneConverter* sceneConverter)
01641 {
01642         m_sceneConverter = sceneConverter;
01643 }
01644 
01645 void KX_Scene::SetPhysicsEnvironment(class PHY_IPhysicsEnvironment* physEnv)
01646 {
01647         m_physicsEnvironment = physEnv;
01648         if(m_physicsEnvironment) {
01649                 KX_TouchEventManager* touchmgr = new KX_TouchEventManager(m_logicmgr, physEnv);
01650                 m_logicmgr->RegisterEventManager(touchmgr);
01651         }
01652 }
01653  
01654 void KX_Scene::setSuspendedTime(double suspendedtime)
01655 {
01656         m_suspendedtime = suspendedtime;
01657 }
01658 double KX_Scene::getSuspendedTime()
01659 {
01660         return m_suspendedtime;
01661 }
01662 void KX_Scene::setSuspendedDelta(double suspendeddelta)
01663 {
01664         m_suspendeddelta = suspendeddelta;
01665 }
01666 double KX_Scene::getSuspendedDelta()
01667 {
01668         return m_suspendeddelta;
01669 }
01670 
01671 #ifdef USE_BULLET
01672 #include "KX_BulletPhysicsController.h"
01673 #endif
01674 
01675 static void MergeScene_LogicBrick(SCA_ILogicBrick* brick, KX_Scene *to)
01676 {
01677         SCA_LogicManager *logicmgr= to->GetLogicManager();
01678 
01679         brick->Replace_IScene(to);
01680         brick->Replace_NetworkScene(to->GetNetworkScene());
01681 
01682         SCA_ISensor *sensor=  dynamic_cast<class SCA_ISensor *>(brick);
01683         if(sensor) {
01684                 sensor->Replace_EventManager(logicmgr);
01685         }
01686 
01687         /* near sensors have physics controllers */
01688 #ifdef USE_BULLET
01689         KX_TouchSensor *touch_sensor = dynamic_cast<class KX_TouchSensor *>(brick);
01690         if(touch_sensor) {
01691                 touch_sensor->GetPhysicsController()->SetPhysicsEnvironment(to->GetPhysicsEnvironment());
01692         }
01693 #endif
01694 }
01695 
01696 #ifdef USE_BULLET
01697 #include "CcdGraphicController.h" // XXX  ctrl->SetPhysicsEnvironment(to->GetPhysicsEnvironment());
01698 #include "CcdPhysicsEnvironment.h" // XXX  ctrl->SetPhysicsEnvironment(to->GetPhysicsEnvironment());
01699 #include "KX_BulletPhysicsController.h"
01700 #endif
01701 
01702 static void MergeScene_GameObject(KX_GameObject* gameobj, KX_Scene *to, KX_Scene *from)
01703 {
01704         {
01705                 SCA_ActuatorList& actuators= gameobj->GetActuators();
01706                 SCA_ActuatorList::iterator ita;
01707 
01708                 for (ita = actuators.begin(); !(ita==actuators.end()); ++ita)
01709                 {
01710                         MergeScene_LogicBrick(*ita, to);
01711                 }
01712         }
01713 
01714 
01715         {
01716                 SCA_SensorList& sensors= gameobj->GetSensors();
01717                 SCA_SensorList::iterator its;
01718 
01719                 for (its = sensors.begin(); !(its==sensors.end()); ++its)
01720                 {
01721                         MergeScene_LogicBrick(*its, to);
01722                 }
01723         }
01724 
01725         {
01726                 SCA_ControllerList& controllers= gameobj->GetControllers();
01727                 SCA_ControllerList::iterator itc;
01728 
01729                 for (itc = controllers.begin(); !(itc==controllers.end()); ++itc)
01730                 {
01731                         SCA_IController *cont= *itc;
01732                         MergeScene_LogicBrick(cont, to);
01733 
01734                         vector<SCA_ISensor*> linkedsensors = cont->GetLinkedSensors();
01735                         vector<SCA_IActuator*> linkedactuators = cont->GetLinkedActuators();
01736 
01737                         for (vector<SCA_IActuator*>::iterator ita = linkedactuators.begin();!(ita==linkedactuators.end());++ita) {
01738                                 MergeScene_LogicBrick(*ita, to);
01739                         }
01740 
01741                         for (vector<SCA_ISensor*>::iterator its = linkedsensors.begin();!(its==linkedsensors.end());++its) {
01742                                 MergeScene_LogicBrick(*its, to);
01743                         }
01744                 }
01745         }
01746 
01747         /* graphics controller */
01748         PHY_IGraphicController *ctrl = gameobj->GetGraphicController();
01749         if(ctrl) {
01750                 /* SHOULD update the m_cullingTree */
01751                 ctrl->SetPhysicsEnvironment(to->GetPhysicsEnvironment());
01752         }
01753 
01754         /* SG_Node can hold a scene reference */
01755         SG_Node *sg= gameobj->GetSGNode();
01756         if(sg) {
01757                 if(sg->GetSGClientInfo() == from) {
01758                         sg->SetSGClientInfo(to);
01759 
01760                         /* Make sure to grab the children too since they might not be tied to a game object */
01761                         NodeList children = sg->GetSGChildren();
01762                         for (int i=0; i<children.size(); i++)
01763                                         children[i]->SetSGClientInfo(to);
01764                 }
01765 #ifdef USE_BULLET
01766                 SGControllerList::iterator contit;
01767                 SGControllerList& controllers = sg->GetSGControllerList();
01768                 for (contit = controllers.begin();contit!=controllers.end();++contit)
01769                 {
01770                         KX_BulletPhysicsController *phys_ctrl= dynamic_cast<KX_BulletPhysicsController *>(*contit);
01771                         if (phys_ctrl)
01772                                 phys_ctrl->SetPhysicsEnvironment(to->GetPhysicsEnvironment());
01773                 }
01774 #endif // USE_BULLET
01775         }
01776         /* If the object is a light, update it's scene */
01777         if (gameobj->GetGameObjectType() == SCA_IObject::OBJ_LIGHT)
01778                 ((KX_LightObject*)gameobj)->UpdateScene(to);
01779 
01780         /* Add the object to the scene's logic manager */
01781         to->GetLogicManager()->RegisterGameObjectName(gameobj->GetName(), gameobj);
01782         to->GetLogicManager()->RegisterGameObj(gameobj->GetBlenderObject(), gameobj);
01783 
01784         for (int i=0; i<gameobj->GetMeshCount(); ++i)
01785                 to->GetLogicManager()->RegisterGameMeshName(gameobj->GetMesh(i)->GetName(), gameobj->GetBlenderObject());
01786 }
01787 
01788 bool KX_Scene::MergeScene(KX_Scene *other)
01789 {
01790 #ifdef USE_BULLET
01791         CcdPhysicsEnvironment *env=                     dynamic_cast<CcdPhysicsEnvironment *>(this->GetPhysicsEnvironment());
01792         CcdPhysicsEnvironment *env_other=       dynamic_cast<CcdPhysicsEnvironment *>(other->GetPhysicsEnvironment());
01793 
01794         if((env==NULL) != (env_other==NULL)) /* TODO - even when both scenes have NONE physics, the other is loaded with bullet enabled, ??? */
01795         {
01796                 printf("KX_Scene::MergeScene: physics scenes type differ, aborting\n");
01797                 printf("\tsource %d, terget %d\n", (int)(env!=NULL), (int)(env_other!=NULL));
01798                 return false;
01799         }
01800 #endif // USE_BULLET
01801 
01802         if(GetSceneConverter() != other->GetSceneConverter()) {
01803                 printf("KX_Scene::MergeScene: converters differ, aborting\n");
01804                 return false;
01805         }
01806 
01807 
01808         GetBucketManager()->MergeBucketManager(other->GetBucketManager(), this);
01809 
01810         /* move materials across, assume they both use the same scene-converters */
01811         GetSceneConverter()->MergeScene(this, other);
01812 
01813         /* active + inactive == all ??? - lets hope so */
01814         for (int i = 0; i < other->GetObjectList()->GetCount(); i++)
01815         {
01816                 KX_GameObject* gameobj = (KX_GameObject*)other->GetObjectList()->GetValue(i);
01817                 MergeScene_GameObject(gameobj, this, other);
01818 
01819                 gameobj->UpdateBuckets(false); /* only for active objects */
01820         }
01821 
01822         for (int i = 0; i < other->GetInactiveList()->GetCount(); i++)
01823         {
01824                 KX_GameObject* gameobj = (KX_GameObject*)other->GetInactiveList()->GetValue(i);
01825                 MergeScene_GameObject(gameobj, this, other);
01826         }
01827 
01828         GetTempObjectList()->MergeList(other->GetTempObjectList());
01829         other->GetTempObjectList()->ReleaseAndRemoveAll();
01830 
01831         GetObjectList()->MergeList(other->GetObjectList());
01832         other->GetObjectList()->ReleaseAndRemoveAll();
01833 
01834         GetInactiveList()->MergeList(other->GetInactiveList());
01835         other->GetInactiveList()->ReleaseAndRemoveAll();
01836 
01837         GetRootParentList()->MergeList(other->GetRootParentList());
01838         other->GetRootParentList()->ReleaseAndRemoveAll();
01839 
01840         GetLightList()->MergeList(other->GetLightList());
01841         other->GetLightList()->ReleaseAndRemoveAll();
01842 
01843 #ifdef USE_BULLET
01844         if(env) /* bullet scene? - dummy scenes dont need touching */
01845                 env->MergeEnvironment(env_other);
01846 #endif
01847         
01848         /* merge logic */
01849         {
01850                 SCA_LogicManager *logicmgr=                     GetLogicManager();
01851                 SCA_LogicManager *logicmgr_other=       other->GetLogicManager();
01852 
01853                 vector<class SCA_EventManager*>evtmgrs= logicmgr->GetEventManagers();
01854                 //vector<class SCA_EventManager*>evtmgrs_others= logicmgr_other->GetEventManagers();
01855 
01856                 //SCA_EventManager *evtmgr;
01857                 SCA_EventManager *evtmgr_other;
01858 
01859                 for(unsigned int i= 0; i < evtmgrs.size(); i++) {
01860                         evtmgr_other= logicmgr_other->FindEventManager(evtmgrs[i]->GetType());
01861 
01862                         if(evtmgr_other) /* unlikely but possible one scene has a joystick and not the other */
01863                                 evtmgr_other->Replace_LogicManager(logicmgr);
01864 
01865                         /* when merging objects sensors are moved across into the new manager, dont need to do this here */
01866                 }
01867 
01868                 /* grab any timer properties from the other scene */
01869                 SCA_TimeEventManager *timemgr=          GetTimeEventManager();
01870                 SCA_TimeEventManager *timemgr_other=    other->GetTimeEventManager();
01871                 vector<CValue*> times = timemgr_other->GetTimeValues();
01872 
01873                 for(unsigned int i= 0; i < times.size(); i++) {
01874                         timemgr->AddTimeProperty(times[i]);
01875                 }
01876                 
01877         }
01878         return true;
01879 }
01880 
01881 void KX_Scene::Update2DFilter(vector<STR_String>& propNames, void* gameObj, RAS_2DFilterManager::RAS_2DFILTER_MODE filtermode, int pass, STR_String& text)
01882 {
01883         m_filtermanager.EnableFilter(propNames, gameObj, filtermode, pass, text);
01884 }
01885 
01886 void KX_Scene::Render2DFilters(RAS_ICanvas* canvas)
01887 {
01888         m_filtermanager.RenderFilters(canvas);
01889 }
01890 
01891 #ifdef WITH_PYTHON
01892 
01893 void KX_Scene::RunDrawingCallbacks(PyObject* cb_list)
01894 {
01895         int len;
01896 
01897         if (cb_list && (len=PyList_GET_SIZE(cb_list)))
01898         {
01899                 PyObject* args= PyTuple_New(0); // save python creating each call
01900                 PyObject* func;
01901                 PyObject* ret;
01902 
01903                 // Iterate the list and run the callbacks
01904                 for (int pos=0; pos < len; pos++)
01905                 {
01906                         func= PyList_GET_ITEM(cb_list, pos);
01907                         ret= PyObject_Call(func, args, NULL);
01908                         if (ret==NULL) {
01909                                 PyErr_Print();
01910                                 PyErr_Clear();
01911                         }
01912                         else {
01913                                 Py_DECREF(ret);
01914                         }
01915                 }
01916 
01917                 Py_DECREF(args);
01918         }
01919 }
01920 
01921 //----------------------------------------------------------------------------
01922 //Python
01923 
01924 PyTypeObject KX_Scene::Type = {
01925         PyVarObject_HEAD_INIT(NULL, 0)
01926         "KX_Scene",
01927         sizeof(PyObjectPlus_Proxy),
01928         0,
01929         py_base_dealloc,
01930         0,
01931         0,
01932         0,
01933         0,
01934         py_base_repr,
01935         0,
01936         &Sequence,
01937         &Mapping,
01938         0,0,0,0,0,0,
01939         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
01940         0,0,0,0,0,0,0,
01941         Methods,
01942         0,
01943         0,
01944         &CValue::Type,
01945         0,0,0,0,0,0,
01946         py_base_new
01947 };
01948 
01949 PyMethodDef KX_Scene::Methods[] = {
01950         KX_PYMETHODTABLE(KX_Scene, addObject),
01951         KX_PYMETHODTABLE(KX_Scene, end),
01952         KX_PYMETHODTABLE(KX_Scene, restart),
01953         KX_PYMETHODTABLE(KX_Scene, replace),
01954         KX_PYMETHODTABLE(KX_Scene, suspend),
01955         KX_PYMETHODTABLE(KX_Scene, resume),
01956         
01957         /* dict style access */
01958         KX_PYMETHODTABLE(KX_Scene, get),
01959         
01960         {NULL,NULL} //Sentinel
01961 };
01962 static PyObject *Map_GetItem(PyObject *self_v, PyObject *item)
01963 {
01964         KX_Scene* self= static_cast<KX_Scene*>BGE_PROXY_REF(self_v);
01965         const char *attr_str= _PyUnicode_AsString(item);
01966         PyObject* pyconvert;
01967         
01968         if (self==NULL) {
01969                 PyErr_SetString(PyExc_SystemError, "val = scene[key]: KX_Scene, "BGE_PROXY_ERROR_MSG);
01970                 return NULL;
01971         }
01972         
01973         if (self->m_attr_dict && (pyconvert=PyDict_GetItem(self->m_attr_dict, item))) {
01974                 
01975                 if (attr_str)
01976                         PyErr_Clear();
01977                 Py_INCREF(pyconvert);
01978                 return pyconvert;
01979         }
01980         else {
01981                 if(attr_str)    PyErr_Format(PyExc_KeyError, "value = scene[key]: KX_Scene, key \"%s\" does not exist", attr_str);
01982                 else                    PyErr_SetString(PyExc_KeyError, "value = scene[key]: KX_Scene, key does not exist");
01983                 return NULL;
01984         }
01985                 
01986 }
01987 
01988 static int Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val)
01989 {
01990         KX_Scene* self= static_cast<KX_Scene*>BGE_PROXY_REF(self_v);
01991         const char *attr_str= _PyUnicode_AsString(key);
01992         if(attr_str==NULL)
01993                 PyErr_Clear();
01994         
01995         if (self==NULL) {
01996                 PyErr_SetString(PyExc_SystemError, "scene[key] = value: KX_Scene, "BGE_PROXY_ERROR_MSG);
01997                 return -1;
01998         }
01999         
02000         if (val==NULL) { /* del ob["key"] */
02001                 int del= 0;
02002                 
02003                 if(self->m_attr_dict)
02004                         del |= (PyDict_DelItem(self->m_attr_dict, key)==0) ? 1:0;
02005                 
02006                 if (del==0) {
02007                         if(attr_str)    PyErr_Format(PyExc_KeyError, "scene[key] = value: KX_Scene, key \"%s\" could not be set", attr_str);
02008                         else                    PyErr_SetString(PyExc_KeyError, "del scene[key]: KX_Scene, key could not be deleted");
02009                         return -1;
02010                 }
02011                 else if (self->m_attr_dict) {
02012                         PyErr_Clear(); /* PyDict_DelItem sets an error when it fails */
02013                 }
02014         }
02015         else { /* ob["key"] = value */
02016                 int set = 0;
02017 
02018                 if (self->m_attr_dict==NULL) /* lazy init */
02019                         self->m_attr_dict= PyDict_New();
02020                 
02021                 
02022                 if(PyDict_SetItem(self->m_attr_dict, key, val)==0)
02023                         set= 1;
02024                 else
02025                         PyErr_SetString(PyExc_KeyError, "scene[key] = value: KX_Scene, key not be added to internal dictionary");
02026         
02027                 if(set==0)
02028                         return -1; /* pythons error value */
02029                 
02030         }
02031         
02032         return 0; /* success */
02033 }
02034 
02035 static int Seq_Contains(PyObject *self_v, PyObject *value)
02036 {
02037         KX_Scene* self= static_cast<KX_Scene*>BGE_PROXY_REF(self_v);
02038         
02039         if (self==NULL) {
02040                 PyErr_SetString(PyExc_SystemError, "val in scene: KX_Scene, "BGE_PROXY_ERROR_MSG);
02041                 return -1;
02042         }
02043         
02044         if (self->m_attr_dict && PyDict_GetItem(self->m_attr_dict, value))
02045                 return 1;
02046         
02047         return 0;
02048 }
02049 
02050 PyMappingMethods KX_Scene::Mapping = {
02051         (lenfunc)NULL                                   ,                       /*inquiry mp_length */
02052         (binaryfunc)Map_GetItem,                /*binaryfunc mp_subscript */
02053         (objobjargproc)Map_SetItem,     /*objobjargproc mp_ass_subscript */
02054 };
02055 
02056 PySequenceMethods KX_Scene::Sequence = {
02057         NULL,           /* Cant set the len otherwise it can evaluate as false */
02058         NULL,           /* sq_concat */
02059         NULL,           /* sq_repeat */
02060         NULL,           /* sq_item */
02061         NULL,           /* sq_slice */
02062         NULL,           /* sq_ass_item */
02063         NULL,           /* sq_ass_slice */
02064         (objobjproc)Seq_Contains,       /* sq_contains */
02065         (binaryfunc) NULL, /* sq_inplace_concat */
02066         (ssizeargfunc) NULL, /* sq_inplace_repeat */
02067 };
02068 
02069 PyObject* KX_Scene::pyattr_get_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
02070 {
02071         KX_Scene* self= static_cast<KX_Scene*>(self_v);
02072         return PyUnicode_FromString(self->GetName().ReadPtr());
02073 }
02074 
02075 PyObject* KX_Scene::pyattr_get_objects(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
02076 {
02077         KX_Scene* self= static_cast<KX_Scene*>(self_v);
02078         return self->GetObjectList()->GetProxy();
02079 }
02080 
02081 PyObject* KX_Scene::pyattr_get_objects_inactive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
02082 {
02083         KX_Scene* self= static_cast<KX_Scene*>(self_v);
02084         return self->GetInactiveList()->GetProxy();
02085 }
02086 
02087 PyObject* KX_Scene::pyattr_get_lights(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
02088 {
02089         KX_Scene* self= static_cast<KX_Scene*>(self_v);
02090         return self->GetLightList()->GetProxy();
02091 }
02092 
02093 PyObject* KX_Scene::pyattr_get_cameras(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
02094 {
02095         /* With refcounts in this case...
02096          * the new CListValue is owned by python, so its possible python holds onto it longer then the BGE
02097          * however this is the same with "scene.objects + []", when you make a copy by adding lists.
02098          */
02099         
02100         KX_Scene* self= static_cast<KX_Scene*>(self_v);
02101         CListValue* clist = new CListValue();
02102         
02103         /* return self->GetCameras()->GetProxy(); */
02104         
02105         list<KX_Camera*>::iterator it = self->GetCameras()->begin();
02106         while (it != self->GetCameras()->end()) {
02107                 clist->Add((*it)->AddRef());
02108                 it++;
02109         }
02110         
02111         return clist->NewProxy(true);
02112 }
02113 
02114 PyObject* KX_Scene::pyattr_get_active_camera(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
02115 {
02116         KX_Scene* self= static_cast<KX_Scene*>(self_v);
02117         return self->GetActiveCamera()->GetProxy();
02118 }
02119 
02120 
02121 int KX_Scene::pyattr_set_active_camera(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
02122 {
02123         KX_Scene* self= static_cast<KX_Scene*>(self_v);
02124         KX_Camera *camOb;
02125         
02126         if (!ConvertPythonToCamera(value, &camOb, false, "scene.active_camera = value: KX_Scene"))
02127                 return PY_SET_ATTR_FAIL;
02128         
02129         self->SetActiveCamera(camOb);
02130         return PY_SET_ATTR_SUCCESS;
02131 }
02132 
02133 PyObject* KX_Scene::pyattr_get_drawing_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
02134 {
02135         KX_Scene* self = static_cast<KX_Scene*>(self_v);
02136 
02137         if(self->m_draw_call_pre==NULL)
02138                 self->m_draw_call_pre= PyList_New(0);
02139         Py_INCREF(self->m_draw_call_pre);
02140         return self->m_draw_call_pre;
02141 }
02142 
02143 PyObject* KX_Scene::pyattr_get_drawing_callback_post(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
02144 {
02145         KX_Scene* self = static_cast<KX_Scene*>(self_v);
02146 
02147         if(self->m_draw_call_post==NULL)
02148                 self->m_draw_call_post= PyList_New(0);
02149         Py_INCREF(self->m_draw_call_post);
02150         return self->m_draw_call_post;
02151 }
02152 
02153 int KX_Scene::pyattr_set_drawing_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
02154 {
02155         KX_Scene* self = static_cast<KX_Scene*>(self_v);
02156 
02157         if (!PyList_CheckExact(value))
02158         {
02159                 PyErr_SetString(PyExc_ValueError, "Expected a list");
02160                 return PY_SET_ATTR_FAIL;
02161         }
02162         Py_XDECREF(self->m_draw_call_pre);
02163 
02164         Py_INCREF(value);
02165         self->m_draw_call_pre = value;
02166 
02167         return PY_SET_ATTR_SUCCESS;
02168 }
02169 
02170 int KX_Scene::pyattr_set_drawing_callback_post(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
02171 {
02172         KX_Scene* self = static_cast<KX_Scene*>(self_v);
02173 
02174         if (!PyList_CheckExact(value))
02175         {
02176                 PyErr_SetString(PyExc_ValueError, "Expected a list");
02177                 return PY_SET_ATTR_FAIL;
02178         }
02179         Py_XDECREF(self->m_draw_call_post);
02180 
02181         Py_INCREF(value);
02182         self->m_draw_call_post = value;
02183 
02184         return PY_SET_ATTR_SUCCESS;
02185 }
02186 
02187 PyAttributeDef KX_Scene::Attributes[] = {
02188         KX_PYATTRIBUTE_RO_FUNCTION("name",                              KX_Scene, pyattr_get_name),
02189         KX_PYATTRIBUTE_RO_FUNCTION("objects",                   KX_Scene, pyattr_get_objects),
02190         KX_PYATTRIBUTE_RO_FUNCTION("objectsInactive",   KX_Scene, pyattr_get_objects_inactive),
02191         KX_PYATTRIBUTE_RO_FUNCTION("lights",                    KX_Scene, pyattr_get_lights),
02192         KX_PYATTRIBUTE_RO_FUNCTION("cameras",                   KX_Scene, pyattr_get_cameras),
02193         KX_PYATTRIBUTE_RO_FUNCTION("lights",                    KX_Scene, pyattr_get_lights),
02194         KX_PYATTRIBUTE_RW_FUNCTION("active_camera",             KX_Scene, pyattr_get_active_camera, pyattr_set_active_camera),
02195         KX_PYATTRIBUTE_RW_FUNCTION("pre_draw",                  KX_Scene, pyattr_get_drawing_callback_pre, pyattr_set_drawing_callback_pre),
02196         KX_PYATTRIBUTE_RW_FUNCTION("post_draw",                 KX_Scene, pyattr_get_drawing_callback_post, pyattr_set_drawing_callback_post),
02197         KX_PYATTRIBUTE_BOOL_RO("suspended",                             KX_Scene, m_suspend),
02198         KX_PYATTRIBUTE_BOOL_RO("activity_culling",              KX_Scene, m_activity_culling),
02199         KX_PYATTRIBUTE_FLOAT_RW("activity_culling_radius", 0.5f, FLT_MAX, KX_Scene, m_activity_box_radius),
02200         KX_PYATTRIBUTE_BOOL_RO("dbvt_culling",                  KX_Scene, m_dbvt_culling),
02201         { NULL }        //Sentinel
02202 };
02203 
02204 KX_PYMETHODDEF_DOC(KX_Scene, addObject,
02205 "addObject(object, other, time=0)\n"
02206 "Returns the added object.\n")
02207 {
02208         PyObject *pyob, *pyother;
02209         KX_GameObject *ob, *other;
02210 
02211         int time = 0;
02212 
02213         if (!PyArg_ParseTuple(args, "OO|i:addObject", &pyob, &pyother, &time))
02214                 return NULL;
02215 
02216         if (    !ConvertPythonToGameObject(pyob, &ob, false, "scene.addObject(object, other, time): KX_Scene (first argument)") ||
02217                         !ConvertPythonToGameObject(pyother, &other, false, "scene.addObject(object, other, time): KX_Scene (second argument)") )
02218                 return NULL;
02219 
02220 
02221         SCA_IObject* replica = AddReplicaObject((SCA_IObject*)ob, other, time);
02222         
02223         // release here because AddReplicaObject AddRef's
02224         // the object is added to the scene so we dont want python to own a reference
02225         replica->Release();
02226         return replica->GetProxy();
02227 }
02228 
02229 KX_PYMETHODDEF_DOC(KX_Scene, end,
02230 "end()\n"
02231 "Removes this scene from the game.\n")
02232 {
02233         
02234         KX_GetActiveEngine()->RemoveScene(m_sceneName);
02235         
02236         Py_RETURN_NONE;
02237 }
02238 
02239 KX_PYMETHODDEF_DOC(KX_Scene, restart,
02240                                    "restart()\n"
02241                                    "Restarts this scene.\n")
02242 {
02243         KX_GetActiveEngine()->ReplaceScene(m_sceneName, m_sceneName);
02244         
02245         Py_RETURN_NONE;
02246 }
02247 
02248 KX_PYMETHODDEF_DOC(KX_Scene, replace,
02249                                    "replace(newScene)\n"
02250                                    "Replaces this scene with another one.\n")
02251 {
02252         char* name;
02253         
02254         if (!PyArg_ParseTuple(args, "s:replace", &name))
02255                 return NULL;
02256         
02257         KX_GetActiveEngine()->ReplaceScene(m_sceneName, name);
02258         
02259         Py_RETURN_NONE;
02260 }
02261 
02262 KX_PYMETHODDEF_DOC(KX_Scene, suspend,
02263                                         "suspend()\n"
02264                                         "Suspends this scene.\n")
02265 {
02266         Suspend();
02267         
02268         Py_RETURN_NONE;
02269 }
02270 
02271 KX_PYMETHODDEF_DOC(KX_Scene, resume,
02272                                         "resume()\n"
02273                                         "Resumes this scene.\n")
02274 {
02275         Resume();
02276         
02277         Py_RETURN_NONE;
02278 }
02279 
02280 /* Matches python dict.get(key, [default]) */
02281 KX_PYMETHODDEF_DOC(KX_Scene, get, "")
02282 {
02283         PyObject *key;
02284         PyObject* def = Py_None;
02285         PyObject* ret;
02286 
02287         if (!PyArg_ParseTuple(args, "O|O:get", &key, &def))
02288                 return NULL;
02289         
02290         if (m_attr_dict && (ret=PyDict_GetItem(m_attr_dict, key))) {
02291                 Py_INCREF(ret);
02292                 return ret;
02293         }
02294         
02295         Py_INCREF(def);
02296         return def;
02297 }
02298 
02299 #endif // WITH_PYTHON