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