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