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.
This commit is contained in:
Benoit Bolsee 2014-08-23 12:31:32 +02:00
parent a0600debda
commit fb49c5aa56
4 changed files with 32 additions and 11 deletions

View File

@ -152,6 +152,8 @@ base class --- :class:`PyObjectPlus`
:arg scene: The name of the scene to replace this scene with.
:type scene: string
:return: True if the scene exists and was scheduled for addition, False otherwise.
:rtype: boolean
.. method:: suspend()

View File

@ -1732,9 +1732,20 @@ void KX_KetsjiEngine::AddScheduledScenes()
void KX_KetsjiEngine::ReplaceScene(const STR_String& oldscene,const STR_String& newscene)
bool KX_KetsjiEngine::ReplaceScene(const STR_String& oldscene,const STR_String& newscene)
{
m_replace_scenes.push_back(std::make_pair(oldscene,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++;
}

View File

@ -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);

View File

@ -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,