Fix crash happening with hair step
[blender.git] / source / creator / creator_args.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  * ***** END GPL LICENSE BLOCK *****
19  */
20
21 /** \file creator/creator_args.c
22  *  \ingroup creator
23  */
24
25 #ifndef WITH_PYTHON_MODULE
26
27 #include <stdlib.h>
28 #include <string.h>
29 #include <errno.h>
30
31 #include "MEM_guardedalloc.h"
32
33 #include "CLG_log.h"
34
35 #ifdef WIN32
36 #  include "BLI_winstuff.h"
37 #endif
38
39 #include "BLI_args.h"
40 #include "BLI_threads.h"
41 #include "BLI_utildefines.h"
42 #include "BLI_listbase.h"
43 #include "BLI_string.h"
44 #include "BLI_string_utf8.h"
45 #include "BLI_path_util.h"
46 #include "BLI_fileops.h"
47 #include "BLI_mempool.h"
48 #include "BLI_system.h"
49
50 #include "BLO_readfile.h"  /* only for BLO_has_bfile_extension */
51
52 #include "BKE_blender_version.h"
53 #include "BKE_context.h"
54
55 #include "BKE_global.h"
56 #include "BKE_image.h"
57 #include "BKE_library.h"
58 #include "BKE_library_override.h"
59 #include "BKE_main.h"
60 #include "BKE_report.h"
61 #include "BKE_scene.h"
62 #include "BKE_sound.h"
63
64 #ifdef WITH_FFMPEG
65 #include "IMB_imbuf.h"
66 #endif
67
68 #ifdef WITH_PYTHON
69 #include "BPY_extern.h"
70 #endif
71
72 #include "RE_engine.h"
73 #include "RE_pipeline.h"
74
75 #include "ED_datafiles.h"
76
77 #include "WM_api.h"
78
79 #include "GPU_draw.h"
80
81 #ifdef WITH_LIBMV
82 #  include "libmv-capi.h"
83 #endif
84
85 #ifdef WITH_CYCLES_LOGGING
86 #  include "CCL_api.h"
87 #endif
88
89 #include "DEG_depsgraph.h"
90 #include "DEG_depsgraph_build.h"
91 #include "DEG_depsgraph_debug.h"
92
93 #include "creator_intern.h"  /* own include */
94
95
96 /* -------------------------------------------------------------------- */
97
98 /** \name Utility String Parsing
99  * \{ */
100
101 static bool parse_int_relative(
102         const char *str, const char *str_end_test, int pos, int neg,
103         int *r_value, const char **r_err_msg)
104 {
105         char *str_end = NULL;
106         long value;
107
108         errno = 0;
109
110         switch (*str) {
111                 case '+':
112                         value = pos + strtol(str + 1, &str_end, 10);
113                         break;
114                 case '-':
115                         value = (neg - strtol(str + 1, &str_end, 10)) + 1;
116                         break;
117                 default:
118                         value = strtol(str, &str_end, 10);
119                         break;
120         }
121
122
123         if (*str_end != '\0' && (str_end != str_end_test)) {
124                 static const char *msg = "not a number";
125                 *r_err_msg = msg;
126                 return false;
127         }
128         else if ((errno == ERANGE) || ((value < INT_MIN || value > INT_MAX))) {
129                 static const char *msg = "exceeds range";
130                 *r_err_msg = msg;
131                 return false;
132         }
133         else {
134                 *r_value = (int)value;
135                 return true;
136         }
137 }
138
139 static const char *parse_int_range_sep_search(const char *str, const char *str_end_test)
140 {
141         const char *str_end_range = NULL;
142         if (str_end_test) {
143                 str_end_range = memchr(str, '.', (str_end_test - str) - 1);
144                 if (str_end_range && (str_end_range[1] != '.')) {
145                         str_end_range = NULL;
146                 }
147         }
148         else {
149                 str_end_range = strstr(str, "..");
150                 if (str_end_range && (str_end_range[2] == '\0')) {
151                         str_end_range = NULL;
152                 }
153         }
154         return str_end_range;
155 }
156
157 /**
158  * Parse a number as a range, eg: `1..4`.
159  *
160  * The \a str_end_range argument is a result of #parse_int_range_sep_search.
161  */
162 static bool parse_int_range_relative(
163         const char *str, const char *str_end_range, const char *str_end_test, int pos, int neg,
164         int r_value_range[2], const char **r_err_msg)
165 {
166         if (parse_int_relative(str,               str_end_range, pos, neg, &r_value_range[0], r_err_msg) &&
167             parse_int_relative(str_end_range + 2, str_end_test,  pos, neg, &r_value_range[1], r_err_msg))
168         {
169                 return true;
170         }
171         else {
172                 return false;
173         }
174 }
175
176 static bool parse_int_relative_clamp(
177         const char *str, const char *str_end_test, int pos, int neg, int min, int max,
178         int *r_value, const char **r_err_msg)
179 {
180         if (parse_int_relative(str, str_end_test, pos, neg, r_value, r_err_msg)) {
181                 CLAMP(*r_value, min, max);
182                 return true;
183         }
184         else {
185                 return false;
186         }
187 }
188
189 static bool parse_int_range_relative_clamp(
190         const char *str, const char *str_end_range, const char *str_end_test, int pos, int neg, int min, int max,
191         int r_value_range[2], const char **r_err_msg)
192 {
193         if (parse_int_range_relative(str, str_end_range, str_end_test, pos, neg, r_value_range, r_err_msg)) {
194                 CLAMP(r_value_range[0], min, max);
195                 CLAMP(r_value_range[1], min, max);
196                 return true;
197         }
198         else {
199                 return false;
200         }
201 }
202
203 /**
204  * No clamping, fails with any number outside the range.
205  */
206 static bool parse_int_strict_range(
207         const char *str, const char *str_end_test, const int min, const int max,
208         int *r_value, const char **r_err_msg)
209 {
210         char *str_end = NULL;
211         long value;
212
213         errno = 0;
214         value = strtol(str, &str_end, 10);
215
216         if (*str_end != '\0' && (str_end != str_end_test)) {
217                 static const char *msg = "not a number";
218                 *r_err_msg = msg;
219                 return false;
220         }
221         else if ((errno == ERANGE) || ((value < min || value > max))) {
222                 static const char *msg = "exceeds range";
223                 *r_err_msg = msg;
224                 return false;
225         }
226         else {
227                 *r_value = (int)value;
228                 return true;
229         }
230 }
231
232 static bool parse_int(
233         const char *str, const char *str_end_test,
234         int *r_value, const char **r_err_msg)
235 {
236         return parse_int_strict_range(str, str_end_test, INT_MIN, INT_MAX, r_value, r_err_msg);
237 }
238
239 static bool parse_int_clamp(
240         const char *str, const char *str_end_test, int min, int max,
241         int *r_value, const char **r_err_msg)
242 {
243         if (parse_int(str, str_end_test, r_value, r_err_msg)) {
244                 CLAMP(*r_value, min, max);
245                 return true;
246         }
247         else {
248                 return false;
249         }
250 }
251
252 #if 0
253 /**
254  * Version of #parse_int_relative_clamp
255  * that parses a comma separated list of numbers.
256  */
257 static int *parse_int_relative_clamp_n(
258         const char *str, int pos, int neg, int min, int max,
259         int *r_value_len, const char **r_err_msg)
260 {
261         const char sep = ',';
262         int len = 1;
263         for (int i = 0; str[i]; i++) {
264                 if (str[i] == sep) {
265                         len++;
266                 }
267         }
268
269         int *values = MEM_mallocN(sizeof(*values) * len, __func__);
270         int i = 0;
271         while (true) {
272                 const char *str_end = strchr(str, sep);
273                 if ((*str == sep) || (*str == '\0')) {
274                         static const char *msg = "incorrect comma use";
275                         *r_err_msg = msg;
276                         goto fail;
277
278                 }
279                 else if (parse_int_relative_clamp(str, str_end, pos, neg, min, max, &values[i], r_err_msg)) {
280                         i++;
281                 }
282                 else {
283                         goto fail;  /* error message already set */
284                 }
285
286                 if (str_end) {  /* next */
287                         str = str_end + 1;
288                 }
289                 else {  /* finished */
290                         break;
291                 }
292         }
293
294         *r_value_len = i;
295         return values;
296
297 fail:
298         MEM_freeN(values);
299         return NULL;
300 }
301
302 #endif
303
304 /**
305  * Version of #parse_int_relative_clamp & #parse_int_range_relative_clamp
306  * that parses a comma separated list of numbers.
307  *
308  * \note single values are evaluated as a range with matching start/end.
309  */
310 static int (*parse_int_range_relative_clamp_n(
311         const char *str, int pos, int neg, int min, int max,
312         int *r_value_len, const char **r_err_msg))[2]
313 {
314         const char sep = ',';
315         int len = 1;
316         for (int i = 0; str[i]; i++) {
317                 if (str[i] == sep) {
318                         len++;
319                 }
320         }
321
322         int (*values)[2] = MEM_mallocN(sizeof(*values) * len, __func__);
323         int i = 0;
324         while (true) {
325                 const char *str_end_range;
326                 const char *str_end = strchr(str, sep);
327                 if ((*str == sep) || (*str == '\0')) {
328                         static const char *msg = "incorrect comma use";
329                         *r_err_msg = msg;
330                         goto fail;
331                 }
332                 else if ((str_end_range = parse_int_range_sep_search(str, str_end)) ?
333                          parse_int_range_relative_clamp(str, str_end_range, str_end, pos, neg, min, max, values[i], r_err_msg) :
334                          parse_int_relative_clamp(str, str_end, pos, neg, min, max, &values[i][0], r_err_msg))
335                 {
336                         if (str_end_range == NULL) {
337                                 values[i][1] = values[i][0];
338                         }
339                         i++;
340                 }
341                 else {
342                         goto fail;  /* error message already set */
343                 }
344
345                 if (str_end) {  /* next */
346                         str = str_end + 1;
347                 }
348                 else {  /* finished */
349                         break;
350                 }
351         }
352
353         *r_value_len = i;
354         return values;
355
356 fail:
357         MEM_freeN(values);
358         return NULL;
359 }
360
361 /** \} */
362
363
364 /* -------------------------------------------------------------------- */
365
366 #ifdef WITH_PYTHON
367
368 /** \name Utilities Python Context Macro (#BPY_CTX_SETUP)
369  * \{ */
370 struct BlendePyContextStore {
371         wmWindowManager *wm;
372         Scene *scene;
373         wmWindow *win;
374         bool has_win;
375 };
376
377 static void arg_py_context_backup(
378         bContext *C, struct BlendePyContextStore *c_py,
379         const char *script_id)
380 {
381         c_py->wm = CTX_wm_manager(C);
382         c_py->scene = CTX_data_scene(C);
383         c_py->has_win = !BLI_listbase_is_empty(&c_py->wm->windows);
384         if (c_py->has_win) {
385                 c_py->win = CTX_wm_window(C);
386                 CTX_wm_window_set(C, c_py->wm->windows.first);
387         }
388         else {
389                 c_py->win = NULL;
390                 fprintf(stderr, "Python script \"%s\" "
391                         "running with missing context data.\n", script_id);
392         }
393 }
394
395 static void arg_py_context_restore(
396         bContext *C, struct BlendePyContextStore *c_py)
397 {
398         /* script may load a file, check old data is valid before using */
399         if (c_py->has_win) {
400                 if ((c_py->win == NULL) ||
401                     ((BLI_findindex(&G_MAIN->wm, c_py->wm) != -1) &&
402                      (BLI_findindex(&c_py->wm->windows, c_py->win) != -1)))
403                 {
404                         CTX_wm_window_set(C, c_py->win);
405                 }
406         }
407
408         if ((c_py->scene == NULL) ||
409             BLI_findindex(&G_MAIN->scene, c_py->scene) != -1)
410         {
411                 CTX_data_scene_set(C, c_py->scene);
412         }
413 }
414
415 /* macro for context setup/reset */
416 #define BPY_CTX_SETUP(_cmd) \
417         { \
418                 struct BlendePyContextStore py_c; \
419                 arg_py_context_backup(C, &py_c, argv[1]); \
420                 { _cmd; } \
421                 arg_py_context_restore(C, &py_c); \
422         } ((void)0)
423
424 #endif /* WITH_PYTHON */
425
426 /** \} */
427
428 /* -------------------------------------------------------------------- */
429
430 /** \name Handle Argument Callbacks
431  *
432  * \note Doc strings here are used in differently:
433  *
434  * - The `--help` message.
435  * - The man page (for Unix systems),
436  *   see: `doc/manpage/blender.1.py`
437  * - Parsed and extracted for the manual,
438  *   which converts our ad-hoc formatting to reStructuredText.
439  *   see: https://docs.blender.org/manual/en/dev/advanced/command_line.html
440  *
441  * \{ */
442
443 static const char arg_handle_print_version_doc[] =
444 "\n\tPrint Blender version and exit."
445 ;
446 static int arg_handle_print_version(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
447 {
448         printf(BLEND_VERSION_STRING_FMT);
449 #ifdef BUILD_DATE
450         printf("\tbuild date: %s\n", build_date);
451         printf("\tbuild time: %s\n", build_time);
452         printf("\tbuild commit date: %s\n", build_commit_date);
453         printf("\tbuild commit time: %s\n", build_commit_time);
454         printf("\tbuild hash: %s\n", build_hash);
455         printf("\tbuild platform: %s\n", build_platform);
456         printf("\tbuild type: %s\n", build_type);
457         printf("\tbuild c flags: %s\n", build_cflags);
458         printf("\tbuild c++ flags: %s\n", build_cxxflags);
459         printf("\tbuild link flags: %s\n", build_linkflags);
460         printf("\tbuild system: %s\n", build_system);
461 #endif
462         exit(0);
463
464         return 0;
465 }
466
467 static const char arg_handle_print_help_doc[] =
468 "\n\tPrint this help text and exit."
469 ;
470 static const char arg_handle_print_help_doc_win32[] =
471 "\n\tPrint this help text and exit (windows only)."
472 ;
473 static int arg_handle_print_help(int UNUSED(argc), const char **UNUSED(argv), void *data)
474 {
475         bArgs *ba = (bArgs *)data;
476
477         printf(BLEND_VERSION_STRING_FMT);
478         printf("Usage: blender [args ...] [file] [args ...]\n\n");
479
480         printf("Render Options:\n");
481         BLI_argsPrintArgDoc(ba, "--background");
482         BLI_argsPrintArgDoc(ba, "--render-anim");
483         BLI_argsPrintArgDoc(ba, "--scene");
484         BLI_argsPrintArgDoc(ba, "--render-frame");
485         BLI_argsPrintArgDoc(ba, "--frame-start");
486         BLI_argsPrintArgDoc(ba, "--frame-end");
487         BLI_argsPrintArgDoc(ba, "--frame-jump");
488         BLI_argsPrintArgDoc(ba, "--render-output");
489         BLI_argsPrintArgDoc(ba, "--engine");
490         BLI_argsPrintArgDoc(ba, "--threads");
491
492         printf("\n");
493         printf("Format Options:\n");
494         BLI_argsPrintArgDoc(ba, "--render-format");
495         BLI_argsPrintArgDoc(ba, "--use-extension");
496
497         printf("\n");
498         printf("Animation Playback Options:\n");
499         BLI_argsPrintArgDoc(ba, "-a");
500
501         printf("\n");
502         printf("Window Options:\n");
503         BLI_argsPrintArgDoc(ba, "--window-border");
504         BLI_argsPrintArgDoc(ba, "--window-fullscreen");
505         BLI_argsPrintArgDoc(ba, "--window-geometry");
506         BLI_argsPrintArgDoc(ba, "--start-console");
507         BLI_argsPrintArgDoc(ba, "--no-native-pixels");
508         BLI_argsPrintArgDoc(ba, "--no-window-focus");
509
510         printf("\n");
511         printf("Python Options:\n");
512         BLI_argsPrintArgDoc(ba, "--enable-autoexec");
513         BLI_argsPrintArgDoc(ba, "--disable-autoexec");
514
515         printf("\n");
516
517         BLI_argsPrintArgDoc(ba, "--python");
518         BLI_argsPrintArgDoc(ba, "--python-text");
519         BLI_argsPrintArgDoc(ba, "--python-expr");
520         BLI_argsPrintArgDoc(ba, "--python-console");
521         BLI_argsPrintArgDoc(ba, "--python-exit-code");
522         BLI_argsPrintArgDoc(ba, "--addons");
523
524         printf("\n");
525         printf("Logging Options:\n");
526         BLI_argsPrintArgDoc(ba, "--log");
527         BLI_argsPrintArgDoc(ba, "--log-level");
528         BLI_argsPrintArgDoc(ba, "--log-show-basename");
529         BLI_argsPrintArgDoc(ba, "--log-show-backtrace");
530         BLI_argsPrintArgDoc(ba, "--log-show-timestamp");
531         BLI_argsPrintArgDoc(ba, "--log-file");
532
533         printf("\n");
534         printf("Debug Options:\n");
535         BLI_argsPrintArgDoc(ba, "--debug");
536         BLI_argsPrintArgDoc(ba, "--debug-value");
537
538         printf("\n");
539         BLI_argsPrintArgDoc(ba, "--debug-events");
540 #ifdef WITH_FFMPEG
541         BLI_argsPrintArgDoc(ba, "--debug-ffmpeg");
542 #endif
543         BLI_argsPrintArgDoc(ba, "--debug-handlers");
544 #ifdef WITH_LIBMV
545         BLI_argsPrintArgDoc(ba, "--debug-libmv");
546 #endif
547 #ifdef WITH_CYCLES_LOGGING
548         BLI_argsPrintArgDoc(ba, "--debug-cycles");
549 #endif
550         BLI_argsPrintArgDoc(ba, "--debug-memory");
551         BLI_argsPrintArgDoc(ba, "--debug-jobs");
552         BLI_argsPrintArgDoc(ba, "--debug-python");
553         BLI_argsPrintArgDoc(ba, "--debug-depsgraph");
554         BLI_argsPrintArgDoc(ba, "--debug-depsgraph-eval");
555         BLI_argsPrintArgDoc(ba, "--debug-depsgraph-build");
556         BLI_argsPrintArgDoc(ba, "--debug-depsgraph-tag");
557         BLI_argsPrintArgDoc(ba, "--debug-depsgraph-no-threads");
558
559         BLI_argsPrintArgDoc(ba, "--debug-gpumem");
560         BLI_argsPrintArgDoc(ba, "--debug-gpu-shaders");
561         BLI_argsPrintArgDoc(ba, "--debug-wm");
562         BLI_argsPrintArgDoc(ba, "--debug-all");
563         BLI_argsPrintArgDoc(ba, "--debug-io");
564
565         printf("\n");
566         BLI_argsPrintArgDoc(ba, "--debug-fpe");
567         BLI_argsPrintArgDoc(ba, "--disable-crash-handler");
568
569         printf("\n");
570         printf("Misc Options:\n");
571         BLI_argsPrintArgDoc(ba, "--app-template");
572         BLI_argsPrintArgDoc(ba, "--factory-startup");
573         BLI_argsPrintArgDoc(ba, "--enable-static-override");
574         printf("\n");
575         BLI_argsPrintArgDoc(ba, "--env-system-datafiles");
576         BLI_argsPrintArgDoc(ba, "--env-system-scripts");
577         BLI_argsPrintArgDoc(ba, "--env-system-python");
578         printf("\n");
579         BLI_argsPrintArgDoc(ba, "-noaudio");
580         BLI_argsPrintArgDoc(ba, "-setaudio");
581
582         printf("\n");
583
584         BLI_argsPrintArgDoc(ba, "--help");
585
586 #ifdef WIN32
587         BLI_argsPrintArgDoc(ba, "-R");
588         BLI_argsPrintArgDoc(ba, "-r");
589 #endif
590         BLI_argsPrintArgDoc(ba, "--version");
591
592         BLI_argsPrintArgDoc(ba, "--");
593
594         //printf("\n");
595         //printf("Experimental Features:\n");
596
597         /* Other options _must_ be last (anything not handled will show here) */
598         printf("\n");
599         printf("Other Options:\n");
600         BLI_argsPrintOtherDoc(ba);
601
602         printf("\n");
603         printf("Argument Parsing:\n");
604         printf("\tArguments must be separated by white space, eg:\n");
605         printf("\t# blender -ba test.blend\n");
606         printf("\t...will ignore the 'a'.\n");
607         printf("\t# blender -b test.blend -f8\n");
608         printf("\t...will ignore '8' because there is no space between the '-f' and the frame value.\n\n");
609
610         printf("Argument Order:\n");
611         printf("\tArguments are executed in the order they are given. eg:\n");
612         printf("\t# blender --background test.blend --render-frame 1 --render-output '/tmp'\n");
613         printf("\t...will not render to '/tmp' because '--render-frame 1' renders before the output path is set.\n");
614         printf("\t# blender --background --render-output /tmp test.blend --render-frame 1\n");
615         printf("\t...will not render to '/tmp' because loading the blend-file overwrites the render output that was set.\n");
616         printf("\t# blender --background test.blend --render-output /tmp --render-frame 1\n");
617         printf("\t...works as expected.\n\n");
618
619         printf("Environment Variables:\n");
620         printf("  $BLENDER_USER_CONFIG      Directory for user configuration files.\n");
621         printf("  $BLENDER_USER_SCRIPTS     Directory for user scripts.\n");
622         printf("  $BLENDER_SYSTEM_SCRIPTS   Directory for system wide scripts.\n");
623         printf("  $BLENDER_USER_DATAFILES   Directory for user data files (icons, translations, ..).\n");
624         printf("  $BLENDER_SYSTEM_DATAFILES Directory for system wide data files.\n");
625         printf("  $BLENDER_SYSTEM_PYTHON    Directory for system Python libraries.\n");
626 #ifdef WIN32
627         printf("  $TEMP                     Store temporary files here.\n");
628 #else
629         printf("  $TMP or $TMPDIR           Store temporary files here.\n");
630 #endif
631 #ifdef WITH_SDL
632         printf("  $SDL_AUDIODRIVER          LibSDL audio driver - alsa, esd, dma.\n");
633 #endif
634         printf("  $PYTHONHOME               Path to the Python directory, eg. /usr/lib/python.\n\n");
635
636         exit(0);
637
638         return 0;
639 }
640
641 static const char arg_handle_arguments_end_doc[] =
642 "\n\tEnd option processing, following arguments passed unchanged. Access via Python's 'sys.argv'."
643 ;
644 static int arg_handle_arguments_end(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
645 {
646         return -1;
647 }
648
649 /* only to give help message */
650 #ifndef WITH_PYTHON_SECURITY /* default */
651 #  define   PY_ENABLE_AUTO ", (default)"
652 #  define   PY_DISABLE_AUTO ""
653 #else
654 #  define   PY_ENABLE_AUTO ""
655 #  define   PY_DISABLE_AUTO ", (compiled as non-standard default)"
656 #endif
657
658 static const char arg_handle_python_set_doc_enable[] =
659 "\n\tEnable automatic Python script execution" PY_ENABLE_AUTO "."
660 ;
661 static const char arg_handle_python_set_doc_disable[] =
662 "\n\tDisable automatic Python script execution (pydrivers & startup scripts)" PY_DISABLE_AUTO "."
663 ;
664 #undef PY_ENABLE_AUTO
665 #undef PY_DISABLE_AUTO
666
667 static int arg_handle_python_set(int UNUSED(argc), const char **UNUSED(argv), void *data)
668 {
669         if ((bool)data) {
670                 G.f |= G_SCRIPT_AUTOEXEC;
671         }
672         else {
673                 G.f &= ~G_SCRIPT_AUTOEXEC;
674         }
675         G.f |= G_SCRIPT_OVERRIDE_PREF;
676         return 0;
677 }
678
679 static const char arg_handle_crash_handler_disable_doc[] =
680 "\n\tDisable the crash handler."
681 ;
682 static int arg_handle_crash_handler_disable(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
683 {
684         app_state.signal.use_crash_handler = false;
685         return 0;
686 }
687
688 static const char arg_handle_abort_handler_disable_doc[] =
689 "\n\tDisable the abort handler."
690 ;
691 static int arg_handle_abort_handler_disable(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
692 {
693         app_state.signal.use_abort_handler = false;
694         return 0;
695 }
696
697 static const char arg_handle_background_mode_set_doc[] =
698 "\n\tRun in background (often used for UI-less rendering)."
699 ;
700 static int arg_handle_background_mode_set(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
701 {
702         G.background = 1;
703         return 0;
704 }
705
706 static const char arg_handle_log_level_set_doc[] =
707 "<level>\n"
708 "\n"
709 "\tSet the logging verbosity level (higher for more details) defaults to 1, use -1 to log all levels."
710 ;
711 static int arg_handle_log_level_set(int argc, const char **argv, void *UNUSED(data))
712 {
713         const char *arg_id = "--log-level";
714         if (argc > 1) {
715                 const char *err_msg = NULL;
716                 if (!parse_int_clamp(argv[1], NULL, -1, INT_MAX, &G.log.level, &err_msg)) {
717                         printf("\nError: %s '%s %s'.\n", err_msg, arg_id, argv[1]);
718                 }
719                 else {
720                         if (G.log.level == -1) {
721                                 G.log.level = INT_MAX;
722                         }
723                         CLG_level_set(G.log.level);
724                 }
725                 return 1;
726         }
727         else {
728                 printf("\nError: '%s' no args given.\n", arg_id);
729                 return 0;
730         }
731 }
732
733 static const char arg_handle_log_show_basename_set_doc[] =
734 "\n\tOnly show file name in output (not the leading path)."
735 ;
736 static int arg_handle_log_show_basename_set(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
737 {
738         CLG_output_use_basename_set(true);
739         return 0;
740 }
741
742 static const char arg_handle_log_show_backtrace_set_doc[] =
743 "\n\tShow a back trace for each log message (debug builds only)."
744 ;
745 static int arg_handle_log_show_backtrace_set(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
746 {
747         /* Ensure types don't become incompatible. */
748         void (*fn)(FILE *fp) = BLI_system_backtrace;
749         CLG_backtrace_fn_set((void (*)(void *))fn);
750         return 0;
751 }
752
753 static const char arg_handle_log_show_timestamp_set_doc[] =
754 "\n\tShow a timestamp for each log message in seconds since start."
755 ;
756 static int arg_handle_log_show_timestamp_set(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
757 {
758         CLG_output_use_timestamp_set(true);
759         return 0;
760 }
761
762 static const char arg_handle_log_file_set_doc[] =
763 "<filename>\n"
764 "\n"
765 "\tSet a file to output the log to."
766 ;
767 static int arg_handle_log_file_set(int argc, const char **argv, void *UNUSED(data))
768 {
769         const char *arg_id = "--log-file";
770         if (argc > 1) {
771                 errno = 0;
772                 FILE *fp = BLI_fopen(argv[1], "w");
773                 if (fp == NULL) {
774                         const char *err_msg = errno ? strerror(errno) : "unknown";
775                         printf("\nError: %s '%s %s'.\n", err_msg, arg_id, argv[1]);
776                 }
777                 else {
778                         if (UNLIKELY(G.log.file != NULL)) {
779                                 fclose(G.log.file);
780                         }
781                         G.log.file = fp;
782                         CLG_output_set(G.log.file);
783                 }
784                 return 1;
785         }
786         else {
787                 printf("\nError: '%s' no args given.\n", arg_id);
788                 return 0;
789         }
790 }
791
792 static const char arg_handle_log_set_doc[] =
793 "<match>\n"
794 "\tEnable logging categories, taking a single comma separated argument.\n"
795 "\tMultiple categories can be matched using a '.*' suffix,\n"
796 "\tso '--log \"wm.*\"' logs every kind of window-manager message.\n"
797 "\tUse \"^\" prefix to ignore, so '--log \"*,^wm.operator.*\"' logs all except for 'wm.operators.*'\n"
798 "\tUse \"*\" to log everything."
799 ;
800 static int arg_handle_log_set(int argc, const char **argv, void *UNUSED(data))
801 {
802         const char *arg_id = "--log";
803         if (argc > 1) {
804                 const char *str_step = argv[1];
805                 while (*str_step) {
806                         const char *str_step_end = strchr(str_step, ',');
807                         int str_step_len = str_step_end ? (str_step_end - str_step) : strlen(str_step);
808
809                         if (str_step[0] == '^') {
810                                 CLG_type_filter_exclude(str_step + 1, str_step_len - 1);
811                         }
812                         else {
813                                 CLG_type_filter_include(str_step, str_step_len);
814                         }
815
816                         if (str_step_end) {
817                                 /* typically only be one, but don't fail on multiple.*/
818                                 while (*str_step_end == ',') {
819                                         str_step_end++;
820                                 }
821                                 str_step = str_step_end;
822                         }
823                         else {
824                                 break;
825                         }
826                 }
827                 return 1;
828         }
829         else {
830                 printf("\nError: '%s' no args given.\n", arg_id);
831                 return 0;
832         }
833 }
834
835 static const char arg_handle_debug_mode_set_doc[] =
836 "\n"
837 "\tTurn debugging on.\n"
838 "\n"
839 "\t* Enables memory error detection\n"
840 "\t* Disables mouse grab (to interact with a debugger in some cases)\n"
841 "\t* Keeps Python's 'sys.stdin' rather than setting it to None"
842 ;
843 static int arg_handle_debug_mode_set(int UNUSED(argc), const char **UNUSED(argv), void *data)
844 {
845         G.debug |= G_DEBUG;  /* std output printf's */
846         printf(BLEND_VERSION_STRING_FMT);
847         MEM_set_memory_debug();
848 #ifndef NDEBUG
849         BLI_mempool_set_memory_debug();
850 #endif
851
852 #ifdef WITH_BUILDINFO
853         printf("Build: %s %s %s %s\n", build_date, build_time, build_platform, build_type);
854 #endif
855
856         BLI_argsPrint(data);
857         return 0;
858 }
859
860 #ifdef WITH_FFMPEG
861 static const char arg_handle_debug_mode_generic_set_doc_ffmpeg[] =
862 "\n\tEnable debug messages from FFmpeg library.";
863 #endif
864 #ifdef WITH_FREESTYLE
865 static const char arg_handle_debug_mode_generic_set_doc_freestyle[] =
866 "\n\tEnable debug messages for FreeStyle.";
867 #endif
868 static const char arg_handle_debug_mode_generic_set_doc_python[] =
869 "\n\tEnable debug messages for Python.";
870 static const char arg_handle_debug_mode_generic_set_doc_events[] =
871 "\n\tEnable debug messages for the event system.";
872 static const char arg_handle_debug_mode_generic_set_doc_handlers[] =
873 "\n\tEnable debug messages for event handling.";
874 static const char arg_handle_debug_mode_generic_set_doc_wm[] =
875 "\n\tEnable debug messages for the window manager, shows all operators in search, shows keymap errors.";
876 static const char arg_handle_debug_mode_generic_set_doc_jobs[] =
877 "\n\tEnable time profiling for background jobs.";
878 static const char arg_handle_debug_mode_generic_set_doc_gpu[] =
879 "\n\tEnable gpu debug context and information for OpenGL 4.3+.";
880 static const char arg_handle_debug_mode_generic_set_doc_depsgraph[] =
881 "\n\tEnable all debug messages from dependency graph.";
882 static const char arg_handle_debug_mode_generic_set_doc_depsgraph_build[] =
883 "\n\tEnable debug messages from dependency graph related on graph construction.";
884 static const char arg_handle_debug_mode_generic_set_doc_depsgraph_tag[] =
885 "\n\tEnable debug messages from dependency graph related on tagging.";
886 static const char arg_handle_debug_mode_generic_set_doc_depsgraph_time[] =
887 "\n\tEnable debug messages from dependency graph related on timing.";
888 static const char arg_handle_debug_mode_generic_set_doc_depsgraph_eval[] =
889 "\n\tEnable debug messages from dependency graph related on evaluation.";
890 static const char arg_handle_debug_mode_generic_set_doc_depsgraph_no_threads[] =
891 "\n\tSwitch dependency graph to a single threaded evaluation.";
892 static const char arg_handle_debug_mode_generic_set_doc_depsgraph_pretty[] =
893 "\n\tEnable colors for dependency graph debug messages.";
894 static const char arg_handle_debug_mode_generic_set_doc_gpumem[] =
895 "\n\tEnable GPU memory stats in status bar.";
896
897 static int arg_handle_debug_mode_generic_set(int UNUSED(argc), const char **UNUSED(argv), void *data)
898 {
899         G.debug |= POINTER_AS_INT(data);
900         return 0;
901 }
902
903 static const char arg_handle_debug_mode_io_doc[] =
904 "\n\tEnable debug messages for I/O (collada, ...).";
905 static int arg_handle_debug_mode_io(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
906 {
907         G.debug |= G_DEBUG_IO;
908         return 0;
909 }
910
911 static const char arg_handle_debug_mode_all_doc[] =
912 "\n\tEnable all debug messages.";
913 static int arg_handle_debug_mode_all(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
914 {
915         G.debug |= G_DEBUG_ALL;
916 #ifdef WITH_LIBMV
917         libmv_startDebugLogging();
918 #endif
919 #ifdef WITH_CYCLES_LOGGING
920         CCL_start_debug_logging();
921 #endif
922         return 0;
923 }
924
925 #ifdef WITH_LIBMV
926 static const char arg_handle_debug_mode_libmv_doc[] =
927 "\n\tEnable debug messages from libmv library."
928 ;
929 static int arg_handle_debug_mode_libmv(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
930 {
931         libmv_startDebugLogging();
932
933         return 0;
934 }
935 #endif
936
937 #ifdef WITH_CYCLES_LOGGING
938 static const char arg_handle_debug_mode_cycles_doc[] =
939 "\n\tEnable debug messages from Cycles."
940 ;
941 static int arg_handle_debug_mode_cycles(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
942 {
943         CCL_start_debug_logging();
944         return 0;
945 }
946 #endif
947
948 static const char arg_handle_debug_mode_memory_set_doc[] =
949 "\n\tEnable fully guarded memory allocation and debugging."
950 ;
951 static int arg_handle_debug_mode_memory_set(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
952 {
953         MEM_set_memory_debug();
954         return 0;
955 }
956
957 static const char arg_handle_debug_value_set_doc[] =
958 "<value>\n"
959 "\tSet debug value of <value> on startup."
960 ;
961 static int arg_handle_debug_value_set(int argc, const char **argv, void *UNUSED(data))
962 {
963         const char *arg_id = "--debug-value";
964         if (argc > 1) {
965                 const char *err_msg = NULL;
966                 int value;
967                 if (!parse_int(argv[1], NULL, &value, &err_msg)) {
968                         printf("\nError: %s '%s %s'.\n", err_msg, arg_id, argv[1]);
969                         return 1;
970                 }
971
972                 G.debug_value = value;
973
974                 return 1;
975         }
976         else {
977                 printf("\nError: you must specify debug value to set.\n");
978                 return 0;
979         }
980 }
981
982 static const char arg_handle_debug_fpe_set_doc[] =
983 "\n\tEnable floating point exceptions."
984 ;
985 static int arg_handle_debug_fpe_set(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
986 {
987         main_signal_setup_fpe();
988         return 0;
989 }
990
991 static const char arg_handle_app_template_doc[] =
992 "\n\tSet the application template, use 'default' for none."
993 ;
994 static int arg_handle_app_template(int argc, const char **argv, void *UNUSED(data))
995 {
996         if (argc > 1) {
997                 const char *app_template = STREQ(argv[1], "default") ? "" : argv[1];
998                 WM_init_state_app_template_set(app_template);
999                 return 1;
1000         }
1001         else {
1002                 printf("\nError: App template must follow '--app-template'.\n");
1003                 return 0;
1004         }
1005 }
1006
1007 static const char arg_handle_factory_startup_set_doc[] =
1008 "\n\tSkip reading the " STRINGIFY(BLENDER_STARTUP_FILE) " in the users home directory."
1009 ;
1010 static int arg_handle_factory_startup_set(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
1011 {
1012         G.factory_startup = 1;
1013         return 0;
1014 }
1015
1016 static const char arg_handle_enable_static_override_doc[] =
1017 "\n\tEnable Static Override features in the UI."
1018 ;
1019 static int arg_handle_enable_static_override(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
1020 {
1021         BKE_override_static_enable(true);
1022         return 0;
1023 }
1024
1025 static const char arg_handle_env_system_set_doc_datafiles[] =
1026 "\n\tSet the "STRINGIFY_ARG (BLENDER_SYSTEM_DATAFILES)" environment variable.";
1027 static const char arg_handle_env_system_set_doc_scripts[] =
1028 "\n\tSet the "STRINGIFY_ARG (BLENDER_SYSTEM_SCRIPTS)" environment variable.";
1029 static const char arg_handle_env_system_set_doc_python[] =
1030 "\n\tSet the "STRINGIFY_ARG (BLENDER_SYSTEM_PYTHON)" environment variable.";
1031
1032 static int arg_handle_env_system_set(int argc, const char **argv, void *UNUSED(data))
1033 {
1034         /* "--env-system-scripts" --> "BLENDER_SYSTEM_SCRIPTS" */
1035
1036         char env[64] = "BLENDER";
1037         char *ch_dst = env + 7; /* skip BLENDER */
1038         const char *ch_src = argv[0] + 5; /* skip --env */
1039
1040         if (argc < 2) {
1041                 printf("%s requires one argument\n", argv[0]);
1042                 exit(1);
1043         }
1044
1045         for (; *ch_src; ch_src++, ch_dst++) {
1046                 *ch_dst = (*ch_src == '-') ? '_' : (*ch_src) - 32; /* toupper() */
1047         }
1048
1049         *ch_dst = '\0';
1050         BLI_setenv(env, argv[1]);
1051         return 1;
1052 }
1053
1054 static const char arg_handle_playback_mode_doc[] =
1055 "<options> <file(s)>\n"
1056 "\tPlayback <file(s)>, only operates this way when not running in background.\n\n"
1057 "\t-p <sx> <sy>\n"
1058 "\t\tOpen with lower left corner at <sx>, <sy>.\n"
1059 "\t-m\n"
1060 "\t\tRead from disk (Do not buffer).\n"
1061 "\t-f <fps> <fps-base>\n"
1062 "\t\tSpecify FPS to start with.\n"
1063 "\t-j <frame>\n"
1064 "\t\tSet frame step to <frame>.\n"
1065 "\t-s <frame>\n"
1066 "\t\tPlay from <frame>.\n"
1067 "\t-e <frame>\n"
1068 "\t\tPlay until <frame>."
1069 ;
1070 static int arg_handle_playback_mode(int argc, const char **argv, void *UNUSED(data))
1071 {
1072         /* not if -b was given first */
1073         if (G.background == 0) {
1074 #ifdef WITH_FFMPEG
1075                 /* Setup FFmpeg with current debug flags. */
1076                 IMB_ffmpeg_init();
1077 #endif
1078
1079                 WM_main_playanim(argc, argv); /* not the same argc and argv as before */
1080                 exit(0); /* 2.4x didn't do this */
1081         }
1082
1083         return -2;
1084 }
1085
1086 static const char arg_handle_window_geometry_doc[] =
1087 "<sx> <sy> <w> <h>\n"
1088 "\tOpen with lower left corner at <sx>, <sy> and width and height as <w>, <h>."
1089 ;
1090 static int arg_handle_window_geometry(int argc, const char **argv, void *UNUSED(data))
1091 {
1092         const char *arg_id = "-p / --window-geometry";
1093         int params[4], i;
1094
1095         if (argc < 5) {
1096                 fprintf(stderr, "Error: requires four arguments '%s'\n", arg_id);
1097                 exit(1);
1098         }
1099
1100         for (i = 0; i < 4; i++) {
1101                 const char *err_msg = NULL;
1102                 if (!parse_int(argv[i + 1], NULL, &params[i], &err_msg)) {
1103                         printf("\nError: %s '%s %s'.\n", err_msg, arg_id, argv[1]);
1104                         exit(1);
1105                 }
1106         }
1107
1108         WM_init_state_size_set(UNPACK4(params));
1109
1110         return 4;
1111 }
1112
1113 static const char arg_handle_native_pixels_set_doc[] =
1114 "\n\tDo not use native pixel size, for high resolution displays (MacBook 'Retina')."
1115 ;
1116 static int arg_handle_native_pixels_set(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
1117 {
1118         WM_init_native_pixels(false);
1119         return 0;
1120 }
1121
1122 static const char arg_handle_with_borders_doc[] =
1123 "\n\tForce opening with borders."
1124 ;
1125 static int arg_handle_with_borders(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
1126 {
1127         WM_init_state_normal_set();
1128         return 0;
1129 }
1130
1131 static const char arg_handle_without_borders_doc[] =
1132 "\n\tForce opening in fullscreen mode."
1133 ;
1134 static int arg_handle_without_borders(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
1135 {
1136         WM_init_state_fullscreen_set();
1137         return 0;
1138 }
1139
1140 static const char arg_handle_no_window_focus_doc[] =
1141 "\n\tOpen behind other windows and without taking focus."
1142 ;
1143 static int arg_handle_no_window_focus(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
1144 {
1145         WM_init_window_focus_set(false);
1146         return 0;
1147 }
1148
1149 extern bool wm_start_with_console; /* wm_init_exit.c */
1150
1151 static const char arg_handle_start_with_console_doc[] =
1152 "\n\tStart with the console window open (ignored if -b is set), (Windows only)."
1153 ;
1154 static int arg_handle_start_with_console(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
1155 {
1156         wm_start_with_console = true;
1157         return 0;
1158 }
1159
1160 static const char arg_handle_register_extension_doc[] =
1161 "\n\tRegister blend-file extension, then exit (Windows only)."
1162 ;
1163 static const char arg_handle_register_extension_doc_silent[] =
1164 "\n\tSilently register blend-file extension, then exit (Windows only)."
1165 ;
1166 static int arg_handle_register_extension(int UNUSED(argc), const char **UNUSED(argv), void *data)
1167 {
1168 #ifdef WIN32
1169         if (data)
1170                 G.background = 1;
1171         RegisterBlendExtension();
1172 #else
1173         (void)data; /* unused */
1174 #endif
1175         return 0;
1176 }
1177
1178 static const char arg_handle_audio_disable_doc[] =
1179 "\n\tForce sound system to None."
1180 ;
1181 static int arg_handle_audio_disable(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
1182 {
1183         BKE_sound_force_device("Null");
1184         return 0;
1185 }
1186
1187 static const char arg_handle_audio_set_doc[] =
1188 "\n\tForce sound system to a specific device.\n\t'NULL' 'SDL' 'OPENAL' 'JACK'."
1189 ;
1190 static int arg_handle_audio_set(int argc, const char **argv, void *UNUSED(data))
1191 {
1192         if (argc < 1) {
1193                 fprintf(stderr, "-setaudio require one argument\n");
1194                 exit(1);
1195         }
1196
1197         BKE_sound_force_device(argv[1]);
1198         return 1;
1199 }
1200
1201 static const char arg_handle_output_set_doc[] =
1202 "<path>\n"
1203 "\tSet the render path and file name.\n"
1204 "\tUse '//' at the start of the path to render relative to the blend-file.\n"
1205 "\n"
1206 "\tThe '#' characters are replaced by the frame number, and used to define zero padding.\n"
1207 "\n"
1208 "\t* 'ani_##_test.png' becomes 'ani_01_test.png'\n"
1209 "\t* 'test-######.png' becomes 'test-000001.png'\n"
1210 "\n"
1211 "\tWhen the filename does not contain '#', The suffix '####' is added to the filename.\n"
1212 "\n"
1213 "\tThe frame number will be added at the end of the filename, eg:\n"
1214 "\t# blender -b foobar.blend -o //render_ -F PNG -x 1 -a\n"
1215 "\t'//render_' becomes '//render_####', writing frames as '//render_0001.png'"
1216 ;
1217 static int arg_handle_output_set(int argc, const char **argv, void *data)
1218 {
1219         bContext *C = data;
1220         if (argc > 1) {
1221                 Scene *scene = CTX_data_scene(C);
1222                 if (scene) {
1223                         BLI_strncpy(scene->r.pic, argv[1], sizeof(scene->r.pic));
1224                 }
1225                 else {
1226                         printf("\nError: no blend loaded. cannot use '-o / --render-output'.\n");
1227                 }
1228                 return 1;
1229         }
1230         else {
1231                 printf("\nError: you must specify a path after '-o  / --render-output'.\n");
1232                 return 0;
1233         }
1234 }
1235
1236 static const char arg_handle_engine_set_doc[] =
1237 "<engine>\n"
1238 "\tSpecify the render engine.\n\tUse -E help to list available engines."
1239 ;
1240 static int arg_handle_engine_set(int argc, const char **argv, void *data)
1241 {
1242         bContext *C = data;
1243         if (argc >= 2) {
1244                 if (STREQ(argv[1], "help")) {
1245                         RenderEngineType *type = NULL;
1246                         printf("Blender Engine Listing:\n");
1247                         for (type = R_engines.first; type; type = type->next) {
1248                                 printf("\t%s\n", type->idname);
1249                         }
1250                         exit(0);
1251                 }
1252                 else {
1253                         Scene *scene = CTX_data_scene(C);
1254                         if (scene) {
1255                                 if (BLI_findstring(&R_engines, argv[1], offsetof(RenderEngineType, idname))) {
1256                                         BLI_strncpy_utf8(scene->r.engine, argv[1], sizeof(scene->r.engine));
1257                                 }
1258                                 else {
1259                                         printf("\nError: engine not found '%s'\n", argv[1]);
1260                                         exit(1);
1261                                 }
1262                         }
1263                         else {
1264                                 printf("\nError: no blend loaded. "
1265                                        "order the arguments so '-E  / --engine ' is after a blend is loaded.\n");
1266                         }
1267                 }
1268
1269                 return 1;
1270         }
1271         else {
1272                 printf("\nEngine not specified, give 'help' for a list of available engines.\n");
1273                 return 0;
1274         }
1275 }
1276
1277 static const char arg_handle_image_type_set_doc[] =
1278 "<format>\n"
1279 "\tSet the render format.\n"
1280 "\tValid options are 'TGA' 'RAWTGA' 'JPEG' 'IRIS' 'IRIZ' 'AVIRAW' 'AVIJPEG' 'PNG' 'BMP'\n"
1281 "\n"
1282 "\tFormats that can be compiled into Blender, not available on all systems: 'HDR' 'TIFF' 'EXR' 'MULTILAYER'\n"
1283 "\t'MPEG' 'CINEON' 'DPX' 'DDS' 'JP2'"
1284 ;
1285 static int arg_handle_image_type_set(int argc, const char **argv, void *data)
1286 {
1287         bContext *C = data;
1288         if (argc > 1) {
1289                 const char *imtype = argv[1];
1290                 Scene *scene = CTX_data_scene(C);
1291                 if (scene) {
1292                         const char imtype_new = BKE_imtype_from_arg(imtype);
1293
1294                         if (imtype_new == R_IMF_IMTYPE_INVALID) {
1295                                 printf("\nError: Format from '-F / --render-format' not known or not compiled in this release.\n");
1296                         }
1297                         else {
1298                                 scene->r.im_format.imtype = imtype_new;
1299                         }
1300                 }
1301                 else {
1302                         printf("\nError: no blend loaded. "
1303                                "order the arguments so '-F  / --render-format' is after the blend is loaded.\n");
1304                 }
1305                 return 1;
1306         }
1307         else {
1308                 printf("\nError: you must specify a format after '-F  / --render-foramt'.\n");
1309                 return 0;
1310         }
1311 }
1312
1313 static const char arg_handle_threads_set_doc[] =
1314 "<threads>\n"
1315 "\tUse amount of <threads> for rendering and other operations\n"
1316 "\t[1-" STRINGIFY(BLENDER_MAX_THREADS) "], 0 for systems processor count."
1317 ;
1318 static int arg_handle_threads_set(int argc, const char **argv, void *UNUSED(data))
1319 {
1320         const char *arg_id = "-t / --threads";
1321         const int min = 0, max = BLENDER_MAX_THREADS;
1322         if (argc > 1) {
1323                 const char *err_msg = NULL;
1324                 int threads;
1325                 if (!parse_int_strict_range(argv[1], NULL, min, max, &threads, &err_msg)) {
1326                         printf("\nError: %s '%s %s', expected number in [%d..%d].\n", err_msg, arg_id, argv[1], min, max);
1327                         return 1;
1328                 }
1329
1330                 BLI_system_num_threads_override_set(threads);
1331                 return 1;
1332         }
1333         else {
1334                 printf("\nError: you must specify a number of threads in [%d..%d] '%s'.\n", min, max, arg_id);
1335                 return 0;
1336         }
1337 }
1338
1339 static const char arg_handle_verbosity_set_doc[] =
1340 "<verbose>\n"
1341 "\tSet logging verbosity level."
1342 ;
1343 static int arg_handle_verbosity_set(int argc, const char **argv, void *UNUSED(data))
1344 {
1345         const char *arg_id = "--verbose";
1346         if (argc > 1) {
1347                 const char *err_msg = NULL;
1348                 int level;
1349                 if (!parse_int(argv[1], NULL, &level, &err_msg)) {
1350                         printf("\nError: %s '%s %s'.\n", err_msg, arg_id, argv[1]);
1351                 }
1352
1353 #ifdef WITH_LIBMV
1354                 libmv_setLoggingVerbosity(level);
1355 #elif defined(WITH_CYCLES_LOGGING)
1356                 CCL_logging_verbosity_set(level);
1357 #else
1358                 (void)level;
1359 #endif
1360
1361                 return 1;
1362         }
1363         else {
1364                 printf("\nError: you must specify a verbosity level.\n");
1365                 return 0;
1366         }
1367 }
1368
1369 static const char arg_handle_extension_set_doc[] =
1370 "<bool>\n"
1371 "\tSet option to add the file extension to the end of the file."
1372 ;
1373 static int arg_handle_extension_set(int argc, const char **argv, void *data)
1374 {
1375         bContext *C = data;
1376         if (argc > 1) {
1377                 Scene *scene = CTX_data_scene(C);
1378                 if (scene) {
1379                         if (argv[1][0] == '0') {
1380                                 scene->r.scemode &= ~R_EXTENSION;
1381                         }
1382                         else if (argv[1][0] == '1') {
1383                                 scene->r.scemode |= R_EXTENSION;
1384                         }
1385                         else {
1386                                 printf("\nError: Use '-x 1 / -x 0' To set the extension option or '--use-extension'\n");
1387                         }
1388                 }
1389                 else {
1390                         printf("\nError: no blend loaded. "
1391                                "order the arguments so '-o ' is after '-x '.\n");
1392                 }
1393                 return 1;
1394         }
1395         else {
1396                 printf("\nError: you must specify a path after '- '.\n");
1397                 return 0;
1398         }
1399 }
1400
1401 static const char arg_handle_render_frame_doc[] =
1402 "<frame>\n"
1403 "\tRender frame <frame> and save it.\n"
1404 "\n"
1405 "\t* +<frame> start frame relative, -<frame> end frame relative.\n"
1406 "\t* A comma separated list of frames can also be used (no spaces).\n"
1407 "\t* A range of frames can be expressed using '..' separator between the first and last frames (inclusive).\n"
1408 ;
1409 static int arg_handle_render_frame(int argc, const char **argv, void *data)
1410 {
1411         const char *arg_id = "-f / --render-frame";
1412         bContext *C = data;
1413         Scene *scene = CTX_data_scene(C);
1414         if (scene) {
1415                 Main *bmain = CTX_data_main(C);
1416
1417                 if (argc > 1) {
1418                         const char *err_msg = NULL;
1419                         Render *re;
1420                         ReportList reports;
1421
1422                         int (*frame_range_arr)[2], frames_range_len;
1423                         if ((frame_range_arr = parse_int_range_relative_clamp_n(
1424                                  argv[1], scene->r.sfra, scene->r.efra, MINAFRAME, MAXFRAME,
1425                                  &frames_range_len, &err_msg)) == NULL)
1426                         {
1427                                 printf("\nError: %s '%s %s'.\n", err_msg, arg_id, argv[1]);
1428                                 return 1;
1429                         }
1430
1431                         re = RE_NewSceneRender(scene);
1432                         BLI_threaded_malloc_begin();
1433                         BKE_reports_init(&reports, RPT_STORE);
1434                         RE_SetReports(re, &reports);
1435                         for (int i = 0; i < frames_range_len; i++) {
1436                                 /* We could pass in frame ranges,
1437                                  * but prefer having exact behavior as passing in multiple frames */
1438                                 if ((frame_range_arr[i][0] <= frame_range_arr[i][1]) == 0) {
1439                                         printf("\nWarning: negative range ignored '%s %s'.\n", arg_id, argv[1]);
1440                                 }
1441
1442                                 for (int frame = frame_range_arr[i][0]; frame <= frame_range_arr[i][1]; frame++) {
1443                                         RE_BlenderAnim(re, bmain, scene, NULL, NULL, frame, frame, scene->r.frame_step);
1444                                 }
1445                         }
1446                         RE_SetReports(re, NULL);
1447                         BKE_reports_clear(&reports);
1448                         BLI_threaded_malloc_end();
1449                         MEM_freeN(frame_range_arr);
1450                         return 1;
1451                 }
1452                 else {
1453                         printf("\nError: frame number must follow '%s'.\n", arg_id);
1454                         return 0;
1455                 }
1456         }
1457         else {
1458                 printf("\nError: no blend loaded. cannot use '%s'.\n", arg_id);
1459                 return 0;
1460         }
1461 }
1462
1463 static const char arg_handle_render_animation_doc[] =
1464 "\n\tRender frames from start to end (inclusive)."
1465 ;
1466 static int arg_handle_render_animation(int UNUSED(argc), const char **UNUSED(argv), void *data)
1467 {
1468         bContext *C = data;
1469         Scene *scene = CTX_data_scene(C);
1470         if (scene) {
1471                 Main *bmain = CTX_data_main(C);
1472                 Render *re = RE_NewSceneRender(scene);
1473                 ReportList reports;
1474                 BLI_threaded_malloc_begin();
1475                 BKE_reports_init(&reports, RPT_STORE);
1476                 RE_SetReports(re, &reports);
1477                 RE_BlenderAnim(re, bmain, scene, NULL, NULL, scene->r.sfra, scene->r.efra, scene->r.frame_step);
1478                 RE_SetReports(re, NULL);
1479                 BKE_reports_clear(&reports);
1480                 BLI_threaded_malloc_end();
1481         }
1482         else {
1483                 printf("\nError: no blend loaded. cannot use '-a'.\n");
1484         }
1485         return 0;
1486 }
1487
1488 static const char arg_handle_scene_set_doc[] =
1489 "<name>\n"
1490 "\tSet the active scene <name> for rendering."
1491 ;
1492 static int arg_handle_scene_set(int argc, const char **argv, void *data)
1493 {
1494         if (argc > 1) {
1495                 bContext *C = data;
1496                 Scene *scene = BKE_scene_set_name(CTX_data_main(C), argv[1]);
1497                 if (scene) {
1498                         CTX_data_scene_set(C, scene);
1499
1500                         /* Set the scene of the first window, see: T55991,
1501                          * otherwise scrips that run later won't get this scene back from the context. */
1502                         wmWindow *win = CTX_wm_window(C);
1503                         if (win == NULL) {
1504                                 win = CTX_wm_manager(C)->windows.first;
1505                         }
1506                         if (win != NULL) {
1507                                 WM_window_set_active_scene(CTX_data_main(C), C, win, scene);
1508                         }
1509                 }
1510                 return 1;
1511         }
1512         else {
1513                 printf("\nError: Scene name must follow '-S / --scene'.\n");
1514                 return 0;
1515         }
1516 }
1517
1518 static const char arg_handle_frame_start_set_doc[] =
1519 "<frame>\n"
1520 "\tSet start to frame <frame>, supports +/- for relative frames too."
1521 ;
1522 static int arg_handle_frame_start_set(int argc, const char **argv, void *data)
1523 {
1524         const char *arg_id = "-s / --frame-start";
1525         bContext *C = data;
1526         Scene *scene = CTX_data_scene(C);
1527         if (scene) {
1528                 if (argc > 1) {
1529                         const char *err_msg = NULL;
1530                         if (!parse_int_relative_clamp(
1531                                 argv[1], NULL, scene->r.sfra, scene->r.sfra - 1, MINAFRAME, MAXFRAME,
1532                                 &scene->r.sfra, &err_msg))
1533                         {
1534                                 printf("\nError: %s '%s %s'.\n", err_msg, arg_id, argv[1]);
1535                         }
1536                         return 1;
1537                 }
1538                 else {
1539                         printf("\nError: frame number must follow '%s'.\n", arg_id);
1540                         return 0;
1541                 }
1542         }
1543         else {
1544                 printf("\nError: no blend loaded. cannot use '%s'.\n", arg_id);
1545                 return 0;
1546         }
1547 }
1548
1549 static const char arg_handle_frame_end_set_doc[] =
1550 "<frame>\n"
1551 "\tSet end to frame <frame>, supports +/- for relative frames too."
1552 ;
1553 static int arg_handle_frame_end_set(int argc, const char **argv, void *data)
1554 {
1555         const char *arg_id = "-e / --frame-end";
1556         bContext *C = data;
1557         Scene *scene = CTX_data_scene(C);
1558         if (scene) {
1559                 if (argc > 1) {
1560                         const char *err_msg = NULL;
1561                         if (!parse_int_relative_clamp(
1562                                 argv[1], NULL, scene->r.efra, scene->r.efra - 1, MINAFRAME, MAXFRAME,
1563                                 &scene->r.efra, &err_msg))
1564                         {
1565                                 printf("\nError: %s '%s %s'.\n", err_msg, arg_id, argv[1]);
1566                         }
1567                         return 1;
1568                 }
1569                 else {
1570                         printf("\nError: frame number must follow '%s'.\n", arg_id);
1571                         return 0;
1572                 }
1573         }
1574         else {
1575                 printf("\nError: no blend loaded. cannot use '%s'.\n", arg_id);
1576                 return 0;
1577         }
1578 }
1579
1580 static const char arg_handle_frame_skip_set_doc[] =
1581 "<frames>\n"
1582 "\tSet number of frames to step forward after each rendered frame."
1583 ;
1584 static int arg_handle_frame_skip_set(int argc, const char **argv, void *data)
1585 {
1586         const char *arg_id = "-j / --frame-jump";
1587         bContext *C = data;
1588         Scene *scene = CTX_data_scene(C);
1589         if (scene) {
1590                 if (argc > 1) {
1591                         const char *err_msg = NULL;
1592                         if (!parse_int_clamp(argv[1], NULL, 1, MAXFRAME, &scene->r.frame_step, &err_msg)) {
1593                                 printf("\nError: %s '%s %s'.\n", err_msg, arg_id, argv[1]);
1594                         }
1595                         return 1;
1596                 }
1597                 else {
1598                         printf("\nError: number of frames to step must follow '%s'.\n", arg_id);
1599                         return 0;
1600                 }
1601         }
1602         else {
1603                 printf("\nError: no blend loaded. cannot use '%s'.\n", arg_id);
1604                 return 0;
1605         }
1606 }
1607
1608 static const char arg_handle_python_file_run_doc[] =
1609 "<filename>\n"
1610 "\tRun the given Python script file."
1611 ;
1612 static int arg_handle_python_file_run(int argc, const char **argv, void *data)
1613 {
1614 #ifdef WITH_PYTHON
1615         bContext *C = data;
1616
1617         /* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */
1618         if (argc > 1) {
1619                 /* Make the path absolute because its needed for relative linked blends to be found */
1620                 char filename[FILE_MAX];
1621                 BLI_strncpy(filename, argv[1], sizeof(filename));
1622                 BLI_path_cwd(filename, sizeof(filename));
1623
1624                 bool ok;
1625                 BPY_CTX_SETUP(ok = BPY_execute_filepath(C, filename, NULL));
1626                 if (!ok && app_state.exit_code_on_error.python) {
1627                         printf("\nError: script failed, file: '%s', exiting.\n", argv[1]);
1628                         BPY_python_end();
1629                         exit(app_state.exit_code_on_error.python);
1630                 }
1631                 return 1;
1632         }
1633         else {
1634                 printf("\nError: you must specify a filepath after '%s'.\n", argv[0]);
1635                 return 0;
1636         }
1637 #else
1638         UNUSED_VARS(argc, argv, data);
1639         printf("This Blender was built without Python support\n");
1640         return 0;
1641 #endif /* WITH_PYTHON */
1642 }
1643
1644 static const char arg_handle_python_text_run_doc[] =
1645 "<name>\n"
1646 "\tRun the given Python script text block."
1647 ;
1648 static int arg_handle_python_text_run(int argc, const char **argv, void *data)
1649 {
1650 #ifdef WITH_PYTHON
1651         bContext *C = data;
1652
1653         /* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */
1654         if (argc > 1) {
1655                 Main *bmain = CTX_data_main(C);
1656                 /* Make the path absolute because its needed for relative linked blends to be found */
1657                 struct Text *text = (struct Text *)BKE_libblock_find_name(bmain, ID_TXT, argv[1]);
1658                 bool ok;
1659
1660                 if (text) {
1661                         BPY_CTX_SETUP(ok = BPY_execute_text(C, text, NULL, false));
1662                 }
1663                 else {
1664                         printf("\nError: text block not found %s.\n", argv[1]);
1665                         ok = false;
1666                 }
1667
1668                 if (!ok && app_state.exit_code_on_error.python) {
1669                         printf("\nError: script failed, text: '%s', exiting.\n", argv[1]);
1670                         BPY_python_end();
1671                         exit(app_state.exit_code_on_error.python);
1672                 }
1673
1674                 return 1;
1675         }
1676         else {
1677                 printf("\nError: you must specify a text block after '%s'.\n", argv[0]);
1678                 return 0;
1679         }
1680 #else
1681         UNUSED_VARS(argc, argv, data);
1682         printf("This Blender was built without Python support\n");
1683         return 0;
1684 #endif /* WITH_PYTHON */
1685 }
1686
1687 static const char arg_handle_python_expr_run_doc[] =
1688 "<expression>\n"
1689 "\tRun the given expression as a Python script."
1690 ;
1691 static int arg_handle_python_expr_run(int argc, const char **argv, void *data)
1692 {
1693 #ifdef WITH_PYTHON
1694         bContext *C = data;
1695
1696         /* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */
1697         if (argc > 1) {
1698                 bool ok;
1699                 BPY_CTX_SETUP(ok = BPY_execute_string_ex(C, NULL, argv[1], false));
1700                 if (!ok && app_state.exit_code_on_error.python) {
1701                         printf("\nError: script failed, expr: '%s', exiting.\n", argv[1]);
1702                         BPY_python_end();
1703                         exit(app_state.exit_code_on_error.python);
1704                 }
1705                 return 1;
1706         }
1707         else {
1708                 printf("\nError: you must specify a Python expression after '%s'.\n", argv[0]);
1709                 return 0;
1710         }
1711 #else
1712         UNUSED_VARS(argc, argv, data);
1713         printf("This Blender was built without Python support\n");
1714         return 0;
1715 #endif /* WITH_PYTHON */
1716 }
1717
1718 static const char arg_handle_python_console_run_doc[] =
1719 "\n\tRun Blender with an interactive console."
1720 ;
1721 static int arg_handle_python_console_run(int UNUSED(argc), const char **argv, void *data)
1722 {
1723 #ifdef WITH_PYTHON
1724         bContext *C = data;
1725
1726         BPY_CTX_SETUP(BPY_execute_string(C, (const char *[]){"code", NULL}, "code.interact()"));
1727
1728         return 0;
1729 #else
1730         UNUSED_VARS(argv, data);
1731         printf("This Blender was built without python support\n");
1732         return 0;
1733 #endif /* WITH_PYTHON */
1734 }
1735
1736 static const char arg_handle_python_exit_code_set_doc[] =
1737 "<code>\n"
1738 "\tSet the exit-code in [0..255] to exit if a Python exception is raised\n"
1739 "\t(only for scripts executed from the command line), zero disables."
1740 ;
1741 static int arg_handle_python_exit_code_set(int argc, const char **argv, void *UNUSED(data))
1742 {
1743         const char *arg_id = "--python-exit-code";
1744         if (argc > 1) {
1745                 const char *err_msg = NULL;
1746                 const int min = 0, max = 255;
1747                 int exit_code;
1748                 if (!parse_int_strict_range(argv[1], NULL, min, max, &exit_code, &err_msg)) {
1749                         printf("\nError: %s '%s %s', expected number in [%d..%d].\n", err_msg, arg_id, argv[1], min, max);
1750                         return 1;
1751                 }
1752
1753                 app_state.exit_code_on_error.python = (unsigned char)exit_code;
1754                 return 1;
1755         }
1756         else {
1757                 printf("\nError: you must specify an exit code number '%s'.\n", arg_id);
1758                 return 0;
1759         }
1760 }
1761
1762 static const char arg_handle_addons_set_doc[] =
1763 "<addon(s)>\n"
1764 "\tComma separated list of add-ons (no spaces)."
1765 ;
1766 static int arg_handle_addons_set(int argc, const char **argv, void *data)
1767 {
1768         /* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */
1769         if (argc > 1) {
1770 #ifdef WITH_PYTHON
1771                 const char script_str[] =
1772                         "from addon_utils import check, enable\n"
1773                         "for m in '%s'.split(','):\n"
1774                         "    if check(m)[1] is False:\n"
1775                         "        enable(m, persistent=True)";
1776                 const int slen = strlen(argv[1]) + (sizeof(script_str) - 2);
1777                 char *str = malloc(slen);
1778                 bContext *C = data;
1779                 BLI_snprintf(str, slen, script_str, argv[1]);
1780
1781                 BLI_assert(strlen(str) + 1 == slen);
1782                 BPY_CTX_SETUP(BPY_execute_string_ex(C, NULL, str, false));
1783                 free(str);
1784 #else
1785                 UNUSED_VARS(argv, data);
1786 #endif /* WITH_PYTHON */
1787                 return 1;
1788         }
1789         else {
1790                 printf("\nError: you must specify a comma separated list after '--addons'.\n");
1791                 return 0;
1792         }
1793 }
1794
1795 static int arg_handle_load_file(int UNUSED(argc), const char **argv, void *data)
1796 {
1797         bContext *C = data;
1798         ReportList reports;
1799         bool success;
1800
1801         /* Make the path absolute because its needed for relative linked blends to be found */
1802         char filename[FILE_MAX];
1803
1804         /* note, we could skip these, but so far we always tried to load these files */
1805         if (argv[0][0] == '-') {
1806                 fprintf(stderr, "unknown argument, loading as file: %s\n", argv[0]);
1807         }
1808
1809         BLI_strncpy(filename, argv[0], sizeof(filename));
1810         BLI_path_cwd(filename, sizeof(filename));
1811
1812         /* load the file */
1813         BKE_reports_init(&reports, RPT_PRINT);
1814         WM_file_autoexec_init(filename);
1815         success = WM_file_read(C, filename, &reports);
1816         BKE_reports_clear(&reports);
1817
1818         if (success) {
1819                 if (G.background) {
1820                         /* ensuer we use 'C->data.scene' for background render */
1821                         CTX_wm_window_set(C, NULL);
1822                 }
1823         }
1824         else {
1825                 /* failed to load file, stop processing arguments if running in background mode */
1826                 if (G.background) {
1827                         /* Set is_break if running in the background mode so
1828                          * blender will return non-zero exit code which then
1829                          * could be used in automated script to control how
1830                          * good or bad things are.
1831                          */
1832                         G.is_break = true;
1833                         return -1;
1834                 }
1835
1836                 if (BLO_has_bfile_extension(filename)) {
1837                         /* Just pretend a file was loaded, so the user can press Save and it'll
1838                          * save at the filename from the CLI. */
1839                         BLI_strncpy(G_MAIN->name, filename, FILE_MAX);
1840                         G.relbase_valid = true;
1841                         G.save_over = true;
1842                         printf("... opened default scene instead; saving will write to: %s\n", filename);
1843                 }
1844                 else {
1845                         printf("Error: argument has no '.blend' file extension, not using as new file, exiting! %s\n", filename);
1846                         G.is_break = true;
1847                         WM_exit(C);
1848                 }
1849         }
1850
1851         G.file_loaded = 1;
1852
1853         return 0;
1854 }
1855
1856
1857 void main_args_setup(bContext *C, bArgs *ba)
1858 {
1859
1860 #define CB(a) a##_doc, a
1861 #define CB_EX(a, b) a##_doc_##b, a
1862
1863         //BLI_argsAdd(ba, pass, short_arg, long_arg, doc, cb, C);
1864
1865         /* end argument processing after -- */
1866         BLI_argsAdd(ba, -1, "--", NULL, CB(arg_handle_arguments_end), NULL);
1867
1868         /* first pass: background mode, disable python and commands that exit after usage */
1869         BLI_argsAdd(ba, 1, "-h", "--help", CB(arg_handle_print_help), ba);
1870         /* Windows only */
1871         BLI_argsAdd(ba, 1, "/?", NULL, CB_EX(arg_handle_print_help, win32), ba);
1872
1873         BLI_argsAdd(ba, 1, "-v", "--version", CB(arg_handle_print_version), NULL);
1874
1875         BLI_argsAdd(ba, 1, "-y", "--enable-autoexec", CB_EX(arg_handle_python_set, enable), (void *)true);
1876         BLI_argsAdd(ba, 1, "-Y", "--disable-autoexec", CB_EX(arg_handle_python_set, disable), (void *)false);
1877
1878         BLI_argsAdd(ba, 1, NULL, "--disable-crash-handler", CB(arg_handle_crash_handler_disable), NULL);
1879         BLI_argsAdd(ba, 1, NULL, "--disable-abort-handler", CB(arg_handle_abort_handler_disable), NULL);
1880
1881         BLI_argsAdd(ba, 1, "-b", "--background", CB(arg_handle_background_mode_set), NULL);
1882
1883         BLI_argsAdd(ba, 1, "-a", NULL, CB(arg_handle_playback_mode), NULL);
1884
1885         BLI_argsAdd(ba, 1, NULL, "--log", CB(arg_handle_log_set), ba);
1886         BLI_argsAdd(ba, 1, NULL, "--log-level", CB(arg_handle_log_level_set), ba);
1887         BLI_argsAdd(ba, 1, NULL, "--log-show-basename", CB(arg_handle_log_show_basename_set), ba);
1888         BLI_argsAdd(ba, 1, NULL, "--log-show-backtrace", CB(arg_handle_log_show_backtrace_set), ba);
1889         BLI_argsAdd(ba, 1, NULL, "--log-show-timestamp", CB(arg_handle_log_show_timestamp_set), ba);
1890         BLI_argsAdd(ba, 1, NULL, "--log-file", CB(arg_handle_log_file_set), ba);
1891
1892         BLI_argsAdd(ba, 1, "-d", "--debug", CB(arg_handle_debug_mode_set), ba);
1893
1894 #ifdef WITH_FFMPEG
1895         BLI_argsAdd(ba, 1, NULL, "--debug-ffmpeg",
1896                     CB_EX(arg_handle_debug_mode_generic_set, ffmpeg), (void *)G_DEBUG_FFMPEG);
1897 #endif
1898
1899 #ifdef WITH_FREESTYLE
1900         BLI_argsAdd(ba, 1, NULL, "--debug-freestyle",
1901                     CB_EX(arg_handle_debug_mode_generic_set, freestyle), (void *)G_DEBUG_FREESTYLE);
1902 #endif
1903
1904         BLI_argsAdd(ba, 1, NULL, "--debug-python",
1905                     CB_EX(arg_handle_debug_mode_generic_set, python), (void *)G_DEBUG_PYTHON);
1906         BLI_argsAdd(ba, 1, NULL, "--debug-events",
1907                     CB_EX(arg_handle_debug_mode_generic_set, events), (void *)G_DEBUG_EVENTS);
1908         BLI_argsAdd(ba, 1, NULL, "--debug-handlers",
1909                     CB_EX(arg_handle_debug_mode_generic_set, handlers), (void *)G_DEBUG_HANDLERS);
1910         BLI_argsAdd(ba, 1, NULL, "--debug-wm",
1911                     CB_EX(arg_handle_debug_mode_generic_set, wm), (void *)G_DEBUG_WM);
1912         BLI_argsAdd(ba, 1, NULL, "--debug-all", CB(arg_handle_debug_mode_all), NULL);
1913
1914         BLI_argsAdd(ba, 1, NULL, "--debug-io", CB(arg_handle_debug_mode_io), NULL);
1915
1916         BLI_argsAdd(ba, 1, NULL, "--debug-fpe",
1917                     CB(arg_handle_debug_fpe_set), NULL);
1918
1919 #ifdef WITH_LIBMV
1920         BLI_argsAdd(ba, 1, NULL, "--debug-libmv", CB(arg_handle_debug_mode_libmv), NULL);
1921 #endif
1922 #ifdef WITH_CYCLES_LOGGING
1923         BLI_argsAdd(ba, 1, NULL, "--debug-cycles", CB(arg_handle_debug_mode_cycles), NULL);
1924 #endif
1925         BLI_argsAdd(ba, 1, NULL, "--debug-memory", CB(arg_handle_debug_mode_memory_set), NULL);
1926
1927         BLI_argsAdd(ba, 1, NULL, "--debug-value",
1928                     CB(arg_handle_debug_value_set), NULL);
1929         BLI_argsAdd(ba, 1, NULL, "--debug-jobs",
1930                     CB_EX(arg_handle_debug_mode_generic_set, jobs), (void *)G_DEBUG_JOBS);
1931         BLI_argsAdd(ba, 1, NULL, "--debug-gpu",
1932                     CB_EX(arg_handle_debug_mode_generic_set, gpu), (void *)G_DEBUG_GPU);
1933         BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph",
1934                     CB_EX(arg_handle_debug_mode_generic_set, depsgraph), (void *)G_DEBUG_DEPSGRAPH);
1935         BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph-build",
1936                     CB_EX(arg_handle_debug_mode_generic_set, depsgraph_build), (void *)G_DEBUG_DEPSGRAPH_BUILD);
1937         BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph-eval",
1938                     CB_EX(arg_handle_debug_mode_generic_set, depsgraph_eval), (void *)G_DEBUG_DEPSGRAPH_EVAL);
1939         BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph-tag",
1940                     CB_EX(arg_handle_debug_mode_generic_set, depsgraph_tag), (void *)G_DEBUG_DEPSGRAPH_TAG);
1941         BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph-time",
1942                     CB_EX(arg_handle_debug_mode_generic_set, depsgraph_time), (void *)G_DEBUG_DEPSGRAPH_TIME);
1943         BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph-no-threads",
1944                     CB_EX(arg_handle_debug_mode_generic_set, depsgraph_no_threads), (void *)G_DEBUG_DEPSGRAPH_NO_THREADS);
1945         BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph-pretty",
1946                     CB_EX(arg_handle_debug_mode_generic_set, depsgraph_pretty), (void *)G_DEBUG_DEPSGRAPH_PRETTY);
1947         BLI_argsAdd(ba, 1, NULL, "--debug-gpumem",
1948                     CB_EX(arg_handle_debug_mode_generic_set, gpumem), (void *)G_DEBUG_GPU_MEM);
1949         BLI_argsAdd(ba, 1, NULL, "--debug-gpu-shaders",
1950                     CB_EX(arg_handle_debug_mode_generic_set, gpumem), (void *)G_DEBUG_GPU_SHADERS);
1951         BLI_argsAdd(ba, 1, NULL, "--debug-gpu-force-workarounds",
1952                     CB_EX(arg_handle_debug_mode_generic_set, gpumem), (void *)G_DEBUG_GPU_FORCE_WORKAROUNDS);
1953
1954         BLI_argsAdd(ba, 1, NULL, "--verbose", CB(arg_handle_verbosity_set), NULL);
1955
1956         BLI_argsAdd(ba, 1, NULL, "--app-template", CB(arg_handle_app_template), NULL);
1957         BLI_argsAdd(ba, 1, NULL, "--factory-startup", CB(arg_handle_factory_startup_set), NULL);
1958         BLI_argsAdd(ba, 1, NULL, "--enable-static-override", CB(arg_handle_enable_static_override), NULL);
1959
1960         /* TODO, add user env vars? */
1961         BLI_argsAdd(ba, 1, NULL, "--env-system-datafiles", CB_EX(arg_handle_env_system_set, datafiles), NULL);
1962         BLI_argsAdd(ba, 1, NULL, "--env-system-scripts", CB_EX(arg_handle_env_system_set, scripts), NULL);
1963         BLI_argsAdd(ba, 1, NULL, "--env-system-python", CB_EX(arg_handle_env_system_set, python), NULL);
1964
1965         /* second pass: custom window stuff */
1966         BLI_argsAdd(ba, 2, "-p", "--window-geometry", CB(arg_handle_window_geometry), NULL);
1967         BLI_argsAdd(ba, 2, "-w", "--window-border", CB(arg_handle_with_borders), NULL);
1968         BLI_argsAdd(ba, 2, "-W", "--window-fullscreen", CB(arg_handle_without_borders), NULL);
1969         BLI_argsAdd(ba, 2, NULL, "--no-window-focus", CB(arg_handle_no_window_focus), NULL);
1970         BLI_argsAdd(ba, 2, "-con", "--start-console", CB(arg_handle_start_with_console), NULL);
1971         BLI_argsAdd(ba, 2, "-R", NULL, CB(arg_handle_register_extension), NULL);
1972         BLI_argsAdd(ba, 2, "-r", NULL, CB_EX(arg_handle_register_extension, silent), ba);
1973         BLI_argsAdd(ba, 2, NULL, "--no-native-pixels", CB(arg_handle_native_pixels_set), ba);
1974
1975         /* third pass: disabling things and forcing settings */
1976         BLI_argsAddCase(ba, 3, "-noaudio", 1, NULL, 0, CB(arg_handle_audio_disable), NULL);
1977         BLI_argsAddCase(ba, 3, "-setaudio", 1, NULL, 0, CB(arg_handle_audio_set), NULL);
1978
1979         /* fourth pass: processing arguments */
1980         BLI_argsAdd(ba, 4, "-f", "--render-frame", CB(arg_handle_render_frame), C);
1981         BLI_argsAdd(ba, 4, "-a", "--render-anim", CB(arg_handle_render_animation), C);
1982         BLI_argsAdd(ba, 4, "-S", "--scene", CB(arg_handle_scene_set), C);
1983         BLI_argsAdd(ba, 4, "-s", "--frame-start", CB(arg_handle_frame_start_set), C);
1984         BLI_argsAdd(ba, 4, "-e", "--frame-end", CB(arg_handle_frame_end_set), C);
1985         BLI_argsAdd(ba, 4, "-j", "--frame-jump", CB(arg_handle_frame_skip_set), C);
1986         BLI_argsAdd(ba, 4, "-P", "--python", CB(arg_handle_python_file_run), C);
1987         BLI_argsAdd(ba, 4, NULL, "--python-text", CB(arg_handle_python_text_run), C);
1988         BLI_argsAdd(ba, 4, NULL, "--python-expr", CB(arg_handle_python_expr_run), C);
1989         BLI_argsAdd(ba, 4, NULL, "--python-console", CB(arg_handle_python_console_run), C);
1990         BLI_argsAdd(ba, 4, NULL, "--python-exit-code", CB(arg_handle_python_exit_code_set), NULL);
1991         BLI_argsAdd(ba, 4, NULL, "--addons", CB(arg_handle_addons_set), C);
1992
1993         BLI_argsAdd(ba, 4, "-o", "--render-output", CB(arg_handle_output_set), C);
1994         BLI_argsAdd(ba, 4, "-E", "--engine", CB(arg_handle_engine_set), C);
1995
1996         BLI_argsAdd(ba, 4, "-F", "--render-format", CB(arg_handle_image_type_set), C);
1997         BLI_argsAdd(ba, 1, "-t", "--threads", CB(arg_handle_threads_set), NULL);
1998         BLI_argsAdd(ba, 4, "-x", "--use-extension", CB(arg_handle_extension_set), C);
1999
2000 #undef CB
2001 #undef CB_EX
2002
2003 }
2004
2005 /**
2006  * Needs to be added separately.
2007  */
2008 void main_args_setup_post(bContext *C, bArgs *ba)
2009 {
2010         BLI_argsParse(ba, 4, arg_handle_load_file, C);
2011 }
2012
2013 /** \} */
2014
2015 #endif /* WITH_PYTHON_MODULE */