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