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