Skip to content

Commit

Permalink
UPBGE: Fix include from blenderplayer python main loop script.
Browse files Browse the repository at this point in the history
Previously the python main loop script was just run as it. So the include
depending on other files located in the same directory than the script
were failing the import.

To fix this issue we have to add the script directory into the python
system path list.
To realize this, a new function LA_Launcher::RunPythonMainLoop is added,
its goal is to run the python main loop and in the LA_PlayerLauncher
override, add the include path (if we use a python script passed from
commad line) before run the python main.

In the same way the complexity of char *(*) used in LA_Launcher and
KX_PythonMain is removed by using simple std::string.
  • Loading branch information
panzergame committed Jan 28, 2017
1 parent fd7717d commit 8d36a66
Show file tree
Hide file tree
Showing 10 changed files with 82 additions and 60 deletions.
2 changes: 1 addition & 1 deletion source/gameengine/GamePlayer/GPG_ghost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,7 @@ int main(
bool isBlenderPlayer = false; //true when lauching from blender or command line. false for bundled player
int validArguments=0;
bool samplesParFound = false;
char *pythonControllerFile = NULL;
std::string pythonControllerFile;
GHOST_TUns16 aasamples = 0;
int alphaBackground = 0;

Expand Down
6 changes: 6 additions & 0 deletions source/gameengine/Ketsji/KX_PythonInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1934,6 +1934,12 @@ static void restorePySysObjects(void)
gp_sys_backup.modules = NULL;
}

void appendPythonPath(const std::string& path)
{
PyObject *sys_path = PySys_GetObject("path");
initPySysObjects__append(sys_path, path.c_str());
}

