small merge needed for testing new animsys in 2.5 BGE, mixing own changes with merge...
[blender.git] / source / gameengine / BlenderRoutines / BL_KetsjiEmbedStart.cpp
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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, 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  * Blender's Ketsji startpoint
29  */
30
31 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
34
35 #include <signal.h>
36 #include <stdlib.h>
37
38 #ifdef WIN32
39 // don't show stl-warnings
40 #pragma warning (disable:4786)
41 #endif
42
43 #include "GL/glew.h"
44
45 #include "KX_BlenderGL.h"
46 #include "KX_BlenderCanvas.h"
47 #include "KX_BlenderKeyboardDevice.h"
48 #include "KX_BlenderMouseDevice.h"
49 #include "KX_BlenderRenderTools.h"
50 #include "KX_BlenderSystem.h"
51 #include "BL_Material.h"
52
53 #include "KX_KetsjiEngine.h"
54 #include "KX_BlenderSceneConverter.h"
55 #include "KX_PythonInit.h"
56 #include "KX_PyConstraintBinding.h"
57
58 #include "RAS_GLExtensionManager.h"
59 #include "RAS_OpenGLRasterizer.h"
60 #include "RAS_VAOpenGLRasterizer.h"
61 #include "RAS_ListRasterizer.h"
62
63 #include "NG_LoopBackNetworkDeviceInterface.h"
64 #include "SND_DeviceManager.h"
65
66 #include "SYS_System.h"
67
68         /***/
69 #include "DNA_view3d_types.h"
70 #include "DNA_screen_types.h"
71 #include "DNA_windowmanager_types.h"
72 #include "BKE_global.h"
73 #include "BKE_report.h"
74
75 #include "BKE_utildefines.h"
76 //XXX #include "BIF_screen.h"
77 //XXX #include "BIF_scrarea.h"
78
79 #include "BKE_main.h"
80 //#include "BKE_context.h"
81 #include "BLI_blenlib.h"
82 #include "BLO_readfile.h"
83 #include "DNA_scene_types.h"
84         /***/
85
86 #include "GPU_extensions.h"
87 #include "Value.h"
88
89
90
91 #ifdef __cplusplus
92 extern "C" {
93 #endif
94 //XXX #include "BSE_headerbuttons.h"
95 #include "../../blender/windowmanager/WM_types.h"
96 #include "../../blender/windowmanager/wm_window.h"
97 #include "../../blender/windowmanager/wm_event_system.h"
98 #ifdef __cplusplus
99 }
100 #endif
101
102
103 static BlendFileData *load_game_data(char *filename)
104 {
105         ReportList reports;
106         BlendFileData *bfd;
107         
108         BKE_reports_init(&reports, RPT_STORE);
109         bfd= BLO_read_from_file(filename, &reports);
110
111         if (!bfd) {
112                 printf("Loading %s failed: ", filename);
113                 BKE_reports_print(&reports, RPT_ERROR);
114         }
115
116         BKE_reports_clear(&reports);
117
118         return bfd;
119 }
120
121
122 /* screw it, BKE_context.h is complaining! */
123 extern "C" struct wmWindow *CTX_wm_window(const bContext *C);
124 extern "C" struct ScrArea *CTX_wm_area(const bContext *C);
125 extern "C" struct ARegion *CTX_wm_region(const bContext *C);
126 extern "C" struct Scene *CTX_data_scene(const bContext *C);
127 extern "C" struct Main *CTX_data_main(const bContext *C);
128
129 extern "C" void StartKetsjiShell(struct bContext *C, int always_use_expand_framing)
130 {
131         /* context values */
132         struct wmWindow *win= CTX_wm_window(C);
133         struct ScrArea *area= CTX_wm_area(C); // curarea
134         struct ARegion *ar= CTX_wm_region(C);
135         struct Scene *scene= CTX_data_scene(C);
136         struct Main* maggie1= CTX_data_main(C);
137         
138         
139         int exitrequested = KX_EXIT_REQUEST_NO_REQUEST;
140         Main* blenderdata = maggie1;
141
142         char* startscenename = scene->id.name+2;
143         char pathname[FILE_MAXDIR+FILE_MAXFILE], oldsce[FILE_MAXDIR+FILE_MAXFILE];
144         STR_String exitstring = "";
145         BlendFileData *bfd= NULL;
146
147         BLI_strncpy(pathname, blenderdata->name, sizeof(pathname));
148         BLI_strncpy(oldsce, G.sce, sizeof(oldsce));
149         resetGamePythonPath(); // need this so running a second time wont use an old blendfiles path
150         setGamePythonPath(G.sce);
151
152         // Acquire Python's GIL (global interpreter lock)
153         // so we can safely run Python code and API calls
154         PyGILState_STATE gilstate = PyGILState_Ensure();
155         
156         PyObject *pyGlobalDict = PyDict_New(); /* python utility storage, spans blend file loading */
157         
158         bgl::InitExtensions(true);
159
160         do
161         {
162                 View3D *v3d= (View3D*) area->spacedata.first;
163                 RegionView3D *rv3d= (RegionView3D*) ar->regiondata;
164
165                 // get some preferences
166                 SYS_SystemHandle syshandle = SYS_GetSystem();
167                 bool properties = (SYS_GetCommandLineInt(syshandle, "show_properties", 0) != 0);
168                 bool usefixed = (SYS_GetCommandLineInt(syshandle, "fixedtime", 0) != 0);
169                 bool profile = (SYS_GetCommandLineInt(syshandle, "show_profile", 0) != 0);
170                 bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0);
171                 bool game2ipo = (SYS_GetCommandLineInt(syshandle, "game2ipo", 0) != 0);
172                 bool displaylists = (SYS_GetCommandLineInt(syshandle, "displaylists", 0) != 0);
173                 bool nodepwarnings = (SYS_GetCommandLineInt(syshandle, "ignore_deprecation_warnings", 0) != 0);
174                 bool novertexarrays = (SYS_GetCommandLineInt(syshandle, "novertexarrays", 0) != 0);
175                 // create the canvas, rasterizer and rendertools
176                 RAS_ICanvas* canvas = new KX_BlenderCanvas(win, ar);
177                 canvas->SetMouseState(RAS_ICanvas::MOUSE_INVISIBLE);
178                 RAS_IRenderTools* rendertools = new KX_BlenderRenderTools();
179                 RAS_IRasterizer* rasterizer = NULL;
180                 
181                 if(displaylists) {
182                         if (GLEW_VERSION_1_1 && !novertexarrays)
183                                 rasterizer = new RAS_ListRasterizer(canvas, true, true);
184                         else
185                                 rasterizer = new RAS_ListRasterizer(canvas);
186                 }
187                 else if (GLEW_VERSION_1_1 && !novertexarrays)
188                         rasterizer = new RAS_VAOpenGLRasterizer(canvas, false);
189                 else
190                         rasterizer = new RAS_OpenGLRasterizer(canvas);
191                 
192                 // create the inputdevices
193                 KX_BlenderKeyboardDevice* keyboarddevice = new KX_BlenderKeyboardDevice();
194                 KX_BlenderMouseDevice* mousedevice = new KX_BlenderMouseDevice();
195                 
196                 // create a networkdevice
197                 NG_NetworkDeviceInterface* networkdevice = new
198                         NG_LoopBackNetworkDeviceInterface();
199                 
200                 //
201                 SYS_SystemHandle hSystem = SYS_GetSystem();
202                 bool noaudio = SYS_GetCommandLineInt(hSystem,"noaudio",0);
203
204                 if (noaudio)/*(noaudio) intrr: disable game engine audio (openal) */
205                         SND_DeviceManager::SetDeviceType(snd_e_dummydevice);
206
207                 // get an audiodevice
208                 SND_DeviceManager::Subscribe();
209                 SND_IAudioDevice* audiodevice = SND_DeviceManager::Instance();
210                 audiodevice->UseCD();
211                 
212                 // create a ketsji/blendersystem (only needed for timing and stuff)
213                 KX_BlenderSystem* kxsystem = new KX_BlenderSystem();
214                 
215                 // create the ketsjiengine
216                 KX_KetsjiEngine* ketsjiengine = new KX_KetsjiEngine(kxsystem);
217                 
218                 // set the devices
219                 ketsjiengine->SetKeyboardDevice(keyboarddevice);
220                 ketsjiengine->SetMouseDevice(mousedevice);
221                 ketsjiengine->SetNetworkDevice(networkdevice);
222                 ketsjiengine->SetCanvas(canvas);
223                 ketsjiengine->SetRenderTools(rendertools);
224                 ketsjiengine->SetRasterizer(rasterizer);
225                 ketsjiengine->SetNetworkDevice(networkdevice);
226                 ketsjiengine->SetAudioDevice(audiodevice);
227                 ketsjiengine->SetUseFixedTime(usefixed);
228                 ketsjiengine->SetTimingDisplay(frameRate, profile, properties);
229
230                 CValue::SetDeprecationWarnings(nodepwarnings);
231
232
233                 //lock frame and camera enabled - storing global values
234                 int tmp_lay= scene->lay;
235                 Object *tmp_camera = scene->camera;
236
237                 if (v3d->scenelock==0){
238                         scene->lay= v3d->lay;
239                         scene->camera= v3d->camera;
240                 }
241
242         
243                 // some blender stuff
244                 MT_CmMatrix4x4 projmat;
245                 MT_CmMatrix4x4 viewmat;
246                 float camzoom;
247                 int i;
248                 
249                 for (i = 0; i < 16; i++)
250                 {
251                         float *viewmat_linear= (float*) rv3d->viewmat;
252                         viewmat.setElem(i, viewmat_linear[i]);
253                 }
254                 for (i = 0; i < 16; i++)
255                 {
256                         float *projmat_linear= (float*) rv3d->winmat;
257                         projmat.setElem(i, projmat_linear[i]);
258                 }
259                 
260                 if(v3d->persp==V3D_CAMOB) {
261                         camzoom = (1.41421 + (rv3d->camzoom / 50.0));
262                         camzoom *= camzoom;
263                 }
264                 else
265                         camzoom = 2.0;
266
267                 camzoom = 4.0 / camzoom;
268                 
269                 ketsjiengine->SetDrawType(v3d->drawtype);
270                 ketsjiengine->SetCameraZoom(camzoom);
271                 
272                 // if we got an exitcode 3 (KX_EXIT_REQUEST_START_OTHER_GAME) load a different file
273                 if (exitrequested == KX_EXIT_REQUEST_START_OTHER_GAME || exitrequested == KX_EXIT_REQUEST_RESTART_GAME)
274                 {
275                         exitrequested = KX_EXIT_REQUEST_NO_REQUEST;
276                         if (bfd) BLO_blendfiledata_free(bfd);
277                         
278                         char basedpath[240];
279                         // base the actuator filename with respect
280                         // to the original file working directory
281
282                         if (exitstring != "")
283                                 strcpy(basedpath, exitstring.Ptr());
284
285                         // load relative to the last loaded file, this used to be relative
286                         // to the first file but that makes no sense, relative paths in
287                         // blend files should be relative to that file, not some other file
288                         // that happened to be loaded first
289                         BLI_convertstringcode(basedpath, pathname);
290                         bfd = load_game_data(basedpath);
291                         
292                         // if it wasn't loaded, try it forced relative
293                         if (!bfd)
294                         {
295                                 // just add "//" in front of it
296                                 char temppath[242];
297                                 strcpy(temppath, "//");
298                                 strcat(temppath, basedpath);
299                                 
300                                 BLI_convertstringcode(temppath, pathname);
301                                 bfd = load_game_data(temppath);
302                         }
303                         
304                         // if we got a loaded blendfile, proceed
305                         if (bfd)
306                         {
307                                 blenderdata = bfd->main;
308                                 startscenename = bfd->curscene->id.name + 2;
309
310                                 if(blenderdata) {
311                                         BLI_strncpy(G.sce, blenderdata->name, sizeof(G.sce));
312                                         BLI_strncpy(pathname, blenderdata->name, sizeof(pathname));
313                                         setGamePythonPath(G.sce);
314                                 }
315                         }
316                         // else forget it, we can't find it
317                         else
318                         {
319                                 exitrequested = KX_EXIT_REQUEST_QUIT_GAME;
320                         }
321                 }
322                 
323                 Scene *blscene = NULL;
324                 if (!bfd)
325                 {
326                         blscene = (Scene*) blenderdata->scene.first;
327                         for (Scene *sce= (Scene*) blenderdata->scene.first; sce; sce= (Scene*) sce->id.next)
328                         {
329                                 if (startscenename == (sce->id.name+2))
330                                 {
331                                         blscene = sce;
332                                         break;
333                                 }
334                         }
335                 } else {
336                         blscene = bfd->curscene;
337                 }
338
339                 if (blscene)
340                 {
341                         int startFrame = blscene->r.cfra;
342                         ketsjiengine->SetGame2IpoMode(game2ipo,startFrame);
343                         
344                         // Quad buffered needs a special window.
345                         if (blscene->r.stereomode != RAS_IRasterizer::RAS_STEREO_QUADBUFFERED)
346                                 rasterizer->SetStereoMode((RAS_IRasterizer::StereoMode) blscene->r.stereomode);
347                 }
348                 
349                 if (exitrequested != KX_EXIT_REQUEST_QUIT_GAME)
350                 {
351                         if (v3d->persp != V3D_CAMOB)
352                         {
353                                 ketsjiengine->EnableCameraOverride(startscenename);
354                                 ketsjiengine->SetCameraOverrideUseOrtho((v3d->persp == V3D_ORTHO));
355                                 ketsjiengine->SetCameraOverrideProjectionMatrix(projmat);
356                                 ketsjiengine->SetCameraOverrideViewMatrix(viewmat);
357                                 ketsjiengine->SetCameraOverrideClipping(v3d->near, v3d->far);
358                                 ketsjiengine->SetCameraOverrideLens(v3d->lens);
359                         }
360                         
361                         // create a scene converter, create and convert the startingscene
362                         KX_ISceneConverter* sceneconverter = new KX_BlenderSceneConverter(blenderdata, ketsjiengine);
363                         ketsjiengine->SetSceneConverter(sceneconverter);
364                         sceneconverter->addInitFromFrame=false;
365                         if (always_use_expand_framing)
366                                 sceneconverter->SetAlwaysUseExpandFraming(true);
367
368                         bool usemat = false, useglslmat = false;
369
370                         if(GLEW_ARB_multitexture && GLEW_VERSION_1_1)
371                                 usemat = true;
372
373                         if(GPU_extensions_minimum_support())
374                                 useglslmat = true;
375                         else if(G.fileflags & G_FILE_GAME_MAT_GLSL)
376                                 usemat = false;
377
378             if(usemat && (G.fileflags & G_FILE_GAME_MAT))
379                                 sceneconverter->SetMaterials(true);
380                         if(useglslmat && (G.fileflags & G_FILE_GAME_MAT_GLSL))
381                                 sceneconverter->SetGLSLMaterials(true);
382                                         
383                         KX_Scene* startscene = new KX_Scene(keyboarddevice,
384                                 mousedevice,
385                                 networkdevice,
386                                 audiodevice,
387                                 startscenename,
388                                 blscene);
389                         
390                         // some python things
391                         PyObject* dictionaryobject = initGamePythonScripting("Ketsji", psl_Lowest, blenderdata);
392                         ketsjiengine->SetPythonDictionary(dictionaryobject);
393                         initRasterizer(rasterizer, canvas);
394                         PyObject *gameLogic = initGameLogic(ketsjiengine, startscene);
395                         PyDict_SetItemString(PyModule_GetDict(gameLogic), "globalDict", pyGlobalDict); // Same as importing the module.
396                         PyObject *gameLogic_keys = PyDict_Keys(PyModule_GetDict(gameLogic));
397                         PyDict_SetItemString(dictionaryobject, "GameLogic", gameLogic); // Same as importing the module.
398                         
399                         initGameKeys();
400                         initPythonConstraintBinding();
401                         initMathutils();
402                         initGeometry();
403                         initBGL();
404 #ifdef WITH_FFMPEG
405                         initVideoTexture();
406 #endif
407
408                         //initialize Dome Settings
409                         if(blscene->r.stereomode == RAS_IRasterizer::RAS_STEREO_DOME)
410                                 ketsjiengine->InitDome(blscene->r.domeres, blscene->r.domemode, blscene->r.domeangle, blscene->r.domeresbuf, blscene->r.dometilt, blscene->r.dometext);
411
412                         if (sceneconverter)
413                         {
414                                 // convert and add scene
415                                 sceneconverter->ConvertScene(
416                                         startscenename,
417                                         startscene,
418                                         dictionaryobject,
419                                         keyboarddevice,
420                                         rendertools,
421                                         canvas);
422                                 ketsjiengine->AddScene(startscene);
423                                 
424                                 // init the rasterizer
425                                 rasterizer->Init();
426                                 
427                                 // start the engine
428                                 ketsjiengine->StartEngine(true);
429                                 
430
431                                 // Set the animation playback rate for ipo's and actions
432                                 // the framerate below should patch with FPS macro defined in blendef.h
433                                 // Could be in StartEngine set the framerate, we need the scene to do this
434                                 ketsjiengine->SetAnimFrameRate( (((double) blscene->r.frs_sec) / blscene->r.frs_sec_base) );
435                                 
436                                 // the mainloop
437                                 printf("\nBlender Game Engine Started\n\n");
438                                 while (!exitrequested)
439                                 {
440                                         // first check if we want to exit
441                                         exitrequested = ketsjiengine->GetExitCode();
442                                         
443                                         // kick the engine
444                                         bool render = ketsjiengine->NextFrame(); // XXX 2.5 Bug, This is never true! FIXME-  Campbell
445                                         
446                                         if (render)
447                                         {
448                                                 // render the frame
449                                                 ketsjiengine->Render();
450                                         }
451                                         
452                                         wm_window_process_events_nosleep(C);
453                                         
454                                         // test for the ESC key
455                                         //XXX while (qtest())
456                                         while(wmEvent *event= (wmEvent *)win->queue.first)
457                                         {
458                                                 short val = 0;
459                                                 //unsigned short event = 0; //XXX extern_qread(&val);
460                                                 
461                                                 if (keyboarddevice->ConvertBlenderEvent(event->type,event->val))
462                                                         exitrequested = KX_EXIT_REQUEST_BLENDER_ESC;
463                                                 
464                                                         /* Coordinate conversion... where
465                                                         * should this really be?
466                                                 */
467                                                 if (event->type==MOUSEMOVE) {
468                                                         /* Note nice! XXX 2.5 event hack */
469                                                         val = event->x - ar->winrct.xmin;
470                                                         mousedevice->ConvertBlenderEvent(MOUSEX, val);
471                                                         
472                                                         val = ar->winy - (event->y - ar->winrct.ymin) - 1;
473                                                         mousedevice->ConvertBlenderEvent(MOUSEY, val);
474                                                 }
475                                                 else {
476                                                         mousedevice->ConvertBlenderEvent(event->type,event->val);
477                                                 }
478                                                 
479                                                 BLI_remlink(&win->queue, event);
480                                                 wm_event_free(event);
481                                         }
482                                         
483                                 }
484                                 printf("\nBlender Game Engine Finished\n\n");
485                                 exitstring = ketsjiengine->GetExitString();
486
487
488                                 // when exiting the mainloop
489                                 
490                                 // Clears the dictionary by hand:
491                                 // This prevents, extra references to global variables
492                                 // inside the GameLogic dictionary when the python interpreter is finalized.
493                                 // which allows the scene to safely delete them :)
494                                 // see: (space.c)->start_game
495                                 
496                                 //PyDict_Clear(PyModule_GetDict(gameLogic));
497                                 
498                                 // Keep original items, means python plugins will autocomplete members
499                                 int listIndex;
500                                 PyObject *gameLogic_keys_new = PyDict_Keys(PyModule_GetDict(gameLogic));
501                                 for (listIndex=0; listIndex < PyList_Size(gameLogic_keys_new); listIndex++)  {
502                                         PyObject* item = PyList_GET_ITEM(gameLogic_keys_new, listIndex);
503                                         if (!PySequence_Contains(gameLogic_keys, item)) {
504                                                 PyDict_DelItem( PyModule_GetDict(gameLogic), item);
505                                         }
506                                 }
507                                 Py_DECREF(gameLogic_keys_new);
508                                 gameLogic_keys_new = NULL;
509                                 
510                                 ketsjiengine->StopEngine();
511                                 exitGamePythonScripting();
512                                 networkdevice->Disconnect();
513                         }
514                         if (sceneconverter)
515                         {
516                                 delete sceneconverter;
517                                 sceneconverter = NULL;
518                         }
519                         
520                         Py_DECREF(gameLogic_keys);
521                         gameLogic_keys = NULL;
522                 }
523                 //lock frame and camera enabled - restoring global values
524                 if (v3d->scenelock==0){
525                         scene->lay= tmp_lay;
526                         scene->camera= tmp_camera;
527                 }
528
529                 // set the cursor back to normal
530                 canvas->SetMouseState(RAS_ICanvas::MOUSE_NORMAL);
531                 
532                 // clean up some stuff
533                 audiodevice->StopCD();
534                 
535                 if (ketsjiengine)
536                 {
537                         delete ketsjiengine;
538                         ketsjiengine = NULL;
539                 }
540                 if (kxsystem)
541                 {
542                         delete kxsystem;
543                         kxsystem = NULL;
544                 }
545                 if (networkdevice)
546                 {
547                         delete networkdevice;
548                         networkdevice = NULL;
549                 }
550                 if (keyboarddevice)
551                 {
552                         delete keyboarddevice;
553                         keyboarddevice = NULL;
554                 }
555                 if (mousedevice)
556                 {
557                         delete mousedevice;
558                         mousedevice = NULL;
559                 }
560                 if (rasterizer)
561                 {
562                         delete rasterizer;
563                         rasterizer = NULL;
564                 }
565                 if (rendertools)
566                 {
567                         delete rendertools;
568                         rendertools = NULL;
569                 }
570                 if (canvas)
571                 {
572                         delete canvas;
573                         canvas = NULL;
574                 }
575                 SND_DeviceManager::Unsubscribe();
576         
577         } while (exitrequested == KX_EXIT_REQUEST_RESTART_GAME || exitrequested == KX_EXIT_REQUEST_START_OTHER_GAME);
578         
579         Py_DECREF(pyGlobalDict);
580         
581         if (bfd) BLO_blendfiledata_free(bfd);
582
583         BLI_strncpy(G.sce, oldsce, sizeof(G.sce));
584
585         // Release Python's GIL
586         PyGILState_Release(gilstate);
587 }
588
589 extern "C" void StartKetsjiShellSimulation(struct wmWindow *win,
590                                                                  struct ScrArea *area,
591                                                                  struct ARegion *ar,
592                                                                  char* scenename,
593                                                                  struct Main* maggie,
594                                                                  int always_use_expand_framing)
595 {
596     int exitrequested = KX_EXIT_REQUEST_NO_REQUEST;
597
598         Main* blenderdata = maggie;
599
600         char* startscenename = scenename;
601         char pathname[FILE_MAXDIR+FILE_MAXFILE];
602         STR_String exitstring = "";
603
604         BLI_strncpy(pathname, blenderdata->name, sizeof(pathname));
605
606         // Acquire Python's GIL (global interpreter lock)
607         // so we can safely run Python code and API calls
608         PyGILState_STATE gilstate = PyGILState_Ensure();
609
610         bgl::InitExtensions(true);
611
612         do
613         {
614
615                 // get some preferences
616                 SYS_SystemHandle syshandle = SYS_GetSystem();
617                 /*
618                 bool properties = (SYS_GetCommandLineInt(syshandle, "show_properties", 0) != 0);
619                 bool usefixed = (SYS_GetCommandLineInt(syshandle, "fixedtime", 0) != 0);
620                 bool profile = (SYS_GetCommandLineInt(syshandle, "show_profile", 0) != 0);
621                 bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0);
622                 */
623                 bool game2ipo = true;//(SYS_GetCommandLineInt(syshandle, "game2ipo", 0) != 0);
624                 bool displaylists = (SYS_GetCommandLineInt(syshandle, "displaylists", 0) != 0);
625                 bool usemat = false;
626
627                 // create the canvas, rasterizer and rendertools
628                 RAS_ICanvas* canvas = new KX_BlenderCanvas(win, ar);
629                 //canvas->SetMouseState(RAS_ICanvas::MOUSE_INVISIBLE);
630                 RAS_IRenderTools* rendertools = new KX_BlenderRenderTools();
631                 RAS_IRasterizer* rasterizer = NULL;
632
633                 if(displaylists) {
634                         if (GLEW_VERSION_1_1)
635                                 rasterizer = new RAS_ListRasterizer(canvas, true, true);
636                         else
637                                 rasterizer = new RAS_ListRasterizer(canvas);
638                 }
639                 else if (GLEW_VERSION_1_1)
640                         rasterizer = new RAS_VAOpenGLRasterizer(canvas, false);
641                 else
642                         rasterizer = new RAS_OpenGLRasterizer(canvas);
643
644                 // create the inputdevices
645                 KX_BlenderKeyboardDevice* keyboarddevice = new KX_BlenderKeyboardDevice();
646                 KX_BlenderMouseDevice* mousedevice = new KX_BlenderMouseDevice();
647
648                 // create a networkdevice
649                 NG_NetworkDeviceInterface* networkdevice = new
650                         NG_LoopBackNetworkDeviceInterface();
651
652                 // get an audiodevice
653                 SND_DeviceManager::Subscribe();
654                 SND_IAudioDevice* audiodevice = SND_DeviceManager::Instance();
655                 audiodevice->UseCD();
656
657                 // create a ketsji/blendersystem (only needed for timing and stuff)
658                 KX_BlenderSystem* kxsystem = new KX_BlenderSystem();
659
660                 // create the ketsjiengine
661                 KX_KetsjiEngine* ketsjiengine = new KX_KetsjiEngine(kxsystem);
662
663                 Scene *blscene = NULL;
664
665                 blscene = (Scene*) maggie->scene.first;
666                 for (Scene *sce= (Scene*) maggie->scene.first; sce; sce= (Scene*) sce->id.next)
667                 {
668                         if (startscenename == (sce->id.name+2))
669                         {
670                                 blscene = sce;
671                                 break;
672                         }
673                 }
674
675         int cframe = 1, startFrame;
676                 if (blscene)
677                 {
678                         cframe=blscene->r.cfra;
679                         startFrame = blscene->r.sfra;
680                         blscene->r.cfra=startFrame;
681                         // update_for_newframe(); // XXX scene_update_for_newframe wont cut it!
682                         ketsjiengine->SetGame2IpoMode(game2ipo,startFrame);
683                 }
684
685                 // Quad buffered needs a special window.
686                 if (blscene->r.stereomode != RAS_IRasterizer::RAS_STEREO_QUADBUFFERED)
687                         rasterizer->SetStereoMode((RAS_IRasterizer::StereoMode) blscene->r.stereomode);
688
689                 if (exitrequested != KX_EXIT_REQUEST_QUIT_GAME)
690                 {
691                         // create a scene converter, create and convert the startingscene
692                         KX_ISceneConverter* sceneconverter = new KX_BlenderSceneConverter(maggie, ketsjiengine);
693                         ketsjiengine->SetSceneConverter(sceneconverter);
694                         sceneconverter->addInitFromFrame=true;
695                         
696                         if (always_use_expand_framing)
697                                 sceneconverter->SetAlwaysUseExpandFraming(true);
698
699                         if(usemat)
700                                 sceneconverter->SetMaterials(true);
701
702                         KX_Scene* startscene = new KX_Scene(keyboarddevice,
703                                 mousedevice,
704                                 networkdevice,
705                                 audiodevice,
706                                 startscenename,
707                                 blscene);
708
709                         // some python things
710                         PyObject* dictionaryobject = initGamePythonScripting("Ketsji", psl_Lowest, blenderdata);
711                         ketsjiengine->SetPythonDictionary(dictionaryobject);
712                         initRasterizer(rasterizer, canvas);
713                         PyObject *gameLogic = initGameLogic(ketsjiengine, startscene);
714                         PyDict_SetItemString(dictionaryobject, "GameLogic", gameLogic); // Same as importing the module
715                         initGameKeys();
716                         initPythonConstraintBinding();
717                         initMathutils();
718                         initGeometry();
719                         initBGL();
720 #ifdef WITH_FFMPEG
721                         initVideoTexture();
722 #endif
723
724                         if (sceneconverter)
725                         {
726                                 // convert and add scene
727                                 sceneconverter->ConvertScene(
728                                         startscenename,
729                                         startscene,
730                                         dictionaryobject,
731                                         keyboarddevice,
732                                         rendertools,
733                                         canvas);
734                                 ketsjiengine->AddScene(startscene);
735
736                                 // start the engine
737                                 ketsjiengine->StartEngine(false);
738                                 
739                                 ketsjiengine->SetUseFixedTime(true);
740                                 
741                                 ketsjiengine->SetTicRate(
742                                         (double) blscene->r.frs_sec /
743                                         (double) blscene->r.frs_sec_base);
744
745                                 // the mainloop
746                                 while ((blscene->r.cfra<=blscene->r.efra)&&(!exitrequested))
747                                 {
748                     printf("frame %i\n",blscene->r.cfra);
749                     // first check if we want to exit
750                                         exitrequested = ketsjiengine->GetExitCode();
751         
752                                         // kick the engine
753                                         ketsjiengine->NextFrame();
754                                     blscene->r.cfra=blscene->r.cfra+1;
755                                     // update_for_newframe(); // XXX scene_update_for_newframe wont cut it
756                                         
757                                 }
758                                 exitstring = ketsjiengine->GetExitString();
759                         }
760                         if (sceneconverter)
761                         {
762                                 delete sceneconverter;
763                                 sceneconverter = NULL;
764                         }
765                 }
766                 blscene->r.cfra=cframe;
767                 // set the cursor back to normal
768                 canvas->SetMouseState(RAS_ICanvas::MOUSE_NORMAL);
769
770                 // clean up some stuff
771                 audiodevice->StopCD();
772                 if (ketsjiengine)
773                 {
774                         delete ketsjiengine;
775                         ketsjiengine = NULL;
776                 }
777                 if (kxsystem)
778                 {
779                         delete kxsystem;
780                         kxsystem = NULL;
781                 }
782                 if (networkdevice)
783                 {
784                         delete networkdevice;
785                         networkdevice = NULL;
786                 }
787                 if (keyboarddevice)
788                 {
789                         delete keyboarddevice;
790                         keyboarddevice = NULL;
791                 }
792                 if (mousedevice)
793                 {
794                         delete mousedevice;
795                         mousedevice = NULL;
796                 }
797                 SND_DeviceManager::Unsubscribe();
798
799         } while (exitrequested == KX_EXIT_REQUEST_RESTART_GAME || exitrequested == KX_EXIT_REQUEST_START_OTHER_GAME);
800
801         // Release Python's GIL
802         PyGILState_Release(gilstate);
803 }