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