save and load configuration actuator, (option in game actuator menu)

saves a marshal'd GameLogic.globalDict to the blendfile path with the blend extension replaced with bgeconf

Use this in YoFrankie to save keyboard layout and graphics quality settings.
This commit is contained in:
Campbell Barton
2008-09-12 02:15:16 +00:00
parent 75841bc97f
commit 0dea748e01
8 changed files with 158 additions and 48 deletions

View File

@@ -876,6 +876,16 @@ void BL_ConvertActuators(char* maggiename,
mode = KX_GameActuator::KX_GAME_QUIT;
break;
}
case ACT_GAME_SAVECFG:
{
mode = KX_GameActuator::KX_GAME_SAVECFG;
break;
}
case ACT_GAME_LOADCFG:
{
mode = KX_GameActuator::KX_GAME_LOADCFG;
break;
}
default:
; /* flag error */
}

View File

@@ -98,7 +98,6 @@ 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);
@@ -685,15 +684,7 @@ bool GPG_Application::startEngine(void)
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");
}
}
loadGamePythonConfig(m_pyGlobalDictString, m_pyGlobalDictString_Length);
m_sceneconverter->ConvertScene(
startscenename,
@@ -731,36 +722,12 @@ 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) {
#ifdef Py_MARSHAL_VERSION
PyObject* pyGlobalDictMarshal = PyMarshal_WriteObjectToString( pyGlobalDict, 2); // Py_MARSHAL_VERSION == 2 as of Py2.5
#else
PyObject* pyGlobalDictMarshal = PyMarshal_WriteObjectToString( pyGlobalDict );
#endif
if (pyGlobalDictMarshal) {
m_pyGlobalDictString_Length = PyString_Size(pyGlobalDictMarshal);
// for testing only
// 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");
}
Py_DECREF(gameLogic);
} else {
printf("Error, GameLogic.globalDict was removed\n");
}
} else {
printf("Error, GameLogic failed to import GameLogic.globalDict will be lost\n");
}
}
char *marshal_buffer;
m_pyGlobalDictString_Length = saveGamePythonConfig(&marshal_buffer);
if (m_pyGlobalDictString_Length) {
m_pyGlobalDictString = static_cast<char *> (malloc(m_pyGlobalDictString_Length));
memcpy(m_pyGlobalDictString, marshal_buffer, m_pyGlobalDictString_Length);
}
// when exiting the mainloop
exitGamePythonScripting();

View File

@@ -34,6 +34,7 @@
//#include <iostream>
#include "KX_Scene.h"
#include "KX_KetsjiEngine.h"
#include "KX_PythonInit.h" /* for config load/saving */
#ifdef HAVE_CONFIG_H
#include <config.h>
@@ -125,6 +126,71 @@ bool KX_GameActuator::Update()
}
break;
}
case KX_GAME_SAVECFG:
{
if (m_ketsjiengine)
{
char mashal_path[512];
char *marshal_buffer = NULL;
int marshal_length;
FILE *fp = NULL;
pathGamePythonConfig(mashal_path);
marshal_length = saveGamePythonConfig(&marshal_buffer);
if (marshal_length && marshal_buffer) {
fp = fopen(mashal_path, "wb");
if (fp) {
if (fwrite(marshal_buffer, 1, marshal_length, fp) != marshal_length) {
printf("Warning: could not write marshal data\n");
}
fclose(fp);
} else {
printf("Warning: could not open marshal file\n");
}
} else {
printf("Warning: could not create marshal buffer\n");
}
}
break;
}
case KX_GAME_LOADCFG:
{
if (m_ketsjiengine)
{
char mashal_path[512];
char *marshal_buffer;
int marshal_length;
FILE *fp = NULL;
int result;
pathGamePythonConfig(mashal_path);
fp = fopen(mashal_path, "rb");
if (fp) {
// obtain file size:
fseek (fp , 0 , SEEK_END);
marshal_length = ftell(fp);
rewind(fp);
marshal_buffer = (char*) malloc (sizeof(char)*marshal_length);
result = fread (marshal_buffer, 1, marshal_length, fp);
if (result == marshal_length) {
loadGamePythonConfig(marshal_buffer, marshal_length);
} else {
printf("warning: could not read all of '%s'\n", mashal_path);
}
free(marshal_buffer);
fclose(fp);
} else {
printf("warning: could not open '%s'\n", mashal_path);
}
}
break;
}
default:
; /* do nothing? this is an internal error !!! */
}