void addImportMain(struct Main *maggie)
{
bpy_import_main_extra_add(maggie);
Expand Down
3 changes: 3 additions & 0 deletions source/gameengine/Ketsji/KX_PythonInit.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ PyMODINIT_FUNC initVideoTexturePythonBinding(void);
PyObject *initGamePlayerPythonScripting(struct Main *maggie, int argc, char **argv);
PyObject *initGamePythonScripting(struct Main *maggie);

// Add a python include path.
void appendPythonPath(const std::string& path);

void exitGamePlayerPythonScripting();
void exitGamePythonScripting();
void setupGamePython(KX_KetsjiEngine *ketsjiengine, Main *blenderdata,
Expand Down
37 changes: 13 additions & 24 deletions source/gameengine/Ketsji/KX_PythonMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,46 +26,35 @@

#include "KX_PythonMain.h"

#ifdef __cplusplus
extern "C" {
#endif
# include "BLI_listbase.h"

#include <stddef.h>
# include "BKE_text.h"
# include "BKE_idprop.h"
# include "BKE_main.h"

#include "MEM_guardedalloc.h"

#include "BLI_string.h"
#include "BLI_listbase.h"

#include "BKE_text.h"
#include "BKE_main.h"
#include "BKE_idprop.h"


#ifdef __cplusplus
# include "DNA_scene_types.h"
}
#endif

extern "C" char *KX_GetPythonMain(struct Scene *scene)
std::string KX_GetPythonMain(Scene *scene)
{
/* examine custom scene properties */
// Examine custom scene properties.
if (scene->id.properties) {
IDProperty *item = IDP_GetPropertyTypeFromGroup(scene->id.properties, "__main__", IDP_STRING);
if (item) {
return BLI_strdup(IDP_String(item));
return IDP_String(item);
}
}

return NULL;
return "";
}

extern "C" char *KX_GetPythonCode(Main *bmain, char *python_main)
std::string KX_GetPythonCode(Main *bmain, const std::string& python_main)
{
Text *text;

if ((text = (Text *)BLI_findstring(&bmain->text, python_main, offsetof(ID, name) + 2))) {
Text *text = (Text *)BLI_findstring(&bmain->text, python_main.c_str(), offsetof(ID, name) + 2);
if (text) {
return txt_to_buf(text);
}

return NULL;
return "";
}
12 changes: 7 additions & 5 deletions source/gameengine/Ketsji/KX_PythonMain.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,12 @@
#ifndef __KX_PYTHON_MAIN__
#define __KX_PYTHON_MAIN__

#include "BLI_sys_types.h"
#include "BKE_main.h"
#include "DNA_scene_types.h"
extern "C" char *KX_GetPythonMain(struct Scene* scene);
extern "C" char *KX_GetPythonCode(struct Main *main, char *python_main);
#include <string>

struct Scene;
struct Main;

std::string KX_GetPythonMain(Scene* scene);
std::string KX_GetPythonCode(Main *main, const std::string& python_main);

#endif /* __KX_PYTHON_MAIN__ */
37 changes: 20 additions & 17 deletions source/gameengine/Launcher/LA_Launcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,6 @@ extern "C" {
# include "DNA_scene_types.h"
# include "DNA_material_types.h"

# include "MEM_guardedalloc.h"

# include "wm_event_types.h"
}

Expand Down Expand Up @@ -454,18 +452,24 @@ void LA_Launcher::RenderEngine()
m_ketsjiEngine->Render();
}

bool LA_Launcher::GetMainLoopPythonCode(char **pythonCode, char **pythonFileName)
bool LA_Launcher::GetPythonMainLoopCode(std::string& pythonCode, std::string& pythonFileName)
{
*pythonFileName = KX_GetPythonMain(m_startScene);
if (*pythonFileName) {
*pythonCode = KX_GetPythonCode(m_maggie, *pythonFileName);
if (!*pythonCode) {
CM_Error("Cannot yield control to Python: no Python text data block named '" << *pythonFileName << "'");
return false;
}
return true;
pythonFileName = KX_GetPythonMain(m_startScene);
if (pythonFileName.empty()) {
return false;
}

pythonCode = KX_GetPythonCode(m_maggie, pythonFileName);
if (pythonCode.empty()) {
CM_Error("cannot yield control to Python: no Python text data block named '" << pythonFileName << "'");
return false;
}
return false;
return true;
}

void LA_Launcher::RunPythonMainLoop(const std::string& pythonCode)
{
PyRun_SimpleString(pythonCode.c_str());
}

bool LA_Launcher::EngineNextFrame()
Expand Down Expand Up @@ -514,9 +518,9 @@ bool LA_Launcher::EngineNextFrame()
void LA_Launcher::EngineMainLoop()
{
#ifdef WITH_PYTHON
char *pythonCode;
char *pythonFileName;
if (GetMainLoopPythonCode(&pythonCode, &pythonFileName)) {
std::string pythonCode;
std::string pythonFileName;
if (GetPythonMainLoopCode(pythonCode, pythonFileName)) {
// Set python environement variable.
KX_SetActiveScene(m_kxStartScene);
PHY_SetActiveEnvironment(m_kxStartScene->GetPhysicsEnvironment());
Expand All @@ -525,9 +529,8 @@ void LA_Launcher::EngineMainLoop()
pynextframestate.func = &PythonEngineNextFrame;

CM_Debug("Yielding control to Python script '" << pythonFileName << "'...");
PyRun_SimpleString(pythonCode);
RunPythonMainLoop(pythonCode);
CM_Debug("Exit Python script '" << pythonFileName << "'");
MEM_freeN(pythonCode);
}
else {
pynextframestate.state = NULL;
Expand Down
5 changes: 4 additions & 1 deletion source/gameengine/Launcher/LA_Launcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,12 +115,15 @@ class LA_Launcher
/// Execute engine render, overrided to render background.
virtual void RenderEngine();

#ifdef WITH_PYTHON
/** Return true if the user use a valid python script for main loop and copy the python code
* to pythonCode and file name to pythonFileName. Else return false.
* This function print itself error messages for invalid script name and only pythonCode
* value must be freed.
*/
virtual bool GetMainLoopPythonCode(char **pythonCode, char **pythonFileName);
virtual bool GetPythonMainLoopCode(std::string& pythonCode, std::string& pythonFileName);
virtual void RunPythonMainLoop(const std::string& pythonCode);
#endif // WITH_PYTHON

virtual RAS_ICanvas *CreateCanvas(RAS_IRasterizer *rasty) = 0;
virtual RAS_IRasterizer::DrawType GetRasterizerDrawMode() = 0;
Expand Down
29 changes: 21 additions & 8 deletions source/gameengine/Launcher/LA_PlayerLauncher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ extern "C" {
# include "BKE_sound.h"

# include "BLI_fileops.h"

# include "MEM_guardedalloc.h"
}

#include "KX_PythonInit.h"
Expand All @@ -57,7 +59,7 @@ extern "C" {
#include "CM_Message.h"

LA_PlayerLauncher::LA_PlayerLauncher(GHOST_ISystem *system, GHOST_IWindow *window, Main *maggie, Scene *scene, GlobalSettings *gs,
RAS_IRasterizer::StereoMode stereoMode, int samples, int argc, char **argv, char *pythonMainLoop)
RAS_IRasterizer::StereoMode stereoMode, int samples, int argc, char **argv, const std::string& pythonMainLoop)
:LA_Launcher(system, maggie, scene, gs, stereoMode, samples, argc, argv),
m_mainWindow(window),
m_pythonMainLoop(pythonMainLoop)
Expand All @@ -68,15 +70,16 @@ LA_PlayerLauncher::~LA_PlayerLauncher()
{
}

bool LA_PlayerLauncher::GetMainLoopPythonCode(char **pythonCode, char **pythonFileName)
bool LA_PlayerLauncher::GetPythonMainLoopCode(std::string& pythonCode, std::string& pythonFileName)
{
#ifndef WITH_GAMEENGINE_SECURITY
if (m_pythonMainLoop) {
if (BLI_is_file(m_pythonMainLoop)) {
if (!m_pythonMainLoop.empty()) {
if (BLI_is_file(m_pythonMainLoop.c_str())) {
size_t filesize = 0;
*pythonCode = (char *)BLI_file_read_text_as_mem(m_pythonMainLoop, 1, &filesize);
(*pythonCode)[filesize] = '\0';
*pythonFileName = m_pythonMainLoop;
char *filecontent = (char *)BLI_file_read_text_as_mem(m_pythonMainLoop.c_str(), 0, &filesize);
pythonCode = std::string(filecontent, filesize);
MEM_freeN(filecontent);
pythonFileName = m_pythonMainLoop;
return true;
}
else {
Expand All @@ -85,7 +88,17 @@ bool LA_PlayerLauncher::GetMainLoopPythonCode(char **pythonCode, char **pythonFi
}
}
#endif
return LA_Launcher::GetMainLoopPythonCode(pythonCode, pythonFileName);
return LA_Launcher::GetPythonMainLoopCode(pythonCode, pythonFileName);
}

void LA_PlayerLauncher::RunPythonMainLoop(const std::string& pythonCode)
{
/* If a valid python main loop file exists is that we are running it.
* Then we put its path in the python include paths. */
if (!m_pythonMainLoop.empty()) {
appendPythonPath(m_pythonMainLoop);
}
LA_Launcher::RunPythonMainLoop(pythonCode);
}

RAS_IRasterizer::DrawType LA_PlayerLauncher::GetRasterizerDrawMode()
Expand Down
9 changes: 6 additions & 3 deletions source/gameengine/Launcher/LA_PlayerLauncher.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,12 @@ class LA_PlayerLauncher : public LA_Launcher
GHOST_IWindow *m_mainWindow;

/// Override python script main loop file name.
char *m_pythonMainLoop;
std::string m_pythonMainLoop;

virtual bool GetMainLoopPythonCode(char **pythonCode, char **pythonFileName);
#ifdef WITH_PYTHON
virtual bool GetPythonMainLoopCode(std::string& pythonCode, std::string& pythonFileName);
virtual void RunPythonMainLoop(const std::string& pythonCode);
#endif // WITH_PYTHON

virtual RAS_ICanvas *CreateCanvas(RAS_IRasterizer *rasty);
virtual RAS_IRasterizer::DrawType GetRasterizerDrawMode();
Expand All @@ -61,7 +64,7 @@ class LA_PlayerLauncher : public LA_Launcher

public:
LA_PlayerLauncher(GHOST_ISystem *system, GHOST_IWindow *window, Main *maggie, Scene *scene, GlobalSettings *gs,
RAS_IRasterizer::StereoMode stereoMode, int samples, int argc, char **argv, char *pythonMainLoop);
RAS_IRasterizer::StereoMode stereoMode, int samples, int argc, char **argv, const std::string& pythonMainLoop);
virtual ~LA_PlayerLauncher();

virtual void InitEngine();
Expand Down
2 changes: 1 addition & 1 deletion source/tools
Submodule tools updated from 6bbb68 to b11375

0 comments on commit 8d36a66

Please sign in to comment.