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