Blender V2.61 - r43446
|
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 }