Blender V2.61 - r43446

BL_KetsjiEmbedStart.cpp

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): none yet.
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  * Blender's Ketsji startpoint
00027  */
00028 
00034 #include <signal.h>
00035 #include <stdlib.h>
00036 #include <stdio.h>
00037 
00038 #if defined(WIN32) && !defined(FREE_WINDOWS)
00039 // don't show stl-warnings
00040 #pragma warning (disable:4786)
00041 #endif
00042 
00043 #include "GL/glew.h"
00044 
00045 #include "KX_BlenderGL.h"
00046 #include "KX_BlenderCanvas.h"
00047 #include "KX_BlenderKeyboardDevice.h"
00048 #include "KX_BlenderMouseDevice.h"
00049 #include "KX_BlenderRenderTools.h"
00050 #include "KX_BlenderSystem.h"
00051 #include "BL_Material.h"
00052 
00053 #include "KX_KetsjiEngine.h"
00054 #include "KX_BlenderSceneConverter.h"
00055 #include "KX_PythonInit.h"
00056 #include "KX_PyConstraintBinding.h"
00057 
00058 #include "RAS_GLExtensionManager.h"
00059 #include "RAS_OpenGLRasterizer.h"
00060 #include "RAS_VAOpenGLRasterizer.h"
00061 #include "RAS_ListRasterizer.h"
00062 
00063 #include "NG_LoopBackNetworkDeviceInterface.h"
00064 
00065 #include "BL_System.h"
00066 
00067 #include "GPU_extensions.h"
00068 #include "Value.h"
00069 
00070 
00071 
00072 #ifdef __cplusplus
00073 extern "C" {
00074 #endif
00075     /***/
00076 #include "DNA_view3d_types.h"
00077 #include "DNA_screen_types.h"
00078 #include "DNA_userdef_types.h"
00079 #include "DNA_windowmanager_types.h"
00080 #include "BKE_global.h"
00081 #include "BKE_report.h"
00082 /* #include "BKE_screen.h" */ /* cant include this because of 'new' function name */
00083 extern float BKE_screen_view3d_zoom_to_fac(float camzoom);
00084 
00085 
00086 //XXX #include "BIF_screen.h"
00087 //XXX #include "BIF_scrarea.h"
00088 
00089 #include "BKE_main.h"
00090 #include "BLI_blenlib.h"
00091 #include "BLO_readfile.h"
00092 #include "DNA_scene_types.h"
00093 #include "BKE_ipo.h"
00094     /***/
00095 
00096 //XXX #include "BSE_headerbuttons.h"
00097 #include "BKE_context.h"
00098 #include "../../blender/windowmanager/WM_types.h"
00099 #include "../../blender/windowmanager/wm_window.h"
00100 #include "../../blender/windowmanager/wm_event_system.h"
00101 #ifdef __cplusplus
00102 }
00103 #endif
00104 
00105 #ifdef WITH_AUDASPACE
00106 #  include "AUD_C-API.h"
00107 #  include "AUD_I3DDevice.h"
00108 #  include "AUD_IDevice.h"
00109 #endif
00110 
00111 static BlendFileData *load_game_data(char *filename)
00112 {
00113     ReportList reports;
00114     BlendFileData *bfd;
00115     
00116     BKE_reports_init(&reports, RPT_STORE);
00117     bfd= BLO_read_from_file(filename, &reports);
00118 
00119     if (!bfd) {
00120         printf("Loading %s failed: ", filename);
00121         BKE_reports_print(&reports, RPT_ERROR);
00122     }
00123 
00124     BKE_reports_clear(&reports);
00125 
00126     return bfd;
00127 }
00128 
00129 extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *cam_frame, int always_use_expand_framing)
00130 {
00131     /* context values */
00132     struct wmWindow *win= CTX_wm_window(C);
00133     struct Scene *startscene= CTX_data_scene(C);
00134     struct Main* maggie1= CTX_data_main(C);
00135 
00136 
00137     RAS_Rect area_rect;
00138     area_rect.SetLeft(cam_frame->xmin);
00139     area_rect.SetBottom(cam_frame->ymin);
00140     area_rect.SetRight(cam_frame->xmax);
00141     area_rect.SetTop(cam_frame->ymax);
00142 
00143     int exitrequested = KX_EXIT_REQUEST_NO_REQUEST;
00144     Main* blenderdata = maggie1;
00145 
00146     char* startscenename = startscene->id.name+2;
00147     char pathname[FILE_MAXDIR+FILE_MAXFILE], oldsce[FILE_MAXDIR+FILE_MAXFILE];
00148     STR_String exitstring = "";
00149     BlendFileData *bfd= NULL;
00150 
00151     BLI_strncpy(pathname, blenderdata->name, sizeof(pathname));
00152     BLI_strncpy(oldsce, G.main->name, sizeof(oldsce));
00153 #ifdef WITH_PYTHON
00154     resetGamePythonPath(); // need this so running a second time wont use an old blendfiles path
00155     setGamePythonPath(G.main->name);
00156 
00157     // Acquire Python's GIL (global interpreter lock)
00158     // so we can safely run Python code and API calls
00159     PyGILState_STATE gilstate = PyGILState_Ensure();
00160     
00161     PyObject *pyGlobalDict = PyDict_New(); /* python utility storage, spans blend file loading */
00162 #endif
00163     
00164     bgl::InitExtensions(true);
00165 
00166     // VBO code for derived mesh is not compatible with BGE (couldn't find why), so disable
00167     int disableVBO = (U.gameflags & USER_DISABLE_VBO);
00168     U.gameflags |= USER_DISABLE_VBO;
00169 
00170     // Globals to be carried on over blender files
00171     GlobalSettings gs;
00172     gs.matmode= startscene->gm.matmode;
00173     gs.glslflag= startscene->gm.flag;
00174 
00175     do
00176     {
00177         View3D *v3d= CTX_wm_view3d(C);
00178         RegionView3D *rv3d= CTX_wm_region_view3d(C);
00179 
00180         // get some preferences
00181         SYS_SystemHandle syshandle = SYS_GetSystem();
00182         bool properties = (SYS_GetCommandLineInt(syshandle, "show_properties", 0) != 0);
00183         bool usefixed = (SYS_GetCommandLineInt(syshandle, "fixedtime", 0) != 0);
00184         bool profile = (SYS_GetCommandLineInt(syshandle, "show_profile", 0) != 0);
00185         bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0);
00186         bool animation_record = (SYS_GetCommandLineInt(syshandle, "animation_record", 0) != 0);
00187         bool displaylists = (SYS_GetCommandLineInt(syshandle, "displaylists", 0) != 0);
00188 #ifdef WITH_PYTHON
00189         bool nodepwarnings = (SYS_GetCommandLineInt(syshandle, "ignore_deprecation_warnings", 0) != 0);
00190 #endif
00191         bool novertexarrays = (SYS_GetCommandLineInt(syshandle, "novertexarrays", 0) != 0);
00192         bool mouse_state = startscene->gm.flag & GAME_SHOW_MOUSE;
00193         bool restrictAnimFPS = startscene->gm.flag & GAME_RESTRICT_ANIM_UPDATES;
00194 
00195         if(animation_record) usefixed= true; /* override since you's always want fixed time for sim recording */
00196 
00197         // create the canvas, rasterizer and rendertools
00198         RAS_ICanvas* canvas = new KX_BlenderCanvas(win, area_rect, ar);
00199         
00200         // default mouse state set on render panel
00201         if (mouse_state)
00202             canvas->SetMouseState(RAS_ICanvas::MOUSE_NORMAL);
00203         else
00204             canvas->SetMouseState(RAS_ICanvas::MOUSE_INVISIBLE);
00205         RAS_IRenderTools* rendertools = new KX_BlenderRenderTools();
00206         RAS_IRasterizer* rasterizer = NULL;
00207         
00208         if(displaylists) {
00209             if (GLEW_VERSION_1_1 && !novertexarrays)
00210                 rasterizer = new RAS_ListRasterizer(canvas, true, true);
00211             else
00212                 rasterizer = new RAS_ListRasterizer(canvas);
00213         }
00214         else if (GLEW_VERSION_1_1 && !novertexarrays)
00215             rasterizer = new RAS_VAOpenGLRasterizer(canvas, false);
00216         else
00217             rasterizer = new RAS_OpenGLRasterizer(canvas);
00218         
00219         // create the inputdevices
00220         KX_BlenderKeyboardDevice* keyboarddevice = new KX_BlenderKeyboardDevice();
00221         KX_BlenderMouseDevice* mousedevice = new KX_BlenderMouseDevice();
00222         
00223         // create a networkdevice
00224         NG_NetworkDeviceInterface* networkdevice = new
00225             NG_LoopBackNetworkDeviceInterface();
00226 
00227         //
00228         // create a ketsji/blendersystem (only needed for timing and stuff)
00229         KX_BlenderSystem* kxsystem = new KX_BlenderSystem();
00230         
00231         // create the ketsjiengine
00232         KX_KetsjiEngine* ketsjiengine = new KX_KetsjiEngine(kxsystem);
00233         
00234         // set the devices
00235         ketsjiengine->SetKeyboardDevice(keyboarddevice);
00236         ketsjiengine->SetMouseDevice(mousedevice);
00237         ketsjiengine->SetNetworkDevice(networkdevice);
00238         ketsjiengine->SetCanvas(canvas);
00239         ketsjiengine->SetRenderTools(rendertools);
00240         ketsjiengine->SetRasterizer(rasterizer);
00241         ketsjiengine->SetUseFixedTime(usefixed);
00242         ketsjiengine->SetTimingDisplay(frameRate, profile, properties);
00243         ketsjiengine->SetRestrictAnimationFPS(restrictAnimFPS);
00244         KX_KetsjiEngine::SetExitKey(ConvertKeyCode(startscene->gm.exitkey));
00245 
00246         //set the global settings (carried over if restart/load new files)
00247         ketsjiengine->SetGlobalSettings(&gs);
00248 
00249 #ifdef WITH_PYTHON
00250         CValue::SetDeprecationWarnings(nodepwarnings);
00251 #endif
00252 
00253         //lock frame and camera enabled - storing global values
00254         int tmp_lay= startscene->lay;
00255         Object *tmp_camera = startscene->camera;
00256 
00257         if (v3d->scenelock==0){
00258             startscene->lay= v3d->lay;
00259             startscene->camera= v3d->camera;
00260         }
00261 
00262         // some blender stuff
00263         float camzoom;
00264         int draw_letterbox = 0;
00265         
00266         if(rv3d->persp==RV3D_CAMOB) {
00267             if(startscene->gm.framing.type == SCE_GAMEFRAMING_BARS) { /* Letterbox */
00268                 camzoom = 1.0f;
00269                 draw_letterbox = 1;
00270             }
00271             else {
00272                 camzoom = 1.0 / BKE_screen_view3d_zoom_to_fac(rv3d->camzoom);
00273             }
00274         }
00275         else {
00276             camzoom = 2.0;
00277         }
00278 
00279 
00280         ketsjiengine->SetDrawType(v3d->drawtype);
00281         ketsjiengine->SetCameraZoom(camzoom);
00282         
00283         // if we got an exitcode 3 (KX_EXIT_REQUEST_START_OTHER_GAME) load a different file
00284         if (exitrequested == KX_EXIT_REQUEST_START_OTHER_GAME || exitrequested == KX_EXIT_REQUEST_RESTART_GAME)
00285         {
00286             exitrequested = KX_EXIT_REQUEST_NO_REQUEST;
00287             if (bfd) BLO_blendfiledata_free(bfd);
00288             
00289             char basedpath[FILE_MAX];
00290             // base the actuator filename with respect
00291             // to the original file working directory
00292 
00293             if (exitstring != "")
00294                 strcpy(basedpath, exitstring.Ptr());
00295 
00296             // load relative to the last loaded file, this used to be relative
00297             // to the first file but that makes no sense, relative paths in
00298             // blend files should be relative to that file, not some other file
00299             // that happened to be loaded first
00300             BLI_path_abs(basedpath, pathname);
00301             bfd = load_game_data(basedpath);
00302             
00303             // if it wasn't loaded, try it forced relative
00304             if (!bfd)
00305             {
00306                 // just add "//" in front of it
00307                 char temppath[242];
00308                 strcpy(temppath, "//");
00309                 strcat(temppath, basedpath);
00310                 
00311                 BLI_path_abs(temppath, pathname);
00312                 bfd = load_game_data(temppath);
00313             }
00314             
00315             // if we got a loaded blendfile, proceed
00316             if (bfd)
00317             {
00318                 blenderdata = bfd->main;
00319                 startscenename = bfd->curscene->id.name + 2;
00320 
00321                 if(blenderdata) {
00322                     BLI_strncpy(G.main->name, blenderdata->name, sizeof(G.main->name));
00323                     BLI_strncpy(pathname, blenderdata->name, sizeof(pathname));
00324 #ifdef WITH_PYTHON
00325                     setGamePythonPath(G.main->name);
00326 #endif
00327                 }
00328             }
00329             // else forget it, we can't find it
00330             else
00331             {
00332                 exitrequested = KX_EXIT_REQUEST_QUIT_GAME;
00333             }
00334         }
00335 
00336         Scene *scene= bfd ? bfd->curscene : (Scene *)BLI_findstring(&blenderdata->scene, startscenename, offsetof(ID, name) + 2);
00337 
00338         if (scene)
00339         {
00340             int startFrame = scene->r.cfra;
00341             ketsjiengine->SetAnimRecordMode(animation_record, startFrame);
00342             
00343             // Quad buffered needs a special window.
00344             if(scene->gm.stereoflag == STEREO_ENABLED){
00345                 if (scene->gm.stereomode != RAS_IRasterizer::RAS_STEREO_QUADBUFFERED)
00346                     rasterizer->SetStereoMode((RAS_IRasterizer::StereoMode) scene->gm.stereomode);
00347 
00348                 rasterizer->SetEyeSeparation(scene->gm.eyeseparation);
00349             }
00350 
00351             rasterizer->SetBackColor(scene->gm.framing.col[0], scene->gm.framing.col[1], scene->gm.framing.col[2], 0.0f);
00352         }
00353         
00354         if (exitrequested != KX_EXIT_REQUEST_QUIT_GAME)
00355         {
00356             if (rv3d->persp != RV3D_CAMOB)
00357             {
00358                 ketsjiengine->EnableCameraOverride(startscenename);
00359                 ketsjiengine->SetCameraOverrideUseOrtho((rv3d->persp == RV3D_ORTHO));
00360                 ketsjiengine->SetCameraOverrideProjectionMatrix(MT_CmMatrix4x4(rv3d->winmat));
00361                 ketsjiengine->SetCameraOverrideViewMatrix(MT_CmMatrix4x4(rv3d->viewmat));
00362                 if(rv3d->persp == RV3D_ORTHO)
00363                 {
00364                     ketsjiengine->SetCameraOverrideClipping(-v3d->far, v3d->far);
00365                 }
00366                 else
00367                 {
00368                     ketsjiengine->SetCameraOverrideClipping(v3d->near, v3d->far);
00369                 }
00370                 ketsjiengine->SetCameraOverrideLens(v3d->lens);
00371             }
00372             
00373             // create a scene converter, create and convert the startingscene
00374             KX_ISceneConverter* sceneconverter = new KX_BlenderSceneConverter(blenderdata, ketsjiengine);
00375             ketsjiengine->SetSceneConverter(sceneconverter);
00376             sceneconverter->addInitFromFrame=false;
00377             if (always_use_expand_framing)
00378                 sceneconverter->SetAlwaysUseExpandFraming(true);
00379 
00380             bool usemat = false, useglslmat = false;
00381 
00382             if(GLEW_ARB_multitexture && GLEW_VERSION_1_1)
00383                 usemat = true;
00384 
00385             if(GPU_glsl_support())
00386                 useglslmat = true;
00387             else if(gs.matmode == GAME_MAT_GLSL)
00388                 usemat = false;
00389 
00390             if(usemat && (gs.matmode != GAME_MAT_TEXFACE))
00391                 sceneconverter->SetMaterials(true);
00392             if(useglslmat && (gs.matmode == GAME_MAT_GLSL))
00393                 sceneconverter->SetGLSLMaterials(true);
00394                     
00395             KX_Scene* startscene = new KX_Scene(keyboarddevice,
00396                 mousedevice,
00397                 networkdevice,
00398                 startscenename,
00399                 scene,
00400                 canvas);
00401 
00402 #ifdef WITH_PYTHON
00403             // some python things
00404             PyObject *gameLogic, *gameLogic_keys;
00405             setupGamePython(ketsjiengine, startscene, blenderdata, pyGlobalDict, &gameLogic, &gameLogic_keys, 0, NULL);
00406 #endif // WITH_PYTHON
00407 
00408             //initialize Dome Settings
00409             if(scene->gm.stereoflag == STEREO_DOME)
00410                 ketsjiengine->InitDome(scene->gm.dome.res, scene->gm.dome.mode, scene->gm.dome.angle, scene->gm.dome.resbuf, scene->gm.dome.tilt, scene->gm.dome.warptext);
00411 
00412             // initialize 3D Audio Settings
00413             AUD_I3DDevice* dev = AUD_get3DDevice();
00414             if(dev)
00415             {
00416                 dev->setSpeedOfSound(scene->audio.speed_of_sound);
00417                 dev->setDopplerFactor(scene->audio.doppler_factor);
00418                 dev->setDistanceModel(AUD_DistanceModel(scene->audio.distance_model));
00419             }
00420 
00421             // from see blender.c:
00422             // FIXME: this version patching should really be part of the file-reading code,
00423             // but we still get too many unrelated data-corruption crashes otherwise...
00424             if (blenderdata->versionfile < 250)
00425                 do_versions_ipos_to_animato(blenderdata);
00426 
00427             if (sceneconverter)
00428             {
00429                 // convert and add scene
00430                 sceneconverter->ConvertScene(
00431                     startscene,
00432                     rendertools,
00433                     canvas);
00434                 ketsjiengine->AddScene(startscene);
00435                 
00436                 // init the rasterizer
00437                 rasterizer->Init();
00438                 
00439                 // start the engine
00440                 ketsjiengine->StartEngine(true);
00441                 
00442 
00443                 // Set the animation playback rate for ipo's and actions
00444                 // the framerate below should patch with FPS macro defined in blendef.h
00445                 // Could be in StartEngine set the framerate, we need the scene to do this
00446                 ketsjiengine->SetAnimFrameRate(FPS);
00447                 
00448                 // the mainloop
00449                 printf("\nBlender Game Engine Started\n");
00450                 while (!exitrequested)
00451                 {
00452                     // first check if we want to exit
00453                     exitrequested = ketsjiengine->GetExitCode();
00454                     
00455                     // kick the engine
00456                     bool render = ketsjiengine->NextFrame();
00457                     
00458                     if (render)
00459                     {
00460                         if(draw_letterbox) {
00461                             // Clear screen to border color
00462                             // We do this here since we set the canvas to be within the frames. This means the engine
00463                             // itself is unaware of the extra space, so we clear the whole region for it.
00464                             glClearColor(scene->gm.framing.col[0], scene->gm.framing.col[1], scene->gm.framing.col[2], 1.0f);
00465                             glViewport(ar->winrct.xmin, ar->winrct.ymin,
00466                                 ar->winrct.xmax - ar->winrct.xmin, ar->winrct.ymax - ar->winrct.ymin);
00467                             glClear(GL_COLOR_BUFFER_BIT);
00468                         }
00469 
00470                         // render the frame
00471                         ketsjiengine->Render();
00472                     }
00473                     
00474                     wm_window_process_events_nosleep();
00475                     
00476                     // test for the ESC key
00477                     //XXX while (qtest())
00478                     while(wmEvent *event= (wmEvent *)win->queue.first)
00479                     {
00480                         short val = 0;
00481                         //unsigned short event = 0; //XXX extern_qread(&val);
00482                         
00483                         if (keyboarddevice->ConvertBlenderEvent(event->type,event->val))
00484                             exitrequested = KX_EXIT_REQUEST_BLENDER_ESC;
00485                         
00486                             /* Coordinate conversion... where
00487                             * should this really be?
00488                         */
00489                         if (event->type==MOUSEMOVE) {
00490                             /* Note, not nice! XXX 2.5 event hack */
00491                             val = event->x - ar->winrct.xmin;
00492                             mousedevice->ConvertBlenderEvent(MOUSEX, val);
00493                             
00494                             val = ar->winy - (event->y - ar->winrct.ymin) - 1;
00495                             mousedevice->ConvertBlenderEvent(MOUSEY, val);
00496                         }
00497                         else {
00498                             mousedevice->ConvertBlenderEvent(event->type,event->val);
00499                         }
00500                         
00501                         BLI_remlink(&win->queue, event);
00502                         wm_event_free(event);
00503                     }
00504                     
00505                     if(win != CTX_wm_window(C)) {
00506                         exitrequested= KX_EXIT_REQUEST_OUTSIDE; /* window closed while bge runs */
00507                     }
00508                 }
00509                 printf("Blender Game Engine Finished\n");
00510                 exitstring = ketsjiengine->GetExitString();
00511                 gs = *(ketsjiengine->GetGlobalSettings());
00512 
00513 
00514                 // when exiting the mainloop
00515 #ifdef WITH_PYTHON
00516                 // Clears the dictionary by hand:
00517                 // This prevents, extra references to global variables
00518                 // inside the GameLogic dictionary when the python interpreter is finalized.
00519                 // which allows the scene to safely delete them :)
00520                 // see: (space.c)->start_game
00521                 
00522                 //PyDict_Clear(PyModule_GetDict(gameLogic));
00523                 
00524                 // Keep original items, means python plugins will autocomplete members
00525                 PyObject *gameLogic_keys_new = PyDict_Keys(PyModule_GetDict(gameLogic));
00526                 const Py_ssize_t numitems= PyList_GET_SIZE(gameLogic_keys_new);
00527                 Py_ssize_t listIndex;
00528                 for (listIndex=0; listIndex < numitems; listIndex++)  {
00529                     PyObject* item = PyList_GET_ITEM(gameLogic_keys_new, listIndex);
00530                     if (!PySequence_Contains(gameLogic_keys, item)) {
00531                         PyDict_DelItem( PyModule_GetDict(gameLogic), item);
00532                     }
00533                 }
00534                 Py_DECREF(gameLogic_keys_new);
00535                 gameLogic_keys_new = NULL;
00536 #endif
00537                 ketsjiengine->StopEngine();
00538 #ifdef WITH_PYTHON
00539                 exitGamePythonScripting();
00540 #endif
00541                 networkdevice->Disconnect();
00542             }
00543             if (sceneconverter)
00544             {
00545                 delete sceneconverter;
00546                 sceneconverter = NULL;
00547             }
00548 
00549 #ifdef WITH_PYTHON
00550             Py_DECREF(gameLogic_keys);
00551             gameLogic_keys = NULL;
00552 #endif
00553         }
00554         //lock frame and camera enabled - restoring global values
00555         if (v3d->scenelock==0){
00556             startscene->lay= tmp_lay;
00557             startscene->camera= tmp_camera;
00558         }
00559 
00560         if(exitrequested != KX_EXIT_REQUEST_OUTSIDE)
00561         {
00562             // set the cursor back to normal
00563             canvas->SetMouseState(RAS_ICanvas::MOUSE_NORMAL);
00564         }
00565         
00566         // clean up some stuff
00567         if (ketsjiengine)
00568         {
00569             delete ketsjiengine;
00570             ketsjiengine = NULL;
00571         }
00572         if (kxsystem)
00573         {
00574             delete kxsystem;
00575             kxsystem = NULL;
00576         }
00577         if (networkdevice)
00578         {
00579             delete networkdevice;
00580             networkdevice = NULL;
00581         }
00582         if (keyboarddevice)
00583         {
00584             delete keyboarddevice;
00585             keyboarddevice = NULL;
00586         }
00587         if (mousedevice)
00588         {
00589             delete mousedevice;
00590             mousedevice = NULL;
00591         }
00592         if (rasterizer)
00593         {
00594             delete rasterizer;
00595             rasterizer = NULL;
00596         }
00597         if (rendertools)
00598         {
00599             delete rendertools;
00600             rendertools = NULL;
00601         }
00602         if (canvas)
00603         {
00604             delete canvas;
00605             canvas = NULL;
00606         }
00607 
00608         // stop all remaining playing sounds
00609         AUD_getDevice()->stopAll();
00610     
00611     } while (exitrequested == KX_EXIT_REQUEST_RESTART_GAME || exitrequested == KX_EXIT_REQUEST_START_OTHER_GAME);
00612     
00613     if (!disableVBO)
00614         U.gameflags &= ~USER_DISABLE_VBO;
00615 
00616     if (bfd) BLO_blendfiledata_free(bfd);
00617 
00618     BLI_strncpy(G.main->name, oldsce, sizeof(G.main->name));
00619 
00620 #ifdef WITH_PYTHON
00621     Py_DECREF(pyGlobalDict);
00622 
00623     // Release Python's GIL
00624     PyGILState_Release(gilstate);
00625 #endif
00626 
00627 }