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