bugfix [#25208] randomize transform doesn't work on objects with keyframes
[blender-staging.git] / source / creator / creator.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #if defined(__linux__) && defined(__GNUC__)
31 #define _GNU_SOURCE
32 #include <fenv.h>
33 #endif
34
35 #define OSX_SSE_FPE (defined(__APPLE__) && (defined(__i386__) || defined(__x86_64__)))
36
37 #if OSX_SSE_FPE
38 #include <xmmintrin.h>
39 #endif
40
41 #include <stdlib.h>
42 #include <string.h>
43
44 /* for setuid / getuid */
45 #ifdef __sgi
46 #include <sys/types.h>
47 #include <unistd.h>
48 #endif
49
50 /* This little block needed for linking to Blender... */
51
52 #include "MEM_guardedalloc.h"
53
54 #ifdef WIN32
55 #include "BLI_winstuff.h"
56 #endif
57
58 #include "BLI_args.h"
59 #include "BLI_threads.h"
60 #include "BLI_scanfill.h" // for BLI_setErrorCallBack, TODO, move elsewhere
61
62 #include "DNA_ID.h"
63 #include "DNA_scene_types.h"
64
65 #include "BLI_blenlib.h"
66
67 #include "BKE_utildefines.h"
68 #include "BKE_blender.h"
69 #include "BKE_context.h"
70 #include "BKE_font.h"
71 #include "BKE_global.h"
72 #include "BKE_main.h"
73 #include "BKE_material.h"
74 #include "BKE_packedFile.h"
75 #include "BKE_scene.h"
76 #include "BKE_node.h"
77 #include "BKE_report.h"
78 #include "BKE_sound.h"
79
80 #include "IMB_imbuf.h"  // for IMB_init
81
82 #ifdef WITH_PYTHON
83 #include "BPY_extern.h"
84 #endif
85
86 #include "RE_pipeline.h"
87
88 //XXX #include "playanim_ext.h"
89 #include "ED_datafiles.h"
90
91 #include "WM_api.h"
92
93 #include "RNA_define.h"
94
95 #include "GPU_draw.h"
96 #include "GPU_extensions.h"
97
98 /* for passing information between creator and gameengine */
99 #ifdef WITH_GAMEENGINE
100 #include "GEN_messaging.h"
101 #include "SYS_System.h"
102 #else /* dummy */
103 #define SYS_SystemHandle int
104 #endif
105
106 #include <signal.h>
107
108 #ifdef __FreeBSD__
109 # include <sys/types.h>
110 # include <floatingpoint.h>
111 # include <sys/rtprio.h>
112 #endif
113
114 #ifdef WITH_BINRELOC
115 #include "binreloc.h"
116 #endif
117
118 // from buildinfo.c
119 #ifdef BUILD_DATE
120 extern char build_date[];
121 extern char build_time[];
122 extern char build_rev[];
123 extern char build_platform[];
124 extern char build_type[];
125 extern char build_cflags[];
126 extern char build_cxxflags[];
127 extern char build_linkflags[];
128 extern char build_system[];
129 #endif
130
131 /*      Local Function prototypes */
132 static int print_help(int argc, char **argv, void *data);
133 static int print_version(int argc, char **argv, void *data);
134
135 /* for the callbacks: */
136
137 extern int pluginapi_force_ref(void);  /* from blenpluginapi:pluginapi.c */
138
139 char bprogname[FILE_MAXDIR+FILE_MAXFILE]; /* from blenpluginapi:pluginapi.c */
140 char btempdir[FILE_MAXDIR+FILE_MAXFILE];
141
142 #define BLEND_VERSION_STRING_FMT "Blender %d.%02d (sub %d) Build\n", BLENDER_VERSION/100, BLENDER_VERSION%100, BLENDER_SUBVERSION
143
144 /* Initialise callbacks for the modules that need them */
145 static void setCallbacks(void); 
146
147 /* set breakpoints here when running in debug mode, useful to catch floating point errors */
148 #if defined(__sgi) || defined(__linux__) || defined(_WIN32) || OSX_SSE_FPE
149 static void fpe_handler(int UNUSED(sig))
150 {
151         // printf("SIGFPE trapped\n");
152 }
153 #endif
154
155 /* handling ctrl-c event in console */
156 static void blender_esc(int sig)
157 {
158         static int count = 0;
159         
160         G.afbreek = 1;  /* forces render loop to read queue, not sure if its needed */
161         
162         if (sig == 2) {
163                 if (count) {
164                         printf("\nBlender killed\n");
165                         exit(2);
166                 }
167                 printf("\nSent an internal break event. Press ^C again to kill Blender\n");
168                 count++;
169         }
170 }
171
172 /* buildinfo can have quotes */
173 #ifdef BUILD_DATE
174 static void strip_quotes(char *str)
175 {
176     if(str[0] == '"') {
177         int len= strlen(str) - 1;
178         memmove(str, str+1, len);
179         if(str[len-1] == '"') {
180             str[len-1]= '\0';
181         }
182     }
183 }
184 #endif
185
186 static int print_version(int UNUSED(argc), char **UNUSED(argv), void *UNUSED(data))
187 {
188         printf (BLEND_VERSION_STRING_FMT);
189 #ifdef BUILD_DATE
190         printf ("\tbuild date: %s\n", build_date);
191         printf ("\tbuild time: %s\n", build_time);
192         printf ("\tbuild revision: %s\n", build_rev);
193         printf ("\tbuild platform: %s\n", build_platform);
194         printf ("\tbuild type: %s\n", build_type);
195         printf ("\tbuild c flags: %s\n", build_cflags);
196         printf ("\tbuild c++ flags: %s\n", build_cxxflags);
197         printf ("\tbuild link flags: %s\n", build_linkflags);
198         printf ("\tbuild system: %s\n", build_system);
199 #endif
200         exit(0);
201
202         return 0;
203 }
204
205 static int print_help(int UNUSED(argc), char **UNUSED(argv), void *data)
206 {
207         bArgs *ba = (bArgs*)data;
208
209         printf (BLEND_VERSION_STRING_FMT);
210         printf ("Usage: blender [args ...] [file] [args ...]\n\n");
211
212         printf ("Render Options:\n");
213         BLI_argsPrintArgDoc(ba, "--background");
214         BLI_argsPrintArgDoc(ba, "--render-anim");
215         BLI_argsPrintArgDoc(ba, "--scene");
216         BLI_argsPrintArgDoc(ba, "--render-frame");
217         BLI_argsPrintArgDoc(ba, "--frame-start");
218         BLI_argsPrintArgDoc(ba, "--frame-end");
219         BLI_argsPrintArgDoc(ba, "--frame-jump");
220         BLI_argsPrintArgDoc(ba, "--render-output");
221         BLI_argsPrintArgDoc(ba, "--engine");
222         
223         printf("\n");
224         printf ("Format Options:\n");
225         BLI_argsPrintArgDoc(ba, "--render-format");
226         BLI_argsPrintArgDoc(ba, "--use-extension");
227         BLI_argsPrintArgDoc(ba, "--threads");
228
229         printf("\n");
230         printf ("Animation Playback Options:\n");
231         BLI_argsPrintArgDoc(ba, "-a");
232                                 
233         printf("\n");
234         printf ("Window Options:\n");
235         BLI_argsPrintArgDoc(ba, "--window-border");
236         BLI_argsPrintArgDoc(ba, "--window-borderless");
237         BLI_argsPrintArgDoc(ba, "--window-geometry");
238
239         printf("\n");
240         printf ("Game Engine Specific Options:\n");
241         BLI_argsPrintArgDoc(ba, "-g");
242
243         printf("\n");
244         printf ("Misc Options:\n");
245         BLI_argsPrintArgDoc(ba, "--debug");
246         BLI_argsPrintArgDoc(ba, "--debug-fpe");
247
248         printf("\n");
249
250         BLI_argsPrintArgDoc(ba, "-nojoystick");
251         BLI_argsPrintArgDoc(ba, "-noglsl");
252         BLI_argsPrintArgDoc(ba, "-noaudio");
253         BLI_argsPrintArgDoc(ba, "-setaudio");
254
255         printf("\n");
256
257         BLI_argsPrintArgDoc(ba, "--help");
258
259         printf("\n");
260
261         BLI_argsPrintArgDoc(ba, "--enable-autoexec");
262         BLI_argsPrintArgDoc(ba, "--disable-autoexec");
263
264         printf("\n");
265
266         BLI_argsPrintArgDoc(ba, "--python");
267         BLI_argsPrintArgDoc(ba, "--python-console");
268
269 #ifdef WIN32
270         BLI_argsPrintArgDoc(ba, "-R");
271 #endif
272         BLI_argsPrintArgDoc(ba, "--version");
273
274         BLI_argsPrintArgDoc(ba, "--");
275
276         printf ("Other Options:\n");
277         BLI_argsPrintOtherDoc(ba);
278
279         printf ("Argument Parsing:\n");
280         printf ("\targuments must be separated by white space. eg\n");
281         printf ("\t\t\"blender -ba test.blend\"\n");
282         printf ("\t...will ignore the 'a'\n");
283         printf ("\t\t\"blender -b test.blend -f8\"\n");
284         printf ("\t...will ignore 8 because there is no space between the -f and the frame value\n\n");
285
286         printf ("Argument Order:\n");
287         printf ("Arguments are executed in the order they are given. eg\n");
288         printf ("\t\t\"blender --background test.blend --render-frame 1 --render-output /tmp\"\n");
289         printf ("\t...will not render to /tmp because '--render-frame 1' renders before the output path is set\n");
290         printf ("\t\t\"blender --background --render-output /tmp test.blend --render-frame 1\"\n");
291         printf ("\t...will not render to /tmp because loading the blend file overwrites the render output that was set\n");
292         printf ("\t\t\"blender --background test.blend --render-output /tmp --render-frame 1\" works as expected.\n\n");
293
294         printf ("\nEnvironment Variables:\n");
295         printf ("  $BLENDER_USER_CONFIG      Directory for user configuration files.\n");
296         printf ("  $BLENDER_SYSTEM_CONFIG    Directory for system wide configuration files.\n");
297         printf ("  $BLENDER_USER_SCRIPTS     Directory for user scripts.\n");
298         printf ("  $BLENDER_SYSTEM_SCRIPTS   Directory for system wide scripts.\n");
299         printf ("  $BLENDER_USER_DATAFILES   Directory for user data files (icons, translations, ..).\n");
300         printf ("  $BLENDER_SYSTEM_DATAFILES Directory for system wide data files.\n");
301         printf ("  $BLENDER_SYSTEM_PYTHON    Directory for system python libraries.\n");
302 #ifdef WIN32
303         printf ("  $TEMP                     Store temporary files here.\n");
304 #else
305         printf ("  $TMP or $TMPDIR           Store temporary files here.\n");
306 #endif
307 #ifndef DISABLE_SDL
308         printf ("  $SDL_AUDIODRIVER          LibSDL audio driver - alsa, esd, dma.\n");
309 #endif
310         printf ("  $PYTHONHOME               Path to the python directory, eg. /usr/lib/python.\n\n");
311
312         exit(0);
313
314         return 0;
315 }
316
317
318 double PIL_check_seconds_timer(void);
319
320 /* XXX This was here to fix a crash when running python scripts
321  * with -P that used the screen.
322  *
323  * static void main_init_screen( void )
324 {
325         setscreen(G.curscreen);
326         
327         if(G.main->scene.first==0) {
328                 set_scene( add_scene("1") );
329         }
330 }*/
331
332 static int end_arguments(int UNUSED(argc), char **UNUSED(argv), void *UNUSED(data))
333 {
334         return -1;
335 }
336
337 static int enable_python(int UNUSED(argc), char **UNUSED(argv), void *UNUSED(data))
338 {
339         G.f |= G_SCRIPT_AUTOEXEC;
340         return 0;
341 }
342
343 static int disable_python(int UNUSED(argc), char **UNUSED(argv), void *UNUSED(data))
344 {
345         G.f &= ~G_SCRIPT_AUTOEXEC;
346         return 0;
347 }
348
349 static int background_mode(int UNUSED(argc), char **UNUSED(argv), void *UNUSED(data))
350 {
351         G.background = 1;
352         return 0;
353 }
354
355 static int debug_mode(int UNUSED(argc), char **UNUSED(argv), void *data)
356 {
357         G.f |= G_DEBUG;         /* std output printf's */
358         printf(BLEND_VERSION_STRING_FMT);
359         MEM_set_memory_debug();
360
361 #ifdef NAN_BUILDINFO
362         printf("Build: %s %s %s %s\n", build_date, build_time, build_platform, build_type);
363 #endif // NAN_BUILDINFO
364
365         BLI_argsPrint(data);
366         return 0;
367 }
368
369 static int set_fpe(int UNUSED(argc), char **UNUSED(argv), void *UNUSED(data))
370 {
371 #if defined(__sgi) || defined(__linux__) || defined(_WIN32) || OSX_SSE_FPE
372         /* zealous but makes float issues a heck of a lot easier to find!
373          * set breakpoints on fpe_handler */
374         signal(SIGFPE, fpe_handler);
375
376 # if defined(__linux__) && defined(__GNUC__)
377         feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW );
378 # endif /* defined(__linux__) && defined(__GNUC__) */
379 # if OSX_SSE_FPE
380         /* OSX uses SSE for floating point by default, so here 
381          * use SSE instructions to throw floating point exceptions */
382         _MM_SET_EXCEPTION_MASK(_MM_MASK_MASK &~
383                                                    (_MM_MASK_OVERFLOW|_MM_MASK_INVALID|_MM_MASK_DIV_ZERO));
384 # endif /* OSX_SSE_FPE */
385 # if defined(_WIN32) && defined(_MSC_VER)
386         _controlfp_s(NULL, 0, _MCW_EM); /* enables all fp exceptions */
387         _controlfp_s(NULL, _EM_DENORMAL | _EM_UNDERFLOW | _EM_INEXACT, _MCW_EM); /* hide the ones we don't care about */
388 # endif /* _WIN32 && _MSC_VER */
389 #endif
390
391         return 0;
392 }
393
394 static int playback_mode(int UNUSED(argc), char **UNUSED(argv), void *UNUSED(data))
395 {
396         /* not if -b was given first */
397         if (G.background == 0) {
398
399 // XXX                          playanim(argc, argv); /* not the same argc and argv as before */
400                 exit(0);
401         }
402
403         return -2;
404 }
405
406 static int prefsize(int argc, char **argv, void *UNUSED(data))
407 {
408         int stax, stay, sizx, sizy;
409
410         if (argc < 5) {
411                 printf ("-p requires four arguments\n");
412                 exit(1);
413         }
414
415         stax= atoi(argv[1]);
416         stay= atoi(argv[2]);
417         sizx= atoi(argv[3]);
418         sizy= atoi(argv[4]);
419
420         WM_setprefsize(stax, stay, sizx, sizy);
421
422         return 4;
423 }
424
425 static int with_borders(int UNUSED(argc), char **UNUSED(argv), void *UNUSED(data))
426 {
427         WM_setinitialstate_normal();
428         return 0;
429 }
430
431 static int without_borders(int UNUSED(argc), char **UNUSED(argv), void *UNUSED(data))
432 {
433         WM_setinitialstate_fullscreen();
434         return 0;
435 }
436
437 static int register_extension(int UNUSED(argc), char **UNUSED(argv), void *data)
438 {
439 #ifdef WIN32
440         char *path = BLI_argsArgv(data)[0];
441         RegisterBlendExtension(path);
442 #else
443         (void)data; /* unused */
444 #endif
445
446         return 0;
447 }
448
449 static int no_joystick(int UNUSED(argc), char **UNUSED(argv), void *data)
450 {
451 #ifndef WITH_GAMEENGINE
452         (void)data;
453 #else
454         SYS_SystemHandle *syshandle = data;
455
456         /**
457                 don't initialize joysticks if user doesn't want to use joysticks
458                 failed joystick initialization delays over 5 seconds, before game engine start
459         */
460         SYS_WriteCommandLineInt(*syshandle, "nojoystick",1);
461         if (G.f & G_DEBUG) printf("disabling nojoystick\n");
462 #endif
463
464         return 0;
465 }
466
467 static int no_glsl(int UNUSED(argc), char **UNUSED(argv), void *UNUSED(data))
468 {
469         GPU_extensions_disable();
470         return 0;
471 }
472
473 static int no_audio(int UNUSED(argc), char **UNUSED(argv), void *UNUSED(data))
474 {
475         sound_force_device(0);
476         return 0;
477 }
478
479 static int set_audio(int argc, char **argv, void *UNUSED(data))
480 {
481         if (argc < 1) {
482                 printf("-setaudio require one argument\n");
483                 exit(1);
484         }
485
486         sound_force_device(sound_define_from_str(argv[1]));
487         return 1;
488 }
489
490 static int set_output(int argc, char **argv, void *data)
491 {
492         bContext *C = data;
493         if (argc >= 1){
494                 if (CTX_data_scene(C)) {
495                         Scene *scene= CTX_data_scene(C);
496                         BLI_strncpy(scene->r.pic, argv[1], FILE_MAXDIR);
497                 } else {
498                         printf("\nError: no blend loaded. cannot use '-o / --render-output'.\n");
499                 }
500                 return 1;
501         } else {
502                 printf("\nError: you must specify a path after '-o  / --render-output'.\n");
503                 return 0;
504         }
505 }
506
507 static int set_engine(int argc, char **argv, void *data)
508 {
509         bContext *C = data;
510         if (argc >= 1)
511         {
512                 if (!strcmp(argv[1],"help"))
513                 {
514                         RenderEngineType *type = NULL;
515
516                         for( type = R_engines.first; type; type = type->next )
517                         {
518                                 printf("\t%s\n", type->idname);
519                         }
520                         exit(0);
521                 }
522                 else
523                 {
524                         if (CTX_data_scene(C)==NULL)
525                         {
526                                 printf("\nError: no blend loaded. order the arguments so '-E  / --engine ' is after a blend is loaded.\n");
527                         }
528                         else
529                         {
530                                 Scene *scene= CTX_data_scene(C);
531                                 RenderData *rd = &scene->r;
532                                 RenderEngineType *type = NULL;
533
534                                 for( type = R_engines.first; type; type = type->next )
535                                 {
536                                         if (!strcmp(argv[1],type->idname))
537                                         {
538                                                 BLI_strncpy(rd->engine, type->idname, sizeof(rd->engine));
539                                         }
540                                 }
541                         }
542                 }
543
544                 return 1;
545         }
546         else
547         {
548                 printf("\nEngine not specified.\n");
549                 return 0;
550         }
551 }
552
553 static int set_image_type(int argc, char **argv, void *data)
554 {
555         bContext *C = data;
556         if (argc >= 1){
557                 char *imtype = argv[1];
558                 if (CTX_data_scene(C)==NULL) {
559                         printf("\nError: no blend loaded. order the arguments so '-F  / --render-format' is after the blend is loaded.\n");
560                 } else {
561                         Scene *scene= CTX_data_scene(C);
562                         if      (!strcmp(imtype,"TGA")) scene->r.imtype = R_TARGA;
563                         else if (!strcmp(imtype,"IRIS")) scene->r.imtype = R_IRIS;
564 #ifdef WITH_DDS
565                         else if (!strcmp(imtype,"DDS")) scene->r.imtype = R_DDS;
566 #endif
567                         else if (!strcmp(imtype,"JPEG")) scene->r.imtype = R_JPEG90;
568                         else if (!strcmp(imtype,"IRIZ")) scene->r.imtype = R_IRIZ;
569                         else if (!strcmp(imtype,"RAWTGA")) scene->r.imtype = R_RAWTGA;
570                         else if (!strcmp(imtype,"AVIRAW")) scene->r.imtype = R_AVIRAW;
571                         else if (!strcmp(imtype,"AVIJPEG")) scene->r.imtype = R_AVIJPEG;
572                         else if (!strcmp(imtype,"PNG")) scene->r.imtype = R_PNG;
573                         else if (!strcmp(imtype,"AVICODEC")) scene->r.imtype = R_AVICODEC;
574                         else if (!strcmp(imtype,"QUICKTIME")) scene->r.imtype = R_QUICKTIME;
575                         else if (!strcmp(imtype,"BMP")) scene->r.imtype = R_BMP;
576 #ifdef WITH_HDR
577                         else if (!strcmp(imtype,"HDR")) scene->r.imtype = R_RADHDR;
578 #endif
579 #ifdef WITH_TIFF
580                         else if (!strcmp(imtype,"TIFF")) scene->r.imtype = R_TIFF;
581 #endif
582 #ifdef WITH_OPENEXR
583                         else if (!strcmp(imtype,"EXR")) scene->r.imtype = R_OPENEXR;
584                         else if (!strcmp(imtype,"MULTILAYER")) scene->r.imtype = R_MULTILAYER;
585 #endif
586                         else if (!strcmp(imtype,"MPEG")) scene->r.imtype = R_FFMPEG;
587                         else if (!strcmp(imtype,"FRAMESERVER")) scene->r.imtype = R_FRAMESERVER;
588 #ifdef WITH_CINEON
589                         else if (!strcmp(imtype,"CINEON")) scene->r.imtype = R_CINEON;
590                         else if (!strcmp(imtype,"DPX")) scene->r.imtype = R_DPX;
591 #endif
592 #if WITH_OPENJPEG
593                         else if (!strcmp(imtype,"JP2")) scene->r.imtype = R_JP2;
594 #endif
595                         else printf("\nError: Format from '-F / --render-format' not known or not compiled in this release.\n");
596                 }
597                 return 1;
598         } else {
599                 printf("\nError: you must specify a format after '-F  / --render-foramt'.\n");
600                 return 0;
601         }
602 }
603
604 static int set_threads(int argc, char **argv, void *UNUSED(data))
605 {
606         if (argc >= 1) {
607                 if(G.background) {
608                         RE_set_max_threads(atoi(argv[1]));
609                 } else {
610                         printf("Warning: threads can only be set in background mode\n");
611                 }
612                 return 1;
613         } else {
614                 printf("\nError: you must specify a number of threads between 0 and 8 '-t  / --threads'.\n");
615                 return 0;
616         }
617 }
618
619 static int set_extension(int argc, char **argv, void *data)
620 {
621         bContext *C = data;
622         if (argc >= 1) {
623                 if (CTX_data_scene(C)) {
624                         Scene *scene= CTX_data_scene(C);
625                         if (argv[1][0] == '0') {
626                                 scene->r.scemode &= ~R_EXTENSION;
627                         } else if (argv[1][0] == '1') {
628                                 scene->r.scemode |= R_EXTENSION;
629                         } else {
630                                 printf("\nError: Use '-x 1 / -x 0' To set the extension option or '--use-extension'\n");
631                         }
632                 } else {
633                         printf("\nError: no blend loaded. order the arguments so '-o ' is after '-x '.\n");
634                 }
635                 return 1;
636         } else {
637                 printf("\nError: you must specify a path after '- '.\n");
638                 return 0;
639         }
640 }
641
642 static int set_ge_parameters(int argc, char **argv, void *data)
643 {
644         int a = 0;
645 #ifdef WITH_GAMEENGINE
646         SYS_SystemHandle syshandle = *(SYS_SystemHandle*)data;
647 #else
648         (void)data;
649 #endif
650
651 /**
652 gameengine parameters are automaticly put into system
653 -g [paramname = value]
654 -g [boolparamname]
655 example:
656 -g novertexarrays
657 -g maxvertexarraysize = 512
658 */
659
660         if(argc >= 1)
661         {
662                 char* paramname = argv[a];
663                 /* check for single value versus assignment */
664                 if (a+1 < argc && (*(argv[a+1]) == '='))
665                 {
666                         a++;
667                         if (a+1 < argc)
668                         {
669                                 a++;
670                                 /* assignment */
671 #ifdef WITH_GAMEENGINE
672                                 SYS_WriteCommandLineString(syshandle,paramname,argv[a]);
673 #endif
674                         }  else
675                         {
676                                 printf("error: argument assignment (%s) without value.\n",paramname);
677                                 return 0;
678                         }
679                         /* name arg eaten */
680
681                 } else {
682 #ifdef WITH_GAMEENGINE
683                         SYS_WriteCommandLineInt(syshandle,argv[a],1);
684 #endif
685                         /* doMipMap */
686                         if (!strcmp(argv[a],"nomipmap"))
687                         {
688                                 GPU_set_mipmap(0); //doMipMap = 0;
689                         }
690                         /* linearMipMap */
691                         if (!strcmp(argv[a],"linearmipmap"))
692                         {
693                                 GPU_set_linear_mipmap(1); //linearMipMap = 1;
694                         }
695
696
697                 } /* if (*(argv[a+1]) == '=') */
698         }
699
700         return a;
701 }
702
703 static int render_frame(int argc, char **argv, void *data)
704 {
705         bContext *C = data;
706         if (CTX_data_scene(C)) {
707                 Main *bmain= CTX_data_main(C);
708                 Scene *scene= CTX_data_scene(C);
709
710                 if (argc > 1) {
711                         Render *re = RE_NewRender(scene->id.name);
712                         int frame;
713                         ReportList reports;
714
715                         switch(*argv[1]) {
716                         case '+':
717                                 frame= scene->r.sfra + atoi(argv[1]+1);
718                                 break;
719                         case '-':
720                                 frame= (scene->r.efra - atoi(argv[1]+1)) + 1;
721                                 break;
722                         default:
723                                 frame= atoi(argv[1]);
724                                 break;
725                         }
726
727                         BKE_reports_init(&reports, RPT_PRINT);
728
729                         frame = MIN2(MAXFRAME, MAX2(MINAFRAME, frame));
730
731                         RE_BlenderAnim(re, bmain, scene, scene->lay, frame, frame, scene->r.frame_step, &reports);
732                         return 1;
733                 } else {
734                         printf("\nError: frame number must follow '-f / --render-frame'.\n");
735                         return 0;
736                 }
737         } else {
738                 printf("\nError: no blend loaded. cannot use '-f / --render-frame'.\n");
739                 return 0;
740         }
741 }
742
743 static int render_animation(int UNUSED(argc), char **UNUSED(argv), void *data)
744 {
745         bContext *C = data;
746         if (CTX_data_scene(C)) {
747                 Main *bmain= CTX_data_main(C);
748                 Scene *scene= CTX_data_scene(C);
749                 Render *re= RE_NewRender(scene->id.name);
750                 ReportList reports;
751                 BKE_reports_init(&reports, RPT_PRINT);
752                 RE_BlenderAnim(re, bmain, scene, scene->lay, scene->r.sfra, scene->r.efra, scene->r.frame_step, &reports);
753         } else {
754                 printf("\nError: no blend loaded. cannot use '-a'.\n");
755         }
756         return 0;
757 }
758
759 static int set_scene(int argc, char **argv, void *data)
760 {
761         if(argc > 1) {
762                 bContext *C= data;
763                 Scene *sce= set_scene_name(CTX_data_main(C), argv[1]);
764                 if(sce) {
765                         CTX_data_scene_set(C, sce);
766                 }
767                 return 1;
768         } else {
769                 printf("\nError: Scene name must follow '-S / --scene'.\n");
770                 return 0;
771         }
772 }
773
774 static int set_start_frame(int argc, char **argv, void *data)
775 {
776         bContext *C = data;
777         if (CTX_data_scene(C)) {
778                 Scene *scene= CTX_data_scene(C);
779                 if (argc > 1) {
780                         int frame = atoi(argv[1]);
781                         (scene->r.sfra) = CLAMPIS(frame, MINFRAME, MAXFRAME);
782                         return 1;
783                 } else {
784                         printf("\nError: frame number must follow '-s / --frame-start'.\n");
785                         return 0;
786                 }
787         } else {
788                 printf("\nError: no blend loaded. cannot use '-s / --frame-start'.\n");
789                 return 0;
790         }
791 }
792
793 static int set_end_frame(int argc, char **argv, void *data)
794 {
795         bContext *C = data;
796         if (CTX_data_scene(C)) {
797                 Scene *scene= CTX_data_scene(C);
798                 if (argc > 1) {
799                         int frame = atoi(argv[1]);
800                         (scene->r.efra) = CLAMPIS(frame, MINFRAME, MAXFRAME);
801                         return 1;
802                 } else {
803                         printf("\nError: frame number must follow '-e / --frame-end'.\n");
804                         return 0;
805                 }
806         } else {
807                 printf("\nError: no blend loaded. cannot use '-e / --frame-end'.\n");
808                 return 0;
809         }
810 }
811
812 static int set_skip_frame(int argc, char **argv, void *data)
813 {
814         bContext *C = data;
815         if (CTX_data_scene(C)) {
816                 Scene *scene= CTX_data_scene(C);
817                 if (argc > 1) {
818                         int frame = atoi(argv[1]);
819                         (scene->r.frame_step) = CLAMPIS(frame, 1, MAXFRAME);
820                         return 1;
821                 } else {
822                         printf("\nError: number of frames to step must follow '-j / --frame-jump'.\n");
823                         return 0;
824                 }
825         } else {
826                 printf("\nError: no blend loaded. cannot use '-j / --frame-jump'.\n");
827                 return 0;
828         }
829 }
830
831 /* macro for ugly context setup/reset */
832 #ifdef WITH_PYTHON
833 #define BPY_CTX_SETUP(_cmd) \
834 { \
835         wmWindowManager *wm= CTX_wm_manager(C); \
836         wmWindow *prevwin= CTX_wm_window(C); \
837         Scene *prevscene= CTX_data_scene(C); \
838         if(wm->windows.first) { \
839                 CTX_wm_window_set(C, wm->windows.first); \
840                 _cmd; \
841                 CTX_wm_window_set(C, prevwin); \
842         } \
843         else { \
844                 fprintf(stderr, "Python script \"%s\" running with missing context data.\n", argv[1]); \
845                 _cmd; \
846         } \
847         CTX_data_scene_set(C, prevscene); \
848 } \
849
850 #endif /* WITH_PYTHON */
851
852 static int run_python(int argc, char **argv, void *data)
853 {
854 #ifdef WITH_PYTHON
855         bContext *C = data;
856
857         /* workaround for scripts not getting a bpy.context.scene, causes internal errors elsewhere */
858         if (argc > 1) {
859                 /* Make the path absolute because its needed for relative linked blends to be found */
860                 char filename[FILE_MAXDIR + FILE_MAXFILE];
861                 BLI_strncpy(filename, argv[1], sizeof(filename));
862                 BLI_path_cwd(filename);
863
864                 BPY_CTX_SETUP( BPY_run_python_script(C, filename, NULL, NULL) )
865
866                 return 1;
867         } else {
868                 printf("\nError: you must specify a Python script after '-P / --python'.\n");
869                 return 0;
870         }
871 #else
872         (void)argc; (void)argv; (void)data; /* unused */
873         printf("This blender was built without python support\n");
874         return 0;
875 #endif /* WITH_PYTHON */
876 }
877
878 static int run_python_console(int UNUSED(argc), char **argv, void *data)
879 {
880 #ifdef WITH_PYTHON
881         bContext *C = data;     
882         const char *expr= "__import__('code').interact()";
883
884         BPY_CTX_SETUP( BPY_eval_string(C, expr) )
885
886         return 0;
887 #else
888         (void)argv; (void)data; /* unused */
889         printf("This blender was built without python support\n");
890         return 0;
891 #endif /* WITH_PYTHON */
892 }
893
894 static int load_file(int UNUSED(argc), char **argv, void *data)
895 {
896         bContext *C = data;
897
898         /* Make the path absolute because its needed for relative linked blends to be found */
899         char filename[FILE_MAXDIR + FILE_MAXFILE];
900         BLI_strncpy(filename, argv[0], sizeof(filename));
901         BLI_path_cwd(filename);
902
903         if (G.background) {
904                 int retval = BKE_read_file(C, filename, NULL);
905
906                 /*we successfully loaded a blend file, get sure that
907                 pointcache works */
908                 if (retval!=0) {
909                         wmWindowManager *wm= CTX_wm_manager(C);
910
911                         /* special case, 2.4x files */
912                         if(wm==NULL && CTX_data_main(C)->wm.first==NULL) {
913                                 extern void wm_add_default(bContext *C);
914
915                                 /* wm_add_default() needs the screen to be set. */
916                                 CTX_wm_screen_set(C, CTX_data_main(C)->screen.first);
917                                 wm_add_default(C);
918                         }
919
920                         CTX_wm_manager_set(C, NULL); /* remove wm to force check */
921                         WM_check(C);
922                         G.relbase_valid = 1;
923                         if (CTX_wm_manager(C) == NULL) CTX_wm_manager_set(C, wm); /* reset wm */
924                 }
925
926                 /* WM_read_file() runs normally but since we're in background mode do here */
927 #ifdef WITH_PYTHON
928                 /* run any texts that were loaded in and flagged as modules */
929                 BPY_reset_driver();
930                 BPY_load_user_modules(C);
931 #endif
932
933                 /* happens for the UI on file reading too (huh? (ton))*/
934         // XXX                  BKE_reset_undo();
935         //                              BKE_write_undo("original");     /* save current state */
936         } else {
937                 /* we are not running in background mode here, but start blender in UI mode with
938                    a file - this should do everything a 'load file' does */
939                 ReportList reports;
940                 BKE_reports_init(&reports, RPT_PRINT);
941                 WM_read_file(C, filename, &reports);
942                 BKE_reports_clear(&reports);
943         }
944
945         G.file_loaded = 1;
946
947         return 0;
948 }
949
950 void setupArguments(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
951 {
952         static char output_doc[] = "<path>"
953                 "\n\tSet the render path and file name."
954                 "\n\tUse // at the start of the path to"
955                 "\n\t\trender relative to the blend file."
956                 "\n\tThe # characters are replaced by the frame number, and used to define zero padding."
957                 "\n\t\tani_##_test.png becomes ani_01_test.png"
958                 "\n\t\ttest-######.png becomes test-000001.png"
959                 "\n\t\tWhen the filename does not contain #, The suffix #### is added to the filename"
960                 "\n\tThe frame number will be added at the end of the filename."
961                 "\n\t\teg: blender -b foobar.blend -o //render_ -F PNG -x 1 -a"
962                 "\n\t\t//render_ becomes //render_####, writing frames as //render_0001.png//";
963
964         static char format_doc[] = "<format>"
965                 "\n\tSet the render format, Valid options are..."
966                 "\n\t\tTGA IRIS JPEG MOVIE IRIZ RAWTGA"
967                 "\n\t\tAVIRAW AVIJPEG PNG BMP FRAMESERVER"
968                 "\n\t(formats that can be compiled into blender, not available on all systems)"
969                 "\n\t\tHDR TIFF EXR MULTILAYER MPEG AVICODEC QUICKTIME CINEON DPX DDS";
970
971         static char playback_doc[] = "<options> <file(s)>"
972                 "\n\tPlayback <file(s)>, only operates this way when not running in background."
973                 "\n\t\t-p <sx> <sy>\tOpen with lower left corner at <sx>, <sy>"
974                 "\n\t\t-m\t\tRead from disk (Don't buffer)"
975                 "\n\t\t-f <fps> <fps-base>\t\tSpecify FPS to start with"
976                 "\n\t\t-j <frame>\tSet frame step to <frame>";
977
978         static char game_doc[] = "Game Engine specific options"
979                 "\n\t-g fixedtime\t\tRun on 50 hertz without dropping frames"
980                 "\n\t-g vertexarrays\t\tUse Vertex Arrays for rendering (usually faster)"
981                 "\n\t-g nomipmap\t\tNo Texture Mipmapping"
982                 "\n\t-g linearmipmap\t\tLinear Texture Mipmapping instead of Nearest (default)";
983
984         static char debug_doc[] = "\n\tTurn debugging on\n"
985                 "\n\t* Prints every operator call and their arguments"
986                 "\n\t* Disables mouse grab (to interact with a debugger in some cases)"
987                 "\n\t* Keeps python sys.stdin rather then setting it to None";
988
989         //BLI_argsAdd(ba, pass, short_arg, long_arg, doc, cb, C);
990
991         /* end argument processing after -- */
992         BLI_argsAdd(ba, -1, "--", NULL, "\n\tEnds option processing, following arguments passed unchanged. Access via python's sys.argv", end_arguments, NULL);
993
994         /* first pass: background mode, disable python and commands that exit after usage */
995         BLI_argsAdd(ba, 1, "-h", "--help", "\n\tPrint this help text and exit", print_help, ba);
996         /* Windows only */
997         BLI_argsAdd(ba, 1, "/?", NULL, "\n\tPrint this help text and exit (windows only)", print_help, ba);
998
999         BLI_argsAdd(ba, 1, "-v", "--version", "\n\tPrint Blender version and exit", print_version, NULL);
1000
1001         BLI_argsAdd(ba, 1, "-y", "--enable-autoexec", "\n\tEnable automatic python script execution (default)", enable_python, NULL);
1002         BLI_argsAdd(ba, 1, "-Y", "--disable-autoexec", "\n\tDisable automatic python script execution (pydrivers, pyconstraints, pynodes)", disable_python, NULL);
1003
1004         BLI_argsAdd(ba, 1, "-b", "--background", "<file>\n\tLoad <file> in background (often used for UI-less rendering)", background_mode, NULL);
1005
1006         BLI_argsAdd(ba, 1, "-a", NULL, playback_doc, playback_mode, NULL);
1007
1008         BLI_argsAdd(ba, 1, "-d", "--debug", debug_doc, debug_mode, ba);
1009     BLI_argsAdd(ba, 1, NULL, "--debug-fpe", "\n\tEnable floating point exceptions", set_fpe, NULL);
1010
1011         /* second pass: custom window stuff */
1012         BLI_argsAdd(ba, 2, "-p", "--window-geometry", "<sx> <sy> <w> <h>\n\tOpen with lower left corner at <sx>, <sy> and width and height as <w>, <h>", prefsize, NULL);
1013         BLI_argsAdd(ba, 2, "-w", "--window-border", "\n\tForce opening with borders (default)", with_borders, NULL);
1014         BLI_argsAdd(ba, 2, "-W", "--window-borderless", "\n\tForce opening without borders", without_borders, NULL);
1015         BLI_argsAdd(ba, 2, "-R", NULL, "\n\tRegister .blend extension (windows only)", register_extension, ba);
1016
1017         /* third pass: disabling things and forcing settings */
1018         BLI_argsAddCase(ba, 3, "-nojoystick", 1, NULL, 0, "\n\tDisable joystick support", no_joystick, syshandle);
1019         BLI_argsAddCase(ba, 3, "-noglsl", 1, NULL, 0, "\n\tDisable GLSL shading", no_glsl, NULL);
1020         BLI_argsAddCase(ba, 3, "-noaudio", 1, NULL, 0, "\n\tForce sound system to None", no_audio, NULL);
1021         BLI_argsAddCase(ba, 3, "-setaudio", 1, NULL, 0, "\n\tForce sound system to a specific device\n\tNULL SDL OPENAL JACK", set_audio, NULL);
1022
1023         /* fourth pass: processing arguments */
1024         BLI_argsAdd(ba, 4, "-g", NULL, game_doc, set_ge_parameters, syshandle);
1025         BLI_argsAdd(ba, 4, "-f", "--render-frame", "<frame>\n\tRender frame <frame> and save it.\n\t+<frame> start frame relative, -<frame> end frame relative.", render_frame, C);
1026         BLI_argsAdd(ba, 4, "-a", "--render-anim", "\n\tRender frames from start to end (inclusive)", render_animation, C);
1027         BLI_argsAdd(ba, 4, "-S", "--scene", "<name>\n\tSet the active scene <name> for rendering", set_scene, C);
1028         BLI_argsAdd(ba, 4, "-s", "--frame-start", "<frame>\n\tSet start to frame <frame> (use before the -a argument)", set_start_frame, C);
1029         BLI_argsAdd(ba, 4, "-e", "--frame-end", "<frame>\n\tSet end to frame <frame> (use before the -a argument)", set_end_frame, C);
1030         BLI_argsAdd(ba, 4, "-j", "--frame-jump", "<frames>\n\tSet number of frames to step forward after each rendered frame", set_skip_frame, C);
1031         BLI_argsAdd(ba, 4, "-P", "--python", "<filename>\n\tRun the given Python script (filename or Blender Text)", run_python, C);
1032         BLI_argsAdd(ba, 4, NULL, "--python-console", "\n\tRun blender with an interactive console", run_python_console, C);
1033
1034         BLI_argsAdd(ba, 4, "-o", "--render-output", output_doc, set_output, C);
1035         BLI_argsAdd(ba, 4, "-E", "--engine", "<engine>\n\tSpecify the render engine\n\tuse -E help to list available engines", set_engine, C);
1036
1037         BLI_argsAdd(ba, 4, "-F", "--render-format", format_doc, set_image_type, C);
1038         BLI_argsAdd(ba, 4, "-t", "--threads", "<threads>\n\tUse amount of <threads> for rendering in background\n\t[1-" STRINGIFY(BLENDER_MAX_THREADS) "], 0 for systems processor count.", set_threads, NULL);
1039         BLI_argsAdd(ba, 4, "-x", "--use-extension", "<bool>\n\tSet option to add the file extension to the end of the file", set_extension, C);
1040
1041 }
1042
1043 int main(int argc, char **argv)
1044 {
1045         SYS_SystemHandle syshandle;
1046         bContext *C= CTX_create();
1047         bArgs *ba;
1048
1049 #ifdef WITH_BINRELOC
1050         br_init( NULL );
1051 #endif
1052
1053         setCallbacks();
1054 #ifdef __APPLE__
1055                 /* patch to ignore argument finder gives us (pid?) */
1056         if (argc==2 && strncmp(argv[1], "-psn_", 5)==0) {
1057                 extern int GHOST_HACK_getFirstFile(char buf[]);
1058                 static char firstfilebuf[512];
1059
1060                 argc= 1;
1061
1062                 if (GHOST_HACK_getFirstFile(firstfilebuf)) {
1063                         argc= 2;
1064                         argv[1]= firstfilebuf;
1065                 }
1066         }
1067
1068 #endif
1069
1070 #ifdef __FreeBSD__
1071         fpsetmask(0);
1072 #endif
1073
1074         // copy path to executable in bprogname. playanim and creting runtimes
1075         // need this.
1076
1077         BLI_where_am_i(bprogname, argv[0]);
1078         
1079 #ifdef BUILD_DATE       
1080         strip_quotes(build_date);
1081         strip_quotes(build_time);
1082         strip_quotes(build_rev);
1083         strip_quotes(build_platform);
1084         strip_quotes(build_type);
1085         strip_quotes(build_cflags);
1086         strip_quotes(build_cxxflags);
1087         strip_quotes(build_linkflags);
1088         strip_quotes(build_system);
1089 #endif
1090
1091         BLI_threadapi_init();
1092
1093         RNA_init();
1094         RE_engines_init();
1095
1096                 /* Hack - force inclusion of the plugin api functions,
1097                  * see blenpluginapi:pluginapi.c
1098                  */
1099         pluginapi_force_ref();
1100
1101         init_nodesystem();
1102         
1103         initglobals();  /* blender.c */
1104
1105         IMB_init();
1106
1107 #ifdef WITH_GAMEENGINE
1108         syshandle = SYS_GetSystem();
1109         GEN_init_messaging_system();
1110 #else
1111         syshandle= 0;
1112 #endif
1113
1114         /* first test for background */
1115         ba = BLI_argsInit(argc, argv); /* skip binary path */
1116         setupArguments(C, ba, &syshandle);
1117
1118         BLI_argsParse(ba, 1, NULL, NULL);
1119
1120 #ifdef __sgi
1121         setuid(getuid()); /* end superuser */
1122 #endif
1123
1124
1125         /* for all platforms, even windos has it! */
1126         if(G.background) signal(SIGINT, blender_esc);   /* ctrl c out bg render */
1127         
1128         /* background render uses this font too */
1129         BKE_font_register_builtin(datatoc_Bfont, datatoc_Bfont_size);
1130
1131         /* Initialiaze ffmpeg if built in, also needed for bg mode if videos are
1132            rendered via ffmpeg */
1133         sound_init_once();
1134         
1135         init_def_material();
1136
1137         if(G.background==0) {
1138                 BLI_argsParse(ba, 2, NULL, NULL);
1139                 BLI_argsParse(ba, 3, NULL, NULL);
1140
1141                 WM_init(C, argc, argv);
1142                 
1143                 /* this is properly initialized with user defs, but this is default */
1144                 BLI_where_is_temp( btempdir, 1 ); /* call after loading the startup.blend so we can read U.tempdir */
1145
1146 #ifndef DISABLE_SDL
1147         BLI_setenv("SDL_VIDEODRIVER", "dummy");
1148 #endif
1149         }
1150         else {
1151                 BLI_argsParse(ba, 3, NULL, NULL);
1152
1153                 WM_init(C, argc, argv);
1154
1155                 BLI_where_is_temp( btempdir, 0 ); /* call after loading the startup.blend so we can read U.tempdir */
1156         }
1157 #ifdef WITH_PYTHON
1158         /**
1159          * NOTE: the U.pythondir string is NULL until WM_init() is executed,
1160          * so we provide the BPY_ function below to append the user defined
1161          * pythondir to Python's sys.path at this point.  Simply putting
1162          * WM_init() before BPY_start_python() crashes Blender at startup.
1163          * Update: now this function also inits the bpymenus, which also depend
1164          * on U.pythondir.
1165          */
1166
1167         // TODO - U.pythondir
1168 #else
1169         printf("\n* WARNING * - Blender compiled without Python!\nthis is not intended for typical usage\n\n");
1170 #endif
1171         
1172         CTX_py_init_set(C, 1);
1173         WM_keymap_init(C);
1174
1175         /* OK we are ready for it */
1176         BLI_argsParse(ba, 4, load_file, C);
1177
1178         BLI_argsFree(ba);
1179
1180         if(G.background) {
1181                 /* actually incorrect, but works for now (ton) */
1182                 WM_exit(C);
1183         }
1184
1185         else {
1186                 if((G.fileflags & G_FILE_AUTOPLAY) && (G.f & G_SCRIPT_AUTOEXEC))
1187                 {
1188                         if(WM_init_game(C))
1189                                 return 0;
1190                 }
1191                 else if(!G.file_loaded)
1192                         WM_init_splash(C);
1193         }
1194
1195         WM_main(C);
1196
1197
1198         /*XXX if (scr_init==0) {
1199                 main_init_screen();
1200         }
1201         
1202         screenmain();*/ /* main display loop */
1203
1204         return 0;
1205 } /* end of int main(argc,argv) */
1206
1207 static void error_cb(char *err)
1208 {
1209         
1210         printf("%s\n", err);    /* XXX do this in WM too */
1211 }
1212
1213 static void mem_error_cb(const char *errorStr)
1214 {
1215         fputs(errorStr, stderr);
1216         fflush(stderr);
1217 }
1218
1219 static void setCallbacks(void)
1220 {
1221         /* Error output from the alloc routines: */
1222         MEM_set_error_callback(mem_error_cb);
1223
1224
1225         /* BLI_blenlib: */
1226
1227         BLI_setErrorCallBack(error_cb); /* */
1228 // XXX  BLI_setInterruptCallBack(blender_test_break);
1229
1230 }