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