[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [47084] branches/soc-2012-swiss_cheese/ source/gameengine: Hive main patch

Benoit Bolsee benoit.bolsee at online.be
Sun May 27 19:39:14 CEST 2012


Revision: 47084
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=47084
Author:   ben2610
Date:     2012-05-27 17:39:13 +0000 (Sun, 27 May 2012)
Log Message:
-----------
Hive main patch
===============
Give the possibility to pass the game control to a python script, the game engine ends when the python script returns. This patch is necessary for the hive system because it needs to control the main loop.

To active this feature, add a custom property "__main__" to the startup scene and set it to the name of a text block that contains the python script.
"NextFrame" python function is provided in the GameLogic module to execute one frame of the BGE, i.e. logic bricks, physics and render. The function returns FALSE if the game hit an exit condition, TRUE otherwise. 
Example: 

  # this python will reproduce the behavior of the BGE (with poor timing):
  import GameLogic, time
  while GameLogic.NextFrame():
      time.sleep(0.016)

Notes: * This feature is used internally by the hive system.
       * This interface is unstable, it may change in the future
       * It is not yet possible to load a new game or restart the game from python

Modified Paths:
--------------
    branches/soc-2012-swiss_cheese/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
    branches/soc-2012-swiss_cheese/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
    branches/soc-2012-swiss_cheese/source/gameengine/Ketsji/CMakeLists.txt
    branches/soc-2012-swiss_cheese/source/gameengine/Ketsji/KX_PythonInit.cpp
    branches/soc-2012-swiss_cheese/source/gameengine/Ketsji/KX_PythonInit.h

Added Paths:
-----------
    branches/soc-2012-swiss_cheese/source/gameengine/Ketsji/KX_PythonMain.cpp
    branches/soc-2012-swiss_cheese/source/gameengine/Ketsji/KX_PythonMain.h

Modified: branches/soc-2012-swiss_cheese/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
===================================================================
--- branches/soc-2012-swiss_cheese/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp	2012-05-27 17:34:10 UTC (rev 47083)
+++ branches/soc-2012-swiss_cheese/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp	2012-05-27 17:39:13 UTC (rev 47084)
@@ -54,6 +54,7 @@
 #include "KX_BlenderSceneConverter.h"
 #include "KX_PythonInit.h"
 #include "KX_PyConstraintBinding.h"
+#include "KX_PythonMain.h"
 
 #include "RAS_GLExtensionManager.h"
 #include "RAS_OpenGLRasterizer.h"
@@ -79,6 +80,9 @@
 #include "DNA_windowmanager_types.h"
 #include "BKE_global.h"
 #include "BKE_report.h"
+
+#include "MEM_guardedalloc.h"
+
 /* #include "BKE_screen.h" */ /* cant include this because of 'new' function name */
 extern float BKE_screen_view3d_zoom_to_fac(float camzoom);
 
@@ -126,6 +130,95 @@
 	return bfd;
 }
 
