Blender V2.61 - r43446

KX_Scene.cpp

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