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