Blender V2.61 - r43446

GPG_Application.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  * GHOST Blender Player application implementation file.
00027  */
00028 
00034 #ifdef WIN32
00035     #pragma warning (disable:4786) // suppress stl-MSVC debug info warning
00036     #include <windows.h>
00037 #endif
00038 
00039 #include "GL/glew.h"
00040 #include "GPU_extensions.h"
00041 
00042 #include "GPG_Application.h"
00043 #include "BL_BlenderDataConversion.h"
00044 
00045 #include <iostream>
00046 #include <MT_assert.h>
00047 #include <stdlib.h>
00048 
00049 /**********************************
00050  * Begin Blender include block
00051  **********************************/
00052 #ifdef __cplusplus
00053 extern "C"
00054 {
00055 #endif  // __cplusplus
00056 #include "BLI_blenlib.h"
00057 #include "BLO_readfile.h"
00058 #include "BKE_global.h"
00059 #include "BKE_main.h"
00060 #include "BKE_sound.h"
00061 #include "IMB_imbuf.h"
00062 #include "DNA_scene_types.h"
00063 #ifdef __cplusplus
00064 }
00065 #endif // __cplusplus
00066 /**********************************
00067  * End Blender include block
00068  **********************************/
00069 
00070 
00071 #include "BL_System.h"
00072 #include "KX_KetsjiEngine.h"
00073 
00074 // include files needed by "KX_BlenderSceneConverter.h"
00075 #include "CTR_Map.h"
00076 #include "SCA_IActuator.h"
00077 #include "RAS_MeshObject.h"
00078 #include "RAS_OpenGLRasterizer.h"
00079 #include "RAS_VAOpenGLRasterizer.h"
00080 #include "RAS_ListRasterizer.h"
00081 #include "RAS_GLExtensionManager.h"
00082 #include "KX_PythonInit.h"
00083 #include "KX_PyConstraintBinding.h"
00084 #include "BL_Material.h" // MAXTEX
00085 
00086 #include "KX_BlenderSceneConverter.h"
00087 #include "NG_LoopBackNetworkDeviceInterface.h"
00088 
00089 #include "GPC_MouseDevice.h"
00090 #include "GPC_RenderTools.h"
00091 #include "GPG_Canvas.h" 
00092 #include "GPG_KeyboardDevice.h"
00093 #include "GPG_System.h"
00094 
00095 #include "STR_String.h"
00096 
00097 #include "GHOST_ISystem.h"
00098 #include "GHOST_IEvent.h"
00099 #include "GHOST_IEventConsumer.h"
00100 #include "GHOST_IWindow.h"
00101 #include "GHOST_Rect.h"
00102 
00103 static void frameTimerProc(GHOST_ITimerTask* task, GHOST_TUns64 time);
00104 
00105 static GHOST_ISystem* fSystem = 0;
00106 static const int kTimerFreq = 10;
00107 
00108 GPG_Application::GPG_Application(GHOST_ISystem* system)
00109     : m_startSceneName(""), 
00110       m_startScene(0),
00111       m_maggie(0),
00112       m_exitRequested(0),
00113       m_system(system), 
00114       m_mainWindow(0), 
00115       m_frameTimer(0), 
00116       m_cursor(GHOST_kStandardCursorFirstCursor),
00117       m_engineInitialized(0), 
00118       m_engineRunning(0), 
00119       m_isEmbedded(false),
00120       m_ketsjiengine(0),
00121       m_kxsystem(0), 
00122       m_keyboard(0), 
00123       m_mouse(0), 
00124       m_canvas(0), 
00125       m_rendertools(0), 
00126       m_rasterizer(0), 
00127       m_sceneconverter(0),
00128       m_networkdevice(0),
00129       m_blendermat(0),
00130       m_blenderglslmat(0),
00131       m_pyGlobalDictString(0),
00132       m_pyGlobalDictString_Length(0)
00133 {
00134     fSystem = system;
00135 }
00136 
00137 
00138 
00139 GPG_Application::~GPG_Application(void)
00140 {
00141     if(m_pyGlobalDictString) {
00142         delete [] m_pyGlobalDictString;
00143         m_pyGlobalDictString = 0;
00144         m_pyGlobalDictString_Length = 0;
00145     }
00146 
00147     exitEngine();
00148     fSystem->disposeWindow(m_mainWindow);
00149 }
00150 
00151 
00152 
00153 bool GPG_Application::SetGameEngineData(struct Main* maggie, Scene *scene, GlobalSettings *gs, int argc, char **argv)
00154 {
00155     bool result = false;
00156 
00157     if (maggie != NULL && scene != NULL)
00158     {
00159 // XXX      G.scene = scene;
00160         m_maggie = maggie;
00161         m_startSceneName = scene->id.name+2;
00162         m_startScene = scene;
00163         result = true;
00164     }
00165     
00166     /* Python needs these */
00167     m_argc= argc;
00168     m_argv= argv;
00169 
00170     /* Global Settings */
00171     m_globalSettings= gs;
00172 
00173     return result;
00174 }
00175 
00176 
00177 #ifdef WIN32
00178 #define SCR_SAVE_MOUSE_MOVE_THRESHOLD 15
00179 
00180 static HWND found_ghost_window_hwnd;
00181 static GHOST_IWindow* ghost_window_to_find;
00182 static WNDPROC ghost_wnd_proc;
00183 static POINT scr_save_mouse_pos;
00184 
00185 static LRESULT CALLBACK screenSaverWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
00186 {
00187     BOOL close = FALSE;
00188     switch (uMsg)
00189     {
00190         case WM_MOUSEMOVE:
00191         { 
00192             POINT pt; 
00193             GetCursorPos(&pt);
00194             LONG dx = scr_save_mouse_pos.x - pt.x;
00195             LONG dy = scr_save_mouse_pos.y - pt.y;
00196             if (abs(dx) > SCR_SAVE_MOUSE_MOVE_THRESHOLD
00197                     || abs(dy) > SCR_SAVE_MOUSE_MOVE_THRESHOLD)
00198             {
00199                 close = TRUE;
00200             }
00201             scr_save_mouse_pos = pt;
00202             break;
00203         }
00204         case WM_LBUTTONDOWN: 
00205         case WM_MBUTTONDOWN: 
00206         case WM_RBUTTONDOWN: 
00207         case WM_KEYDOWN:
00208             close = TRUE;
00209     }
00210     if (close)
00211         PostMessage(hwnd,WM_CLOSE,0,0);
00212     return CallWindowProc(ghost_wnd_proc, hwnd, uMsg, wParam, lParam);
00213 }
00214 
00215 BOOL CALLBACK findGhostWindowHWNDProc(HWND hwnd, LPARAM lParam)
00216 {
00217     GHOST_IWindow *p = (GHOST_IWindow*) GetWindowLongPtr(hwnd, GWLP_USERDATA);
00218     BOOL ret = TRUE;
00219     if (p == ghost_window_to_find)
00220     {
00221         found_ghost_window_hwnd = hwnd;
00222         ret = FALSE;
00223     }
00224     return ret;
00225 }
00226 
00227 static HWND findGhostWindowHWND(GHOST_IWindow* window)
00228 {
00229     found_ghost_window_hwnd = NULL;
00230     ghost_window_to_find = window;
00231     EnumWindows(findGhostWindowHWNDProc, NULL);
00232     return found_ghost_window_hwnd;
00233 }
00234 
00235 bool GPG_Application::startScreenSaverPreview(
00236     HWND parentWindow,
00237     const bool stereoVisual,
00238     const int stereoMode,
00239     const GHOST_TUns16 samples)
00240 {
00241     bool success = false;
00242 
00243     RECT rc;
00244     if (GetWindowRect(parentWindow, &rc))
00245     {
00246         int windowWidth = rc.right - rc.left;
00247         int windowHeight = rc.bottom - rc.top;
00248         STR_String title = "";
00249                             
00250         m_mainWindow = fSystem->createWindow(title, 0, 0, windowWidth, windowHeight, GHOST_kWindowStateMinimized,
00251             GHOST_kDrawingContextTypeOpenGL, stereoVisual, samples);
00252         if (!m_mainWindow) {
00253             printf("error: could not create main window\n");
00254             exit(-1);
00255         }
00256 
00257         HWND ghost_hwnd = findGhostWindowHWND(m_mainWindow);
00258         if (!ghost_hwnd) {
00259             printf("error: could find main window\n");
00260             exit(-1);
00261         }
00262 
00263         SetParent(ghost_hwnd, parentWindow);
00264         LONG style = GetWindowLong(ghost_hwnd, GWL_STYLE);
00265         LONG exstyle = GetWindowLong(ghost_hwnd, GWL_EXSTYLE);
00266 
00267         RECT adjrc = { 0, 0, windowWidth, windowHeight };
00268         AdjustWindowRectEx(&adjrc, style, FALSE, exstyle);
00269 
00270         style = (style & (~(WS_POPUP|WS_OVERLAPPEDWINDOW|WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_TILEDWINDOW ))) | WS_CHILD;
00271         SetWindowLong(ghost_hwnd, GWL_STYLE, style);
00272         SetWindowPos(ghost_hwnd, NULL, adjrc.left, adjrc.top, 0, 0, SWP_NOZORDER|SWP_NOSIZE|SWP_NOACTIVATE);
00273 
00274         /* Check the size of the client rectangle of the window and resize the window
00275          * so that the client rectangle has the size requested.
00276          */
00277         m_mainWindow->setClientSize(windowWidth, windowHeight);
00278 
00279         success = initEngine(m_mainWindow, stereoMode);
00280         if (success) {
00281             success = startEngine();
00282         }
00283 
00284     }
00285     return success;
00286 }
00287 
00288 bool GPG_Application::startScreenSaverFullScreen(
00289         int width,
00290         int height,
00291         int bpp,int frequency,
00292         const bool stereoVisual,
00293         const int stereoMode,
00294         const GHOST_TUns16 samples)
00295 {
00296     bool ret = startFullScreen(width, height, bpp, frequency, stereoVisual, stereoMode, samples);
00297     if (ret)
00298     {
00299         HWND ghost_hwnd = findGhostWindowHWND(m_mainWindow);
00300         if (ghost_hwnd != NULL)
00301         {
00302             GetCursorPos(&scr_save_mouse_pos);
00303             ghost_wnd_proc = (WNDPROC) GetWindowLongPtr(ghost_hwnd, GWLP_WNDPROC);
00304             SetWindowLongPtr(ghost_hwnd,GWLP_WNDPROC, (uintptr_t) screenSaverWindowProc);
00305         }
00306     }
00307     return ret;
00308 }
00309 
00310 #endif
00311 
00312 bool GPG_Application::startWindow(STR_String& title,
00313     int windowLeft,
00314     int windowTop,
00315     int windowWidth,
00316     int windowHeight,
00317     const bool stereoVisual,
00318     const int stereoMode,
00319     const GHOST_TUns16 samples)
00320 {
00321     bool success;
00322     // Create the main window
00323     //STR_String title ("Blender Player - GHOST");
00324     m_mainWindow = fSystem->createWindow(title, windowLeft, windowTop, windowWidth, windowHeight, GHOST_kWindowStateNormal,
00325         GHOST_kDrawingContextTypeOpenGL, stereoVisual, samples);
00326     if (!m_mainWindow) {
00327         printf("error: could not create main window\n");
00328         exit(-1);
00329     }
00330 
00331     /* Check the size of the client rectangle of the window and resize the window
00332      * so that the client rectangle has the size requested.
00333      */
00334     m_mainWindow->setClientSize(windowWidth, windowHeight);
00335     m_mainWindow->setCursorVisibility(false);
00336 
00337     success = initEngine(m_mainWindow, stereoMode);
00338     if (success) {
00339         success = startEngine();
00340     }
00341     return success;
00342 }
00343 
00344 bool GPG_Application::startEmbeddedWindow(STR_String& title,
00345     const GHOST_TEmbedderWindowID parentWindow, 
00346     const bool stereoVisual, 
00347     const int stereoMode,
00348     const GHOST_TUns16 samples) {
00349     GHOST_TWindowState state = GHOST_kWindowStateNormal;
00350     if (parentWindow != 0)
00351         state = GHOST_kWindowStateEmbedded;
00352     m_mainWindow = fSystem->createWindow(title, 0, 0, 0, 0, state,
00353         GHOST_kDrawingContextTypeOpenGL, stereoVisual, samples, parentWindow);
00354 
00355     if (!m_mainWindow) {
00356         printf("error: could not create main window\n");
00357         exit(-1);
00358     }
00359     m_isEmbedded = true;
00360 
00361     bool success = initEngine(m_mainWindow, stereoMode);
00362     if (success) {
00363         success = startEngine();
00364     }
00365     return success;
00366 }
00367 
00368 
00369 bool GPG_Application::startFullScreen(
00370         int width,
00371         int height,
00372         int bpp,int frequency,
00373         const bool stereoVisual,
00374         const int stereoMode,
00375         const GHOST_TUns16 samples,
00376         bool useDesktop)
00377 {
00378     bool success;
00379     GHOST_TUns32 sysWidth=0, sysHeight=0;
00380     fSystem->getMainDisplayDimensions(sysWidth, sysHeight);
00381     // Create the main window
00382     GHOST_DisplaySetting setting;
00383     setting.xPixels = (useDesktop) ? sysWidth : width;
00384     setting.yPixels = (useDesktop) ? sysHeight : height;
00385     setting.bpp = bpp;
00386     setting.frequency = frequency;
00387 
00388     fSystem->beginFullScreen(setting, &m_mainWindow, stereoVisual, samples);
00389     m_mainWindow->setCursorVisibility(false);
00390     m_mainWindow->setState(GHOST_kWindowStateFullScreen);
00391 
00392     success = initEngine(m_mainWindow, stereoMode);
00393     if (success) {
00394         success = startEngine();
00395     }
00396     return success;
00397 }
00398 
00399 
00400 
00401 
00402 bool GPG_Application::StartGameEngine(int stereoMode)
00403 {
00404     bool success = initEngine(m_mainWindow, stereoMode);
00405     
00406     if (success)
00407         success = startEngine();
00408 
00409     return success;
00410 }
00411 
00412 
00413 
00414 void GPG_Application::StopGameEngine()
00415 {
00416     exitEngine();
00417 }
00418 
00419 
00420 
00421 bool GPG_Application::processEvent(GHOST_IEvent* event)
00422 {
00423     bool handled = true;
00424 
00425     switch (event->getType())
00426     {
00427         case GHOST_kEventUnknown:
00428             break;
00429 
00430         case GHOST_kEventButtonDown:
00431             handled = handleButton(event, true);
00432             break;
00433 
00434         case GHOST_kEventButtonUp:
00435             handled = handleButton(event, false);
00436             break;
00437             
00438         case GHOST_kEventWheel:
00439             handled = handleWheel(event);
00440             break;
00441 
00442         case GHOST_kEventCursorMove:
00443             handled = handleCursorMove(event);
00444             break;
00445 
00446         case GHOST_kEventKeyDown:
00447             handleKey(event, true);
00448             break;
00449 
00450         case GHOST_kEventKeyUp:
00451             handleKey(event, false);
00452             break;
00453 
00454 
00455         case GHOST_kEventWindowClose:
00456         case GHOST_kEventQuit:
00457             m_exitRequested = KX_EXIT_REQUEST_OUTSIDE;
00458             break;
00459 
00460         case GHOST_kEventWindowActivate:
00461             handled = false;
00462             break;
00463         case GHOST_kEventWindowDeactivate:
00464             handled = false;
00465             break;
00466 
00467         case GHOST_kEventWindowUpdate:
00468             {
00469                 GHOST_IWindow* window = event->getWindow();
00470                 if (!m_system->validWindow(window)) break;
00471                 // Update the state of the game engine
00472                 if (m_kxsystem && !m_exitRequested)
00473                 {
00474                     // Proceed to next frame
00475                     window->activateDrawingContext();
00476 
00477                     // first check if we want to exit
00478                     m_exitRequested = m_ketsjiengine->GetExitCode();
00479                     
00480                     // kick the engine
00481                     bool renderFrame = m_ketsjiengine->NextFrame();
00482                     if (renderFrame)
00483                     {
00484                         // render the frame
00485                         m_ketsjiengine->Render();
00486                     }
00487                 }
00488                 m_exitString = m_ketsjiengine->GetExitString();
00489             }
00490             break;
00491         
00492         case GHOST_kEventWindowSize:
00493             {
00494             GHOST_IWindow* window = event->getWindow();
00495             if (!m_system->validWindow(window)) break;
00496             if (m_canvas) {
00497                 GHOST_Rect bnds;
00498                 window->getClientBounds(bnds);
00499                 m_canvas->Resize(bnds.getWidth(), bnds.getHeight());
00500             }
00501             }
00502             break;
00503         
00504         default:
00505             handled = false;
00506             break;
00507     }
00508     return handled;
00509 }
00510 
00511 
00512 
00513 int GPG_Application::getExitRequested(void)
00514 {
00515     return m_exitRequested;
00516 }
00517 
00518 
00519 GlobalSettings* GPG_Application::getGlobalSettings(void)
00520 {
00521     return m_ketsjiengine->GetGlobalSettings();
00522 }
00523 
00524 
00525 
00526 const STR_String& GPG_Application::getExitString(void)
00527 {
00528     return m_exitString;
00529 }
00530 
00531 
00532 
00533 bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode)
00534 {
00535     if (!m_engineInitialized)
00536     {
00537         GPU_extensions_init();
00538         bgl::InitExtensions(true);
00539 
00540         // get and set the preferences
00541         SYS_SystemHandle syshandle = SYS_GetSystem();
00542         if (!syshandle)
00543             return false;
00544         
00545         // SYS_WriteCommandLineInt(syshandle, "fixedtime", 0);
00546         // SYS_WriteCommandLineInt(syshandle, "vertexarrays",1);        
00547         GameData *gm= &m_startScene->gm;
00548         bool properties = (SYS_GetCommandLineInt(syshandle, "show_properties", 0) != 0);
00549         bool profile = (SYS_GetCommandLineInt(syshandle, "show_profile", 0) != 0);
00550         bool fixedFr = (gm->flag & GAME_ENABLE_ALL_FRAMES);
00551 
00552         bool showPhysics = (gm->flag & GAME_SHOW_PHYSICS);
00553         SYS_WriteCommandLineInt(syshandle, "show_physics", showPhysics);
00554 
00555         bool fixed_framerate= (SYS_GetCommandLineInt(syshandle, "fixed_framerate", fixedFr) != 0);
00556         bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0);
00557         bool useLists = (SYS_GetCommandLineInt(syshandle, "displaylists", gm->flag & GAME_DISPLAY_LISTS) != 0);
00558         bool nodepwarnings = (SYS_GetCommandLineInt(syshandle, "ignore_deprecation_warnings", 1) != 0);
00559         bool restrictAnimFPS = gm->flag & GAME_RESTRICT_ANIM_UPDATES;
00560 
00561         if(GLEW_ARB_multitexture && GLEW_VERSION_1_1)
00562             m_blendermat = (SYS_GetCommandLineInt(syshandle, "blender_material", 1) != 0);
00563 
00564         if(GPU_glsl_support())
00565             m_blenderglslmat = (SYS_GetCommandLineInt(syshandle, "blender_glsl_material", 1) != 0);
00566         else if(m_globalSettings->matmode == GAME_MAT_GLSL)
00567             m_blendermat = false;
00568 
00569         // create the canvas, rasterizer and rendertools
00570         m_canvas = new GPG_Canvas(window);
00571         if (!m_canvas)
00572             return false;
00573                 
00574         m_canvas->Init();
00575         if (gm->flag & GAME_SHOW_MOUSE)
00576             m_canvas->SetMouseState(RAS_ICanvas::MOUSE_NORMAL);             
00577 
00578         m_rendertools = new GPC_RenderTools();
00579         if (!m_rendertools)
00580             goto initFailed;
00581         
00582         if(useLists) {
00583             if(GLEW_VERSION_1_1)
00584                 m_rasterizer = new RAS_ListRasterizer(m_canvas, true);
00585             else
00586                 m_rasterizer = new RAS_ListRasterizer(m_canvas);
00587         }
00588         else if (GLEW_VERSION_1_1)
00589             m_rasterizer = new RAS_VAOpenGLRasterizer(m_canvas);
00590         else
00591             m_rasterizer = new RAS_OpenGLRasterizer(m_canvas);
00592 
00593         /* Stereo parameters - Eye Separation from the UI - stereomode from the command-line/UI */
00594         m_rasterizer->SetStereoMode((RAS_IRasterizer::StereoMode) stereoMode);
00595         m_rasterizer->SetEyeSeparation(m_startScene->gm.eyeseparation);
00596         
00597         if (!m_rasterizer)
00598             goto initFailed;
00599                         
00600         // create the inputdevices
00601         m_keyboard = new GPG_KeyboardDevice();
00602         if (!m_keyboard)
00603             goto initFailed;
00604             
00605         m_mouse = new GPC_MouseDevice();
00606         if (!m_mouse)
00607             goto initFailed;
00608             
00609         // create a networkdevice
00610         m_networkdevice = new NG_LoopBackNetworkDeviceInterface();
00611         if (!m_networkdevice)
00612             goto initFailed;
00613             
00614         sound_init(m_maggie);
00615 
00616         // create a ketsjisystem (only needed for timing and stuff)
00617         m_kxsystem = new GPG_System (m_system);
00618         if (!m_kxsystem)
00619             goto initFailed;
00620         
00621         // create the ketsjiengine
00622         m_ketsjiengine = new KX_KetsjiEngine(m_kxsystem);
00623         
00624         // set the devices
00625         m_ketsjiengine->SetKeyboardDevice(m_keyboard);
00626         m_ketsjiengine->SetMouseDevice(m_mouse);
00627         m_ketsjiengine->SetNetworkDevice(m_networkdevice);
00628         m_ketsjiengine->SetCanvas(m_canvas);
00629         m_ketsjiengine->SetRenderTools(m_rendertools);
00630         m_ketsjiengine->SetRasterizer(m_rasterizer);
00631 
00632         m_ketsjiengine->SetTimingDisplay(frameRate, false, false);
00633 
00634         KX_KetsjiEngine::SetExitKey(ConvertKeyCode(gm->exitkey));
00635 #ifdef WITH_PYTHON
00636         CValue::SetDeprecationWarnings(nodepwarnings);
00637 #else
00638         (void)nodepwarnings;
00639 #endif
00640 
00641         m_ketsjiengine->SetUseFixedTime(fixed_framerate);
00642         m_ketsjiengine->SetTimingDisplay(frameRate, profile, properties);
00643         m_ketsjiengine->SetRestrictAnimationFPS(restrictAnimFPS);
00644 
00645         //set the global settings (carried over if restart/load new files)
00646         m_ketsjiengine->SetGlobalSettings(m_globalSettings);
00647 
00648         m_engineInitialized = true;
00649     }
00650 
00651     return m_engineInitialized;
00652 initFailed:
00653     sound_exit();
00654     delete m_kxsystem;
00655     delete m_networkdevice;
00656     delete m_mouse;
00657     delete m_keyboard;
00658     delete m_rasterizer;
00659     delete m_rendertools;
00660     delete m_canvas;
00661     m_canvas = NULL;
00662     m_rendertools = NULL;
00663     m_rasterizer = NULL;
00664     m_keyboard = NULL;
00665     m_mouse = NULL;
00666     m_networkdevice = NULL;
00667     m_kxsystem = NULL;
00668     return false;
00669 }
00670 
00671 
00672 
00673 bool GPG_Application::startEngine(void)
00674 {
00675     if (m_engineRunning) {
00676         return false;
00677     }
00678     
00679     // Temporary hack to disable banner display for NaN approved content.
00680     /*
00681     m_canvas->SetBannerDisplayEnabled(true);    
00682     Camera* cam;
00683     cam = (Camera*)scene->camera->data;
00684     if (cam) {
00685     if (((cam->flag) & 48)==48) {
00686     m_canvas->SetBannerDisplayEnabled(false);
00687     }
00688     }
00689     else {
00690     showError(CString("Camera data invalid."));
00691     return false;
00692     }
00693     */
00694     
00695     // create a scene converter, create and convert the stratingscene
00696     m_sceneconverter = new KX_BlenderSceneConverter(m_maggie, m_ketsjiengine);
00697     if (m_sceneconverter)
00698     {
00699         STR_String startscenename = m_startSceneName.Ptr();
00700         m_ketsjiengine->SetSceneConverter(m_sceneconverter);
00701 
00702         //  if (always_use_expand_framing)
00703         //      sceneconverter->SetAlwaysUseExpandFraming(true);
00704         if(m_blendermat && (m_globalSettings->matmode != GAME_MAT_TEXFACE))
00705             m_sceneconverter->SetMaterials(true);
00706         if(m_blenderglslmat && (m_globalSettings->matmode == GAME_MAT_GLSL))
00707             m_sceneconverter->SetGLSLMaterials(true);
00708 
00709         KX_Scene* startscene = new KX_Scene(m_keyboard,
00710             m_mouse,
00711             m_networkdevice,
00712             startscenename,
00713             m_startScene,
00714             m_canvas);
00715         
00716 #ifdef WITH_PYTHON
00717             // some python things
00718             PyObject *gameLogic, *gameLogic_keys;
00719             setupGamePython(m_ketsjiengine, startscene, m_maggie, NULL, &gameLogic, &gameLogic_keys, m_argc, m_argv);
00720 #endif // WITH_PYTHON
00721 
00722         //initialize Dome Settings
00723         if(m_startScene->gm.stereoflag == STEREO_DOME)
00724             m_ketsjiengine->InitDome(m_startScene->gm.dome.res, m_startScene->gm.dome.mode, m_startScene->gm.dome.angle, m_startScene->gm.dome.resbuf, m_startScene->gm.dome.tilt, m_startScene->gm.dome.warptext);
00725 
00726 #ifdef WITH_PYTHON
00727         // Set the GameLogic.globalDict from marshal'd data, so we can
00728         // load new blend files and keep data in GameLogic.globalDict
00729         loadGamePythonConfig(m_pyGlobalDictString, m_pyGlobalDictString_Length);
00730 #endif      
00731         m_sceneconverter->ConvertScene(
00732             startscene,
00733             m_rendertools,
00734             m_canvas);
00735         m_ketsjiengine->AddScene(startscene);
00736         
00737         // Create a timer that is used to kick the engine
00738         if (!m_frameTimer) {
00739             m_frameTimer = m_system->installTimer(0, kTimerFreq, frameTimerProc, m_mainWindow);
00740         }
00741         m_rasterizer->Init();
00742         m_ketsjiengine->StartEngine(true);
00743         m_engineRunning = true;
00744         
00745         // Set the animation playback rate for ipo's and actions
00746         // the framerate below should patch with FPS macro defined in blendef.h
00747         // Could be in StartEngine set the framerate, we need the scene to do this
00748         Scene *scene= startscene->GetBlenderScene(); // needed for macro
00749         m_ketsjiengine->SetAnimFrameRate(FPS);
00750     }
00751     
00752     if (!m_engineRunning)
00753     {
00754         stopEngine();
00755     }
00756     
00757     return m_engineRunning;
00758 }
00759 
00760 
00761 void GPG_Application::stopEngine()
00762 {
00763 #ifdef WITH_PYTHON
00764     // GameLogic.globalDict gets converted into a buffer, and sorted in
00765     // m_pyGlobalDictString so we can restore after python has stopped
00766     // and started between .blend file loads.
00767     if(m_pyGlobalDictString) {
00768         delete [] m_pyGlobalDictString;
00769         m_pyGlobalDictString = 0;
00770     }
00771 
00772     m_pyGlobalDictString_Length = saveGamePythonConfig(&m_pyGlobalDictString);
00773     
00774     // when exiting the mainloop
00775     exitGamePythonScripting();
00776 #endif
00777     
00778     m_ketsjiengine->StopEngine();
00779     m_networkdevice->Disconnect();
00780 
00781     if (m_sceneconverter) {
00782         delete m_sceneconverter;
00783         m_sceneconverter = 0;
00784     }
00785     if (m_system && m_frameTimer) {
00786         m_system->removeTimer(m_frameTimer);
00787         m_frameTimer = 0;
00788     }
00789     m_engineRunning = false;
00790 }
00791 
00792 
00793 void GPG_Application::exitEngine()
00794 {
00795     // We only want to kill the engine if it has been initialized
00796     if (!m_engineInitialized)
00797         return;
00798 
00799     sound_exit();
00800     if (m_ketsjiengine)
00801     {
00802         stopEngine();
00803         delete m_ketsjiengine;
00804         m_ketsjiengine = 0;
00805     }
00806     if (m_kxsystem)
00807     {
00808         delete m_kxsystem;
00809         m_kxsystem = 0;
00810     }
00811     if (m_networkdevice)
00812     {
00813         delete m_networkdevice;
00814         m_networkdevice = 0;
00815     }
00816     if (m_mouse)
00817     {
00818         delete m_mouse;
00819         m_mouse = 0;
00820     }
00821     if (m_keyboard)
00822     {
00823         delete m_keyboard;
00824         m_keyboard = 0;
00825     }
00826     if (m_rasterizer)
00827     {
00828         delete m_rasterizer;
00829         m_rasterizer = 0;
00830     }
00831     if (m_rendertools)
00832     {
00833         delete m_rendertools;
00834         m_rendertools = 0;
00835     }
00836     if (m_canvas)
00837     {
00838         delete m_canvas;
00839         m_canvas = 0;
00840     }
00841 
00842     GPU_extensions_exit();
00843 
00844     m_exitRequested = 0;
00845     m_engineInitialized = false;
00846 }
00847 
00848 bool GPG_Application::handleWheel(GHOST_IEvent* event)
00849 {
00850     bool handled = false;
00851     MT_assert(event);
00852     if (m_mouse) 
00853     {
00854         GHOST_TEventDataPtr eventData = ((GHOST_IEvent*)event)->getData();
00855         GHOST_TEventWheelData* wheelData = static_cast<GHOST_TEventWheelData*>(eventData);
00856         GPC_MouseDevice::TButtonId button;
00857         if (wheelData->z > 0)
00858             button = GPC_MouseDevice::buttonWheelUp;
00859         else
00860             button = GPC_MouseDevice::buttonWheelDown;
00861         m_mouse->ConvertButtonEvent(button, true);
00862         handled = true;
00863     }
00864     return handled;
00865 }
00866 
00867 bool GPG_Application::handleButton(GHOST_IEvent* event, bool isDown)
00868 {
00869     bool handled = false;
00870     MT_assert(event);
00871     if (m_mouse) 
00872     {
00873         GHOST_TEventDataPtr eventData = ((GHOST_IEvent*)event)->getData();
00874         GHOST_TEventButtonData* buttonData = static_cast<GHOST_TEventButtonData*>(eventData);
00875         GPC_MouseDevice::TButtonId button;
00876         switch (buttonData->button)
00877         {
00878         case GHOST_kButtonMaskMiddle:
00879             button = GPC_MouseDevice::buttonMiddle;
00880             break;
00881         case GHOST_kButtonMaskRight:
00882             button = GPC_MouseDevice::buttonRight;
00883             break;
00884         case GHOST_kButtonMaskLeft:
00885         default:
00886             button = GPC_MouseDevice::buttonLeft;
00887             break;
00888         }
00889         m_mouse->ConvertButtonEvent(button, isDown);
00890         handled = true;
00891     }
00892     return handled;
00893 }
00894 
00895 
00896 bool GPG_Application::handleCursorMove(GHOST_IEvent* event)
00897 {
00898     bool handled = false;
00899     MT_assert(event);
00900     if (m_mouse && m_mainWindow)
00901     {
00902         GHOST_TEventDataPtr eventData = ((GHOST_IEvent*)event)->getData();
00903         GHOST_TEventCursorData* cursorData = static_cast<GHOST_TEventCursorData*>(eventData);
00904         GHOST_TInt32 x, y;
00905         m_mainWindow->screenToClient(cursorData->x, cursorData->y, x, y);
00906         m_mouse->ConvertMoveEvent(x, y);
00907         handled = true;
00908     }
00909     return handled;
00910 }
00911 
00912 
00913 bool GPG_Application::handleKey(GHOST_IEvent* event, bool isDown)
00914 {
00915     bool handled = false;
00916     MT_assert(event);
00917     if (m_keyboard)
00918     {
00919         GHOST_TEventDataPtr eventData = ((GHOST_IEvent*)event)->getData();
00920         GHOST_TEventKeyData* keyData = static_cast<GHOST_TEventKeyData*>(eventData);
00921 
00922         if (m_keyboard->ToNative(keyData->key) == KX_KetsjiEngine::GetExitKey() && !m_keyboard->m_hookesc && !m_isEmbedded) {
00923             m_exitRequested = KX_EXIT_REQUEST_OUTSIDE;
00924         }
00925         m_keyboard->ConvertEvent(keyData->key, isDown);
00926         handled = true;
00927     }
00928     return handled;
00929 }
00930 
00931 
00932 
00933 static void frameTimerProc(GHOST_ITimerTask* task, GHOST_TUns64 time)
00934 {
00935     GHOST_IWindow* window = (GHOST_IWindow*)task->getUserData();
00936     if (fSystem->validWindow(window)) {
00937         window->invalidate();
00938     }
00939 }