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