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