From fb49c5aa5662da3c2434c75ea6283408c01d6c23 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Sat, 23 Aug 2014 12:31:32 +0200 Subject: BGE: fix crash and return boolean on scene.replace() Scene replacement with invalid scene name was crashing blender, now it's a no-op. KS_Scene.replace() to return a boolean to indicate if the scene is valid and is scheduled for replacement. This allows more robust game management. --- source/gameengine/Ketsji/KX_KetsjiEngine.cpp | 33 +++++++++++++++++++++------- source/gameengine/Ketsji/KX_KetsjiEngine.h | 2 +- source/gameengine/Ketsji/KX_Scene.cpp | 8 ++++--- 3 files changed, 31 insertions(+), 12 deletions(-) (limited to 'source') diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index 5a2cb0c3a97..14772cda113 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -1732,9 +1732,20 @@ void KX_KetsjiEngine::AddScheduledScenes() -void KX_KetsjiEngine::ReplaceScene(const STR_String& oldscene,const STR_String& newscene) -{ - m_replace_scenes.push_back(std::make_pair(oldscene,newscene)); +bool KX_KetsjiEngine::ReplaceScene(const STR_String& oldscene,const STR_String& newscene) +{ + // Don't allow replacement if the new scene doesn't exists. + // Allows smarter game design (used to have no check here). + // Note that it creates a small backward compatbility issue + // for a game that did a replace followed by a lib load with the + // new scene in the lib => it won't work anymore, the lib + // must be loaded before doing the replace. + if (m_sceneconverter->GetBlenderSceneForName(newscene) != NULL) + { + m_replace_scenes.push_back(std::make_pair(oldscene,newscene)); + return true; + } + return false; } // replace scene is not the same as removing and adding because the @@ -1758,13 +1769,19 @@ void KX_KetsjiEngine::ReplaceScheduledScenes() KX_SceneList::iterator sceneit; for (sceneit = m_scenes.begin();sceneit != m_scenes.end() ; sceneit++) { - KX_Scene* scene = *sceneit; + KX_Scene* scene = *sceneit; if (scene->GetName() == oldscenename) { - m_sceneconverter->RemoveScene(scene); - KX_Scene* tmpscene = CreateScene(newscenename); - m_scenes[i]=tmpscene; - PostProcessScene(tmpscene); + // avoid crash if the new scene doesn't exist, just do nothing + Scene *blScene = m_sceneconverter->GetBlenderSceneForName(newscenename); + if (blScene) { + m_sceneconverter->RemoveScene(scene); + KX_Scene* tmpscene = CreateScene(blScene); + m_scenes[i]=tmpscene; + PostProcessScene(tmpscene); + } else { + printf("warning: scene %s could not be found, not replaced!\n",newscenename.ReadPtr()); + } } i++; } diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.h b/source/gameengine/Ketsji/KX_KetsjiEngine.h index 2bc5bad6daf..2b80e3bd69a 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.h +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.h @@ -258,7 +258,7 @@ public: void ConvertAndAddScene(const STR_String& scenename,bool overlay); void RemoveScene(const STR_String& scenename); - void ReplaceScene(const STR_String& oldscene,const STR_String& newscene); + bool ReplaceScene(const STR_String& oldscene,const STR_String& newscene); void SuspendScene(const STR_String& scenename); void ResumeScene(const STR_String& scenename); diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 5745e3adbc5..625bbee2c8e 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -2501,16 +2501,18 @@ KX_PYMETHODDEF_DOC(KX_Scene, restart, KX_PYMETHODDEF_DOC(KX_Scene, replace, "replace(newScene)\n" - "Replaces this scene with another one.\n") + "Replaces this scene with another one.\n" + "Return True if the new scene exists and scheduled for replacement, False otherwise.\n") { char* name; if (!PyArg_ParseTuple(args, "s:replace", &name)) return NULL; - KX_GetActiveEngine()->ReplaceScene(m_sceneName, name); + if (KX_GetActiveEngine()->ReplaceScene(m_sceneName, name)) + Py_RETURN_TRUE; - Py_RETURN_NONE; + Py_RETURN_FALSE; } KX_PYMETHODDEF_DOC(KX_Scene, suspend, -- cgit v1.2.3