RNA: strict naming for types in bpy.types
[blender.git] / source / creator / creator_args.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * ***** END GPL LICENSE BLOCK *****
19  */
20
21 /** \file creator/creator_args.c
22  *  \ingroup creator
23  */
24
25 #ifndef WITH_PYTHON_MODULE
26
27 #include <stdlib.h>
28 #include <string.h>
29 #include <errno.h>
30
31 #include "MEM_guardedalloc.h"
32
33 #ifdef WIN32
34 #  include "BLI_winstuff.h"
35 #endif
36
37 #include "BLI_args.h"
38 #include "BLI_threads.h"
39 #include "BLI_utildefines.h"
40 #include "BLI_listbase.h"
41 #include "BLI_string.h"
42 #include "BLI_string_utf8.h"
43 #include "BLI_path_util.h"
44 #include "BLI_fileops.h"
45 #include "BLI_mempool.h"
46
47 #include "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\tEnds 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\n"
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"
889 "\t\t-p <sx> <sy>\tOpen with lower left corner at <sx>, <sy>\n"
890 "\t\t-m\t\tRead from disk (Do not buffer)\n"
891 "\t\t-f <fps> <fps-base>\t\tSpecify FPS to start with\n"
892 "\t\t-j <frame>\tSet frame step to <frame>\n"
893 "\t\t-s <frame>\tPlay from <frame>\n"
894 "\t\t-e <frame>\tPlay until <frame>"
895 ;
896 static int arg_handle_playback_mode(int argc, const char **argv, void *UNUSED(data))
897 {
898         /* not if -b was given first */
899         if (G.background == 0) {
900 #ifdef WITH_FFMPEG
901                 /* Setup FFmpeg with current debug flags. */
902                 IMB_ffmpeg_init();
903 #endif
904
905                 WM_main_playanim(argc, argv); /* not the same argc and argv as before */
906                 exit(0); /* 2.4x didn't do this */
907         }
908
909         return -2;
910 }
911
912 static const char arg_handle_window_geometry_doc[] =
913 "<sx> <sy> <w> <h>\n"
914 "\tOpen with lower left corner at <sx>, <sy> and width and height as <w>, <h>"
915 ;
916 static int arg_handle_window_geometry(int argc, const char **argv, void *UNUSED(data))
917 {
918         const char *arg_id = "-p / --window-geometry";
919         int params[4], i;
920
921         if (argc < 5) {
922                 fprintf(stderr, "Error: requires four arguments '%s'\n", arg_id);
923                 exit(1);
924         }
925
926         for (i = 0; i < 4; i++) {
927                 const char *err_msg = NULL;
928                 if (!parse_int(argv[i + 1], NULL, &params[i], &err_msg)) {
929                         printf("\nError: %s '%s %s'.\n", err_msg, arg_id, argv[1]);
930                         exit(1);
931                 }
932         }
933
934         WM_init_state_size_set(UNPACK4(params));
935
936         return 4;
937 }
938
939 static const char arg_handle_native_pixels_set_doc[] =
940 "\n\tDo not use native pixel size, for high resolution displays (MacBook 'Retina')"
941 ;
942 static int arg_handle_native_pixels_set(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
943 {
944         WM_init_native_pixels(false);
945         return 0;
946 }
947
948 static const char arg_handle_with_borders_doc[] =
949 "\n\tForce opening with borders"
950 ;
951 static int arg_handle_with_borders(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
952 {
953         WM_init_state_normal_set();
954         return 0;
955 }
956
957 static const char arg_handle_without_borders_doc[] =
958 "\n\tForce opening without borders"
959 ;
960 static int arg_handle_without_borders(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
961 {
962         WM_init_state_fullscreen_set();
963         return 0;
964 }
965
966 extern bool wm_start_with_console; /* wm_init_exit.c */
967
968 static const char arg_handle_start_with_console_doc[] =
969 "\n\tStart with the console window open (ignored if -b is set), (Windows only)"
970 ;
971 static int arg_handle_start_with_console(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
972 {
973         wm_start_with_console = true;
974         return 0;
975 }
976
977 static const char arg_handle_register_extension_doc[] =
978 "\n\tRegister blend-file extension, then exit (Windows only)"
979 ;
980 static const char arg_handle_register_extension_doc_silent[] =
981 "\n\tSilently register blend-file extension, then exit (Windows only)"
982 ;
983 static int arg_handle_register_extension(int UNUSED(argc), const char **UNUSED(argv), void *data)
984 {
985 #ifdef WIN32
986         if (data)
987                 G.background = 1;
988         RegisterBlendExtension();
989 #else
990         (void)data; /* unused */
991 #endif
992         return 0;
993 }
994
995 static const char arg_handle_joystick_disable_doc[] =
996 "\n\tDisable joystick support"
997 ;
998 static int arg_handle_joystick_disable(int UNUSED(argc), const char **UNUSED(argv), void *data)
999 {
1000 #ifndef WITH_GAMEENGINE
1001         (void)data;
1002 #else
1003         SYS_SystemHandle *syshandle = data;
1004
1005         /**
1006          * don't initialize joysticks if user doesn't want to use joysticks
1007          * failed joystick initialization delays over 5 seconds, before game engine start
1008          */
1009         SYS_WriteCommandLineInt(*syshandle, "nojoystick", 1);
1010         if (G.debug & G_DEBUG) printf("disabling nojoystick\n");
1011 #endif
1012
1013         return 0;
1014 }
1015
1016 static const char arg_handle_glsl_disable_doc[] =
1017 "\n\tDisable GLSL shading"
1018 ;
1019 static int arg_handle_glsl_disable(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
1020 {
1021         GPU_extensions_disable();
1022         return 0;
1023 }
1024
1025 static const char arg_handle_audio_disable_doc[] =
1026 "\n\tForce sound system to None"
1027 ;
1028 static int arg_handle_audio_disable(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
1029 {
1030         BKE_sound_force_device("Null");
1031         return 0;
1032 }
1033
1034 static const char arg_handle_audio_set_doc[] =
1035 "\n\tForce sound system to a specific device\n\tNULL SDL OPENAL JACK"
1036 ;
1037 static int arg_handle_audio_set(int argc, const char **argv, void *UNUSED(data))
1038 {
1039         if (argc < 1) {
1040                 fprintf(stderr, "-setaudio require one argument\n");
1041                 exit(1);
1042         }
1043
1044         BKE_sound_force_device(argv[1]);
1045         return 1;
1046 }
1047
1048 static const char arg_handle_output_set_doc[] =
1049 "<path>\n"
1050 "\tSet the render path and file name.\n"
1051 "\tUse '//' at the start of the path to render relative to the blend-file.\n"
1052 "\n"
1053 "\tThe '#' characters are replaced by the frame number, and used to define zero padding.\n"
1054 "\n"
1055 "\t* 'ani_##_test.png' becomes 'ani_01_test.png'\n"
1056 "\t* 'test-######.png' becomes 'test-000001.png'\n"
1057 "\n"
1058 "\tWhen the filename does not contain '#', The suffix '####' is added to the filename.\n"
1059 "\n"
1060 "\tThe frame number will be added at the end of the filename, eg:\n"
1061 "\t# blender -b foobar.blend -o //render_ -F PNG -x 1 -a\n"
1062 "\t'//render_' becomes '//render_####', writing frames as '//render_0001.png'"
1063 ;
1064 static int arg_handle_output_set(int argc, const char **argv, void *data)
1065 {
1066         bContext *C = data;
1067         if (argc > 1) {
1068                 Scene *scene = CTX_data_scene(C);
1069                 if (scene) {
1070                         BLI_strncpy(scene->r.pic, argv[1], sizeof(scene->r.pic));
1071                 }
1072                 else {
1073                         printf("\nError: no blend loaded. cannot use '-o / --render-output'.\n");
1074                 }
1075                 return 1;
1076         }
1077         else {
1078                 printf("\nError: you must specify a path after '-o  / --render-output'.\n");
1079                 return 0;
1080         }
1081 }
1082
1083 static const char arg_handle_engine_set_doc[] =
1084 "<engine>\n"
1085 "\tSpecify the render engine\n\tuse -E help to list available engines"
1086 ;
1087 static int arg_handle_engine_set(int argc, const char **argv, void *data)
1088 {
1089         bContext *C = data;
1090         if (argc >= 2) {
1091                 if (STREQ(argv[1], "help")) {
1092                         RenderEngineType *type = NULL;
1093                         printf("Blender Engine Listing:\n");
1094                         for (type = R_engines.first; type; type = type->next) {
1095                                 printf("\t%s\n", type->idname);
1096                         }
1097                         exit(0);
1098                 }
1099                 else {
1100                         Scene *scene = CTX_data_scene(C);
1101                         if (scene) {
1102                                 RenderData *rd = &scene->r;
1103
1104                                 if (BLI_findstring(&R_engines, argv[1], offsetof(RenderEngineType, idname))) {
1105                                         BLI_strncpy_utf8(rd->engine, argv[1], sizeof(rd->engine));
1106                                 }
1107                                 else {
1108                                         printf("\nError: engine not found '%s'\n", argv[1]);
1109                                         exit(1);
1110                                 }
1111                         }
1112                         else {
1113                                 printf("\nError: no blend loaded. "
1114                                        "order the arguments so '-E  / --engine ' is after a blend is loaded.\n");
1115                         }
1116                 }
1117
1118                 return 1;
1119         }
1120         else {
1121                 printf("\nEngine not specified, give 'help' for a list of available engines.\n");
1122                 return 0;
1123         }
1124 }
1125
1126 static const char arg_handle_image_type_set_doc[] =
1127 "<format>\n"
1128 "\tSet the render format, Valid options are...\n"
1129 "\t\tTGA RAWTGA JPEG IRIS IRIZ\n"
1130 "\t\tAVIRAW AVIJPEG PNG BMP\n"
1131 "\t(formats that can be compiled into blender, not available on all systems)\n"
1132 "\t\tHDR TIFF EXR MULTILAYER MPEG FRAMESERVER QUICKTIME CINEON DPX DDS JP2"
1133 ;
1134 static int arg_handle_image_type_set(int argc, const char **argv, void *data)
1135 {
1136         bContext *C = data;
1137         if (argc > 1) {
1138                 const char *imtype = argv[1];
1139                 Scene *scene = CTX_data_scene(C);
1140                 if (scene) {
1141                         const char imtype_new = BKE_imtype_from_arg(imtype);
1142
1143                         if (imtype_new == R_IMF_IMTYPE_INVALID) {
1144                                 printf("\nError: Format from '-F / --render-format' not known or not compiled in this release.\n");
1145                         }
1146                         else {
1147                                 scene->r.im_format.imtype = imtype_new;
1148                         }
1149                 }
1150                 else {
1151                         printf("\nError: no blend loaded. "
1152                                "order the arguments so '-F  / --render-format' is after the blend is loaded.\n");
1153                 }
1154                 return 1;
1155         }
1156         else {
1157                 printf("\nError: you must specify a format after '-F  / --render-foramt'.\n");
1158                 return 0;
1159         }
1160 }
1161
1162 static const char arg_handle_threads_set_doc[] =
1163 "<threads>\n"
1164 "\tUse amount of <threads> for rendering and other operations\n"
1165 "\t[1-" STRINGIFY(BLENDER_MAX_THREADS) "], 0 for systems processor count."
1166 ;
1167 static int arg_handle_threads_set(int argc, const char **argv, void *UNUSED(data))
1168 {
1169         const char *arg_id = "-t / --threads";
1170         const int min = 0, max = BLENDER_MAX_THREADS;
1171         if (argc > 1) {
1172                 const char *err_msg = NULL;
1173                 int threads;
1174                 if (!parse_int_strict_range(argv[1], NULL, min, max, &threads, &err_msg)) {
1175                         printf("\nError: %s '%s %s', expected number in [%d..%d].\n", err_msg, arg_id, argv[1], min, max);
1176                         return 1;
1177                 }
1178
1179                 BLI_system_num_threads_override_set(threads);
1180                 return 1;
1181         }
1182         else {
1183                 printf("\nError: you must specify a number of threads in [%d..%d] '%s'.\n", min, max, arg_id);
1184                 return 0;
1185         }
1186 }
1187
1188 static const char arg_handle_depsgraph_use_new_doc[] =
1189 "\n\tUse new dependency graph"
1190 ;
1191 static int arg_handle_depsgraph_use_new(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
1192 {
1193         printf("Using new dependency graph.\n");
1194         DEG_depsgraph_switch_to_new();
1195         return 0;
1196 }
1197
1198 static const char arg_handle_basic_shader_glsl_use_new_doc[] =
1199 "\n\tUse new GLSL basic shader"
1200 ;
1201 static int arg_handle_basic_shader_glsl_use_new(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
1202 {
1203         printf("Using new GLSL basic shader.\n");
1204         GPU_basic_shader_use_glsl_set(true);
1205         return 0;
1206 }
1207
1208 static const char arg_handle_verbosity_set_doc[] =
1209 "<verbose>\n"
1210 "\tSet logging verbosity level."
1211 ;
1212 static int arg_handle_verbosity_set(int argc, const char **argv, void *UNUSED(data))
1213 {
1214         const char *arg_id = "--verbose";
1215         if (argc > 1) {
1216                 const char *err_msg = NULL;
1217                 int level;
1218                 if (!parse_int(argv[1], NULL, &level, &err_msg)) {
1219                         printf("\nError: %s '%s %s'.\n", err_msg, arg_id, argv[1]);
1220                 }
1221
1222 #ifdef WITH_LIBMV
1223                 libmv_setLoggingVerbosity(level);
1224 #elif defined(WITH_CYCLES_LOGGING)
1225                 CCL_logging_verbosity_set(level);
1226 #else
1227                 (void)level;
1228 #endif
1229
1230                 return 1;
1231         }
1232         else {
1233                 printf("\nError: you must specify a verbosity level.\n");
1234                 return 0;
1235         }
1236 }
1237
1238 static const char arg_handle_extension_set_doc[] =
1239 "<bool>\n"
1240 "\tSet option to add the file extension to the end of the file"
1241 ;
1242 static int arg_handle_extension_set(int argc, const char **argv, void *data)
1243 {
1244         bContext *C = data;
1245         if (argc > 1) {
1246                 Scene *scene = CTX_data_scene(C);
1247                 if (scene) {
1248                         if (argv[1][0] == '0') {
1249                                 scene->r.scemode &= ~R_EXTENSION;
1250                         }
1251                         else if (argv[1][0] == '1') {
1252                                 scene->r.scemode |= R_EXTENSION;
1253                         }
1254                         else {
1255                                 printf("\nError: Use '-x 1 / -x 0' To set the extension option or '--use-extension'\n");
1256                         }
1257                 }
1258                 else {
1259                         printf("\nError: no blend loaded. "
1260                                "order the arguments so '-o ' is after '-x '.\n");
1261                 }
1262                 return 1;
1263         }
1264         else {
1265                 printf("\nError: you must specify a path after '- '.\n");
1266                 return 0;
1267         }
1268 }
1269
1270 static const char arg_handle_ge_parameters_set_doc[] =
1271 "Game Engine specific options\n"
1272 "\t-g fixedtime\t\tRun on 50 hertz without dropping frames\n"
1273 "\t-g vertexarrays\t\tUse Vertex Arrays for rendering (usually faster)\n"
1274 "\t-g nomipmap\t\tNo Texture Mipmapping\n"
1275 "\t-g linearmipmap\t\tLinear Texture Mipmapping instead of Nearest (default)"
1276 ;
1277 static int arg_handle_ge_parameters_set(int argc, const char **argv, void *data)
1278 {
1279         int a = 0;
1280 #ifdef WITH_GAMEENGINE
1281         SYS_SystemHandle syshandle = *(SYS_SystemHandle *)data;
1282 #else
1283         (void)data;
1284 #endif
1285
1286         /**
1287          * gameengine parameters are automatically put into system
1288          * -g [paramname = value]
1289          * -g [boolparamname]
1290          * example:
1291          * -g novertexarrays
1292          * -g maxvertexarraysize = 512
1293          */
1294
1295         if (argc >= 1) {
1296                 const char *paramname = argv[a];
1297                 /* check for single value versus assignment */
1298                 if (a + 1 < argc && (*(argv[a + 1]) == '=')) {
1299                         a++;
1300                         if (a + 1 < argc) {
1301                                 a++;
1302                                 /* assignment */
1303 #ifdef WITH_GAMEENGINE
1304                                 SYS_WriteCommandLineString(syshandle, paramname, argv[a]);
1305 #endif
1306                         }
1307                         else {
1308                                 printf("error: argument assignment (%s) without value.\n", paramname);
1309                                 return 0;
1310                         }
1311                         /* name arg eaten */
1312
1313                 }
1314                 else {
1315 #ifdef WITH_GAMEENGINE
1316                         SYS_WriteCommandLineInt(syshandle, argv[a], 1);
1317 #endif
1318                         /* doMipMap */
1319                         if (STREQ(argv[a], "nomipmap")) {
1320                                 GPU_set_mipmap(0); //doMipMap = 0;
1321                         }
1322                         /* linearMipMap */
1323                         if (STREQ(argv[a], "linearmipmap")) {
1324                                 GPU_set_mipmap(1);
1325                                 GPU_set_linear_mipmap(1); //linearMipMap = 1;
1326                         }
1327
1328
1329                 } /* if (*(argv[a + 1]) == '=') */
1330         }
1331
1332         return a;
1333 }
1334
1335 static const char arg_handle_render_frame_doc[] =
1336 "<frame>\n"
1337 "\tRender frame <frame> and save it.\n"
1338 "\n"
1339 "\t* +<frame> start frame relative, -<frame> end frame relative.\n"
1340 "\t* A comma separated list of frames can also be used (no spaces).\n"
1341 "\t* A range of frames can be expressed using '..' seperator between the first and last frames (inclusive).\n"
1342 ;
1343 static int arg_handle_render_frame(int argc, const char **argv, void *data)
1344 {
1345         const char *arg_id = "-f / --render-frame";
1346         bContext *C = data;
1347         Scene *scene = CTX_data_scene(C);
1348         if (scene) {
1349                 Main *bmain = CTX_data_main(C);
1350
1351                 if (argc > 1) {
1352                         const char *err_msg = NULL;
1353                         Render *re;
1354                         ReportList reports;
1355
1356                         int (*frame_range_arr)[2], frames_range_len;
1357                         if ((frame_range_arr = parse_int_range_relative_clamp_n(
1358                                  argv[1], scene->r.sfra, scene->r.efra, MINAFRAME, MAXFRAME,
1359                                  &frames_range_len, &err_msg)) == NULL)
1360                         {
1361                                 printf("\nError: %s '%s %s'.\n", err_msg, arg_id, argv[1]);
1362                                 return 1;
1363                         }
1364
1365                         re = RE_NewRender(scene->id.name);
1366                         BLI_begin_threaded_malloc();
1367                         BKE_reports_init(&reports, RPT_STORE);
1368
1369                         RE_SetReports(re, &reports);
1370                         for (int i = 0; i < frames_range_len; i++) {
1371                                 /* We could pass in frame ranges,
1372                                  * but prefer having exact behavior as passing in multiple frames */
1373                                 if ((frame_range_arr[i][0] <= frame_range_arr[i][1]) == 0) {
1374                                         printf("\nWarning: negative range ignored '%s %s'.\n", arg_id, argv[1]);
1375                                 }
1376
1377                                 for (int frame = frame_range_arr[i][0]; frame <= frame_range_arr[i][1]; frame++) {
1378                                         RE_BlenderAnim(re, bmain, scene, NULL, scene->lay, frame, frame, scene->r.frame_step);
1379                                 }
1380                         }
1381                         RE_SetReports(re, NULL);
1382                         BKE_reports_clear(&reports);
1383                         BLI_end_threaded_malloc();
1384                         MEM_freeN(frame_range_arr);
1385                         return 1;
1386                 }
1387                 else {
1388                         printf("\nError: frame number must follow '%s'.\n", arg_id);
1389                         return 0;
1390                 }
1391         }
1392         else {
1393                 printf("\nError: no blend loaded. cannot use '%s'.\n", arg_id);
1394                 return 0;
1395         }
1396 }
1397
1398 static const char arg_handle_render_animation_doc[] =
1399 "\n\tRender frames from start to end (inclusive)"
1400 ;
1401 static int arg_handle_render_animation(int UNUSED(argc), const char **UNUSED(argv), void *data)
1402 {
1403         bContext *C = data;
1404         Scene *scene = CTX_data_scene(C);
1405         if (scene) {
1406                 Main *bmain = CTX_data_main(C);
1407                 Render *re = RE_NewRender(scene->id.name);
1408                 ReportList reports;
1409                 BLI_begin_threaded_malloc();
1410                 BKE_reports_init(&reports, RPT_STORE);
1411                 RE_SetReports(re, &reports);
1412                 RE_BlenderAnim(re, bmain, scene, NULL, scene->lay, scene->r.sfra, scene->r.efra, scene->r.frame_step);
1413                 RE_SetReports(re, NULL);
1414                 BKE_reports_clear(&reports);
1415                 BLI_end_threaded_malloc();
1416         }
1417         else {
1418                 printf("\nError: no blend loaded. cannot use '-a'.\n");
1419         }
1420         return 0;
1421 }
1422
1423 static const char arg_handle_scene_set_doc[] =
1424 "<name>\n"
1425 "\tSet the active scene <name> for rendering"
1426 ;
1427 static int arg_handle_scene_set(int argc, const char **argv, void *data)
1428 {
1429         if (argc > 1) {
1430                 bContext *C = data;
1431                 Scene *scene = BKE_scene_set_name(CTX_data_main(C), argv[1]);
1432                 if (scene) {
1433                         CTX_data_scene_set(C, scene);
1434                 }
1435                 return 1;
1436         }
1437         else {
1438                 printf("\nError: Scene name must follow '-S / --scene'.\n");
1439                 return 0;
1440         }
1441 }
1442
1443 static const char arg_handle_frame_start_set_doc[] =
1444 "<frame>\n"
1445 "\tSet start to frame <frame>, supports +/- for relative frames too."
1446 ;
1447 static int arg_handle_frame_start_set(int argc, const char **argv, void *data)
1448 {
1449         const char *arg_id = "-s / --frame-start";
1450         bContext *C = data;
1451         Scene *scene = CTX_data_scene(C);
1452         if (scene) {
1453                 if (argc > 1) {
1454                         const char *err_msg = NULL;
1455                         if (!parse_int_relative_clamp(
1456                                 argv[1], NULL, scene->r.sfra, scene->r.sfra - 1, MINAFRAME, MAXFRAME,
1457                                 &scene->r.sfra, &err_msg))
1458                         {
1459                                 printf("\nError: %s '%s %s'.\n", err_msg, arg_id, argv[1]);
1460                         }
1461                         return 1;
1462                 }
1463                 else {
1464                         printf("\nError: frame number must follow '%s'.\n", arg_id);
1465                         return 0;
1466                 }
1467         }
1468         else {
1469                 printf("\nError: no blend loaded. cannot use '%s'.\n", arg_id);
1470                 return 0;
1471         }
1472 }
1473
1474 static const char arg_handle_frame_end_set_doc[] =
1475 "<frame>\n"
1476 "\tSet end to frame <frame>, supports +/- for relative frames too."
1477 ;
1478 static int arg_handle_frame_end_set(int argc, const char **argv, void *data)
1479 {
1480         const char *arg_id = "-e / --frame-end";
1481         bContext *C = data;
1482         Scene *scene = CTX_data_scene(C);
1483         if (scene) {
1484                 if (argc > 1) {
1485                         const char *err_msg = NULL;
1486                         if (!parse_int_relative_clamp(
1487                                 argv[1], NULL, scene->r.efra, scene->r.efra - 1, MINAFRAME, MAXFRAME,
1488                                 &scene->r.efra, &err_msg))
1489                         {
1490                                 printf("\nError: %s '%s %s'.\n", err_msg, arg_id, argv[1]);
1491                         }
1492                         return 1;
1493                 }
1494                 else {
1495                         printf("\nError: frame number must follow '%s'.\n", arg_id);
1496                         return 0;
1497                 }
1498         }
1499         else {
1500                 printf("\nError: no blend loaded. cannot use '%s'.\n", arg_id);
1501                 return 0;
1502         }
1503 }
1504
1505 static const char arg_handle_frame_skip_set_doc[] =
1506 "<frames>\n"
1507 "\tSet number of frames to step forward after each rendered frame"
1508 ;
1509 static int arg_handle_frame_skip_set(int argc, const char **argv, void *data)
1510 {
1511         const char *arg_id = "-j / --frame-jump";
1512         bContext *C = data;
1513         Scene *scene = CTX_data_scene(C);
1514         if (scene) {
1515                 if (argc > 1) {
1516                         const char *err_msg = NULL;
1517                         if (!parse_int_clamp(argv[1], NULL, 1, MAXFRAME, &scene->r.frame_step, &err_msg)) {
1518                                 printf("\nError: %s '%s %s'.\n", err_msg, arg_id, argv[1]);
1519                         }
1520                         return 1;
1521                 }
1522                 else {
1523                         printf("\nError: number of frames to step must follow '%s'.\n", arg_id);
1524                         return 0;
1525                 }
1526         }
1527         else {
1528                 printf("\nError: no blend loaded. cannot use '%s'.\n", arg_id);
1529                 return 0;
1530         }
1531 }
1532
1533 static const char arg_handle_python_file_run_doc[] =
1534 "<filename>\n"
1535 "\tRun the given Python script file"
1536 ;
1537 static int arg_handle_python_file_run(int argc, const char **argv, void *data)
1538 {
1539 #ifdef WITH_PYTHON
1540         bContext *C = data;
1541
1542         /* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */
1543         if (argc > 1) {
1544                 /* Make the path absolute because its needed for relative linked blends to be found */
1545                 char filename[FILE_MAX];
1546                 BLI_strncpy(filename, argv[1], sizeof(filename));
1547                 BLI_path_cwd(filename, sizeof(filename));
1548
1549                 bool ok;
1550                 BPY_CTX_SETUP(ok = BPY_execute_filepath(C, filename, NULL));
1551                 if (!ok && app_state.exit_code_on_error.python) {
1552                         printf("\nError: script failed, file: '%s', exiting.\n", argv[1]);
1553                         exit(app_state.exit_code_on_error.python);
1554                 }
1555                 return 1;
1556         }
1557         else {
1558                 printf("\nError: you must specify a filepath after '%s'.\n", argv[0]);
1559                 return 0;
1560         }
1561 #else
1562         UNUSED_VARS(argc, argv, data);
1563         printf("This blender was built without python support\n");
1564         return 0;
1565 #endif /* WITH_PYTHON */
1566 }
1567
1568 static const char arg_handle_python_text_run_doc[] =
1569 "<name>\n"
1570 "\tRun the given Python script text block"
1571 ;
1572 static int arg_handle_python_text_run(int argc, const char **argv, void *data)
1573 {
1574 #ifdef WITH_PYTHON
1575         bContext *C = data;
1576
1577         /* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */
1578         if (argc > 1) {
1579                 /* Make the path absolute because its needed for relative linked blends to be found */
1580                 struct Text *text = (struct Text *)BKE_libblock_find_name(ID_TXT, argv[1]);
1581                 bool ok;
1582
1583                 if (text) {
1584                         BPY_CTX_SETUP(ok = BPY_execute_text(C, text, NULL, false));
1585                 }
1586                 else {
1587                         printf("\nError: text block not found %s.\n", argv[1]);
1588                         ok = false;
1589                 }
1590
1591                 if (!ok && app_state.exit_code_on_error.python) {
1592                         printf("\nError: script failed, text: '%s', exiting.\n", argv[1]);
1593                         exit(app_state.exit_code_on_error.python);
1594                 }
1595
1596                 return 1;
1597         }
1598         else {
1599                 printf("\nError: you must specify a text block after '%s'.\n", argv[0]);
1600                 return 0;
1601         }
1602 #else
1603         UNUSED_VARS(argc, argv, data);
1604         printf("This blender was built without python support\n");
1605         return 0;
1606 #endif /* WITH_PYTHON */
1607 }
1608
1609 static const char arg_handle_python_expr_run_doc[] =
1610 "<expression>\n"
1611 "\tRun the given expression as a Python script"
1612 ;
1613 static int arg_handle_python_expr_run(int argc, const char **argv, void *data)
1614 {
1615 #ifdef WITH_PYTHON
1616         bContext *C = data;
1617
1618         /* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */
1619         if (argc > 1) {
1620                 bool ok;
1621                 BPY_CTX_SETUP(ok = BPY_execute_string_ex(C, argv[1], false));
1622                 if (!ok && app_state.exit_code_on_error.python) {
1623                         printf("\nError: script failed, expr: '%s', exiting.\n", argv[1]);
1624                         exit(app_state.exit_code_on_error.python);
1625                 }
1626                 return 1;
1627         }
1628         else {
1629                 printf("\nError: you must specify a Python expression after '%s'.\n", argv[0]);
1630                 return 0;
1631         }
1632 #else
1633         UNUSED_VARS(argc, argv, data);
1634         printf("This blender was built without python support\n");
1635         return 0;
1636 #endif /* WITH_PYTHON */
1637 }
1638
1639 static const char arg_handle_python_console_run_doc[] =
1640 "\n\tRun blender with an interactive console"
1641 ;
1642 static int arg_handle_python_console_run(int UNUSED(argc), const char **argv, void *data)
1643 {
1644 #ifdef WITH_PYTHON
1645         bContext *C = data;
1646
1647         BPY_CTX_SETUP(BPY_execute_string(C, "__import__('code').interact()"));
1648
1649         return 0;
1650 #else
1651         UNUSED_VARS(argv, data);
1652         printf("This blender was built without python support\n");
1653         return 0;
1654 #endif /* WITH_PYTHON */
1655 }
1656
1657 static const char arg_handle_python_exit_code_set_doc[] =
1658 "\n"
1659 "\tSet the exit-code in [0..255] to exit if a Python exception is raised\n"
1660 "\t(only for scripts executed from the command line), zero disables."
1661 ;
1662 static int arg_handle_python_exit_code_set(int argc, const char **argv, void *UNUSED(data))
1663 {
1664         const char *arg_id = "--python-exit-code";
1665         if (argc > 1) {
1666                 const char *err_msg = NULL;
1667                 const int min = 0, max = 255;
1668                 int exit_code;
1669                 if (!parse_int_strict_range(argv[1], NULL, min, max, &exit_code, &err_msg)) {
1670                         printf("\nError: %s '%s %s', expected number in [%d..%d].\n", err_msg, arg_id, argv[1], min, max);
1671                         return 1;
1672                 }
1673
1674                 app_state.exit_code_on_error.python = (unsigned char)exit_code;
1675                 return 1;
1676         }
1677         else {
1678                 printf("\nError: you must specify an exit code number '%s'.\n", arg_id);
1679                 return 0;
1680         }
1681 }
1682
1683 static const char arg_handle_addons_set_doc[] =
1684 "\n\tComma separated list of add-ons (no spaces)"
1685 ;
1686 static int arg_handle_addons_set(int argc, const char **argv, void *data)
1687 {
1688         /* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */
1689         if (argc > 1) {
1690 #ifdef WITH_PYTHON
1691                 const char script_str[] =
1692                         "from addon_utils import check, enable\n"
1693                         "for m in '%s'.split(','):\n"
1694                         "    if check(m)[1] is False:\n"
1695                         "        enable(m, persistent=True)";
1696                 const int slen = strlen(argv[1]) + (sizeof(script_str) - 2);
1697                 char *str = malloc(slen);
1698                 bContext *C = data;
1699                 BLI_snprintf(str, slen, script_str, argv[1]);
1700
1701                 BLI_assert(strlen(str) + 1 == slen);
1702                 BPY_CTX_SETUP(BPY_execute_string_ex(C, str, false));
1703                 free(str);
1704 #else
1705                 UNUSED_VARS(argv, data);
1706 #endif /* WITH_PYTHON */
1707                 return 1;
1708         }
1709         else {
1710                 printf("\nError: you must specify a comma separated list after '--addons'.\n");
1711                 return 0;
1712         }
1713 }
1714
1715 static int arg_handle_load_file(int UNUSED(argc), const char **argv, void *data)
1716 {
1717         bContext *C = data;
1718         ReportList reports;
1719         bool success;
1720
1721         /* Make the path absolute because its needed for relative linked blends to be found */
1722         char filename[FILE_MAX];
1723
1724         /* note, we could skip these, but so far we always tried to load these files */
1725         if (argv[0][0] == '-') {
1726                 fprintf(stderr, "unknown argument, loading as file: %s\n", argv[0]);
1727         }
1728
1729         BLI_strncpy(filename, argv[0], sizeof(filename));
1730         BLI_path_cwd(filename, sizeof(filename));
1731
1732         /* load the file */
1733         BKE_reports_init(&reports, RPT_PRINT);
1734         WM_file_autoexec_init(filename);
1735         success = WM_file_read(C, filename, &reports);
1736         BKE_reports_clear(&reports);
1737
1738         if (success) {
1739                 if (G.background) {
1740                         /* ensuer we use 'C->data.scene' for background render */
1741                         CTX_wm_window_set(C, NULL);
1742                 }
1743         }
1744         else {
1745                 /* failed to load file, stop processing arguments if running in background mode */
1746                 if (G.background) {
1747                         /* Set is_break if running in the background mode so
1748                          * blender will return non-zero exit code which then
1749                          * could be used in automated script to control how
1750                          * good or bad things are.
1751                          */
1752                         G.is_break = true;
1753                         return -1;
1754                 }
1755
1756                 /* Just pretend a file was loaded, so the user can press Save and it'll save at the filename from the CLI. */
1757                 BLI_strncpy(G.main->name, filename, FILE_MAX);
1758                 G.relbase_valid = true;
1759                 G.save_over = true;
1760                 printf("... opened default scene instead; saving will write to %s\n", filename);
1761         }
1762
1763         G.file_loaded = 1;
1764
1765         return 0;
1766 }
1767
1768
1769 void main_args_setup(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
1770 {
1771
1772 #define CB(a) a##_doc, a
1773 #define CB_EX(a, b) a##_doc_##b, a
1774
1775         //BLI_argsAdd(ba, pass, short_arg, long_arg, doc, cb, C);
1776
1777         /* end argument processing after -- */
1778         BLI_argsAdd(ba, -1, "--", NULL, CB(arg_handle_arguments_end), NULL);
1779
1780         /* first pass: background mode, disable python and commands that exit after usage */
1781         BLI_argsAdd(ba, 1, "-h", "--help", CB(arg_handle_print_help), ba);
1782         /* Windows only */
1783         BLI_argsAdd(ba, 1, "/?", NULL, CB_EX(arg_handle_print_help, win32), ba);
1784
1785         BLI_argsAdd(ba, 1, "-v", "--version", CB(arg_handle_print_version), NULL);
1786
1787         BLI_argsAdd(ba, 1, "-y", "--enable-autoexec", CB_EX(arg_handle_python_set, enable), (void *)true);
1788         BLI_argsAdd(ba, 1, "-Y", "--disable-autoexec", CB_EX(arg_handle_python_set, disable), (void *)false);
1789
1790         BLI_argsAdd(ba, 1, NULL, "--disable-crash-handler", CB(arg_handle_crash_handler_disable), NULL);
1791         BLI_argsAdd(ba, 1, NULL, "--disable-abort-handler", CB(arg_handle_abort_handler_disable), NULL);
1792
1793         BLI_argsAdd(ba, 1, "-b", "--background", CB(arg_handle_background_mode_set), NULL);
1794
1795         BLI_argsAdd(ba, 1, "-a", NULL, CB(arg_handle_playback_mode), NULL);
1796
1797         BLI_argsAdd(ba, 1, "-d", "--debug", CB(arg_handle_debug_mode_set), ba);
1798
1799 #ifdef WITH_FFMPEG
1800         BLI_argsAdd(ba, 1, NULL, "--debug-ffmpeg",
1801                     CB_EX(arg_handle_debug_mode_generic_set, ffmpeg), (void *)G_DEBUG_FFMPEG);
1802 #endif
1803
1804 #ifdef WITH_FREESTYLE
1805         BLI_argsAdd(ba, 1, NULL, "--debug-freestyle",
1806                     CB_EX(arg_handle_debug_mode_generic_set, freestyle), (void *)G_DEBUG_FREESTYLE);
1807 #endif
1808
1809         BLI_argsAdd(ba, 1, NULL, "--debug-python",
1810                     CB_EX(arg_handle_debug_mode_generic_set, python), (void *)G_DEBUG_PYTHON);
1811         BLI_argsAdd(ba, 1, NULL, "--debug-events",
1812                     CB_EX(arg_handle_debug_mode_generic_set, events), (void *)G_DEBUG_EVENTS);
1813         BLI_argsAdd(ba, 1, NULL, "--debug-handlers",
1814                     CB_EX(arg_handle_debug_mode_generic_set, handlers), (void *)G_DEBUG_HANDLERS);
1815         BLI_argsAdd(ba, 1, NULL, "--debug-wm",
1816                     CB_EX(arg_handle_debug_mode_generic_set, wm), (void *)G_DEBUG_WM);
1817         BLI_argsAdd(ba, 1, NULL, "--debug-all", CB(arg_handle_debug_mode_all), NULL);
1818
1819         BLI_argsAdd(ba, 1, NULL, "--debug-io", CB(arg_handle_debug_mode_io), NULL);
1820
1821         BLI_argsAdd(ba, 1, NULL, "--debug-fpe",
1822                     CB(arg_handle_debug_fpe_set), NULL);
1823
1824 #ifdef WITH_LIBMV
1825         BLI_argsAdd(ba, 1, NULL, "--debug-libmv", CB(arg_handle_debug_mode_libmv), NULL);
1826 #endif
1827 #ifdef WITH_CYCLES_LOGGING
1828         BLI_argsAdd(ba, 1, NULL, "--debug-cycles", CB(arg_handle_debug_mode_cycles), NULL);
1829 #endif
1830         BLI_argsAdd(ba, 1, NULL, "--debug-memory", CB(arg_handle_debug_mode_memory_set), NULL);
1831
1832         BLI_argsAdd(ba, 1, NULL, "--debug-value",
1833                     CB(arg_handle_debug_value_set), NULL);
1834         BLI_argsAdd(ba, 1, NULL, "--debug-jobs",
1835                     CB_EX(arg_handle_debug_mode_generic_set, jobs), (void *)G_DEBUG_JOBS);
1836         BLI_argsAdd(ba, 1, NULL, "--debug-gpu",
1837                     CB_EX(arg_handle_debug_mode_generic_set, gpu), (void *)G_DEBUG_GPU);
1838         BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph",
1839                     CB_EX(arg_handle_debug_mode_generic_set, depsgraph), (void *)G_DEBUG_DEPSGRAPH);
1840         BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph-no-threads",
1841                     CB_EX(arg_handle_debug_mode_generic_set, depsgraph_no_threads), (void *)G_DEBUG_DEPSGRAPH_NO_THREADS);
1842         BLI_argsAdd(ba, 1, NULL, "--debug-gpumem",
1843                     CB_EX(arg_handle_debug_mode_generic_set, gpumem), (void *)G_DEBUG_GPU_MEM);
1844
1845         BLI_argsAdd(ba, 1, NULL, "--enable-new-depsgraph", CB(arg_handle_depsgraph_use_new), NULL);
1846         BLI_argsAdd(ba, 1, NULL, "--enable-new-basic-shader-glsl", CB(arg_handle_basic_shader_glsl_use_new), NULL);
1847
1848         BLI_argsAdd(ba, 1, NULL, "--verbose", CB(arg_handle_verbosity_set), NULL);
1849
1850         BLI_argsAdd(ba, 1, NULL, "--factory-startup", CB(arg_handle_factory_startup_set), NULL);
1851
1852         /* TODO, add user env vars? */
1853         BLI_argsAdd(ba, 1, NULL, "--env-system-datafiles", CB_EX(arg_handle_env_system_set, datafiles), NULL);
1854         BLI_argsAdd(ba, 1, NULL, "--env-system-scripts", CB_EX(arg_handle_env_system_set, scripts), NULL);
1855         BLI_argsAdd(ba, 1, NULL, "--env-system-python", CB_EX(arg_handle_env_system_set, python), NULL);
1856
1857         /* second pass: custom window stuff */
1858         BLI_argsAdd(ba, 2, "-p", "--window-geometry", CB(arg_handle_window_geometry), NULL);
1859         BLI_argsAdd(ba, 2, "-w", "--window-border", CB(arg_handle_with_borders), NULL);
1860         BLI_argsAdd(ba, 2, "-W", "--window-borderless", CB(arg_handle_without_borders), NULL);
1861         BLI_argsAdd(ba, 2, "-con", "--start-console", CB(arg_handle_start_with_console), NULL);
1862         BLI_argsAdd(ba, 2, "-R", NULL, CB(arg_handle_register_extension), NULL);
1863         BLI_argsAdd(ba, 2, "-r", NULL, CB_EX(arg_handle_register_extension, silent), ba);
1864         BLI_argsAdd(ba, 2, NULL, "--no-native-pixels", CB(arg_handle_native_pixels_set), ba);
1865
1866         /* third pass: disabling things and forcing settings */
1867         BLI_argsAddCase(ba, 3, "-nojoystick", 1, NULL, 0, CB(arg_handle_joystick_disable), syshandle);
1868         BLI_argsAddCase(ba, 3, "-noglsl", 1, NULL, 0, CB(arg_handle_glsl_disable), NULL);
1869         BLI_argsAddCase(ba, 3, "-noaudio", 1, NULL, 0, CB(arg_handle_audio_disable), NULL);
1870         BLI_argsAddCase(ba, 3, "-setaudio", 1, NULL, 0, CB(arg_handle_audio_set), NULL);
1871
1872         /* fourth pass: processing arguments */
1873         BLI_argsAdd(ba, 4, "-g", NULL, CB(arg_handle_ge_parameters_set), syshandle);
1874         BLI_argsAdd(ba, 4, "-f", "--render-frame", CB(arg_handle_render_frame), C);
1875         BLI_argsAdd(ba, 4, "-a", "--render-anim", CB(arg_handle_render_animation), C);
1876         BLI_argsAdd(ba, 4, "-S", "--scene", CB(arg_handle_scene_set), C);
1877         BLI_argsAdd(ba, 4, "-s", "--frame-start", CB(arg_handle_frame_start_set), C);
1878         BLI_argsAdd(ba, 4, "-e", "--frame-end", CB(arg_handle_frame_end_set), C);
1879         BLI_argsAdd(ba, 4, "-j", "--frame-jump", CB(arg_handle_frame_skip_set), C);
1880         BLI_argsAdd(ba, 4, "-P", "--python", CB(arg_handle_python_file_run), C);
1881         BLI_argsAdd(ba, 4, NULL, "--python-text", CB(arg_handle_python_text_run), C);
1882         BLI_argsAdd(ba, 4, NULL, "--python-expr", CB(arg_handle_python_expr_run), C);
1883         BLI_argsAdd(ba, 4, NULL, "--python-console", CB(arg_handle_python_console_run), C);
1884         BLI_argsAdd(ba, 4, NULL, "--python-exit-code", CB(arg_handle_python_exit_code_set), NULL);
1885         BLI_argsAdd(ba, 4, NULL, "--addons", CB(arg_handle_addons_set), C);
1886
1887         BLI_argsAdd(ba, 4, "-o", "--render-output", CB(arg_handle_output_set), C);
1888         BLI_argsAdd(ba, 4, "-E", "--engine", CB(arg_handle_engine_set), C);
1889
1890         BLI_argsAdd(ba, 4, "-F", "--render-format", CB(arg_handle_image_type_set), C);
1891         BLI_argsAdd(ba, 1, "-t", "--threads", CB(arg_handle_threads_set), NULL);
1892         BLI_argsAdd(ba, 4, "-x", "--use-extension", CB(arg_handle_extension_set), C);
1893
1894 #undef CB
1895 #undef CB_EX
1896
1897 }
1898
1899 /**
1900  * Needs to be added separately.
1901  */
1902 void main_args_setup_post(bContext *C, bArgs *ba)
1903 {
1904         BLI_argsParse(ba, 4, arg_handle_load_file, C);
1905 }
1906
1907 /** \} */
1908
1909 #endif /* WITH_PYTHON_MODULE */