+int BL_KetsjiNextFrame(struct KX_KetsjiEngine* ketsjiengine, struct bContext *C, struct wmWindow* win, struct Scene* scene, struct ARegion *ar,
+                    KX_BlenderKeyboardDevice* keyboarddevice, KX_BlenderMouseDevice* mousedevice, int draw_letterbox)
+{
+    int exitrequested;
+
+    // first check if we want to exit
+    exitrequested = ketsjiengine->GetExitCode();
+
+    // kick the engine
+    bool render = ketsjiengine->NextFrame();
+
+    if (render)
+    {
+        if(draw_letterbox) {
+            // Clear screen to border color
+            // We do this here since we set the canvas to be within the frames. This means the engine
+            // itself is unaware of the extra space, so we clear the whole region for it.
+            glClearColor(scene->gm.framing.col[0], scene->gm.framing.col[1], scene->gm.framing.col[2], 1.0f);
+            glViewport(ar->winrct.xmin, ar->winrct.ymin,
+                ar->winrct.xmax - ar->winrct.xmin, ar->winrct.ymax - ar->winrct.ymin);
+            glClear(GL_COLOR_BUFFER_BIT);
+        }
+
+        // render the frame
+        ketsjiengine->Render();
+    }
+
+    wm_window_process_events_nosleep();
+
+    // test for the ESC key
+    //XXX while (qtest())
+    while(wmEvent *event= (wmEvent *)win->queue.first)
+    {
+        short val = 0;
+        //unsigned short event = 0; //XXX extern_qread(&val);
+
+        if (keyboarddevice->ConvertBlenderEvent(event->type,event->val))
+            exitrequested = KX_EXIT_REQUEST_BLENDER_ESC;
+
+            /* Coordinate conversion... where
+            * should this really be?
+        */
+        if (event->type==MOUSEMOVE) {
+            /* Note, not nice! XXX 2.5 event hack */
+            val = event->x - ar->winrct.xmin;
+            mousedevice->ConvertBlenderEvent(MOUSEX, val);
+
+            val = ar->winy - (event->y - ar->winrct.ymin) - 1;
+            mousedevice->ConvertBlenderEvent(MOUSEY, val);
+        }
+        else {
+            mousedevice->ConvertBlenderEvent(event->type,event->val);
+        }
+
+        BLI_remlink(&win->queue, event);
+        wm_event_free(event);
+    }
+
+    if(win != CTX_wm_window(C)) {
+        exitrequested= KX_EXIT_REQUEST_OUTSIDE; /* window closed while bge runs */
+    }
+    return exitrequested;
+}
+
+struct BL_KetsjiNextFrameState {
+	struct KX_KetsjiEngine* ketsjiengine;
+	struct bContext *C;
+	struct wmWindow* win;
+	struct Scene* scene;
+	struct ARegion *ar;
+	KX_BlenderKeyboardDevice* keyboarddevice;
+	KX_BlenderMouseDevice* mousedevice;
+	int draw_letterbox;
+} ketsjinextframestate;
+
+int BL_KetsjiPyNextFrame(void *state0) 
+{
+	BL_KetsjiNextFrameState *state = (BL_KetsjiNextFrameState *) state0;
+	return BL_KetsjiNextFrame(
+		state->ketsjiengine, 
+		state->C, 
+		state->win, 
+		state->scene, 
+		state->ar,
+		state->keyboarddevice, 
+		state->mousedevice, 
+		state->draw_letterbox);
+}
+
 extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *cam_frame, int always_use_expand_framing)
 {
 	/* context values */
@@ -351,6 +444,7 @@
 			rasterizer->SetBackColor(scene->gm.framing.col[0], scene->gm.framing.col[1], scene->gm.framing.col[2], 0.0f);
 		}
 		
