Cleanup: minor adjustments to --help text formatting
[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     "\tInstead of showing Blender's user interface, this runs Blender as an animation player,\n"
1172     "\tto view movies and image sequences rendered in Blender (ignored if '-b' is set).\n"
1173     "\n"
1174     "\tPlayback Arguments:\n"
1175     "\n"
1176     "\t-p <sx> <sy>\n"
1177     "\t\tOpen with lower left corner at <sx>, <sy>.\n"
1178     "\t-m\n"
1179     "\t\tRead from disk (Do not buffer).\n"
1180     "\t-f <fps> <fps-base>\n"
1181     "\t\tSpecify FPS to start with.\n"
1182     "\t-j <frame>\n"
1183     "\t\tSet frame step to <frame>.\n"
1184     "\t-s <frame>\n"
1185     "\t\tPlay from <frame>.\n"
1186     "\t-e <frame>\n"
1187     "\t\tPlay until <frame>.";
1188 static int arg_handle_playback_mode(int argc, const char **argv, void *UNUSED(data))
1189 {
1190   /* not if -b was given first */
1191   if (G.background == 0) {
1192 #  ifdef WITH_FFMPEG
1193     /* Setup FFmpeg with current debug flags. */
1194     IMB_ffmpeg_init();
1195 #  endif
1196
1197     WM_main_playanim(argc, argv); /* not the same argc and argv as before */
1198     exit(0);                      /* 2.4x didn't do this */
1199   }
1200
1201   return -2;
1202 }
1203
1204 static const char arg_handle_window_geometry_doc[] =
1205     "<sx> <sy> <w> <h>\n"
1206     "\tOpen with lower left corner at <sx>, <sy> and width and height as <w>, <h>.";
1207 static int arg_handle_window_geometry(int argc, const char **argv, void *UNUSED(data))
1208 {
1209   const char *arg_id = "-p / --window-geometry";
1210   int params[4], i;
1211
1212   if (argc < 5) {
1213     fprintf(stderr, "Error: requires four arguments '%s'\n", arg_id);
1214     exit(1);
1215   }
1216
1217   for (i = 0; i < 4; i++) {
1218     const char *err_msg = NULL;
1219     if (!parse_int(argv[i + 1], NULL, &params[i], &err_msg)) {
1220       printf("\nError: %s '%s %s'.\n", err_msg, arg_id, argv[1]);
1221       exit(1);
1222     }
1223   }
1224
1225   WM_init_state_size_set(UNPACK4(params));
1226
1227   return 4;
1228 }
1229
1230 static const char arg_handle_native_pixels_set_doc[] =
1231     "\n\t"
1232     "Do not use native pixel size, for high resolution displays (MacBook 'Retina').";
1233 static int arg_handle_native_pixels_set(int UNUSED(argc),
1234                                         const char **UNUSED(argv),
1235                                         void *UNUSED(data))
1236 {
1237   WM_init_native_pixels(false);
1238   return 0;
1239 }
1240
1241 static const char arg_handle_with_borders_doc[] =
1242     "\n\t"
1243     "Force opening with borders.";
1244 static int arg_handle_with_borders(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
1245 {
1246   WM_init_state_normal_set();
1247   return 0;
1248 }
1249
1250 static const char arg_handle_without_borders_doc[] =
1251     "\n\t"
1252     "Force opening in fullscreen mode.";
1253 static int arg_handle_without_borders(int UNUSED(argc),
1254                                       const char **UNUSED(argv),
1255                                       void *UNUSED(data))
1256 {
1257   WM_init_state_fullscreen_set();
1258   return 0;
1259 }
1260
1261 static const char arg_handle_window_maximized_doc[] =
1262     "\n\t"
1263     "Force opening maximized.";
1264 static int arg_handle_window_maximized(int UNUSED(argc),
1265                                        const char **UNUSED(argv),
1266                                        void *UNUSED(data))
1267 {
1268   WM_init_state_maximized_set();
1269   return 0;
1270 }
1271
1272 static const char arg_handle_no_window_focus_doc[] =
1273     "\n\t"
1274     "Open behind other windows and without taking focus.";
1275 static int arg_handle_no_window_focus(int UNUSED(argc),
1276                                       const char **UNUSED(argv),
1277                                       void *UNUSED(data))
1278 {
1279   WM_init_window_focus_set(false);
1280   return 0;
1281 }
1282
1283 static const char arg_handle_start_with_console_doc[] =
1284     "\n\t"
1285     "Start with the console window open (ignored if '-b' is set), (Windows only).";
1286 static int arg_handle_start_with_console(int UNUSED(argc),
1287                                          const char **UNUSED(argv),
1288                                          void *UNUSED(data))
1289 {
1290   WM_init_state_start_with_console_set(true);
1291   return 0;
1292 }
1293
1294 static const char arg_handle_register_extension_doc[] =
1295     "\n\t"
1296     "Register blend-file extension, then exit (Windows only).";
1297 static const char arg_handle_register_extension_doc_silent[] =
1298     "\n\t"
1299     "Silently register blend-file extension, then exit (Windows only).";
1300 static int arg_handle_register_extension(int UNUSED(argc), const char **UNUSED(argv), void *data)
1301 {
1302 #  ifdef WIN32
1303   if (data) {
1304     G.background = 1;
1305   }
1306   RegisterBlendExtension();
1307 #  else
1308   (void)data; /* unused */
1309 #  endif
1310   return 0;
1311 }
1312
1313 static const char arg_handle_audio_disable_doc[] =
1314     "\n\t"
1315     "Force sound system to None.";
1316 static int arg_handle_audio_disable(int UNUSED(argc),
1317                                     const char **UNUSED(argv),
1318                                     void *UNUSED(data))
1319 {
1320   BKE_sound_force_device("Null");
1321   return 0;
1322 }
1323
1324 static const char arg_handle_audio_set_doc[] =
1325     "\n\t"
1326     "Force sound system to a specific device."
1327     "\n\t"
1328     "'NULL' 'SDL' 'OPENAL' 'JACK'.";
1329 static int arg_handle_audio_set(int argc, const char **argv, void *UNUSED(data))
1330 {
1331   if (argc < 1) {
1332     fprintf(stderr, "-setaudio require one argument\n");
1333     exit(1);
1334   }
1335
1336   BKE_sound_force_device(argv[1]);
1337   return 1;
1338 }
1339
1340 static const char arg_handle_output_set_doc[] =
1341     "<path>\n"
1342     "\tSet the render path and file name.\n"
1343     "\tUse '//' at the start of the path to render relative to the blend-file.\n"
1344     "\n"
1345     "\tThe '#' characters are replaced by the frame number, and used to define zero padding.\n"
1346     "\n"
1347     "\t* 'animation_##_test.png' becomes 'animation_01_test.png'\n"
1348     "\t* 'test-######.png' becomes 'test-000001.png'\n"
1349     "\n"
1350     "\tWhen the filename does not contain '#', The suffix '####' is added to the filename.\n"
1351     "\n"
1352     "\tThe frame number will be added at the end of the filename, eg:\n"
1353     "\t# blender -b animation.blend -o //render_ -F PNG -x 1 -a\n"
1354     "\t'//render_' becomes '//render_####', writing frames as '//render_0001.png'";
1355 static int arg_handle_output_set(int argc, const char **argv, void *data)
1356 {
1357   bContext *C = data;
1358   if (argc > 1) {
1359     Scene *scene = CTX_data_scene(C);
1360     if (scene) {
1361       BLI_strncpy(scene->r.pic, argv[1], sizeof(scene->r.pic));
1362     }
1363     else {
1364       printf("\nError: no blend loaded. cannot use '-o / --render-output'.\n");
1365     }
1366     return 1;
1367   }
1368   else {
1369     printf("\nError: you must specify a path after '-o  / --render-output'.\n");
1370     return 0;
1371   }
1372 }
1373
1374 static const char arg_handle_engine_set_doc[] =
1375     "<engine>\n"
1376     "\tSpecify the render engine.\n"
1377     "\tUse '-E' help to list available engines.";
1378 static int arg_handle_engine_set(int argc, const char **argv, void *data)
1379 {
1380   bContext *C = data;
1381   if (argc >= 2) {
1382     if (STREQ(argv[1], "help")) {
1383       RenderEngineType *type = NULL;
1384       printf("Blender Engine Listing:\n");
1385       for (type = R_engines.first; type; type = type->next) {
1386         printf("\t%s\n", type->idname);
1387       }
1388       exit(0);
1389     }
1390     else {
1391       Scene *scene = CTX_data_scene(C);
1392       if (scene) {
1393         if (BLI_findstring(&R_engines, argv[1], offsetof(RenderEngineType, idname))) {
1394           BLI_strncpy_utf8(scene->r.engine, argv[1], sizeof(scene->r.engine));
1395         }
1396         else {
1397           printf("\nError: engine not found '%s'\n", argv[1]);
1398           exit(1);
1399         }
1400       }
1401       else {
1402         printf(
1403             "\nError: no blend loaded. "
1404             "order the arguments so '-E / --engine' is after a blend is loaded.\n");
1405       }
1406     }
1407
1408     return 1;
1409   }
1410   else {
1411     printf("\nEngine not specified, give 'help' for a list of available engines.\n");
1412     return 0;
1413   }
1414 }
1415
1416 static const char arg_handle_image_type_set_doc[] =
1417     "<format>\n"
1418     "\tSet the render format.\n"
1419     "\tValid options are:\n"
1420     "\t'TGA' 'RAWTGA' 'JPEG' 'IRIS' 'IRIZ' 'AVIRAW' 'AVIJPEG' 'PNG' 'BMP'\n"
1421     "\n"
1422     "\tFormats that can be compiled into Blender, not available on all systems:\n"
1423     "\t'HDR' 'TIFF' 'OPEN_EXR' 'OPEN_EXR_MULTILAYER' 'MPEG' 'CINEON' 'DPX' 'DDS' 'JP2'";
1424 static int arg_handle_image_type_set(int argc, const char **argv, void *data)
1425 {
1426   bContext *C = data;
1427   if (argc > 1) {
1428     const char *imtype = argv[1];
1429     Scene *scene = CTX_data_scene(C);
1430     if (scene) {
1431       const char imtype_new = BKE_imtype_from_arg(imtype);
1432
1433       if (imtype_new == R_IMF_IMTYPE_INVALID) {
1434         printf(
1435             "\nError: Format from '-F / --render-format' not known or not compiled in this "
1436             "release.\n");
1437       }
1438       else {
1439         scene->r.im_format.imtype = imtype_new;
1440       }
1441     }
1442     else {
1443       printf(
1444           "\nError: no blend loaded. "
1445           "order the arguments so '-F  / --render-format' is after the blend is loaded.\n");
1446     }
1447     return 1;
1448   }
1449   else {
1450     printf("\nError: you must specify a format after '-F  / --render-foramt'.\n");
1451     return 0;
1452   }
1453 }
1454
1455 static const char arg_handle_threads_set_doc[] =
1456     "<threads>\n"
1457     "\tUse amount of <threads> for rendering and other operations\n"
1458     "\t[1-" STRINGIFY(BLENDER_MAX_THREADS) "], 0 for systems processor count.";
1459 static int arg_handle_threads_set(int argc, const char **argv, void *UNUSED(data))
1460 {
1461   const char *arg_id = "-t / --threads";
1462   const int min = 0, max = BLENDER_MAX_THREADS;
1463   if (argc > 1) {
1464     const char *err_msg = NULL;
1465     int threads;
1466     if (!parse_int_strict_range(argv[1], NULL, min, max, &threads, &err_msg)) {
1467       printf("\nError: %s '%s %s', expected number in [%d..%d].\n",
1468              err_msg,
1469              arg_id,
1470              argv[1],
1471              min,
1472              max);
1473       return 1;
1474     }
1475
1476     BLI_system_num_threads_override_set(threads);
1477     return 1;
1478   }
1479   else {
1480     printf("\nError: you must specify a number of threads in [%d..%d] '%s'.\n", min, max, arg_id);
1481     return 0;
1482   }
1483 }
1484
1485 static const char arg_handle_verbosity_set_doc[] =
1486     "<verbose>\n"
1487     "\tSet logging verbosity level.";
1488 static int arg_handle_verbosity_set(int argc, const char **argv, void *UNUSED(data))
1489 {
1490   const char *arg_id = "--verbose";
1491   if (argc > 1) {
1492     const char *err_msg = NULL;
1493     int level;
1494     if (!parse_int(argv[1], NULL, &level, &err_msg)) {
1495       printf("\nError: %s '%s %s'.\n", err_msg, arg_id, argv[1]);
1496     }
1497
1498 #  ifdef WITH_LIBMV
1499     libmv_setLoggingVerbosity(level);
1500 #  elif defined(WITH_CYCLES_LOGGING)
1501     CCL_logging_verbosity_set(level);
1502 #  else
1503     (void)level;
1504 #  endif
1505
1506     return 1;
1507   }
1508   else {
1509     printf("\nError: you must specify a verbosity level.\n");
1510     return 0;
1511   }
1512 }
1513
1514 static const char arg_handle_extension_set_doc[] =
1515     "<bool>\n"
1516     "\tSet option to add the file extension to the end of the file.";
1517 static int arg_handle_extension_set(int argc, const char **argv, void *data)
1518 {
1519   bContext *C = data;
1520   if (argc > 1) {
1521     Scene *scene = CTX_data_scene(C);
1522     if (scene) {
1523       if (argv[1][0] == '0') {
1524         scene->r.scemode &= ~R_EXTENSION;
1525       }
1526       else if (argv[1][0] == '1') {
1527         scene->r.scemode |= R_EXTENSION;
1528       }
1529       else {
1530         printf("\nError: Use '-x 1 / -x 0' To set the extension option or '--use-extension'\n");
1531       }
1532     }
1533     else {
1534       printf(
1535           "\nError: no blend loaded. "
1536           "order the arguments so '-o ' is after '-x '.\n");
1537     }
1538     return 1;
1539   }
1540   else {
1541     printf("\nError: you must specify a path after '- '.\n");
1542     return 0;
1543   }
1544 }
1545
1546 static const char arg_handle_render_frame_doc[] =
1547     "<frame>\n"
1548     "\tRender frame <frame> and save it.\n"
1549     "\n"
1550     "\t* +<frame> start frame relative, -<frame> end frame relative.\n"
1551     "\t* A comma separated list of frames can also be used (no spaces).\n"
1552     "\t* A range of frames can be expressed using '..' separator between the first and last "
1553     "frames (inclusive).\n";
1554 static int arg_handle_render_frame(int argc, const char **argv, void *data)
1555 {
1556   const char *arg_id = "-f / --render-frame";
1557   bContext *C = data;
1558   Scene *scene = CTX_data_scene(C);
1559   if (scene) {
1560     Main *bmain = CTX_data_main(C);
1561
1562     if (argc > 1) {
1563       const char *err_msg = NULL;
1564       Render *re;
1565       ReportList reports;
1566
1567       int(*frame_range_arr)[2], frames_range_len;
1568       if ((frame_range_arr = parse_int_range_relative_clamp_n(argv[1],
1569                                                               scene->r.sfra,
1570                                                               scene->r.efra,
1571                                                               MINAFRAME,
1572                                                               MAXFRAME,
1573                                                               &frames_range_len,
1574                                                               &err_msg)) == NULL) {
1575         printf("\nError: %s '%s %s'.\n", err_msg, arg_id, argv[1]);
1576         return 1;
1577       }
1578
1579       re = RE_NewSceneRender(scene);
1580       BLI_threaded_malloc_begin();
1581       BKE_reports_init(&reports, RPT_STORE);
1582       RE_SetReports(re, &reports);
1583       for (int i = 0; i < frames_range_len; i++) {
1584         /* We could pass in frame ranges,
1585          * but prefer having exact behavior as passing in multiple frames */
1586         if ((frame_range_arr[i][0] <= frame_range_arr[i][1]) == 0) {
1587           printf("\nWarning: negative range ignored '%s %s'.\n", arg_id, argv[1]);
1588         }
1589
1590         for (int frame = frame_range_arr[i][0]; frame <= frame_range_arr[i][1]; frame++) {
1591           RE_RenderAnim(re, bmain, scene, NULL, NULL, frame, frame, scene->r.frame_step);
1592         }
1593       }
1594       RE_SetReports(re, NULL);
1595       BKE_reports_clear(&reports);
1596       BLI_threaded_malloc_end();
1597       MEM_freeN(frame_range_arr);
1598       return 1;
1599     }
1600     else {
1601       printf("\nError: frame number must follow '%s'.\n", arg_id);
1602       return 0;
1603     }
1604   }
1605   else {
1606     printf("\nError: no blend loaded. cannot use '%s'.\n", arg_id);
1607     return 0;
1608   }
1609 }
1610
1611 static const char arg_handle_render_animation_doc[] =
1612     "\n\t"
1613     "Render frames from start to end (inclusive).";
1614 static int arg_handle_render_animation(int UNUSED(argc), const char **UNUSED(argv), void *data)
1615 {
1616   bContext *C = data;
1617   Scene *scene = CTX_data_scene(C);
1618   if (scene) {
1619     Main *bmain = CTX_data_main(C);
1620     Render *re = RE_NewSceneRender(scene);
1621     ReportList reports;
1622     BLI_threaded_malloc_begin();
1623     BKE_reports_init(&reports, RPT_STORE);
1624     RE_SetReports(re, &reports);
1625     RE_RenderAnim(re, bmain, scene, NULL, NULL, scene->r.sfra, scene->r.efra, scene->r.frame_step);
1626     RE_SetReports(re, NULL);
1627     BKE_reports_clear(&reports);
1628     BLI_threaded_malloc_end();
1629   }
1630   else {
1631     printf("\nError: no blend loaded. cannot use '-a'.\n");
1632   }
1633   return 0;
1634 }
1635
1636 static const char arg_handle_scene_set_doc[] =
1637     "<name>\n"
1638     "\tSet the active scene <name> for rendering.";
1639 static int arg_handle_scene_set(int argc, const char **argv, void *data)
1640 {
1641   if (argc > 1) {
1642     bContext *C = data;
1643     Scene *scene = BKE_scene_set_name(CTX_data_main(C), argv[1]);
1644     if (scene) {
1645       CTX_data_scene_set(C, scene);
1646
1647       /* Set the scene of the first window, see: T55991,
1648        * otherwise scrips that run later won't get this scene back from the context. */
1649       wmWindow *win = CTX_wm_window(C);
1650       if (win == NULL) {
1651         win = CTX_wm_manager(C)->windows.first;
1652       }
1653       if (win != NULL) {
1654         WM_window_set_active_scene(CTX_data_main(C), C, win, scene);
1655       }
1656     }
1657     return 1;
1658   }
1659   else {
1660     printf("\nError: Scene name must follow '-S / --scene'.\n");
1661     return 0;
1662   }
1663 }
1664
1665 static const char arg_handle_frame_start_set_doc[] =
1666     "<frame>\n"
1667     "\tSet start to frame <frame>, supports +/- for relative frames too.";
1668 static int arg_handle_frame_start_set(int argc, const char **argv, void *data)
1669 {
1670   const char *arg_id = "-s / --frame-start";
1671   bContext *C = data;
1672   Scene *scene = CTX_data_scene(C);
1673   if (scene) {
1674     if (argc > 1) {
1675       const char *err_msg = NULL;
1676       if (!parse_int_relative_clamp(argv[1],
1677                                     NULL,
1678                                     scene->r.sfra,
1679                                     scene->r.sfra - 1,
1680                                     MINAFRAME,
1681                                     MAXFRAME,
1682                                     &scene->r.sfra,
1683                                     &err_msg)) {
1684         printf("\nError: %s '%s %s'.\n", err_msg, arg_id, argv[1]);
1685       }
1686       return 1;
1687     }
1688     else {
1689       printf("\nError: frame number must follow '%s'.\n", arg_id);
1690       return 0;
1691     }
1692   }
1693   else {
1694     printf("\nError: no blend loaded. cannot use '%s'.\n", arg_id);
1695     return 0;
1696   }
1697 }
1698
1699 static const char arg_handle_frame_end_set_doc[] =
1700     "<frame>\n"
1701     "\tSet end to frame <frame>, supports +/- for relative frames too.";
1702 static int arg_handle_frame_end_set(int argc, const char **argv, void *data)
1703 {
1704   const char *arg_id = "-e / --frame-end";
1705   bContext *C = data;
1706   Scene *scene = CTX_data_scene(C);
1707   if (scene) {
1708     if (argc > 1) {
1709       const char *err_msg = NULL;
1710       if (!parse_int_relative_clamp(argv[1],
1711                                     NULL,
1712                                     scene->r.efra,
1713                                     scene->r.efra - 1,
1714                                     MINAFRAME,
1715                                     MAXFRAME,
1716                                     &scene->r.efra,
1717                                     &err_msg)) {
1718         printf("\nError: %s '%s %s'.\n", err_msg, arg_id, argv[1]);
1719       }
1720       return 1;
1721     }
1722     else {
1723       printf("\nError: frame number must follow '%s'.\n", arg_id);
1724       return 0;
1725     }
1726   }
1727   else {
1728     printf("\nError: no blend loaded. cannot use '%s'.\n", arg_id);
1729     return 0;
1730   }
1731 }
1732
1733 static const char arg_handle_frame_skip_set_doc[] =
1734     "<frames>\n"
1735     "\tSet number of frames to step forward after each rendered frame.";
1736 static int arg_handle_frame_skip_set(int argc, const char **argv, void *data)
1737 {
1738   const char *arg_id = "-j / --frame-jump";
1739   bContext *C = data;
1740   Scene *scene = CTX_data_scene(C);
1741   if (scene) {
1742     if (argc > 1) {
1743       const char *err_msg = NULL;
1744       if (!parse_int_clamp(argv[1], NULL, 1, MAXFRAME, &scene->r.frame_step, &err_msg)) {
1745         printf("\nError: %s '%s %s'.\n", err_msg, arg_id, argv[1]);
1746       }
1747       return 1;
1748     }
1749     else {
1750       printf("\nError: number of frames to step must follow '%s'.\n", arg_id);
1751       return 0;
1752     }
1753   }
1754   else {
1755     printf("\nError: no blend loaded. cannot use '%s'.\n", arg_id);
1756     return 0;
1757   }
1758 }
1759
1760 static const char arg_handle_python_file_run_doc[] =
1761     "<filename>\n"
1762     "\tRun the given Python script file.";
1763 static int arg_handle_python_file_run(int argc, const char **argv, void *data)
1764 {
1765 #  ifdef WITH_PYTHON
1766   bContext *C = data;
1767
1768   /* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */
1769   if (argc > 1) {
1770     /* Make the path absolute because its needed for relative linked blends to be found */
1771     char filename[FILE_MAX];
1772     BLI_strncpy(filename, argv[1], sizeof(filename));
1773     BLI_path_cwd(filename, sizeof(filename));
1774
1775     bool ok;
1776     BPY_CTX_SETUP(ok = BPY_execute_filepath(C, filename, NULL));
1777     if (!ok && app_state.exit_code_on_error.python) {
1778       printf("\nError: script failed, file: '%s', exiting.\n", argv[1]);
1779       BPY_python_end();
1780       exit(app_state.exit_code_on_error.python);
1781     }
1782     return 1;
1783   }
1784   else {
1785     printf("\nError: you must specify a filepath after '%s'.\n", argv[0]);
1786     return 0;
1787   }
1788 #  else
1789   UNUSED_VARS(argc, argv, data);
1790   printf("This Blender was built without Python support\n");
1791   return 0;
1792 #  endif /* WITH_PYTHON */
1793 }
1794
1795 static const char arg_handle_python_text_run_doc[] =
1796     "<name>\n"
1797     "\tRun the given Python script text block.";
1798 static int arg_handle_python_text_run(int argc, const char **argv, void *data)
1799 {
1800 #  ifdef WITH_PYTHON
1801   bContext *C = data;
1802
1803   /* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */
1804   if (argc > 1) {
1805     Main *bmain = CTX_data_main(C);
1806     /* Make the path absolute because its needed for relative linked blends to be found */
1807     struct Text *text = (struct Text *)BKE_libblock_find_name(bmain, ID_TXT, argv[1]);
1808     bool ok;
1809
1810     if (text) {
1811       BPY_CTX_SETUP(ok = BPY_execute_text(C, text, NULL, false));
1812     }
1813     else {
1814       printf("\nError: text block not found %s.\n", argv[1]);
1815       ok = false;
1816     }
1817
1818     if (!ok && app_state.exit_code_on_error.python) {
1819       printf("\nError: script failed, text: '%s', exiting.\n", argv[1]);
1820       BPY_python_end();
1821       exit(app_state.exit_code_on_error.python);
1822     }
1823
1824     return 1;
1825   }
1826   else {
1827     printf("\nError: you must specify a text block after '%s'.\n", argv[0]);
1828     return 0;
1829   }
1830 #  else
1831   UNUSED_VARS(argc, argv, data);
1832   printf("This Blender was built without Python support\n");
1833   return 0;
1834 #  endif /* WITH_PYTHON */
1835 }
1836
1837 static const char arg_handle_python_expr_run_doc[] =
1838     "<expression>\n"
1839     "\tRun the given expression as a Python script.";
1840 static int arg_handle_python_expr_run(int argc, const char **argv, void *data)
1841 {
1842 #  ifdef WITH_PYTHON
1843   bContext *C = data;
1844
1845   /* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */
1846   if (argc > 1) {
1847     bool ok;
1848     BPY_CTX_SETUP(ok = BPY_execute_string_ex(C, NULL, argv[1], false));
1849     if (!ok && app_state.exit_code_on_error.python) {
1850       printf("\nError: script failed, expr: '%s', exiting.\n", argv[1]);
1851       BPY_python_end();
1852       exit(app_state.exit_code_on_error.python);
1853     }
1854     return 1;
1855   }
1856   else {
1857     printf("\nError: you must specify a Python expression after '%s'.\n", argv[0]);
1858     return 0;
1859   }
1860 #  else
1861   UNUSED_VARS(argc, argv, data);
1862   printf("This Blender was built without Python support\n");
1863   return 0;
1864 #  endif /* WITH_PYTHON */
1865 }
1866
1867 static const char arg_handle_python_console_run_doc[] =
1868     "\n\t"
1869     "Run Blender with an interactive console.";
1870 static int arg_handle_python_console_run(int UNUSED(argc), const char **argv, void *data)
1871 {
1872 #  ifdef WITH_PYTHON
1873   bContext *C = data;
1874
1875   BPY_CTX_SETUP(BPY_execute_string(C, (const char *[]){"code", NULL}, "code.interact()"));
1876
1877   return 0;
1878 #  else
1879   UNUSED_VARS(argv, data);
1880   printf("This Blender was built without python support\n");
1881   return 0;
1882 #  endif /* WITH_PYTHON */
1883 }
1884
1885 static const char arg_handle_python_exit_code_set_doc[] =
1886     "<code>\n"
1887     "\tSet the exit-code in [0..255] to exit if a Python exception is raised\n"
1888     "\t(only for scripts executed from the command line), zero disables.";
1889 static int arg_handle_python_exit_code_set(int argc, const char **argv, void *UNUSED(data))
1890 {
1891   const char *arg_id = "--python-exit-code";
1892   if (argc > 1) {
1893     const char *err_msg = NULL;
1894     const int min = 0, max = 255;
1895     int exit_code;
1896     if (!parse_int_strict_range(argv[1], NULL, min, max, &exit_code, &err_msg)) {
1897       printf("\nError: %s '%s %s', expected number in [%d..%d].\n",
1898              err_msg,
1899              arg_id,
1900              argv[1],
1901              min,
1902              max);
1903       return 1;
1904     }
1905
1906     app_state.exit_code_on_error.python = (unsigned char)exit_code;
1907     return 1;
1908   }
1909   else {
1910     printf("\nError: you must specify an exit code number '%s'.\n", arg_id);
1911     return 0;
1912   }
1913 }
1914
1915 static const char arg_handle_addons_set_doc[] =
1916     "<addon(s)>\n"
1917     "\tComma separated list of add-ons (no spaces).";
1918 static int arg_handle_addons_set(int argc, const char **argv, void *data)
1919 {
1920   /* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */
1921   if (argc > 1) {
1922 #  ifdef WITH_PYTHON
1923     const char script_str[] =
1924         "from addon_utils import check, enable\n"
1925         "for m in '%s'.split(','):\n"
1926         "    if check(m)[1] is False:\n"
1927         "        enable(m, persistent=True)";
1928     const int slen = strlen(argv[1]) + (sizeof(script_str) - 2);
1929     char *str = malloc(slen);
1930     bContext *C = data;
1931     BLI_snprintf(str, slen, script_str, argv[1]);
1932
1933     BLI_assert(strlen(str) + 1 == slen);
1934     BPY_CTX_SETUP(BPY_execute_string_ex(C, NULL, str, false));
1935     free(str);
1936 #  else
1937     UNUSED_VARS(argv, data);
1938 #  endif /* WITH_PYTHON */
1939     return 1;
1940   }
1941   else {
1942     printf("\nError: you must specify a comma separated list after '--addons'.\n");
1943     return 0;
1944   }
1945 }
1946
1947 static int arg_handle_load_file(int UNUSED(argc), const char **argv, void *data)
1948 {
1949   bContext *C = data;
1950   ReportList reports;
1951   bool success;
1952
1953   /* Make the path absolute because its needed for relative linked blends to be found */
1954   char filename[FILE_MAX];
1955
1956   /* note, we could skip these, but so far we always tried to load these files */
1957   if (argv[0][0] == '-') {
1958     fprintf(stderr, "unknown argument, loading as file: %s\n", argv[0]);
1959   }
1960
1961   BLI_strncpy(filename, argv[0], sizeof(filename));
1962   BLI_path_cwd(filename, sizeof(filename));
1963
1964   /* load the file */
1965   BKE_reports_init(&reports, RPT_PRINT);
1966   WM_file_autoexec_init(filename);
1967   success = WM_file_read(C, filename, &reports);
1968   BKE_reports_clear(&reports);
1969
1970   if (success) {
1971     if (G.background) {
1972       /* ensuer we use 'C->data.scene' for background render */
1973       CTX_wm_window_set(C, NULL);
1974     }
1975   }
1976   else {
1977     /* failed to load file, stop processing arguments if running in background mode */
1978     if (G.background) {
1979       /* Set is_break if running in the background mode so
1980        * blender will return non-zero exit code which then
1981        * could be used in automated script to control how
1982        * good or bad things are.
1983        */
1984       G.is_break = true;
1985       return -1;
1986     }
1987
1988     if (BLO_has_bfile_extension(filename)) {
1989       /* Just pretend a file was loaded, so the user can press Save and it'll
1990        * save at the filename from the CLI. */
1991       BLI_strncpy(G_MAIN->name, filename, FILE_MAX);
1992       G.relbase_valid = true;
1993       G.save_over = true;
1994       printf("... opened default scene instead; saving will write to: %s\n", filename);
1995     }
1996     else {
1997       printf(
1998           "Error: argument has no '.blend' file extension, not using as new file, exiting! %s\n",
1999           filename);
2000       G.is_break = true;
2001       WM_exit(C);
2002     }
2003   }
2004
2005   G.file_loaded = 1;
2006
2007   return 0;
2008 }
2009
2010 void main_args_setup(bContext *C, bArgs *ba)
2011 {
2012
2013 #  define CB(a) a##_doc, a
2014 #  define CB_EX(a, b) a##_doc_##b, a
2015
2016   // BLI_argsAdd(ba, pass, short_arg, long_arg, doc, cb, C);
2017
2018   /* end argument processing after -- */
2019   BLI_argsAdd(ba, -1, "--", NULL, CB(arg_handle_arguments_end), NULL);
2020
2021   /* first pass: background mode, disable python and commands that exit after usage */
2022   BLI_argsAdd(ba, 1, "-h", "--help", CB(arg_handle_print_help), ba);
2023   /* Windows only */
2024   BLI_argsAdd(ba, 1, "/?", NULL, CB_EX(arg_handle_print_help, win32), ba);
2025
2026   BLI_argsAdd(ba, 1, "-v", "--version", CB(arg_handle_print_version), NULL);
2027
2028   BLI_argsAdd(
2029       ba, 1, "-y", "--enable-autoexec", CB_EX(arg_handle_python_set, enable), (void *)true);
2030   BLI_argsAdd(
2031       ba, 1, "-Y", "--disable-autoexec", CB_EX(arg_handle_python_set, disable), (void *)false);
2032
2033   BLI_argsAdd(ba, 1, NULL, "--disable-crash-handler", CB(arg_handle_crash_handler_disable), NULL);
2034   BLI_argsAdd(ba, 1, NULL, "--disable-abort-handler", CB(arg_handle_abort_handler_disable), NULL);
2035
2036   BLI_argsAdd(ba, 1, "-b", "--background", CB(arg_handle_background_mode_set), NULL);
2037
2038   BLI_argsAdd(ba, 1, "-a", NULL, CB(arg_handle_playback_mode), NULL);
2039
2040   BLI_argsAdd(ba, 1, NULL, "--log", CB(arg_handle_log_set), ba);
2041   BLI_argsAdd(ba, 1, NULL, "--log-level", CB(arg_handle_log_level_set), ba);
2042   BLI_argsAdd(ba, 1, NULL, "--log-show-basename", CB(arg_handle_log_show_basename_set), ba);
2043   BLI_argsAdd(ba, 1, NULL, "--log-show-backtrace", CB(arg_handle_log_show_backtrace_set), ba);
2044   BLI_argsAdd(ba, 1, NULL, "--log-show-timestamp", CB(arg_handle_log_show_timestamp_set), ba);
2045   BLI_argsAdd(ba, 1, NULL, "--log-file", CB(arg_handle_log_file_set), ba);
2046
2047   BLI_argsAdd(ba, 1, "-d", "--debug", CB(arg_handle_debug_mode_set), ba);
2048
2049 #  ifdef WITH_FFMPEG
2050   BLI_argsAdd(ba,
2051               1,
2052               NULL,
2053               "--debug-ffmpeg",
2054               CB_EX(arg_handle_debug_mode_generic_set, ffmpeg),
2055               (void *)G_DEBUG_FFMPEG);
2056 #  endif
2057
2058 #  ifdef WITH_FREESTYLE
2059   BLI_argsAdd(ba,
2060               1,
2061               NULL,
2062               "--debug-freestyle",
2063               CB_EX(arg_handle_debug_mode_generic_set, freestyle),
2064               (void *)G_DEBUG_FREESTYLE);
2065 #  endif
2066
2067   BLI_argsAdd(ba,
2068               1,
2069               NULL,
2070               "--debug-python",
2071               CB_EX(arg_handle_debug_mode_generic_set, python),
2072               (void *)G_DEBUG_PYTHON);
2073   BLI_argsAdd(ba,
2074               1,
2075               NULL,
2076               "--debug-events",
2077               CB_EX(arg_handle_debug_mode_generic_set, events),
2078               (void *)G_DEBUG_EVENTS);
2079   BLI_argsAdd(ba,
2080               1,
2081               NULL,
2082               "--debug-handlers",
2083               CB_EX(arg_handle_debug_mode_generic_set, handlers),
2084               (void *)G_DEBUG_HANDLERS);
2085   BLI_argsAdd(
2086       ba, 1, NULL, "--debug-wm", CB_EX(arg_handle_debug_mode_generic_set, wm), (void *)G_DEBUG_WM);
2087   BLI_argsAdd(ba, 1, NULL, "--debug-all", CB(arg_handle_debug_mode_all), NULL);
2088
2089   BLI_argsAdd(ba, 1, NULL, "--debug-io", CB(arg_handle_debug_mode_io), NULL);
2090
2091   BLI_argsAdd(ba, 1, NULL, "--debug-fpe", CB(arg_handle_debug_fpe_set), NULL);
2092
2093 #  ifdef WITH_LIBMV
2094   BLI_argsAdd(ba, 1, NULL, "--debug-libmv", CB(arg_handle_debug_mode_libmv), NULL);
2095 #  endif
2096 #  ifdef WITH_CYCLES_LOGGING
2097   BLI_argsAdd(ba, 1, NULL, "--debug-cycles", CB(arg_handle_debug_mode_cycles), NULL);
2098 #  endif
2099   BLI_argsAdd(ba, 1, NULL, "--debug-memory", CB(arg_handle_debug_mode_memory_set), NULL);
2100
2101   BLI_argsAdd(ba, 1, NULL, "--debug-value", CB(arg_handle_debug_value_set), NULL);
2102   BLI_argsAdd(ba,
2103               1,
2104               NULL,
2105               "--debug-jobs",
2106               CB_EX(arg_handle_debug_mode_generic_set, jobs),
2107               (void *)G_DEBUG_JOBS);
2108   BLI_argsAdd(ba,
2109               1,
2110               NULL,
2111               "--debug-gpu",
2112               CB_EX(arg_handle_debug_mode_generic_set, gpu),
2113               (void *)G_DEBUG_GPU);
2114   BLI_argsAdd(ba,
2115               1,
2116               NULL,
2117               "--debug-depsgraph",
2118               CB_EX(arg_handle_debug_mode_generic_set, depsgraph),
2119               (void *)G_DEBUG_DEPSGRAPH);
2120   BLI_argsAdd(ba,
2121               1,
2122               NULL,
2123               "--debug-depsgraph-build",
2124               CB_EX(arg_handle_debug_mode_generic_set, depsgraph_build),
2125               (void *)G_DEBUG_DEPSGRAPH_BUILD);
2126   BLI_argsAdd(ba,
2127               1,
2128               NULL,
2129               "--debug-depsgraph-eval",
2130               CB_EX(arg_handle_debug_mode_generic_set, depsgraph_eval),
2131               (void *)G_DEBUG_DEPSGRAPH_EVAL);
2132   BLI_argsAdd(ba,
2133               1,
2134               NULL,
2135               "--debug-depsgraph-tag",
2136               CB_EX(arg_handle_debug_mode_generic_set, depsgraph_tag),
2137               (void *)G_DEBUG_DEPSGRAPH_TAG);
2138   BLI_argsAdd(ba,
2139               1,
2140               NULL,
2141               "--debug-depsgraph-time",
2142               CB_EX(arg_handle_debug_mode_generic_set, depsgraph_time),
2143               (void *)G_DEBUG_DEPSGRAPH_TIME);
2144   BLI_argsAdd(ba,
2145               1,
2146               NULL,
2147               "--debug-depsgraph-no-threads",
2148               CB_EX(arg_handle_debug_mode_generic_set, depsgraph_no_threads),
2149               (void *)G_DEBUG_DEPSGRAPH_NO_THREADS);
2150   BLI_argsAdd(ba,
2151               1,
2152               NULL,
2153               "--debug-depsgraph-pretty",
2154               CB_EX(arg_handle_debug_mode_generic_set, depsgraph_pretty),
2155               (void *)G_DEBUG_DEPSGRAPH_PRETTY);
2156   BLI_argsAdd(ba,
2157               1,
2158               NULL,
2159               "--debug-gpumem",
2160               CB_EX(arg_handle_debug_mode_generic_set, gpumem),
2161               (void *)G_DEBUG_GPU_MEM);
2162   BLI_argsAdd(ba,
2163               1,
2164               NULL,
2165               "--debug-gpu-shaders",
2166               CB_EX(arg_handle_debug_mode_generic_set, gpumem),
2167               (void *)G_DEBUG_GPU_SHADERS);
2168   BLI_argsAdd(ba,
2169               1,
2170               NULL,
2171               "--debug-gpu-force-workarounds",
2172               CB_EX(arg_handle_debug_mode_generic_set, gpumem),
2173               (void *)G_DEBUG_GPU_FORCE_WORKAROUNDS);
2174
2175   BLI_argsAdd(ba, 1, NULL, "--verbose", CB(arg_handle_verbosity_set), NULL);
2176
2177   BLI_argsAdd(ba, 1, NULL, "--app-template", CB(arg_handle_app_template), NULL);
2178   BLI_argsAdd(ba, 1, NULL, "--factory-startup", CB(arg_handle_factory_startup_set), NULL);
2179   BLI_argsAdd(
2180       ba, 1, NULL, "--enable-static-override", CB(arg_handle_enable_static_override), NULL);
2181   BLI_argsAdd(ba, 1, NULL, "--enable-event-simulate", CB(arg_handle_enable_event_simulate), NULL);
2182
2183   /* TODO, add user env vars? */
2184   BLI_argsAdd(
2185       ba, 1, NULL, "--env-system-datafiles", CB_EX(arg_handle_env_system_set, datafiles), NULL);
2186   BLI_argsAdd(
2187       ba, 1, NULL, "--env-system-scripts", CB_EX(arg_handle_env_system_set, scripts), NULL);
2188   BLI_argsAdd(ba, 1, NULL, "--env-system-python", CB_EX(arg_handle_env_system_set, python), NULL);
2189
2190   /* second pass: custom window stuff */
2191   BLI_argsAdd(ba, 2, "-p", "--window-geometry", CB(arg_handle_window_geometry), NULL);
2192   BLI_argsAdd(ba, 2, "-w", "--window-border", CB(arg_handle_with_borders), NULL);
2193   BLI_argsAdd(ba, 2, "-W", "--window-fullscreen", CB(arg_handle_without_borders), NULL);
2194   BLI_argsAdd(ba, 2, "-M", "--window-maximized", CB(arg_handle_window_maximized), NULL);
2195   BLI_argsAdd(ba, 2, NULL, "--no-window-focus", CB(arg_handle_no_window_focus), NULL);
2196   BLI_argsAdd(ba, 2, "-con", "--start-console", CB(arg_handle_start_with_console), NULL);
2197   BLI_argsAdd(ba, 2, "-R", NULL, CB(arg_handle_register_extension), NULL);
2198   BLI_argsAdd(ba, 2, "-r", NULL, CB_EX(arg_handle_register_extension, silent), ba);
2199   BLI_argsAdd(ba, 2, NULL, "--no-native-pixels", CB(arg_handle_native_pixels_set), ba);
2200
2201   /* third pass: disabling things and forcing settings */
2202   BLI_argsAddCase(ba, 3, "-noaudio", 1, NULL, 0, CB(arg_handle_audio_disable), NULL);
2203   BLI_argsAddCase(ba, 3, "-setaudio", 1, NULL, 0, CB(arg_handle_audio_set), NULL);
2204
2205   /* fourth pass: processing arguments */
2206   BLI_argsAdd(ba, 4, "-f", "--render-frame", CB(arg_handle_render_frame), C);
2207   BLI_argsAdd(ba, 4, "-a", "--render-anim", CB(arg_handle_render_animation), C);
2208   BLI_argsAdd(ba, 4, "-S", "--scene", CB(arg_handle_scene_set), C);
2209   BLI_argsAdd(ba, 4, "-s", "--frame-start", CB(arg_handle_frame_start_set), C);
2210   BLI_argsAdd(ba, 4, "-e", "--frame-end", CB(arg_handle_frame_end_set), C);
2211   BLI_argsAdd(ba, 4, "-j", "--frame-jump", CB(arg_handle_frame_skip_set), C);
2212   BLI_argsAdd(ba, 4, "-P", "--python", CB(arg_handle_python_file_run), C);
2213   BLI_argsAdd(ba, 4, NULL, "--python-text", CB(arg_handle_python_text_run), C);
2214   BLI_argsAdd(ba, 4, NULL, "--python-expr", CB(arg_handle_python_expr_run), C);
2215   BLI_argsAdd(ba, 4, NULL, "--python-console", CB(arg_handle_python_console_run), C);
2216   BLI_argsAdd(ba, 4, NULL, "--python-exit-code", CB(arg_handle_python_exit_code_set), NULL);
2217   BLI_argsAdd(ba, 4, NULL, "--addons", CB(arg_handle_addons_set), C);
2218
2219   BLI_argsAdd(ba, 4, "-o", "--render-output", CB(arg_handle_output_set), C);
2220   BLI_argsAdd(ba, 4, "-E", "--engine", CB(arg_handle_engine_set), C);
2221
2222   BLI_argsAdd(ba, 4, "-F", "--render-format", CB(arg_handle_image_type_set), C);
2223   BLI_argsAdd(ba, 1, "-t", "--threads", CB(arg_handle_threads_set), NULL);
2224   BLI_argsAdd(ba, 4, "-x", "--use-extension", CB(arg_handle_extension_set), C);
2225
2226 #  undef CB
2227 #  undef CB_EX
2228 }
2229
2230 /**
2231  * Needs to be added separately.
2232  */
2233 void main_args_setup_post(bContext *C, bArgs *ba)
2234 {
2235   BLI_argsParse(ba, 4, arg_handle_load_file, C);
2236 }
2237
2238 /** \} */
2239
2240 #endif /* WITH_PYTHON_MODULE */