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