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
49 #include "BLO_readfile.h"  /* only for BLO_has_bfile_extension */
50
51 #include "BKE_blender_version.h"
52 #include "BKE_context.h"
53
54 #include "BKE_global.h"
55 #include "BKE_library.h"
56 #include "BKE_main.h"
57 #include "BKE_scene.h"
58 #include "BKE_report.h"
59 #include "BKE_sound.h"
60 #include "BKE_image.h"
61
62 #ifdef WITH_FFMPEG
63 #include "IMB_imbuf.h"
64 #endif
65
66 #ifdef WITH_PYTHON
67 #include "BPY_extern.h"
68 #endif
69
70 #include "RE_engine.h"
71 #include "RE_pipeline.h"
72
73 #include "ED_datafiles.h"
74
75 #include "WM_api.h"
76
77 #include "GPU_draw.h"
78
79 #ifdef WITH_LIBMV
80 #  include "libmv-capi.h"
81 #endif
82
83 #ifdef WITH_CYCLES_LOGGING
84 #  include "CCL_api.h"
85 #endif
86
87 #include "DEG_depsgraph.h"
88 #include "DEG_depsgraph_build.h"
89 #include "DEG_depsgraph_debug.h"
90
91 #include "creator_intern.h"  /* own include */
92
93
94 /* -------------------------------------------------------------------- */
95
96 /** \name Utility String Parsing
97  * \{ */
98
99 static bool parse_int_relative(
100         const char *str, const char *str_end_test, int pos, int neg,
101         int *r_value, const char **r_err_msg)
102 {
103         char *str_end = NULL;
104         long value;
105
106         errno = 0;
107
108         switch (*str) {
109                 case '+':
110                         value = pos + strtol(str + 1, &str_end, 10);
111                         break;
112                 case '-':
113                         value = (neg - strtol(str + 1, &str_end, 10)) + 1;
114                         break;
115                 default:
116                         value = strtol(str, &str_end, 10);
117                         break;
118         }
119
120
121         if (*str_end != '\0' && (str_end != str_end_test)) {
122                 static const char *msg = "not a number";
123                 *r_err_msg = msg;
124                 return false;
125         }
126         else if ((errno == ERANGE) || ((value < INT_MIN || value > INT_MAX))) {
127                 static const char *msg = "exceeds range";
128                 *r_err_msg = msg;
129                 return false;
130         }
131         else {
132                 *r_value = (int)value;
133                 return true;
134         }
135 }
136
137 static const char *parse_int_range_sep_search(const char *str, const char *str_end_test)
138 {
139         const char *str_end_range = NULL;
140         if (str_end_test) {
141                 str_end_range = memchr(str, '.', (str_end_test - str) - 1);
142                 if (str_end_range && (str_end_range[1] != '.')) {
143                         str_end_range = NULL;
144                 }
145         }
146         else {
147                 str_end_range = strstr(str, "..");
148                 if (str_end_range && (str_end_range[2] == '\0')) {
149                         str_end_range = NULL;
150                 }
151         }
152         return str_end_range;
153 }
154
155 /**
156  * Parse a number as a range, eg: `1..4`.
157  *
158  * The \a str_end_range argument is a result of #parse_int_range_sep_search.
159  */
160 static bool parse_int_range_relative(
161         const char *str, const char *str_end_range, const char *str_end_test, int pos, int neg,
162         int r_value_range[2], const char **r_err_msg)
163 {
164         if (parse_int_relative(str,               str_end_range, pos, neg, &r_value_range[0], r_err_msg) &&
165             parse_int_relative(str_end_range + 2, str_end_test,  pos, neg, &r_value_range[1], r_err_msg))
166         {
167                 return true;
168         }
169         else {
170                 return false;
171         }
172 }
173
174 static bool parse_int_relative_clamp(
175         const char *str, const char *str_end_test, int pos, int neg, int min, int max,
176         int *r_value, const char **r_err_msg)
177 {
178         if (parse_int_relative(str, str_end_test, pos, neg, r_value, r_err_msg)) {
179                 CLAMP(*r_value, min, max);
180                 return true;
181         }
182         else {
183                 return false;
184         }
185 }
186
187 static bool parse_int_range_relative_clamp(
188         const char *str, const char *str_end_range, const char *str_end_test, int pos, int neg, int min, int max,
189         int r_value_range[2], const char **r_err_msg)
190 {
191         if (parse_int_range_relative(str, str_end_range, str_end_test, pos, neg, r_value_range, r_err_msg)) {
192                 CLAMP(r_value_range[0], min, max);
193                 CLAMP(r_value_range[1], min, max);
194                 return true;
195         }
196         else {
197                 return false;
198         }
199 }
200
201 /**
202  * No clamping, fails with any number outside the range.
203  */
204 static bool parse_int_strict_range(
205         const char *str, const char *str_end_test, const int min, const int max,
206         int *r_value, const char **r_err_msg)
207 {
208         char *str_end = NULL;
209         long value;
210
211         errno = 0;
212         value = strtol(str, &str_end, 10);
213
214         if (*str_end != '\0' && (str_end != str_end_test)) {
215                 static const char *msg = "not a number";
216                 *r_err_msg = msg;
217                 return false;
218         }
219         else if ((errno == ERANGE) || ((value < min || value > max))) {
220                 static const char *msg = "exceeds range";
221                 *r_err_msg = msg;
222                 return false;
223         }
224         else {
225                 *r_value = (int)value;
226                 return true;
227         }
228 }
229
230 static bool parse_int(
231         const char *str, const char *str_end_test,
232         int *r_value, const char **r_err_msg)
233 {
234         return parse_int_strict_range(str, str_end_test, INT_MIN, INT_MAX, r_value, r_err_msg);
235 }
236
237 static bool parse_int_clamp(
238         const char *str, const char *str_end_test, int min, int max,
239         int *r_value, const char **r_err_msg)
240 {
241         if (parse_int(str, str_end_test, r_value, r_err_msg)) {
242                 CLAMP(*r_value, min, max);
243                 return true;
244         }
245         else {
246                 return false;
247         }
248 }
249
250 #if 0
251 /**
252  * Version of #parse_int_relative_clamp
253  * that parses a comma separated list of numbers.
254  */
255 static int *parse_int_relative_clamp_n(
256         const char *str, int pos, int neg, int min, int max,
257         int *r_value_len, const char **r_err_msg)
258 {
259         const char sep = ',';
260         int len = 1;
261         for (int i = 0; str[i]; i++) {
262                 if (str[i] == sep) {
263                         len++;
264                 }
265         }
266
267         int *values = MEM_mallocN(sizeof(*values) * len, __func__);
268         int i = 0;
269         while (true) {
270                 const char *str_end = strchr(str, sep);
271                 if ((*str == sep) || (*str == '\0')) {
272                         static const char *msg = "incorrect comma use";
273                         *r_err_msg = msg;
274                         goto fail;
275
276                 }
277                 else if (parse_int_relative_clamp(str, str_end, pos, neg, min, max, &values[i], r_err_msg)) {
278                         i++;
279                 }
280                 else {
281                         goto fail;  /* error message already set */
282                 }
283
284                 if (str_end) {  /* next */
285                         str = str_end + 1;
286                 }
287                 else {  /* finished */
288                         break;
289                 }
290         }
291
292         *r_value_len = i;
293         return values;
294
295 fail:
296         MEM_freeN(values);
297         return NULL;
298 }
299
300 #endif
301
302 /**
303  * Version of #parse_int_relative_clamp & #parse_int_range_relative_clamp
304  * that parses a comma separated list of numbers.
305  *
306  * \note single values are evaluated as a range with matching start/end.
307  */
308 static int (*parse_int_range_relative_clamp_n(
309         const char *str, int pos, int neg, int min, int max,
310         int *r_value_len, const char **r_err_msg))[2]
311 {
312         const char sep = ',';
313         int len = 1;
314         for (int i = 0; str[i]; i++) {
315                 if (str[i] == sep) {
316                         len++;
317                 }
318         }
319
320         int (*values)[2] = MEM_mallocN(sizeof(*values) * len, __func__);
321         int i = 0;
322         while (true) {
323                 const char *str_end_range;
324                 const char *str_end = strchr(str, sep);
325                 if ((*str == sep) || (*str == '\0')) {
326                         static const char *msg = "incorrect comma use";
327                         *r_err_msg = msg;
328                         goto fail;
329                 }
330                 else if ((str_end_range = parse_int_range_sep_search(str, str_end)) ?
331                          parse_int_range_relative_clamp(str, str_end_range, str_end, pos, neg, min, max, values[i], r_err_msg) :
332                          parse_int_relative_clamp(str, str_end, pos, neg, min, max, &values[i][0], r_err_msg))
333                 {
334                         if (str_end_range == NULL) {
335                                 values[i][1] = values[i][0];
336                         }
337                         i++;
338                 }
339                 else {
340                         goto fail;  /* error message already set */
341                 }
342
343                 if (str_end) {  /* next */
344                         str = str_end + 1;
345                 }
346                 else {  /* finished */
347                         break;
348                 }
349         }
350
351         *r_value_len = i;
352         return values;
353
354 fail:
355         MEM_freeN(values);
356         return NULL;
357 }
358
359 /** \} */
360
361
362 /* -------------------------------------------------------------------- */
363
364 #ifdef WITH_PYTHON
365
366 /** \name Utilities Python Context Macro (#BPY_CTX_SETUP)
367  * \{ */
368 struct BlendePyContextStore {
369         wmWindowManager *wm;
370         Scene *scene;
371         wmWindow *win;
372         bool has_win;
373 };
374
375 static void arg_py_context_backup(
376         bContext *C, struct BlendePyContextStore *c_py,
377         const char *script_id)
378 {
379         c_py->wm = CTX_wm_manager(C);
380         c_py->scene = CTX_data_scene(C);
381         c_py->has_win = !BLI_listbase_is_empty(&c_py->wm->windows);
382         if (c_py->has_win) {
383                 c_py->win = CTX_wm_window(C);
384                 CTX_wm_window_set(C, c_py->wm->windows.first);
385         }
386         else {
387                 c_py->win = NULL;
388                 fprintf(stderr, "Python script \"%s\" "
389                         "running with missing context data.\n", script_id);
390         }
391 }
392
393 static void arg_py_context_restore(
394         bContext *C, struct BlendePyContextStore *c_py)
395 {
396         /* script may load a file, check old data is valid before using */
397         if (c_py->has_win) {
398                 if ((c_py->win == NULL) ||
399                     ((BLI_findindex(&G.main->wm, c_py->wm) != -1) &&
400                      (BLI_findindex(&c_py->wm->windows, c_py->win) != -1)))
401                 {
402                         CTX_wm_window_set(C, c_py->win);
403                 }
404         }
405
406         if ((c_py->scene == NULL) ||
407             BLI_findindex(&G.main->scene, c_py->scene) != -1)
408         {
409                 CTX_data_scene_set(C, c_py->scene);
410         }
411 }
412
413 /* macro for context setup/reset */
414 #define BPY_CTX_SETUP(_cmd) \
415         { \
416                 struct BlendePyContextStore py_c; \
417                 arg_py_context_backup(C, &py_c, argv[1]); \
418                 { _cmd; } \
419                 arg_py_context_restore(C, &py_c); \
420         } ((void)0)
421
422 #endif /* WITH_PYTHON */
423
424 /** \} */
425
426 /* -------------------------------------------------------------------- */
427
428 /** \name Handle Argument Callbacks
429  *
430  * \note Doc strings here are used in differently:
431  *
432  * - The `--help` message.
433  * - The man page (for Unix systems),
434  *   see: `doc/manpage/blender.1.py`
435  * - Parsed and extracted for the manual,
436  *   which converts our ad-hoc formatting to reStructuredText.
437  *   see: https://docs.blender.org/manual/en/dev/advanced/command_line.html
438  *
439  * \{ */
440
441 static const char arg_handle_print_version_doc[] =
442 "\n\tPrint Blender version and exit."
443 ;
444 static int arg_handle_print_version(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
445 {
446         printf(BLEND_VERSION_STRING_FMT);
447 #ifdef BUILD_DATE
448         printf("\tbuild date: %s\n", build_date);
449         printf("\tbuild time: %s\n", build_time);
450         printf("\tbuild commit date: %s\n", build_commit_date);
451         printf("\tbuild commit time: %s\n", build_commit_time);
452         printf("\tbuild hash: %s\n", build_hash);
453         printf("\tbuild platform: %s\n", build_platform);
454         printf("\tbuild type: %s\n", build_type);
455         printf("\tbuild c flags: %s\n", build_cflags);
456         printf("\tbuild c++ flags: %s\n", build_cxxflags);
457         printf("\tbuild link flags: %s\n", build_linkflags);
458         printf("\tbuild system: %s\n", build_system);
459 #endif
460         exit(0);
461
462         return 0;
463 }
464
465 static const char arg_handle_print_help_doc[] =
466 "\n\tPrint this help text and exit."
467 ;
468 static const char arg_handle_print_help_doc_win32[] =
469 "\n\tPrint this help text and exit (windows only)."
470 ;
471 static int arg_handle_print_help(int UNUSED(argc), const char **UNUSED(argv), void *data)
472 {
473         bArgs *ba = (bArgs *)data;
474
475         printf(BLEND_VERSION_STRING_FMT);
476         printf("Usage: blender [args ...] [file] [args ...]\n\n");
477
478         printf("Render Options:\n");
479         BLI_argsPrintArgDoc(ba, "--background");
480         BLI_argsPrintArgDoc(ba, "--render-anim");
481         BLI_argsPrintArgDoc(ba, "--scene");
482         BLI_argsPrintArgDoc(ba, "--render-frame");
483         BLI_argsPrintArgDoc(ba, "--frame-start");
484         BLI_argsPrintArgDoc(ba, "--frame-end");
485         BLI_argsPrintArgDoc(ba, "--frame-jump");
486         BLI_argsPrintArgDoc(ba, "--render-output");
487         BLI_argsPrintArgDoc(ba, "--engine");
488         BLI_argsPrintArgDoc(ba, "--threads");
489
490         printf("\n");
491         printf("Format Options:\n");
492         BLI_argsPrintArgDoc(ba, "--render-format");
493         BLI_argsPrintArgDoc(ba, "--use-extension");
494
495         printf("\n");
496         printf("Animation Playback Options:\n");
497         BLI_argsPrintArgDoc(ba, "-a");
498
499         printf("\n");
500         printf("Window Options:\n");
501         BLI_argsPrintArgDoc(ba, "--window-border");
502         BLI_argsPrintArgDoc(ba, "--window-fullscreen");
503         BLI_argsPrintArgDoc(ba, "--window-geometry");
504         BLI_argsPrintArgDoc(ba, "--start-console");
505         BLI_argsPrintArgDoc(ba, "--no-native-pixels");
506
507         printf("\n");
508         printf("Python Options:\n");
509         BLI_argsPrintArgDoc(ba, "--enable-autoexec");
510         BLI_argsPrintArgDoc(ba, "--disable-autoexec");
511
512         printf("\n");
513
514         BLI_argsPrintArgDoc(ba, "--python");
515         BLI_argsPrintArgDoc(ba, "--python-text");
516         BLI_argsPrintArgDoc(ba, "--python-expr");
517         BLI_argsPrintArgDoc(ba, "--python-console");
518         BLI_argsPrintArgDoc(ba, "--python-exit-code");
519         BLI_argsPrintArgDoc(ba, "--addons");
520
521         printf("\n");
522         printf("Logging Options:\n");
523         BLI_argsPrintArgDoc(ba, "--log");
524         BLI_argsPrintArgDoc(ba, "--log-level");
525         BLI_argsPrintArgDoc(ba, "--log-show-basename");
526         BLI_argsPrintArgDoc(ba, "--log-show-backtrace");
527         BLI_argsPrintArgDoc(ba, "--log-file");
528
529         printf("\n");
530         printf("Debug Options:\n");
531         BLI_argsPrintArgDoc(ba, "--debug");
532         BLI_argsPrintArgDoc(ba, "--debug-value");
533
534         printf("\n");
535         BLI_argsPrintArgDoc(ba, "--debug-events");
536 #ifdef WITH_FFMPEG
537         BLI_argsPrintArgDoc(ba, "--debug-ffmpeg");
538 #endif
539         BLI_argsPrintArgDoc(ba, "--debug-handlers");
540 #ifdef WITH_LIBMV
541         BLI_argsPrintArgDoc(ba, "--debug-libmv");
542 #endif
543 #ifdef WITH_CYCLES_LOGGING
544         BLI_argsPrintArgDoc(ba, "--debug-cycles");
545 #endif
546         BLI_argsPrintArgDoc(ba, "--debug-memory");
547         BLI_argsPrintArgDoc(ba, "--debug-jobs");
548         BLI_argsPrintArgDoc(ba, "--debug-python");
549         BLI_argsPrintArgDoc(ba, "--debug-depsgraph");
550         BLI_argsPrintArgDoc(ba, "--debug-depsgraph-eval");
551         BLI_argsPrintArgDoc(ba, "--debug-depsgraph-build");
552         BLI_argsPrintArgDoc(ba, "--debug-depsgraph-tag");
553         BLI_argsPrintArgDoc(ba, "--debug-depsgraph-no-threads");
554
555         BLI_argsPrintArgDoc(ba, "--debug-gpumem");
556         BLI_argsPrintArgDoc(ba, "--debug-gpu-shaders");
557         BLI_argsPrintArgDoc(ba, "--debug-wm");
558         BLI_argsPrintArgDoc(ba, "--debug-all");
559         BLI_argsPrintArgDoc(ba, "--debug-io");
560
561         printf("\n");
562         BLI_argsPrintArgDoc(ba, "--debug-fpe");
563         BLI_argsPrintArgDoc(ba, "--disable-crash-handler");
564
565         printf("\n");
566         printf("Misc Options:\n");
567         BLI_argsPrintArgDoc(ba, "--factory-startup");
568         printf("\n");
569         BLI_argsPrintArgDoc(ba, "--env-system-datafiles");
570         BLI_argsPrintArgDoc(ba, "--env-system-scripts");
571         BLI_argsPrintArgDoc(ba, "--env-system-python");
572         printf("\n");
573         BLI_argsPrintArgDoc(ba, "-noaudio");
574         BLI_argsPrintArgDoc(ba, "-setaudio");
575
576         printf("\n");
577
578         BLI_argsPrintArgDoc(ba, "--help");
579
580 #ifdef WIN32
581         BLI_argsPrintArgDoc(ba, "-R");
582         BLI_argsPrintArgDoc(ba, "-r");
583 #endif
584         BLI_argsPrintArgDoc(ba, "--version");
585
586         BLI_argsPrintArgDoc(ba, "--");
587
588         printf("\n");
589         printf("Experimental Features:\n");
590         BLI_argsPrintArgDoc(ba, "--enable-copy-on-write");
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_use_copy_on_write_doc[] =
1292 "\n\tUse new dependency graph"
1293 ;
1294 static int arg_handle_use_copy_on_write(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
1295 {
1296         printf("Using copy on write. This is highly EXPERIMENTAL!\n");
1297         DEG_depsgraph_enable_copy_on_write();
1298         return 0;
1299 }
1300
1301 static const char arg_handle_verbosity_set_doc[] =
1302 "<verbose>\n"
1303 "\tSet logging verbosity level."
1304 ;
1305 static int arg_handle_verbosity_set(int argc, const char **argv, void *UNUSED(data))
1306 {
1307         const char *arg_id = "--verbose";
1308         if (argc > 1) {
1309                 const char *err_msg = NULL;
1310                 int level;
1311                 if (!parse_int(argv[1], NULL, &level, &err_msg)) {
1312                         printf("\nError: %s '%s %s'.\n", err_msg, arg_id, argv[1]);
1313                 }
1314
1315 #ifdef WITH_LIBMV
1316                 libmv_setLoggingVerbosity(level);
1317 #elif defined(WITH_CYCLES_LOGGING)
1318                 CCL_logging_verbosity_set(level);
1319 #else
1320                 (void)level;
1321 #endif
1322
1323                 return 1;
1324         }
1325         else {
1326                 printf("\nError: you must specify a verbosity level.\n");
1327                 return 0;
1328         }
1329 }
1330
1331 static const char arg_handle_extension_set_doc[] =
1332 "<bool>\n"
1333 "\tSet option to add the file extension to the end of the file."
1334 ;
1335 static int arg_handle_extension_set(int argc, const char **argv, void *data)
1336 {
1337         bContext *C = data;
1338         if (argc > 1) {
1339                 Scene *scene = CTX_data_scene(C);
1340                 if (scene) {
1341                         if (argv[1][0] == '0') {
1342                                 scene->r.scemode &= ~R_EXTENSION;
1343                         }
1344                         else if (argv[1][0] == '1') {
1345                                 scene->r.scemode |= R_EXTENSION;
1346                         }
1347                         else {
1348                                 printf("\nError: Use '-x 1 / -x 0' To set the extension option or '--use-extension'\n");
1349                         }
1350                 }
1351                 else {
1352                         printf("\nError: no blend loaded. "
1353                                "order the arguments so '-o ' is after '-x '.\n");
1354                 }
1355                 return 1;
1356         }
1357         else {
1358                 printf("\nError: you must specify a path after '- '.\n");
1359                 return 0;
1360         }
1361 }
1362
1363 static const char arg_handle_render_frame_doc[] =
1364 "<frame>\n"
1365 "\tRender frame <frame> and save it.\n"
1366 "\n"
1367 "\t* +<frame> start frame relative, -<frame> end frame relative.\n"
1368 "\t* A comma separated list of frames can also be used (no spaces).\n"
1369 "\t* A range of frames can be expressed using '..' separator between the first and last frames (inclusive).\n"
1370 ;
1371 static int arg_handle_render_frame(int argc, const char **argv, void *data)
1372 {
1373         const char *arg_id = "-f / --render-frame";
1374         bContext *C = data;
1375         Scene *scene = CTX_data_scene(C);
1376         if (scene) {
1377                 Main *bmain = CTX_data_main(C);
1378
1379                 if (argc > 1) {
1380                         const char *err_msg = NULL;
1381                         Render *re;
1382                         ReportList reports;
1383
1384                         int (*frame_range_arr)[2], frames_range_len;
1385                         if ((frame_range_arr = parse_int_range_relative_clamp_n(
1386                                  argv[1], scene->r.sfra, scene->r.efra, MINAFRAME, MAXFRAME,
1387                                  &frames_range_len, &err_msg)) == NULL)
1388                         {
1389                                 printf("\nError: %s '%s %s'.\n", err_msg, arg_id, argv[1]);
1390                                 return 1;
1391                         }
1392
1393                         re = RE_NewSceneRender(scene);
1394                         BLI_threaded_malloc_begin();
1395                         BKE_reports_init(&reports, RPT_STORE);
1396                         RE_SetReports(re, &reports);
1397                         for (int i = 0; i < frames_range_len; i++) {
1398                                 /* We could pass in frame ranges,
1399                                  * but prefer having exact behavior as passing in multiple frames */
1400                                 if ((frame_range_arr[i][0] <= frame_range_arr[i][1]) == 0) {
1401                                         printf("\nWarning: negative range ignored '%s %s'.\n", arg_id, argv[1]);
1402                                 }
1403
1404                                 for (int frame = frame_range_arr[i][0]; frame <= frame_range_arr[i][1]; frame++) {
1405                                         RE_BlenderAnim(re, bmain, scene, NULL, scene->lay, frame, frame, scene->r.frame_step);
1406                                 }
1407                         }
1408                         RE_SetReports(re, NULL);
1409                         BKE_reports_clear(&reports);
1410                         BLI_threaded_malloc_end();
1411                         MEM_freeN(frame_range_arr);
1412                         return 1;
1413                 }
1414                 else {
1415                         printf("\nError: frame number must follow '%s'.\n", arg_id);
1416                         return 0;
1417                 }
1418         }
1419         else {
1420                 printf("\nError: no blend loaded. cannot use '%s'.\n", arg_id);
1421                 return 0;
1422         }
1423 }
1424
1425 static const char arg_handle_render_animation_doc[] =
1426 "\n\tRender frames from start to end (inclusive)."
1427 ;
1428 static int arg_handle_render_animation(int UNUSED(argc), const char **UNUSED(argv), void *data)
1429 {
1430         bContext *C = data;
1431         Scene *scene = CTX_data_scene(C);
1432         if (scene) {
1433                 Main *bmain = CTX_data_main(C);
1434                 Render *re = RE_NewSceneRender(scene);
1435                 ReportList reports;
1436                 BLI_threaded_malloc_begin();
1437                 BKE_reports_init(&reports, RPT_STORE);
1438                 RE_SetReports(re, &reports);
1439                 RE_BlenderAnim(re, bmain, scene, NULL, scene->lay, scene->r.sfra, scene->r.efra, scene->r.frame_step);
1440                 RE_SetReports(re, NULL);
1441                 BKE_reports_clear(&reports);
1442                 BLI_threaded_malloc_end();
1443         }
1444         else {
1445                 printf("\nError: no blend loaded. cannot use '-a'.\n");
1446         }
1447         return 0;
1448 }
1449
1450 static const char arg_handle_scene_set_doc[] =
1451 "<name>\n"
1452 "\tSet the active scene <name> for rendering."
1453 ;
1454 static int arg_handle_scene_set(int argc, const char **argv, void *data)
1455 {
1456         if (argc > 1) {
1457                 bContext *C = data;
1458                 Scene *scene = BKE_scene_set_name(CTX_data_main(C), argv[1]);
1459                 if (scene) {
1460                         CTX_data_scene_set(C, scene);
1461                 }
1462                 return 1;
1463         }
1464         else {
1465                 printf("\nError: Scene name must follow '-S / --scene'.\n");
1466                 return 0;
1467         }
1468 }
1469
1470 static const char arg_handle_frame_start_set_doc[] =
1471 "<frame>\n"
1472 "\tSet start to frame <frame>, supports +/- for relative frames too."
1473 ;
1474 static int arg_handle_frame_start_set(int argc, const char **argv, void *data)
1475 {
1476         const char *arg_id = "-s / --frame-start";
1477         bContext *C = data;
1478         Scene *scene = CTX_data_scene(C);
1479         if (scene) {
1480                 if (argc > 1) {
1481                         const char *err_msg = NULL;
1482                         if (!parse_int_relative_clamp(
1483                                 argv[1], NULL, scene->r.sfra, scene->r.sfra - 1, MINAFRAME, MAXFRAME,
1484                                 &scene->r.sfra, &err_msg))
1485                         {
1486                                 printf("\nError: %s '%s %s'.\n", err_msg, arg_id, argv[1]);
1487                         }
1488                         return 1;
1489                 }
1490                 else {
1491                         printf("\nError: frame number must follow '%s'.\n", arg_id);
1492                         return 0;
1493                 }
1494         }
1495         else {
1496                 printf("\nError: no blend loaded. cannot use '%s'.\n", arg_id);
1497                 return 0;
1498         }
1499 }
1500
1501 static const char arg_handle_frame_end_set_doc[] =
1502 "<frame>\n"
1503 "\tSet end to frame <frame>, supports +/- for relative frames too."
1504 ;
1505 static int arg_handle_frame_end_set(int argc, const char **argv, void *data)
1506 {
1507         const char *arg_id = "-e / --frame-end";
1508         bContext *C = data;
1509         Scene *scene = CTX_data_scene(C);
1510         if (scene) {
1511                 if (argc > 1) {
1512                         const char *err_msg = NULL;
1513                         if (!parse_int_relative_clamp(
1514                                 argv[1], NULL, scene->r.efra, scene->r.efra - 1, MINAFRAME, MAXFRAME,
1515                                 &scene->r.efra, &err_msg))
1516                         {
1517                                 printf("\nError: %s '%s %s'.\n", err_msg, arg_id, argv[1]);
1518                         }
1519                         return 1;
1520                 }
1521                 else {
1522                         printf("\nError: frame number must follow '%s'.\n", arg_id);
1523                         return 0;
1524                 }
1525         }
1526         else {
1527                 printf("\nError: no blend loaded. cannot use '%s'.\n", arg_id);
1528                 return 0;
1529         }
1530 }
1531
1532 static const char arg_handle_frame_skip_set_doc[] =
1533 "<frames>\n"
1534 "\tSet number of frames to step forward after each rendered frame."
1535 ;
1536 static int arg_handle_frame_skip_set(int argc, const char **argv, void *data)
1537 {
1538         const char *arg_id = "-j / --frame-jump";
1539         bContext *C = data;
1540         Scene *scene = CTX_data_scene(C);
1541         if (scene) {
1542                 if (argc > 1) {
1543                         const char *err_msg = NULL;
1544                         if (!parse_int_clamp(argv[1], NULL, 1, MAXFRAME, &scene->r.frame_step, &err_msg)) {
1545                                 printf("\nError: %s '%s %s'.\n", err_msg, arg_id, argv[1]);
1546                         }
1547                         return 1;
1548                 }
1549                 else {
1550                         printf("\nError: number of frames to step must follow '%s'.\n", arg_id);
1551                         return 0;
1552                 }
1553         }
1554         else {
1555                 printf("\nError: no blend loaded. cannot use '%s'.\n", arg_id);
1556                 return 0;
1557         }
1558 }
1559
1560 static const char arg_handle_python_file_run_doc[] =
1561 "<filename>\n"
1562 "\tRun the given Python script file."
1563 ;
1564 static int arg_handle_python_file_run(int argc, const char **argv, void *data)
1565 {
1566 #ifdef WITH_PYTHON
1567         bContext *C = data;
1568
1569         /* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */
1570         if (argc > 1) {
1571                 /* Make the path absolute because its needed for relative linked blends to be found */
1572                 char filename[FILE_MAX];
1573                 BLI_strncpy(filename, argv[1], sizeof(filename));
1574                 BLI_path_cwd(filename, sizeof(filename));
1575
1576                 bool ok;
1577                 BPY_CTX_SETUP(ok = BPY_execute_filepath(C, filename, NULL));
1578                 if (!ok && app_state.exit_code_on_error.python) {
1579                         printf("\nError: script failed, file: '%s', exiting.\n", argv[1]);
1580                         exit(app_state.exit_code_on_error.python);
1581                 }
1582                 return 1;
1583         }
1584         else {
1585                 printf("\nError: you must specify a filepath after '%s'.\n", argv[0]);
1586                 return 0;
1587         }
1588 #else
1589         UNUSED_VARS(argc, argv, data);
1590         printf("This Blender was built without Python support\n");
1591         return 0;
1592 #endif /* WITH_PYTHON */
1593 }
1594
1595 static const char arg_handle_python_text_run_doc[] =
1596 "<name>\n"
1597 "\tRun the given Python script text block."
1598 ;
1599 static int arg_handle_python_text_run(int argc, const char **argv, void *data)
1600 {
1601 #ifdef WITH_PYTHON
1602         bContext *C = data;
1603
1604         /* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */
1605         if (argc > 1) {
1606                 /* Make the path absolute because its needed for relative linked blends to be found */
1607                 struct Text *text = (struct Text *)BKE_libblock_find_name(ID_TXT, argv[1]);
1608                 bool ok;
1609
1610                 if (text) {
1611                         BPY_CTX_SETUP(ok = BPY_execute_text(C, text, NULL, false));
1612                 }
1613                 else {
1614                         printf("\nError: text block not found %s.\n", argv[1]);
1615                         ok = false;
1616                 }
1617
1618                 if (!ok && app_state.exit_code_on_error.python) {
1619                         printf("\nError: script failed, text: '%s', exiting.\n", argv[1]);
1620                         exit(app_state.exit_code_on_error.python);
1621                 }
1622
1623                 return 1;
1624         }
1625         else {
1626                 printf("\nError: you must specify a text block after '%s'.\n", argv[0]);
1627                 return 0;
1628         }
1629 #else
1630         UNUSED_VARS(argc, argv, data);
1631         printf("This Blender was built without Python support\n");
1632         return 0;
1633 #endif /* WITH_PYTHON */
1634 }
1635
1636 static const char arg_handle_python_expr_run_doc[] =
1637 "<expression>\n"
1638 "\tRun the given expression as a Python script."
1639 ;
1640 static int arg_handle_python_expr_run(int argc, const char **argv, void *data)
1641 {
1642 #ifdef WITH_PYTHON
1643         bContext *C = data;
1644
1645         /* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */
1646         if (argc > 1) {
1647                 bool ok;
1648                 BPY_CTX_SETUP(ok = BPY_execute_string_ex(C, argv[1], false));
1649                 if (!ok && app_state.exit_code_on_error.python) {
1650                         printf("\nError: script failed, expr: '%s', exiting.\n", argv[1]);
1651                         exit(app_state.exit_code_on_error.python);
1652                 }
1653                 return 1;
1654         }
1655         else {
1656                 printf("\nError: you must specify a Python expression after '%s'.\n", argv[0]);
1657                 return 0;
1658         }
1659 #else
1660         UNUSED_VARS(argc, argv, data);
1661         printf("This Blender was built without Python support\n");
1662         return 0;
1663 #endif /* WITH_PYTHON */
1664 }
1665
1666 static const char arg_handle_python_console_run_doc[] =
1667 "\n\tRun Blender with an interactive console."
1668 ;
1669 static int arg_handle_python_console_run(int UNUSED(argc), const char **argv, void *data)
1670 {
1671 #ifdef WITH_PYTHON
1672         bContext *C = data;
1673
1674         BPY_CTX_SETUP(BPY_execute_string(C, "__import__('code').interact()"));
1675
1676         return 0;
1677 #else
1678         UNUSED_VARS(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_exit_code_set_doc[] =
1685 "<code>\n"
1686 "\tSet the exit-code in [0..255] to exit if a Python exception is raised\n"
1687 "\t(only for scripts executed from the command line), zero disables."
1688 ;
1689 static int arg_handle_python_exit_code_set(int argc, const char **argv, void *UNUSED(data))
1690 {
1691         const char *arg_id = "--python-exit-code";
1692         if (argc > 1) {
1693                 const char *err_msg = NULL;
1694                 const int min = 0, max = 255;
1695                 int exit_code;
1696                 if (!parse_int_strict_range(argv[1], NULL, min, max, &exit_code, &err_msg)) {
1697                         printf("\nError: %s '%s %s', expected number in [%d..%d].\n", err_msg, arg_id, argv[1], min, max);
1698                         return 1;
1699                 }
1700
1701                 app_state.exit_code_on_error.python = (unsigned char)exit_code;
1702                 return 1;
1703         }
1704         else {
1705                 printf("\nError: you must specify an exit code number '%s'.\n", arg_id);
1706                 return 0;
1707         }
1708 }
1709
1710 static const char arg_handle_addons_set_doc[] =
1711 "<addon(s)>\n"
1712 "\tComma separated list of add-ons (no spaces)."
1713 ;
1714 static int arg_handle_addons_set(int argc, const char **argv, void *data)
1715 {
1716         /* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */
1717         if (argc > 1) {
1718 #ifdef WITH_PYTHON
1719                 const char script_str[] =
1720                         "from addon_utils import check, enable\n"
1721                         "for m in '%s'.split(','):\n"
1722                         "    if check(m)[1] is False:\n"
1723                         "        enable(m, persistent=True)";
1724                 const int slen = strlen(argv[1]) + (sizeof(script_str) - 2);
1725                 char *str = malloc(slen);
1726                 bContext *C = data;
1727                 BLI_snprintf(str, slen, script_str, argv[1]);
1728
1729                 BLI_assert(strlen(str) + 1 == slen);
1730                 BPY_CTX_SETUP(BPY_execute_string_ex(C, str, false));
1731                 free(str);
1732 #else
1733                 UNUSED_VARS(argv, data);
1734 #endif /* WITH_PYTHON */
1735                 return 1;
1736         }
1737         else {
1738                 printf("\nError: you must specify a comma separated list after '--addons'.\n");
1739                 return 0;
1740         }
1741 }
1742
1743 static int arg_handle_load_file(int UNUSED(argc), const char **argv, void *data)
1744 {
1745         bContext *C = data;
1746         ReportList reports;
1747         bool success;
1748
1749         /* Make the path absolute because its needed for relative linked blends to be found */
1750         char filename[FILE_MAX];
1751
1752         /* note, we could skip these, but so far we always tried to load these files */
1753         if (argv[0][0] == '-') {
1754                 fprintf(stderr, "unknown argument, loading as file: %s\n", argv[0]);
1755         }
1756
1757         BLI_strncpy(filename, argv[0], sizeof(filename));
1758         BLI_path_cwd(filename, sizeof(filename));
1759
1760         /* load the file */
1761         BKE_reports_init(&reports, RPT_PRINT);
1762         WM_file_autoexec_init(filename);
1763         success = WM_file_read(C, filename, &reports);
1764         BKE_reports_clear(&reports);
1765
1766         if (success) {
1767                 if (G.background) {
1768                         /* ensuer we use 'C->data.scene' for background render */
1769                         CTX_wm_window_set(C, NULL);
1770                 }
1771         }
1772         else {
1773                 /* failed to load file, stop processing arguments if running in background mode */
1774                 if (G.background) {
1775                         /* Set is_break if running in the background mode so
1776                          * blender will return non-zero exit code which then
1777                          * could be used in automated script to control how
1778                          * good or bad things are.
1779                          */
1780                         G.is_break = true;
1781                         return -1;
1782                 }
1783
1784                 if (BLO_has_bfile_extension(filename)) {
1785                         /* Just pretend a file was loaded, so the user can press Save and it'll save at the filename from the CLI. */
1786                         BLI_strncpy(G.main->name, filename, FILE_MAX);
1787                         G.relbase_valid = true;
1788                         G.save_over = true;
1789                         printf("... opened default scene instead; saving will write to: %s\n", filename);
1790                 }
1791                 else {
1792                         printf("Error: argument has no '.blend' file extension, not using as new file, exiting! %s\n", filename);
1793                         G.is_break = true;
1794                         WM_exit(C);
1795                 }
1796         }
1797
1798         G.file_loaded = 1;
1799
1800         return 0;
1801 }
1802
1803
1804 void main_args_setup(bContext *C, bArgs *ba)
1805 {
1806
1807 #define CB(a) a##_doc, a
1808 #define CB_EX(a, b) a##_doc_##b, a
1809
1810         //BLI_argsAdd(ba, pass, short_arg, long_arg, doc, cb, C);
1811
1812         /* end argument processing after -- */
1813         BLI_argsAdd(ba, -1, "--", NULL, CB(arg_handle_arguments_end), NULL);
1814
1815         /* first pass: background mode, disable python and commands that exit after usage */
1816         BLI_argsAdd(ba, 1, "-h", "--help", CB(arg_handle_print_help), ba);
1817         /* Windows only */
1818         BLI_argsAdd(ba, 1, "/?", NULL, CB_EX(arg_handle_print_help, win32), ba);
1819
1820         BLI_argsAdd(ba, 1, "-v", "--version", CB(arg_handle_print_version), NULL);
1821
1822         BLI_argsAdd(ba, 1, "-y", "--enable-autoexec", CB_EX(arg_handle_python_set, enable), (void *)true);
1823         BLI_argsAdd(ba, 1, "-Y", "--disable-autoexec", CB_EX(arg_handle_python_set, disable), (void *)false);
1824
1825         BLI_argsAdd(ba, 1, NULL, "--disable-crash-handler", CB(arg_handle_crash_handler_disable), NULL);
1826         BLI_argsAdd(ba, 1, NULL, "--disable-abort-handler", CB(arg_handle_abort_handler_disable), NULL);
1827
1828         BLI_argsAdd(ba, 1, "-b", "--background", CB(arg_handle_background_mode_set), NULL);
1829
1830         BLI_argsAdd(ba, 1, "-a", NULL, CB(arg_handle_playback_mode), NULL);
1831
1832         BLI_argsAdd(ba, 1, NULL, "--log", CB(arg_handle_log_set), ba);
1833         BLI_argsAdd(ba, 1, NULL, "--log-level", CB(arg_handle_log_level_set), ba);
1834         BLI_argsAdd(ba, 1, NULL, "--log-show-basename", CB(arg_handle_log_show_basename_set), ba);
1835         BLI_argsAdd(ba, 1, NULL, "--log-show-backtrace", CB(arg_handle_log_show_backtrace_set), ba);
1836         BLI_argsAdd(ba, 1, NULL, "--log-file", CB(arg_handle_log_file_set), ba);
1837
1838         BLI_argsAdd(ba, 1, "-d", "--debug", CB(arg_handle_debug_mode_set), ba);
1839
1840 #ifdef WITH_FFMPEG
1841         BLI_argsAdd(ba, 1, NULL, "--debug-ffmpeg",
1842                     CB_EX(arg_handle_debug_mode_generic_set, ffmpeg), (void *)G_DEBUG_FFMPEG);
1843 #endif
1844
1845 #ifdef WITH_FREESTYLE
1846         BLI_argsAdd(ba, 1, NULL, "--debug-freestyle",
1847                     CB_EX(arg_handle_debug_mode_generic_set, freestyle), (void *)G_DEBUG_FREESTYLE);
1848 #endif
1849
1850         BLI_argsAdd(ba, 1, NULL, "--debug-python",
1851                     CB_EX(arg_handle_debug_mode_generic_set, python), (void *)G_DEBUG_PYTHON);
1852         BLI_argsAdd(ba, 1, NULL, "--debug-events",
1853                     CB_EX(arg_handle_debug_mode_generic_set, events), (void *)G_DEBUG_EVENTS);
1854         BLI_argsAdd(ba, 1, NULL, "--debug-handlers",
1855                     CB_EX(arg_handle_debug_mode_generic_set, handlers), (void *)G_DEBUG_HANDLERS);
1856         BLI_argsAdd(ba, 1, NULL, "--debug-wm",
1857                     CB_EX(arg_handle_debug_mode_generic_set, wm), (void *)G_DEBUG_WM);
1858         BLI_argsAdd(ba, 1, NULL, "--debug-all", CB(arg_handle_debug_mode_all), NULL);
1859
1860         BLI_argsAdd(ba, 1, NULL, "--debug-io", CB(arg_handle_debug_mode_io), NULL);
1861
1862         BLI_argsAdd(ba, 1, NULL, "--debug-fpe",
1863                     CB(arg_handle_debug_fpe_set), NULL);
1864
1865 #ifdef WITH_LIBMV
1866         BLI_argsAdd(ba, 1, NULL, "--debug-libmv", CB(arg_handle_debug_mode_libmv), NULL);
1867 #endif
1868 #ifdef WITH_CYCLES_LOGGING
1869         BLI_argsAdd(ba, 1, NULL, "--debug-cycles", CB(arg_handle_debug_mode_cycles), NULL);
1870 #endif
1871         BLI_argsAdd(ba, 1, NULL, "--debug-memory", CB(arg_handle_debug_mode_memory_set), NULL);
1872
1873         BLI_argsAdd(ba, 1, NULL, "--debug-value",
1874                     CB(arg_handle_debug_value_set), NULL);
1875         BLI_argsAdd(ba, 1, NULL, "--debug-jobs",
1876                     CB_EX(arg_handle_debug_mode_generic_set, jobs), (void *)G_DEBUG_JOBS);
1877         BLI_argsAdd(ba, 1, NULL, "--debug-gpu",
1878                     CB_EX(arg_handle_debug_mode_generic_set, gpu), (void *)G_DEBUG_GPU);
1879         BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph",
1880                     CB_EX(arg_handle_debug_mode_generic_set, depsgraph), (void *)G_DEBUG_DEPSGRAPH);
1881         BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph-build",
1882                     CB_EX(arg_handle_debug_mode_generic_set, depsgraph_build), (void *)G_DEBUG_DEPSGRAPH_BUILD);
1883         BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph-eval",
1884                     CB_EX(arg_handle_debug_mode_generic_set, depsgraph_eval), (void *)G_DEBUG_DEPSGRAPH_EVAL);
1885         BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph-tag",
1886                     CB_EX(arg_handle_debug_mode_generic_set, depsgraph_tag), (void *)G_DEBUG_DEPSGRAPH_TAG);
1887         BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph-time",
1888                     CB_EX(arg_handle_debug_mode_generic_set, depsgraph_time), (void *)G_DEBUG_DEPSGRAPH_TIME);
1889         BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph-no-threads",
1890                     CB_EX(arg_handle_debug_mode_generic_set, depsgraph_no_threads), (void *)G_DEBUG_DEPSGRAPH_NO_THREADS);
1891         BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph-pretty",
1892                     CB_EX(arg_handle_debug_mode_generic_set, depsgraph_pretty), (void *)G_DEBUG_DEPSGRAPH_PRETTY);
1893         BLI_argsAdd(ba, 1, NULL, "--debug-gpumem",
1894                     CB_EX(arg_handle_debug_mode_generic_set, gpumem), (void *)G_DEBUG_GPU_MEM);
1895         BLI_argsAdd(ba, 1, NULL, "--debug-gpu-shaders",
1896                     CB_EX(arg_handle_debug_mode_generic_set, gpumem), (void *)G_DEBUG_GPU_SHADERS);
1897
1898         BLI_argsAdd(ba, 1, NULL, "--enable-copy-on-write", CB(arg_handle_use_copy_on_write), NULL);
1899
1900         BLI_argsAdd(ba, 1, NULL, "--verbose", CB(arg_handle_verbosity_set), NULL);
1901
1902         BLI_argsAdd(ba, 1, NULL, "--factory-startup", CB(arg_handle_factory_startup_set), NULL);
1903
1904         /* TODO, add user env vars? */
1905         BLI_argsAdd(ba, 1, NULL, "--env-system-datafiles", CB_EX(arg_handle_env_system_set, datafiles), NULL);
1906         BLI_argsAdd(ba, 1, NULL, "--env-system-scripts", CB_EX(arg_handle_env_system_set, scripts), NULL);
1907         BLI_argsAdd(ba, 1, NULL, "--env-system-python", CB_EX(arg_handle_env_system_set, python), NULL);
1908
1909         /* second pass: custom window stuff */
1910         BLI_argsAdd(ba, 2, "-p", "--window-geometry", CB(arg_handle_window_geometry), NULL);
1911         BLI_argsAdd(ba, 2, "-w", "--window-border", CB(arg_handle_with_borders), NULL);
1912         BLI_argsAdd(ba, 2, "-W", "--window-fullscreen", CB(arg_handle_without_borders), NULL);
1913         BLI_argsAdd(ba, 2, "-con", "--start-console", CB(arg_handle_start_with_console), NULL);
1914         BLI_argsAdd(ba, 2, "-R", NULL, CB(arg_handle_register_extension), NULL);
1915         BLI_argsAdd(ba, 2, "-r", NULL, CB_EX(arg_handle_register_extension, silent), ba);
1916         BLI_argsAdd(ba, 2, NULL, "--no-native-pixels", CB(arg_handle_native_pixels_set), ba);
1917
1918         /* third pass: disabling things and forcing settings */
1919         BLI_argsAddCase(ba, 3, "-noaudio", 1, NULL, 0, CB(arg_handle_audio_disable), NULL);
1920         BLI_argsAddCase(ba, 3, "-setaudio", 1, NULL, 0, CB(arg_handle_audio_set), NULL);
1921
1922         /* fourth pass: processing arguments */
1923         BLI_argsAdd(ba, 4, "-f", "--render-frame", CB(arg_handle_render_frame), C);
1924         BLI_argsAdd(ba, 4, "-a", "--render-anim", CB(arg_handle_render_animation), C);
1925         BLI_argsAdd(ba, 4, "-S", "--scene", CB(arg_handle_scene_set), C);
1926         BLI_argsAdd(ba, 4, "-s", "--frame-start", CB(arg_handle_frame_start_set), C);
1927         BLI_argsAdd(ba, 4, "-e", "--frame-end", CB(arg_handle_frame_end_set), C);
1928         BLI_argsAdd(ba, 4, "-j", "--frame-jump", CB(arg_handle_frame_skip_set), C);
1929         BLI_argsAdd(ba, 4, "-P", "--python", CB(arg_handle_python_file_run), C);
1930         BLI_argsAdd(ba, 4, NULL, "--python-text", CB(arg_handle_python_text_run), C);
1931         BLI_argsAdd(ba, 4, NULL, "--python-expr", CB(arg_handle_python_expr_run), C);
1932         BLI_argsAdd(ba, 4, NULL, "--python-console", CB(arg_handle_python_console_run), C);
1933         BLI_argsAdd(ba, 4, NULL, "--python-exit-code", CB(arg_handle_python_exit_code_set), NULL);
1934         BLI_argsAdd(ba, 4, NULL, "--addons", CB(arg_handle_addons_set), C);
1935
1936         BLI_argsAdd(ba, 4, "-o", "--render-output", CB(arg_handle_output_set), C);
1937         BLI_argsAdd(ba, 4, "-E", "--engine", CB(arg_handle_engine_set), C);
1938
1939         BLI_argsAdd(ba, 4, "-F", "--render-format", CB(arg_handle_image_type_set), C);
1940         BLI_argsAdd(ba, 1, "-t", "--threads", CB(arg_handle_threads_set), NULL);
1941         BLI_argsAdd(ba, 4, "-x", "--use-extension", CB(arg_handle_extension_set), C);
1942
1943 #undef CB
1944 #undef CB_EX
1945
1946 }
1947
1948 /**
1949  * Needs to be added separately.
1950  */
1951 void main_args_setup_post(bContext *C, bArgs *ba)
1952 {
1953         BLI_argsParse(ba, 4, arg_handle_load_file, C);
1954 }
1955
1956 /** \} */
1957
1958 #endif /* WITH_PYTHON_MODULE */