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