FIFE 2008.0
|
00001 /*************************************************************************** 00002 * Copyright (C) 2005-2008 by the FIFE team * 00003 * http://www.fifengine.de * 00004 * This file is part of FIFE. * 00005 * * 00006 * FIFE is free software; you can redistribute it and/or * 00007 * modify it under the terms of the GNU Lesser General Public * 00008 * License as published by the Free Software Foundation; either * 00009 * version 2.1 of the License, or (at your option) any later version. * 00010 * * 00011 * This library 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 GNU * 00014 * Lesser General Public License for more details. * 00015 * * 00016 * You should have received a copy of the GNU Lesser General Public * 00017 * License along with this library; if not, write to the * 00018 * Free Software Foundation, Inc., * 00019 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * 00020 ***************************************************************************/ 00021 00022 // Standard C++ library includes 00023 #include <iostream> 00024 #include <algorithm> 00025 00026 // 3rd party library includes 00027 #include <SDL.h> 00028 #include <SDL_ttf.h> 00029 00030 // FIFE includes 00031 // These includes are split up in two parts, separated by one empty line 00032 // First block: files included from the FIFE root src directory 00033 // Second block: files included from the same folder 00034 #include "util/base/exception.h" 00035 #include "util/log/logger.h" 00036 #include "util/time/timemanager.h" 00037 #include "audio/soundmanager.h" 00038 #include "gui/console/console.h" 00039 #include "gui/guimanager.h" 00040 #include "vfs/vfs.h" 00041 #include "vfs/vfsdirectory.h" 00042 #include "vfs/directoryprovider.h" 00043 #ifdef HAVE_ZIP 00044 #include "vfs/zip/zipprovider.h" 00045 #endif 00046 #include "eventchannel/eventmanager.h" 00047 #include "video/imagepool.h" 00048 #include "video/animationpool.h" 00049 #include "audio/soundclippool.h" 00050 #include "video/renderbackend.h" 00051 #include "video/cursor.h" 00052 #include "video/devicecaps.h" 00053 #ifdef HAVE_OPENGL 00054 #include "video/opengl/fife_opengl.h" 00055 #include "video/opengl/renderbackendopengl.h" 00056 #include "gui/base/opengl/opengl_gui_graphics.h" 00057 #endif 00058 #include "gui/base/sdl/sdl_gui_graphics.h" 00059 #include "gui/base/gui_font.h" 00060 #include "video/sdl/renderbackendsdl.h" 00061 #include "video/fonts/abstractfont.h" 00062 #include "loaders/native/video_loaders/subimage_loader.h" 00063 #include "loaders/native/video_loaders/image_loader.h" 00064 #include "loaders/native/audio_loaders/ogg_loader.h" 00065 #include "model/model.h" 00066 #include "pathfinder/routepather/routepather.h" 00067 #include "model/metamodel/grids/hexgrid.h" 00068 #include "model/metamodel/grids/squaregrid.h" 00069 #include "view/renderers/quadtreerenderer.h" 00070 #include "view/renderers/gridrenderer.h" 00071 #include "view/renderers/instancerenderer.h" 00072 #include "view/renderers/coordinaterenderer.h" 00073 #include "view/renderers/floatingtextrenderer.h" 00074 #include "view/renderers/cellselectionrenderer.h" 00075 #include "view/renderers/blockinginforenderer.h" 00076 #include "view/renderers/genericrenderer.h" 00077 #include "view/renderers/lightrenderer.h" 00078 #include "video/image.h" 00079 #include "gui/console/console.h" 00080 #include "engine.h" 00081 00082 #ifdef USE_COCOA 00083 00084 #include <objc/message.h> 00085 #include <dlfcn.h> 00086 00087 int main(int argc, char **argv) 00088 { 00089 return 0; 00090 } 00091 #endif 00092 00093 namespace FIFE { 00094 static Logger _log(LM_CONTROLLER); 00095 00096 Engine::Engine(): 00097 m_renderbackend(0), 00098 m_guimanager(0), 00099 m_eventmanager(0), 00100 m_soundmanager(0), 00101 m_timemanager(0), 00102 m_imagepool(0), 00103 m_animpool(0), 00104 m_soundclippool(0), 00105 m_vfs(0), 00106 m_model(0), 00107 m_gui_graphics(0), 00108 m_logmanager(0), 00109 m_cursor(0), 00110 m_settings(), 00111 m_devcaps(), 00112 m_changelisteners() { 00113 #ifdef USE_COCOA 00114 // The next lines ensure that Cocoa is initialzed correctly. 00115 // This is needed for SDL to function properly on MAC OS X. 00116 void* cocoa_lib; 00117 cocoa_lib = dlopen( "/System/Library/Frameworks/Cocoa.framework/Cocoa", RTLD_LAZY ); 00118 void (*nsappload)(void); 00119 nsappload = (void(*)()) dlsym( cocoa_lib, "NSApplicationLoad"); 00120 nsappload(); 00121 00122 // Create an autorelease pool, so autoreleased SDL objects don't leak. 00123 objc_object *NSAutoreleasePool = objc_getClass("NSAutoreleasePool"); 00124 m_autoreleasePool = 00125 objc_msgSend(NSAutoreleasePool, sel_registerName("new")); 00126 #endif 00127 preInit(); 00128 } 00129 00130 EngineSettings& Engine::getSettings() { 00131 return m_settings; 00132 } 00133 00134 const DeviceCaps& Engine::getDeviceCaps() const { 00135 return m_devcaps; 00136 } 00137 00138 Image* Engine::changeScreenMode(const ScreenMode& mode){ 00139 m_cursor->invalidate(); 00140 m_imagepool->invalidateLoadedImages(); 00141 m_defaultfont->invalidate(); 00142 m_guimanager->invalidateFonts(); 00143 00144 Image* screen = m_renderbackend->setScreenMode(mode); 00145 00146 m_guimanager->resizeTopContainer(0,0,mode.getWidth(), mode.getHeight()); 00147 m_guimanager->getConsole()->reLayout(); 00148 00149 std::vector<IEngineChangeListener*>::iterator i = m_changelisteners.begin(); 00150 while (i != m_changelisteners.end()) { 00151 (*i)->onScreenModeChanged(mode); 00152 ++i; 00153 } 00154 00155 return screen; 00156 } 00157 00158 void Engine::preInit() { 00159 m_logmanager = LogManager::instance(); 00160 00161 FL_LOG(_log, "================== Engine pre-init start ================="); 00162 m_timemanager = new TimeManager(); 00163 FL_LOG(_log, "Time manager created"); 00164 00165 FL_LOG(_log, "Creating VFS"); 00166 m_vfs = new VFS(); 00167 00168 FL_LOG(_log, "Adding root directory to VFS"); 00169 m_vfs->addSource( new VFSDirectory(m_vfs) ); 00170 m_vfs->addProvider( new DirectoryProvider() ); 00171 #ifdef HAVE_ZIP 00172 FL_LOG(_log, "Adding zip provider to VFS"); 00173 m_vfs->addProvider( new ZipProvider() ); 00174 #endif 00175 //m_vfs->addProvider(ProviderDAT2()); 00176 //m_vfs->addProvider(ProviderDAT1()); 00177 FL_LOG(_log, "Engine pre-init done"); 00178 m_destroyed = false; 00179 } 00180 00181 void Engine::init() { 00182 FL_LOG(_log, "Engine initialize start"); 00183 m_settings.validate(); 00184 FL_LOG(_log, "Engine settings validated"); 00185 00186 // If failed to init SDL throw exception. 00187 if (SDL_Init(SDL_INIT_NOPARACHUTE | SDL_INIT_TIMER) < 0) { 00188 throw SDLException(SDL_GetError()); 00189 } 00190 00191 SDL_EnableUNICODE(1); 00192 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); 00193 TTF_Init(); 00194 00195 FL_LOG(_log, "Creating event manager"); 00196 m_eventmanager = new EventManager(); 00197 00198 FL_LOG(_log, "Creating pools"); 00199 m_imagepool = new ImagePool(); 00200 m_animpool = new AnimationPool(); 00201 m_soundclippool = new SoundClipPool(); 00202 m_imagepool->addResourceLoader(new SubImageLoader()); 00203 m_imagepool->addResourceLoader(new ImageLoader(m_vfs)); 00204 m_soundclippool->addResourceLoader(new OggLoader(m_vfs)); 00205 00206 FL_LOG(_log, "Creating render backend"); 00207 std::string rbackend(m_settings.getRenderBackend()); 00208 if (rbackend == "SDL") { 00209 m_renderbackend = new RenderBackendSDL(m_settings.getColorKey()); 00210 FL_LOG(_log, "SDL Render backend created"); 00211 } else { 00212 #ifdef HAVE_OPENGL 00213 m_renderbackend = new RenderBackendOpenGL(m_settings.getColorKey()); 00214 FL_LOG(_log, "OpenGL Render backend created"); 00215 #else 00216 m_renderbackend = new RenderBackendSDL(m_settings.getColorKey()); 00217 // Remember the choice so we pick the right graphics class. 00218 rbackend = "SDL"; 00219 FL_WARN(_log, "Tried to select OpenGL, even though it is not compiled into the engine. Falling back to SDL Render backend"); 00220 #endif 00221 } 00222 FL_LOG(_log, "Initializing render backend"); 00223 m_renderbackend->setColorKeyEnabled(m_settings.isColorKeyEnabled()); 00224 00225 std::string driver = m_settings.getVideoDriver(); 00226 std::vector<std::string> drivers = m_devcaps.getAvailableDrivers(); 00227 00228 if (driver != ""){ 00229 if (std::find (drivers.begin(), drivers.end(), driver) == drivers.end()) { 00230 FL_WARN(_log, "Selected driver is not supported for your Operating System! Reverting to default driver."); 00231 driver = ""; 00232 } 00233 } 00234 00235 m_renderbackend->init(driver); 00236 00237 FL_LOG(_log, "Querying device capabilities"); 00238 m_devcaps.fillDeviceCaps(); 00239 00240 uint16_t bpp = m_settings.getBitsPerPixel(); 00241 00242 m_screenMode = m_devcaps.getNearestScreenMode( 00243 m_settings.getScreenWidth(), 00244 m_settings.getScreenHeight(), 00245 bpp, 00246 rbackend, 00247 m_settings.isFullScreen()); 00248 00249 FL_LOG(_log, "Creating main screen"); 00250 m_renderbackend->createMainScreen( 00251 m_screenMode, 00252 m_settings.getWindowTitle(), 00253 m_settings.getWindowIcon()); 00254 FL_LOG(_log, "Main screen created"); 00255 00256 #ifdef HAVE_OPENGL 00257 if( rbackend != "SDL" ) { 00258 m_gui_graphics = new OpenGLGuiGraphics(*m_imagepool); 00259 } 00260 00261 if (m_settings.getLightingModel() != 0) { 00262 m_renderbackend->setLightingModel(m_settings.getLightingModel()); 00263 } 00264 00265 #endif 00266 if( rbackend == "SDL" ) { 00267 m_gui_graphics = new SdlGuiGraphics(*m_imagepool); 00268 } 00269 FL_LOG(_log, "Constructing GUI manager"); 00270 m_guimanager = new GUIManager(*m_imagepool); 00271 FL_LOG(_log, "Events bind to GUI manager"); 00272 m_eventmanager->addSdlEventListener(m_guimanager); 00273 00274 FL_LOG(_log, "Creating default font"); 00275 m_defaultfont = m_guimanager->setDefaultFont( 00276 m_settings.getDefaultFontPath(), 00277 m_settings.getDefaultFontSize(), 00278 m_settings.getDefaultFontGlyphs()); 00279 FL_LOG(_log, "Initializing GUI manager"); 00280 m_guimanager->init(m_gui_graphics, m_renderbackend->getScreenWidth(), m_renderbackend->getScreenHeight()); 00281 FL_LOG(_log, "GUI manager initialized"); 00282 SDL_EnableUNICODE(1); 00283 00284 FL_LOG(_log, "Creating sound manager"); 00285 m_soundmanager = new SoundManager(m_soundclippool); 00286 m_soundmanager->setVolume(static_cast<float>(m_settings.getInitialVolume()) / 10); 00287 00288 FL_LOG(_log, "Creating renderers"); 00289 m_renderers.push_back(new InstanceRenderer(m_renderbackend, 10, m_imagepool, m_animpool)); 00290 m_renderers.push_back(new GridRenderer(m_renderbackend, 20)); 00291 m_renderers.push_back(new CellSelectionRenderer(m_renderbackend, 30)); 00292 m_renderers.push_back(new BlockingInfoRenderer(m_renderbackend, 40)); 00293 m_renderers.push_back(new FloatingTextRenderer(m_renderbackend, 50, dynamic_cast<AbstractFont*>(m_defaultfont))); 00294 m_renderers.push_back(new QuadTreeRenderer(m_renderbackend, 60)); 00295 m_renderers.push_back(new CoordinateRenderer(m_renderbackend, 70, dynamic_cast<AbstractFont*>(m_defaultfont))); 00296 m_renderers.push_back(new GenericRenderer(m_renderbackend, 80, m_imagepool, m_animpool)); 00297 m_renderers.push_back(new LightRenderer(m_renderbackend, 90, m_imagepool, m_animpool)); 00298 00299 FL_LOG(_log, "Creating model"); 00300 m_model = new Model(m_renderbackend, m_renderers, m_imagepool, m_animpool); 00301 FL_LOG(_log, "Adding pathers to model"); 00302 m_model->adoptPather(new RoutePather()); 00303 FL_LOG(_log, "Adding grid prototypes to model"); 00304 m_model->adoptCellGrid(new SquareGrid()); 00305 m_model->adoptCellGrid(new HexGrid()); 00306 00307 m_cursor = new Cursor(m_imagepool, m_animpool, m_renderbackend); 00308 FL_LOG(_log, "Engine intialized"); 00309 } 00310 00311 Engine::~Engine() { 00312 if( !m_destroyed ) { 00313 destroy(); 00314 } 00315 } 00316 00317 void Engine::destroy() { 00318 FL_LOG(_log, "Destructing engine"); 00319 delete m_cursor; 00320 delete m_model; 00321 delete m_soundmanager; 00322 delete m_guimanager; 00323 delete m_gui_graphics; 00324 00325 // Note the dependancy between image and animation pools 00326 // as animations reference images they have to be deleted 00327 // before clearing the image pool. 00328 delete m_animpool; 00329 delete m_imagepool; 00330 delete m_eventmanager; 00331 00332 // properly remove all the renderers created during init 00333 std::vector<RendererBase*>::iterator rendererIter = m_renderers.begin(); 00334 for ( ; rendererIter != m_renderers.end(); ++rendererIter) 00335 { 00336 delete *rendererIter; 00337 } 00338 m_renderers.clear(); 00339 00340 m_renderbackend->deinit(); 00341 delete m_renderbackend; 00342 00343 delete m_vfs; 00344 00345 delete m_timemanager; 00346 00347 TTF_Quit(); 00348 SDL_Quit(); 00349 00350 #ifdef USE_COCOA 00351 objc_msgSend(m_autoreleasePool, sel_registerName("release")); 00352 #endif 00353 00354 FL_LOG(_log, "================== Engine destructed =================="); 00355 m_destroyed = true; 00356 //delete m_logmanager; 00357 } 00358 void Engine::initializePumping() { 00359 m_eventmanager->processEvents(); 00360 } 00361 00362 void Engine::pump() { 00363 m_eventmanager->processEvents(); 00364 m_renderbackend->startFrame(); 00365 m_timemanager->update(); 00366 00367 if (m_model->getNumMaps() == 0) { 00368 m_renderbackend->clearBackBuffer(); 00369 } 00370 00371 m_model->update(); 00372 #ifdef HAVE_OPENGL 00373 if (m_settings.getLightingModel() == 1) { 00374 m_renderbackend->disableLighting(); 00375 } 00376 #endif 00377 m_guimanager->turn(); 00378 m_cursor->draw(); 00379 #ifdef HAVE_OPENGL 00380 if (m_settings.getLightingModel() == 1) { 00381 m_renderbackend->enableLighting(); 00382 } 00383 #endif 00384 m_renderbackend->endFrame(); 00385 } 00386 00387 void Engine::finalizePumping() { 00388 // nothing here at the moment.. 00389 } 00390 00391 void Engine::addChangeListener(IEngineChangeListener* listener) { 00392 m_changelisteners.push_back(listener); 00393 } 00394 00395 void Engine::removeChangeListener(IEngineChangeListener* listener) { 00396 std::vector<IEngineChangeListener*>::iterator i = m_changelisteners.begin(); 00397 while (i != m_changelisteners.end()) { 00398 if ((*i) == listener) { 00399 m_changelisteners.erase(i); 00400 return; 00401 } 00402 ++i; 00403 } 00404 } 00405 }//FIFE 00406 00407 /* vim: set noexpandtab: set shiftwidth=2: set tabstop=2: */