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