Patch [#26799] 2.5x blenderplayer (BGE) anti-aliasing & embedding by Sebastian Korcza...
[blender-staging.git] / source / gameengine / GamePlayer / ghost / GPG_ghost.cpp
1 /*
2 * $Id$
3 *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28 * Start up of the Blender Player on GHOST.
29 */
30
31 /** \file gameengine/GamePlayer/ghost/GPG_ghost.cpp
32  *  \ingroup player
33  */
34
35
36 #include <iostream>
37 #include <math.h>
38
39 #ifdef __linux__
40 #ifdef __alpha__
41 #include <signal.h>
42 #endif /* __alpha__ */
43 #endif /* __linux__ */
44
45 #ifdef __APPLE__
46 // Can't use Carbon right now because of double defined type ID (In Carbon.h and DNA_ID.h, sigh)
47 //#include <Carbon/Carbon.h>
48 //#include <CFBundle.h>
49 #endif // __APPLE__
50 #include "GEN_messaging.h"
51 #include "KX_KetsjiEngine.h"
52 #include "KX_PythonInit.h"
53
54 /**********************************
55 * Begin Blender include block
56 **********************************/
57 #ifdef __cplusplus
58 extern "C"
59 {
60 #endif  // __cplusplus
61 #include "MEM_guardedalloc.h"
62 #include "BKE_blender.h"        
63 #include "BKE_global.h" 
64 #include "BKE_icons.h"  
65 #include "BKE_node.h"   
66 #include "BKE_report.h" 
67 #include "BLI_blenlib.h"
68 #include "DNA_scene_types.h"
69 #include "DNA_userdef_types.h"
70 #include "BLO_readfile.h"
71 #include "BLO_readblenfile.h"
72 #include "IMB_imbuf.h"
73 #include "BKE_text.h"
74         
75         int GHOST_HACK_getFirstFile(char buf[]);
76         
77 extern char bprogname[];        /* holds a copy of argv[0], from creator.c */
78 extern char btempdir[];         /* use this to store a valid temp directory */
79
80 // For BLF
81 #include "BLF_api.h"
82 extern int datatoc_bfont_ttf_size;
83 extern char datatoc_bfont_ttf[];
84
85 #ifdef __cplusplus
86 }
87 #endif // __cplusplus
88
89 #include "GPU_draw.h"
90
91 /**********************************
92 * End Blender include block
93 **********************************/
94
95 #include "SYS_System.h"
96 #include "GPG_Application.h"
97
98 #include "GHOST_ISystem.h"
99 #include "RAS_IRasterizer.h"
100
101 #include "BKE_main.h"
102 #include "BKE_utildefines.h"
103
104 #include "RNA_define.h"
105
106 #ifdef WIN32
107 #include <windows.h>
108 #if !defined(DEBUG)
109 #include <wincon.h>
110 #endif // !defined(DEBUG)
111 #endif // WIN32
112
113 const int kMinWindowWidth = 100;
114 const int kMinWindowHeight = 100;
115
116 char bprogname[FILE_MAX];
117
118 static void mem_error_cb(const char *errorStr)
119 {
120         fprintf(stderr, "%s", errorStr);
121         fflush(stderr);
122 }
123
124 #ifdef WIN32
125 typedef enum 
126 {
127   SCREEN_SAVER_MODE_NONE = 0,
128   SCREEN_SAVER_MODE_PREVIEW,
129   SCREEN_SAVER_MODE_SAVER,
130   SCREEN_SAVER_MODE_CONFIGURATION,
131   SCREEN_SAVER_MODE_PASSWORD,
132 } ScreenSaverMode;
133
134 static ScreenSaverMode scr_saver_mode = SCREEN_SAVER_MODE_NONE;
135 static HWND scr_saver_hwnd = NULL;
136
137 static BOOL scr_saver_init(int argc, char **argv) 
138 {
139         scr_saver_mode = SCREEN_SAVER_MODE_NONE;
140         scr_saver_hwnd = NULL;
141         BOOL ret = FALSE;
142
143         int len = ::strlen(argv[0]);
144         if (len > 4 && !::stricmp(".scr", argv[0] + len - 4))
145         {
146                 scr_saver_mode = SCREEN_SAVER_MODE_CONFIGURATION;
147                 ret = TRUE;
148                 if (argc >= 2)
149                 {
150                         if (argc >= 3)
151                         {
152                                 scr_saver_hwnd = (HWND) ::atoi(argv[2]);
153                         }
154                         if (!::stricmp("/c", argv[1]))
155                         {
156                                 scr_saver_mode = SCREEN_SAVER_MODE_CONFIGURATION;
157                                 if (scr_saver_hwnd == NULL)
158                                         scr_saver_hwnd = ::GetForegroundWindow();
159                         }
160                         else if (!::stricmp("/s", argv[1]))
161                         {
162                                 scr_saver_mode = SCREEN_SAVER_MODE_SAVER;
163                         }
164                         else if (!::stricmp("/a", argv[1]))
165                         {
166                                 scr_saver_mode = SCREEN_SAVER_MODE_PASSWORD;
167                         }
168                         else if (!::stricmp("/p", argv[1])
169                                  || !::stricmp("/l", argv[1]))
170                         {
171                                 scr_saver_mode = SCREEN_SAVER_MODE_PREVIEW;
172                         }
173                 }
174         }
175         return ret;
176 }
177
178 #endif /* WIN32 */
179
180 void usage(const char* program, bool isBlenderPlayer)
181 {
182         const char * consoleoption;
183         const char * filename = "";
184         const char * pathname = "";
185
186 #ifdef _WIN32
187         consoleoption = "-c ";
188 #else
189         consoleoption = "";
190 #endif
191
192         if (isBlenderPlayer) {
193                 filename = "filename.blend";
194 #ifdef _WIN32
195                 pathname = "c:\\";
196 #else
197                 pathname = "//home//user//";
198 #endif
199         }
200         
201         printf("usage:   %s [-w [w h l t]] [-f [fw fh fb ff]] %s[-g gamengineoptions] "
202                 "[-s stereomode] [-m aasamples] %s\n", program, consoleoption, filename);
203         printf("  -h: Prints this command summary\n\n");
204         printf("  -w: display in a window\n");
205         printf("       --Optional parameters--\n"); 
206         printf("       w = window width\n");
207         printf("       h = window height\n\n");
208         printf("       l = window left coordinate\n");
209         printf("       t = window top coordinate\n");
210         printf("       Note: If w or h is defined, both must be defined.\n");
211         printf("          Also, if l or t is defined, all options must be used.\n\n");
212         printf("  -f: start game in full screen mode\n");
213         printf("       --Optional parameters--\n");
214         printf("       fw = full screen mode pixel width\n");
215         printf("       fh = full screen mode pixel height\n\n");
216         printf("       fb = full screen mode bits per pixel\n");
217         printf("       ff = full screen mode frequency\n");
218         printf("       Note: If fw or fh is defined, both must be defined.\n");
219         printf("          Also, if fb is used, fw and fh must be used. ff requires all options.\n\n");
220         printf("  -s: start player in stereo\n");
221         printf("       stereomode: hwpageflip       (Quad buffered shutter glasses)\n");
222         printf("                   syncdoubling     (Above Below)\n");
223         printf("                   sidebyside       (Left Right)\n");
224         printf("                   anaglyph         (Red-Blue glasses)\n");
225         printf("                   vinterlace       (Vertical interlace for autostereo display)\n");
226         printf("                             depending on the type of stereo you want\n\n");
227         printf("  -D: start player in dome mode\n");
228         printf("       --Optional parameters--\n");
229         printf("       angle    = field of view in degrees\n");
230         printf("       tilt     = tilt angle in degrees\n");
231         printf("       warpdata = a file to use for warping the image (absolute path)\n");      
232         printf("       mode: fisheye                (Fisheye)\n");
233         printf("             truncatedfront         (Front-Truncated)\n");
234         printf("             truncatedrear          (Rear-Truncated)\n");
235         printf("             cubemap                (Cube Map)\n");
236         printf("             sphericalpanoramic     (Spherical Panoramic)\n");
237         printf("                             depending on the type of dome you are using\n\n");
238         printf("  -m: maximum anti-aliasing (eg. 2,4,8,16)\n\n");
239         printf("  -i: parent windows ID \n\n");
240 #ifdef _WIN32
241         printf("  -c: keep console window open\n\n");
242 #endif
243         printf("  -d: turn debugging on\n\n");
244         printf("  -g: game engine options:\n\n");
245         printf("       Name                       Default      Description\n");
246         printf("       ------------------------------------------------------------------------\n");
247         printf("       fixedtime                      0         \"Enable all frames\"\n");
248         printf("       nomipmap                       0         Disable mipmaps\n");
249         printf("       show_framerate                 0         Show the frame rate\n");
250         printf("       show_properties                0         Show debug properties\n");
251         printf("       show_profile                   0         Show profiling information\n");
252         printf("       blender_material               0         Enable material settings\n");
253         printf("       ignore_deprecation_warnings    1         Ignore deprecation warnings\n");
254         printf("\n");
255         printf("  - : all arguments after this are ignored, allowing python to access them from sys.argv\n");
256         printf("\n");
257         printf("example: %s -w 320 200 10 10 -g noaudio%s%s\n", program, pathname, filename);
258         printf("example: %s -g show_framerate = 0 %s%s\n", program, pathname, filename);
259         printf("example: %s -i 232421 -m 16 %s%s\n\n", program, pathname, filename);
260 }
261
262 static void get_filename(int argc, char **argv, char *filename)
263 {
264 #ifdef __APPLE__
265 /* On Mac we park the game file (called game.blend) in the application bundle.
266 * The executable is located in the bundle as well.
267 * Therefore, we can locate the game relative to the executable.
268         */
269         int srclen = ::strlen(argv[0]);
270         int len = 0;
271         char *gamefile = NULL;
272         
273         filename[0] = '\0';
274
275         if (argc > 1) {
276                 if (BLI_exists(argv[argc-1])) {
277                         BLI_strncpy(filename, argv[argc-1], FILE_MAXDIR + FILE_MAXFILE);
278                 }
279                 if (::strncmp(argv[argc-1], "-psn_", 5)==0) {
280                         static char firstfilebuf[512];
281                         if (GHOST_HACK_getFirstFile(firstfilebuf)) {
282                                 BLI_strncpy(filename, firstfilebuf, FILE_MAXDIR + FILE_MAXFILE);
283                         }
284                 }                        
285         }
286         
287         srclen -= ::strlen("MacOS/blenderplayer");
288         if (srclen > 0) {
289                 len = srclen + ::strlen("Resources/game.blend"); 
290                 gamefile = new char [len + 1];
291                 ::strcpy(gamefile, argv[0]);
292                 ::strcpy(gamefile + srclen, "Resources/game.blend");
293                 //::printf("looking for file: %s\n", filename);
294                 
295                 if (BLI_exists(gamefile))
296                         BLI_strncpy(filename, gamefile, FILE_MAXDIR + FILE_MAXFILE);
297
298                 delete [] gamefile;
299         }
300         
301 #else
302         filename[0] = '\0';
303
304         if(argc > 1)
305                 BLI_strncpy(filename, argv[argc-1], FILE_MAXDIR + FILE_MAXFILE);
306 #endif // !_APPLE
307 }
308
309 static BlendFileData *load_game_data(char *progname, char *filename = NULL, char *relativename = NULL)
310 {
311         ReportList reports;
312         BlendFileData *bfd = NULL;
313
314         BKE_reports_init(&reports, RPT_STORE);
315         
316         /* try to load ourself, will only work if we are a runtime */
317         if (blo_is_a_runtime(progname)) {
318                 bfd= blo_read_runtime(progname, &reports);
319                 if (bfd) {
320                         bfd->type= BLENFILETYPE_RUNTIME;
321                         strcpy(bfd->main->name, progname);
322                 }
323         } else {
324                 bfd= BLO_read_from_file(progname, &reports);
325         }
326         
327         if (!bfd && filename) {
328                 bfd = load_game_data(filename);
329                 if (!bfd) {
330                         printf("Loading %s failed: ", filename);
331                         BKE_reports_print(&reports, RPT_ERROR);
332                 }
333         }
334
335         BKE_reports_clear(&reports);
336         
337         return bfd;
338 }
339
340 int main(int argc, char** argv)
341 {
342         int i;
343         int argc_py_clamped= argc; /* use this so python args can be added after ' - ' */
344         bool error = false;
345         SYS_SystemHandle syshandle = SYS_GetSystem();
346         bool fullScreen = false;
347         bool fullScreenParFound = false;
348         bool windowParFound = false;
349         bool closeConsole = true;
350         RAS_IRasterizer::StereoMode stereomode = RAS_IRasterizer::RAS_STEREO_NOSTEREO;
351         bool stereoWindow = false;
352         bool stereoParFound = false;
353         int stereoFlag = STEREO_NOSTEREO;
354         int domeFov = -1;
355         int domeTilt = -200;
356         int domeMode = 0;
357         char* domeWarp = NULL;
358         Text *domeText  = NULL;
359         int windowLeft = 100;
360         int windowTop = 100;
361         int windowWidth = 640;
362         int windowHeight = 480;
363         GHOST_TUns32 fullScreenWidth = 0;
364         GHOST_TUns32 fullScreenHeight= 0;
365         int fullScreenBpp = 32;
366         int fullScreenFrequency = 60;
367         GHOST_TEmbedderWindowID parentWindow = 0;
368         bool isBlenderPlayer = false;
369         int validArguments=0;
370         GHOST_TUns16 aasamples = 0;
371         
372 #ifdef __linux__
373 #ifdef __alpha__
374         signal (SIGFPE, SIG_IGN);
375 #endif /* __alpha__ */
376 #endif /* __linux__ */
377         BLI_where_am_i(bprogname, sizeof(bprogname), argv[0]);
378 #ifdef __APPLE__
379     // Can't use Carbon right now because of double defined type ID (In Carbon.h and DNA_ID.h, sigh)
380     /*
381     IBNibRef            nibRef;
382     WindowRef           window;
383     OSStatus            err;
384         
385           // Create a Nib reference passing the name of the nib file (without the .nib extension)
386           // CreateNibReference only searches into the application bundle.
387           err = ::CreateNibReference(CFSTR("main"), &nibRef);
388           if (err) return -1;
389           
390                 // Once the nib reference is created, set the menu bar. "MainMenu" is the name of the menu bar
391                 // object. This name is set in InterfaceBuilder when the nib is created.
392                 err = ::SetMenuBarFromNib(nibRef, CFSTR("MenuBar"));
393                 if (err) return -1;
394                 
395                   // We don't need the nib reference anymore.
396                   ::DisposeNibReference(nibRef);
397     */
398 #endif // __APPLE__
399
400         RNA_init();
401
402         init_nodesystem();
403         
404         initglobals();
405
406         GEN_init_messaging_system();
407
408         IMB_init();
409
410         // Setup builtin font for BLF (mostly copied from creator.c, wm_init_exit.c and interface_style.c)
411         BLF_init(11, U.dpi);
412         BLF_lang_init();
413         BLF_load_mem("default", (unsigned char*)datatoc_bfont_ttf, datatoc_bfont_ttf_size);
414  
415         // Parse command line options
416 #if defined(DEBUG)
417         printf("argv[0] = '%s'\n", argv[0]);
418 #endif
419
420 #ifdef WIN32
421         if (scr_saver_init(argc, argv))
422         {
423                 switch (scr_saver_mode)
424                 {
425                 case SCREEN_SAVER_MODE_CONFIGURATION:
426                         MessageBox(scr_saver_hwnd, "This screen saver has no options that you can set", "Screen Saver", MB_OK);
427                         break;
428                 case SCREEN_SAVER_MODE_PASSWORD:
429                         /* This is W95 only, which we currently do not support.
430                            Fall-back to normal screen saver behaviour in that case... */
431                 case SCREEN_SAVER_MODE_SAVER:
432                         fullScreen = true;
433                         fullScreenParFound = true;
434                         break;
435
436                 case SCREEN_SAVER_MODE_PREVIEW:
437                         /* This will actually be handled somewhere below... */
438                         break;
439                 }
440         }
441 #endif
442         // XXX add the ability to change this values to the command line parsing.
443         U.mixbufsize = 2048;
444         U.audiodevice = 2;
445         U.audiorate = 44100;
446         U.audioformat = 0x24;
447         U.audiochannels = 2;
448
449         /* if running blenderplayer the last argument can't be parsed since it has to be the filename. */
450         isBlenderPlayer = !blo_is_a_runtime(argv[0]);
451         if (isBlenderPlayer)
452                 validArguments = argc - 1;
453         else
454                 validArguments = argc;
455
456         for (i = 1; (i < validArguments) && !error 
457 #ifdef WIN32
458                 && scr_saver_mode == SCREEN_SAVER_MODE_NONE
459 #endif
460                 ;)
461
462         {
463 #if defined(DEBUG)
464                 printf("argv[%d] = '%s'   , %i\n", i, argv[i],argc);
465 #endif
466                 if (argv[i][0] == '-')
467                 {
468                         /* ignore all args after " - ", allow python to have own args */
469                         if (argv[i][1]=='\0') {
470                                 argc_py_clamped= i;
471                                 break;
472                         }
473                         
474                         switch (argv[i][1])
475                         {
476                         case 'g':
477                                 // Parse game options
478                                 {
479                                         i++;
480                                         if (i <= validArguments)
481                                         {
482                                                 char* paramname = argv[i];
483                                                 // Check for single value versus assignment
484                                                 if (i+1 <= validArguments && (*(argv[i+1]) == '='))
485                                                 {
486                                                         i++;
487                                                         if (i + 1 <= validArguments)
488                                                         {
489                                                                 i++;
490                                                                 // Assignment
491                                                                 SYS_WriteCommandLineInt(syshandle, paramname, atoi(argv[i]));
492                                                                 SYS_WriteCommandLineFloat(syshandle, paramname, atof(argv[i]));
493                                                                 SYS_WriteCommandLineString(syshandle, paramname, argv[i]);
494 #if defined(DEBUG)
495                                                                 printf("%s = '%s'\n", paramname, argv[i]);
496 #endif
497                                                                 i++;
498                                                         }
499                                                         else
500                                                         {
501                                                                 error = true;
502                                                                 printf("error: argument assignment %s without value.\n", paramname);
503                                                         }
504                                                 }
505                                                 else
506                                                 {
507 //                                                      SYS_WriteCommandLineInt(syshandle, argv[i++], 1);
508                                                 }
509                                         }
510                                 }
511                                 break;
512
513                         case 'd':
514                                 i++;
515                                 G.f |= G_DEBUG;     /* std output printf's */
516                                 MEM_set_memory_debug();
517                                 break;
518
519                         case 'f':
520                                 i++;
521                                 fullScreen = true;
522                                 fullScreenParFound = true;
523                                 if ((i + 2) <= validArguments && argv[i][0] != '-' && argv[i+1][0] != '-')
524                                 {
525                                         fullScreenWidth = atoi(argv[i++]);
526                                         fullScreenHeight = atoi(argv[i++]);
527                                         if ((i + 1) <= validArguments && argv[i][0] != '-')
528                                         {
529                                                 fullScreenBpp = atoi(argv[i++]);
530                                                 if ((i + 1) <= validArguments && argv[i][0] != '-')
531                                                         fullScreenFrequency = atoi(argv[i++]);
532                                         }
533                                 }
534                                 break;
535                         case 'w':
536                                 // Parse window position and size options
537                                 i++;
538                                 fullScreen = false;
539                                 windowParFound = true;
540
541                                 if ((i + 2) <= validArguments && argv[i][0] != '-' && argv[i+1][0] != '-')
542                                 {
543                                         windowWidth = atoi(argv[i++]);
544                                         windowHeight = atoi(argv[i++]);
545                                         if ((i + 2) <= validArguments && argv[i][0] != '-' && argv[i+1][0] != '-')
546                                         {
547                                                 windowLeft = atoi(argv[i++]);
548                                                 windowTop = atoi(argv[i++]);
549                                         }
550                                 }
551                                 break;
552                                         
553                         case 'h':
554                                 usage(argv[0], isBlenderPlayer);
555                                 return 0;
556                                 break;
557                         case 'i':
558                                 i++;
559                                 if ( (i + 1) <= validArguments )
560                                         parentWindow = atoi(argv[i++]); 
561                                 else {
562                                         error = true;
563                                         printf("error: too few options for parent window argument.\n");
564                                 }
565 #if defined(DEBUG)
566                                 printf("XWindows ID = %d\n", parentWindow);
567 #endif // defined(DEBUG)
568                                 break;
569                         case 'm':
570                                 i++;
571                                 if ((i+1) <= validArguments )
572                                 aasamples = atoi(argv[i++]);
573                                 break;
574                         case 'c':
575                                 i++;
576                                 closeConsole = false;
577                                 break;
578                         case 's':  // stereo
579                                 i++;
580                                 if ((i + 1) <= validArguments)
581                                 {
582                                         stereomode = (RAS_IRasterizer::StereoMode) atoi(argv[i]);
583                                         if (stereomode < RAS_IRasterizer::RAS_STEREO_NOSTEREO || stereomode >= RAS_IRasterizer::RAS_STEREO_MAXSTEREO)
584                                                 stereomode = RAS_IRasterizer::RAS_STEREO_NOSTEREO;
585                                         
586                                         if(!strcmp(argv[i], "nostereo"))  // ok, redundant but clear
587                                                 stereomode = RAS_IRasterizer::RAS_STEREO_NOSTEREO;
588                                         
589                                         // only the hardware pageflip method needs a stereo window
590                                         else if(!strcmp(argv[i], "hwpageflip")) {
591                                                 stereomode = RAS_IRasterizer::RAS_STEREO_QUADBUFFERED;
592                                                 stereoWindow = true;
593                                         }
594                                         else if(!strcmp(argv[i], "syncdoubling"))
595                                                 stereomode = RAS_IRasterizer::RAS_STEREO_ABOVEBELOW;
596                                         
597                                         else if(!strcmp(argv[i], "anaglyph"))
598                                                 stereomode = RAS_IRasterizer::RAS_STEREO_ANAGLYPH;
599                                         
600                                         else if(!strcmp(argv[i], "sidebyside"))
601                                                 stereomode = RAS_IRasterizer::RAS_STEREO_SIDEBYSIDE;
602                                         
603                                         else if(!strcmp(argv[i], "vinterlace"))
604                                                 stereomode = RAS_IRasterizer::RAS_STEREO_VINTERLACE;
605                                         
606 #if 0
607                                         // future stuff
608                                         else if(!strcmp(argv[i], "stencil")
609                                                 stereomode = RAS_STEREO_STENCIL;
610 #endif
611                                         
612                                         i++;
613                                         stereoParFound = true;
614                                         stereoFlag = STEREO_ENABLED;
615                                 }
616                                 else
617                                 {
618                                         error = true;
619                                         printf("error: too few options for stereo argument.\n");
620                                 }
621                                 break;
622                         case 'D':
623                                 stereoFlag = STEREO_DOME;
624                                 stereomode = RAS_IRasterizer::RAS_STEREO_DOME;
625                                 i++;
626                                 if ((i + 1) <= validArguments)
627                                 {
628                                         if(!strcmp(argv[i], "angle")){
629                                                 i++;
630                                                 domeFov = atoi(argv[i++]);
631                                         }
632                                         if(!strcmp(argv[i], "tilt")){
633                                                 i++;
634                                                 domeTilt = atoi(argv[i++]);
635                                         }
636                                         if(!strcmp(argv[i], "warpdata")){
637                                                 i++;
638                                                 domeWarp = argv[i++];
639                                         }
640                                         if(!strcmp(argv[i], "mode")){
641                                                 i++;
642                                                 if(!strcmp(argv[i], "fisheye"))
643                                                         domeMode = DOME_FISHEYE;
644                                                         
645                                                 else if(!strcmp(argv[i], "truncatedfront"))
646                                                         domeMode = DOME_TRUNCATED_FRONT;
647                                                         
648                                                 else if(!strcmp(argv[i], "truncatedrear"))
649                                                         domeMode = DOME_TRUNCATED_REAR;
650                                                         
651                                                 else if(!strcmp(argv[i], "cubemap"))
652                                                         domeMode = DOME_ENVMAP;
653                                                         
654                                                 else if(!strcmp(argv[i], "sphericalpanoramic"))
655                                                         domeMode = DOME_PANORAM_SPH;
656
657                                                 else
658                                                         printf("error: %s is not a valid dome mode.\n", argv[i]);
659                                         }
660                                         i++;
661                                 }
662                                 break;
663                         default:
664                                 printf("Unknown argument: %s\n", argv[i++]);
665                                 break;
666                         }
667                 }
668                 else
669                 {
670                         i++;
671                 }
672         }
673         
674         if ((windowWidth < kMinWindowWidth) || (windowHeight < kMinWindowHeight))
675         {
676                 error = true;
677                 printf("error: window size too small.\n");
678         }
679         
680         if (error )
681         {
682                 usage(argv[0], isBlenderPlayer);
683                 return 0;
684         }
685
686 #ifdef WIN32
687         if (scr_saver_mode != SCREEN_SAVER_MODE_CONFIGURATION)
688 #endif
689         {
690 #ifdef __APPLE__
691                 //SYS_WriteCommandLineInt(syshandle, "show_framerate", 1);
692                 //SYS_WriteCommandLineInt(syshandle, "nomipmap", 1);
693                 //fullScreen = false;           // Can't use full screen
694 #endif
695
696                 if (SYS_GetCommandLineInt(syshandle, "nomipmap", 0))
697                 {
698                         GPU_set_mipmap(0);
699                 }
700                 
701                 // Create the system
702                 if (GHOST_ISystem::createSystem() == GHOST_kSuccess)
703                 {
704                         GHOST_ISystem* system = GHOST_ISystem::getSystem();
705                         assertd(system);
706                         
707                         if (!fullScreenWidth || !fullScreenHeight)
708                                 system->getMainDisplayDimensions(fullScreenWidth, fullScreenHeight);
709                         // process first batch of events. If the user
710                         // drops a file on top off the blenderplayer icon, we 
711                         // receive an event with the filename
712                         
713                         system->processEvents(0);
714                         
715                         // this bracket is needed for app (see below) to get out
716                         // of scope before GHOST_ISystem::disposeSystem() is called.
717                         {
718                                 int exitcode = KX_EXIT_REQUEST_NO_REQUEST;
719                                 STR_String exitstring = "";
720                                 GPG_Application app(system);
721                                 bool firstTimeRunning = true;
722                                 char filename[FILE_MAXDIR + FILE_MAXFILE];
723                                 char pathname[FILE_MAXDIR + FILE_MAXFILE];
724                                 char *titlename;
725
726                                 get_filename(argc_py_clamped, argv, filename);
727                                 if(filename[0])
728                                         BLI_path_cwd(filename);
729                                 
730                                 do
731                                 {
732                                         // Read the Blender file
733                                         BlendFileData *bfd;
734                                         
735                                         // if we got an exitcode 3 (KX_EXIT_REQUEST_START_OTHER_GAME) load a different file
736                                         if (exitcode == KX_EXIT_REQUEST_START_OTHER_GAME)
737                                         {
738                                                 char basedpath[240];
739                                                 
740                                                 // base the actuator filename relative to the last file
741                                                 strcpy(basedpath, exitstring.Ptr());
742                                                 BLI_path_abs(basedpath, pathname);
743                                                 
744                                                 bfd = load_game_data(basedpath);
745
746                                                 if (!bfd)
747                                                 {
748                                                         // just add "//" in front of it
749                                                         char temppath[242];
750                                                         strcpy(temppath, "//");
751                                                         strcat(temppath, basedpath);
752                                 
753                                                         BLI_path_abs(temppath, pathname);
754                                                         bfd = load_game_data(temppath);
755                                                 }
756                                         }
757                                         else
758                                         {
759                                                 bfd = load_game_data(bprogname, filename[0]? filename: NULL);
760                                         }
761                                         
762                                         //::printf("game data loaded from %s\n", filename);
763                                         
764                                         if (!bfd) {
765                                                 usage(argv[0], isBlenderPlayer);
766                                                 error = true;
767                                                 exitcode = KX_EXIT_REQUEST_QUIT_GAME;
768                                         } 
769                                         else 
770                                         {
771 #ifdef WIN32
772 #if !defined(DEBUG)
773                                                 if (closeConsole)
774                                                 {
775                                                         //::FreeConsole();    // Close a console window
776                                                 }
777 #endif // !defined(DEBUG)
778 #endif // WIN32
779                                                 Main *maggie = bfd->main;
780                                                 Scene *scene = bfd->curscene;
781                                                 G.main = maggie;
782
783                                                 if (firstTimeRunning)
784                                                         G.fileflags  = bfd->fileflags;
785
786                                                 //Seg Fault; icon.c gIcons == 0
787                                                 BKE_icons_init(1);
788                                                 
789                                                 titlename = maggie->name;
790                                                 
791                                                 // Check whether the game should be displayed full-screen
792                                                 if ((!fullScreenParFound) && (!windowParFound))
793                                                 {
794                                                         // Only use file settings when command line did not override
795                                                         if (scene->gm.fullscreen) {
796                                                                 //printf("fullscreen option found in Blender file\n");
797                                                                 fullScreen = true;
798                                                                 fullScreenWidth= scene->gm.xplay;
799                                                                 fullScreenHeight= scene->gm.yplay;
800                                                                 fullScreenFrequency= scene->gm.freqplay;
801                                                                 fullScreenBpp = scene->gm.depth;
802                                                         }
803                                                         else
804                                                         {
805                                                                 fullScreen = false;
806                                                                 windowWidth = scene->gm.xplay;
807                                                                 windowHeight = scene->gm.yplay;
808                                                         }
809                                                 }
810                                                 
811                                                 
812                                                 // Check whether the game should be displayed in stereo
813                                                 if (!stereoParFound)
814                                                 {
815                                                         if(scene->gm.stereoflag == STEREO_ENABLED){
816                                                                 stereomode = (RAS_IRasterizer::StereoMode) scene->gm.stereomode;
817                                                                 if (stereomode != RAS_IRasterizer::RAS_STEREO_QUADBUFFERED)
818                                                                         stereoWindow = true;
819                                                         }
820                                                 }
821                                                 else
822                                                         scene->gm.stereoflag = STEREO_ENABLED;
823
824                                                 if (stereoFlag == STEREO_DOME){
825                                                         stereomode = RAS_IRasterizer::RAS_STEREO_DOME;
826                                                         scene->gm.stereoflag = STEREO_DOME;
827                                                         if (domeFov > 89)
828                                                                 scene->gm.dome.angle = domeFov;
829                                                         if (domeTilt > -180)
830                                                                 scene->gm.dome.tilt = domeTilt;
831                                                         if (domeMode > 0)
832                                                                 scene->gm.dome.mode = domeMode;
833                                                         if (domeWarp)
834                                                         {
835                                                                 //XXX to do: convert relative to absolute path
836                                                                 domeText= add_text(domeWarp, "");
837                                                                 if(!domeText)
838                                                                         printf("error: invalid warpdata text file - %s\n", domeWarp);
839                                                                 else
840                                                                         scene->gm.dome.warptext = domeText;
841                                                         }
842                                                 }
843                                                 
844                                                 //                                      GPG_Application app (system, maggie, startscenename);
845                                                 app.SetGameEngineData(maggie, scene, argc, argv); /* this argc cant be argc_py_clamped, since python uses it */
846                                                 BLI_strncpy(pathname, maggie->name, sizeof(pathname));
847                                                 if(G.main != maggie) {
848                                                         BLI_strncpy(G.main->name, maggie->name, sizeof(G.main->name));
849                                                 }
850 #ifdef WITH_PYTHON
851                                                 setGamePythonPath(G.main->name);
852 #endif
853                                                 if (firstTimeRunning)
854                                                 {
855                                                         firstTimeRunning = false;
856
857                                                         if (fullScreen)
858                                                         {
859 #ifdef WIN32
860                                                                 if (scr_saver_mode == SCREEN_SAVER_MODE_SAVER)
861                                                                 {
862                                                                         app.startScreenSaverFullScreen(fullScreenWidth, fullScreenHeight, fullScreenBpp, fullScreenFrequency,
863                                                                                 stereoWindow, stereomode, aasamples);
864                                                                 }
865                                                                 else
866 #endif
867                                                                 {
868                                                                         app.startFullScreen(fullScreenWidth, fullScreenHeight, fullScreenBpp, fullScreenFrequency,
869                                                                                 stereoWindow, stereomode, aasamples);
870                                                                 }
871                                                         }
872                                                         else
873                                                         {
874 #ifdef __APPLE__
875                                                                 // on Mac's we'll show the executable name instead of the 'game.blend' name
876                                                                 char tempname[1024], *appstring;
877                                                                 ::strcpy(tempname, titlename);
878                                                                 
879                                                                 appstring = strstr(tempname, ".app/");
880                                                                 if (appstring) {
881                                                                         appstring[2] = 0;
882                                                                         titlename = &tempname[0];
883                                                                 }
884 #endif
885                                                                 // Strip the path so that we have the name of the game file
886                                                                 STR_String path = titlename;
887 #ifndef WIN32
888                                                                 vector<STR_String> parts = path.Explode('/');
889 #else  // WIN32
890                                                                 vector<STR_String> parts = path.Explode('\\');
891 #endif // WIN32                        
892                                                                 STR_String title;
893                                                                 if (parts.size())
894                                                                 {
895                                                                         title = parts[parts.size()-1];
896                                                                         parts = title.Explode('.');
897                                                                         if (parts.size() > 1)
898                                                                         {
899                                                                                 title = parts[0];
900                                                                         }
901                                                                 }
902                                                                 else
903                                                                 {
904                                                                         title = "blenderplayer";
905                                                                 }
906 #ifdef WIN32
907                                                                 if (scr_saver_mode == SCREEN_SAVER_MODE_PREVIEW)
908                                                                 {
909                                                                         app.startScreenSaverPreview(scr_saver_hwnd, stereoWindow, stereomode, aasamples);
910                                                                 }
911                                                                 else
912 #endif
913                                                                 {
914                                                                                                                                                                                                                 if (parentWindow != 0)
915                                                                                 app.startEmbeddedWindow(title, parentWindow, stereoWindow, stereomode, aasamples);
916                                                                         else
917                                                                                 app.startWindow(title, windowLeft, windowTop, windowWidth, windowHeight,
918                                                                                 stereoWindow, stereomode, aasamples);
919                                                                 }
920                                                         }
921                                                 }
922                                                 else
923                                                 {
924                                                         app.StartGameEngine(stereomode);
925                                                         exitcode = KX_EXIT_REQUEST_NO_REQUEST;
926                                                 }
927                                                 
928                                                 // Add the application as event consumer
929                                                 system->addEventConsumer(&app);
930                                                 
931                                                 // Enter main loop
932                                                 bool run = true;
933                                                 while (run)
934                                                 {
935                                                         system->processEvents(false);
936                                                         system->dispatchEvents();
937                                                         if ((exitcode = app.getExitRequested()))
938                                                         {
939                                                                 run = false;
940                                                                 exitstring = app.getExitString();
941                                                         }
942                                                 }
943                                                 app.StopGameEngine();
944
945                                                 /* 'app' is freed automatic when out of scope. 
946                                                  * removal is needed else the system will free an already freed value */
947                                                 system->removeEventConsumer(&app);
948
949                                                 BLO_blendfiledata_free(bfd);
950                                         }
951                                 } while (exitcode == KX_EXIT_REQUEST_RESTART_GAME || exitcode == KX_EXIT_REQUEST_START_OTHER_GAME);
952                         }
953
954                         // Seg Fault; icon.c gIcons == 0
955                         BKE_icons_free();
956
957                         // Dispose the system
958                         GHOST_ISystem::disposeSystem();
959                 } else {
960                         error = true;
961                         printf("error: couldn't create a system.\n");
962                 }
963         }
964
965         // Cleanup
966         RNA_exit();
967         BLF_exit();
968         IMB_exit();
969         free_nodesystem();
970
971         SYS_DeleteSystem(syshandle);
972
973         int totblock= MEM_get_memory_blocks_in_use();
974         if(totblock!=0) {
975                 printf("Error Totblock: %d\n",totblock);
976                 MEM_set_error_callback(mem_error_cb);
977                 MEM_printmemlist();
978         }
979
980         return error ? -1 : 0;
981 }
982
983