Blender V2.61 - r43446
|
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