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