+		char *python_main = NULL;
 		if (exitrequested != KX_EXIT_REQUEST_QUIT_GAME)
 		{
 			if (rv3d->persp != RV3D_CAMOB)
@@ -445,72 +539,48 @@
 				// Could be in StartEngine set the framerate, we need the scene to do this
 				ketsjiengine->SetAnimFrameRate(FPS);
 				
+				char *python_main = NULL;
+				pynextframestate.state = NULL;
+				pynextframestate.func = NULL;
+#ifdef WITH_PYTHON
+				python_main = KX_GetPythonMain(scene);
+#endif // WITH_PYTHON
 				// the mainloop
 				printf("\nBlender Game Engine Started\n");
-				while (!exitrequested)
-				{
-					// first check if we want to exit
-					exitrequested = ketsjiengine->GetExitCode();
-					
-					// kick the engine
-					bool render = ketsjiengine->NextFrame();
-					
-					if (render)
+				if (python_main) {
+					char *python_code = KX_GetPythonCode(blenderdata, python_main);
+					if (python_code) {
+#ifdef WITH_PYTHON			    
+						ketsjinextframestate.ketsjiengine = ketsjiengine;
+						ketsjinextframestate.C = C;
+						ketsjinextframestate.win = win;
+						ketsjinextframestate.scene = scene;
+						ketsjinextframestate.ar = ar;
+						ketsjinextframestate.keyboarddevice = keyboarddevice;
+						ketsjinextframestate.mousedevice = mousedevice;
+						ketsjinextframestate.draw_letterbox = draw_letterbox;
+			
+						pynextframestate.state = &ketsjinextframestate;
+						pynextframestate.func = &BL_KetsjiPyNextFrame;			
+						printf("Yielding control to Python script '%s'...\n", python_main);
+						PyRun_SimpleString(python_code);
+						printf("Exit Python script '%s'\n", python_main);
+#endif // WITH_PYTHON				
+						MEM_freeN(python_code);
+					}				
+				}
+				else {
+					while (!exitrequested)
 					{
-						if (draw_letterbox) {
-							// Clear screen to border color
-							// We do this here since we set the canvas to be within the frames. This means the engine
-							// itself is unaware of the extra space, so we clear the whole region for it.
-							glClearColor(scene->gm.framing.col[0], scene->gm.framing.col[1], scene->gm.framing.col[2], 1.0f);
-							glViewport(ar->winrct.xmin, ar->winrct.ymin,
-								ar->winrct.xmax - ar->winrct.xmin, ar->winrct.ymax - ar->winrct.ymin);
-							glClear(GL_COLOR_BUFFER_BIT);
-						}
-
-						// render the frame
-						ketsjiengine->Render();
+						exitrequested = BL_KetsjiNextFrame(ketsjiengine, C, win, scene, ar, keyboarddevice, mousedevice, draw_letterbox);
 					}
-					
-					wm_window_process_events_nosleep();
-					
-					// test for the ESC key
-					//XXX while (qtest())
-					while(wmEvent *event= (wmEvent *)win->queue.first)
-					{
-						short val = 0;
-						//unsigned short event = 0; //XXX extern_qread(&val);
-						
-						if (keyboarddevice->ConvertBlenderEvent(event->type,event->val))
-							exitrequested = KX_EXIT_REQUEST_BLENDER_ESC;
-						
-							/* Coordinate conversion... where
-							* should this really be?
-						*/
-						if (event->type==MOUSEMOVE) {
-							/* Note, not nice! XXX 2.5 event hack */
-							val = event->x - ar->winrct.xmin;
-							mousedevice->ConvertBlenderEvent(MOUSEX, val);
-							
-							val = ar->winy - (event->y - ar->winrct.ymin) - 1;
-							mousedevice->ConvertBlenderEvent(MOUSEY, val);
-						}
-						else {
-							mousedevice->ConvertBlenderEvent(event->type,event->val);
-						}
-						
-						BLI_remlink(&win->queue, event);
-						wm_event_free(event);
-					}
-					
-					if (win != CTX_wm_window(C)) {
-						exitrequested= KX_EXIT_REQUEST_OUTSIDE; /* window closed while bge runs */
-					}
 				}
 				printf("Blender Game Engine Finished\n");
 				exitstring = ketsjiengine->GetExitString();
+				if (python_main) MEM_freeN(python_main);
+
 				gs = *(ketsjiengine->GetGlobalSettings());
 
-
 				// when exiting the mainloop
 #ifdef WITH_PYTHON
 				// Clears the dictionary by hand:

Modified: branches/soc-2012-swiss_cheese/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
===================================================================
--- branches/soc-2012-swiss_cheese/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp	2012-05-27 17:34:10 UTC (rev 47083)
+++ branches/soc-2012-swiss_cheese/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp	2012-05-27 17:39:13 UTC (rev 47084)
@@ -47,6 +47,7 @@
 #endif // __APPLE__
 #include "KX_KetsjiEngine.h"
 #include "KX_PythonInit.h"
+#include "KX_PythonMain.h"
 
 /**********************************
 * Begin Blender include block
@@ -333,6 +334,40 @@
 	return bfd;
 }
 
+bool GPG_NextFrame(GHOST_ISystem* system, GPG_Application *app, int &exitcode, STR_String &exitstring, GlobalSettings *gs)
+{
+    bool run = true;
+    system->processEvents(false);
+    system->dispatchEvents();
+    if ((exitcode = app->getExitRequested()))
+    {
+        run = false;
+        exitstring = app->getExitString();
+        *gs = *app->getGlobalSettings();
+    }
+    return run;
+}
+
+struct GPG_NextFrameState {
+	GHOST_ISystem* system;
+	GPG_Application *app;
+	GlobalSettings *gs;
+} gpg_nextframestate;
+
+int GPG_PyNextFrame(void *state0)
+{
+	GPG_NextFrameState *state = (GPG_NextFrameState *) state0;
+	int exitcode;
+	STR_String exitstring;
+	bool run = GPG_NextFrame(state->system, state->app, exitcode, exitstring, state->gs);
+	if (run) return 0;  
+	else {
+		if (exitcode) 
+			fprintf(stderr, "Exit code %d: %s\n", exitcode, exitstring.ReadPtr());
+		return 1;
+	}
+}
+
 int main(int argc, char** argv)
 {
 	int i;
@@ -967,15 +1002,39 @@
 						
 						// Enter main loop
 						bool run = true;
-						while (run)
+                        char *python_main = NULL;
+						pynextframestate.state = NULL;
+						pynextframestate.func = NULL;
+#ifdef WITH_PYTHON
+						python_main = KX_GetPythonMain(scene);
+#endif // WITH_PYTHON
+						if (python_main) 
 						{
-							system->processEvents(false);
-							system->dispatchEvents();
-							if ((exitcode = app.getExitRequested()))
+							char *python_code = KX_GetPythonCode(maggie, python_main);
+							if (python_code)
 							{
-								run = false;
-								exitstring = app.getExitString();
-								gs = *app.getGlobalSettings();
+#ifdef WITH_PYTHON			    
+								gpg_nextframestate.system = system;
+								gpg_nextframestate.app = &app;
+								gpg_nextframestate.gs = &gs;
+								pynextframestate.state = &gpg_nextframestate;
+								pynextframestate.func = &GPG_PyNextFrame;			
+

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list