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