2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19 * All rights reserved.
21 * The Original Code is: all of this file.
23 * Contributor(s): none yet.
25 * ***** END GPL LICENSE BLOCK *****
26 * Start up of the Blender Player on GHOST.
29 /** \file gameengine/GamePlayer/ghost/GPG_ghost.cpp
40 #endif /* __alpha__ */
41 #endif /* __linux__ */
43 #include "KX_KetsjiEngine.h"
44 #include "KX_PythonInit.h"
45 #include "KX_PythonMain.h"
46 #include "KX_PyConstraintBinding.h" // for PHY_SetActiveEnvironment
48 /**********************************
49 * Begin Blender include block
50 **********************************/
55 #include "MEM_guardedalloc.h"
56 #include "MEM_CacheLimiterC-Api.h"
58 #include "BLI_threads.h"
59 #include "BLI_mempool.h"
60 #include "BLI_blenlib.h"
62 #include "DNA_scene_types.h"
63 #include "DNA_userdef_types.h"
64 #include "DNA_genfile.h"
66 #include "BLO_readfile.h"
67 #include "BLO_runtime.h"
69 #include "BKE_appdir.h"
70 #include "BKE_blender.h"
71 #include "BKE_global.h"
72 #include "BKE_icons.h"
73 #include "BKE_image.h"
75 #include "BKE_report.h"
76 #include "BKE_library.h"
77 #include "BKE_library_remap.h"
78 #include "BKE_modifier.h"
79 #include "BKE_material.h"
81 #include "BKE_sound.h"
83 #include "DEG_depsgraph.h"
85 #include "IMB_imbuf.h"
86 #include "IMB_moviecache.h"
89 int GHOST_HACK_getFirstFile(char buf[]);
94 #include "BLT_translation.h"
96 extern int datatoc_bfont_ttf_size;
97 extern char datatoc_bfont_ttf[];
98 extern int datatoc_bmonofont_ttf_size;
99 extern char datatoc_bmonofont_ttf[];
103 #endif // __cplusplus
105 #include "GPU_draw.h"
107 /**********************************
108 * End Blender include block
109 **********************************/
111 #include "BL_System.h"
112 #include "GPG_Application.h"
114 #include "GHOST_ISystem.h"
115 #include "RAS_IRasterizer.h"
117 #include "BKE_main.h"
119 #include "RNA_define.h"
122 # include <windows.h>
125 # endif // !defined(DEBUG)
126 # if defined(_MSC_VER) && defined(_M_X64)
127 # include <math.h> /* needed for _set_FMA3_enable */
129 # include "utfconv.h"
132 #ifdef WITH_SDL_DYNLOAD
136 const int kMinWindowWidth = 100;
137 const int kMinWindowHeight = 100;
139 static void mem_error_cb(const char *errorStr)
141 fprintf(stderr, "%s", errorStr);
145 // library.c will only free window managers with a callback function.
146 // We don't actually use a wmWindowManager, but loading a blendfile
147 // loads wmWindows, so we need to free those.
148 static void wm_free(bContext *C, wmWindowManager *wm)
150 BLI_freelistN(&wm->windows);
155 SCREEN_SAVER_MODE_NONE = 0,
156 SCREEN_SAVER_MODE_PREVIEW,
157 SCREEN_SAVER_MODE_SAVER,
158 SCREEN_SAVER_MODE_CONFIGURATION,
159 SCREEN_SAVER_MODE_PASSWORD,
162 static ScreenSaverMode scr_saver_mode = SCREEN_SAVER_MODE_NONE;
163 static HWND scr_saver_hwnd = NULL;
165 static BOOL scr_saver_init(int argc, char **argv)
167 scr_saver_mode = SCREEN_SAVER_MODE_NONE;
168 scr_saver_hwnd = NULL;
171 int len = ::strlen(argv[0]);
172 if (len > 4 && !::stricmp(".scr", argv[0] + len - 4))
174 scr_saver_mode = SCREEN_SAVER_MODE_CONFIGURATION;
180 scr_saver_hwnd = (HWND) ::atoi(argv[2]);
182 if (!::stricmp("/c", argv[1]))
184 scr_saver_mode = SCREEN_SAVER_MODE_CONFIGURATION;
185 if (scr_saver_hwnd == NULL)
186 scr_saver_hwnd = ::GetForegroundWindow();
188 else if (!::stricmp("/s", argv[1]))
190 scr_saver_mode = SCREEN_SAVER_MODE_SAVER;
192 else if (!::stricmp("/a", argv[1]))
194 scr_saver_mode = SCREEN_SAVER_MODE_PASSWORD;
196 else if (!::stricmp("/p", argv[1])
197 || !::stricmp("/l", argv[1]))
199 scr_saver_mode = SCREEN_SAVER_MODE_PREVIEW;
208 static void usage(const char* program, bool isBlenderPlayer)
210 const char * consoleoption;
211 const char * example_filename = "";
212 const char * example_pathname = "";
215 consoleoption = "[-c] ";
220 if (isBlenderPlayer) {
221 example_filename = "filename.blend";
223 example_pathname = "c:\\";
225 example_pathname = "/home/user/";
229 printf("usage: %s [--options] %s\n\n", program, example_filename);
230 printf("Available options are: [-w [w h l t]] [-f [fw fh fb ff]] %s[-g gamengineoptions] ", consoleoption);
231 printf("[-s stereomode] [-m aasamples]\n");
232 printf("Optional parameters must be passed in order.\n");
233 printf("Default values are set in the blend file.\n\n");
234 printf(" -h: Prints this command summary\n\n");
235 printf(" -w: display in a window\n");
236 printf(" --Optional parameters--\n");
237 printf(" w = window width\n");
238 printf(" h = window height\n");
239 printf(" l = window left coordinate\n");
240 printf(" t = window top coordinate\n");
241 printf(" Note: To define 'w' or 'h', both must be used.");
242 printf("Also, to define 'l' or 't', all four parameters must be used.\n");
243 printf(" Example: -w or -w 500 300 or -w 500 300 0 0\n\n");
244 printf(" -f: start game in fullscreen mode\n");
245 printf(" --Optional parameters--\n");
246 printf(" fw = fullscreen mode pixel width (use 0 to detect automatically)\n");
247 printf(" fh = fullscreen mode pixel height (use 0 to detect automatically)\n");
248 printf(" fb = fullscreen mode bits per pixel (default unless set in the blend file: 32)\n");
249 printf(" ff = fullscreen mode frequency (default unless set in the blend file: 60)\n");
250 printf(" Note: To define 'fw'' or 'fh'', both must be used.\n");
251 printf(" Example: -f or -f 1024 768 or -f 0 0 16 or -f 1024 728 16 30\n\n");
252 printf(" -s: start player in stereoscopy mode (requires 3D capable hardware)\n");
253 printf(" stereomode: nostereo (default unless stereo is set in the blend file)\n");
254 printf(" anaglyph (Red-Blue glasses)\n");
255 printf(" sidebyside (Left Right)\n");
256 printf(" syncdoubling (Above Below)\n");
257 printf(" 3dtvtopbottom (Squashed Top-Bottom for passive glasses)\n");
258 printf(" interlace (Interlace horizontally)\n");
259 printf(" vinterlace (Vertical interlace for autostereo display)\n");
260 printf(" hwpageflip (Quad buffered shutter glasses)\n");
261 printf(" Example: -s sidebyside or -s vinterlace\n\n");
262 printf(" -D: start player in dome mode\n");
263 printf(" --Optional parameters--\n");
264 printf(" angle = field of view in degrees\n");
265 printf(" tilt = tilt angle in degrees\n");
266 printf(" warpdata = a file to use for warping the image (absolute path)\n");
267 printf(" mode: fisheye (Fisheye)\n");
268 printf(" truncatedfront (Front-Truncated)\n");
269 printf(" truncatedrear (Rear-Truncated)\n");
270 printf(" cubemap (Cube Map)\n");
271 printf(" sphericalpanoramic (Spherical Panoramic)\n");
272 printf(" Example: -D or -D mode cubemap\n\n");
273 printf(" -m: maximum anti-aliasing (eg. 2,4,8,16)\n\n");
274 printf(" -i: parent window's ID\n\n");
276 printf(" -c: keep console window open\n\n");
278 printf(" -d: turn debugging on\n\n");
279 printf(" -g: game engine options:\n\n");
280 printf(" Name Default Description\n");
281 printf(" ------------------------------------------------------------------------\n");
282 printf(" fixedtime 0 \"Enable all frames\"\n");
283 printf(" nomipmap 0 Disable mipmaps\n");
284 printf(" show_framerate 0 Show the frame rate\n");
285 printf(" show_properties 0 Show debug properties\n");
286 printf(" show_profile 0 Show profiling information\n");
287 printf(" blender_material 0 Enable material settings\n");
288 printf(" ignore_deprecation_warnings 1 Ignore deprecation warnings\n");
290 printf(" - : all arguments after this are ignored, allowing python to access them from sys.argv\n");
292 printf("example: %s -w 320 200 10 10 -g noaudio %s%s\n", program, example_pathname, example_filename);
293 printf("example: %s -g show_framerate = 0 %s%s\n", program, example_pathname, example_filename);
294 printf("example: %s -i 232421 -m 16 %s%s\n\n", program, example_pathname, example_filename);
297 static void get_filename(int argc, char **argv, char *filename)
300 /* On Mac we park the game file (called game.blend) in the application bundle.
301 * The executable is located in the bundle as well.
302 * Therefore, we can locate the game relative to the executable.
304 int srclen = ::strlen(argv[0]);
306 char *gamefile = NULL;
311 if (BLI_exists(argv[argc-1])) {
312 BLI_strncpy(filename, argv[argc-1], FILE_MAX);
314 if (::strncmp(argv[argc-1], "-psn_", 5)==0) {
315 static char firstfilebuf[512];
316 if (GHOST_HACK_getFirstFile(firstfilebuf)) {
317 BLI_strncpy(filename, firstfilebuf, FILE_MAX);
322 srclen -= ::strlen("MacOS/blenderplayer");
324 len = srclen + ::strlen("Resources/game.blend");
325 gamefile = new char [len + 1];
326 ::strcpy(gamefile, argv[0]);
327 ::strcpy(gamefile + srclen, "Resources/game.blend");
328 //::printf("looking for file: %s\n", filename);
330 if (BLI_exists(gamefile))
331 BLI_strncpy(filename, gamefile, FILE_MAX);
340 BLI_strncpy(filename, argv[argc-1], FILE_MAX);
344 static BlendFileData *load_game_data(const char *progname, char *filename = NULL, char *relativename = NULL)
347 BlendFileData *bfd = NULL;
349 BKE_reports_init(&reports, RPT_STORE);
351 /* try to load ourself, will only work if we are a runtime */
352 if (BLO_is_a_runtime(progname)) {
353 bfd= BLO_read_runtime(progname, &reports);
355 bfd->type= BLENFILETYPE_RUNTIME;
356 BLI_strncpy(bfd->main->name, progname, sizeof(bfd->main->name));
359 bfd= BLO_read_from_file(progname, &reports, BLO_READ_SKIP_NONE);
362 if (!bfd && filename) {
363 bfd = load_game_data(filename);
365 printf("Loading %s failed: ", filename);
366 BKE_reports_print(&reports, RPT_ERROR);
370 BKE_reports_clear(&reports);
375 static bool GPG_NextFrame(GHOST_ISystem* system, GPG_Application *app, int &exitcode, STR_String &exitstring, GlobalSettings *gs)
378 system->processEvents(false);
379 system->dispatchEvents();
380 app->EngineNextFrame();
381 if ((exitcode = app->getExitRequested())) {
383 exitstring = app->getExitString();
384 *gs = *app->getGlobalSettings();
389 struct GPG_NextFrameState {
390 GHOST_ISystem* system;
391 GPG_Application *app;
393 } gpg_nextframestate;
395 static int GPG_PyNextFrame(void *state0)
397 GPG_NextFrameState *state = (GPG_NextFrameState *) state0;
399 STR_String exitstring;
400 bool run = GPG_NextFrame(state->system, state->app, exitcode, exitstring, state->gs);
404 fprintf(stderr, "Exit code %d: %s\n", exitcode, exitstring.ReadPtr());
412 char **UNUSED(argv_c)
419 int argc_py_clamped= argc; /* use this so python args can be added after ' - ' */
421 SYS_SystemHandle syshandle = SYS_GetSystem();
422 bool fullScreen = false;
423 bool fullScreenParFound = false;
424 bool windowParFound = false;
426 bool closeConsole = true;
428 RAS_IRasterizer::StereoMode stereomode = RAS_IRasterizer::RAS_STEREO_NOSTEREO;
429 bool stereoWindow = false;
430 bool stereoParFound = false;
431 int stereoFlag = STEREO_NOSTEREO;
435 char* domeWarp = NULL;
436 Text *domeText = NULL;
437 int windowLeft = 100;
439 int windowWidth = 640;
440 int windowHeight = 480;
441 GHOST_TUns32 fullScreenWidth = 0;
442 GHOST_TUns32 fullScreenHeight= 0;
443 int fullScreenBpp = 32;
444 int fullScreenFrequency = 60;
445 GHOST_TEmbedderWindowID parentWindow = 0;
446 bool isBlenderPlayer = false; //true when lauching from blender or command line. false for bundled player
447 int validArguments=0;
448 bool samplesParFound = false;
449 GHOST_TUns16 aasamples = 0;
450 int alphaBackground = 0;
456 /* We delay loading of openmp so we can set the policy here. */
457 # if defined(_MSC_VER)
458 _putenv_s("OMP_WAIT_POLICY", "PASSIVE");
461 /* FMA3 support in the 2013 CRT is broken on Vista and Windows 7 RTM (fixed in SP1). Just disable it. */
462 # if defined(_MSC_VER) && defined(_M_X64)
466 /* Win32 Unicode Args */
467 /* NOTE: cannot use guardedalloc malloc here, as it's not yet initialized
468 * (it depends on the args passed in, which is what we're getting here!)
471 wchar_t **argv_16 = CommandLineToArgvW(GetCommandLineW(), &argc);
472 argv = (char**)malloc(argc * sizeof(char *));
473 for (argv_num = 0; argv_num < argc; argv_num++) {
474 argv[argv_num] = alloc_utf_8_from_16(argv_16[argv_num], 0);
482 signal (SIGFPE, SIG_IGN);
483 #endif /* __alpha__ */
484 #endif /* __linux__ */
486 #ifdef WITH_SDL_DYNLOAD
490 BKE_appdir_program_path_init(argv[0]);
491 BKE_tempdir_init(NULL);
493 // We don't use threads directly in the BGE, but we need to call this so things like
494 // freeing up GPU_Textures works correctly.
495 BLI_threadapi_init();
497 DNA_sdna_current_init();
503 BKE_blender_globals_init();
505 // We load our own G.main, so free the one that BKE_blender_globals_init() gives us
506 BKE_main_free(G.main);
509 MEM_CacheLimiter_set_disabled(true);
513 DEG_register_node_types();
519 // Setup builtin font for BLF (mostly copied from creator.c, wm_init_exit.c and interface_style.c)
524 BLF_load_mem("default", (unsigned char*)datatoc_bfont_ttf, datatoc_bfont_ttf_size);
525 if (blf_mono_font == -1)
526 blf_mono_font = BLF_load_mem_unique("monospace", (unsigned char*)datatoc_bmonofont_ttf, datatoc_bmonofont_ttf_size);
528 // Parse command line options
530 printf("argv[0] = '%s'\n", argv[0]);
534 if (scr_saver_init(argc, argv))
536 switch (scr_saver_mode)
538 case SCREEN_SAVER_MODE_CONFIGURATION:
539 MessageBox(scr_saver_hwnd, "This screen saver has no options that you can set", "Screen Saver", MB_OK);
541 case SCREEN_SAVER_MODE_PASSWORD:
542 /* This is W95 only, which we currently do not support.
543 * Fall-back to normal screen saver behavior in that case... */
544 case SCREEN_SAVER_MODE_SAVER:
546 fullScreenParFound = true;
549 case SCREEN_SAVER_MODE_PREVIEW:
550 /* This will actually be handled somewhere below... */
555 // XXX add the ability to change this values to the command line parsing.
559 U.audioformat = 0x24;
563 U.anisotropic_filter = 2;
564 // enable fast mipmap generation
565 U.use_gpu_mipmap = 1;
567 BKE_sound_init_once();
569 // Initialize a default material for meshes without materials.
572 BKE_library_callback_free_window_manager_set(wm_free);
574 /* if running blenderplayer the last argument can't be parsed since it has to be the filename. else it is bundled */
575 isBlenderPlayer = !BLO_is_a_runtime(argv[0]);
577 validArguments = argc - 1;
579 validArguments = argc;
582 /* Parsing command line arguments (can be set from WM_OT_blenderplayer_start) */
584 printf("Parsing command line arguments...\n");
585 printf("Num of arguments is: %i\n", validArguments-1); //-1 because i starts at 1
588 for (i = 1; (i < validArguments) && !error
590 && scr_saver_mode == SCREEN_SAVER_MODE_NONE
596 printf("argv[%d] = '%s'\n", i, argv[i]);
598 if (argv[i][0] == '-')
600 /* ignore all args after " - ", allow python to have own args */
601 if (argv[i][1]=='\0') {
608 case 'g': //game engine options (show_framerate, fixedtime, etc)
611 if (i <= validArguments)
613 char* paramname = argv[i];
614 // Check for single value versus assignment
615 if (i+1 <= validArguments && (*(argv[i+1]) == '='))
618 if (i + 1 <= validArguments)
622 SYS_WriteCommandLineInt(syshandle, paramname, atoi(argv[i]));
623 SYS_WriteCommandLineFloat(syshandle, paramname, atof(argv[i]));
624 SYS_WriteCommandLineString(syshandle, paramname, argv[i]);
626 printf("%s = '%s'\n", paramname, argv[i]);
633 printf("error: argument assignment %s without value.\n", paramname);
638 // SYS_WriteCommandLineInt(syshandle, argv[i++], 1);
647 MEM_set_memory_debug();
649 BLI_mempool_set_memory_debug();
653 case 'f': //fullscreen mode
657 fullScreenParFound = true;
658 if ((i + 2) <= validArguments && argv[i][0] != '-' && argv[i+1][0] != '-')
660 fullScreenWidth = atoi(argv[i++]);
661 fullScreenHeight = atoi(argv[i++]);
662 if ((i + 1) <= validArguments && argv[i][0] != '-')
664 fullScreenBpp = atoi(argv[i++]);
665 if ((i + 1) <= validArguments && argv[i][0] != '-')
666 fullScreenFrequency = atoi(argv[i++]);
669 else if ((i + 1) <= validArguments && argv[i][0] != '-' && argv[i+1][0] != '-')
672 printf("error: to define fullscreen width or height, both options must be used.\n");
676 case 'w': //display in a window
680 windowParFound = true;
682 // Parse window position and size options
683 if ((i + 2) <= validArguments && argv[i][0] != '-' && argv[i+1][0] != '-')
685 windowWidth = atoi(argv[i++]);
686 windowHeight = atoi(argv[i++]);
688 if ((i + 2) <= validArguments && argv[i][0] != '-' && argv[i+1][0] != '-')
690 windowLeft = atoi(argv[i++]);
691 windowTop = atoi(argv[i++]);
693 else if ((i + 1) <= validArguments && argv[i][0] != '-' && argv[i+1][0] != '-')
696 printf("error: to define the window left or right coordinates, both options must be used.\n");
699 else if ((i + 1) <= validArguments && argv[i][0] != '-' && argv[i+1][0] != '-')
702 printf("error: to define the window's width or height, both options must be used.\n");
706 case 'h': //display help
708 usage(argv[0], isBlenderPlayer);
712 case 'i': //parent window ID
715 if ( (i + 1) <= validArguments )
716 parentWindow = (GHOST_TEmbedderWindowID)atoll(argv[i++]);
719 printf("error: too few options for parent window argument.\n");
722 printf("XWindows ID = %d\n", parentWindow);
723 #endif // defined(DEBUG)
726 case 'm': //maximum anti-aliasing (eg. 2,4,8,16)
729 samplesParFound = true;
730 if ((i+1) <= validArguments )
731 aasamples = atoi(argv[i++]);
735 printf("error: No argument supplied for -m");
739 case 'c': //keep console (windows only)
743 closeConsole = false;
747 case 's': //stereo mode
750 if ((i + 1) <= validArguments)
752 stereoParFound = true;
753 stereoFlag = STEREO_ENABLED;
755 if (!strcmp(argv[i], "nostereo")) // may not be redundant if the file has different setting
757 stereomode = RAS_IRasterizer::RAS_STEREO_NOSTEREO;
758 stereoFlag = STEREO_NOSTEREO;
761 // only the hardware pageflip method needs a stereo window
762 else if (!strcmp(argv[i], "hwpageflip")) {
763 stereomode = RAS_IRasterizer::RAS_STEREO_QUADBUFFERED;
766 else if (!strcmp(argv[i], "syncdoubling"))
767 stereomode = RAS_IRasterizer::RAS_STEREO_ABOVEBELOW;
769 else if (!strcmp(argv[i], "3dtvtopbottom"))
770 stereomode = RAS_IRasterizer::RAS_STEREO_3DTVTOPBOTTOM;
772 else if (!strcmp(argv[i], "anaglyph"))
773 stereomode = RAS_IRasterizer::RAS_STEREO_ANAGLYPH;
775 else if (!strcmp(argv[i], "sidebyside"))
776 stereomode = RAS_IRasterizer::RAS_STEREO_SIDEBYSIDE;
778 else if (!strcmp(argv[i], "interlace"))
779 stereomode = RAS_IRasterizer::RAS_STEREO_INTERLACED;
781 else if (!strcmp(argv[i], "vinterlace"))
782 stereomode = RAS_IRasterizer::RAS_STEREO_VINTERLACE;
786 // else if (!strcmp(argv[i], "stencil")
787 // stereomode = RAS_STEREO_STENCIL;
792 printf("error: stereomode '%s' unrecognized.\n", argv[i]);
800 printf("error: too few options for stereo argument.\n");
804 case 'D': //dome mode
806 stereoFlag = STEREO_DOME;
807 stereomode = RAS_IRasterizer::RAS_STEREO_DOME;
809 if ((i + 1) <= validArguments)
811 if (!strcmp(argv[i], "angle")) {
813 domeFov = atoi(argv[i++]);
815 if (!strcmp(argv[i], "tilt")) {
817 domeTilt = atoi(argv[i++]);
819 if (!strcmp(argv[i], "warpdata")) {
821 domeWarp = argv[i++];
823 if (!strcmp(argv[i], "mode")) {
825 if (!strcmp(argv[i], "fisheye"))
826 domeMode = DOME_FISHEYE;
828 else if (!strcmp(argv[i], "truncatedfront"))
829 domeMode = DOME_TRUNCATED_FRONT;
831 else if (!strcmp(argv[i], "truncatedrear"))
832 domeMode = DOME_TRUNCATED_REAR;
834 else if (!strcmp(argv[i], "cubemap"))
835 domeMode = DOME_ENVMAP;
837 else if (!strcmp(argv[i], "sphericalpanoramic"))
838 domeMode = DOME_PANORAM_SPH;
841 printf("error: %s is not a valid dome mode.\n", argv[i]);
847 case 'a': // allow window to blend with display background
853 default: //not recognized
855 printf("Unknown argument: %s\n", argv[i++]);
866 if ((windowWidth < kMinWindowWidth) || (windowHeight < kMinWindowHeight))
869 printf("error: window size too small.\n");
874 usage(argv[0], isBlenderPlayer);
879 if (scr_saver_mode != SCREEN_SAVER_MODE_CONFIGURATION)
883 if (GHOST_ISystem::createSystem() == GHOST_kSuccess) {
884 GHOST_ISystem* system = GHOST_ISystem::getSystem();
887 if (!fullScreenWidth || !fullScreenHeight)
888 system->getMainDisplayDimensions(fullScreenWidth, fullScreenHeight);
889 // process first batch of events. If the user
890 // drops a file on top off the blenderplayer icon, we
891 // receive an event with the filename
893 system->processEvents(0);
895 // this bracket is needed for app (see below) to get out
896 // of scope before GHOST_ISystem::disposeSystem() is called.
898 int exitcode = KX_EXIT_REQUEST_NO_REQUEST;
899 STR_String exitstring = "";
900 GPG_Application app(system);
901 bool firstTimeRunning = true;
902 char filename[FILE_MAX];
903 char pathname[FILE_MAX];
906 get_filename(argc_py_clamped, argv, filename);
908 BLI_path_cwd(filename, sizeof(filename));
911 // fill the GlobalSettings with the first scene files
912 // those may change during the game and persist after using Game Actuator
916 // Read the Blender file
919 // if we got an exitcode 3 (KX_EXIT_REQUEST_START_OTHER_GAME) load a different file
920 if (exitcode == KX_EXIT_REQUEST_START_OTHER_GAME)
922 char basedpath[FILE_MAX];
924 // base the actuator filename relative to the last file
925 BLI_strncpy(basedpath, exitstring.Ptr(), sizeof(basedpath));
926 BLI_path_abs(basedpath, pathname);
928 bfd = load_game_data(basedpath);
931 // just add "//" in front of it
932 char temppath[FILE_MAX] = "//";
933 BLI_strncpy(temppath + 2, basedpath, FILE_MAX - 2);
935 BLI_path_abs(temppath, pathname);
936 bfd = load_game_data(temppath);
940 bfd = load_game_data(BKE_appdir_program_path(), filename[0]? filename: NULL);
944 printf("Game data loaded from %s\n", filename);
948 usage(argv[0], isBlenderPlayer);
950 exitcode = KX_EXIT_REQUEST_QUIT_GAME;
953 /* Setting options according to the blend file if not overriden in the command line */
957 system->toggleConsole(0); // Close a console window
959 #endif // !defined(DEBUG)
961 Main *maggie = bfd->main;
962 Scene *scene = bfd->curscene;
965 if (firstTimeRunning) {
966 G.fileflags = bfd->fileflags;
968 gs.matmode= scene->gm.matmode;
969 gs.glslflag= scene->gm.flag;
972 //Seg Fault; icon.c gIcons == 0
975 titlename = maggie->name;
977 // Check whether the game should be displayed full-screen
978 if ((!fullScreenParFound) && (!windowParFound)) {
979 // Only use file settings when command line did not override
980 if ((scene->gm.playerflag & GAME_PLAYER_FULLSCREEN)) {
981 //printf("fullscreen option found in Blender file\n");
983 fullScreenWidth= scene->gm.xplay;
984 fullScreenHeight= scene->gm.yplay;
985 fullScreenFrequency= scene->gm.freqplay;
986 fullScreenBpp = scene->gm.depth;
991 windowWidth = scene->gm.xplay;
992 windowHeight = scene->gm.yplay;
997 // Check whether the game should be displayed in stereo (dome included)
998 if (!stereoParFound) {
999 // Only use file settings when command line did not override
1000 if (scene->gm.stereoflag == STEREO_ENABLED) {
1001 stereomode = (RAS_IRasterizer::StereoMode) scene->gm.stereomode;
1002 if (stereomode == RAS_IRasterizer::RAS_STEREO_QUADBUFFERED)
1003 stereoWindow = true;
1007 scene->gm.stereoflag = STEREO_ENABLED;
1010 if (!samplesParFound)
1011 aasamples = scene->gm.aasamples;
1013 // Dome specific settings
1014 if (stereoFlag == STEREO_DOME) {
1015 stereomode = RAS_IRasterizer::RAS_STEREO_DOME;
1016 scene->gm.stereoflag = STEREO_DOME;
1018 scene->gm.dome.angle = domeFov;
1019 if (domeTilt > -180)
1020 scene->gm.dome.tilt = domeTilt;
1022 scene->gm.dome.mode = domeMode;
1024 //XXX to do: convert relative to absolute path
1025 domeText= BKE_text_load(G.main, domeWarp, "");
1027 printf("error: invalid warpdata text file - %s\n", domeWarp);
1029 scene->gm.dome.warptext = domeText;
1033 // GPG_Application app (system, maggie, startscenename);
1034 app.SetGameEngineData(maggie, scene, &gs, argc, argv); /* this argc cant be argc_py_clamped, since python uses it */
1035 BLI_strncpy(pathname, maggie->name, sizeof(pathname));
1036 if (G.main != maggie) {
1037 BLI_strncpy(G.main->name, maggie->name, sizeof(G.main->name));
1040 setGamePythonPath(G.main->name);
1042 if (firstTimeRunning) {
1043 firstTimeRunning = false;
1047 if (scr_saver_mode == SCREEN_SAVER_MODE_SAVER)
1049 app.startScreenSaverFullScreen(fullScreenWidth, fullScreenHeight, fullScreenBpp, fullScreenFrequency,
1050 stereoWindow, stereomode, aasamples);
1055 app.startFullScreen(fullScreenWidth, fullScreenHeight, fullScreenBpp, fullScreenFrequency,
1056 stereoWindow, stereomode, alphaBackground, aasamples, (scene->gm.playerflag & GAME_PLAYER_DESKTOP_RESOLUTION));
1062 // on Mac's we'll show the executable name instead of the 'game.blend' name
1063 char tempname[1024], *appstring;
1064 ::strcpy(tempname, titlename);
1066 appstring = strstr(tempname, ".app/");
1069 titlename = &tempname[0];
1072 // Strip the path so that we have the name of the game file
1073 STR_String path = titlename;
1075 vector<STR_String> parts = path.Explode('/');
1077 vector<STR_String> parts = path.Explode('\\');
1081 title = parts[parts.size()-1];
1082 parts = title.Explode('.');
1083 if (parts.size() > 1)
1089 title = "blenderplayer";
1092 if (scr_saver_mode == SCREEN_SAVER_MODE_PREVIEW)
1094 app.startScreenSaverPreview(scr_saver_hwnd, stereoWindow, stereomode, aasamples);
1099 if (parentWindow != 0)
1100 app.startEmbeddedWindow(title, parentWindow, stereoWindow, stereomode, aasamples);
1102 app.startWindow(title, windowLeft, windowTop, windowWidth, windowHeight,
1103 stereoWindow, stereomode, alphaBackground, aasamples);
1105 if (SYS_GetCommandLineInt(syshandle, "nomipmap", 0)) {
1109 GPU_set_anisotropic(U.anisotropic_filter);
1110 GPU_set_gpu_mipmapping(U.use_gpu_mipmap);
1115 app.StartGameEngine(stereomode);
1116 exitcode = KX_EXIT_REQUEST_NO_REQUEST;
1119 // Add the application as event consumer
1120 system->addEventConsumer(&app);
1124 char *python_main = NULL;
1125 pynextframestate.state = NULL;
1126 pynextframestate.func = NULL;
1128 python_main = KX_GetPythonMain(scene);
1129 #endif // WITH_PYTHON
1131 char *python_code = KX_GetPythonCode(maggie, python_main);
1134 // Set python environement variable.
1135 KX_Scene *startscene = app.GetStartScene();
1136 KX_SetActiveScene(startscene);
1137 PHY_SetActiveEnvironment(startscene->GetPhysicsEnvironment());
1139 gpg_nextframestate.system = system;
1140 gpg_nextframestate.app = &app;
1141 gpg_nextframestate.gs = &gs;
1142 pynextframestate.state = &gpg_nextframestate;
1143 pynextframestate.func = &GPG_PyNextFrame;
1145 printf("Yielding control to Python script '%s'...\n", python_main);
1146 PyRun_SimpleString(python_code);
1147 printf("Exit Python script '%s'\n", python_main);
1148 #endif // WITH_PYTHON
1149 MEM_freeN(python_code);
1152 fprintf(stderr, "ERROR: cannot yield control to Python: no Python text data-block named '%s'\n", python_main);
1157 run = GPG_NextFrame(system, &app, exitcode, exitstring, &gs);
1160 app.StopGameEngine();
1162 /* 'app' is freed automatic when out of scope.
1163 * removal is needed else the system will free an already freed value */
1164 system->removeEventConsumer(&app);
1166 BLO_blendfiledata_free(bfd);
1167 /* G.main == bfd->main, it gets referenced in free_nodesystem so we can't have a dangling pointer */
1169 if (python_main) MEM_freeN(python_main);
1171 } while (exitcode == KX_EXIT_REQUEST_RESTART_GAME || exitcode == KX_EXIT_REQUEST_START_OTHER_GAME);
1174 // Seg Fault; icon.c gIcons == 0
1177 // Dispose the system
1178 GHOST_ISystem::disposeSystem();
1182 printf("error: couldn't create a system.\n");
1186 /* refer to WM_exit_ext() and BKE_blender_free(),
1187 * these are not called in the player but we need to match some of there behavior here,
1188 * if the order of function calls or blenders state isn't matching that of blender proper,
1189 * we may get troubles later on */
1197 #ifdef WITH_INTERNATIONAL
1199 BLF_free_unifont_mono();
1205 DEG_free_node_types();
1206 IMB_moviecache_destruct();
1208 SYS_DeleteSystem(syshandle);
1210 int totblock= MEM_get_memory_blocks_in_use();
1212 printf("Error Totblock: %d\n",totblock);
1213 MEM_set_error_callback(mem_error_cb);
1217 BKE_tempdir_session_purge();
1221 free(argv[--argv_num]);
1227 return error ? -1 : 0;