Bevel Factor Mapping
[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 /* crash handler */
44 #ifdef WIN32
45 #  include <process.h> /* getpid */
46 #else
47 #  include <unistd.h> /* getpid */
48 #endif
49
50 #ifdef WIN32
51 #  include <windows.h>
52 #  include "utfconv.h"
53 #endif
54
55 /* for backtrace */
56 #if defined(__linux__) || defined(__APPLE__)
57 #  include <execinfo.h>
58 #elif defined(_MSV_VER)
59 #  include <DbgHelp.h>
60 #endif
61
62 #include <stdlib.h>
63 #include <stddef.h>
64 #include <string.h>
65 #include <errno.h>
66 #include <time.h>
67
68 /* This little block needed for linking to Blender... */
69
70 #include "MEM_guardedalloc.h"
71
72 #ifdef WIN32
73 #  include "BLI_winstuff.h"
74 #endif
75
76 #include "BLI_args.h"
77 #include "BLI_threads.h"
78 #include "BLI_utildefines.h"
79 #include "BLI_callbacks.h"
80 #include "BLI_blenlib.h"
81 #include "BLI_mempool.h"
82
83 #include "DNA_ID.h"
84 #include "DNA_scene_types.h"
85 #include "DNA_userdef_types.h"
86
87 #include "BKE_blender.h"
88 #include "BKE_brush.h"
89 #include "BKE_context.h"
90 #include "BKE_depsgraph.h" /* for DAG_on_visible_update */
91 #include "BKE_font.h"
92 #include "BKE_global.h"
93 #include "BKE_library.h"
94 #include "BKE_main.h"
95 #include "BKE_material.h"
96 #include "BKE_modifier.h"
97 #include "BKE_packedFile.h"
98 #include "BKE_scene.h"
99 #include "BKE_node.h"
100 #include "BKE_report.h"
101 #include "BKE_sound.h"
102 #include "BKE_image.h"
103 #include "BKE_particle.h"
104
105 #include "IMB_imbuf.h"  /* for IMB_init */
106
107 #ifdef WITH_PYTHON
108 #include "BPY_extern.h"
109 #endif
110
111 #include "RE_engine.h"
112 #include "RE_pipeline.h"
113
114 #include "ED_datafiles.h"
115 #include "ED_util.h"
116
117 #include "WM_api.h"
118
119 #include "RNA_define.h"
120
121 #include "GPU_draw.h"
122 #include "GPU_extensions.h"
123
124 #ifdef WITH_FREESTYLE
125 #  include "FRS_freestyle.h"
126 #endif
127
128 #ifdef WITH_BUILDINFO_HEADER
129 #  define BUILD_DATE
130 #endif
131
132 /* for passing information between creator and gameengine */
133 #ifdef WITH_GAMEENGINE
134 #  include "BL_System.h"
135 #else /* dummy */
136 #  define SYS_SystemHandle int
137 #endif
138
139 #include <signal.h>
140
141 #ifdef __FreeBSD__
142 #  include <sys/types.h>
143 #  include <floatingpoint.h>
144 #  include <sys/rtprio.h>
145 #endif
146
147 #ifdef WITH_BINRELOC
148 #  include "binreloc.h"
149 #endif
150
151 #ifdef WITH_LIBMV
152 #  include "libmv-capi.h"
153 #endif
154
155 /* from buildinfo.c */
156 #ifdef BUILD_DATE
157 extern char build_date[];
158 extern char build_time[];
159 extern char build_hash[];
160 extern unsigned long build_commit_timestamp;
161
162 /* TODO(sergey): ideally size need to be in sync with buildinfo.c */
163 extern char build_commit_date[16];
164 extern char build_commit_time[16];
165
166 extern char build_branch[];
167 extern char build_platform[];
168 extern char build_type[];
169 extern char build_cflags[];
170 extern char build_cxxflags[];
171 extern char build_linkflags[];
172 extern char build_system[];
173 #endif
174
175 /*      Local Function prototypes */
176 #ifdef WITH_PYTHON_MODULE
177 int  main_python_enter(int argc, const char **argv);
178 void main_python_exit(void);
179 #else
180 static int print_help(int argc, const char **argv, void *data);
181 static int print_version(int argc, const char **argv, void *data);
182 #endif
183
184 /* for the callbacks: */
185 #ifndef WITH_PYTHON_MODULE
186 #define BLEND_VERSION_FMT         "Blender %d.%02d (sub %d)"
187 #define BLEND_VERSION_ARG         BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION
188 /* pass directly to printf */
189 #define BLEND_VERSION_STRING_FMT  BLEND_VERSION_FMT "\n", BLEND_VERSION_ARG
190 #endif
191
192 /* Initialize callbacks for the modules that need them */
193 static void setCallbacks(void); 
194
195 #ifndef WITH_PYTHON_MODULE
196
197 static bool use_crash_handler = true;
198
199 /* set breakpoints here when running in debug mode, useful to catch floating point errors */
200 #if defined(__linux__) || defined(_WIN32) || defined(OSX_SSE_FPE)
201 static void fpe_handler(int UNUSED(sig))
202 {
203         // printf("SIGFPE trapped\n");
204 }
205 #endif
206
207 /* handling ctrl-c event in console */
208 #if !(defined(WITH_PYTHON_MODULE) || defined(WITH_HEADLESS))
209 static void blender_esc(int sig)
210 {
211         static int count = 0;
212         
213         G.is_break = TRUE;  /* forces render loop to read queue, not sure if its needed */
214         
215         if (sig == 2) {
216                 if (count) {
217                         printf("\nBlender killed\n");
218                         exit(2);
219                 }
220                 printf("\nSent an internal break event. Press ^C again to kill Blender\n");
221                 count++;
222         }
223 }
224 #endif
225
226 static int print_version(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
227 {
228         printf(BLEND_VERSION_STRING_FMT);
229 #ifdef BUILD_DATE
230         printf("\tbuild date: %s\n", build_date);
231         printf("\tbuild time: %s\n", build_time);
232         printf("\tbuild commit date: %s\n", build_commit_date);
233         printf("\tbuild commit time: %s\n", build_commit_time);
234         printf("\tbuild hash: %s\n", build_hash);
235         printf("\tbuild platform: %s\n", build_platform);
236         printf("\tbuild type: %s\n", build_type);
237         printf("\tbuild c flags: %s\n", build_cflags);
238         printf("\tbuild c++ flags: %s\n", build_cxxflags);
239         printf("\tbuild link flags: %s\n", build_linkflags);
240         printf("\tbuild system: %s\n", build_system);
241 #endif
242         exit(0);
243
244         return 0;
245 }
246
247 static int print_help(int UNUSED(argc), const char **UNUSED(argv), void *data)
248 {
249         bArgs *ba = (bArgs *)data;
250
251         printf(BLEND_VERSION_STRING_FMT);
252         printf("Usage: blender [args ...] [file] [args ...]\n\n");
253
254         printf("Render Options:\n");
255         BLI_argsPrintArgDoc(ba, "--background");
256         BLI_argsPrintArgDoc(ba, "--render-anim");
257         BLI_argsPrintArgDoc(ba, "--scene");
258         BLI_argsPrintArgDoc(ba, "--render-frame");
259         BLI_argsPrintArgDoc(ba, "--frame-start");
260         BLI_argsPrintArgDoc(ba, "--frame-end");
261         BLI_argsPrintArgDoc(ba, "--frame-jump");
262         BLI_argsPrintArgDoc(ba, "--render-output");
263         BLI_argsPrintArgDoc(ba, "--engine");
264         BLI_argsPrintArgDoc(ba, "--threads");
265         
266         printf("\n");
267         printf("Format Options:\n");
268         BLI_argsPrintArgDoc(ba, "--render-format");
269         BLI_argsPrintArgDoc(ba, "--use-extension");
270
271         printf("\n");
272         printf("Animation Playback Options:\n");
273         BLI_argsPrintArgDoc(ba, "-a");
274                                 
275         printf("\n");
276         printf("Window Options:\n");
277         BLI_argsPrintArgDoc(ba, "--window-border");
278         BLI_argsPrintArgDoc(ba, "--window-borderless");
279         BLI_argsPrintArgDoc(ba, "--window-geometry");
280         BLI_argsPrintArgDoc(ba, "--start-console");
281         BLI_argsPrintArgDoc(ba, "--no-native-pixels");
282
283
284         printf("\n");
285         printf("Game Engine Specific Options:\n");
286         BLI_argsPrintArgDoc(ba, "-g");
287
288         printf("\n");
289         printf("Python Options:\n");
290         BLI_argsPrintArgDoc(ba, "--enable-autoexec");
291         BLI_argsPrintArgDoc(ba, "--disable-autoexec");
292
293         printf("\n");
294
295         BLI_argsPrintArgDoc(ba, "--python");
296         BLI_argsPrintArgDoc(ba, "--python-text");
297         BLI_argsPrintArgDoc(ba, "--python-console");
298         BLI_argsPrintArgDoc(ba, "--addons");
299
300
301         printf("\n");
302         printf("Debug Options:\n");
303         BLI_argsPrintArgDoc(ba, "--debug");
304         BLI_argsPrintArgDoc(ba, "--debug-value");
305
306         printf("\n");
307         BLI_argsPrintArgDoc(ba, "--debug-events");
308 #ifdef WITH_FFMPEG
309         BLI_argsPrintArgDoc(ba, "--debug-ffmpeg");
310 #endif
311         BLI_argsPrintArgDoc(ba, "--debug-handlers");
312 #ifdef WITH_LIBMV
313         BLI_argsPrintArgDoc(ba, "--debug-libmv");
314 #endif
315         BLI_argsPrintArgDoc(ba, "--debug-memory");
316         BLI_argsPrintArgDoc(ba, "--debug-jobs");
317         BLI_argsPrintArgDoc(ba, "--debug-python");
318         BLI_argsPrintArgDoc(ba, "--debug-depsgraph");
319
320         BLI_argsPrintArgDoc(ba, "--debug-wm");
321         BLI_argsPrintArgDoc(ba, "--debug-all");
322
323         printf("\n");
324         BLI_argsPrintArgDoc(ba, "--debug-fpe");
325         BLI_argsPrintArgDoc(ba, "--disable-crash-handler");
326
327         printf("\n");
328         printf("Misc Options:\n");
329         BLI_argsPrintArgDoc(ba, "--factory-startup");
330         printf("\n");
331         BLI_argsPrintArgDoc(ba, "--env-system-config");
332         BLI_argsPrintArgDoc(ba, "--env-system-datafiles");
333         BLI_argsPrintArgDoc(ba, "--env-system-scripts");
334         BLI_argsPrintArgDoc(ba, "--env-system-python");
335         printf("\n");
336         BLI_argsPrintArgDoc(ba, "-nojoystick");
337         BLI_argsPrintArgDoc(ba, "-noglsl");
338         BLI_argsPrintArgDoc(ba, "-noaudio");
339         BLI_argsPrintArgDoc(ba, "-setaudio");
340
341         printf("\n");
342
343         BLI_argsPrintArgDoc(ba, "--help");
344
345 #ifdef WIN32
346         BLI_argsPrintArgDoc(ba, "-R");
347         BLI_argsPrintArgDoc(ba, "-r");
348 #endif
349         BLI_argsPrintArgDoc(ba, "--version");
350
351         BLI_argsPrintArgDoc(ba, "--");
352
353         printf("Other Options:\n");
354         BLI_argsPrintOtherDoc(ba);
355
356         printf("Argument Parsing:\n");
357         printf("\targuments must be separated by white space. eg\n");
358         printf("\t\t\"blender -ba test.blend\"\n");
359         printf("\t...will ignore the 'a'\n");
360         printf("\t\t\"blender -b test.blend -f8\"\n");
361         printf("\t...will ignore 8 because there is no space between the -f and the frame value\n\n");
362
363         printf("Argument Order:\n");
364         printf("\targuments are executed in the order they are given. eg\n");
365         printf("\t\t\"blender --background test.blend --render-frame 1 --render-output /tmp\"\n");
366         printf("\t...will not render to /tmp because '--render-frame 1' renders before the output path is set\n");
367         printf("\t\t\"blender --background --render-output /tmp test.blend --render-frame 1\"\n");
368         printf("\t...will not render to /tmp because loading the blend file overwrites the render output that was set\n");
369         printf("\t\t\"blender --background test.blend --render-output /tmp --render-frame 1\" works as expected.\n\n");
370
371         printf("\nEnvironment Variables:\n");
372         printf("  $BLENDER_USER_CONFIG      Directory for user configuration files.\n");
373         printf("  $BLENDER_USER_SCRIPTS     Directory for user scripts.\n");
374         printf("  $BLENDER_SYSTEM_SCRIPTS   Directory for system wide scripts.\n");
375         printf("  $BLENDER_USER_DATAFILES   Directory for user data files (icons, translations, ..).\n");
376         printf("  $BLENDER_SYSTEM_DATAFILES Directory for system wide data files.\n");
377         printf("  $BLENDER_SYSTEM_PYTHON    Directory for system python libraries.\n");
378 #ifdef WIN32
379         printf("  $TEMP                     Store temporary files here.\n");
380 #else
381         printf("  $TMP or $TMPDIR           Store temporary files here.\n");
382 #endif
383 #ifdef WITH_SDL
384         printf("  $SDL_AUDIODRIVER          LibSDL audio driver - alsa, esd, dma.\n");
385 #endif
386         printf("  $PYTHONHOME               Path to the python directory, eg. /usr/lib/python.\n\n");
387
388         exit(0);
389
390         return 0;
391 }
392
393 static int end_arguments(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
394 {
395         return -1;
396 }
397
398 static int enable_python(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
399 {
400         G.f |= G_SCRIPT_AUTOEXEC;
401         G.f |= G_SCRIPT_OVERRIDE_PREF;
402         return 0;
403 }
404
405 static int disable_python(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
406 {
407         G.f &= ~G_SCRIPT_AUTOEXEC;
408         G.f |= G_SCRIPT_OVERRIDE_PREF;
409         return 0;
410 }
411
412 static int disable_crash_handler(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
413 {
414         use_crash_handler = false;
415         return 0;
416 }
417
418 static int background_mode(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
419 {
420         G.background = 1;
421         return 0;
422 }
423
424 static int debug_mode(int UNUSED(argc), const char **UNUSED(argv), void *data)
425 {
426         G.debug |= G_DEBUG;  /* std output printf's */
427         printf(BLEND_VERSION_STRING_FMT);
428         MEM_set_memory_debug();
429 #ifdef DEBUG
430         BLI_mempool_set_memory_debug();
431 #endif
432
433 #ifdef WITH_BUILDINFO
434         printf("Build: %s %s %s %s\n", build_date, build_time, build_platform, build_type);
435 #endif
436
437         BLI_argsPrint(data);
438         return 0;
439 }
440
441 static int debug_mode_generic(int UNUSED(argc), const char **UNUSED(argv), void *data)
442 {
443         G.debug |= GET_INT_FROM_POINTER(data);
444         return 0;
445 }
446
447 #ifdef WITH_LIBMV
448 static int debug_mode_libmv(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
449 {
450         libmv_startDebugLogging();
451
452         return 0;
453 }
454 #endif
455
456 static int debug_mode_memory(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
457 {
458         MEM_set_memory_debug();
459         return 0;
460 }
461
462 static int set_debug_value(int argc, const char **argv, void *UNUSED(data))
463 {
464         if (argc > 1) {
465                 G.debug_value = atoi(argv[1]);
466
467                 return 1;
468         }
469         else {
470                 printf("\nError: you must specify debug value to set.\n");
471                 return 0;
472         }
473 }
474
475 static int set_fpe(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
476 {
477 #if defined(__linux__) || defined(_WIN32) || defined(OSX_SSE_FPE)
478         /* zealous but makes float issues a heck of a lot easier to find!
479          * set breakpoints on fpe_handler */
480         signal(SIGFPE, fpe_handler);
481
482 # if defined(__linux__) && defined(__GNUC__)
483         feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);
484 # endif /* defined(__linux__) && defined(__GNUC__) */
485 # if defined(OSX_SSE_FPE)
486         /* OSX uses SSE for floating point by default, so here 
487          * use SSE instructions to throw floating point exceptions */
488         _MM_SET_EXCEPTION_MASK(_MM_MASK_MASK & ~
489                                (_MM_MASK_OVERFLOW | _MM_MASK_INVALID | _MM_MASK_DIV_ZERO));
490 # endif /* OSX_SSE_FPE */
491 # if defined(_WIN32) && defined(_MSC_VER)
492         _controlfp_s(NULL, 0, _MCW_EM); /* enables all fp exceptions */
493         _controlfp_s(NULL, _EM_DENORMAL | _EM_UNDERFLOW | _EM_INEXACT, _MCW_EM); /* hide the ones we don't care about */
494 # endif /* _WIN32 && _MSC_VER */
495 #endif
496
497         return 0;
498 }
499
500 #if defined(__linux__) || defined(__APPLE__)
501
502 /* Unix */
503 static void blender_crash_handler_backtrace(FILE *fp)
504 {
505 #define SIZE 100
506         void *buffer[SIZE];
507         int nptrs;
508         char **strings;
509         int i;
510
511         fputs("\n# backtrace\n", fp);
512
513         /* include a backtrace for good measure */
514         nptrs = backtrace(buffer, SIZE);
515         strings = backtrace_symbols(buffer, nptrs);
516         for (i = 0; i < nptrs; i++) {
517                 fputs(strings[i], fp);
518                 fputc('\n', fp);
519         }
520
521         free(strings);
522 #undef SIZE
523 }
524
525 #elif defined(_MSC_VER)
526
527 static void blender_crash_handler_backtrace(FILE *fp)
528 {
529         (void)fp;
530
531 #if 0
532 #define MAXSYMBOL 256
533         unsigned short  i;
534         void *stack[SIZE];
535         unsigned short nframes;
536         SYMBOL_INFO     *symbolinfo;
537         HANDLE process;
538
539         process = GetCurrentProcess();
540
541         SymInitialize(process, NULL, TRUE);
542
543         nframes = CaptureStackBackTrace(0, SIZE, stack, NULL);
544         symbolinfo = MEM_callocN(sizeof(SYMBOL_INFO) + MAXSYMBOL * sizeof( char ), "crash Symbol table");
545         symbolinfo->MaxNameLen = MAXSYMBOL - 1;
546         symbolinfo->SizeOfStruct = sizeof(SYMBOL_INFO);
547
548         for (i = 0; i < nframes; i++) {
549                 SymFromAddr(process, ( DWORD64 )( stack[ i ] ), 0, symbolinfo);
550
551                 fprintf(fp, "%u: %s - 0x%0X\n", nframes - i - 1, symbolinfo->Name, symbolinfo->Address);
552         }
553
554         MEM_freeN(symbolinfo);
555 #endif
556 }
557
558 #else  /* non msvc/osx/linux */
559
560 static void blender_crash_handler_backtrace(FILE *fp)
561 {
562         (void)fp;
563 }
564
565 #endif
566
567 static void blender_crash_handler(int signum)
568 {
569
570 #if 0
571         {
572                 char fname[FILE_MAX];
573
574                 if (!G.main->name[0]) {
575                         BLI_make_file_string("/", fname, BLI_temporary_dir(), "crash.blend");
576                 }
577                 else {
578                         BLI_strncpy(fname, G.main->name, sizeof(fname));
579                         BLI_replace_extension(fname, sizeof(fname), ".crash.blend");
580                 }
581
582                 printf("Writing: %s\n", fname);
583                 fflush(stdout);
584
585                 BKE_undo_save_file(fname);
586         }
587 #endif
588
589         FILE *fp;
590         char header[512];
591         wmWindowManager *wm = G.main->wm.first;
592
593         char fname[FILE_MAX];
594
595         if (!G.main->name[0]) {
596                 BLI_join_dirfile(fname, sizeof(fname), BLI_temporary_dir(), "blender.crash.txt");
597         }
598         else {
599                 BLI_join_dirfile(fname, sizeof(fname), BLI_temporary_dir(), BLI_path_basename(G.main->name));
600                 BLI_replace_extension(fname, sizeof(fname), ".crash.txt");
601         }
602
603         printf("Writing: %s\n", fname);
604         fflush(stdout);
605
606 #ifndef BUILD_DATE
607         BLI_snprintf(header, sizeof(header), "# " BLEND_VERSION_FMT ", Unknown revision\n", BLEND_VERSION_ARG);
608 #else
609         BLI_snprintf(header, sizeof(header), "# " BLEND_VERSION_FMT ", Commit date: %s %s, Hash %s\n",
610                      BLEND_VERSION_ARG, build_commit_date, build_commit_time, build_hash);
611 #endif
612
613         /* open the crash log */
614         errno = 0;
615         fp = BLI_fopen(fname, "wb");
616         if (fp == NULL) {
617                 fprintf(stderr, "Unable to save '%s': %s\n",
618                         fname, errno ? strerror(errno) : "Unknown error opening file");
619         }
620         else {
621                 if (wm) {
622                         BKE_report_write_file_fp(fp, &wm->reports, header);
623                 }
624
625                 blender_crash_handler_backtrace(fp);
626
627                 fclose(fp);
628         }
629
630
631         /* really crash */
632         signal(signum, SIG_DFL);
633 #ifndef WIN32
634         kill(getpid(), signum);
635 #else
636         TerminateProcess(GetCurrentProcess(), signum);
637 #endif
638 }
639
640
641 static int set_factory_startup(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
642 {
643         G.factory_startup = 1;
644         return 0;
645 }
646
647 static int set_env(int argc, const char **argv, void *UNUSED(data))
648 {
649         /* "--env-system-scripts" --> "BLENDER_SYSTEM_SCRIPTS" */
650
651         char env[64] = "BLENDER";
652         char *ch_dst = env + 7; /* skip BLENDER */
653         const char *ch_src = argv[0] + 5; /* skip --env */
654
655         if (argc < 2) {
656                 printf("%s requires one argument\n", argv[0]);
657                 exit(1);
658         }
659
660         for (; *ch_src; ch_src++, ch_dst++) {
661                 *ch_dst = (*ch_src == '-') ? '_' : (*ch_src) - 32; /* toupper() */
662         }
663
664         *ch_dst = '\0';
665         BLI_setenv(env, argv[1]);
666         return 1;
667 }
668
669 static int playback_mode(int argc, const char **argv, void *UNUSED(data))
670 {
671         /* not if -b was given first */
672         if (G.background == 0) {
673 #ifdef WITH_FFMPEG
674                 /* Setup FFmpeg with current debug flags. */
675                 IMB_ffmpeg_init();
676 #endif
677
678                 WM_main_playanim(argc, argv); /* not the same argc and argv as before */
679                 exit(0); /* 2.4x didn't do this */
680         }
681
682         return -2;
683 }
684
685 static int prefsize(int argc, const char **argv, void *UNUSED(data))
686 {
687         int stax, stay, sizx, sizy;
688
689         if (argc < 5) {
690                 fprintf(stderr, "-p requires four arguments\n");
691                 exit(1);
692         }
693
694         stax = atoi(argv[1]);
695         stay = atoi(argv[2]);
696         sizx = atoi(argv[3]);
697         sizy = atoi(argv[4]);
698
699         WM_init_state_size_set(stax, stay, sizx, sizy);
700
701         return 4;
702 }
703
704 static int native_pixels(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
705 {
706         WM_init_native_pixels(false);
707         return 0;
708 }
709
710 static int with_borders(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
711 {
712         WM_init_state_normal_set();
713         return 0;
714 }
715
716 static int without_borders(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
717 {
718         WM_init_state_fullscreen_set();
719         return 0;
720 }
721
722 extern bool wm_start_with_console; /* wm_init_exit.c */
723 static int start_with_console(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
724 {
725         wm_start_with_console = true;
726         return 0;
727 }
728
729 static int register_extension(int UNUSED(argc), const char **UNUSED(argv), void *data)
730 {
731 #ifdef WIN32
732         if (data)
733                 G.background = 1;
734         RegisterBlendExtension();
735 #else
736         (void)data; /* unused */
737 #endif
738         return 0;
739 }
740
741 static int no_joystick(int UNUSED(argc), const char **UNUSED(argv), void *data)
742 {
743 #ifndef WITH_GAMEENGINE
744         (void)data;
745 #else
746         SYS_SystemHandle *syshandle = data;
747
748         /**
749          * don't initialize joysticks if user doesn't want to use joysticks
750          * failed joystick initialization delays over 5 seconds, before game engine start
751          */
752         SYS_WriteCommandLineInt(*syshandle, "nojoystick", 1);
753         if (G.debug & G_DEBUG) printf("disabling nojoystick\n");
754 #endif
755
756         return 0;
757 }
758
759 static int no_glsl(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
760 {
761         GPU_extensions_disable();
762         return 0;
763 }
764
765 static int no_audio(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
766 {
767         sound_force_device(0);
768         return 0;
769 }
770
771 static int set_audio(int argc, const char **argv, void *UNUSED(data))
772 {
773         if (argc < 1) {
774                 fprintf(stderr, "-setaudio require one argument\n");
775                 exit(1);
776         }
777
778         sound_force_device(sound_define_from_str(argv[1]));
779         return 1;
780 }
781
782 static int set_output(int argc, const char **argv, void *data)
783 {
784         bContext *C = data;
785         if (argc > 1) {
786                 Scene *scene = CTX_data_scene(C);
787                 if (scene) {
788                         BLI_strncpy(scene->r.pic, argv[1], sizeof(scene->r.pic));
789                 }
790                 else {
791                         printf("\nError: no blend loaded. cannot use '-o / --render-output'.\n");
792                 }
793                 return 1;
794         }
795         else {
796                 printf("\nError: you must specify a path after '-o  / --render-output'.\n");
797                 return 0;
798         }
799 }
800
801 static int set_engine(int argc, const char **argv, void *data)
802 {
803         bContext *C = data;
804         if (argc >= 2) {
805                 if (!strcmp(argv[1], "help")) {
806                         RenderEngineType *type = NULL;
807                         printf("Blender Engine Listing:\n");
808                         for (type = R_engines.first; type; type = type->next) {
809                                 printf("\t%s\n", type->idname);
810                         }
811                         exit(0);
812                 }
813                 else {
814                         Scene *scene = CTX_data_scene(C);
815                         if (scene) {
816                                 RenderData *rd = &scene->r;
817
818                                 if (BLI_findstring(&R_engines, argv[1], offsetof(RenderEngineType, idname))) {
819                                         BLI_strncpy_utf8(rd->engine, argv[1], sizeof(rd->engine));
820                                 }
821                         }
822                         else {
823                                 printf("\nError: no blend loaded. order the arguments so '-E  / --engine ' is after a blend is loaded.\n");
824                         }
825                 }
826
827                 return 1;
828         }
829         else {
830                 printf("\nEngine not specified, give 'help' for a list of available engines.\n");
831                 return 0;
832         }
833 }
834
835 static int set_image_type(int argc, const char **argv, void *data)
836 {
837         bContext *C = data;
838         if (argc > 1) {
839                 const char *imtype = argv[1];
840                 Scene *scene = CTX_data_scene(C);
841                 if (scene) {
842                         const char imtype_new = BKE_imtype_from_arg(imtype);
843
844                         if (imtype_new == R_IMF_IMTYPE_INVALID) {
845                                 printf("\nError: Format from '-F / --render-format' not known or not compiled in this release.\n");
846                         }
847                         else {
848                                 scene->r.im_format.imtype = imtype_new;
849                         }
850                 }
851                 else {
852                         printf("\nError: no blend loaded. order the arguments so '-F  / --render-format' is after the blend is loaded.\n");
853                 }
854                 return 1;
855         }
856         else {
857                 printf("\nError: you must specify a format after '-F  / --render-foramt'.\n");
858                 return 0;
859         }
860 }
861
862 static int set_threads(int argc, const char **argv, void *UNUSED(data))
863 {
864         if (argc > 1) {
865                 int threads = atoi(argv[1]);
866
867                 if (threads >= 0 && threads <= BLENDER_MAX_THREADS) {
868                         BLI_system_num_threads_override_set(threads);
869                 }
870                 else {
871                         printf("Error, threads has to be in range 0-%d\n", BLENDER_MAX_THREADS);
872                 }
873                 return 1;
874         }
875         else {
876                 printf("\nError: you must specify a number of threads between 0 and %d '-t / --threads'.\n", BLENDER_MAX_THREADS);
877                 return 0;
878         }
879 }
880
881 static int set_verbosity(int argc, const char **argv, void *UNUSED(data))
882 {
883         if (argc > 1) {
884                 int level = atoi(argv[1]);
885
886 #ifdef WITH_LIBMV
887                 libmv_setLoggingVerbosity(level);
888 #else
889                 (void)level;
890 #endif
891
892                 return 1;
893         }
894         else {
895                 printf("\nError: you must specify a verbosity level.\n");
896                 return 0;
897         }
898 }
899
900 static int set_extension(int argc, const char **argv, void *data)
901 {
902         bContext *C = data;
903         if (argc > 1) {
904                 Scene *scene = CTX_data_scene(C);
905                 if (scene) {
906                         if (argv[1][0] == '0') {
907                                 scene->r.scemode &= ~R_EXTENSION;
908                         }
909                         else if (argv[1][0] == '1') {
910                                 scene->r.scemode |= R_EXTENSION;
911                         }
912                         else {
913                                 printf("\nError: Use '-x 1 / -x 0' To set the extension option or '--use-extension'\n");
914                         }
915                 }
916                 else {
917                         printf("\nError: no blend loaded. order the arguments so '-o ' is after '-x '.\n");
918                 }
919                 return 1;
920         }
921         else {
922                 printf("\nError: you must specify a path after '- '.\n");
923                 return 0;
924         }
925 }
926
927 static int set_ge_parameters(int argc, const char **argv, void *data)
928 {
929         int a = 0;
930 #ifdef WITH_GAMEENGINE
931         SYS_SystemHandle syshandle = *(SYS_SystemHandle *)data;
932 #else
933         (void)data;
934 #endif
935
936         /**
937          * gameengine parameters are automatically put into system
938          * -g [paramname = value]
939          * -g [boolparamname]
940          * example:
941          * -g novertexarrays
942          * -g maxvertexarraysize = 512
943          */
944
945         if (argc >= 1) {
946                 const char *paramname = argv[a];
947                 /* check for single value versus assignment */
948                 if (a + 1 < argc && (*(argv[a + 1]) == '=')) {
949                         a++;
950                         if (a + 1 < argc) {
951                                 a++;
952                                 /* assignment */
953 #ifdef WITH_GAMEENGINE
954                                 SYS_WriteCommandLineString(syshandle, paramname, argv[a]);
955 #endif
956                         }
957                         else {
958                                 printf("error: argument assignment (%s) without value.\n", paramname);
959                                 return 0;
960                         }
961                         /* name arg eaten */
962
963                 }
964                 else {
965 #ifdef WITH_GAMEENGINE
966                         SYS_WriteCommandLineInt(syshandle, argv[a], 1);
967 #endif
968                         /* doMipMap */
969                         if (!strcmp(argv[a], "nomipmap")) {
970                                 GPU_set_mipmap(0); //doMipMap = 0;
971                         }
972                         /* linearMipMap */
973                         if (!strcmp(argv[a], "linearmipmap")) {
974                                 GPU_set_linear_mipmap(1); //linearMipMap = 1;
975                         }
976
977
978                 } /* if (*(argv[a + 1]) == '=') */
979         }
980
981         return a;
982 }
983
984 static int render_frame(int argc, const char **argv, void *data)
985 {
986         bContext *C = data;
987         Scene *scene = CTX_data_scene(C);
988         if (scene) {
989                 Main *bmain = CTX_data_main(C);
990
991                 if (argc > 1) {
992                         Render *re = RE_NewRender(scene->id.name);
993                         int frame;
994                         ReportList reports;
995
996                         switch (*argv[1]) {
997                                 case '+':
998                                         frame = scene->r.sfra + atoi(argv[1] + 1);
999                                         break;
1000                                 case '-':
1001                                         frame = (scene->r.efra - atoi(argv[1] + 1)) + 1;
1002                                         break;
1003                                 default:
1004                                         frame = atoi(argv[1]);
1005                                         break;
1006                         }
1007
1008                         BKE_reports_init(&reports, RPT_PRINT);
1009
1010                         frame = CLAMPIS(frame, MINAFRAME, MAXFRAME);
1011
1012                         RE_SetReports(re, &reports);
1013                         RE_BlenderAnim(re, bmain, scene, NULL, scene->lay, frame, frame, scene->r.frame_step);
1014                         RE_SetReports(re, NULL);
1015                         return 1;
1016                 }
1017                 else {
1018                         printf("\nError: frame number must follow '-f / --render-frame'.\n");
1019                         return 0;
1020                 }
1021         }
1022         else {
1023                 printf("\nError: no blend loaded. cannot use '-f / --render-frame'.\n");
1024                 return 0;
1025         }
1026 }
1027
1028 static int render_animation(int UNUSED(argc), const char **UNUSED(argv), void *data)
1029 {
1030         bContext *C = data;
1031         Scene *scene = CTX_data_scene(C);
1032         if (scene) {
1033                 Main *bmain = CTX_data_main(C);
1034                 Render *re = RE_NewRender(scene->id.name);
1035                 ReportList reports;
1036                 BKE_reports_init(&reports, RPT_PRINT);
1037                 RE_SetReports(re, &reports);
1038                 RE_BlenderAnim(re, bmain, scene, NULL, scene->lay, scene->r.sfra, scene->r.efra, scene->r.frame_step);
1039                 RE_SetReports(re, NULL);
1040         }
1041         else {
1042                 printf("\nError: no blend loaded. cannot use '-a'.\n");
1043         }
1044         return 0;
1045 }
1046
1047 static int set_scene(int argc, const char **argv, void *data)
1048 {
1049         if (argc > 1) {
1050                 bContext *C = data;
1051                 Scene *scene = BKE_scene_set_name(CTX_data_main(C), argv[1]);
1052                 if (scene) {
1053                         CTX_data_scene_set(C, scene);
1054                 }
1055                 return 1;
1056         }
1057         else {
1058                 printf("\nError: Scene name must follow '-S / --scene'.\n");
1059                 return 0;
1060         }
1061 }
1062
1063 static int set_start_frame(int argc, const char **argv, void *data)
1064 {
1065         bContext *C = data;
1066         Scene *scene = CTX_data_scene(C);
1067         if (scene) {
1068                 if (argc > 1) {
1069                         int frame = atoi(argv[1]);
1070                         (scene->r.sfra) = CLAMPIS(frame, MINFRAME, MAXFRAME);
1071                         return 1;
1072                 }
1073                 else {
1074                         printf("\nError: frame number must follow '-s / --frame-start'.\n");
1075                         return 0;
1076                 }
1077         }
1078         else {
1079                 printf("\nError: no blend loaded. cannot use '-s / --frame-start'.\n");
1080                 return 0;
1081         }
1082 }
1083
1084 static int set_end_frame(int argc, const char **argv, void *data)
1085 {
1086         bContext *C = data;
1087         Scene *scene = CTX_data_scene(C);
1088         if (scene) {
1089                 if (argc > 1) {
1090                         int frame = atoi(argv[1]);
1091                         (scene->r.efra) = CLAMPIS(frame, MINFRAME, MAXFRAME);
1092                         return 1;
1093                 }
1094                 else {
1095                         printf("\nError: frame number must follow '-e / --frame-end'.\n");
1096                         return 0;
1097                 }
1098         }
1099         else {
1100                 printf("\nError: no blend loaded. cannot use '-e / --frame-end'.\n");
1101                 return 0;
1102         }
1103 }
1104
1105 static int set_skip_frame(int argc, const char **argv, void *data)
1106 {
1107         bContext *C = data;
1108         Scene *scene = CTX_data_scene(C);
1109         if (scene) {
1110                 if (argc > 1) {
1111                         int frame = atoi(argv[1]);
1112                         (scene->r.frame_step) = CLAMPIS(frame, 1, MAXFRAME);
1113                         return 1;
1114                 }
1115                 else {
1116                         printf("\nError: number of frames to step must follow '-j / --frame-jump'.\n");
1117                         return 0;
1118                 }
1119         }
1120         else {
1121                 printf("\nError: no blend loaded. cannot use '-j / --frame-jump'.\n");
1122                 return 0;
1123         }
1124 }
1125
1126 /* macro for ugly context setup/reset */
1127 #ifdef WITH_PYTHON
1128 #define BPY_CTX_SETUP(_cmd)                                                   \
1129         {                                                                         \
1130                 wmWindowManager *wm = CTX_wm_manager(C);                              \
1131                 wmWindow *prevwin = CTX_wm_window(C);                                 \
1132                 Scene *prevscene = CTX_data_scene(C);                                 \
1133                 if (wm->windows.first) {                                              \
1134                         CTX_wm_window_set(C, wm->windows.first);                          \
1135                         _cmd;                                                             \
1136                         CTX_wm_window_set(C, prevwin);                                    \
1137                 }                                                                     \
1138                 else {                                                                \
1139                         fprintf(stderr, "Python script \"%s\" "                           \
1140                                 "running with missing context data.\n", argv[1]);         \
1141                         _cmd;                                                             \
1142                 }                                                                     \
1143                 CTX_data_scene_set(C, prevscene);                                     \
1144         } (void)0                                                                 \
1145
1146 #endif /* WITH_PYTHON */
1147
1148 static int run_python_file(int argc, const char **argv, void *data)
1149 {
1150 #ifdef WITH_PYTHON
1151         bContext *C = data;
1152
1153         /* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */
1154         if (argc > 1) {
1155                 /* Make the path absolute because its needed for relative linked blends to be found */
1156                 char filename[FILE_MAX];
1157                 BLI_strncpy(filename, argv[1], sizeof(filename));
1158                 BLI_path_cwd(filename);
1159
1160                 BPY_CTX_SETUP(BPY_filepath_exec(C, filename, NULL));
1161
1162                 return 1;
1163         }
1164         else {
1165                 printf("\nError: you must specify a filepath after '%s'.\n", argv[0]);
1166                 return 0;
1167         }
1168 #else
1169         (void)argc; (void)argv; (void)data; /* unused */
1170         printf("This blender was built without python support\n");
1171         return 0;
1172 #endif /* WITH_PYTHON */
1173 }
1174
1175 static int run_python_text(int argc, const char **argv, void *data)
1176 {
1177 #ifdef WITH_PYTHON
1178         bContext *C = data;
1179
1180         /* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */
1181         if (argc > 1) {
1182                 /* Make the path absolute because its needed for relative linked blends to be found */
1183                 struct Text *text = (struct Text *)BKE_libblock_find_name(ID_TXT, argv[1]);
1184
1185                 if (text) {
1186                         BPY_CTX_SETUP(BPY_text_exec(C, text, NULL, false));
1187                         return 1;
1188                 }
1189                 else {
1190                         printf("\nError: text block not found %s.\n", argv[1]);
1191                         return 1;
1192                 }
1193         }
1194         else {
1195                 printf("\nError: you must specify a text block after '%s'.\n", argv[0]);
1196                 return 0;
1197         }
1198 #else
1199         (void)argc; (void)argv; (void)data; /* unused */
1200         printf("This blender was built without python support\n");
1201         return 0;
1202 #endif /* WITH_PYTHON */
1203 }
1204
1205 static int run_python_console(int UNUSED(argc), const char **argv, void *data)
1206 {
1207 #ifdef WITH_PYTHON
1208         bContext *C = data;
1209
1210         BPY_CTX_SETUP(BPY_string_exec(C, "__import__('code').interact()"));
1211
1212         return 0;
1213 #else
1214         (void)argv; (void)data; /* unused */
1215         printf("This blender was built without python support\n");
1216         return 0;
1217 #endif /* WITH_PYTHON */
1218 }
1219
1220 static int set_addons(int argc, const char **argv, void *data)
1221 {
1222         /* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */
1223         if (argc > 1) {
1224 #ifdef WITH_PYTHON
1225                 const int slen = strlen(argv[1]) + 128;
1226                 char *str = malloc(slen);
1227                 bContext *C = data;
1228                 BLI_snprintf(str, slen, "[__import__('addon_utils').enable(i, default_set=False) for i in '%s'.split(',')]", argv[1]);
1229                 BPY_CTX_SETUP(BPY_string_exec(C, str));
1230                 free(str);
1231 #else
1232                 (void)argv; (void)data; /* unused */
1233 #endif /* WITH_PYTHON */
1234                 return 1;
1235         }
1236         else {
1237                 printf("\nError: you must specify a comma separated list after '--addons'.\n");
1238                 return 0;
1239         }
1240 }
1241
1242 static int load_file(int UNUSED(argc), const char **argv, void *data)
1243 {
1244         bContext *C = data;
1245
1246         /* Make the path absolute because its needed for relative linked blends to be found */
1247         char filename[FILE_MAX];
1248
1249         /* note, we could skip these, but so far we always tried to load these files */
1250         if (argv[0][0] == '-') {
1251                 fprintf(stderr, "unknown argument, loading as file: %s\n", argv[0]);
1252         }
1253
1254         BLI_strncpy(filename, argv[0], sizeof(filename));
1255         BLI_path_cwd(filename);
1256
1257         if (G.background) {
1258                 int retval;
1259
1260                 BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_PRE);
1261
1262                 retval = BKE_read_file(C, filename, NULL);
1263
1264                 /* we successfully loaded a blend file, get sure that
1265                  * pointcache works */
1266                 if (retval != BKE_READ_FILE_FAIL) {
1267                         wmWindowManager *wm = CTX_wm_manager(C);
1268                         Main *bmain = CTX_data_main(C);
1269
1270                         /* special case, 2.4x files */
1271                         if (wm == NULL && BLI_listbase_is_empty(&bmain->wm)) {
1272                                 extern void wm_add_default(bContext *C);
1273
1274                                 /* wm_add_default() needs the screen to be set. */
1275                                 CTX_wm_screen_set(C, bmain->screen.first);
1276                                 wm_add_default(C);
1277                         }
1278
1279                         CTX_wm_manager_set(C, NULL); /* remove wm to force check */
1280                         WM_check(C);
1281                         G.relbase_valid = 1;
1282                         if (CTX_wm_manager(C) == NULL) CTX_wm_manager_set(C, wm);  /* reset wm */
1283
1284                         /* WM_file_read would call normally */
1285                         ED_editors_init(C);
1286                         DAG_on_visible_update(bmain, TRUE);
1287                         BKE_scene_update_tagged(bmain->eval_ctx, bmain, CTX_data_scene(C));
1288                 }
1289                 else {
1290                         /* failed to load file, stop processing arguments */
1291                         return -1;
1292                 }
1293
1294                 /* WM_file_read() runs normally but since we're in background mode do here */
1295 #ifdef WITH_PYTHON
1296                 /* run any texts that were loaded in and flagged as modules */
1297                 BPY_python_reset(C);
1298 #endif
1299
1300                 BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_POST);
1301
1302                 /* happens for the UI on file reading too (huh? (ton))*/
1303                 // XXX          BKE_reset_undo();
1304                 //                      BKE_write_undo("original");     /* save current state */
1305         }
1306         else {
1307                 /* we are not running in background mode here, but start blender in UI mode with
1308                  * a file - this should do everything a 'load file' does */
1309                 ReportList reports;
1310                 BKE_reports_init(&reports, RPT_PRINT);
1311                 WM_file_autoexec_init(filename);
1312                 WM_file_read(C, filename, &reports);
1313                 BKE_reports_clear(&reports);
1314         }
1315
1316         G.file_loaded = 1;
1317
1318         return 0;
1319 }
1320
1321 static void setupArguments(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
1322 {
1323         static char output_doc[] = "<path>"
1324                 "\n\tSet the render path and file name."
1325                 "\n\tUse // at the start of the path to"
1326                 "\n\t\trender relative to the blend file."
1327                 "\n\tThe # characters are replaced by the frame number, and used to define zero padding."
1328                 "\n\t\tani_##_test.png becomes ani_01_test.png"
1329                 "\n\t\ttest-######.png becomes test-000001.png"
1330                 "\n\t\tWhen the filename does not contain #, The suffix #### is added to the filename"
1331                 "\n\tThe frame number will be added at the end of the filename."
1332                 "\n\t\teg: blender -b foobar.blend -o //render_ -F PNG -x 1 -a"
1333                 "\n\t\t//render_ becomes //render_####, writing frames as //render_0001.png//";
1334
1335         static char format_doc[] = "<format>"
1336                 "\n\tSet the render format, Valid options are..."
1337                 "\n\t\tTGA IRIS JPEG MOVIE IRIZ RAWTGA"
1338                 "\n\t\tAVIRAW AVIJPEG PNG BMP FRAMESERVER"
1339                 "\n\t(formats that can be compiled into blender, not available on all systems)"
1340                 "\n\t\tHDR TIFF EXR MULTILAYER MPEG AVICODEC QUICKTIME CINEON DPX DDS";
1341
1342         static char playback_doc[] = "<options> <file(s)>"
1343                 "\n\tPlayback <file(s)>, only operates this way when not running in background."
1344                 "\n\t\t-p <sx> <sy>\tOpen with lower left corner at <sx>, <sy>"
1345                 "\n\t\t-m\t\tRead from disk (Don't buffer)"
1346                 "\n\t\t-f <fps> <fps-base>\t\tSpecify FPS to start with"
1347                 "\n\t\t-j <frame>\tSet frame step to <frame>"
1348                 "\n\t\t-s <frame>\tPlay from <frame>"
1349                 "\n\t\t-e <frame>\tPlay until <frame>";
1350
1351         static char game_doc[] = "Game Engine specific options"
1352                 "\n\t-g fixedtime\t\tRun on 50 hertz without dropping frames"
1353                 "\n\t-g vertexarrays\t\tUse Vertex Arrays for rendering (usually faster)"
1354                 "\n\t-g nomipmap\t\tNo Texture Mipmapping"
1355                 "\n\t-g linearmipmap\t\tLinear Texture Mipmapping instead of Nearest (default)";
1356
1357         static char debug_doc[] = "\n\tTurn debugging on\n"
1358                 "\n\t* Prints every operator call and their arguments"
1359                 "\n\t* Disables mouse grab (to interact with a debugger in some cases)"
1360                 "\n\t* Keeps python sys.stdin rather than setting it to None";
1361
1362         //BLI_argsAdd(ba, pass, short_arg, long_arg, doc, cb, C);
1363
1364         /* end argument processing after -- */
1365         BLI_argsAdd(ba, -1, "--", NULL, "\n\tEnds option processing, following arguments passed unchanged. Access via python's sys.argv", end_arguments, NULL);
1366
1367         /* first pass: background mode, disable python and commands that exit after usage */
1368         BLI_argsAdd(ba, 1, "-h", "--help", "\n\tPrint this help text and exit", print_help, ba);
1369         /* Windows only */
1370         BLI_argsAdd(ba, 1, "/?", NULL, "\n\tPrint this help text and exit (windows only)", print_help, ba);
1371
1372         BLI_argsAdd(ba, 1, "-v", "--version", "\n\tPrint Blender version and exit", print_version, NULL);
1373         
1374         /* only to give help message */
1375 #ifndef WITH_PYTHON_SECURITY /* default */
1376 #  define   PY_ENABLE_AUTO ", (default)"
1377 #  define   PY_DISABLE_AUTO ""
1378 #else
1379 #  define   PY_ENABLE_AUTO ""
1380 #  define   PY_DISABLE_AUTO ", (compiled as non-standard default)"
1381 #endif
1382
1383         BLI_argsAdd(ba, 1, "-y", "--enable-autoexec", "\n\tEnable automatic python script execution" PY_ENABLE_AUTO, enable_python, NULL);
1384         BLI_argsAdd(ba, 1, "-Y", "--disable-autoexec", "\n\tDisable automatic python script execution (pydrivers & startup scripts)" PY_DISABLE_AUTO, disable_python, NULL);
1385
1386         BLI_argsAdd(ba, 1, NULL, "--disable-crash-handler", "\n\tDisable the crash handler", disable_crash_handler, NULL);
1387
1388 #undef PY_ENABLE_AUTO
1389 #undef PY_DISABLE_AUTO
1390         
1391         BLI_argsAdd(ba, 1, "-b", "--background", "\n\tRun in background (often used for UI-less rendering)", background_mode, NULL);
1392
1393         BLI_argsAdd(ba, 1, "-a", NULL, playback_doc, playback_mode, NULL);
1394
1395         BLI_argsAdd(ba, 1, "-d", "--debug", debug_doc, debug_mode, ba);
1396
1397 #ifdef WITH_FFMPEG
1398         BLI_argsAdd(ba, 1, NULL, "--debug-ffmpeg", "\n\tEnable debug messages from FFmpeg library", debug_mode_generic, (void *)G_DEBUG_FFMPEG);
1399 #endif
1400
1401 #ifdef WITH_FREESTYLE
1402         BLI_argsAdd(ba, 1, NULL, "--debug-freestyle", "\n\tEnable debug/profiling messages from Freestyle rendering", debug_mode_generic, (void *)G_DEBUG_FREESTYLE);
1403 #endif
1404
1405         BLI_argsAdd(ba, 1, NULL, "--debug-python", "\n\tEnable debug messages for python", debug_mode_generic, (void *)G_DEBUG_PYTHON);
1406         BLI_argsAdd(ba, 1, NULL, "--debug-events", "\n\tEnable debug messages for the event system", debug_mode_generic, (void *)G_DEBUG_EVENTS);
1407         BLI_argsAdd(ba, 1, NULL, "--debug-handlers", "\n\tEnable debug messages for event handling", debug_mode_generic, (void *)G_DEBUG_HANDLERS);
1408         BLI_argsAdd(ba, 1, NULL, "--debug-wm",     "\n\tEnable debug messages for the window manager", debug_mode_generic, (void *)G_DEBUG_WM);
1409         BLI_argsAdd(ba, 1, NULL, "--debug-all",    "\n\tEnable all debug messages (excludes libmv)", debug_mode_generic, (void *)G_DEBUG_ALL);
1410
1411         BLI_argsAdd(ba, 1, NULL, "--debug-fpe", "\n\tEnable floating point exceptions", set_fpe, NULL);
1412
1413 #ifdef WITH_LIBMV
1414         BLI_argsAdd(ba, 1, NULL, "--debug-libmv", "\n\tEnable debug messages from libmv library", debug_mode_libmv, NULL);
1415 #endif
1416         BLI_argsAdd(ba, 1, NULL, "--debug-memory", "\n\tEnable fully guarded memory allocation and debugging", debug_mode_memory, NULL);
1417
1418         BLI_argsAdd(ba, 1, NULL, "--debug-value", "<value>\n\tSet debug value of <value> on startup\n", set_debug_value, NULL);
1419         BLI_argsAdd(ba, 1, NULL, "--debug-jobs",  "\n\tEnable time profiling for background jobs.", debug_mode_generic, (void *)G_DEBUG_JOBS);
1420         BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph", "\n\tEnable debug messages from dependency graph", debug_mode_generic, (void *)G_DEBUG_DEPSGRAPH);
1421
1422         BLI_argsAdd(ba, 1, NULL, "--verbose", "<verbose>\n\tSet logging verbosity level.", set_verbosity, NULL);
1423
1424         BLI_argsAdd(ba, 1, NULL, "--factory-startup", "\n\tSkip reading the "STRINGIFY (BLENDER_STARTUP_FILE)" in the users home directory", set_factory_startup, NULL);
1425
1426         /* TODO, add user env vars? */
1427         BLI_argsAdd(ba, 1, NULL, "--env-system-datafiles",  "\n\tSet the "STRINGIFY_ARG (BLENDER_SYSTEM_DATAFILES)" environment variable", set_env, NULL);
1428         BLI_argsAdd(ba, 1, NULL, "--env-system-scripts",    "\n\tSet the "STRINGIFY_ARG (BLENDER_SYSTEM_SCRIPTS)" environment variable", set_env, NULL);
1429         BLI_argsAdd(ba, 1, NULL, "--env-system-python",     "\n\tSet the "STRINGIFY_ARG (BLENDER_SYSTEM_PYTHON)" environment variable", set_env, NULL);
1430
1431         /* second pass: custom window stuff */
1432         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);
1433         BLI_argsAdd(ba, 2, "-w", "--window-border", "\n\tForce opening with borders (default)", with_borders, NULL);
1434         BLI_argsAdd(ba, 2, "-W", "--window-borderless", "\n\tForce opening without borders", without_borders, NULL);
1435         BLI_argsAdd(ba, 2, "-con", "--start-console", "\n\tStart with the console window open (ignored if -b is set), (Windows only)", start_with_console, NULL);
1436         BLI_argsAdd(ba, 2, "-R", NULL, "\n\tRegister .blend extension, then exit (Windows only)", register_extension, NULL);
1437         BLI_argsAdd(ba, 2, "-r", NULL, "\n\tSilently register .blend extension, then exit (Windows only)", register_extension, ba);
1438         BLI_argsAdd(ba, 2, NULL, "--no-native-pixels", "\n\tDo not use native pixel size, for high resolution displays (MacBook 'Retina')", native_pixels, ba);
1439
1440         /* third pass: disabling things and forcing settings */
1441         BLI_argsAddCase(ba, 3, "-nojoystick", 1, NULL, 0, "\n\tDisable joystick support", no_joystick, syshandle);
1442         BLI_argsAddCase(ba, 3, "-noglsl", 1, NULL, 0, "\n\tDisable GLSL shading", no_glsl, NULL);
1443         BLI_argsAddCase(ba, 3, "-noaudio", 1, NULL, 0, "\n\tForce sound system to None", no_audio, NULL);
1444         BLI_argsAddCase(ba, 3, "-setaudio", 1, NULL, 0, "\n\tForce sound system to a specific device\n\tNULL SDL OPENAL JACK", set_audio, NULL);
1445
1446         /* fourth pass: processing arguments */
1447         BLI_argsAdd(ba, 4, "-g", NULL, game_doc, set_ge_parameters, syshandle);
1448         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);
1449         BLI_argsAdd(ba, 4, "-a", "--render-anim", "\n\tRender frames from start to end (inclusive)", render_animation, C);
1450         BLI_argsAdd(ba, 4, "-S", "--scene", "<name>\n\tSet the active scene <name> for rendering", set_scene, C);
1451         BLI_argsAdd(ba, 4, "-s", "--frame-start", "<frame>\n\tSet start to frame <frame> (use before the -a argument)", set_start_frame, C);
1452         BLI_argsAdd(ba, 4, "-e", "--frame-end", "<frame>\n\tSet end to frame <frame> (use before the -a argument)", set_end_frame, C);
1453         BLI_argsAdd(ba, 4, "-j", "--frame-jump", "<frames>\n\tSet number of frames to step forward after each rendered frame", set_skip_frame, C);
1454         BLI_argsAdd(ba, 4, "-P", "--python", "<filename>\n\tRun the given Python script file", run_python_file, C);
1455         BLI_argsAdd(ba, 4, NULL, "--python-text", "<name>\n\tRun the given Python script text block", run_python_text, C);
1456         BLI_argsAdd(ba, 4, NULL, "--python-console", "\n\tRun blender with an interactive console", run_python_console, C);
1457         BLI_argsAdd(ba, 4, NULL, "--addons", "\n\tComma separated list of addons (no spaces)", set_addons, C);
1458
1459         BLI_argsAdd(ba, 4, "-o", "--render-output", output_doc, set_output, C);
1460         BLI_argsAdd(ba, 4, "-E", "--engine", "<engine>\n\tSpecify the render engine\n\tuse -E help to list available engines", set_engine, C);
1461
1462         BLI_argsAdd(ba, 4, "-F", "--render-format", format_doc, set_image_type, C);
1463         BLI_argsAdd(ba, 4, "-t", "--threads", "<threads>\n\tUse amount of <threads> for rendering and other operations\n\t[1-" STRINGIFY(BLENDER_MAX_THREADS) "], 0 for systems processor count.", set_threads, NULL);
1464         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);
1465
1466 }
1467 #endif /* WITH_PYTHON_MODULE */
1468
1469 #ifdef WITH_PYTHON_MODULE
1470 /* allow python module to call main */
1471 #  define main main_python_enter
1472 static void *evil_C = NULL;
1473
1474 #  ifdef __APPLE__
1475      /* environ is not available in mac shared libraries */
1476 #    include <crt_externs.h>
1477 char **environ = NULL;
1478 #  endif
1479 #endif
1480
1481
1482 #ifdef WIN32
1483 int main(int argc, const char **UNUSED(argv_c)) /* Do not mess with const */
1484 #else
1485 int main(int argc, const char **argv)
1486 #endif
1487 {
1488         bContext *C;
1489         SYS_SystemHandle syshandle;
1490
1491 #ifndef WITH_PYTHON_MODULE
1492         bArgs *ba;
1493 #endif
1494
1495 #ifdef WIN32 /* Win32 Unicode Args */
1496         /* NOTE: cannot use guardedalloc malloc here, as it's not yet initialized
1497          *       (it depends on the args passed in, which is what we're getting here!)
1498          */
1499         wchar_t **argv_16 = CommandLineToArgvW(GetCommandLineW(), &argc);
1500         char **argv = malloc(argc * sizeof(char *));
1501         int argci = 0;
1502         
1503         for (argci = 0; argci < argc; argci++) {
1504                 argv[argci] = alloc_utf_8_from_16(argv_16[argci], 0);
1505         }
1506         
1507         LocalFree(argv_16);
1508 #endif
1509
1510         /* NOTE: Special exception for guarded allocator type switch:
1511          *       we need to perform switch from lock-free to fully
1512          *       guarded allocator before any allocation happened.
1513          */
1514         {
1515                 int i;
1516                 for (i = 0; i < argc; i++) {
1517                         if (STREQ(argv[i], "--debug") || STREQ(argv[i], "-d") ||
1518                             STREQ(argv[i], "--debug-memory"))
1519                         {
1520                                 printf("Switching to fully guarded memory allocator.\n");
1521                                 MEM_use_guarded_allocator();
1522                                 break;
1523                         }
1524                         else if (STREQ(argv[i], "--")) {
1525                                 break;
1526                         }
1527                 }
1528         }
1529
1530 #ifdef BUILD_DATE
1531         {
1532                 time_t temp_time = build_commit_timestamp;
1533                 struct tm *tm = gmtime(&temp_time);
1534                 if (LIKELY(tm)) {
1535                         strftime(build_commit_date, sizeof(build_commit_date), "%Y-%m-%d", tm);
1536                         strftime(build_commit_time, sizeof(build_commit_time), "%H:%M", tm);
1537                 }
1538                 else {
1539                         const char *unknown = "date-unknown";
1540                         BLI_strncpy(build_commit_date, unknown, sizeof(build_commit_date));
1541                         BLI_strncpy(build_commit_time, unknown, sizeof(build_commit_time));
1542                 }
1543         }
1544 #endif
1545
1546         C = CTX_create();
1547
1548 #ifdef WITH_PYTHON_MODULE
1549 #ifdef __APPLE__
1550         environ = *_NSGetEnviron();
1551 #endif
1552
1553 #undef main
1554         evil_C = C;
1555 #endif
1556
1557
1558
1559 #ifdef WITH_BINRELOC
1560         br_init(NULL);
1561 #endif
1562
1563 #ifdef WITH_LIBMV
1564         libmv_initLogging(argv[0]);
1565 #endif
1566
1567         setCallbacks();
1568 #if defined(__APPLE__) && !defined(WITH_PYTHON_MODULE)
1569         /* patch to ignore argument finder gives us (pid?) */
1570         if (argc == 2 && strncmp(argv[1], "-psn_", 5) == 0) {
1571                 extern int GHOST_HACK_getFirstFile(char buf[]);
1572                 static char firstfilebuf[512];
1573
1574                 argc = 1;
1575
1576                 if (GHOST_HACK_getFirstFile(firstfilebuf)) {
1577                         argc = 2;
1578                         argv[1] = firstfilebuf;
1579                 }
1580         }
1581
1582 #endif
1583
1584 #ifdef __FreeBSD__
1585         fpsetmask(0);
1586 #endif
1587
1588         /* initialize path to executable */
1589         BLI_init_program_path(argv[0]);
1590
1591         BLI_threadapi_init();
1592
1593         initglobals();  /* blender.c */
1594
1595         IMB_init();
1596         BKE_images_init();
1597         BKE_modifier_init();
1598         DAG_init();
1599
1600         BKE_brush_system_init();
1601
1602         BLI_callback_global_init();
1603
1604 #ifdef WITH_GAMEENGINE
1605         syshandle = SYS_GetSystem();
1606 #else
1607         syshandle = 0;
1608 #endif
1609
1610         /* first test for background */
1611 #ifndef WITH_PYTHON_MODULE
1612         ba = BLI_argsInit(argc, (const char **)argv); /* skip binary path */
1613         setupArguments(C, ba, &syshandle);
1614
1615         BLI_argsParse(ba, 1, NULL, NULL);
1616
1617         if (use_crash_handler) {
1618                 /* after parsing args */
1619                 signal(SIGSEGV, blender_crash_handler);
1620         }
1621 #else
1622         G.factory_startup = true;  /* using preferences or user startup makes no sense for py-as-module */
1623         (void)syshandle;
1624 #endif
1625
1626 #ifdef WITH_FFMPEG
1627         IMB_ffmpeg_init();
1628 #endif
1629
1630         /* after level 1 args, this is so playanim skips RNA init */
1631         RNA_init();
1632
1633         RE_engines_init();
1634         init_nodesystem();
1635         psys_init_rng();
1636         /* end second init */
1637
1638
1639 #if defined(WITH_PYTHON_MODULE) || defined(WITH_HEADLESS)
1640         G.background = true; /* python module mode ALWAYS runs in background mode (for now) */
1641 #else
1642         /* for all platforms, even windos has it! */
1643         if (G.background) {
1644                 signal(SIGINT, blender_esc);  /* ctrl c out bg render */
1645         }
1646 #endif
1647
1648         /* background render uses this font too */
1649         BKE_vfont_builtin_register(datatoc_bfont_pfb, datatoc_bfont_pfb_size);
1650
1651         /* Initialize ffmpeg if built in, also needed for bg mode if videos are
1652          * rendered via ffmpeg */
1653         sound_init_once();
1654         
1655         init_def_material();
1656
1657         if (G.background == 0) {
1658 #ifndef WITH_PYTHON_MODULE
1659                 BLI_argsParse(ba, 2, NULL, NULL);
1660                 BLI_argsParse(ba, 3, NULL, NULL);
1661 #endif
1662                 WM_init(C, argc, (const char **)argv);
1663
1664                 /* this is properly initialized with user defs, but this is default */
1665                 /* call after loading the startup.blend so we can read U.tempdir */
1666                 BLI_init_temporary_dir(U.tempdir);
1667         }
1668         else {
1669 #ifndef WITH_PYTHON_MODULE
1670                 BLI_argsParse(ba, 3, NULL, NULL);
1671 #endif
1672
1673                 WM_init(C, argc, (const char **)argv);
1674
1675                 /* don't use user preferences temp dir */
1676                 BLI_init_temporary_dir(NULL);
1677         }
1678 #ifdef WITH_PYTHON
1679         /**
1680          * NOTE: the U.pythondir string is NULL until WM_init() is executed,
1681          * so we provide the BPY_ function below to append the user defined
1682          * python-dir to Python's sys.path at this point.  Simply putting
1683          * WM_init() before #BPY_python_start() crashes Blender at startup.
1684          */
1685
1686         /* TODO - U.pythondir */
1687 #else
1688         printf("\n* WARNING * - Blender compiled without Python!\nthis is not intended for typical usage\n\n");
1689 #endif
1690         
1691         CTX_py_init_set(C, 1);
1692         WM_keymap_init(C);
1693
1694 #ifdef WITH_FREESTYLE
1695         /* initialize Freestyle */
1696         FRS_initialize();
1697         FRS_set_context(C);
1698 #endif
1699
1700         /* OK we are ready for it */
1701 #ifndef WITH_PYTHON_MODULE
1702         BLI_argsParse(ba, 4, load_file, C);
1703         
1704         if (G.background == 0) {
1705                 if (!G.file_loaded)
1706                         if (U.uiflag2 & USER_KEEP_SESSION)
1707                                 WM_recover_last_session(C, NULL);
1708         }
1709
1710 #endif
1711
1712 #ifndef WITH_PYTHON_MODULE
1713         BLI_argsFree(ba);
1714 #endif
1715
1716 #ifdef WIN32
1717         while (argci) {
1718                 free(argv[--argci]);
1719         }
1720         free(argv);
1721         argv = NULL;
1722 #endif
1723
1724 #ifdef WITH_PYTHON_MODULE
1725         return 0; /* keep blender in background mode running */
1726 #endif
1727
1728         if (G.background) {
1729                 /* actually incorrect, but works for now (ton) */
1730                 WM_exit(C);
1731         }
1732         else {
1733                 if (G.fileflags & G_FILE_AUTOPLAY) {
1734                         if (G.f & G_SCRIPT_AUTOEXEC) {
1735                                 if (WM_init_game(C)) {
1736                                         return 0;
1737                                 }
1738                         }
1739                         else {
1740                                 if (!(G.f & G_SCRIPT_AUTOEXEC_FAIL_QUIET)) {
1741                                         G.f |= G_SCRIPT_AUTOEXEC_FAIL;
1742                                         BLI_snprintf(G.autoexec_fail, sizeof(G.autoexec_fail), "Game AutoStart");
1743                                 }
1744                         }
1745                 }
1746
1747                 if (!G.file_loaded) {
1748                         WM_init_splash(C);
1749                 }
1750         }
1751
1752         WM_main(C);
1753
1754         return 0;
1755 } /* end of int main(argc, argv)        */
1756
1757 #ifdef WITH_PYTHON_MODULE
1758 void main_python_exit(void)
1759 {
1760         WM_exit_ext((bContext *)evil_C, true);
1761         evil_C = NULL;
1762 }
1763 #endif
1764
1765 static void mem_error_cb(const char *errorStr)
1766 {
1767         fputs(errorStr, stderr);
1768         fflush(stderr);
1769 }
1770
1771 static void setCallbacks(void)
1772 {
1773         /* Error output from the alloc routines: */
1774         MEM_set_error_callback(mem_error_cb);
1775 }