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