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