engine.cpp

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: */
Generated on Wed Nov 23 13:04:42 2011 for FIFE by  doxygen 1.6.3