-fpe command line argument. Tying it to -d is just hell.
[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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, 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 #include <stdlib.h>
30 #include <string.h>
31
32 /* for setuid / getuid */
33 #ifdef __sgi
34 #include <sys/types.h>
35 #include <unistd.h>
36 #endif
37
38 #ifdef __linux__
39 #include <fenv.h>
40 #endif
41
42 /* This little block needed for linking to Blender... */
43
44 #include "MEM_guardedalloc.h"
45
46 #ifdef WIN32
47 #include "BLI_winstuff.h"
48 #endif
49
50 #include "BLI_args.h"
51
52 #include "GEN_messaging.h"
53
54 #include "DNA_ID.h"
55 #include "DNA_scene_types.h"
56
57 #include "BLI_blenlib.h"
58
59 #include "BKE_utildefines.h"
60 #include "BKE_blender.h"
61 #include "BKE_context.h"
62 #include "BKE_font.h"
63 #include "BKE_global.h"
64 #include "BKE_main.h"
65 #include "BKE_material.h"
66 #include "BKE_packedFile.h"
67 #include "BKE_scene.h"
68 #include "BKE_node.h"
69 #include "BKE_report.h"
70 #include "BKE_sound.h"
71
72 #include "IMB_imbuf.h"  // for quicktime_init
73
74 #ifndef DISABLE_PYTHON
75 #include "BPY_extern.h"
76 #endif
77
78 #include "RE_pipeline.h"
79
80 //XXX #include "playanim_ext.h"
81 #include "ED_datafiles.h"
82 #include "UI_interface.h"
83
84 #include "WM_api.h"
85
86 #include "RNA_define.h"
87
88 #include "GPU_draw.h"
89 #include "GPU_extensions.h"
90
91 /* for passing information between creator and gameengine */
92 #include "SYS_System.h"
93
94 #include <signal.h>
95
96 #ifdef __FreeBSD__
97 # include <sys/types.h>
98 # include <floatingpoint.h>
99 # include <sys/rtprio.h>
100 #endif
101
102 #ifdef WITH_BINRELOC
103 #include "binreloc.h"
104 #endif
105
106 // from buildinfo.c
107 #ifdef BUILD_DATE
108 extern char * build_date;
109 extern char * build_time;
110 extern char * build_rev;
111 extern char * build_platform;
112 extern char * build_type;
113 #endif
114
115 /*      Local Function prototypes */
116 static int print_help(int argc, char **argv, void *data);
117 static int print_version(int argc, char **argv, void *data);
118
119 /* for the callbacks: */
120
121 extern int pluginapi_force_ref(void);  /* from blenpluginapi:pluginapi.c */
122
123 char bprogname[FILE_MAXDIR+FILE_MAXFILE]; /* from blenpluginapi:pluginapi.c */
124 char btempdir[FILE_MAXDIR+FILE_MAXFILE];
125
126 /* unix path support.
127  * defined by the compiler. eg "/usr/share/blender/2.5" "/opt/blender/2.5" */
128 #ifndef BLENDERPATH
129 #define BLENDERPATH ""
130 #endif
131  
132 char blender_path[FILE_MAXDIR+FILE_MAXFILE] = BLENDERPATH;
133
134 /* Initialise callbacks for the modules that need them */
135 static void setCallbacks(void); 
136
137 /* on linux set breakpoints here when running in debug mode, useful to catch floating point errors */
138 #if defined(__sgi) || defined(__linux__)
139 static void fpe_handler(int sig)
140 {
141         // printf("SIGFPE trapped\n");
142 }
143 #endif
144
145 /* handling ctrl-c event in console */
146 static void blender_esc(int sig)
147 {
148         static int count = 0;
149         
150         G.afbreek = 1;  /* forces render loop to read queue, not sure if its needed */
151         
152         if (sig == 2) {
153                 if (count) {
154                         printf("\nBlender killed\n");
155                         exit(2);
156                 }
157                 printf("\nSent an internal break event. Press ^C again to kill Blender\n");
158                 count++;
159         }
160 }
161
162 static int print_version(int argc, char **argv, void *data)
163 {
164 #ifdef BUILD_DATE
165         printf ("Blender %d.%02d (sub %d) Build\n", BLENDER_VERSION/100, BLENDER_VERSION%100, BLENDER_SUBVERSION);
166         printf ("\tbuild date: %s\n", build_date);
167         printf ("\tbuild time: %s\n", build_time);
168         printf ("\tbuild revision: %s\n", build_rev);
169         printf ("\tbuild platform: %s\n", build_platform);
170         printf ("\tbuild type: %s\n", build_type);
171 #else
172         printf ("Blender %d.%02d (sub %d) Build\n", BLENDER_VERSION/100, BLENDER_VERSION%100, BLENDER_SUBVERSION);
173 #endif
174
175         exit(0);
176
177         return 0;
178 }
179
180 static int print_help(int argc, char **argv, void *data)
181 {
182         printf ("Blender %d.%02d (sub %d) Build\n", BLENDER_VERSION/100, BLENDER_VERSION%100, BLENDER_SUBVERSION);
183         printf ("Usage: blender [args ...] [file] [args ...]\n");
184         printf ("\nRender options:\n");
185         printf ("  -b <file>\tRender <file> in background (doesn't load the user defaults .B.blend file)\n");
186         printf ("    -a render frames from start to end (inclusive), only works when used after -b\n");
187         printf ("    -S <name>\tSet scene <name>\n");
188         printf ("    -f <frame>\tRender frame <frame> and save it\n");                          
189         printf ("    -s <frame>\tSet start to frame <frame> (use before the -a argument)\n");
190         printf ("    -e <frame>\tSet end to frame <frame> (use before the -a argument)\n");
191         printf ("    -o <path>\tSet the render path and file name.\n");
192         printf ("      Use // at the start of the path to\n");
193         printf ("        render relative to the blend file.\n");
194         printf ("      The # characters are replaced by the frame number, and used to define zero padding.\n");
195         printf ("        ani_##_test.png becomes ani_01_test.png\n");
196         printf ("        test-######.png becomes test-000001.png\n");
197         printf ("        When the filename has no #, The suffix #### is added to the filename\n");
198         printf ("      The frame number will be added at the end of the filename.\n");
199         printf ("      eg: blender -b foobar.blend -o //render_ -F PNG -x 1 -a\n");
200         printf ("    -E <engine>\tSpecify the render engine.\n");
201         printf ("      use -E help to list available engines.\n");
202         printf ("\nFormat options:\n");
203         printf ("    -F <format>\tSet the render format, Valid options are...\n");
204         printf ("    \tTGA IRIS HAMX JPEG MOVIE IRIZ RAWTGA\n");
205         printf ("    \tAVIRAW AVIJPEG PNG BMP FRAMESERVER\n");
206         printf ("    (formats that can be compiled into blender, not available on all systems)\n");
207         printf ("    \tHDR TIFF EXR MULTILAYER MPEG AVICODEC QUICKTIME CINEON DPX DDS\n");
208         printf ("    -x <bool>\tSet option to add the file extension to the end of the file.\n");
209         printf ("    -t <threads>\tUse amount of <threads> for rendering (background mode only).\n");
210         printf ("      [1-8], 0 for systems processor count.\n");
211         printf ("\nAnimation playback options:\n");
212         printf ("  -a <options> <file(s)>\tPlayback <file(s)>, only operates this way when -b is not used.\n");
213         printf ("    -p <sx> <sy>\tOpen with lower left corner at <sx>, <sy>\n");
214         printf ("    -m\t\tRead from disk (Don't buffer)\n");
215         printf ("    -f <fps> <fps-base>\t\tSpecify FPS to start with\n");
216         printf ("    -j <frame>\tSet frame step to <frame>\n");
217                                 
218         printf ("\nWindow options:\n");
219         printf ("  -w\t\tForce opening with borders (default)\n");
220         printf ("  -W\t\tForce opening without borders\n");
221         printf ("  -p <sx> <sy> <w> <h>\tOpen with lower left corner at <sx>, <sy>\n");
222         printf ("                      \tand width and height <w>, <h>\n");
223         printf ("\nGame Engine specific options:\n");
224         printf ("  -g fixedtime\t\tRun on 50 hertz without dropping frames\n");
225         printf ("  -g vertexarrays\tUse Vertex Arrays for rendering (usually faster)\n");
226         printf ("  -g nomipmap\t\tNo Texture Mipmapping\n");
227         printf ("  -g linearmipmap\tLinear Texture Mipmapping instead of Nearest (default)\n");
228
229         printf ("\nMisc options:\n");
230         printf ("  -d\t\tTurn debugging on\n");
231         printf ("  -nojoystick\tDisable joystick support\n");
232         printf ("  -noglsl\tDisable GLSL shading\n");
233         printf ("  -noaudio\tForce sound system to None\n");
234         printf ("  -setaudio\tForce sound system to a specific device\n");
235         printf ("    \tNULL SDL OPENAL JACK\n");
236         printf ("  -h\t\tPrint this help text\n");
237         printf ("  -y\t\tDisable automatic python script execution (pydrivers, pyconstraints, pynodes)\n");
238         printf ("  -P <filename>\tRun the given Python script (filename or Blender Text)\n");
239 #ifdef WIN32
240         printf ("  -R\t\tRegister .blend extension\n");
241 #endif
242         printf ("  -v\t\tPrint Blender version and exit\n");
243         printf ("  --\t\tEnds option processing.  Following arguments are \n");
244         printf ("    \t\t   passed unchanged.  Access via Python's sys.argv\n");
245         printf ("\nEnvironment Variables:\n");
246         printf ("  $HOME\t\t\tStore files such as .blender/ .B.blend .Bfs .Blog here.\n");
247         printf ("  $BLENDERPATH\tSystem directory to use for data files and scripts.\n");
248         printf ("              \tFor this build of blender the default BLENDERPATH is...\n");
249         printf ("              \t\"%s\"\n", blender_path);
250         printf ("              \tseting the $BLENDERPATH will override this\n");
251 #ifdef WIN32
252         printf ("  $TEMP\t\tStore temporary files here.\n");
253 #else
254         printf ("  $TMP or $TMPDIR\tStore temporary files here.\n");
255         printf ("  $BF_TIFF_LIB\t\tUse an alternative libtiff.so for loading tiff image files.\n");
256 #endif
257 #ifndef DISABLE_SDL
258         printf ("  $SDL_AUDIODRIVER\tLibSDL audio driver - alsa, esd, alsa, dma.\n");
259 #endif
260         printf ("  $IMAGEEDITOR\t\tImage editor executable, launch with the IKey from the file selector.\n");
261         printf ("  $WINEDITOR\t\tText editor executable, launch with the EKey from the file selector.\n");
262         printf ("  $PYTHONHOME\t\tPath to the python directory, eg. /usr/lib/python.\n");
263         printf ("\nNote: Arguments must be separated by white space. eg:\n");
264         printf ("    \"blender -ba test.blend\"\n");
265         printf ("  ...will ignore the 'a'\n");
266         printf ("    \"blender -b test.blend -f8\"\n");
267         printf ("  ...will ignore 8 because there is no space between the -f and the frame value\n");
268         printf ("Note: Arguments are executed in the order they are given. eg:\n");
269         printf ("    \"blender -b test.blend -f 1 -o /tmp\"\n");
270         printf ("  ...may not render to /tmp because '-f 1' renders before the output path is set\n");
271         printf ("    \"blender -b -o /tmp test.blend -f 1\"\n");
272         printf ("  ...may not render to /tmp because loading the blend file overwrites the output path that was set\n");
273         printf ("    \"blender -b test.blend -o /tmp -f 1\" works as expected.\n\n");
274
275         exit(0);
276
277         return 0;
278 }
279
280
281 double PIL_check_seconds_timer(void);
282
283 /* XXX This was here to fix a crash when running python scripts
284  * with -P that used the screen.
285  *
286  * static void main_init_screen( void )
287 {
288         setscreen(G.curscreen);
289         
290         if(G.main->scene.first==0) {
291                 set_scene( add_scene("1") );
292         }
293 }*/
294
295 static int end_arguments(int argc, char **argv, void *data)
296 {
297         return -1;
298 }
299
300 static int disable_python(int argc, char **argv, void *data)
301 {
302         G.f &= ~G_DOSCRIPTLINKS;
303         return 0;
304 }
305
306
307 static int forked_tongue(int argc, char **argv, void *data)
308 {
309         printf ("-y was used to disable script links because,\n");
310         printf ("\t-p being taken, Ton was of the opinion that Y\n");
311         printf ("\tlooked like a split (disabled) snake, and also\n");
312         printf ("\twas similar to a python's tongue (unproven).\n\n");
313
314         printf ("\tZr agreed because it gave him a reason to add a\n");
315         printf ("\tcompletely useless text into Blender.\n\n");
316
317         printf ("\tADDENDUM! Ton, in defense, found this picture of\n");
318         printf ("\tan Australian python, exhibiting her (his/its) forked\n");
319         printf ("\tY tongue. It could be part of an H Zr retorted!\n\n");
320         printf ("\thttp://www.users.bigpond.com/snake.man/\n");
321
322         exit(252);
323         return 0;
324 }
325
326 static int background_mode(int argc, char **argv, void *data)
327 {
328         G.background = 1;
329         return 0;
330 }
331
332 static int debug_mode(int argc, char **argv, void *data)
333 {
334         G.f |= G_DEBUG;         /* std output printf's */
335         printf ("Blender %d.%02d (sub %d) Build\n", BLENDER_VERSION/100, BLENDER_VERSION%100, BLENDER_SUBVERSION);
336         MEM_set_memory_debug();
337
338 #ifdef NAN_BUILDINFO
339         printf("Build: %s %s %s %s\n", build_date, build_time, build_platform, build_type);
340 #endif // NAN_BUILDINFO
341
342         BLI_argsPrint(data);
343         return 0;
344 }
345
346 static int set_fpe(int argc, char **argv, void *data)
347 {
348 #if defined(__sgi) || defined(__linux__)
349         /* zealous but makes float issues a heck of a lot easier to find!
350          * set breakpoints on fpe_handler */
351         signal(SIGFPE, fpe_handler);
352
353 #ifdef __linux__
354         feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW );
355 #endif
356 #endif
357         return 0;
358 }
359
360 static int playback_mode(int argc, char **argv, void *data)
361 {
362         /* not if -b was given first */
363         if (G.background == 0) {
364                 /* exception here, see below, it probably needs happens after qt init? */
365                 libtiff_init();
366
367 // XXX                          playanim(argc, argv); /* not the same argc and argv as before */
368                 exit(0);
369         }
370
371         return -2;
372 }
373
374 static int prefsize(int argc, char **argv, void *data)
375 {
376         int stax, stay, sizx, sizy;
377
378         if (argc < 5) {
379                 printf ("-p requires four arguments\n");
380                 exit(1);
381         }
382
383         stax= atoi(argv[1]);
384         stay= atoi(argv[2]);
385         sizx= atoi(argv[3]);
386         sizy= atoi(argv[4]);
387
388         WM_setprefsize(stax, stay, sizx, sizy);
389
390         return 4;
391 }
392
393 static int with_borders(int argc, char **argv, void *data)
394 {
395         /* with borders XXX OLD CRUFT!*/
396
397         return 0;
398 }
399
400 static int without_borders(int argc, char **argv, void *data)
401 {
402         /* borderless, win + linux XXX OLD CRUFT */
403         /* XXX, fixme mein, borderless on OSX */
404
405         return 0;
406 }
407
408 static int register_extension(int argc, char **argv, void *data)
409 {
410 #ifdef WIN32
411         char *path = BLI_argsArgv(data)[0];
412         RegisterBlendExtension(path);
413 #endif
414
415         return 0;
416 }
417
418 static int no_joystick(int argc, char **argv, void *data)
419 {
420         SYS_SystemHandle *syshandle = data;
421
422         /**
423                 don't initialize joysticks if user doesn't want to use joysticks
424                 failed joystick initialization delays over 5 seconds, before game engine start
425         */
426         SYS_WriteCommandLineInt(*syshandle, "nojoystick",1);
427         if (G.f & G_DEBUG) printf("disabling nojoystick\n");
428
429         return 0;
430 }
431
432 static int no_glsl(int argc, char **argv, void *data)
433 {
434         GPU_extensions_disable();
435         return 0;
436 }
437
438 static int no_audio(int argc, char **argv, void *data)
439 {
440         sound_force_device(0);
441         return 0;
442 }
443
444 static int set_audio(int argc, char **argv, void *data)
445 {
446         if (argc < 1) {
447                 printf("-setaudio require one argument\n");
448                 exit(1);
449         }
450
451         sound_force_device(sound_define_from_str(argv[1]));
452         return 1;
453 }
454
455 static int set_output(int argc, char **argv, void *data)
456 {
457         bContext *C = data;
458         if (argc >= 1){
459                 if (CTX_data_scene(C)) {
460                         Scene *scene= CTX_data_scene(C);
461                         BLI_strncpy(scene->r.pic, argv[1], FILE_MAXDIR);
462                 } else {
463                         printf("\nError: no blend loaded. cannot use '-o'.\n");
464                 }
465                 return 1;
466         } else {
467                 printf("\nError: you must specify a path after '-o '.\n");
468                 return 0;
469         }
470 }
471
472 static int set_engine(int argc, char **argv, void *data)
473 {
474         bContext *C = data;
475         if (argc >= 1)
476         {
477                 if (!strcmp(argv[1],"help"))
478                 {
479                         RenderEngineType *type = NULL;
480
481                         for( type = R_engines.first; type; type = type->next )
482                         {
483                                 printf("\t%s\n", type->idname);
484                         }
485                         exit(0);
486                 }
487                 else
488                 {
489                         if (CTX_data_scene(C)==NULL)
490                         {
491                                 printf("\nError: no blend loaded. order the arguments so '-E ' is after a blend is loaded.\n");
492                         }
493                         else
494                         {
495                                 Scene *scene= CTX_data_scene(C);
496                                 RenderData *rd = &scene->r;
497                                 RenderEngineType *type = NULL;
498
499                                 for( type = R_engines.first; type; type = type->next )
500                                 {
501                                         if (!strcmp(argv[1],type->idname))
502                                         {
503                                                 BLI_strncpy(rd->engine, type->idname, sizeof(rd->engine));
504                                         }
505                                 }
506                         }
507                 }
508
509                 return 1;
510         }
511         else
512         {
513                 printf("\nEngine not specified.\n");
514                 return 0;
515         }
516 }
517
518 static int set_image_type(int argc, char **argv, void *data)
519 {
520         bContext *C = data;
521         if (argc >= 1){
522                 char *imtype = argv[1];
523                 if (CTX_data_scene(C)==NULL) {
524                         printf("\nError: no blend loaded. order the arguments so '-F ' is after the blend is loaded.\n");
525                 } else {
526                         Scene *scene= CTX_data_scene(C);
527                         if      (!strcmp(imtype,"TGA")) scene->r.imtype = R_TARGA;
528                         else if (!strcmp(imtype,"IRIS")) scene->r.imtype = R_IRIS;
529                         else if (!strcmp(imtype,"HAMX")) scene->r.imtype = R_HAMX;
530 #ifdef WITH_DDS
531                         else if (!strcmp(imtype,"DDS")) scene->r.imtype = R_DDS;
532 #endif
533                         else if (!strcmp(imtype,"JPEG")) scene->r.imtype = R_JPEG90;
534                         else if (!strcmp(imtype,"MOVIE")) scene->r.imtype = R_MOVIE;
535                         else if (!strcmp(imtype,"IRIZ")) scene->r.imtype = R_IRIZ;
536                         else if (!strcmp(imtype,"RAWTGA")) scene->r.imtype = R_RAWTGA;
537                         else if (!strcmp(imtype,"AVIRAW")) scene->r.imtype = R_AVIRAW;
538                         else if (!strcmp(imtype,"AVIJPEG")) scene->r.imtype = R_AVIJPEG;
539                         else if (!strcmp(imtype,"PNG")) scene->r.imtype = R_PNG;
540                         else if (!strcmp(imtype,"AVICODEC")) scene->r.imtype = R_AVICODEC;
541                         else if (!strcmp(imtype,"QUICKTIME")) scene->r.imtype = R_QUICKTIME;
542                         else if (!strcmp(imtype,"BMP")) scene->r.imtype = R_BMP;
543                         else if (!strcmp(imtype,"HDR")) scene->r.imtype = R_RADHDR;
544                         else if (!strcmp(imtype,"TIFF")) scene->r.imtype = R_TIFF;
545 #ifdef WITH_OPENEXR
546                         else if (!strcmp(imtype,"EXR")) scene->r.imtype = R_OPENEXR;
547                         else if (!strcmp(imtype,"MULTILAYER")) scene->r.imtype = R_MULTILAYER;
548 #endif
549                         else if (!strcmp(imtype,"MPEG")) scene->r.imtype = R_FFMPEG;
550                         else if (!strcmp(imtype,"FRAMESERVER")) scene->r.imtype = R_FRAMESERVER;
551                         else if (!strcmp(imtype,"CINEON")) scene->r.imtype = R_CINEON;
552                         else if (!strcmp(imtype,"DPX")) scene->r.imtype = R_DPX;
553 #if WITH_OPENJPEG
554                         else if (!strcmp(imtype,"JP2")) scene->r.imtype = R_JP2;
555 #endif
556                         else printf("\nError: Format from '-F' not known or not compiled in this release.\n");
557
558                 }
559                 return 1;
560         } else {
561                 printf("\nError: no blend loaded. cannot use '-x'.\n");
562                 return 0;
563         }
564 }
565
566 static int set_threads(int argc, char **argv, void *data)
567 {
568         if (argc >= 1) {
569                 if(G.background) {
570                         RE_set_max_threads(atoi(argv[1]));
571                 } else {
572                         printf("Warning: threads can only be set in background mode\n");
573                 }
574                 return 1;
575         } else {
576                 printf("\nError: you must specify a number of threads between 0 and 8 '-t '.\n");
577                 return 0;
578         }
579 }
580
581 static int set_extension(int argc, char **argv, void *data)
582 {
583         bContext *C = data;
584         if (argc >= 1) {
585                 if (CTX_data_scene(C)) {
586                         Scene *scene= CTX_data_scene(C);
587                         if (argv[1][0] == '0') {
588                                 scene->r.scemode &= ~R_EXTENSION;
589                         } else if (argv[1][0] == '1') {
590                                 scene->r.scemode |= R_EXTENSION;
591                         } else {
592                                 printf("\nError: Use '-x 1' or '-x 0' To set the extension option.\n");
593                         }
594                 } else {
595                         printf("\nError: no blend loaded. order the arguments so '-o ' is after '-x '.\n");
596                 }
597                 return 1;
598         } else {
599                 printf("\nError: you must specify a path after '- '.\n");
600                 return 0;
601         }
602 }
603
604 static int set_ge_parameters(int argc, char **argv, void *data)
605 {
606         SYS_SystemHandle syshandle = *(SYS_SystemHandle*)data;
607         int a = 0;
608 /**
609 gameengine parameters are automaticly put into system
610 -g [paramname = value]
611 -g [boolparamname]
612 example:
613 -g novertexarrays
614 -g maxvertexarraysize = 512
615 */
616
617         if(argc >= 1)
618         {
619                 char* paramname = argv[a];
620                 /* check for single value versus assignment */
621                 if (a+1 < argc && (*(argv[a+1]) == '='))
622                 {
623                         a++;
624                         if (a+1 < argc)
625                         {
626                                 a++;
627                                 /* assignment */
628                                 SYS_WriteCommandLineString(syshandle,paramname,argv[a]);
629                         }  else
630                         {
631                                 printf("error: argument assignment (%s) without value.\n",paramname);
632                                 return 0;
633                         }
634                         /* name arg eaten */
635
636                 } else {
637                         SYS_WriteCommandLineInt(syshandle,argv[a],1);
638
639                         /* doMipMap */
640                         if (!strcmp(argv[a],"nomipmap"))
641                         {
642                                 GPU_set_mipmap(0); //doMipMap = 0;
643                         }
644                         /* linearMipMap */
645                         if (!strcmp(argv[a],"linearmipmap"))
646                         {
647                                 GPU_set_linear_mipmap(1); //linearMipMap = 1;
648                         }
649
650
651                 } /* if (*(argv[a+1]) == '=') */
652         }
653
654         return a;
655 }
656
657 static int render_frame(int argc, char **argv, void *data)
658 {
659         bContext *C = data;
660         if (CTX_data_scene(C)) {
661                 Scene *scene= CTX_data_scene(C);
662
663                 if (argc > 1) {
664                         int frame = atoi(argv[1]);
665                         Render *re = RE_NewRender(scene->id.name);
666                         ReportList reports;
667
668                         BKE_reports_init(&reports, RPT_PRINT);
669
670                         frame = MIN2(MAXFRAME, MAX2(MINAFRAME, frame));
671
672                         RE_BlenderAnim(re, scene, frame, frame, scene->r.frame_step, &reports);
673                         return 1;
674                 } else {
675                         printf("\nError: frame number must follow '-f'.\n");
676                         return 0;
677                 }
678         } else {
679                 printf("\nError: no blend loaded. cannot use '-f'.\n");
680                 return 0;
681         }
682 }
683
684 static int render_animation(int argc, char **argv, void *data)
685 {
686         bContext *C = data;
687         if (CTX_data_scene(C)) {
688                 Scene *scene= CTX_data_scene(C);
689                 Render *re= RE_NewRender(scene->id.name);
690                 ReportList reports;
691                 BKE_reports_init(&reports, RPT_PRINT);
692                 RE_BlenderAnim(re, scene, scene->r.sfra, scene->r.efra, scene->r.frame_step, &reports);
693         } else {
694                 printf("\nError: no blend loaded. cannot use '-a'.\n");
695         }
696         return 0;
697 }
698
699 static int set_scene(int argc, char **argv, void *data)
700 {
701         if(argc > 1) {
702                 set_scene_name(argv[1]);
703                 return 1;
704         } else {
705                 printf("\nError: Scene name must follow '-S'.\n");
706                 return 0;
707         }
708 }
709
710 static int set_start_frame(int argc, char **argv, void *data)
711 {
712         bContext *C = data;
713         if (CTX_data_scene(C)) {
714                 Scene *scene= CTX_data_scene(C);
715                 if (argc > 1) {
716                         int frame = atoi(argv[1]);
717                         (scene->r.sfra) = MIN2(MAXFRAME, MAX2(1, frame));
718                         return 1;
719                 } else {
720                         printf("\nError: frame number must follow '-s'.\n");
721                         return 0;
722                 }
723         } else {
724                 printf("\nError: no blend loaded. cannot use '-s'.\n");
725                 return 0;
726         }
727 }
728
729 static int set_end_frame(int argc, char **argv, void *data)
730 {
731         bContext *C = data;
732         if (CTX_data_scene(C)) {
733                 Scene *scene= CTX_data_scene(C);
734                 if (argc > 1) {
735                         int frame = atoi(argv[1]);
736                         (scene->r.efra) = MIN2(MAXFRAME, MAX2(1, frame));
737                         return 1;
738                 } else {
739                         printf("\nError: frame number must follow '-e'.\n");
740                         return 0;
741                 }
742         } else {
743                 printf("\nError: no blend loaded. cannot use '-e'.\n");
744                 return 0;
745         }
746 }
747
748 static int set_skip_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.frame_step) = MIN2(MAXFRAME, MAX2(1, frame));
756                         return 1;
757                 } else {
758                         printf("\nError: number of frames must follow '-j'.\n");
759                         return 0;
760                 }
761         } else {
762                 printf("\nError: no blend loaded. cannot use '-j'.\n");
763                 return 0;
764         }
765 }
766
767 static int run_python(int argc, char **argv, void *data)
768 {
769         bContext *C = data;
770 #ifndef DISABLE_PYTHON
771         /* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */
772         if (argc > 1) {
773                 /* XXX, temp setting the WM is ugly, splash also does this :S */
774                 wmWindowManager *wm= CTX_wm_manager(C);
775                 wmWindow *prevwin= CTX_wm_window(C);
776
777                 if(wm->windows.first) {
778                         CTX_wm_window_set(C, wm->windows.first);
779
780                         BPY_run_python_script(C, argv[1], NULL, NULL); // use reports?
781
782                         CTX_wm_window_set(C, prevwin);
783                 }
784                 else {
785                         fprintf(stderr, "Python script \"%s\" running with missing context data.\n", argv[1]);
786                         BPY_run_python_script(C, argv[1], NULL, NULL); // use reports?
787                 }
788                 return 1;
789         } else {
790                 printf("\nError: you must specify a Python script after '-P '.\n");
791                 return 0;
792         }
793 #else
794         printf("This blender was built without python support\n");
795         return 0;
796 #endif /* DISABLE_PYTHON */
797 }
798
799 static int load_file(int argc, char **argv, void *data)
800 {
801         bContext *C = data;
802
803         /* Make the path absolute because its needed for relative linked blends to be found */
804         char filename[FILE_MAXDIR + FILE_MAXFILE];
805
806         BLI_strncpy(filename, argv[0], sizeof(filename));
807         BLI_convertstringcwd(filename);
808
809         if (G.background) {
810                 int retval = BKE_read_file(C, argv[0], NULL, NULL);
811
812                 /*we successfully loaded a blend file, get sure that
813                 pointcache works */
814                 if (retval!=0) {
815                         CTX_wm_manager_set(C, NULL); /* remove wm to force check */
816                         WM_check(C);
817                         G.relbase_valid = 1;
818                 }
819
820                 /* happens for the UI on file reading too (huh? (ton))*/
821         // XXX                  BKE_reset_undo();
822         //                              BKE_write_undo("original");     /* save current state */
823         } else {
824                 /* we are not running in background mode here, but start blender in UI mode with
825                    a file - this should do everything a 'load file' does */
826                 WM_read_file(C, filename, NULL);
827         }
828
829         G.file_loaded = 1;
830
831         return 0;
832 }
833
834 void setupArguments(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
835 {
836         //BLI_argsAdd(ba, arg, pass, BA_ArgCallback cb, C);
837
838         /* end argument processing after -- */
839         BLI_argsAdd(ba, "--", -1, end_arguments, NULL);
840
841         /* first pass: background mode, disable python and commands that exit after usage */
842         BLI_argsAdd(ba, "--help", 1, print_help, NULL);
843         BLI_argsAdd(ba, "-h", 1, print_help, NULL);
844         BLI_argsAdd(ba, "/?", 1, print_help, NULL);
845
846         BLI_argsAdd(ba, "--version", 1, print_version, NULL);
847         BLI_argsAdd(ba, "-v", 1, print_version, NULL);
848
849         BLI_argsAdd(ba, "-Y", 1, forked_tongue, NULL);
850         BLI_argsAdd(ba, "-y", 1, disable_python, NULL);
851
852         BLI_argsAdd(ba, "-fpe", 1, set_fpe, NULL);
853
854         BLI_argsAdd(ba, "-B", 1, background_mode, NULL);
855         BLI_argsAdd(ba, "-b", 1, background_mode, NULL);
856         BLI_argsAdd(ba, "-a", 1, playback_mode, NULL);
857
858         BLI_argsAdd(ba, "-d", 1, debug_mode, ba);
859
860         /* second pass: custom window stuff */
861         BLI_argsAdd(ba, "-p", 2, prefsize, NULL);
862         BLI_argsAdd(ba, "-w", 2, with_borders, NULL);
863         BLI_argsAdd(ba, "-W", 2, without_borders, NULL);
864         BLI_argsAdd(ba, "-R", 2, register_extension, ba);
865
866         /* third pass: disabling things and forcing settings */
867         BLI_argsAddCase(ba, "-nojoystick", 3, no_joystick, syshandle);
868         BLI_argsAddCase(ba, "-noglsl", 3, no_glsl, NULL);
869         BLI_argsAddCase(ba, "-noaudio", 3, no_audio, NULL);
870         BLI_argsAddCase(ba, "-setaudio", 3, set_audio, NULL);
871
872         /* fourth pass: processing arguments */
873         BLI_argsAdd(ba, "-g", 4, set_ge_parameters, syshandle);
874         BLI_argsAdd(ba, "-f", 4, render_frame, C);
875         BLI_argsAdd(ba, "-a", 4, render_animation, C);
876         BLI_argsAdd(ba, "-S", 4, set_scene, NULL);
877         BLI_argsAdd(ba, "-s", 4, set_start_frame, C);
878         BLI_argsAdd(ba, "-e", 4, set_end_frame, C);
879         BLI_argsAdd(ba, "-j", 4, set_skip_frame, C);
880         BLI_argsAdd(ba, "-P", 4, run_python, C);
881         BLI_argsAdd(ba, "-o", 4, set_output, C);
882         BLI_argsAdd(ba, "-E", 4, set_engine, C);
883         BLI_argsAdd(ba, "-F", 4, set_image_type, C);
884         BLI_argsAdd(ba, "-t", 4, set_threads, NULL);
885         BLI_argsAdd(ba, "-x", 4, set_extension, C);
886
887 }
888
889 int main(int argc, char **argv)
890 {
891         SYS_SystemHandle syshandle;
892         bContext *C= CTX_create();
893         bArgs *ba;
894
895 #ifdef WITH_BINRELOC
896         br_init( NULL );
897 #endif
898
899         setCallbacks();
900 #ifdef __APPLE__
901                 /* patch to ignore argument finder gives us (pid?) */
902         if (argc==2 && strncmp(argv[1], "-psn_", 5)==0) {
903                 extern int GHOST_HACK_getFirstFile(char buf[]);
904                 static char firstfilebuf[512];
905
906                 argc= 1;
907
908                 if (GHOST_HACK_getFirstFile(firstfilebuf)) {
909                         argc= 2;
910                         argv[1]= firstfilebuf;
911                 }
912         }
913
914 #endif
915
916 #ifdef __FreeBSD__
917         fpsetmask(0);
918 #endif
919
920         // copy path to executable in bprogname. playanim and creting runtimes
921         // need this.
922
923         BLI_where_am_i(bprogname, argv[0]);
924         
925         {       /* override the hard coded blender path */
926                 char *blender_path_env = getenv("BLENDERPATH");
927                 if(blender_path_env)
928                         BLI_strncpy(blender_path, blender_path_env, sizeof(blender_path));
929         }
930         
931         RNA_init();
932         RE_engines_init();
933
934                 /* Hack - force inclusion of the plugin api functions,
935                  * see blenpluginapi:pluginapi.c
936                  */
937         pluginapi_force_ref();
938
939         init_nodesystem();
940         
941         initglobals();  /* blender.c */
942
943         syshandle = SYS_GetSystem();
944         GEN_init_messaging_system();
945
946         /* first test for background */
947
948         G.f |= G_DOSCRIPTLINKS; /* script links enabled by default */
949
950         ba = BLI_argsInit(argc, argv); /* skip binary path */
951         setupArguments(C, ba, &syshandle);
952
953         BLI_argsParse(ba, 1, NULL, NULL);
954
955 #ifdef __sgi
956         setuid(getuid()); /* end superuser */
957 #endif
958
959
960         /* for all platforms, even windos has it! */
961         if(G.background) signal(SIGINT, blender_esc);   /* ctrl c out bg render */
962         
963         /* background render uses this font too */
964         BKE_font_register_builtin(datatoc_Bfont, datatoc_Bfont_size);
965         
966         init_def_material();
967
968         if(G.background==0) {
969                 BLI_argsParse(ba, 2, NULL, NULL);
970                 BLI_argsParse(ba, 3, NULL, NULL);
971
972                 WM_init(C, argc, argv);
973                 
974                 // XXX BRECHT SOLVE
975                 BLI_where_is_temp( btempdir, 1 ); /* call after loading the .B.blend so we can read U.tempdir */
976
977 #ifndef DISABLE_SDL
978         BLI_setenv("SDL_VIDEODRIVER", "dummy");
979 #ifdef __linux__
980         /* On linux the default SDL driver dma often would not play
981          * use alsa if none is set */
982         setenv("SDL_AUDIODRIVER", "alsa", 0);
983 #endif
984 #endif
985         }
986         else {
987                 BLI_argsParse(ba, 3, NULL, NULL);
988
989                 WM_init(C, argc, argv);
990
991                 BLI_where_is_temp( btempdir, 0 ); /* call after loading the .B.blend so we can read U.tempdir */
992         }
993 #ifndef DISABLE_PYTHON
994         /**
995          * NOTE: the U.pythondir string is NULL until WM_init() is executed,
996          * so we provide the BPY_ function below to append the user defined
997          * pythondir to Python's sys.path at this point.  Simply putting
998          * WM_init() before BPY_start_python() crashes Blender at startup.
999          * Update: now this function also inits the bpymenus, which also depend
1000          * on U.pythondir.
1001          */
1002         
1003         // TODO - U.pythondir
1004
1005 #endif
1006         
1007         CTX_py_init_set(C, 1);
1008         WM_keymap_init(C);
1009
1010 #ifdef WITH_QUICKTIME
1011
1012         quicktime_init();
1013
1014 #endif /* WITH_QUICKTIME */
1015
1016         /* dynamically load libtiff, if available */
1017         libtiff_init();
1018         if (!G.have_libtiff && (G.f & G_DEBUG)) {
1019                 printf("Unable to load: libtiff.\n");
1020                 printf("Try setting the BF_TIFF_LIB environment variable if you want this support.\n");
1021                 printf("Example: setenv BF_TIFF_LIB /usr/lib/libtiff.so\n");
1022         }
1023
1024         /* OK we are ready for it */
1025         BLI_argsParse(ba, 4, load_file, C);
1026
1027         BLI_argsFree(ba);
1028
1029         if(G.background) {
1030                 /* actually incorrect, but works for now (ton) */
1031                 WM_exit(C);
1032         }
1033
1034         if(!G.background && !G.file_loaded)
1035                 WM_init_splash(C);
1036
1037         WM_main(C);
1038
1039
1040         /*XXX if (scr_init==0) {
1041                 main_init_screen();
1042         }
1043         
1044         screenmain();*/ /* main display loop */
1045
1046         return 0;
1047 } /* end of int main(argc,argv) */
1048
1049 static void error_cb(char *err)
1050 {
1051         
1052         printf("%s\n", err);    /* XXX do this in WM too */
1053 }
1054
1055 static void mem_error_cb(char *errorStr)
1056 {
1057         fputs(errorStr, stderr);
1058         fflush(stderr);
1059 }
1060
1061 static void setCallbacks(void)
1062 {
1063         /* Error output from the alloc routines: */
1064         MEM_set_error_callback(mem_error_cb);
1065
1066
1067         /* BLI_blenlib: */
1068
1069         BLI_setErrorCallBack(error_cb); /* */
1070 // XXX  BLI_setInterruptCallBack(blender_test_break);
1071
1072 }