diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp index 7be3b94d8ae..f859193ef7a 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp @@ -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 (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(); diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.h b/source/gameengine/GamePlayer/ghost/GPG_Application.h index 17f5add8b19..31f5eb75e52 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.h +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.h @@ -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; }; diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index 8222e5c8bac..26a85128025 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -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; }