warning fixes.
[blender-staging.git] / source / creator / creator.c
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  */
29
30 #if defined(__linux__) && defined(__GNUC__)
31 #define _GNU_SOURCE
32 #include <fenv.h>
33 #endif
34
35 #define OSX_SSE_FPE (defined(__APPLE__) && (defined(__i386__) || defined(__x86_64__)))
36
37 #if OSX_SSE_FPE
38 #include <xmmintrin.h>
39 #endif
40
41 #include <stdlib.h>
42 #include <string.h>
43
44 /* for setuid / getuid */
45 #ifdef __sgi
46 #include <sys/types.h>
47 #include <unistd.h>
48 #endif
49
50 /* This little block needed for linking to Blender... */
51
52 #include "MEM_guardedalloc.h"
53
54 #ifdef WIN32
55 #include "BLI_winstuff.h"
56 #endif
57
58 #include "BLI_args.h"
59 #include "BLI_threads.h"
60
61 #include "GEN_messaging.h"
62
63 #include "DNA_ID.h"
64 #include "DNA_scene_types.h"
65
66 #include "BLI_blenlib.h"
67
68 #include "BKE_utildefines.h"
69 #include "BKE_blender.h"
70 #include "BKE_context.h"
71 #include "BKE_font.h"
72 #include "BKE_global.h"
73 #include "BKE_main.h"
74 #include "BKE_material.h"
75 #include "BKE_packedFile.h"
76 #include "BKE_scene.h"
77 #include "BKE_node.h"
78 #include "BKE_report.h"
79 #include "BKE_sound.h"
80
81 #include "IMB_imbuf.h"  // for IMB_init
82
83 #ifndef DISABLE_PYTHON
84 #include "BPY_extern.h"
85 #endif
86
87 #include "RE_pipeline.h"
88
89 //XXX #include "playanim_ext.h"
90 #include "ED_datafiles.h"
91
92 #include "WM_api.h"
93
94 #include "RNA_define.h"
95
96 #include "GPU_draw.h"
97 #include "GPU_extensions.h"
98
99 /* for passing information between creator and gameengine */
100 #include "SYS_System.h"
101
102 #include <signal.h>
103
104 #ifdef __FreeBSD__
105 # include <sys/types.h>
106 # include <floatingpoint.h>
107 # include <sys/rtprio.h>
108 #endif
109
110 #ifdef WITH_BINRELOC
111 #include "binreloc.h"
112 #endif
113
114 // from buildinfo.c
115 #ifdef BUILD_DATE
116 extern char build_date[];
117 extern char build_time[];
118 extern char build_rev[];
119 extern char build_platform[];
120 extern char build_type[];
121 extern char build_cflags[];
122 extern char build_cxxflags[];
123 extern char build_linkflags[];
124 extern char build_system[];
125 #endif
126
127 /*      Local Function prototypes */
128 static int print_help(int argc, char **argv, void *data);
129 static int print_version(int argc, char **argv, void *data);
130
131 /* for the callbacks: */
132
133 extern int pluginapi_force_ref(void);  /* from blenpluginapi:pluginapi.c */
134
135 char bprogname[FILE_MAXDIR+FILE_MAXFILE]; /* from blenpluginapi:pluginapi.c */
136 char btempdir[FILE_MAXDIR+FILE_MAXFILE];
137
138 #define BLEND_VERSION_STRING_FMT "Blender %d.%02d (sub %d) Build\n", BLENDER_VERSION/100, BLENDER_VERSION%100, BLENDER_SUBVERSION
139
140 /* Initialise callbacks for the modules that need them */
141 static void setCallbacks(void); 
142
143 /* set breakpoints here when running in debug mode, useful to catch floating point errors */
144 #if defined(__sgi) || defined(__linux__) || defined(_WIN32) || OSX_SSE_FPE
145 static void fpe_handler(int UNUSED(sig))
146 {
147         // printf("SIGFPE trapped\n");
148 }
149 #endif
150
151 /* handling ctrl-c event in console */
152 static void blender_esc(int sig)
153 {
154         static int count = 0;
155         
156         G.afbreek = 1;  /* forces render loop to read queue, not sure if its needed */
157         
158         if (sig == 2) {
159                 if (count) {
160                         printf("\nBlender killed\n");
161                         exit(2);
162                 }
163                 printf("\nSent an internal break event. Press ^C again to kill Blender\n");
164                 count++;
165         }
166 }
167
168 /* buildinfo can have quotes */
169 #ifdef BUILD_DATE
170 static void strip_quotes(char *str)
171 {
172     if(str[0] == '"') {
173         int len= strlen(str) - 1;
174         memmove(str, str+1, len);
175         if(str[len-1] == '"') {
176             str[len-1]= '\0';
177         }
178     }
179 }
180 #endif
181
182 static int print_version(int UNUSED(argc), char **UNUSED(argv), void *UNUSED(data))
183 {
184         printf (BLEND_VERSION_STRING_FMT);
185 #ifdef BUILD_DATE
186         printf ("\tbuild date: %s\n", build_date);
187         printf ("\tbuild time: %s\n", build_time);
188         printf ("\tbuild revision: %s\n", build_rev);
189         printf ("\tbuild platform: %s\n", build_platform);
190         printf ("\tbuild type: %s\n", build_type);
191         printf ("\tbuild c flags: %s\n", build_cflags);
192         printf ("\tbuild c++ flags: %s\n", build_cxxflags);
193         printf ("\tbuild link flags: %s\n", build_linkflags);
194         printf ("\tbuild system: %s\n", build_system);
195 #endif
196         exit(0);
197
198         return 0;
199 }
200
201 static int print_help(int UNUSED(argc), char **UNUSED(argv), void *data)
202 {
203         bArgs *ba = (bArgs*)data;
204
205         printf (BLEND_VERSION_STRING_FMT);
206         printf ("Usage: blender [args ...] [file] [args ...]\n\n");
207
208         printf ("Render Options:\n");
209         BLI_argsPrintArgDoc(ba, "--background");
210         BLI_argsPrintArgDoc(ba, "--render-anim");
211         BLI_argsPrintArgDoc(ba, "--scene");
212         BLI_argsPrintArgDoc(ba, "--render-frame");
213         BLI_argsPrintArgDoc(ba, "--frame-start");
214         BLI_argsPrintArgDoc(ba, "--frame-end");
215         BLI_argsPrintArgDoc(ba, "--frame-jump");
216         BLI_argsPrintArgDoc(ba, "--render-output");
217         BLI_argsPrintArgDoc(ba, "--engine");
218         
219         printf("\n");
220         printf ("Format Options:\n");
221         BLI_argsPrintArgDoc(ba, "--render-format");
222         BLI_argsPrintArgDoc(ba, "--use-extension");
223         BLI_argsPrintArgDoc(ba, "--threads");
224
225         printf("\n");
226         printf ("Animation Playback Options:\n");
227         BLI_argsPrintArgDoc(ba, "-a");
228                                 
229         printf("\n");
230         printf ("Window Options:\n");
231         BLI_argsPrintArgDoc(ba, "--window-border");
232         BLI_argsPrintArgDoc(ba, "--window-borderless");
233         BLI_argsPrintArgDoc(ba, "--window-geometry");
234
235         printf("\n");
236         printf ("Game Engine Specific Options:\n");
237         BLI_argsPrintArgDoc(ba, "-g");
238
239         printf("\n");
240         printf ("Misc Options:\n");
241         BLI_argsPrintArgDoc(ba, "--debug");
242         BLI_argsPrintArgDoc(ba, "--debug-fpe");
243
244         printf("\n");
245
246         BLI_argsPrintArgDoc(ba, "-nojoystick");
247         BLI_argsPrintArgDoc(ba, "-noglsl");
248         BLI_argsPrintArgDoc(ba, "-noaudio");
249         BLI_argsPrintArgDoc(ba, "-setaudio");
250
251         printf("\n");
252
253         BLI_argsPrintArgDoc(ba, "--help");
254
255         printf("\n");
256
257         BLI_argsPrintArgDoc(ba, "--enable-autoexec");
258         BLI_argsPrintArgDoc(ba, "--disable-autoexec");
259
260         printf("\n");
261
262         BLI_argsPrintArgDoc(ba, "--python");
263         BLI_argsPrintArgDoc(ba, "--python-console");
264
265 #ifdef WIN32
266         BLI_argsPrintArgDoc(ba, "-R");
267 #endif
268         BLI_argsPrintArgDoc(ba, "--version");
269
270         BLI_argsPrintArgDoc(ba, "--");
271
272         printf ("Other Options:\n");
273         BLI_argsPrintOtherDoc(ba);
274
275         printf ("Argument Parsing:\n");
276         printf ("\targuments must be separated by white space. eg\n");
277         printf ("\t\t\"blender -ba test.blend\"\n");
278         printf ("\t...will ignore the 'a'\n");
279         printf ("\t\t\"blender -b test.blend -f8\"\n");
280         printf ("\t...will ignore 8 because there is no space between the -f and the frame value\n\n");
281
282         printf ("Argument Order:\n");
283         printf ("Arguments are executed in the order they are given. eg\n");
284         printf ("\t\t\"blender --background test.blend --render-frame 1 --render-output /tmp\"\n");
285         printf ("\t...will not render to /tmp because '--render-frame 1' renders before the output path is set\n");
286         printf ("\t\t\"blender --background --render-output /tmp test.blend --render-frame 1\"\n");
287         printf ("\t...will not render to /tmp because loading the blend file overwrites the render output that was set\n");
288         printf ("\t\t\"blender --background test.blend --render-output /tmp --render-frame 1\" works as expected.\n\n");
289
290         printf ("\nEnvironment Variables:\n");
291         printf ("  $BLENDER_USER_CONFIG      Directory for user configuration files.\n");
292         printf ("  $BLENDER_SYSTEM_CONFIG    Directory for system wide configuration files.\n");
293         printf ("  $BLENDER_USER_SCRIPTS     Directory for user scripts.\n");
294         printf ("  $BLENDER_SYSTEM_SCRIPTS   Directory for system wide scripts.\n");
295         printf ("  $BLENDER_USER_DATAFILES   Directory for user data files (icons, translations, ..).\n");
296         printf ("  $BLENDER_SYSTEM_DATAFILES Directory for system wide data files.\n");
297         printf ("  $BLENDER_SYSTEM_PYTHON    Directory for system python libraries.\n");
298 #ifdef WIN32
299         printf ("  $TEMP                     Store temporary files here.\n");
300 #else
301         printf ("  $TMP or $TMPDIR           Store temporary files here.\n");
302 #endif
303 #ifndef DISABLE_SDL
304         printf ("  $SDL_AUDIODRIVER          LibSDL audio driver - alsa, esd, dma.\n");
305 #endif
306         printf ("  $PYTHONHOME               Path to the python directory, eg. /usr/lib/python.\n\n");
307
308         exit(0);
309
310         return 0;
311 }
312
313
314 double PIL_check_seconds_timer(void);
315
316 /* XXX This was here to fix a crash when running python scripts
317  * with -P that used the screen.
318  *
319  * static void main_init_screen( void )
320 {
321         setscreen(G.curscreen);
322         
323         if(G.main->scene.first==0) {
324                 set_scene( add_scene("1") );
325         }
326 }*/
327
328 static int end_arguments(int UNUSED(argc), char **UNUSED(argv), void *UNUSED(data))
329 {
330         return -1;
331 }
332
333 static int enable_python(int UNUSED(argc), char **UNUSED(argv), void *UNUSED(data))
334 {
335         G.f |= G_SCRIPT_AUTOEXEC;
336         return 0;
337 }
338
339 static int disable_python(int UNUSED(argc), char **UNUSED(argv), void *UNUSED(data))
340 {
341         G.f &= ~G_SCRIPT_AUTOEXEC;
342         return 0;
343 }
344
345 static int background_mode(int UNUSED(argc), char **UNUSED(argv), void *UNUSED(data))
346 {
347         G.background = 1;
348         return 0;
349 }
350
351 static int debug_mode(int UNUSED(argc), char **UNUSED(argv), void *data)
352 {
353         G.f |= G_DEBUG;         /* std output printf's */
354         printf(BLEND_VERSION_STRING_FMT);
355         MEM_set_memory_debug();
356
357 #ifdef NAN_BUILDINFO
358         printf("Build: %s %s %s %s\n", build_date, build_time, build_platform, build_type);
359 #endif // NAN_BUILDINFO
360
361         BLI_argsPrint(data);
362         return 0;
363 }
364
365 static int set_fpe(int UNUSED(argc), char **UNUSED(argv), void *UNUSED(data))
366 {
367 #if defined(__sgi) || defined(__linux__) || defined(_WIN32) || OSX_SSE_FPE
368         /* zealous but makes float issues a heck of a lot easier to find!
369          * set breakpoints on fpe_handler */
370         signal(SIGFPE, fpe_handler);
371
372 # if defined(__linux__) && defined(__GNUC__)
373         feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW );
374 # endif /* defined(__linux__) && defined(__GNUC__) */
375 # if OSX_SSE_FPE
376         /* OSX uses SSE for floating point by default, so here 
377          * use SSE instructions to throw floating point exceptions */
378         _MM_SET_EXCEPTION_MASK(_MM_MASK_MASK &~
379                                                    (_MM_MASK_OVERFLOW|_MM_MASK_INVALID|_MM_MASK_DIV_ZERO));
380 # endif /* OSX_SSE_FPE */
381 # if defined(_WIN32) && defined(_MSC_VER)
382         _controlfp_s(NULL, 0, _MCW_EM); /* enables all fp exceptions */
383         _controlfp_s(NULL, _EM_DENORMAL | _EM_UNDERFLOW | _EM_INEXACT, _MCW_EM); /* hide the ones we don't care about */
384 # endif /* _WIN32 && _MSC_VER */
385 #endif
386
387         return 0;
388 }
389
390 static int playback_mode(int UNUSED(argc), char **UNUSED(argv), void *UNUSED(data))
391 {
392         /* not if -b was given first */
393         if (G.background == 0) {
394
395 // XXX                          playanim(argc, argv); /* not the same argc and argv as before */
396                 exit(0);
397         }
398
399         return -2;
400 }
401
402 static int prefsize(int argc, char **argv, void *UNUSED(data))
403 {
404         int stax, stay, sizx, sizy;
405
406         if (argc < 5) {
407                 printf ("-p requires four arguments\n");
408                 exit(1);
409         }
410
411         stax= atoi(argv[1]);
412         stay= atoi(argv[2]);
413         sizx= atoi(argv[3]);
414         sizy= atoi(argv[4]);
415
416         WM_setprefsize(stax, stay, sizx, sizy);
417
418         return 4;
419 }
420
421 static int with_borders(int UNUSED(argc), char **UNUSED(argv), void *UNUSED(data))
422 {
423         WM_setinitialstate_normal();
424         return 0;
425 }
426
427 static int without_borders(int UNUSED(argc), char **UNUSED(argv), void *UNUSED(data))
428 {
429         WM_setinitialstate_fullscreen();
430         return 0;
431 }
432
433 static int register_extension(int UNUSED(argc), char **UNUSED(argv), void *data)
434 {
435 #ifdef WIN32
436         char *path = BLI_argsArgv(data)[0];
437         RegisterBlendExtension(path);
438 #else
439         (void)data; /* unused */
440 #endif
441
442         return 0;
443 }
444
445 static int no_joystick(int UNUSED(argc), char **UNUSED(argv), void *data)
446 {
447         SYS_SystemHandle *syshandle = data;
448
449         /**
450                 don't initialize joysticks if user doesn't want to use joysticks
451                 failed joystick initialization delays over 5 seconds, before game engine start
452         */
453         SYS_WriteCommandLineInt(*syshandle, "nojoystick",1);
454         if (G.f & G_DEBUG) printf("disabling nojoystick\n");
455
456         return 0;
457 }
458
459 static int no_glsl(int UNUSED(argc), char **UNUSED(argv), void *UNUSED(data))
460 {
461         GPU_extensions_disable();
462         return 0;
463 }
464
465 static int no_audio(int UNUSED(argc), char **UNUSED(argv), void *UNUSED(data))
466 {
467         sound_force_device(0);
468         return 0;
469 }
470
471 static int set_audio(int argc, char **argv, void *UNUSED(data))
472 {
473         if (argc < 1) {
474                 printf("-setaudio require one argument\n");
475                 exit(1);
476         }
477
478         sound_force_device(sound_define_from_str(argv[1]));
479         return 1;
480 }
481
482 static int set_output(int argc, char **argv, void *data)
483 {
484         bContext *C = data;
485         if (argc >= 1){
486                 if (CTX_data_scene(C)) {
487                         Scene *scene= CTX_data_scene(C);
488                         BLI_strncpy(scene->r.pic, argv[1], FILE_MAXDIR);
489                 } else {
490                         printf("\nError: no blend loaded. cannot use '-o / --render-output'.\n");
491                 }
492                 return 1;
493         } else {
494                 printf("\nError: you must specify a path after '-o  / --render-output'.\n");
495                 return 0;
496         }
497 }
498
499 static int set_engine(int argc, char **argv, void *data)
500 {
501         bContext *C = data;
502         if (argc >= 1)
503         {
504                 if (!strcmp(argv[1],"help"))
505                 {
506                         RenderEngineType *type = NULL;
507
508                         for( type = R_engines.first; type; type = type->next )
509                         {
510                                 printf("\t%s\n", type->idname);
511                         }
512                         exit(0);
513                 }
514                 else
515                 {
516                         if (CTX_data_scene(C)==NULL)
517                         {
518                                 printf("\nError: no blend loaded. order the arguments so '-E  / --engine ' is after a blend is loaded.\n");
519                         }
520                         else
521                         {
522                                 Scene *scene= CTX_data_scene(C);
523                                 RenderData *rd = &scene->r;
524                                 RenderEngineType *type = NULL;
525
526                                 for( type = R_engines.first; type; type = type->next )
527                                 {
528                                         if (!strcmp(argv[1],type->idname))
529                                         {
530                                                 BLI_strncpy(rd->engine, type->idname, sizeof(rd->engine));
531                                         }
532                                 }
533                         }
534                 }
535
536                 return 1;
537         }
538         else
539         {
540                 printf("\nEngine not specified.\n");
541                 return 0;
542         }
543 }
544
545 static int set_image_type(int argc, char **argv, void *data)
546 {
547         bContext *C = data;
548         if (argc >= 1){
549                 char *imtype = argv[1];
550                 if (CTX_data_scene(C)==NULL) {
551                         printf("\nError: no blend loaded. order the arguments so '-F  / --render-format' is after the blend is loaded.\n");
552                 } else {
553                         Scene *scene= CTX_data_scene(C);
554                         if      (!strcmp(imtype,"TGA")) scene->r.imtype = R_TARGA;
555                         else if (!strcmp(imtype,"IRIS")) scene->r.imtype = R_IRIS;
556 #ifdef WITH_DDS
557                         else if (!strcmp(imtype,"DDS")) scene->r.imtype = R_DDS;
558 #endif
559                         else if (!strcmp(imtype,"JPEG")) scene->r.imtype = R_JPEG90;
560                         else if (!strcmp(imtype,"IRIZ")) scene->r.imtype = R_IRIZ;
561                         else if (!strcmp(imtype,"RAWTGA")) scene->r.imtype = R_RAWTGA;
562                         else if (!strcmp(imtype,"AVIRAW")) scene->r.imtype = R_AVIRAW;
563                         else if (!strcmp(imtype,"AVIJPEG")) scene->r.imtype = R_AVIJPEG;
564                         else if (!strcmp(imtype,"PNG")) scene->r.imtype = R_PNG;
565                         else if (!strcmp(imtype,"AVICODEC")) scene->r.imtype = R_AVICODEC;
566                         else if (!strcmp(imtype,"QUICKTIME")) scene->r.imtype = R_QUICKTIME;
567                         else if (!strcmp(imtype,"BMP")) scene->r.imtype = R_BMP;
568 #ifdef WITH_HDR
569                         else if (!strcmp(imtype,"HDR")) scene->r.imtype = R_RADHDR;
570 #endif
571 #ifdef WITH_TIFF
572                         else if (!strcmp(imtype,"TIFF")) scene->r.imtype = R_TIFF;
573 #endif
574 #ifdef WITH_OPENEXR
575                         else if (!strcmp(imtype,"EXR")) scene->r.imtype = R_OPENEXR;
576                         else if (!strcmp(imtype,"MULTILAYER")) scene->r.imtype = R_MULTILAYER;
577 #endif
578                         else if (!strcmp(imtype,"MPEG")) scene->r.imtype = R_FFMPEG;
579                         else if (!strcmp(imtype,"FRAMESERVER")) scene->r.imtype = R_FRAMESERVER;
580 #ifdef WITH_CINEON
581                         else if (!strcmp(imtype,"CINEON")) scene->r.imtype = R_CINEON;
582                         else if (!strcmp(imtype,"DPX")) scene->r.imtype = R_DPX;
583 #endif
584 #if WITH_OPENJPEG
585                         else if (!strcmp(imtype,"JP2")) scene->r.imtype = R_JP2;
586 #endif
587                         else printf("\nError: Format from '-F / --render-format' not known or not compiled in this release.\n");
588                 }
589                 return 1;
590         } else {
591                 printf("\nError: you must specify a format after '-F  / --render-foramt'.\n");
592                 return 0;
593         }
594 }
595
596 static int set_threads(int argc, char **argv, void *UNUSED(data))
597 {
598         if (argc >= 1) {
599                 if(G.background) {
600                         RE_set_max_threads(atoi(argv[1]));
601                 } else {
602                         printf("Warning: threads can only be set in background mode\n");
603                 }
604                 return 1;
605         } else {
606                 printf("\nError: you must specify a number of threads between 0 and 8 '-t  / --threads'.\n");
607                 return 0;
608         }
609 }
610
611 static int set_extension(int argc, char **argv, void *data)
612 {
613         bContext *C = data;
614         if (argc >= 1) {
615                 if (CTX_data_scene(C)) {
616                         Scene *scene= CTX_data_scene(C);
617                         if (argv[1][0] == '0') {
618                                 scene->r.scemode &= ~R_EXTENSION;
619                         } else if (argv[1][0] == '1') {
620                                 scene->r.scemode |= R_EXTENSION;
621                         } else {
622                                 printf("\nError: Use '-x 1 / -x 0' To set the extension option or '--use-extension'\n");
623                         }
624                 } else {
625                         printf("\nError: no blend loaded. order the arguments so '-o ' is after '-x '.\n");
626                 }
627                 return 1;
628         } else {
629                 printf("\nError: you must specify a path after '- '.\n");
630                 return 0;
631         }
632 }
633
634 static int set_ge_parameters(int argc, char **argv, void *data)
635 {
636         SYS_SystemHandle syshandle = *(SYS_SystemHandle*)data;
637         int a = 0;
638 /**
639 gameengine parameters are automaticly put into system
640 -g [paramname = value]
641 -g [boolparamname]
642 example:
643 -g novertexarrays
644 -g maxvertexarraysize = 512
645 */
646
647         if(argc >= 1)
648         {
649                 char* paramname = argv[a];
650                 /* check for single value versus assignment */
651                 if (a+1 < argc && (*(argv[a+1]) == '='))
652                 {
653                         a++;
654                         if (a+1 < argc)
655                         {
656                                 a++;
657                                 /* assignment */
658                                 SYS_WriteCommandLineString(syshandle,paramname,argv[a]);
659                         }  else
660                         {
661                                 printf("error: argument assignment (%s) without value.\n",paramname);
662                                 return 0;
663                         }
664                         /* name arg eaten */
665
666                 } else {
667                         SYS_WriteCommandLineInt(syshandle,argv[a],1);
668
669                         /* doMipMap */
670                         if (!strcmp(argv[a],"nomipmap"))
671                         {
672                                 GPU_set_mipmap(0); //doMipMap = 0;
673                         }
674                         /* linearMipMap */
675                         if (!strcmp(argv[a],"linearmipmap"))
676                         {
677                                 GPU_set_linear_mipmap(1); //linearMipMap = 1;
678                         }
679
680
681                 } /* if (*(argv[a+1]) == '=') */
682         }
683
684         return a;
685 }
686
687 static int render_frame(int argc, char **argv, void *data)
688 {
689         bContext *C = data;
690         if (CTX_data_scene(C)) {
691                 Main *bmain= CTX_data_main(C);
692                 Scene *scene= CTX_data_scene(C);
693
694                 if (argc > 1) {
695                         Render *re = RE_NewRender(scene->id.name);
696                         int frame;
697                         ReportList reports;
698
699                         switch(*argv[1]) {
700                         case '+':
701                                 frame= scene->r.sfra + atoi(argv[1]+1);
702                                 break;
703                         case '-':
704                                 frame= (scene->r.efra - atoi(argv[1]+1)) + 1;
705                                 break;
706                         default:
707                                 frame= atoi(argv[1]);
708                                 break;
709                         }
710
711                         BKE_reports_init(&reports, RPT_PRINT);
712
713                         frame = MIN2(MAXFRAME, MAX2(MINAFRAME, frame));
714
715                         RE_BlenderAnim(re, bmain, scene, scene->lay, frame, frame, scene->r.frame_step, &reports);
716                         return 1;
717                 } else {
718                         printf("\nError: frame number must follow '-f / --render-frame'.\n");
719                         return 0;
720                 }
721         } else {
722                 printf("\nError: no blend loaded. cannot use '-f / --render-frame'.\n");
723                 return 0;
724         }
725 }
726
727 static int render_animation(int UNUSED(argc), char **UNUSED(argv), void *data)
728 {
729         bContext *C = data;
730         if (CTX_data_scene(C)) {
731                 Main *bmain= CTX_data_main(C);
732                 Scene *scene= CTX_data_scene(C);
733                 Render *re= RE_NewRender(scene->id.name);
734                 ReportList reports;
735                 BKE_reports_init(&reports, RPT_PRINT);
736                 RE_BlenderAnim(re, bmain, scene, scene->lay, scene->r.sfra, scene->r.efra, scene->r.frame_step, &reports);
737         } else {
738                 printf("\nError: no blend loaded. cannot use '-a'.\n");
739         }
740         return 0;
741 }
742
743 static int set_scene(int argc, char **argv, void *data)
744 {
745         if(argc > 1) {
746                 bContext *C= data;
747                 Scene *sce= set_scene_name(CTX_data_main(C), argv[1]);
748                 if(sce) {
749                         CTX_data_scene_set(C, sce);
750                 }
751                 return 1;
752         } else {
753                 printf("\nError: Scene name must follow '-S / --scene'.\n");
754                 return 0;
755         }
756 }
757
758 static int set_start_frame(int argc, char **argv, void *data)
759 {
760         bContext *C = data;
761         if (CTX_data_scene(C)) {
762                 Scene *scene= CTX_data_scene(C);
763                 if (argc > 1) {
764                         int frame = atoi(argv[1]);
765                         (scene->r.sfra) = CLAMPIS(frame, MINFRAME, MAXFRAME);
766                         return 1;
767                 } else {
768                         printf("\nError: frame number must follow '-s / --frame-start'.\n");
769                         return 0;
770                 }
771         } else {
772                 printf("\nError: no blend loaded. cannot use '-s / --frame-start'.\n");
773                 return 0;
774         }
775 }
776
777 static int set_end_frame(int argc, char **argv, void *data)
778 {
779         bContext *C = data;
780         if (CTX_data_scene(C)) {
781                 Scene *scene= CTX_data_scene(C);
782                 if (argc > 1) {
783                         int frame = atoi(argv[1]);
784                         (scene->r.efra) = CLAMPIS(frame, MINFRAME, MAXFRAME);
785                         return 1;
786                 } else {
787                         printf("\nError: frame number must follow '-e / --frame-end'.\n");
788                         return 0;
789                 }
790         } else {
791                 printf("\nError: no blend loaded. cannot use '-e / --frame-end'.\n");
792                 return 0;
793         }
794 }
795
796 static int set_skip_frame(int argc, char **argv, void *data)
797 {
798         bContext *C = data;
799         if (CTX_data_scene(C)) {
800                 Scene *scene= CTX_data_scene(C);
801                 if (argc > 1) {
802                         int frame = atoi(argv[1]);
803                         (scene->r.frame_step) = CLAMPIS(frame, 1, MAXFRAME);
804                         return 1;
805                 } else {
806                         printf("\nError: number of frames to step must follow '-j / --frame-jump'.\n");
807                         return 0;
808                 }
809         } else {
810                 printf("\nError: no blend loaded. cannot use '-j / --frame-jump'.\n");
811                 return 0;
812         }
813 }
814
815 /* macro for ugly context setup/reset */
816 #ifndef DISABLE_PYTHON
817 #define BPY_CTX_SETUP(_cmd) \
818 { \
819         wmWindowManager *wm= CTX_wm_manager(C); \
820         wmWindow *prevwin= CTX_wm_window(C); \
821         Scene *prevscene= CTX_data_scene(C); \
822         if(wm->windows.first) { \
823                 CTX_wm_window_set(C, wm->windows.first); \
824                 _cmd; \
825                 CTX_wm_window_set(C, prevwin); \
826         } \
827         else { \
828                 fprintf(stderr, "Python script \"%s\" running with missing context data.\n", argv[1]); \
829                 _cmd; \
830         } \
831         CTX_data_scene_set(C, prevscene); \
832 } \
833
834 #endif /* DISABLE_PYTHON */
835
836 static int run_python(int argc, char **argv, void *data)
837 {
838 #ifndef DISABLE_PYTHON
839         bContext *C = data;
840
841         /* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */
842         if (argc > 1) {
843                 /* Make the path absolute because its needed for relative linked blends to be found */
844                 char filename[FILE_MAXDIR + FILE_MAXFILE];
845                 BLI_strncpy(filename, argv[1], sizeof(filename));
846                 BLI_path_cwd(filename);
847
848                 BPY_CTX_SETUP( BPY_run_python_script(C, filename, NULL, NULL) )
849
850                 return 1;
851         } else {
852                 printf("\nError: you must specify a Python script after '-P / --python'.\n");
853                 return 0;
854         }
855 #else
856         (void)argc; (void)argv; (void)data; /* unused */
857         printf("This blender was built without python support\n");
858         return 0;
859 #endif /* DISABLE_PYTHON */
860 }
861
862 static int run_python_console(int UNUSED(argc), char **argv, void *data)
863 {
864 #ifndef DISABLE_PYTHON
865         bContext *C = data;     
866         const char *expr= "__import__('code').interact()";
867
868         BPY_CTX_SETUP( BPY_eval_string(C, expr) )
869
870         return 0;
871 #else
872         (void)argv; (void)data; /* unused */
873         printf("This blender was built without python support\n");
874         return 0;
875 #endif /* DISABLE_PYTHON */
876 }
877
878 static int load_file(int UNUSED(argc), char **argv, void *data)
879 {
880         bContext *C = data;
881
882         /* Make the path absolute because its needed for relative linked blends to be found */
883         char filename[FILE_MAXDIR + FILE_MAXFILE];
884         BLI_strncpy(filename, argv[0], sizeof(filename));
885         BLI_path_cwd(filename);
886
887         if (G.background) {
888                 int retval = BKE_read_file(C, filename, NULL);
889
890                 /*we successfully loaded a blend file, get sure that
891                 pointcache works */
892                 if (retval!=0) {
893                         wmWindowManager *wm= CTX_wm_manager(C);
894                         CTX_wm_manager_set(C, NULL); /* remove wm to force check */
895                         WM_check(C);
896                         G.relbase_valid = 1;
897                         if (CTX_wm_manager(C) == NULL) CTX_wm_manager_set(C, wm); /* reset wm */
898                 }
899
900                 /* WM_read_file() runs normally but since we're in background mode do here */
901 #ifndef DISABLE_PYTHON
902                 /* run any texts that were loaded in and flagged as modules */
903                 BPY_load_user_modules(C);
904 #endif
905
906                 /* happens for the UI on file reading too (huh? (ton))*/
907         // XXX                  BKE_reset_undo();
908         //                              BKE_write_undo("original");     /* save current state */
909         } else {
910                 /* we are not running in background mode here, but start blender in UI mode with
911                    a file - this should do everything a 'load file' does */
912                 ReportList reports;
913                 BKE_reports_init(&reports, RPT_PRINT);
914                 WM_read_file(C, filename, &reports);
915                 BKE_reports_clear(&reports);
916         }
917
918         G.file_loaded = 1;
919
920         return 0;
921 }
922
923 void setupArguments(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
924 {
925         static char output_doc[] = "<path>"
926                 "\n\tSet the render path and file name."
927                 "\n\tUse // at the start of the path to"
928                 "\n\t\trender relative to the blend file."
929                 "\n\tThe # characters are replaced by the frame number, and used to define zero padding."
930                 "\n\t\tani_##_test.png becomes ani_01_test.png"
931                 "\n\t\ttest-######.png becomes test-000001.png"
932                 "\n\t\tWhen the filename does not contain #, The suffix #### is added to the filename"
933                 "\n\tThe frame number will be added at the end of the filename."
934                 "\n\t\teg: blender -b foobar.blend -o //render_ -F PNG -x 1 -a"
935                 "\n\t\t//render_ becomes //render_####, writing frames as //render_0001.png//";
936
937         static char format_doc[] = "<format>"
938                 "\n\tSet the render format, Valid options are..."
939                 "\n\t\tTGA IRIS JPEG MOVIE IRIZ RAWTGA"
940                 "\n\t\tAVIRAW AVIJPEG PNG BMP FRAMESERVER"
941                 "\n\t(formats that can be compiled into blender, not available on all systems)"
942                 "\n\t\tHDR TIFF EXR MULTILAYER MPEG AVICODEC QUICKTIME CINEON DPX DDS";
943
944         static char playback_doc[] = "<options> <file(s)>"
945                 "\n\tPlayback <file(s)>, only operates this way when not running in background."
946                 "\n\t\t-p <sx> <sy>\tOpen with lower left corner at <sx>, <sy>"
947                 "\n\t\t-m\t\tRead from disk (Don't buffer)"
948                 "\n\t\t-f <fps> <fps-base>\t\tSpecify FPS to start with"
949                 "\n\t\t-j <frame>\tSet frame step to <frame>";
950
951         static char game_doc[] = "Game Engine specific options"
952                 "\n\t-g fixedtime\t\tRun on 50 hertz without dropping frames"
953                 "\n\t-g vertexarrays\tUse Vertex Arrays for rendering (usually faster)"
954                 "\n\t-g nomipmap\t\tNo Texture Mipmapping"
955                 "\n\t-g linearmipmap\tLinear Texture Mipmapping instead of Nearest (default)";
956
957         static char debug_doc[] = "\n\tTurn debugging on\n"
958                 "\n\t* Prints every operator call and their arguments"
959                 "\n\t* Disables mouse grab (to interact with a debugger in some cases)"
960                 "\n\t* Keeps python sys.stdin rather then setting it to None";
961
962         //BLI_argsAdd(ba, pass, short_arg, long_arg, doc, cb, C);
963
964         /* end argument processing after -- */
965         BLI_argsAdd(ba, -1, "--", NULL, "\n\tEnds option processing, following arguments passed unchanged. Access via python's sys.argv", end_arguments, NULL);
966
967         /* first pass: background mode, disable python and commands that exit after usage */
968         BLI_argsAdd(ba, 1, "-h", "--help", "\n\tPrint this help text and exit", print_help, ba);
969         /* Windows only */
970         BLI_argsAdd(ba, 1, "/?", NULL, "\n\tPrint this help text and exit (windows only)", print_help, ba);
971
972         BLI_argsAdd(ba, 1, "-v", "--version", "\n\tPrint Blender version and exit", print_version, NULL);
973
974         BLI_argsAdd(ba, 1, "-y", "--enable-autoexec", "\n\tEnable automatic python script execution (default)", enable_python, NULL);
975         BLI_argsAdd(ba, 1, "-Y", "--disable-autoexec", "\n\tDisable automatic python script execution (pydrivers, pyconstraints, pynodes)", disable_python, NULL);
976
977         BLI_argsAdd(ba, 1, "-b", "--background", "<file>\n\tLoad <file> in background (often used for UI-less rendering)", background_mode, NULL);
978
979         BLI_argsAdd(ba, 1, "-a", NULL, playback_doc, playback_mode, NULL);
980
981         BLI_argsAdd(ba, 1, "-d", "--debug", debug_doc, debug_mode, ba);
982     BLI_argsAdd(ba, 1, NULL, "--debug-fpe", "\n\tEnable floating point exceptions", set_fpe, NULL);
983
984         /* second pass: custom window stuff */
985         BLI_argsAdd(ba, 2, "-p", "--window-geometry", "<sx> <sy> <w> <h>\n\tOpen with lower left corner at <sx>, <sy> and width and height as <w>, <h>", prefsize, NULL);
986         BLI_argsAdd(ba, 2, "-w", "--window-border", "\n\tForce opening with borders (default)", with_borders, NULL);
987         BLI_argsAdd(ba, 2, "-W", "--window-borderless", "\n\tForce opening with without borders", without_borders, NULL);
988         BLI_argsAdd(ba, 2, "-R", NULL, "\n\tRegister .blend extension (windows only)", register_extension, ba);
989
990         /* third pass: disabling things and forcing settings */
991         BLI_argsAddCase(ba, 3, "-nojoystick", 1, NULL, 0, "\n\tDisable joystick support", no_joystick, syshandle);
992         BLI_argsAddCase(ba, 3, "-noglsl", 1, NULL, 0, "\n\tDisable GLSL shading", no_glsl, NULL);
993         BLI_argsAddCase(ba, 3, "-noaudio", 1, NULL, 0, "\n\tForce sound system to None", no_audio, NULL);
994         BLI_argsAddCase(ba, 3, "-setaudio", 1, NULL, 0, "\n\tForce sound system to a specific device\n\tNULL SDL OPENAL JACK", set_audio, NULL);
995
996         /* fourth pass: processing arguments */
997         BLI_argsAdd(ba, 4, "-g", NULL, game_doc, set_ge_parameters, syshandle);
998         BLI_argsAdd(ba, 4, "-f", "--render-frame", "<frame>\n\tRender frame <frame> and save it.\n\t+<frame> start frame relative, -<frame> end frame relative.", render_frame, C);
999         BLI_argsAdd(ba, 4, "-a", "--render-anim", "\n\tRender frames from start to end (inclusive)", render_animation, C);
1000         BLI_argsAdd(ba, 4, "-S", "--scene", "<name>\n\tSet the active scene <name> for rendering", set_scene, C);
1001         BLI_argsAdd(ba, 4, "-s", "--frame-start", "<frame>\n\tSet start to frame <frame> (use before the -a argument)", set_start_frame, C);
1002         BLI_argsAdd(ba, 4, "-e", "--frame-end", "<frame>\n\tSet end to frame <frame> (use before the -a argument)", set_end_frame, C);
1003         BLI_argsAdd(ba, 4, "-j", "--frame-jump", "<frames>\n\tSet number of frames to step forward after each rendered frame", set_skip_frame, C);
1004         BLI_argsAdd(ba, 4, "-P", "--python", "<filename>\n\tRun the given Python script (filename or Blender Text)", run_python, C);
1005         BLI_argsAdd(ba, 4, NULL, "--python-console", "\n\tRun blender with an interactive console", run_python_console, C);
1006
1007         BLI_argsAdd(ba, 4, "-o", "--render-output", output_doc, set_output, C);
1008         BLI_argsAdd(ba, 4, "-E", "--engine", "<engine>\n\tSpecify the render engine\n\tuse -E help to list available engines", set_engine, C);
1009
1010         BLI_argsAdd(ba, 4, "-F", "--render-format", format_doc, set_image_type, C);
1011         BLI_argsAdd(ba, 4, "-t", "--threads", "<threads>\n\tUse amount of <threads> for rendering in background\n\t[1-" STRINGIFY(BLENDER_MAX_THREADS) "], 0 for systems processor count.", set_threads, NULL);
1012         BLI_argsAdd(ba, 4, "-x", "--use-extension", "<bool>\n\tSet option to add the file extension to the end of the file", set_extension, C);
1013
1014 }
1015
1016 int main(int argc, char **argv)
1017 {
1018         SYS_SystemHandle syshandle;
1019         bContext *C= CTX_create();
1020         bArgs *ba;
1021
1022 #ifdef WITH_BINRELOC
1023         br_init( NULL );
1024 #endif
1025
1026         setCallbacks();
1027 #ifdef __APPLE__
1028                 /* patch to ignore argument finder gives us (pid?) */
1029         if (argc==2 && strncmp(argv[1], "-psn_", 5)==0) {
1030                 extern int GHOST_HACK_getFirstFile(char buf[]);
1031                 static char firstfilebuf[512];
1032
1033                 argc= 1;
1034
1035                 if (GHOST_HACK_getFirstFile(firstfilebuf)) {
1036                         argc= 2;
1037                         argv[1]= firstfilebuf;
1038                 }
1039         }
1040
1041 #endif
1042
1043 #ifdef __FreeBSD__
1044         fpsetmask(0);
1045 #endif
1046
1047         // copy path to executable in bprogname. playanim and creting runtimes
1048         // need this.
1049
1050         BLI_where_am_i(bprogname, argv[0]);
1051         
1052 #ifdef BUILD_DATE       
1053         strip_quotes(build_date);
1054         strip_quotes(build_time);
1055         strip_quotes(build_rev);
1056         strip_quotes(build_platform);
1057         strip_quotes(build_type);
1058         strip_quotes(build_cflags);
1059         strip_quotes(build_cxxflags);
1060         strip_quotes(build_linkflags);
1061         strip_quotes(build_system);
1062 #endif
1063
1064         BLI_threadapi_init();
1065
1066         RNA_init();
1067         RE_engines_init();
1068
1069                 /* Hack - force inclusion of the plugin api functions,
1070                  * see blenpluginapi:pluginapi.c
1071                  */
1072         pluginapi_force_ref();
1073
1074         init_nodesystem();
1075         
1076         initglobals();  /* blender.c */
1077
1078         IMB_init();
1079
1080         syshandle = SYS_GetSystem();
1081         GEN_init_messaging_system();
1082
1083         /* first test for background */
1084         ba = BLI_argsInit(argc, argv); /* skip binary path */
1085         setupArguments(C, ba, &syshandle);
1086
1087         BLI_argsParse(ba, 1, NULL, NULL);
1088
1089 #ifdef __sgi
1090         setuid(getuid()); /* end superuser */
1091 #endif
1092
1093
1094         /* for all platforms, even windos has it! */
1095         if(G.background) signal(SIGINT, blender_esc);   /* ctrl c out bg render */
1096         
1097         /* background render uses this font too */
1098         BKE_font_register_builtin(datatoc_Bfont, datatoc_Bfont_size);
1099
1100         /* Initialiaze ffmpeg if built in, also needed for bg mode if videos are
1101            rendered via ffmpeg */
1102         sound_init_once();
1103         
1104         init_def_material();
1105
1106         if(G.background==0) {
1107                 BLI_argsParse(ba, 2, NULL, NULL);
1108                 BLI_argsParse(ba, 3, NULL, NULL);
1109
1110                 WM_init(C, argc, argv);
1111                 
1112                 /* this is properly initialized with user defs, but this is default */
1113                 BLI_where_is_temp( btempdir, 1 ); /* call after loading the startup.blend so we can read U.tempdir */
1114
1115 #ifndef DISABLE_SDL
1116         BLI_setenv("SDL_VIDEODRIVER", "dummy");
1117 /* I think this is not necessary anymore (04-24-2010 neXyon)
1118 #ifdef __linux__
1119         // On linux the default SDL driver dma often would not play
1120         // use alsa if none is set
1121         setenv("SDL_AUDIODRIVER", "alsa", 0);
1122 #endif
1123 */
1124 #endif
1125         }
1126         else {
1127                 BLI_argsParse(ba, 3, NULL, NULL);
1128
1129                 WM_init(C, argc, argv);
1130
1131                 BLI_where_is_temp( btempdir, 0 ); /* call after loading the startup.blend so we can read U.tempdir */
1132         }
1133 #ifndef DISABLE_PYTHON
1134         /**
1135          * NOTE: the U.pythondir string is NULL until WM_init() is executed,
1136          * so we provide the BPY_ function below to append the user defined
1137          * pythondir to Python's sys.path at this point.  Simply putting
1138          * WM_init() before BPY_start_python() crashes Blender at startup.
1139          * Update: now this function also inits the bpymenus, which also depend
1140          * on U.pythondir.
1141          */
1142
1143         // TODO - U.pythondir
1144
1145 #endif
1146         
1147         CTX_py_init_set(C, 1);
1148         WM_keymap_init(C);
1149
1150         /* OK we are ready for it */
1151         BLI_argsParse(ba, 4, load_file, C);
1152
1153         BLI_argsFree(ba);
1154
1155         if(G.background) {
1156                 /* actually incorrect, but works for now (ton) */
1157                 WM_exit(C);
1158         }
1159
1160         else {
1161                 if((G.fileflags & G_FILE_AUTOPLAY) && (G.f & G_SCRIPT_AUTOEXEC))
1162                 {
1163                         if(WM_init_game(C))
1164                                 return 0;
1165                 }
1166                 else if(!G.file_loaded)
1167                         WM_init_splash(C);
1168         }
1169
1170         WM_main(C);
1171
1172
1173         /*XXX if (scr_init==0) {
1174                 main_init_screen();
1175         }
1176         
1177         screenmain();*/ /* main display loop */
1178
1179         return 0;
1180 } /* end of int main(argc,argv) */
1181
1182 static void error_cb(char *err)
1183 {
1184         
1185         printf("%s\n", err);    /* XXX do this in WM too */
1186 }
1187
1188 static void mem_error_cb(const char *errorStr)
1189 {
1190         fputs(errorStr, stderr);
1191         fflush(stderr);
1192 }
1193
1194 static void setCallbacks(void)
1195 {
1196         /* Error output from the alloc routines: */
1197         MEM_set_error_callback(mem_error_cb);
1198
1199
1200         /* BLI_blenlib: */
1201
1202         BLI_setErrorCallBack(error_cb); /* */
1203 // XXX  BLI_setInterruptCallBack(blender_test_break);
1204
1205 }