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