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