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