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