forked from bartvdbraak/blender
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:
parent
75841bc97f
commit
0dea748e01
@ -445,6 +445,8 @@ typedef struct FreeCamera {
|
||||
#define ACT_GAME_START 1
|
||||
#define ACT_GAME_RESTART 2
|
||||
#define ACT_GAME_QUIT 3
|
||||
#define ACT_GAME_SAVECFG 4
|
||||
#define ACT_GAME_LOADCFG 5
|
||||
|
||||
/* visibilityact->flag */
|
||||
/* Set means the object will become invisible */
|
||||
|
@ -2296,13 +2296,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh
|
||||
uiDefBut(block, TEX, 1, "File: ", xco+10, yco-44,width-20,19, &(gma->filename), 0, 63, 0, 0, "Load this file");
|
||||
uiDefBut(block, TEX, 1, "Anim: ", xco+10, yco-64,width-20,19, &(gma->loadaniname), 0, 63, 0, 0, "Use this loadinganimation");
|
||||
}
|
||||
*/ else if (gma->type == ACT_GAME_RESTART)
|
||||
{
|
||||
ysize = 28;
|
||||
glRects(xco, yco-ysize, xco+width, yco);
|
||||
uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1);
|
||||
}
|
||||
else if (gma->type == ACT_GAME_QUIT)
|
||||
*/ else if (ELEM4(gma->type, ACT_GAME_RESTART, ACT_GAME_QUIT, ACT_GAME_SAVECFG, ACT_GAME_LOADCFG))
|
||||
{
|
||||
ysize = 28;
|
||||
glRects(xco, yco-ysize, xco+width, yco);
|
||||
@ -2310,7 +2304,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh
|
||||
}
|
||||
|
||||
//str = "Scene %t|Load game%x0|Start loaded game%x1|Restart this game%x2|Quit this game %x3";
|
||||
str = "Scene %t|Start new game%x0|Restart this game%x2|Quit this game %x3";
|
||||
str = "Scene %t|Start new game%x0|Restart this game%x2|Quit this game %x3|Save GameLogic.globalDict %x4|Load GameLogic.globalDict %x5";
|
||||
uiDefButS(block, MENU, B_REDR, str, xco+40, yco-24, (width-80), 19, &gma->type, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
yco -= ysize;
|
||||
|
@ -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 */
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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 !!! */
|
||||
}
|
||||
|
@ -54,6 +54,8 @@ protected:
|
||||
KX_GAME_START,
|
||||
KX_GAME_RESTART,
|
||||
KX_GAME_QUIT,
|
||||
KX_GAME_SAVECFG,
|
||||
KX_GAME_LOADCFG,
|
||||
KX_GAME_MAX
|
||||
|
||||
};
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user