2ad3881a4a0426a7b4246a3199cc1468c58b7fc4
[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                 return 1;
559         } else {
560                 printf("\nError: you must specify a format after '-F '.\n");
561                 return 0;
562         }
563 }
564
565 static int set_threads(int argc, char **argv, void *data)
566 {
567         if (argc >= 1) {
568                 if(G.background) {
569                         RE_set_max_threads(atoi(argv[1]));
570                 } else {
571                         printf("Warning: threads can only be set in background mode\n");
572                 }
573                 return 1;
574         } else {
575                 printf("\nError: you must specify a number of threads between 0 and 8 '-t '.\n");
576                 return 0;
577         }
578 }
579
580 static int set_extension(int argc, char **argv, void *data)
581 {
582         bContext *C = data;
583         if (argc >= 1) {
584                 if (CTX_data_scene(C)) {
585                         Scene *scene= CTX_data_scene(C);
586                         if (argv[1][0] == '0') {
587                                 scene->r.scemode &= ~R_EXTENSION;
588                         } else if (argv[1][0] == '1') {
589                                 scene->r.scemode |= R_EXTENSION;
590                         } else {
591                                 printf("\nError: Use '-x 1' or '-x 0' To set the extension option.\n");
592                         }
593                 } else {
594                         printf("\nError: no blend loaded. order the arguments so '-o ' is after '-x '.\n");
595                 }
596                 return 1;
597         } else {
598                 printf("\nError: you must specify a path after '- '.\n");
599                 return 0;
600         }
601 }
602
603 static int set_ge_parameters(int argc, char **argv, void *data)
604 {
605         SYS_SystemHandle syshandle = *(SYS_SystemHandle*)data;
606         int a = 0;
607 /**
608 gameengine parameters are automaticly put into system
609 -g [paramname = value]
610 -g [boolparamname]
611 example:
612 -g novertexarrays
613 -g maxvertexarraysize = 512
614 */
615
616         if(argc >= 1)
617         {
618                 char* paramname = argv[a];
619                 /* check for single value versus assignment */
620                 if (a+1 < argc && (*(argv[a+1]) == '='))
621                 {
622                         a++;
623                         if (a+1 < argc)
624                         {
625                                 a++;
626                                 /* assignment */
627                                 SYS_WriteCommandLineString(syshandle,paramname,argv[a]);
628                         }  else
629                         {
630                                 printf("error: argument assignment (%s) without value.\n",paramname);
631                                 return 0;
632                         }
633                         /* name arg eaten */
634
635                 } else {
636                         SYS_WriteCommandLineInt(syshandle,argv[a],1);
637
638                         /* doMipMap */
639                         if (!strcmp(argv[a],"nomipmap"))
640                         {
641                                 GPU_set_mipmap(0); //doMipMap = 0;
642                         }
643                         /* linearMipMap */
644                         if (!strcmp(argv[a],"linearmipmap"))
645                         {
646                                 GPU_set_linear_mipmap(1); //linearMipMap = 1;
647                         }
648
649
650                 } /* if (*(argv[a+1]) == '=') */
651         }
652
653         return a;
654 }
655
656 static int render_frame(int argc, char **argv, void *data)
657 {
658         bContext *C = data;
659         if (CTX_data_scene(C)) {
660                 Scene *scene= CTX_data_scene(C);
661
662                 if (argc > 1) {
663                         int frame = atoi(argv[1]);
664                         Render *re = RE_NewRender(scene->id.name);
665                         ReportList reports;
666
667                         BKE_reports_init(&reports, RPT_PRINT);
668
669                         frame = MIN2(MAXFRAME, MAX2(MINAFRAME, frame));
670
671                         RE_BlenderAnim(re, scene, frame, frame, scene->r.frame_step, &reports);
672                         return 1;
673                 } else {
674                         printf("\nError: frame number must follow '-f'.\n");
675                         return 0;
676                 }
677         } else {
678                 printf("\nError: no blend loaded. cannot use '-f'.\n");
679                 return 0;
680         }
681 }
682
683 static int render_animation(int argc, char **argv, void *data)
684 {
685         bContext *C = data;
686         if (CTX_data_scene(C)) {
687                 Scene *scene= CTX_data_scene(C);
688                 Render *re= RE_NewRender(scene->id.name);
689                 ReportList reports;
690                 BKE_reports_init(&reports, RPT_PRINT);
691                 RE_BlenderAnim(re, scene, scene->r.sfra, scene->r.efra, scene->r.frame_step, &reports);
692         } else {
693                 printf("\nError: no blend loaded. cannot use '-a'.\n");
694         }
695         return 0;
696 }
697
698 static int set_scene(int argc, char **argv, void *data)
699 {
700         if(argc > 1) {
701                 set_scene_name(argv[1]);
702                 return 1;
703         } else {
704                 printf("\nError: Scene name must follow '-S'.\n");
705                 return 0;
706         }
707 }
708
709 static int set_start_frame(int argc, char **argv, void *data)
710 {
711         bContext *C = data;
712         if (CTX_data_scene(C)) {
713                 Scene *scene= CTX_data_scene(C);
714                 if (argc > 1) {
715                         int frame = atoi(argv[1]);
716                         (scene->r.sfra) = MIN2(MAXFRAME, MAX2(1, frame));
717                         return 1;
718                 } else {
719                         printf("\nError: frame number must follow '-s'.\n");
720                         return 0;
721                 }
722         } else {
723                 printf("\nError: no blend loaded. cannot use '-s'.\n");
724                 return 0;
725         }
726 }
727
728 static int set_end_frame(int argc, char **argv, void *data)
729 {
730         bContext *C = data;
731         if (CTX_data_scene(C)) {
732                 Scene *scene= CTX_data_scene(C);
733                 if (argc > 1) {
734                         int frame = atoi(argv[1]);
735                         (scene->r.efra) = MIN2(MAXFRAME, MAX2(1, frame));
736                         return 1;
737                 } else {
738                         printf("\nError: frame number must follow '-e'.\n");
739                         return 0;
740                 }
741         } else {
742                 printf("\nError: no blend loaded. cannot use '-e'.\n");
743                 return 0;
744         }
745 }
746
747 static int set_skip_frame(int argc, char **argv, void *data)
748 {
749         bContext *C = data;
750         if (CTX_data_scene(C)) {
751                 Scene *scene= CTX_data_scene(C);
752                 if (argc > 1) {
753                         int frame = atoi(argv[1]);
754                         (scene->r.frame_step) = MIN2(MAXFRAME, MAX2(1, frame));
755                         return 1;
756                 } else {
757                         printf("\nError: number of frames must follow '-j'.\n");
758                         return 0;
759                 }
760         } else {
761                 printf("\nError: no blend loaded. cannot use '-j'.\n");
762                 return 0;
763         }
764 }
765
766 static int run_python(int argc, char **argv, void *data)
767 {
768         bContext *C = data;
769 #ifndef DISABLE_PYTHON
770         /* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */
771         if (argc > 1) {
772                 /* XXX, temp setting the WM is ugly, splash also does this :S */
773                 wmWindowManager *wm= CTX_wm_manager(C);
774                 wmWindow *prevwin= CTX_wm_window(C);
775
776                 if(wm->windows.first) {
777                         CTX_wm_window_set(C, wm->windows.first);
778
779                         BPY_run_python_script(C, argv[1], NULL, NULL); // use reports?
780
781                         CTX_wm_window_set(C, prevwin);
782                 }
783                 else {
784                         fprintf(stderr, "Python script \"%s\" running with missing context data.\n", argv[1]);
785                         BPY_run_python_script(C, argv[1], NULL, NULL); // use reports?
786                 }
787                 return 1;
788         } else {
789                 printf("\nError: you must specify a Python script after '-P '.\n");
790                 return 0;
791         }
792 #else
793         printf("This blender was built without python support\n");
794         return 0;
795 #endif /* DISABLE_PYTHON */
796 }
797
798 static int load_file(int argc, char **argv, void *data)
799 {
800         bContext *C = data;
801
802         /* Make the path absolute because its needed for relative linked blends to be found */
803         char filename[FILE_MAXDIR + FILE_MAXFILE];
804
805         BLI_strncpy(filename, argv[0], sizeof(filename));
806         BLI_convertstringcwd(filename);
807
808         if (G.background) {
809                 int retval = BKE_read_file(C, argv[0], NULL, NULL);
810
811                 /*we successfully loaded a blend file, get sure that
812                 pointcache works */
813                 if (retval!=0) {
814                         CTX_wm_manager_set(C, NULL); /* remove wm to force check */
815                         WM_check(C);
816                         G.relbase_valid = 1;
817                 }
818
819                 /* happens for the UI on file reading too (huh? (ton))*/
820         // XXX                  BKE_reset_undo();
821         //                              BKE_write_undo("original");     /* save current state */
822         } else {
823                 /* we are not running in background mode here, but start blender in UI mode with
824                    a file - this should do everything a 'load file' does */
825                 WM_read_file(C, filename, NULL);
826         }
827
828         G.file_loaded = 1;
829
830         return 0;
831 }
832
833 void setupArguments(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
834 {
835         //BLI_argsAdd(ba, arg, pass, BA_ArgCallback cb, C);
836
837         /* end argument processing after -- */
838         BLI_argsAdd(ba, "--", -1, end_arguments, NULL);
839
840         /* first pass: background mode, disable python and commands that exit after usage */
841         BLI_argsAdd(ba, "--help", 1, print_help, NULL);
842         BLI_argsAdd(ba, "-h", 1, print_help, NULL);
843         BLI_argsAdd(ba, "/?", 1, print_help, NULL);
844
845         BLI_argsAdd(ba, "--version", 1, print_version, NULL);
846         BLI_argsAdd(ba, "-v", 1, print_version, NULL);
847
848         BLI_argsAdd(ba, "-Y", 1, forked_tongue, NULL);
849         BLI_argsAdd(ba, "-y", 1, disable_python, NULL);
850
851         BLI_argsAdd(ba, "-fpe", 1, set_fpe, NULL);
852
853         BLI_argsAdd(ba, "-B", 1, background_mode, NULL);
854         BLI_argsAdd(ba, "-b", 1, background_mode, NULL);
855         BLI_argsAdd(ba, "-a", 1, playback_mode, NULL);
856
857         BLI_argsAdd(ba, "-d", 1, debug_mode, ba);
858
859         /* second pass: custom window stuff */
860         BLI_argsAdd(ba, "-p", 2, prefsize, NULL);
861         BLI_argsAdd(ba, "-w", 2, with_borders, NULL);
862         BLI_argsAdd(ba, "-W", 2, without_borders, NULL);
863         BLI_argsAdd(ba, "-R", 2, register_extension, ba);
864
865         /* third pass: disabling things and forcing settings */
866         BLI_argsAddCase(ba, "-nojoystick", 3, no_joystick, syshandle);
867         BLI_argsAddCase(ba, "-noglsl", 3, no_glsl, NULL);
868         BLI_argsAddCase(ba, "-noaudio", 3, no_audio, NULL);
869         BLI_argsAddCase(ba, "-setaudio", 3, set_audio, NULL);
870
871         /* fourth pass: processing arguments */
872         BLI_argsAdd(ba, "-g", 4, set_ge_parameters, syshandle);
873         BLI_argsAdd(ba, "-f", 4, render_frame, C);
874         BLI_argsAdd(ba, "-a", 4, render_animation, C);
875         BLI_argsAdd(ba, "-S", 4, set_scene, NULL);
876         BLI_argsAdd(ba, "-s", 4, set_start_frame, C);
877         BLI_argsAdd(ba, "-e", 4, set_end_frame, C);
878         BLI_argsAdd(ba, "-j", 4, set_skip_frame, C);
879         BLI_argsAdd(ba, "-P", 4, run_python, C);
880         BLI_argsAdd(ba, "-o", 4, set_output, C);
881         BLI_argsAdd(ba, "-E", 4, set_engine, C);
882         BLI_argsAdd(ba, "-F", 4, set_image_type, C);
883         BLI_argsAdd(ba, "-t", 4, set_threads, NULL);
884         BLI_argsAdd(ba, "-x", 4, set_extension, C);
885
886 }
887
888 int main(int argc, char **argv)
889 {
890         SYS_SystemHandle syshandle;
891         bContext *C= CTX_create();
892         bArgs *ba;
893
894 #ifdef WITH_BINRELOC
895         br_init( NULL );
896 #endif
897
898         setCallbacks();
899 #ifdef __APPLE__
900                 /* patch to ignore argument finder gives us (pid?) */
901         if (argc==2 && strncmp(argv[1], "-psn_", 5)==0) {
902                 extern int GHOST_HACK_getFirstFile(char buf[]);
903                 static char firstfilebuf[512];
904
905                 argc= 1;
906
907                 if (GHOST_HACK_getFirstFile(firstfilebuf)) {
908                         argc= 2;
909                         argv[1]= firstfilebuf;
910                 }
911         }
912
913 #endif
914
915 #ifdef __FreeBSD__
916         fpsetmask(0);
917 #endif
918
919         // copy path to executable in bprogname. playanim and creting runtimes
920         // need this.
921
922         BLI_where_am_i(bprogname, argv[0]);
923         
924         {       /* override the hard coded blender path */
925                 char *blender_path_env = getenv("BLENDERPATH");
926                 if(blender_path_env)
927                         BLI_strncpy(blender_path, blender_path_env, sizeof(blender_path));
928         }
929         
930         RNA_init();
931         RE_engines_init();
932
933                 /* Hack - force inclusion of the plugin api functions,
934                  * see blenpluginapi:pluginapi.c
935                  */
936         pluginapi_force_ref();
937
938         init_nodesystem();
939         
940         initglobals();  /* blender.c */
941
942         syshandle = SYS_GetSystem();
943         GEN_init_messaging_system();
944
945         /* first test for background */
946
947         G.f |= G_DOSCRIPTLINKS; /* script links enabled by default */
948
949         ba = BLI_argsInit(argc, argv); /* skip binary path */
950         setupArguments(C, ba, &syshandle);
951
952         BLI_argsParse(ba, 1, NULL, NULL);
953
954 #ifdef __sgi
955         setuid(getuid()); /* end superuser */
956 #endif
957
958
959         /* for all platforms, even windos has it! */
960         if(G.background) signal(SIGINT, blender_esc);   /* ctrl c out bg render */
961         
962         /* background render uses this font too */
963         BKE_font_register_builtin(datatoc_Bfont, datatoc_Bfont_size);
964         
965         init_def_material();
966
967         if(G.background==0) {
968                 BLI_argsParse(ba, 2, NULL, NULL);
969                 BLI_argsParse(ba, 3, NULL, NULL);
970
971                 WM_init(C, argc, argv);
972                 
973                 // XXX BRECHT SOLVE
974                 BLI_where_is_temp( btempdir, 1 ); /* call after loading the .B.blend so we can read U.tempdir */
975
976 #ifndef DISABLE_SDL
977         BLI_setenv("SDL_VIDEODRIVER", "dummy");
978 #ifdef __linux__
979         /* On linux the default SDL driver dma often would not play
980          * use alsa if none is set */
981         setenv("SDL_AUDIODRIVER", "alsa", 0);
982 #endif
983 #endif
984         }
985         else {
986                 BLI_argsParse(ba, 3, NULL, NULL);
987
988                 WM_init(C, argc, argv);
989
990                 BLI_where_is_temp( btempdir, 0 ); /* call after loading the .B.blend so we can read U.tempdir */
991         }
992 #ifndef DISABLE_PYTHON
993         /**
994          * NOTE: the U.pythondir string is NULL until WM_init() is executed,
995          * so we provide the BPY_ function below to append the user defined
996          * pythondir to Python's sys.path at this point.  Simply putting
997          * WM_init() before BPY_start_python() crashes Blender at startup.
998          * Update: now this function also inits the bpymenus, which also depend
999          * on U.pythondir.
1000          */
1001         
1002         // TODO - U.pythondir
1003
1004 #endif
1005         
1006         CTX_py_init_set(C, 1);
1007         WM_keymap_init(C);
1008
1009 #ifdef WITH_QUICKTIME
1010
1011         quicktime_init();
1012
1013 #endif /* WITH_QUICKTIME */
1014
1015         /* dynamically load libtiff, if available */
1016         libtiff_init();
1017         if (!G.have_libtiff && (G.f & G_DEBUG)) {
1018                 printf("Unable to load: libtiff.\n");
1019                 printf("Try setting the BF_TIFF_LIB environment variable if you want this support.\n");
1020                 printf("Example: setenv BF_TIFF_LIB /usr/lib/libtiff.so\n");
1021         }
1022
1023         /* OK we are ready for it */
1024         BLI_argsParse(ba, 4, load_file, C);
1025
1026         BLI_argsFree(ba);
1027
1028         if(G.background) {
1029                 /* actually incorrect, but works for now (ton) */
1030                 WM_exit(C);
1031         }
1032
1033         if(!G.background && !G.file_loaded)
1034                 WM_init_splash(C);
1035
1036         WM_main(C);
1037
1038
1039         /*XXX if (scr_init==0) {
1040                 main_init_screen();
1041         }
1042         
1043         screenmain();*/ /* main display loop */
1044
1045         return 0;
1046 } /* end of int main(argc,argv) */
1047
1048 static void error_cb(char *err)
1049 {
1050         
1051         printf("%s\n", err);    /* XXX do this in WM too */
1052 }
1053
1054 static void mem_error_cb(char *errorStr)
1055 {
1056         fputs(errorStr, stderr);
1057         fflush(stderr);
1058 }
1059
1060 static void setCallbacks(void)
1061 {
1062         /* Error output from the alloc routines: */
1063         MEM_set_error_callback(mem_error_cb);
1064
1065
1066         /* BLI_blenlib: */
1067
1068         BLI_setErrorCallBack(error_cb); /* */
1069 // XXX  BLI_setInterruptCallBack(blender_test_break);
1070
1071 }