FIFE  2008.0
 All Classes Namespaces Functions Variables Enumerations Enumerator Pages
engine.cpp
1 /***************************************************************************
2  * Copyright (C) 2005-2008 by the FIFE team *
3  * http://www.fifengine.de *
4  * This file is part of FIFE. *
5  * *
6  * FIFE is free software; you can redistribute it and/or *
7  * modify it under the terms of the GNU Lesser General Public *
8  * License as published by the Free Software Foundation; either *
9  * version 2.1 of the License, or (at your option) any later version. *
10  * *
11  * This library is distributed in the hope that it will be useful, *
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
14  * Lesser General Public License for more details. *
15  * *
16  * You should have received a copy of the GNU Lesser General Public *
17  * License along with this library; if not, write to the *
18  * Free Software Foundation, Inc., *
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
20  ***************************************************************************/
21 
22 // Standard C++ library includes
23 #include <iostream>
24 #include <algorithm>
25 
26 // 3rd party library includes
27 #include <SDL.h>
28 #include <SDL_ttf.h>
29 
30 // FIFE includes
31 // These includes are split up in two parts, separated by one empty line
32 // First block: files included from the FIFE root src directory
33 // Second block: files included from the same folder
34 #include "util/base/exception.h"
35 #include "util/log/logger.h"
36 #include "util/time/timemanager.h"
37 #include "audio/soundmanager.h"
38 #include "gui/console/console.h"
39 #include "gui/guimanager.h"
40 #include "vfs/vfs.h"
41 #include "vfs/vfsdirectory.h"
42 #include "vfs/directoryprovider.h"
43 #ifdef HAVE_ZIP
44 #include "vfs/zip/zipprovider.h"
45 #endif
46 #include "eventchannel/eventmanager.h"
47 #include "video/imagepool.h"
48 #include "video/animationpool.h"
49 #include "audio/soundclippool.h"
50 #include "video/renderbackend.h"
51 #include "video/cursor.h"
52 #include "video/devicecaps.h"
53 #ifdef HAVE_OPENGL
54 #include "video/opengl/fife_opengl.h"
55 #include "video/opengl/renderbackendopengl.h"
56 #include "gui/base/opengl/opengl_gui_graphics.h"
57 #endif
58 #include "gui/base/sdl/sdl_gui_graphics.h"
59 #include "gui/base/gui_font.h"
60 #include "video/sdl/renderbackendsdl.h"
61 #include "video/fonts/abstractfont.h"
62 #include "loaders/native/video_loaders/subimage_loader.h"
63 #include "loaders/native/video_loaders/image_loader.h"
64 #include "loaders/native/audio_loaders/ogg_loader.h"
65 #include "model/model.h"
66 #include "pathfinder/routepather/routepather.h"
67 #include "model/metamodel/grids/hexgrid.h"
68 #include "model/metamodel/grids/squaregrid.h"
69 #include "view/renderers/quadtreerenderer.h"
70 #include "view/renderers/gridrenderer.h"
71 #include "view/renderers/instancerenderer.h"
72 #include "view/renderers/coordinaterenderer.h"
73 #include "view/renderers/floatingtextrenderer.h"
74 #include "view/renderers/cellselectionrenderer.h"
75 #include "view/renderers/blockinginforenderer.h"
76 #include "view/renderers/genericrenderer.h"
77 #include "view/renderers/lightrenderer.h"
78 #include "video/image.h"
79 #include "gui/console/console.h"
80 #include "engine.h"
81 
82 #ifdef USE_COCOA
83 
84 #include <objc/message.h>
85 #include <dlfcn.h>
86 
87 int main(int argc, char **argv)
88 {
89  return 0;
90 }
91 #endif
92 
93 namespace FIFE {
94  static Logger _log(LM_CONTROLLER);
95 
97  m_renderbackend(0),
98  m_guimanager(0),
99  m_eventmanager(0),
100  m_soundmanager(0),
101  m_timemanager(0),
102  m_imagepool(0),
103  m_animpool(0),
104  m_soundclippool(0),
105  m_vfs(0),
106  m_model(0),
107  m_gui_graphics(0),
108  m_logmanager(0),
109  m_cursor(0),
110  m_settings(),
111  m_devcaps(),
112  m_changelisteners() {
113 #ifdef USE_COCOA
114  // The next lines ensure that Cocoa is initialzed correctly.
115  // This is needed for SDL to function properly on MAC OS X.
116  void* cocoa_lib;
117  cocoa_lib = dlopen( "/System/Library/Frameworks/Cocoa.framework/Cocoa", RTLD_LAZY );
118  void (*nsappload)(void);
119  nsappload = (void(*)()) dlsym( cocoa_lib, "NSApplicationLoad");
120  nsappload();
121 
122  // Create an autorelease pool, so autoreleased SDL objects don't leak.
123  objc_object *NSAutoreleasePool = objc_getClass("NSAutoreleasePool");
124  m_autoreleasePool =
125  objc_msgSend(NSAutoreleasePool, sel_registerName("new"));
126 #endif
127  preInit();
128  }
129 
131  return m_settings;
132  }
133 
134  const DeviceCaps& Engine::getDeviceCaps() const {
135  return m_devcaps;
136  }
137 
138  Image* Engine::changeScreenMode(const ScreenMode& mode){
139  m_cursor->invalidate();
140  m_imagepool->invalidateLoadedImages();
141  m_defaultfont->invalidate();
142  m_guimanager->invalidateFonts();
143 
144  Image* screen = m_renderbackend->setScreenMode(mode);
145 
146  m_guimanager->resizeTopContainer(0,0,mode.getWidth(), mode.getHeight());
147  m_guimanager->getConsole()->reLayout();
148 
149  std::vector<IEngineChangeListener*>::iterator i = m_changelisteners.begin();
150  while (i != m_changelisteners.end()) {
151  (*i)->onScreenModeChanged(mode);
152  ++i;
153  }
154 
155  return screen;
156  }
157 
158  void Engine::preInit() {
159  m_logmanager = LogManager::instance();
160 
161  FL_LOG(_log, "================== Engine pre-init start =================");
162  m_timemanager = new TimeManager();
163  FL_LOG(_log, "Time manager created");
164 
165  FL_LOG(_log, "Creating VFS");
166  m_vfs = new VFS();
167 
168  FL_LOG(_log, "Adding root directory to VFS");
169  m_vfs->addSource( new VFSDirectory(m_vfs) );
170  m_vfs->addProvider( new DirectoryProvider() );
171 #ifdef HAVE_ZIP
172  FL_LOG(_log, "Adding zip provider to VFS");
173  m_vfs->addProvider( new ZipProvider() );
174 #endif
175  //m_vfs->addProvider(ProviderDAT2());
176  //m_vfs->addProvider(ProviderDAT1());
177  FL_LOG(_log, "Engine pre-init done");
178  m_destroyed = false;
179  }
180 
181  void Engine::init() {
182  FL_LOG(_log, "Engine initialize start");
183  m_settings.validate();
184  FL_LOG(_log, "Engine settings validated");
185 
186  // If failed to init SDL throw exception.
187  if (SDL_Init(SDL_INIT_NOPARACHUTE | SDL_INIT_TIMER) < 0) {
188  throw SDLException(SDL_GetError());
189  }
190 
191  SDL_EnableUNICODE(1);
192  SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
193  TTF_Init();
194 
195  FL_LOG(_log, "Creating event manager");
196  m_eventmanager = new EventManager();
197 
198  FL_LOG(_log, "Creating pools");
199  m_imagepool = new ImagePool();
200  m_animpool = new AnimationPool();
201  m_soundclippool = new SoundClipPool();
202  m_imagepool->addResourceLoader(new SubImageLoader());
203  m_imagepool->addResourceLoader(new ImageLoader(m_vfs));
204  m_soundclippool->addResourceLoader(new OggLoader(m_vfs));
205 
206  FL_LOG(_log, "Creating render backend");
207  std::string rbackend(m_settings.getRenderBackend());
208  if (rbackend == "SDL") {
209  m_renderbackend = new RenderBackendSDL(m_settings.getColorKey());
210  FL_LOG(_log, "SDL Render backend created");
211  } else {
212 #ifdef HAVE_OPENGL
213  m_renderbackend = new RenderBackendOpenGL(m_settings.getColorKey());
214  FL_LOG(_log, "OpenGL Render backend created");
215 #else
216  m_renderbackend = new RenderBackendSDL(m_settings.getColorKey());
217  // Remember the choice so we pick the right graphics class.
218  rbackend = "SDL";
219  FL_WARN(_log, "Tried to select OpenGL, even though it is not compiled into the engine. Falling back to SDL Render backend");
220 #endif
221  }
222  FL_LOG(_log, "Initializing render backend");
223  m_renderbackend->setColorKeyEnabled(m_settings.isColorKeyEnabled());
224 
225  std::string driver = m_settings.getVideoDriver();
226  std::vector<std::string> drivers = m_devcaps.getAvailableDrivers();
227 
228  if (driver != ""){
229  if (std::find (drivers.begin(), drivers.end(), driver) == drivers.end()) {
230  FL_WARN(_log, "Selected driver is not supported for your Operating System! Reverting to default driver.");
231  driver = "";
232  }
233  }
234 
235  m_renderbackend->init(driver);
236 
237  FL_LOG(_log, "Querying device capabilities");
238  m_devcaps.fillDeviceCaps();
239 
240  uint16_t bpp = m_settings.getBitsPerPixel();
241 
242  m_screenMode = m_devcaps.getNearestScreenMode(
243  m_settings.getScreenWidth(),
244  m_settings.getScreenHeight(),
245  bpp,
246  rbackend,
247  m_settings.isFullScreen());
248 
249  FL_LOG(_log, "Creating main screen");
250  m_renderbackend->createMainScreen(
251  m_screenMode,
252  m_settings.getWindowTitle(),
253  m_settings.getWindowIcon());
254  FL_LOG(_log, "Main screen created");
255 
256 #ifdef HAVE_OPENGL
257  if( rbackend != "SDL" ) {
258  m_gui_graphics = new OpenGLGuiGraphics(*m_imagepool);
259  }
260 
261  if (m_settings.getLightingModel() != 0) {
262  m_renderbackend->setLightingModel(m_settings.getLightingModel());
263  }
264 
265 #endif
266  if( rbackend == "SDL" ) {
267  m_gui_graphics = new SdlGuiGraphics(*m_imagepool);
268  }
269  FL_LOG(_log, "Constructing GUI manager");
270  m_guimanager = new GUIManager(*m_imagepool);
271  FL_LOG(_log, "Events bind to GUI manager");
272  m_eventmanager->addSdlEventListener(m_guimanager);
273 
274  FL_LOG(_log, "Creating default font");
275  m_defaultfont = m_guimanager->setDefaultFont(
276  m_settings.getDefaultFontPath(),
277  m_settings.getDefaultFontSize(),
278  m_settings.getDefaultFontGlyphs());
279  FL_LOG(_log, "Initializing GUI manager");
280  m_guimanager->init(m_gui_graphics, m_renderbackend->getScreenWidth(), m_renderbackend->getScreenHeight());
281  FL_LOG(_log, "GUI manager initialized");
282  SDL_EnableUNICODE(1);
283 
284  FL_LOG(_log, "Creating sound manager");
285  m_soundmanager = new SoundManager(m_soundclippool);
286  m_soundmanager->setVolume(static_cast<float>(m_settings.getInitialVolume()) / 10);
287 
288  FL_LOG(_log, "Creating renderers");
289  m_renderers.push_back(new InstanceRenderer(m_renderbackend, 10, m_imagepool, m_animpool));
290  m_renderers.push_back(new GridRenderer(m_renderbackend, 20));
291  m_renderers.push_back(new CellSelectionRenderer(m_renderbackend, 30));
292  m_renderers.push_back(new BlockingInfoRenderer(m_renderbackend, 40));
293  m_renderers.push_back(new FloatingTextRenderer(m_renderbackend, 50, dynamic_cast<AbstractFont*>(m_defaultfont)));
294  m_renderers.push_back(new QuadTreeRenderer(m_renderbackend, 60));
295  m_renderers.push_back(new CoordinateRenderer(m_renderbackend, 70, dynamic_cast<AbstractFont*>(m_defaultfont)));
296  m_renderers.push_back(new GenericRenderer(m_renderbackend, 80, m_imagepool, m_animpool));
297  m_renderers.push_back(new LightRenderer(m_renderbackend, 90, m_imagepool, m_animpool));
298 
299  FL_LOG(_log, "Creating model");
300  m_model = new Model(m_renderbackend, m_renderers, m_imagepool, m_animpool);
301  FL_LOG(_log, "Adding pathers to model");
302  m_model->adoptPather(new RoutePather());
303  FL_LOG(_log, "Adding grid prototypes to model");
304  m_model->adoptCellGrid(new SquareGrid());
305  m_model->adoptCellGrid(new HexGrid());
306 
307  m_cursor = new Cursor(m_imagepool, m_animpool, m_renderbackend);
308  FL_LOG(_log, "Engine intialized");
309  }
310 
312  if( !m_destroyed ) {
313  destroy();
314  }
315  }
316 
318  FL_LOG(_log, "Destructing engine");
319  delete m_cursor;
320  delete m_model;
321  delete m_soundmanager;
322  delete m_guimanager;
323  delete m_gui_graphics;
324 
325  // Note the dependancy between image and animation pools
326  // as animations reference images they have to be deleted
327  // before clearing the image pool.
328  delete m_animpool;
329  delete m_imagepool;
330  delete m_eventmanager;
331 
332  // properly remove all the renderers created during init
333  std::vector<RendererBase*>::iterator rendererIter = m_renderers.begin();
334  for ( ; rendererIter != m_renderers.end(); ++rendererIter)
335  {
336  delete *rendererIter;
337  }
338  m_renderers.clear();
339 
340  m_renderbackend->deinit();
341  delete m_renderbackend;
342 
343  delete m_vfs;
344 
345  delete m_timemanager;
346 
347  TTF_Quit();
348  SDL_Quit();
349 
350 #ifdef USE_COCOA
351  objc_msgSend(m_autoreleasePool, sel_registerName("release"));
352 #endif
353 
354  FL_LOG(_log, "================== Engine destructed ==================");
355  m_destroyed = true;
356  //delete m_logmanager;
357  }
359  m_eventmanager->processEvents();
360  }
361 
362  void Engine::pump() {
363  m_eventmanager->processEvents();
364  m_renderbackend->startFrame();
365  m_timemanager->update();
366 
367  if (m_model->getNumMaps() == 0) {
368  m_renderbackend->clearBackBuffer();
369  }
370 
371  m_model->update();
372 #ifdef HAVE_OPENGL
373  if (m_settings.getLightingModel() == 1) {
374  m_renderbackend->disableLighting();
375  }
376 #endif
377  m_guimanager->turn();
378  m_cursor->draw();
379 #ifdef HAVE_OPENGL
380  if (m_settings.getLightingModel() == 1) {
381  m_renderbackend->enableLighting();
382  }
383 #endif
384  m_renderbackend->endFrame();
385  }
386 
388  // nothing here at the moment..
389  }
390 
391  void Engine::addChangeListener(IEngineChangeListener* listener) {
392  m_changelisteners.push_back(listener);
393  }
394 
395  void Engine::removeChangeListener(IEngineChangeListener* listener) {
396  std::vector<IEngineChangeListener*>::iterator i = m_changelisteners.begin();
397  while (i != m_changelisteners.end()) {
398  if ((*i) == listener) {
399  m_changelisteners.erase(i);
400  return;
401  }
402  ++i;
403  }
404  }
405 }//FIFE
406 
407 /* vim: set noexpandtab: set shiftwidth=2: set tabstop=2: */