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