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