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