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