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