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