Merge branch '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, "--factory-startup");
569         printf("\n");
570         BLI_argsPrintArgDoc(ba, "--env-system-datafiles");
571         BLI_argsPrintArgDoc(ba, "--env-system-scripts");
572         BLI_argsPrintArgDoc(ba, "--env-system-python");
573         printf("\n");
574         BLI_argsPrintArgDoc(ba, "-noaudio");
575         BLI_argsPrintArgDoc(ba, "-setaudio");
576
577         printf("\n");
578
579         BLI_argsPrintArgDoc(ba, "--help");
580
581 #ifdef WIN32
582         BLI_argsPrintArgDoc(ba, "-R");
583         BLI_argsPrintArgDoc(ba, "-r");
584 #endif
585         BLI_argsPrintArgDoc(ba, "--version");
586
587         BLI_argsPrintArgDoc(ba, "--");
588
589         //printf("\n");
590         //printf("Experimental Features:\n");
591
592         /* Other options _must_ be last (anything not handled will show here) */
593         printf("\n");
594         printf("Other Options:\n");
595         BLI_argsPrintOtherDoc(ba);
596
597         printf("\n");
598         printf("Argument Parsing:\n");
599         printf("\tArguments must be separated by white space, eg:\n");
600         printf("\t# blender -ba test.blend\n");
601         printf("\t...will ignore the 'a'.\n");
602         printf("\t# blender -b test.blend -f8\n");
603         printf("\t...will ignore '8' because there is no space between the '-f' and the frame value.\n\n");
604
605         printf("Argument Order:\n");
606         printf("\tArguments are executed in the order they are given. eg:\n");
607         printf("\t# blender --background test.blend --render-frame 1 --render-output '/tmp'\n");
608         printf("\t...will not render to '/tmp' because '--render-frame 1' renders before the output path is set.\n");
609         printf("\t# blender --background --render-output /tmp test.blend --render-frame 1\n");
610         printf("\t...will not render to '/tmp' because loading the blend-file overwrites the render output that was set.\n");
611         printf("\t# blender --background test.blend --render-output /tmp --render-frame 1\n");
612         printf("\t...works as expected.\n\n");
613
614         printf("Environment Variables:\n");
615         printf("  $BLENDER_USER_CONFIG      Directory for user configuration files.\n");
616         printf("  $BLENDER_USER_SCRIPTS     Directory for user scripts.\n");
617         printf("  $BLENDER_SYSTEM_SCRIPTS   Directory for system wide scripts.\n");
618         printf("  $BLENDER_USER_DATAFILES   Directory for user data files (icons, translations, ..).\n");
619         printf("  $BLENDER_SYSTEM_DATAFILES Directory for system wide data files.\n");
620         printf("  $BLENDER_SYSTEM_PYTHON    Directory for system Python libraries.\n");
621 #ifdef WIN32
622         printf("  $TEMP                     Store temporary files here.\n");
623 #else
624         printf("  $TMP or $TMPDIR           Store temporary files here.\n");
625 #endif
626 #ifdef WITH_SDL
627         printf("  $SDL_AUDIODRIVER          LibSDL audio driver - alsa, esd, dma.\n");
628 #endif
629         printf("  $PYTHONHOME               Path to the Python directory, eg. /usr/lib/python.\n\n");
630
631         exit(0);
632
633         return 0;
634 }
635
636 static const char arg_handle_arguments_end_doc[] =
637 "\n\tEnd option processing, following arguments passed unchanged. Access via Python's 'sys.argv'."
638 ;
639 static int arg_handle_arguments_end(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
640 {
641         return -1;
642 }
643
644 /* only to give help message */
645 #ifndef WITH_PYTHON_SECURITY /* default */
646 #  define   PY_ENABLE_AUTO ", (default)"
647 #  define   PY_DISABLE_AUTO ""
648 #else
649 #  define   PY_ENABLE_AUTO ""
650 #  define   PY_DISABLE_AUTO ", (compiled as non-standard default)"
651 #endif
652
653 static const char arg_handle_python_set_doc_enable[] =
654 "\n\tEnable automatic Python script execution" PY_ENABLE_AUTO "."
655 ;
656 static const char arg_handle_python_set_doc_disable[] =
657 "\n\tDisable automatic Python script execution (pydrivers & startup scripts)" PY_DISABLE_AUTO "."
658 ;
659 #undef PY_ENABLE_AUTO
660 #undef PY_DISABLE_AUTO
661
662 static int arg_handle_python_set(int UNUSED(argc), const char **UNUSED(argv), void *data)
663 {
664         if ((bool)data) {
665                 G.f |= G_SCRIPT_AUTOEXEC;
666         }
667         else {
668                 G.f &= ~G_SCRIPT_AUTOEXEC;
669         }
670         G.f |= G_SCRIPT_OVERRIDE_PREF;
671         return 0;
672 }
673
674 static const char arg_handle_crash_handler_disable_doc[] =
675 "\n\tDisable the crash handler."
676 ;
677 static int arg_handle_crash_handler_disable(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
678 {
679         app_state.signal.use_crash_handler = false;
680         return 0;
681 }
682
683 static const char arg_handle_abort_handler_disable_doc[] =
684 "\n\tDisable the abort handler."
685 ;
686 static int arg_handle_abort_handler_disable(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
687 {
688         app_state.signal.use_abort_handler = false;
689         return 0;
690 }
691
692 static const char arg_handle_background_mode_set_doc[] =
693 "\n\tRun in background (often used for UI-less rendering)."
694 ;
695 static int arg_handle_background_mode_set(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
696 {
697         G.background = 1;
698         return 0;
699 }
700
701 static const char arg_handle_log_level_set_doc[] =
702 "<level>\n"
703 "\n"
704 "\tSet the logging verbosity level (higher for more details) defaults to 1, use -1 to log all levels."
705 ;
706 static int arg_handle_log_level_set(int argc, const char **argv, void *UNUSED(data))
707 {
708         const char *arg_id = "--log-level";
709         if (argc > 1) {
710                 const char *err_msg = NULL;
711                 if (!parse_int_clamp(argv[1], NULL, -1, INT_MAX, &G.log.level, &err_msg)) {
712                         printf("\nError: %s '%s %s'.\n", err_msg, arg_id, argv[1]);
713                 }
714                 else {
715                         if (G.log.level == -1) {
716                                 G.log.level = INT_MAX;
717                         }
718                         CLG_level_set(G.log.level);
719                 }
720                 return 1;
721         }
722         else {
723                 printf("\nError: '%s' no args given.\n", arg_id);
724                 return 0;
725         }
726 }
727
728 static const char arg_handle_log_show_basename_set_doc[] =
729 "\n\tOnly show file name in output (not the leading path)."
730 ;
731 static int arg_handle_log_show_basename_set(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
732 {
733         CLG_output_use_basename_set(true);
734         return 0;
735 }
736
737 static const char arg_handle_log_show_backtrace_set_doc[] =
738 "\n\tShow a back trace for each log message (debug builds only)."
739 ;
740 static int arg_handle_log_show_backtrace_set(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
741 {
742         /* Ensure types don't become incompatible. */
743         void (*fn)(FILE *fp) = BLI_system_backtrace;
744         CLG_backtrace_fn_set((void (*)(void *))fn);
745         return 0;
746 }
747
748 static const char arg_handle_log_file_set_doc[] =
749 "<filename>\n"
750 "\n"
751 "\tSet a file to output the log to."
752 ;
753 static int arg_handle_log_file_set(int argc, const char **argv, void *UNUSED(data))
754 {
755         const char *arg_id = "--log-file";
756         if (argc > 1) {
757                 errno = 0;
758                 FILE *fp = BLI_fopen(argv[1], "w");
759                 if (fp == NULL) {
760                         const char *err_msg = errno ? strerror(errno) : "unknown";
761                         printf("\nError: %s '%s %s'.\n", err_msg, arg_id, argv[1]);
762                 }
763                 else {
764                         if (UNLIKELY(G.log.file != NULL)) {
765                                 fclose(G.log.file);
766                         }
767                         G.log.file = fp;
768                         CLG_output_set(G.log.file);
769                 }
770                 return 1;
771         }
772         else {
773                 printf("\nError: '%s' no args given.\n", arg_id);
774                 return 0;
775         }
776 }
777
778 static const char arg_handle_log_set_doc[] =
779 "<match>\n"
780 "\tEnable logging categories, taking a single comma separated argument.\n"
781 "\tMultiple categories can be matched using a '.*' suffix,\n"
782 "\tso '--log \"wm.*\"' logs every kind of window-manager message.\n"
783 "\tUse \"^\" prefix to ignore, so '--log \"*,^wm.operator.*\"' logs all except for 'wm.operators.*'\n"
784 "\tUse \"*\" to log everything."
785 ;
786 static int arg_handle_log_set(int argc, const char **argv, void *UNUSED(data))
787 {
788         const char *arg_id = "--log";
789         if (argc > 1) {
790                 const char *str_step = argv[1];
791                 while (*str_step) {
792                         const char *str_step_end = strchr(str_step, ',');
793                         int str_step_len = str_step_end ? (str_step_end - str_step) : strlen(str_step);
794
795                         if (str_step[0] == '^') {
796                                 CLG_type_filter_exclude(str_step + 1, str_step_len - 1);
797                         }
798                         else {
799                                 CLG_type_filter_include(str_step, str_step_len);
800                         }
801
802                         if (str_step_end) {
803                                 /* typically only be one, but don't fail on multiple.*/
804                                 while (*str_step_end == ',') {
805                                         str_step_end++;
806                                 }
807                                 str_step = str_step_end;
808                         }
809                         else {
810                                 break;
811                         }
812                 }
813                 return 1;
814         }
815         else {
816                 printf("\nError: '%s' no args given.\n", arg_id);
817                 return 0;
818         }
819 }
820
821 static const char arg_handle_debug_mode_set_doc[] =
822 "\n"
823 "\tTurn debugging on.\n"
824 "\n"
825 "\t* Enables memory error detection\n"
826 "\t* Disables mouse grab (to interact with a debugger in some cases)\n"
827 "\t* Keeps Python's 'sys.stdin' rather than setting it to None"
828 ;
829 static int arg_handle_debug_mode_set(int UNUSED(argc), const char **UNUSED(argv), void *data)
830 {
831         G.debug |= G_DEBUG;  /* std output printf's */
832         printf(BLEND_VERSION_STRING_FMT);
833         MEM_set_memory_debug();
834 #ifndef NDEBUG
835         BLI_mempool_set_memory_debug();
836 #endif
837
838 #ifdef WITH_BUILDINFO
839         printf("Build: %s %s %s %s\n", build_date, build_time, build_platform, build_type);
840 #endif
841
842         BLI_argsPrint(data);
843         return 0;
844 }
845
846 #ifdef WITH_FFMPEG
847 static const char arg_handle_debug_mode_generic_set_doc_ffmpeg[] =
848 "\n\tEnable debug messages from FFmpeg library.";
849 #endif
850 #ifdef WITH_FREESTYLE
851 static const char arg_handle_debug_mode_generic_set_doc_freestyle[] =
852 "\n\tEnable debug messages for FreeStyle.";
853 #endif
854 static const char arg_handle_debug_mode_generic_set_doc_python[] =
855 "\n\tEnable debug messages for Python.";
856 static const char arg_handle_debug_mode_generic_set_doc_events[] =
857 "\n\tEnable debug messages for the event system.";
858 static const char arg_handle_debug_mode_generic_set_doc_handlers[] =
859 "\n\tEnable debug messages for event handling.";
860 static const char arg_handle_debug_mode_generic_set_doc_wm[] =
861 "\n\tEnable debug messages for the window manager, shows all operators in search, shows keymap errors.";
862 static const char arg_handle_debug_mode_generic_set_doc_jobs[] =
863 "\n\tEnable time profiling for background jobs.";
864 static const char arg_handle_debug_mode_generic_set_doc_gpu[] =
865 "\n\tEnable gpu debug context and information for OpenGL 4.3+.";
866 static const char arg_handle_debug_mode_generic_set_doc_depsgraph[] =
867 "\n\tEnable all debug messages from dependency graph.";
868 static const char arg_handle_debug_mode_generic_set_doc_depsgraph_build[] =
869 "\n\tEnable debug messages from dependency graph related on graph construction.";
870 static const char arg_handle_debug_mode_generic_set_doc_depsgraph_tag[] =
871 "\n\tEnable debug messages from dependency graph related on tagging.";
872 static const char arg_handle_debug_mode_generic_set_doc_depsgraph_time[] =
873 "\n\tEnable debug messages from dependency graph related on timing.";
874 static const char arg_handle_debug_mode_generic_set_doc_depsgraph_eval[] =
875 "\n\tEnable debug messages from dependency graph related on evaluation.";
876 static const char arg_handle_debug_mode_generic_set_doc_depsgraph_no_threads[] =
877 "\n\tSwitch dependency graph to a single threaded evaluation.";
878 static const char arg_handle_debug_mode_generic_set_doc_depsgraph_pretty[] =
879 "\n\tEnable colors for dependency graph debug messages.";
880 static const char arg_handle_debug_mode_generic_set_doc_gpumem[] =
881 "\n\tEnable GPU memory stats in status bar.";
882
883 static int arg_handle_debug_mode_generic_set(int UNUSED(argc), const char **UNUSED(argv), void *data)
884 {
885         G.debug |= GET_INT_FROM_POINTER(data);
886         return 0;
887 }
888
889 static const char arg_handle_debug_mode_io_doc[] =
890 "\n\tEnable debug messages for I/O (collada, ...).";
891 static int arg_handle_debug_mode_io(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
892 {
893         G.debug |= G_DEBUG_IO;
894         return 0;
895 }
896
897 static const char arg_handle_debug_mode_all_doc[] =
898 "\n\tEnable all debug messages.";
899 static int arg_handle_debug_mode_all(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
900 {
901         G.debug |= G_DEBUG_ALL;
902 #ifdef WITH_LIBMV
903         libmv_startDebugLogging();
904 #endif
905 #ifdef WITH_CYCLES_LOGGING
906         CCL_start_debug_logging();
907 #endif
908         return 0;
909 }
910
911 #ifdef WITH_LIBMV
912 static const char arg_handle_debug_mode_libmv_doc[] =
913 "\n\tEnable debug messages from libmv library."
914 ;
915 static int arg_handle_debug_mode_libmv(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
916 {
917         libmv_startDebugLogging();
918
919         return 0;
920 }
921 #endif
922
923 #ifdef WITH_CYCLES_LOGGING
924 static const char arg_handle_debug_mode_cycles_doc[] =
925 "\n\tEnable debug messages from Cycles."
926 ;
927 static int arg_handle_debug_mode_cycles(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
928 {
929         CCL_start_debug_logging();
930         return 0;
931 }
932 #endif
933
934 static const char arg_handle_debug_mode_memory_set_doc[] =
935 "\n\tEnable fully guarded memory allocation and debugging."
936 ;
937 static int arg_handle_debug_mode_memory_set(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
938 {
939         MEM_set_memory_debug();
940         return 0;
941 }
942
943 static const char arg_handle_debug_value_set_doc[] =
944 "<value>\n"
945 "\tSet debug value of <value> on startup."
946 ;
947 static int arg_handle_debug_value_set(int argc, const char **argv, void *UNUSED(data))
948 {
949         const char *arg_id = "--debug-value";
950         if (argc > 1) {
951                 const char *err_msg = NULL;
952                 int value;
953                 if (!parse_int(argv[1], NULL, &value, &err_msg)) {
954                         printf("\nError: %s '%s %s'.\n", err_msg, arg_id, argv[1]);
955                         return 1;
956                 }
957
958                 G.debug_value = value;
959
960                 return 1;
961         }
962         else {
963                 printf("\nError: you must specify debug value to set.\n");
964                 return 0;
965         }
966 }
967
968 static const char arg_handle_debug_fpe_set_doc[] =
969 "\n\tEnable floating point exceptions."
970 ;
971 static int arg_handle_debug_fpe_set(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
972 {
973         main_signal_setup_fpe();
974         return 0;
975 }
976
977 static const char arg_handle_factory_startup_set_doc[] =
978 "\n\tSkip reading the " STRINGIFY(BLENDER_STARTUP_FILE) " in the users home directory."
979 ;
980 static int arg_handle_factory_startup_set(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
981 {
982         G.factory_startup = 1;
983         return 0;
984 }
985
986 static const char arg_handle_env_system_set_doc_datafiles[] =
987 "\n\tSet the "STRINGIFY_ARG (BLENDER_SYSTEM_DATAFILES)" environment variable.";
988 static const char arg_handle_env_system_set_doc_scripts[] =
989 "\n\tSet the "STRINGIFY_ARG (BLENDER_SYSTEM_SCRIPTS)" environment variable.";
990 static const char arg_handle_env_system_set_doc_python[] =
991 "\n\tSet the "STRINGIFY_ARG (BLENDER_SYSTEM_PYTHON)" environment variable.";
992
993 static int arg_handle_env_system_set(int argc, const char **argv, void *UNUSED(data))
994 {
995         /* "--env-system-scripts" --> "BLENDER_SYSTEM_SCRIPTS" */
996
997         char env[64] = "BLENDER";
998         char *ch_dst = env + 7; /* skip BLENDER */
999         const char *ch_src = argv[0] + 5; /* skip --env */
1000
1001         if (argc < 2) {
1002                 printf("%s requires one argument\n", argv[0]);
1003                 exit(1);
1004         }
1005
1006         for (; *ch_src; ch_src++, ch_dst++) {
1007                 *ch_dst = (*ch_src == '-') ? '_' : (*ch_src) - 32; /* toupper() */
1008         }
1009
1010         *ch_dst = '\0';
1011         BLI_setenv(env, argv[1]);
1012         return 1;
1013 }
1014
1015 static const char arg_handle_playback_mode_doc[] =
1016 "<options> <file(s)>\n"
1017 "\tPlayback <file(s)>, only operates this way when not running in background.\n\n"
1018 "\t-p <sx> <sy>\n"
1019 "\t\tOpen with lower left corner at <sx>, <sy>.\n"
1020 "\t-m\n"
1021 "\t\tRead from disk (Do not buffer).\n"
1022 "\t-f <fps> <fps-base>\n"
1023 "\t\tSpecify FPS to start with.\n"
1024 "\t-j <frame>\n"
1025 "\t\tSet frame step to <frame>.\n"
1026 "\t-s <frame>\n"
1027 "\t\tPlay from <frame>.\n"
1028 "\t-e <frame>\n"
1029 "\t\tPlay until <frame>."
1030 ;
1031 static int arg_handle_playback_mode(int argc, const char **argv, void *UNUSED(data))
1032 {
1033         /* not if -b was given first */
1034         if (G.background == 0) {
1035 #ifdef WITH_FFMPEG
1036                 /* Setup FFmpeg with current debug flags. */
1037                 IMB_ffmpeg_init();
1038 #endif
1039
1040                 WM_main_playanim(argc, argv); /* not the same argc and argv as before */
1041                 exit(0); /* 2.4x didn't do this */
1042         }
1043
1044         return -2;
1045 }
1046
1047 static const char arg_handle_window_geometry_doc[] =
1048 "<sx> <sy> <w> <h>\n"
1049 "\tOpen with lower left corner at <sx>, <sy> and width and height as <w>, <h>."
1050 ;
1051 static int arg_handle_window_geometry(int argc, const char **argv, void *UNUSED(data))
1052 {
1053         const char *arg_id = "-p / --window-geometry";
1054         int params[4], i;
1055
1056         if (argc < 5) {
1057                 fprintf(stderr, "Error: requires four arguments '%s'\n", arg_id);
1058                 exit(1);
1059         }
1060
1061         for (i = 0; i < 4; i++) {
1062                 const char *err_msg = NULL;
1063                 if (!parse_int(argv[i + 1], NULL, &params[i], &err_msg)) {
1064                         printf("\nError: %s '%s %s'.\n", err_msg, arg_id, argv[1]);
1065                         exit(1);
1066                 }
1067         }
1068
1069         WM_init_state_size_set(UNPACK4(params));
1070
1071         return 4;
1072 }
1073
1074 static const char arg_handle_native_pixels_set_doc[] =
1075 "\n\tDo not use native pixel size, for high resolution displays (MacBook 'Retina')."
1076 ;
1077 static int arg_handle_native_pixels_set(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
1078 {
1079         WM_init_native_pixels(false);
1080         return 0;
1081 }
1082
1083 static const char arg_handle_with_borders_doc[] =
1084 "\n\tForce opening with borders."
1085 ;
1086 static int arg_handle_with_borders(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
1087 {
1088         WM_init_state_normal_set();
1089         return 0;
1090 }
1091
1092 static const char arg_handle_without_borders_doc[] =
1093 "\n\tForce opening in fullscreen mode."
1094 ;
1095 static int arg_handle_without_borders(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
1096 {
1097         WM_init_state_fullscreen_set();
1098         return 0;
1099 }
1100
1101 extern bool wm_start_with_console; /* wm_init_exit.c */
1102
1103 static const char arg_handle_start_with_console_doc[] =
1104 "\n\tStart with the console window open (ignored if -b is set), (Windows only)."
1105 ;
1106 static int arg_handle_start_with_console(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
1107 {
1108         wm_start_with_console = true;
1109         return 0;
1110 }
1111
1112 static const char arg_handle_register_extension_doc[] =
1113 "\n\tRegister blend-file extension, then exit (Windows only)."
1114 ;
1115 static const char arg_handle_register_extension_doc_silent[] =
1116 "\n\tSilently register blend-file extension, then exit (Windows only)."
1117 ;
1118 static int arg_handle_register_extension(int UNUSED(argc), const char **UNUSED(argv), void *data)
1119 {
1120 #ifdef WIN32
1121         if (data)
1122                 G.background = 1;
1123         RegisterBlendExtension();
1124 #else
1125         (void)data; /* unused */
1126 #endif
1127         return 0;
1128 }
1129
1130 static const char arg_handle_audio_disable_doc[] =
1131 "\n\tForce sound system to None."
1132 ;
1133 static int arg_handle_audio_disable(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
1134 {
1135         BKE_sound_force_device("Null");
1136         return 0;
1137 }
1138
1139 static const char arg_handle_audio_set_doc[] =
1140 "\n\tForce sound system to a specific device.\n\t'NULL' 'SDL' 'OPENAL' 'JACK'."
1141 ;
1142 static int arg_handle_audio_set(int argc, const char **argv, void *UNUSED(data))
1143 {
1144         if (argc < 1) {
1145                 fprintf(stderr, "-setaudio require one argument\n");
1146                 exit(1);
1147         }
1148
1149         BKE_sound_force_device(argv[1]);
1150         return 1;
1151 }
1152
1153 static const char arg_handle_output_set_doc[] =
1154 "<path>\n"
1155 "\tSet the render path and file name.\n"
1156 "\tUse '//' at the start of the path to render relative to the blend-file.\n"
1157 "\n"
1158 "\tThe '#' characters are replaced by the frame number, and used to define zero padding.\n"
1159 "\n"
1160 "\t* 'ani_##_test.png' becomes 'ani_01_test.png'\n"
1161 "\t* 'test-######.png' becomes 'test-000001.png'\n"
1162 "\n"
1163 "\tWhen the filename does not contain '#', The suffix '####' is added to the filename.\n"
1164 "\n"
1165 "\tThe frame number will be added at the end of the filename, eg:\n"
1166 "\t# blender -b foobar.blend -o //render_ -F PNG -x 1 -a\n"
1167 "\t'//render_' becomes '//render_####', writing frames as '//render_0001.png'"
1168 ;
1169 static int arg_handle_output_set(int argc, const char **argv, void *data)
1170 {
1171         bContext *C = data;
1172         if (argc > 1) {
1173                 Scene *scene = CTX_data_scene(C);
1174                 if (scene) {
1175                         BLI_strncpy(scene->r.pic, argv[1], sizeof(scene->r.pic));
1176                 }
1177                 else {
1178                         printf("\nError: no blend loaded. cannot use '-o / --render-output'.\n");
1179                 }
1180                 return 1;
1181         }
1182         else {
1183                 printf("\nError: you must specify a path after '-o  / --render-output'.\n");
1184                 return 0;
1185         }
1186 }
1187
1188 static const char arg_handle_engine_set_doc[] =
1189 "<engine>\n"
1190 "\tSpecify the render engine.\n\tUse -E help to list available engines."
1191 ;
1192 static int arg_handle_engine_set(int argc, const char **argv, void *data)
1193 {
1194         bContext *C = data;
1195         if (argc >= 2) {
1196                 if (STREQ(argv[1], "help")) {
1197                         RenderEngineType *type = NULL;
1198                         printf("Blender Engine Listing:\n");
1199                         for (type = R_engines.first; type; type = type->next) {
1200                                 printf("\t%s\n", type->idname);
1201                         }
1202                         exit(0);
1203                 }
1204                 else {
1205                         Scene *scene = CTX_data_scene(C);
1206                         if (scene) {
1207                                 if (BLI_findstring(&R_engines, argv[1], offsetof(RenderEngineType, idname))) {
1208                                         BLI_strncpy_utf8(scene->r.engine, argv[1], sizeof(scene->r.engine));
1209                                 }
1210                                 else {
1211                                         printf("\nError: engine not found '%s'\n", argv[1]);
1212                                         exit(1);
1213                                 }
1214                         }
1215                         else {
1216                                 printf("\nError: no blend loaded. "
1217                                        "order the arguments so '-E  / --engine ' is after a blend is loaded.\n");
1218                         }
1219                 }
1220
1221                 return 1;
1222         }
1223         else {
1224                 printf("\nEngine not specified, give 'help' for a list of available engines.\n");
1225                 return 0;
1226         }
1227 }
1228
1229 static const char arg_handle_image_type_set_doc[] =
1230 "<format>\n"
1231 "\tSet the render format.\n"
1232 "\tValid options are 'TGA' 'RAWTGA' 'JPEG' 'IRIS' 'IRIZ' 'AVIRAW' 'AVIJPEG' 'PNG' 'BMP'\n"
1233 "\n"
1234 "\tFormats that can be compiled into Blender, not available on all systems: 'HDR' 'TIFF' 'EXR' 'MULTILAYER'\n"
1235 "\t'MPEG' 'CINEON' 'DPX' 'DDS' 'JP2'"
1236 ;
1237 static int arg_handle_image_type_set(int argc, const char **argv, void *data)
1238 {
1239         bContext *C = data;
1240         if (argc > 1) {
1241                 const char *imtype = argv[1];
1242                 Scene *scene = CTX_data_scene(C);
1243                 if (scene) {
1244                         const char imtype_new = BKE_imtype_from_arg(imtype);
1245
1246                         if (imtype_new == R_IMF_IMTYPE_INVALID) {
1247                                 printf("\nError: Format from '-F / --render-format' not known or not compiled in this release.\n");
1248                         }
1249                         else {
1250                                 scene->r.im_format.imtype = imtype_new;
1251                         }
1252                 }
1253                 else {
1254                         printf("\nError: no blend loaded. "
1255                                "order the arguments so '-F  / --render-format' is after the blend is loaded.\n");
1256                 }
1257                 return 1;
1258         }
1259         else {
1260                 printf("\nError: you must specify a format after '-F  / --render-foramt'.\n");
1261                 return 0;
1262         }
1263 }
1264
1265 static const char arg_handle_threads_set_doc[] =
1266 "<threads>\n"
1267 "\tUse amount of <threads> for rendering and other operations\n"
1268 "\t[1-" STRINGIFY(BLENDER_MAX_THREADS) "], 0 for systems processor count."
1269 ;
1270 static int arg_handle_threads_set(int argc, const char **argv, void *UNUSED(data))
1271 {
1272         const char *arg_id = "-t / --threads";
1273         const int min = 0, max = BLENDER_MAX_THREADS;
1274         if (argc > 1) {
1275                 const char *err_msg = NULL;
1276                 int threads;
1277                 if (!parse_int_strict_range(argv[1], NULL, min, max, &threads, &err_msg)) {
1278                         printf("\nError: %s '%s %s', expected number in [%d..%d].\n", err_msg, arg_id, argv[1], min, max);
1279                         return 1;
1280                 }
1281
1282                 BLI_system_num_threads_override_set(threads);
1283                 return 1;
1284         }
1285         else {
1286                 printf("\nError: you must specify a number of threads in [%d..%d] '%s'.\n", min, max, arg_id);
1287                 return 0;
1288         }
1289 }
1290
1291 static const char arg_handle_verbosity_set_doc[] =
1292 "<verbose>\n"
1293 "\tSet logging verbosity level."
1294 ;
1295 static int arg_handle_verbosity_set(int argc, const char **argv, void *UNUSED(data))
1296 {
1297         const char *arg_id = "--verbose";
1298         if (argc > 1) {
1299                 const char *err_msg = NULL;
1300                 int level;
1301                 if (!parse_int(argv[1], NULL, &level, &err_msg)) {
1302                         printf("\nError: %s '%s %s'.\n", err_msg, arg_id, argv[1]);
1303                 }
1304
1305 #ifdef WITH_LIBMV
1306                 libmv_setLoggingVerbosity(level);
1307 #elif defined(WITH_CYCLES_LOGGING)
1308                 CCL_logging_verbosity_set(level);
1309 #else
1310                 (void)level;
1311 #endif
1312
1313                 return 1;
1314         }
1315         else {
1316                 printf("\nError: you must specify a verbosity level.\n");
1317                 return 0;
1318         }
1319 }
1320
1321 static const char arg_handle_extension_set_doc[] =
1322 "<bool>\n"
1323 "\tSet option to add the file extension to the end of the file."
1324 ;
1325 static int arg_handle_extension_set(int argc, const char **argv, void *data)
1326 {
1327         bContext *C = data;
1328         if (argc > 1) {
1329                 Scene *scene = CTX_data_scene(C);
1330                 if (scene) {
1331                         if (argv[1][0] == '0') {
1332                                 scene->r.scemode &= ~R_EXTENSION;
1333                         }
1334                         else if (argv[1][0] == '1') {
1335                                 scene->r.scemode |= R_EXTENSION;
1336                         }
1337                         else {
1338                                 printf("\nError: Use '-x 1 / -x 0' To set the extension option or '--use-extension'\n");
1339                         }
1340                 }
1341                 else {
1342                         printf("\nError: no blend loaded. "
1343                                "order the arguments so '-o ' is after '-x '.\n");
1344                 }
1345                 return 1;
1346         }
1347         else {
1348                 printf("\nError: you must specify a path after '- '.\n");
1349                 return 0;
1350         }
1351 }
1352
1353 static const char arg_handle_render_frame_doc[] =
1354 "<frame>\n"
1355 "\tRender frame <frame> and save it.\n"
1356 "\n"
1357 "\t* +<frame> start frame relative, -<frame> end frame relative.\n"
1358 "\t* A comma separated list of frames can also be used (no spaces).\n"
1359 "\t* A range of frames can be expressed using '..' separator between the first and last frames (inclusive).\n"
1360 ;
1361 static int arg_handle_render_frame(int argc, const char **argv, void *data)
1362 {
1363         const char *arg_id = "-f / --render-frame";
1364         bContext *C = data;
1365         Scene *scene = CTX_data_scene(C);
1366         if (scene) {
1367                 Main *bmain = CTX_data_main(C);
1368
1369                 if (argc > 1) {
1370                         const char *err_msg = NULL;
1371                         Render *re;
1372                         ReportList reports;
1373
1374                         int (*frame_range_arr)[2], frames_range_len;
1375                         if ((frame_range_arr = parse_int_range_relative_clamp_n(
1376                                  argv[1], scene->r.sfra, scene->r.efra, MINAFRAME, MAXFRAME,
1377                                  &frames_range_len, &err_msg)) == NULL)
1378                         {
1379                                 printf("\nError: %s '%s %s'.\n", err_msg, arg_id, argv[1]);
1380                                 return 1;
1381                         }
1382
1383                         re = RE_NewSceneRender(scene);
1384                         BLI_threaded_malloc_begin();
1385                         BKE_reports_init(&reports, RPT_STORE);
1386                         RE_SetReports(re, &reports);
1387                         for (int i = 0; i < frames_range_len; i++) {
1388                                 /* We could pass in frame ranges,
1389                                  * but prefer having exact behavior as passing in multiple frames */
1390                                 if ((frame_range_arr[i][0] <= frame_range_arr[i][1]) == 0) {
1391                                         printf("\nWarning: negative range ignored '%s %s'.\n", arg_id, argv[1]);
1392                                 }
1393
1394                                 for (int frame = frame_range_arr[i][0]; frame <= frame_range_arr[i][1]; frame++) {
1395                                         RE_BlenderAnim(re, bmain, scene, NULL, scene->lay, frame, frame, scene->r.frame_step);
1396                                 }
1397                         }
1398                         RE_SetReports(re, NULL);
1399                         BKE_reports_clear(&reports);
1400                         BLI_threaded_malloc_end();
1401                         MEM_freeN(frame_range_arr);
1402                         return 1;
1403                 }
1404                 else {
1405                         printf("\nError: frame number must follow '%s'.\n", arg_id);
1406                         return 0;
1407                 }
1408         }
1409         else {
1410                 printf("\nError: no blend loaded. cannot use '%s'.\n", arg_id);
1411                 return 0;
1412         }
1413 }
1414
1415 static const char arg_handle_render_animation_doc[] =
1416 "\n\tRender frames from start to end (inclusive)."
1417 ;
1418 static int arg_handle_render_animation(int UNUSED(argc), const char **UNUSED(argv), void *data)
1419 {
1420         bContext *C = data;
1421         Scene *scene = CTX_data_scene(C);
1422         if (scene) {
1423                 Main *bmain = CTX_data_main(C);
1424                 Render *re = RE_NewSceneRender(scene);
1425                 ReportList reports;
1426                 BLI_threaded_malloc_begin();
1427                 BKE_reports_init(&reports, RPT_STORE);
1428                 RE_SetReports(re, &reports);
1429                 RE_BlenderAnim(re, bmain, scene, NULL, scene->lay, scene->r.sfra, scene->r.efra, scene->r.frame_step);
1430                 RE_SetReports(re, NULL);
1431                 BKE_reports_clear(&reports);
1432                 BLI_threaded_malloc_end();
1433         }
1434         else {
1435                 printf("\nError: no blend loaded. cannot use '-a'.\n");
1436         }
1437         return 0;
1438 }
1439
1440 static const char arg_handle_scene_set_doc[] =
1441 "<name>\n"
1442 "\tSet the active scene <name> for rendering."
1443 ;
1444 static int arg_handle_scene_set(int argc, const char **argv, void *data)
1445 {
1446         if (argc > 1) {
1447                 bContext *C = data;
1448                 Scene *scene = BKE_scene_set_name(CTX_data_main(C), argv[1]);
1449                 if (scene) {
1450                         CTX_data_scene_set(C, scene);
1451                 }
1452                 return 1;
1453         }
1454         else {
1455                 printf("\nError: Scene name must follow '-S / --scene'.\n");
1456                 return 0;
1457         }
1458 }
1459
1460 static const char arg_handle_frame_start_set_doc[] =
1461 "<frame>\n"
1462 "\tSet start to frame <frame>, supports +/- for relative frames too."
1463 ;
1464 static int arg_handle_frame_start_set(int argc, const char **argv, void *data)
1465 {
1466         const char *arg_id = "-s / --frame-start";
1467         bContext *C = data;
1468         Scene *scene = CTX_data_scene(C);
1469         if (scene) {
1470                 if (argc > 1) {
1471                         const char *err_msg = NULL;
1472                         if (!parse_int_relative_clamp(
1473                                 argv[1], NULL, scene->r.sfra, scene->r.sfra - 1, MINAFRAME, MAXFRAME,
1474                                 &scene->r.sfra, &err_msg))
1475                         {
1476                                 printf("\nError: %s '%s %s'.\n", err_msg, arg_id, argv[1]);
1477                         }
1478                         return 1;
1479                 }
1480                 else {
1481                         printf("\nError: frame number must follow '%s'.\n", arg_id);
1482                         return 0;
1483                 }
1484         }
1485         else {
1486                 printf("\nError: no blend loaded. cannot use '%s'.\n", arg_id);
1487                 return 0;
1488         }
1489 }
1490
1491 static const char arg_handle_frame_end_set_doc[] =
1492 "<frame>\n"
1493 "\tSet end to frame <frame>, supports +/- for relative frames too."
1494 ;
1495 static int arg_handle_frame_end_set(int argc, const char **argv, void *data)
1496 {
1497         const char *arg_id = "-e / --frame-end";
1498         bContext *C = data;
1499         Scene *scene = CTX_data_scene(C);
1500         if (scene) {
1501                 if (argc > 1) {
1502                         const char *err_msg = NULL;
1503                         if (!parse_int_relative_clamp(
1504                                 argv[1], NULL, scene->r.efra, scene->r.efra - 1, MINAFRAME, MAXFRAME,
1505                                 &scene->r.efra, &err_msg))
1506                         {
1507                                 printf("\nError: %s '%s %s'.\n", err_msg, arg_id, argv[1]);
1508                         }
1509                         return 1;
1510                 }
1511                 else {
1512                         printf("\nError: frame number must follow '%s'.\n", arg_id);
1513                         return 0;
1514                 }
1515         }
1516         else {
1517                 printf("\nError: no blend loaded. cannot use '%s'.\n", arg_id);
1518                 return 0;
1519         }
1520 }
1521
1522 static const char arg_handle_frame_skip_set_doc[] =
1523 "<frames>\n"
1524 "\tSet number of frames to step forward after each rendered frame."
1525 ;
1526 static int arg_handle_frame_skip_set(int argc, const char **argv, void *data)
1527 {
1528         const char *arg_id = "-j / --frame-jump";
1529         bContext *C = data;
1530         Scene *scene = CTX_data_scene(C);
1531         if (scene) {
1532                 if (argc > 1) {
1533                         const char *err_msg = NULL;
1534                         if (!parse_int_clamp(argv[1], NULL, 1, MAXFRAME, &scene->r.frame_step, &err_msg)) {
1535                                 printf("\nError: %s '%s %s'.\n", err_msg, arg_id, argv[1]);
1536                         }
1537                         return 1;
1538                 }
1539                 else {
1540                         printf("\nError: number of frames to step must follow '%s'.\n", arg_id);
1541                         return 0;
1542                 }
1543         }
1544         else {
1545                 printf("\nError: no blend loaded. cannot use '%s'.\n", arg_id);
1546                 return 0;
1547         }
1548 }
1549
1550 static const char arg_handle_python_file_run_doc[] =
1551 "<filename>\n"
1552 "\tRun the given Python script file."
1553 ;
1554 static int arg_handle_python_file_run(int argc, const char **argv, void *data)
1555 {
1556 #ifdef WITH_PYTHON
1557         bContext *C = data;
1558
1559         /* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */
1560         if (argc > 1) {
1561                 /* Make the path absolute because its needed for relative linked blends to be found */
1562                 char filename[FILE_MAX];
1563                 BLI_strncpy(filename, argv[1], sizeof(filename));
1564                 BLI_path_cwd(filename, sizeof(filename));
1565
1566                 bool ok;
1567                 BPY_CTX_SETUP(ok = BPY_execute_filepath(C, filename, NULL));
1568                 if (!ok && app_state.exit_code_on_error.python) {
1569                         printf("\nError: script failed, file: '%s', exiting.\n", argv[1]);
1570                         exit(app_state.exit_code_on_error.python);
1571                 }
1572                 return 1;
1573         }
1574         else {
1575                 printf("\nError: you must specify a filepath after '%s'.\n", argv[0]);
1576                 return 0;
1577         }
1578 #else
1579         UNUSED_VARS(argc, argv, data);
1580         printf("This Blender was built without Python support\n");
1581         return 0;
1582 #endif /* WITH_PYTHON */
1583 }
1584
1585 static const char arg_handle_python_text_run_doc[] =
1586 "<name>\n"
1587 "\tRun the given Python script text block."
1588 ;
1589 static int arg_handle_python_text_run(int argc, const char **argv, void *data)
1590 {
1591 #ifdef WITH_PYTHON
1592         bContext *C = data;
1593
1594         /* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */
1595         if (argc > 1) {
1596                 Main *bmain = CTX_data_main(C);
1597                 /* Make the path absolute because its needed for relative linked blends to be found */
1598                 struct Text *text = (struct Text *)BKE_libblock_find_name(bmain, ID_TXT, argv[1]);
1599                 bool ok;
1600
1601                 if (text) {
1602                         BPY_CTX_SETUP(ok = BPY_execute_text(C, text, NULL, false));
1603                 }
1604                 else {
1605                         printf("\nError: text block not found %s.\n", argv[1]);
1606                         ok = false;
1607                 }
1608
1609                 if (!ok && app_state.exit_code_on_error.python) {
1610                         printf("\nError: script failed, text: '%s', exiting.\n", argv[1]);
1611                         exit(app_state.exit_code_on_error.python);
1612                 }
1613
1614                 return 1;
1615         }
1616         else {
1617                 printf("\nError: you must specify a text block after '%s'.\n", argv[0]);
1618                 return 0;
1619         }
1620 #else
1621         UNUSED_VARS(argc, argv, data);
1622         printf("This Blender was built without Python support\n");
1623         return 0;
1624 #endif /* WITH_PYTHON */
1625 }
1626
1627 static const char arg_handle_python_expr_run_doc[] =
1628 "<expression>\n"
1629 "\tRun the given expression as a Python script."
1630 ;
1631 static int arg_handle_python_expr_run(int argc, const char **argv, void *data)
1632 {
1633 #ifdef WITH_PYTHON
1634         bContext *C = data;
1635
1636         /* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */
1637         if (argc > 1) {
1638                 bool ok;
1639                 BPY_CTX_SETUP(ok = BPY_execute_string_ex(C, argv[1], false));
1640                 if (!ok && app_state.exit_code_on_error.python) {
1641                         printf("\nError: script failed, expr: '%s', exiting.\n", argv[1]);
1642                         exit(app_state.exit_code_on_error.python);
1643                 }
1644                 return 1;
1645         }
1646         else {
1647                 printf("\nError: you must specify a Python expression after '%s'.\n", argv[0]);
1648                 return 0;
1649         }
1650 #else
1651         UNUSED_VARS(argc, argv, data);
1652         printf("This Blender was built without Python support\n");
1653         return 0;
1654 #endif /* WITH_PYTHON */
1655 }
1656
1657 static const char arg_handle_python_console_run_doc[] =
1658 "\n\tRun Blender with an interactive console."
1659 ;
1660 static int arg_handle_python_console_run(int UNUSED(argc), const char **argv, void *data)
1661 {
1662 #ifdef WITH_PYTHON
1663         bContext *C = data;
1664
1665         BPY_CTX_SETUP(BPY_execute_string(C, "__import__('code').interact()"));
1666
1667         return 0;
1668 #else
1669         UNUSED_VARS(argv, data);
1670         printf("This Blender was built without python support\n");
1671         return 0;
1672 #endif /* WITH_PYTHON */
1673 }
1674
1675 static const char arg_handle_python_exit_code_set_doc[] =
1676 "<code>\n"
1677 "\tSet the exit-code in [0..255] to exit if a Python exception is raised\n"
1678 "\t(only for scripts executed from the command line), zero disables."
1679 ;
1680 static int arg_handle_python_exit_code_set(int argc, const char **argv, void *UNUSED(data))
1681 {
1682         const char *arg_id = "--python-exit-code";
1683         if (argc > 1) {
1684                 const char *err_msg = NULL;
1685                 const int min = 0, max = 255;
1686                 int exit_code;
1687                 if (!parse_int_strict_range(argv[1], NULL, min, max, &exit_code, &err_msg)) {
1688                         printf("\nError: %s '%s %s', expected number in [%d..%d].\n", err_msg, arg_id, argv[1], min, max);
1689                         return 1;
1690                 }
1691
1692                 app_state.exit_code_on_error.python = (unsigned char)exit_code;
1693                 return 1;
1694         }
1695         else {
1696                 printf("\nError: you must specify an exit code number '%s'.\n", arg_id);
1697                 return 0;
1698         }
1699 }
1700
1701 static const char arg_handle_addons_set_doc[] =
1702 "<addon(s)>\n"
1703 "\tComma separated list of add-ons (no spaces)."
1704 ;
1705 static int arg_handle_addons_set(int argc, const char **argv, void *data)
1706 {
1707         /* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */
1708         if (argc > 1) {
1709 #ifdef WITH_PYTHON
1710                 const char script_str[] =
1711                         "from addon_utils import check, enable\n"
1712                         "for m in '%s'.split(','):\n"
1713                         "    if check(m)[1] is False:\n"
1714                         "        enable(m, persistent=True)";
1715                 const int slen = strlen(argv[1]) + (sizeof(script_str) - 2);
1716                 char *str = malloc(slen);
1717                 bContext *C = data;
1718                 BLI_snprintf(str, slen, script_str, argv[1]);
1719
1720                 BLI_assert(strlen(str) + 1 == slen);
1721                 BPY_CTX_SETUP(BPY_execute_string_ex(C, str, false));
1722                 free(str);
1723 #else
1724                 UNUSED_VARS(argv, data);
1725 #endif /* WITH_PYTHON */
1726                 return 1;
1727         }
1728         else {
1729                 printf("\nError: you must specify a comma separated list after '--addons'.\n");
1730                 return 0;
1731         }
1732 }
1733
1734 static int arg_handle_load_file(int UNUSED(argc), const char **argv, void *data)
1735 {
1736         bContext *C = data;
1737         ReportList reports;
1738         bool success;
1739
1740         /* Make the path absolute because its needed for relative linked blends to be found */
1741         char filename[FILE_MAX];
1742
1743         /* note, we could skip these, but so far we always tried to load these files */
1744         if (argv[0][0] == '-') {
1745                 fprintf(stderr, "unknown argument, loading as file: %s\n", argv[0]);
1746         }
1747
1748         BLI_strncpy(filename, argv[0], sizeof(filename));
1749         BLI_path_cwd(filename, sizeof(filename));
1750
1751         /* load the file */
1752         BKE_reports_init(&reports, RPT_PRINT);
1753         WM_file_autoexec_init(filename);
1754         success = WM_file_read(C, filename, &reports);
1755         BKE_reports_clear(&reports);
1756
1757         if (success) {
1758                 if (G.background) {
1759                         /* ensuer we use 'C->data.scene' for background render */
1760                         CTX_wm_window_set(C, NULL);
1761                 }
1762         }
1763         else {
1764                 /* failed to load file, stop processing arguments if running in background mode */
1765                 if (G.background) {
1766                         /* Set is_break if running in the background mode so
1767                          * blender will return non-zero exit code which then
1768                          * could be used in automated script to control how
1769                          * good or bad things are.
1770                          */
1771                         G.is_break = true;
1772                         return -1;
1773                 }
1774
1775                 if (BLO_has_bfile_extension(filename)) {
1776                         /* Just pretend a file was loaded, so the user can press Save and it'll save at the filename from the CLI. */
1777                         BLI_strncpy(G_MAIN->name, filename, FILE_MAX);
1778                         G.relbase_valid = true;
1779                         G.save_over = true;
1780                         printf("... opened default scene instead; saving will write to: %s\n", filename);
1781                 }
1782                 else {
1783                         printf("Error: argument has no '.blend' file extension, not using as new file, exiting! %s\n", filename);
1784                         G.is_break = true;
1785                         WM_exit(C);
1786                 }
1787         }
1788
1789         G.file_loaded = 1;
1790
1791         return 0;
1792 }
1793
1794
1795 void main_args_setup(bContext *C, bArgs *ba)
1796 {
1797
1798 #define CB(a) a##_doc, a
1799 #define CB_EX(a, b) a##_doc_##b, a
1800
1801         //BLI_argsAdd(ba, pass, short_arg, long_arg, doc, cb, C);
1802
1803         /* end argument processing after -- */
1804         BLI_argsAdd(ba, -1, "--", NULL, CB(arg_handle_arguments_end), NULL);
1805
1806         /* first pass: background mode, disable python and commands that exit after usage */
1807         BLI_argsAdd(ba, 1, "-h", "--help", CB(arg_handle_print_help), ba);
1808         /* Windows only */
1809         BLI_argsAdd(ba, 1, "/?", NULL, CB_EX(arg_handle_print_help, win32), ba);
1810
1811         BLI_argsAdd(ba, 1, "-v", "--version", CB(arg_handle_print_version), NULL);
1812
1813         BLI_argsAdd(ba, 1, "-y", "--enable-autoexec", CB_EX(arg_handle_python_set, enable), (void *)true);
1814         BLI_argsAdd(ba, 1, "-Y", "--disable-autoexec", CB_EX(arg_handle_python_set, disable), (void *)false);
1815
1816         BLI_argsAdd(ba, 1, NULL, "--disable-crash-handler", CB(arg_handle_crash_handler_disable), NULL);
1817         BLI_argsAdd(ba, 1, NULL, "--disable-abort-handler", CB(arg_handle_abort_handler_disable), NULL);
1818
1819         BLI_argsAdd(ba, 1, "-b", "--background", CB(arg_handle_background_mode_set), NULL);
1820
1821         BLI_argsAdd(ba, 1, "-a", NULL, CB(arg_handle_playback_mode), NULL);
1822
1823         BLI_argsAdd(ba, 1, NULL, "--log", CB(arg_handle_log_set), ba);
1824         BLI_argsAdd(ba, 1, NULL, "--log-level", CB(arg_handle_log_level_set), ba);
1825         BLI_argsAdd(ba, 1, NULL, "--log-show-basename", CB(arg_handle_log_show_basename_set), ba);
1826         BLI_argsAdd(ba, 1, NULL, "--log-show-backtrace", CB(arg_handle_log_show_backtrace_set), ba);
1827         BLI_argsAdd(ba, 1, NULL, "--log-file", CB(arg_handle_log_file_set), ba);
1828
1829         BLI_argsAdd(ba, 1, "-d", "--debug", CB(arg_handle_debug_mode_set), ba);
1830
1831 #ifdef WITH_FFMPEG
1832         BLI_argsAdd(ba, 1, NULL, "--debug-ffmpeg",
1833                     CB_EX(arg_handle_debug_mode_generic_set, ffmpeg), (void *)G_DEBUG_FFMPEG);
1834 #endif
1835
1836 #ifdef WITH_FREESTYLE
1837         BLI_argsAdd(ba, 1, NULL, "--debug-freestyle",
1838                     CB_EX(arg_handle_debug_mode_generic_set, freestyle), (void *)G_DEBUG_FREESTYLE);
1839 #endif
1840
1841         BLI_argsAdd(ba, 1, NULL, "--debug-python",
1842                     CB_EX(arg_handle_debug_mode_generic_set, python), (void *)G_DEBUG_PYTHON);
1843         BLI_argsAdd(ba, 1, NULL, "--debug-events",
1844                     CB_EX(arg_handle_debug_mode_generic_set, events), (void *)G_DEBUG_EVENTS);
1845         BLI_argsAdd(ba, 1, NULL, "--debug-handlers",
1846                     CB_EX(arg_handle_debug_mode_generic_set, handlers), (void *)G_DEBUG_HANDLERS);
1847         BLI_argsAdd(ba, 1, NULL, "--debug-wm",
1848                     CB_EX(arg_handle_debug_mode_generic_set, wm), (void *)G_DEBUG_WM);
1849         BLI_argsAdd(ba, 1, NULL, "--debug-all", CB(arg_handle_debug_mode_all), NULL);
1850
1851         BLI_argsAdd(ba, 1, NULL, "--debug-io", CB(arg_handle_debug_mode_io), NULL);
1852
1853         BLI_argsAdd(ba, 1, NULL, "--debug-fpe",
1854                     CB(arg_handle_debug_fpe_set), NULL);
1855
1856 #ifdef WITH_LIBMV
1857         BLI_argsAdd(ba, 1, NULL, "--debug-libmv", CB(arg_handle_debug_mode_libmv), NULL);
1858 #endif
1859 #ifdef WITH_CYCLES_LOGGING
1860         BLI_argsAdd(ba, 1, NULL, "--debug-cycles", CB(arg_handle_debug_mode_cycles), NULL);
1861 #endif
1862         BLI_argsAdd(ba, 1, NULL, "--debug-memory", CB(arg_handle_debug_mode_memory_set), NULL);
1863
1864         BLI_argsAdd(ba, 1, NULL, "--debug-value",
1865                     CB(arg_handle_debug_value_set), NULL);
1866         BLI_argsAdd(ba, 1, NULL, "--debug-jobs",
1867                     CB_EX(arg_handle_debug_mode_generic_set, jobs), (void *)G_DEBUG_JOBS);
1868         BLI_argsAdd(ba, 1, NULL, "--debug-gpu",
1869                     CB_EX(arg_handle_debug_mode_generic_set, gpu), (void *)G_DEBUG_GPU);
1870         BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph",
1871                     CB_EX(arg_handle_debug_mode_generic_set, depsgraph), (void *)G_DEBUG_DEPSGRAPH);
1872         BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph-build",
1873                     CB_EX(arg_handle_debug_mode_generic_set, depsgraph_build), (void *)G_DEBUG_DEPSGRAPH_BUILD);
1874         BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph-eval",
1875                     CB_EX(arg_handle_debug_mode_generic_set, depsgraph_eval), (void *)G_DEBUG_DEPSGRAPH_EVAL);
1876         BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph-tag",
1877                     CB_EX(arg_handle_debug_mode_generic_set, depsgraph_tag), (void *)G_DEBUG_DEPSGRAPH_TAG);
1878         BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph-time",
1879                     CB_EX(arg_handle_debug_mode_generic_set, depsgraph_time), (void *)G_DEBUG_DEPSGRAPH_TIME);
1880         BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph-no-threads",
1881                     CB_EX(arg_handle_debug_mode_generic_set, depsgraph_no_threads), (void *)G_DEBUG_DEPSGRAPH_NO_THREADS);
1882         BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph-pretty",
1883                     CB_EX(arg_handle_debug_mode_generic_set, depsgraph_pretty), (void *)G_DEBUG_DEPSGRAPH_PRETTY);
1884         BLI_argsAdd(ba, 1, NULL, "--debug-gpumem",
1885                     CB_EX(arg_handle_debug_mode_generic_set, gpumem), (void *)G_DEBUG_GPU_MEM);
1886         BLI_argsAdd(ba, 1, NULL, "--debug-gpu-shaders",
1887                     CB_EX(arg_handle_debug_mode_generic_set, gpumem), (void *)G_DEBUG_GPU_SHADERS);
1888
1889         BLI_argsAdd(ba, 1, NULL, "--verbose", CB(arg_handle_verbosity_set), NULL);
1890
1891         BLI_argsAdd(ba, 1, NULL, "--factory-startup", CB(arg_handle_factory_startup_set), NULL);
1892
1893         /* TODO, add user env vars? */
1894         BLI_argsAdd(ba, 1, NULL, "--env-system-datafiles", CB_EX(arg_handle_env_system_set, datafiles), NULL);
1895         BLI_argsAdd(ba, 1, NULL, "--env-system-scripts", CB_EX(arg_handle_env_system_set, scripts), NULL);
1896         BLI_argsAdd(ba, 1, NULL, "--env-system-python", CB_EX(arg_handle_env_system_set, python), NULL);
1897
1898         /* second pass: custom window stuff */
1899         BLI_argsAdd(ba, 2, "-p", "--window-geometry", CB(arg_handle_window_geometry), NULL);
1900         BLI_argsAdd(ba, 2, "-w", "--window-border", CB(arg_handle_with_borders), NULL);
1901         BLI_argsAdd(ba, 2, "-W", "--window-fullscreen", CB(arg_handle_without_borders), NULL);
1902         BLI_argsAdd(ba, 2, "-con", "--start-console", CB(arg_handle_start_with_console), NULL);
1903         BLI_argsAdd(ba, 2, "-R", NULL, CB(arg_handle_register_extension), NULL);
1904         BLI_argsAdd(ba, 2, "-r", NULL, CB_EX(arg_handle_register_extension, silent), ba);
1905         BLI_argsAdd(ba, 2, NULL, "--no-native-pixels", CB(arg_handle_native_pixels_set), ba);
1906
1907         /* third pass: disabling things and forcing settings */
1908         BLI_argsAddCase(ba, 3, "-noaudio", 1, NULL, 0, CB(arg_handle_audio_disable), NULL);
1909         BLI_argsAddCase(ba, 3, "-setaudio", 1, NULL, 0, CB(arg_handle_audio_set), NULL);
1910
1911         /* fourth pass: processing arguments */
1912         BLI_argsAdd(ba, 4, "-f", "--render-frame", CB(arg_handle_render_frame), C);
1913         BLI_argsAdd(ba, 4, "-a", "--render-anim", CB(arg_handle_render_animation), C);
1914         BLI_argsAdd(ba, 4, "-S", "--scene", CB(arg_handle_scene_set), C);
1915         BLI_argsAdd(ba, 4, "-s", "--frame-start", CB(arg_handle_frame_start_set), C);
1916         BLI_argsAdd(ba, 4, "-e", "--frame-end", CB(arg_handle_frame_end_set), C);
1917         BLI_argsAdd(ba, 4, "-j", "--frame-jump", CB(arg_handle_frame_skip_set), C);
1918         BLI_argsAdd(ba, 4, "-P", "--python", CB(arg_handle_python_file_run), C);
1919         BLI_argsAdd(ba, 4, NULL, "--python-text", CB(arg_handle_python_text_run), C);
1920         BLI_argsAdd(ba, 4, NULL, "--python-expr", CB(arg_handle_python_expr_run), C);
1921         BLI_argsAdd(ba, 4, NULL, "--python-console", CB(arg_handle_python_console_run), C);
1922         BLI_argsAdd(ba, 4, NULL, "--python-exit-code", CB(arg_handle_python_exit_code_set), NULL);
1923         BLI_argsAdd(ba, 4, NULL, "--addons", CB(arg_handle_addons_set), C);
1924
1925         BLI_argsAdd(ba, 4, "-o", "--render-output", CB(arg_handle_output_set), C);
1926         BLI_argsAdd(ba, 4, "-E", "--engine", CB(arg_handle_engine_set), C);
1927
1928         BLI_argsAdd(ba, 4, "-F", "--render-format", CB(arg_handle_image_type_set), C);
1929         BLI_argsAdd(ba, 1, "-t", "--threads", CB(arg_handle_threads_set), NULL);
1930         BLI_argsAdd(ba, 4, "-x", "--use-extension", CB(arg_handle_extension_set), C);
1931
1932 #undef CB
1933 #undef CB_EX
1934
1935 }
1936
1937 /**
1938  * Needs to be added separately.
1939  */
1940 void main_args_setup_post(bContext *C, bArgs *ba)
1941 {
1942         BLI_argsParse(ba, 4, arg_handle_load_file, C);
1943 }
1944
1945 /** \} */
1946
1947 #endif /* WITH_PYTHON_MODULE */