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