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