View File

@@ -54,6 +54,8 @@ protected:
KX_GAME_START,
KX_GAME_RESTART,
KX_GAME_QUIT,
KX_GAME_SAVECFG,
KX_GAME_LOADCFG,
KX_GAME_MAX
};

View File

@@ -74,6 +74,8 @@ extern "C" {
#include "Mathutils.h" // Blender.Mathutils module copied here so the blenderlayer can use.
}
#include "marshal.h" /* python header for loading/saving dicts */
#include "PHY_IPhysicsEnvironment.h"
// FIXME: Enable for access to blender python modules. This is disabled because
// python has dependencies on a lot of other modules and is a pain to link.
@@ -1319,3 +1321,66 @@ class KX_Scene* PHY_GetActiveScene()
{
return gp_KetsjiScene;
}
// utility function for loading and saving the globalDict
int saveGamePythonConfig( char **marshal_buffer)
{
int marshal_length = 0;
PyObject* gameLogic = PyImport_ImportModule("GameLogic");
if (gameLogic) {
PyObject* pyGlobalDict = PyDict_GetItemString(PyModule_GetDict(gameLogic), "globalDict"); // Same as importing the module
if (pyGlobalDict) {
#ifdef Py_MARSHAL_VERSION
PyObject* pyGlobalDictMarshal = PyMarshal_WriteObjectToString( pyGlobalDict, 2); // Py_MARSHAL_VERSION == 2 as of Py2.5
#else
PyObject* pyGlobalDictMarshal = PyMarshal_WriteObjectToString( pyGlobalDict );
#endif
if (pyGlobalDictMarshal) {
marshal_length= PyString_Size(pyGlobalDictMarshal);
// for testing only
// PyObject_Print(pyGlobalDictMarshal, stderr, 0);
*marshal_buffer = PyString_AsString(pyGlobalDictMarshal);
} else {
printf("Error, GameLogic.globalDict could not be marshal'd\n");
}
Py_DECREF(gameLogic);
} else {
printf("Error, GameLogic.globalDict was removed\n");
}
} else {
printf("Error, GameLogic failed to import GameLogic.globalDict will be lost\n");
}
return marshal_length;
}
int loadGamePythonConfig(char *marshal_buffer, int marshal_length)
{
PyObject* gameLogic = PyImport_ImportModule("GameLogic");
/* Restore the dict */
if (marshal_buffer) {
PyObject* pyGlobalDict = PyMarshal_ReadObjectFromString(marshal_buffer, marshal_length);
if (pyGlobalDict) {
PyDict_SetItemString(PyModule_GetDict(gameLogic), "globalDict", pyGlobalDict); // Same as importing the module.
return 1;
} else {
PyErr_Clear();
printf("Error could not marshall string\n");
}
} else {
printf("Error, GameLogic failed to import GameLogic.globalDict will be lost\n");
}
return 0;
}
void pathGamePythonConfig( char *path )
{
int len = strlen(G.sce);
strncpy(path, G.sce, sizeof(G.sce));
/* replace extension */
if (BLI_testextensie(path, ".blend")) {
strcpy(path+(len-6), ".bgeconf");
} else {
strcpy(path+len, ".bgeconf");
}
}

View File

@@ -49,6 +49,10 @@ void exitGamePlayerPythonScripting();
PyObject* initGamePythonScripting(const STR_String& progname, TPythonSecurityLevel level);
void exitGamePythonScripting();
void pathGamePythonConfig( char *path );
int saveGamePythonConfig( char **marshal_buffer);
int loadGamePythonConfig(char *marshal_buffer, int marshal_length);
void PHY_SetActiveScene(class KX_Scene* scene);
class KX_Scene* PHY_GetActiveScene();
#include "MT_Vector3.h"