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