GameLogic.globalDict blenderplayer now keeps settings when loading new blend files.

workaround for python stopping and starting by storing the dictionary as marshal'd data. this means only python types are supported.
This feature is needed so when switching from a menu to a level blendfile, the configuration isnt lost.
This commit is contained in:
Campbell Barton 2008-08-20 06:11:11 +00:00
parent b23f3f62c2
commit 7608dcfc51
3 changed files with 91 additions and 8 deletions

@ -97,7 +97,7 @@ extern "C"
#include "GHOST_IEventConsumer.h"
#include "GHOST_IWindow.h"
#include "GHOST_Rect.h"
#include "marshal.h"
static void frameTimerProc(GHOST_ITimerTask* task, GHOST_TUns64 time);
@ -125,7 +125,9 @@ GPG_Application::GPG_Application(GHOST_ISystem* system, struct Main* maggie, STR
m_networkdevice(0),
m_audiodevice(0),
m_blendermat(0),
m_blenderglslmat(0)
m_blenderglslmat(0),
m_pyGlobalDictString(0),
m_pyGlobalDictString_Length(0)
{
fSystem = system;
}
@ -645,14 +647,23 @@ bool GPG_Application::startEngine(void)
PyObject* dictionaryobject = initGamePlayerPythonScripting("Ketsji", psl_Lowest);
m_ketsjiengine->SetPythonDictionary(dictionaryobject);
initRasterizer(m_rasterizer, m_canvas);
PyDict_SetItemString(dictionaryobject, "GameLogic", initGameLogic(startscene)); // Same as importing the module
PyObject *gameLogic = initGameLogic(startscene);
PyDict_SetItemString(dictionaryobject, "GameLogic", gameLogic); // Same as importing the module
initGameKeys();
initPythonConstraintBinding();
initMathutils();
/* Restore the dict */
if (m_pyGlobalDictString) {
PyObject* pyGlobalDict = PyMarshal_ReadObjectFromString(m_pyGlobalDictString, m_pyGlobalDictString_Length);
if (pyGlobalDict) {
PyDict_SetItemString(PyModule_GetDict(gameLogic), "globalDict", pyGlobalDict); // Same as importing the module.
} else {
PyErr_Clear();
printf("Error could not marshall string\n");
}
}
m_sceneconverter->ConvertScene(
startscenename,
startscene,
@ -688,6 +699,32 @@ bool GPG_Application::startEngine(void)
void GPG_Application::stopEngine()
{
// get the python dict and convert to a string for future use
{
SetPyGlobalDictMarshal(NULL, 0);
PyObject* gameLogic = PyImport_ImportModule("GameLogic");
if (gameLogic) {
PyObject* pyGlobalDict = PyDict_GetItemString(PyModule_GetDict(gameLogic), "globalDict"); // Same as importing the module
if (pyGlobalDict) {
PyObject* pyGlobalDictMarshal = PyMarshal_WriteObjectToString( pyGlobalDict, 2); // Py_MARSHAL_VERSION == 2 as of Py2.5
if (pyGlobalDictMarshal) {
m_pyGlobalDictString_Length = PyString_Size(pyGlobalDictMarshal);
PyObject_Print(pyGlobalDictMarshal, stderr, 0);
m_pyGlobalDictString = static_cast<char *> (malloc(m_pyGlobalDictString_Length));
memcpy(m_pyGlobalDictString, PyString_AsString(pyGlobalDictMarshal), m_pyGlobalDictString_Length);
} else {
printf("Error, GameLogic.globalDict could not be marshal'd\n");
}
} else {
printf("Error, GameLogic.globalDict was removed\n");
}
} else {
printf("Error, GameLogic failed to import GameLogic.globalDict will be lost\n");
}
}
// when exiting the mainloop
exitGamePythonScripting();
m_ketsjiengine->StopEngine();

@ -72,6 +72,29 @@ public:
bool StartGameEngine(int stereoMode);
void StopGameEngine();
char*
GetPyGlobalDictMarshal()
{
return m_pyGlobalDictString;
};
void
SetPyGlobalDictMarshal( char* pyGlobalDictString, int length )
{
if (m_pyGlobalDictString && m_pyGlobalDictString != pyGlobalDictString)
free(m_pyGlobalDictString);
m_pyGlobalDictString = pyGlobalDictString;
m_pyGlobalDictString_Length = length;
};
int
GetPyGlobalDictMarshalLength()
{
return m_pyGlobalDictString_Length;
};
protected:
bool handleWheel(GHOST_IEvent* event);
bool handleButton(GHOST_IEvent* event, bool isDown);
@ -142,6 +165,12 @@ protected:
bool m_blendermat;
bool m_blenderglslmat;
/*
* GameLogic.globalDict as a string so that loading new blend files can use the same dict.
* Do this because python starts/stops when loading blend files.
*/
char* m_pyGlobalDictString;
int m_pyGlobalDictString_Length;
};

@ -293,7 +293,9 @@ int main(int argc, char** argv)
GHOST_TUns32 fullScreenHeight= 0;
int fullScreenBpp = 32;
int fullScreenFrequency = 60;
char* pyGlobalDictString = NULL; /* store python dict data between blend file loading */
int pyGlobalDictString_Length = 0;
#ifdef __linux__
#ifdef __alpha__
signal (SIGFPE, SIG_IGN);
@ -625,6 +627,10 @@ int main(int argc, char** argv)
titlename = maggie->name;
// Set the GameLogic.globalDict from marshal'd data, so we can load new blend files
// abd keep data in GameLogic.globalDict
app.SetPyGlobalDictMarshal(pyGlobalDictString, pyGlobalDictString_Length);
// Check whether the game should be displayed full-screen
if ((!fullScreenParFound) && (!windowParFound))
{
@ -750,6 +756,12 @@ int main(int argc, char** argv)
}
}
app.StopGameEngine();
// GameLogic.globalDict has been converted into a buffer
// store in pyGlobalDictString so we can restore after python has stopped and started.
pyGlobalDictString = app.GetPyGlobalDictMarshal();
pyGlobalDictString_Length = app.GetPyGlobalDictMarshalLength();
BLO_blendfiledata_free(bfd);
#ifdef __APPLE__
@ -772,6 +784,11 @@ int main(int argc, char** argv)
}
}
if (pyGlobalDictString) {
free(pyGlobalDictString);
pyGlobalDictString = NULL;
}
return error ? -1 : 0;
}