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