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