# HG changeset patch # User helios2000@33b003aa-7bff-0310-803a-e67f0ece8222 # Date 1288970470 0 # Node ID e3140f01749d4bf83fe879b9c2220712c6306cb6 # Parent b0733d998d0f9360fef12ccab36df5795078baf1 * Merged the light branch back into trunk. * Modified the demos so they work with the new loaders and setting. diff -r b0733d998d0f -r e3140f01749d demos/pychan_demo/settings-dist.xml --- a/demos/pychan_demo/settings-dist.xml Wed Nov 03 13:44:12 2010 +0000 +++ b/demos/pychan_demo/settings-dist.xml Fri Nov 05 15:21:10 2010 +0000 @@ -1,24 +1,25 @@ - - - + + + False True OpenGL 1024x768 - 0 - 5.0 - 1 - Pychan demo [FIFE Client] - gui/icons/pychan_logo.png - fonts/freefont/FreeMono.ttf - abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,!?-+/():;%&`'*#=[]\" - 16 - controller ; GUI - True - 1 - 0 - False - 255,0,255 - - + 0 + 5.0 + 1 + Pychan demo [FIFE Client] + gui/icons/pychan_logo.png + fonts/freefont/FreeMono.ttf + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,!?-+/():;%&`'*#=[]\" + 16 + controller ; GUI + True + 1 + 0 + False + 255,0,255 + 0 + + \ No newline at end of file diff -r b0733d998d0f -r e3140f01749d demos/rio_de_hola/misc/infotext.txt --- a/demos/rio_de_hola/misc/infotext.txt Wed Nov 03 13:44:12 2010 +0000 +++ b/demos/rio_de_hola/misc/infotext.txt Fri Nov 05 15:21:10 2010 +0000 @@ -11,6 +11,8 @@ - R = Reload map (useful for map editing) - S = Second camera on / off - O = Rotate main camera +- 1,2 = Change global light intensity +- 3,4 = Change light source intensity Have fun, The FIFE team diff -r b0733d998d0f -r e3140f01749d demos/rio_de_hola/scripts/world.py --- a/demos/rio_de_hola/scripts/world.py Wed Nov 03 13:44:12 2010 +0000 +++ b/demos/rio_de_hola/scripts/world.py Fri Nov 05 15:21:10 2010 +0000 @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # #################################################################### -# Copyright (C) 2005-2009 by the FIFE team +# Copyright (C) 2005-2010 by the FIFE team # http://www.fifengine.de # This file is part of FIFE. # @@ -83,6 +83,10 @@ self.instance_to_agent = {} self.dynamic_widgets = {} + self.light_intensity = 1 + self.light_sources = 0 + self.lightmodel = int(TDS.get("FIFE", "Lighting")) + self.soundmanager = SoundManager(self.engine) self.music = None @@ -157,7 +161,7 @@ self.filename = filename self.reset() - self.map = loadMapFile(filename, self.engine) + self.map = loadMapFile(filename, self.engine, extensions = {'lights': True}) self.maplistener = MapListener(self.map) self.initAgents() @@ -259,6 +263,13 @@ if str(TDS.get("rio", "QuadTreeLayerName")): renderer.addActiveLayer(self.map.getLayer(str(TDS.get("rio", "QuadTreeLayerName")))) + # If Light is enabled in settings then init the lightrenderer. + if self.lightmodel != 0: + renderer = fife.LightRenderer.getInstance(self.cameras['main']) + renderer.setEnabled(True) + renderer.clearActiveLayers() + renderer.addActiveLayer(self.map.getLayer('TechdemoMapGroundObjectLayer')) + # Set up the second camera # NOTE: We need to explicitly call setLocation, there's a bit of a messup in the Camera code. self.cameras['small'].setLocation(self.hero.agent.getLocation()) @@ -304,6 +315,14 @@ self.load(self.filename) elif keystr == 'o': self.target_rotation = (self.target_rotation + 90) % 360 + elif keystr == '2': + self.lightIntensity(0.1) + elif keystr == '1': + self.lightIntensity(-0.1) + elif keystr == '5': + self.lightSourceIntensity(25) + elif keystr == '4': + self.lightSourceIntensity(-25) elif keyval in (fife.Key.LEFT_CONTROL, fife.Key.RIGHT_CONTROL): self.ctrldown = True @@ -354,6 +373,50 @@ if i.getObject().getId() in ('girl', 'beekeeper'): renderer.addOutlined(i, 173, 255, 47, 2) + def lightIntensity(self, value): + if self.light_intensity+value <= 1 and self.light_intensity+value >= 0: + self.light_intensity = self.light_intensity + value + + if self.lightmodel == 1: + self.cameras['main'].setLightingColor(self.light_intensity, self.light_intensity, self.light_intensity, 1.0) + + if self.lightmodel == 2: + self.cameras['main'].setLightingColor(0, 0, 0, 1-self.light_intensity) + + def lightSourceIntensity(self, value): + if self.light_sources+value <= 255 and self.light_sources+value >= 0: + self.light_sources = self.light_sources+value + renderer = fife.LightRenderer.getInstance(self.cameras['main']) + + renderer.removeAll("beekeeper_simple_light") + renderer.removeAll("hero_simple_light") + renderer.removeAll("girl_simple_light") + + if self.lightmodel == 1: + node = fife.LightRendererNode(self.hero.agent) + renderer.addSimpleLight("hero_simple_light", node, self.light_sources, 64, 32, 1, 1, 255, 255, 255) + + node = fife.LightRendererNode(self.girl.agent) + renderer.addSimpleLight("girl_simple_light", node, self.light_sources, 64, 32, 1, 1, 255, 255, 255) + + for beekeeper in self.beekeepers: + node = fife.LightRendererNode(beekeeper.agent) + renderer.addSimpleLight("beekeeper_simple_light", node, self.light_sources, 120, 32, 1, 1, 255, 255, 255) + + if self.lightmodel == 2: + node = fife.LightRendererNode(self.hero.agent) + renderer.addSimpleLight("hero_simple_light", node, self.light_sources, 64, 32, 1, 1, 0, 0, 0) + renderer.addStencilTest("hero_simple_light") + + node = fife.LightRendererNode(self.girl.agent) + renderer.addSimpleLight("girl_simple_light", node, self.light_sources, 64, 32, 1, 1, 0, 0, 0) + renderer.addStencilTest("girl_simple_light") + + for beekeeper in self.beekeepers: + node = fife.LightRendererNode(beekeeper.agent) + renderer.addSimpleLight("beekeeper_simple_light", node, 255, 120, 32, 1, 1, 0, 0, 0) + renderer.addStencilTest("beekeeper_simple_light") + def onConsoleCommand(self, command): result = '' try: diff -r b0733d998d0f -r e3140f01749d demos/rio_de_hola/settings-dist.xml --- a/demos/rio_de_hola/settings-dist.xml Wed Nov 03 13:44:12 2010 +0000 +++ b/demos/rio_de_hola/settings-dist.xml Fri Nov 05 15:21:10 2010 +0000 @@ -19,6 +19,7 @@ False False 0 + 0 diff -r b0733d998d0f -r e3140f01749d demos/rpg/scripts/gamecontroller.py --- a/demos/rpg/scripts/gamecontroller.py Wed Nov 03 13:44:12 2010 +0000 +++ b/demos/rpg/scripts/gamecontroller.py Fri Nov 05 15:21:10 2010 +0000 @@ -28,7 +28,7 @@ from fife import fife from fife.extensions.soundmanager import SoundManager -from fife.extensions.loaders import loadImportFile +from fife.extensions.serializers.xml_loader_tools import loadImportFile from scripts.scene import Scene from scripts.guicontroller import GUIController diff -r b0733d998d0f -r e3140f01749d demos/rpg/scripts/scene.py --- a/demos/rpg/scripts/scene.py Wed Nov 03 13:44:12 2010 +0000 +++ b/demos/rpg/scripts/scene.py Fri Nov 05 15:21:10 2010 +0000 @@ -27,8 +27,9 @@ from fife import fife from fife.extensions.loaders import loadMapFile -from fife.extensions.loaders import loadImportFile +from fife.extensions.serializers.xml_loader_tools import loadImportFile from fife.extensions.serializers.simplexml import SimpleXMLSerializer +from fife.extensions.serializers.xmlobject import XMLObjectLoader from scripts.actors.baseactor import Actor from scripts.actors.questgiver import QuestGiver @@ -57,6 +58,13 @@ self._objectsettings = None self._modelsettings = None + self.obj_loader = XMLObjectLoader( + gamecontroller.engine.getImagePool(), + gamecontroller.engine.getAnimationPool(), + gamecontroller.engine.getModel(), + gamecontroller.engine.getVFS() + ) + def loadObject(self, objectname, objectid=None, valuedict=None): if objectid: identifier = objectid @@ -67,7 +75,7 @@ objdict = self._modelsettings.get("objects", objectname, {}) modeldict = self._modelsettings.get("models", objdict["modelname"], {}) - loadImportFile(modeldict["file"], self._gamecontroller.engine) + loadImportFile(self.obj_loader, modeldict["file"], self._gamecontroller.engine) if objdict["type"] == "GOLD": newobject = GoldStack(self._gamecontroller, self.itemlayer, objdict["type"], objectname, modeldict["model"], identifier) @@ -114,7 +122,7 @@ """ modeldict = self._modelsettings.get("models", "Player", {}) - loadImportFile(modeldict["file"], self._gamecontroller.engine) + loadImportFile(self.obj_loader, modeldict["file"], self._gamecontroller.engine) self._player = Player(self._gamecontroller, self.actorlayer, "warrior") playerfilename = os.path.join("saves", "player_save.xml") diff -r b0733d998d0f -r e3140f01749d demos/rpg/settings-dist.xml --- a/demos/rpg/settings-dist.xml Wed Nov 03 13:44:12 2010 +0000 +++ b/demos/rpg/settings-dist.xml Fri Nov 05 15:21:10 2010 +0000 @@ -19,6 +19,7 @@ False False 0 + 0 diff -r b0733d998d0f -r e3140f01749d demos/shooter/gui/highscores.xml --- a/demos/shooter/gui/highscores.xml Wed Nov 03 13:44:12 2010 +0000 +++ b/demos/shooter/gui/highscores.xml Fri Nov 05 15:21:10 2010 +0000 @@ -1,5 +1,5 @@ - + 100 diff -r b0733d998d0f -r e3140f01749d engine/core/controller/engine.cpp --- a/engine/core/controller/engine.cpp Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/core/controller/engine.cpp Fri Nov 05 15:21:10 2010 +0000 @@ -51,6 +51,7 @@ #include "video/cursor.h" #include "video/devicecaps.h" #ifdef HAVE_OPENGL +#include "video/opengl/fife_opengl.h" #include "video/opengl/renderbackendopengl.h" #include "gui/base/opengl/opengl_gui_graphics.h" #endif @@ -74,6 +75,7 @@ #include "view/renderers/cellselectionrenderer.h" #include "view/renderers/blockinginforenderer.h" #include "view/renderers/genericrenderer.h" +#include "view/renderers/lightrenderer.h" #include "video/image.h" #include "gui/console/console.h" #include "engine.h" @@ -256,6 +258,11 @@ if( rbackend != "SDL" ) { m_gui_graphics = new OpenGLGuiGraphics(*m_imagepool); } + + if (m_settings.getLightingModel() != 0) { + m_renderbackend->setLightingModel(m_settings.getLightingModel()); + } + #endif if( rbackend == "SDL" ) { m_gui_graphics = new SdlGuiGraphics(*m_imagepool); @@ -289,6 +296,7 @@ m_renderers.push_back(new QuadTreeRenderer(m_renderbackend, 60)); m_renderers.push_back(new CoordinateRenderer(m_renderbackend, 70, dynamic_cast(m_defaultfont))); m_renderers.push_back(new GenericRenderer(m_renderbackend, 80, m_imagepool, m_animpool)); + m_renderers.push_back(new LightRenderer(m_renderbackend, 90, m_imagepool, m_animpool)); FL_LOG(_log, "Creating model"); m_model = new Model(m_renderbackend, m_renderers, m_imagepool, m_animpool); @@ -358,8 +366,18 @@ m_renderbackend->startFrame(); m_timemanager->update(); m_model->update(); +#ifdef HAVE_OPENGL + if (m_settings.getLightingModel() == 1) { + m_renderbackend->disableLighting(); + } +#endif m_guimanager->turn(); m_cursor->draw(); +#ifdef HAVE_OPENGL + if (m_settings.getLightingModel() == 1) { + m_renderbackend->enableLighting(); + } +#endif m_renderbackend->endFrame(); } diff -r b0733d998d0f -r e3140f01749d engine/core/controller/engine.i --- a/engine/core/controller/engine.i Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/core/controller/engine.i Fri Nov 05 15:21:10 2010 +0000 @@ -81,6 +81,8 @@ const SDL_Color& getColorKey() const; void setVideoDriver(const std::string& driver); const std::string& getVideoDriver() const; + void setLightingModel(unsigned int lighting); + unsigned int getLightingModel() const; private: EngineSettings(); diff -r b0733d998d0f -r e3140f01749d engine/core/controller/enginesettings.cpp --- a/engine/core/controller/enginesettings.cpp Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/core/controller/enginesettings.cpp Fri Nov 05 15:21:10 2010 +0000 @@ -50,6 +50,7 @@ m_defaultfontpath(""), m_defaultfontsize(8), m_defaultfontglyphs(""), + m_lighting(0), m_iscolorkeyenabled(false){ m_colorkey.r = 255; m_colorkey.g = 0; @@ -199,5 +200,13 @@ const std::string& EngineSettings::getVideoDriver() const { return m_videodriver; } + void EngineSettings::setLightingModel(unsigned int lighting) { + if (lighting <= 2) { + m_lighting = lighting; + return; + } + throw NotSupported("Given light model is not supported"); + } + } diff -r b0733d998d0f -r e3140f01749d engine/core/controller/enginesettings.h --- a/engine/core/controller/enginesettings.h Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/core/controller/enginesettings.h Fri Nov 05 15:21:10 2010 +0000 @@ -214,6 +214,16 @@ const std::string& getVideoDriver() const; + /** Sets the light model + */ + void setLightingModel(unsigned int lighting); + + /** Gets the currently set light model + */ + unsigned int getLightingModel() const { + return m_lighting; + } + private: uint8_t m_bitsperpixel; bool m_fullscreen; @@ -223,7 +233,7 @@ uint16_t m_screenwidth; uint16_t m_screenheight; std::string m_windowtitle; - std::string m_windowicon; + std::string m_windowicon; std::string m_defaultfontpath; @@ -232,6 +242,7 @@ bool m_iscolorkeyenabled; SDL_Color m_colorkey; std::string m_videodriver; + unsigned int m_lighting; }; }//FIFE diff -r b0733d998d0f -r e3140f01749d engine/core/video/animation.cpp --- a/engine/core/video/animation.cpp Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/core/video/animation.cpp Fri Nov 05 15:21:10 2010 +0000 @@ -82,7 +82,7 @@ bool Animation::isValidIndex(int index) const{ int size = m_frames.size(); return size > 0 && index >= 0 && index < size; - } + } Image* Animation::getFrame(int index) { if (isValidIndex(index)) { diff -r b0733d998d0f -r e3140f01749d engine/core/video/image.h --- a/engine/core/video/image.h Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/core/video/image.h Fri Nov 05 15:21:10 2010 +0000 @@ -93,6 +93,10 @@ */ virtual void drawVertex(const Point& p, const uint8_t size, int r, int g, int b, int a = 255) = 0; + /** Draws a light primitive that based on a triangle fan + */ + virtual void drawLightPrimitive(const Point& p, uint8_t intensity, float radius, int subdivisions, float xstretch, float ystretch, uint8_t red, uint8_t green, uint8_t blue) = 0; + /** Returns pixel RGBA values from given position */ virtual void getPixelRGBA(int x, int y, uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a) = 0; diff -r b0733d998d0f -r e3140f01749d engine/core/video/opengl/fife_opengl.h --- a/engine/core/video/opengl/fife_opengl.h Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/core/video/opengl/fife_opengl.h Fri Nov 05 15:21:10 2010 +0000 @@ -29,6 +29,7 @@ #if defined( __unix__ ) #include #include +#include #endif // Win32 @@ -38,11 +39,13 @@ #include #include #include +#include #undef DELETE // MinGW #else #include #include +#include #endif #endif @@ -50,6 +53,7 @@ #if defined( __APPLE_CC__ ) #include #include +#include #endif // 3rd party library includes diff -r b0733d998d0f -r e3140f01749d engine/core/video/opengl/glimage.cpp --- a/engine/core/video/opengl/glimage.cpp Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/core/video/opengl/glimage.cpp Fri Nov 05 15:21:10 2010 +0000 @@ -110,7 +110,7 @@ uint16_t w = static_cast(round(scale_x*m_surface->w)); uint16_t h = static_cast(round(scale_y*m_surface->h)); - /// setting transparency for the whole primitive: + // setting transparency for the whole primitive: glColor4ub( 255, 255, 255, alpha ); glEnable(GL_TEXTURE_2D); @@ -239,7 +239,7 @@ glScissor(cliparea.x, getHeight() - cliparea.y - cliparea.h, cliparea.w, cliparea.h); if (clear) { - glClear(GL_COLOR_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT); } } @@ -277,4 +277,9 @@ cleanup(); m_sdlimage->drawVertex(p, size, r, g, b, a); } + + void GLImage::drawLightPrimitive(const Point& p, uint8_t intensity, float radius, int subdivisions, float xstretch, float ystretch, uint8_t red, uint8_t green, uint8_t blue) { + cleanup(); + m_sdlimage->drawLightPrimitive(p, intensity, radius, subdivisions, xstretch, ystretch, red, green, blue); + } } diff -r b0733d998d0f -r e3140f01749d engine/core/video/opengl/glimage.h --- a/engine/core/video/opengl/glimage.h Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/core/video/opengl/glimage.h Fri Nov 05 15:21:10 2010 +0000 @@ -70,6 +70,7 @@ void fillRectangle(const Point& p, uint16_t w, uint16_t h, uint8_t r, uint8_t g, uint8_t b, uint8_t a = 255); void drawQuad(const Point& p1, const Point& p2, const Point& p3, const Point& p4, int r, int g, int b, int a = 255); void drawVertex(const Point& p, const uint8_t size, int r, int g, int b, int a = 255); + void drawLightPrimitive(const Point& p, uint8_t intensity, float radius, int subdivisions, float xstretch, float ystretch, uint8_t red, uint8_t green, uint8_t blue); protected: void setClipArea(const Rect& cliparea, bool clear); diff -r b0733d998d0f -r e3140f01749d engine/core/video/opengl/renderbackendopengl.cpp --- a/engine/core/video/opengl/renderbackendopengl.cpp Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/core/video/opengl/renderbackendopengl.cpp Fri Nov 05 15:21:10 2010 +0000 @@ -36,6 +36,7 @@ #include "renderbackendopengl.h" #include "SDL_image.h" + namespace FIFE { static Logger _log(LM_VIDEO); @@ -47,6 +48,16 @@ m_rgba_format = *(testsurface->format); SDL_FreeSurface(testsurface); m_clear = false; + m_lightmodel = 0; + m_light_enabled = false; + m_stencil_enabled = false; + m_alpha_enabled = false; + m_sten_ref = 0; + m_sten_buf = 0; + m_sten_op = 0; + m_sten_func = 0; + m_blend_src = GL_SRC_ALPHA; + m_blend_dst = GL_ONE_MINUS_SRC_ALPHA; } const std::string& RenderBackendOpenGL::getName() const { @@ -66,8 +77,10 @@ if (SDL_InitSubSystem(flags) < 0) throw SDLException(SDL_GetError()); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); // temporary hack + } void RenderBackendOpenGL::clearBackBuffer() { @@ -132,6 +145,7 @@ glMatrixMode(GL_MODELVIEW); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -140,7 +154,7 @@ glPointSize(1.0); glLineWidth(1.0); - + delete m_screen; delete m_screen; m_screen = new GLImage(screen); return m_screen; @@ -182,7 +196,7 @@ return new GLImage(surface); } - SDL_Surface* conv = SDL_ConvertSurface(surface, &m_rgba_format, SDL_SWSURFACE|SDL_SRCALPHA); + SDL_Surface* conv = SDL_ConvertSurface(surface, &m_rgba_format, SDL_SWSURFACE | SDL_SRCALPHA); GLImage* image = new GLImage(conv); SDL_FreeSurface( surface ); return image; @@ -192,6 +206,183 @@ return new GLImage(data, width, height); } + void RenderBackendOpenGL::setLightingModel(unsigned int lighting) { + if (m_lightmodel != lighting) { + if (m_lightmodel == 1) { + disableLighting(); + glDisable(GL_COLOR_MATERIAL); + } else if (lighting == 1) { + enableLighting(); + glEnable(GL_LIGHT0); + glColorMaterial(GL_FRONT, GL_DIFFUSE); + glEnable(GL_COLOR_MATERIAL); + } + m_lightmodel = lighting; + } + } + + unsigned int RenderBackendOpenGL::getLightingModel() const { + return m_lightmodel; + } + + void RenderBackendOpenGL::enableLighting() { + if (m_lightmodel == 1 && !m_light_enabled) { + glEnable(GL_LIGHTING); + m_light_enabled = true; + } + } + + void RenderBackendOpenGL::disableLighting() { + if (m_lightmodel == 1 && m_light_enabled) { + glDisable(GL_LIGHTING); + m_light_enabled = false; + } + } + + void RenderBackendOpenGL::setLighting(float red, float green, float blue, float alpha) { + if (m_lightmodel == 1) { + GLfloat lightDiffuse[] = {red, green, blue, alpha}; + glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse); + } else if(m_lightmodel == 2) { + m_lred = red; + m_lgreen = green; + m_lblue = blue; + m_lalpha = alpha; + } + } + + void RenderBackendOpenGL::resetLighting() { + if (m_lightmodel == 1) { + setLighting(1.0, 1.0, 1.0, 1.0); + } else if (m_lightmodel == 2 && m_lalpha > 0.01) { + uint16_t width = getScreenWidth(); + uint16_t height = getScreenHeight(); + Point p = Point(0,0); + setStencilTest(0, 0, 5); + fillRectangle(p, width, height, m_lred*255, m_lgreen*255, m_lblue*255, m_lalpha*255); + disableStencilTest(); + } + } + + void RenderBackendOpenGL::enableStencilTest() { + if (!m_stencil_enabled) { + glEnable(GL_STENCIL_TEST); + m_stencil_enabled = true; + } + } + + void RenderBackendOpenGL::disableStencilTest() { + if (m_stencil_enabled) { + glDisable(GL_STENCIL_TEST); + m_stencil_enabled = false; + } + } + + void RenderBackendOpenGL::setStencilTest(uint8_t stencil_ref, unsigned int stencil_op, unsigned int stencil_func) { + enableStencilTest(); + if(m_sten_op != stencil_op) { + GLenum op; + m_sten_op = stencil_op; + switch(stencil_op) { + default : + case 0 : op = GL_KEEP; break; + case 1 : op = GL_ZERO; break; + case 2 : op = GL_REPLACE; break; + case 3 : op = GL_INCR; break; + case 4 : op = GL_DECR; break; + case 5 : op = GL_INVERT; break; + } + glStencilOp(GL_KEEP, GL_KEEP, op); + } + + if(m_sten_ref != stencil_ref || m_sten_func != stencil_func) { + GLenum func; + m_sten_ref = stencil_ref; + m_sten_func = stencil_func; + switch(stencil_func) { + default : + case 0 : func = GL_NEVER; break; + case 1 : func = GL_LESS; break; + case 2 : func = GL_LEQUAL; break; + case 3 : func = GL_GREATER; break; + case 4 : func = GL_GEQUAL; break; + case 5 : func = GL_EQUAL; break; + case 6 : func = GL_NOTEQUAL; break; + case 7 : func = GL_ALWAYS; break; + } + glStencilFunc(func, stencil_ref, 0xff); + } + } + + void RenderBackendOpenGL::resetStencilBuffer(uint8_t buffer) { + if (buffer != m_sten_buf) { + m_sten_buf = buffer; + glClearStencil(buffer); + } + GLDisable flag(GL_SCISSOR_TEST); + glClear(GL_STENCIL_BUFFER_BIT); + } + + uint8_t RenderBackendOpenGL::getStencilRef() const { + return m_sten_ref; + } + + void RenderBackendOpenGL::enableAlphaTest() { + if (!m_alpha_enabled) { + glEnable(GL_ALPHA_TEST); + m_alpha_enabled = true; + } + } + + void RenderBackendOpenGL::disableAlphaTest() { + if (m_alpha_enabled) { + glDisable(GL_ALPHA_TEST); + m_alpha_enabled = false; + } + } + + void RenderBackendOpenGL::setAlphaTest(float ref_alpha) { + enableAlphaTest(); + glAlphaFunc(GL_GREATER, ref_alpha); + } + + void RenderBackendOpenGL::changeBlending(int src, int dst) { + GLenum src_fact; + GLenum dst_fact; + + switch(src) { + case 0 : src_fact = GL_ZERO; break; + case 1 : src_fact = GL_ONE; break; + case 2 : src_fact = GL_DST_COLOR; break; + case 3 : src_fact = GL_ONE_MINUS_DST_COLOR; break; + case 4 : src_fact = GL_SRC_ALPHA; break; + case 5 : src_fact = GL_ONE_MINUS_SRC_ALPHA; break; + case 6 : src_fact = GL_DST_ALPHA; break; + case 7 : src_fact = GL_ONE_MINUS_DST_ALPHA; break; + + default : src_fact = GL_DST_COLOR; break; + } + + switch(dst) { + case 0 : dst_fact = GL_ZERO; break; + case 1 : dst_fact = GL_ONE; break; + case 2 : dst_fact = GL_SRC_COLOR; break; + case 3 : dst_fact = GL_ONE_MINUS_SRC_COLOR; break; + case 4 : dst_fact = GL_SRC_ALPHA; break; + case 5 : dst_fact = GL_ONE_MINUS_SRC_ALPHA; break; + case 6 : dst_fact = GL_DST_ALPHA; break; + case 7 : dst_fact = GL_ONE_MINUS_DST_ALPHA; break; + + default : dst_fact = GL_SRC_ALPHA; break; + } + + if (m_blend_src != src_fact || m_blend_dst != dst_fact) { + m_blend_src = src_fact; + m_blend_dst = dst_fact; + glBlendFunc(src_fact, dst_fact); + } + } + bool RenderBackendOpenGL::putPixel(int x, int y, int r, int g, int b, int a) { if ((x < 0) || (x >= (int)getWidth()) || (y < 0) || (y >= (int)getHeight())) { return false; @@ -277,4 +468,21 @@ glLineWidth(width); } + + void RenderBackendOpenGL::drawLightPrimitive(const Point& p, uint8_t intensity, float radius, int subdivisions, float xstretch, float ystretch, uint8_t red, uint8_t green, uint8_t blue) { + glBegin(GL_TRIANGLE_FAN); + glColor4ub(red, green, blue, intensity); + glVertex2f(p.x, p.y); + if (m_lightmodel == 2) { + glColor4ub(0, 0, 0, intensity); + } else { + glColor4ub(0, 0, 0, 255); + } + for(float angle=0; angle<=Mathf::twoPi(); angle+=(Mathf::twoPi()/subdivisions)){ + glVertex2f( radius*Mathf::Cos(angle)*xstretch + p.x, + radius*Mathf::Sin(angle)*ystretch + p.y); + } + glVertex2f(p.x+radius*xstretch, p.y); + glEnd(); + } } diff -r b0733d998d0f -r e3140f01749d engine/core/video/opengl/renderbackendopengl.h --- a/engine/core/video/opengl/renderbackendopengl.h Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/core/video/opengl/renderbackendopengl.h Fri Nov 05 15:21:10 2010 +0000 @@ -48,6 +48,21 @@ void endFrame(); void init(const std::string& driver); void clearBackBuffer(); + void setLightingModel(unsigned int lighting); + unsigned int getLightingModel() const; + void enableLighting(); + void disableLighting(); + void setLighting(float red, float green, float blue, float alpha); + void resetLighting(); + void enableStencilTest(); + void disableStencilTest(); + void setStencilTest(uint8_t stencil_ref, unsigned int stencil_op, unsigned int stencil_func); + void resetStencilBuffer(uint8_t buffer); + uint8_t getStencilRef() const; + void enableAlphaTest(); + void disableAlphaTest(); + void setAlphaTest(float ref_alpha); + void changeBlending(int scr, int dst); Image* createMainScreen(const ScreenMode& mode, const std::string& title, const std::string& icon); Image* setScreenMode(const ScreenMode& mode); @@ -60,9 +75,25 @@ void fillRectangle(const Point& p, uint16_t w, uint16_t h, uint8_t r, uint8_t g, uint8_t b, uint8_t a = 255); void drawQuad(const Point& p1, const Point& p2, const Point& p3, const Point& p4, int r, int g, int b, int a = 255); void drawVertex(const Point& p, const uint8_t size, int r, int g, int b, int a = 255); + void drawLightPrimitive(const Point& p, uint8_t intensity, float radius, int subdivisions, float xstretch, float ystretch, uint8_t red, uint8_t green, uint8_t blue); private: SDL_PixelFormat m_rgba_format; + + unsigned int m_lightmodel; + float m_lred; + float m_lgreen; + float m_lblue; + float m_lalpha; + bool m_light_enabled; + bool m_stencil_enabled; + bool m_alpha_enabled; + uint8_t m_sten_ref; + GLint m_sten_buf; + unsigned int m_sten_op; + unsigned int m_sten_func; + GLenum m_blend_src; + GLenum m_blend_dst; }; } diff -r b0733d998d0f -r e3140f01749d engine/core/video/renderbackend.h --- a/engine/core/video/renderbackend.h Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/core/video/renderbackend.h Fri Nov 05 15:21:10 2010 +0000 @@ -24,6 +24,7 @@ // Standard C++ library includes #include +#include // Platform specific includes #include "util/base/fife_stdint.h" @@ -80,6 +81,66 @@ */ virtual void clearBackBuffer() = 0; + /** Initializes the light. + */ + virtual void setLightingModel(unsigned int lighting) = 0; + + /** Gets the current light model. + */ + virtual unsigned int getLightingModel() const = 0; + + /** Enable the lighting. + */ + virtual void enableLighting() = 0; + + /** Disable the lighting. + */ + virtual void disableLighting() = 0; + + /** Set colors for lighting + */ + virtual void setLighting(float red, float green, float blue, float alpha) = 0; + + /** Reset lighting with default values. + */ + virtual void resetLighting() = 0; + + /** Enable the stencil test. + */ + virtual void enableStencilTest() = 0; + + /** Disable the stencil test. + */ + virtual void disableStencilTest() = 0; + + /** Set reference for the stencil test. + */ + virtual void setStencilTest(Uint8 stencil_ref, unsigned int stencil_op, unsigned int stencil_func) = 0; + + /** Reset stencil buffer with given value. + */ + virtual void resetStencilBuffer(Uint8 buffer) = 0; + + /** Return the reference value for the stencil test. + */ + virtual Uint8 getStencilRef() const = 0; + + /** Enable the alpha test. + */ + virtual void enableAlphaTest() = 0; + + /** Disable the stencil test. + */ + virtual void disableAlphaTest() = 0; + + /** Set reference for the alpha test. + */ + virtual void setAlphaTest(float ref_alpha) = 0; + + /** Change the Blendingmodel. + */ + virtual void changeBlending(int scr, int dst) = 0; + /** Performs cleanup actions. */ virtual void deinit(); diff -r b0733d998d0f -r e3140f01749d engine/core/video/sdl/renderbackendsdl.cpp --- a/engine/core/video/sdl/renderbackendsdl.cpp Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/core/video/sdl/renderbackendsdl.cpp Fri Nov 05 15:21:10 2010 +0000 @@ -152,6 +152,54 @@ return new SDLImage(data, width, height); } + void RenderBackendSDL::setLightingModel(unsigned int lighting) { + SDLException("Lighting not available under SDL"); + } + + unsigned int RenderBackendSDL::getLightingModel() const { + return 0; + } + + void RenderBackendSDL::enableLighting() { + } + + void RenderBackendSDL::disableLighting() { + } + + void RenderBackendSDL::setLighting(float red, float green, float blue, float alpha) { + } + + void RenderBackendSDL::resetLighting() { + } + + void RenderBackendSDL::enableStencilTest() { + } + + void RenderBackendSDL::disableStencilTest() { + } + + void RenderBackendSDL::setStencilTest(uint8_t stencil_ref, unsigned int stencil_op, unsigned int stencil_func) { + } + + void RenderBackendSDL::resetStencilBuffer(uint8_t buffer) { + } + + uint8_t RenderBackendSDL::getStencilRef() const { + return 0; + } + + void RenderBackendSDL::enableAlphaTest() { + } + + void RenderBackendSDL::disableAlphaTest() { + } + + void RenderBackendSDL::setAlphaTest(float ref_alpha) { + } + + void RenderBackendSDL::changeBlending(int scr, int dst){ + } + bool RenderBackendSDL::putPixel(int x, int y, int r, int g, int b, int a) { return static_cast(m_screen)->putPixel(x, y, r, g, b, a); } @@ -180,4 +228,7 @@ static_cast(m_screen)->drawVertex(p, 2, r, g, b, a); } + void RenderBackendSDL::drawLightPrimitive(const Point& p, uint8_t intensity, float radius, int subdivisions, float xstretch, float ystretch, uint8_t red, uint8_t green, uint8_t blue){ + static_cast(m_screen)->drawLightPrimitive(p, intensity, radius, subdivisions, xstretch, ystretch, red, green, blue); + } }//FIFE diff -r b0733d998d0f -r e3140f01749d engine/core/video/sdl/renderbackendsdl.h --- a/engine/core/video/sdl/renderbackendsdl.h Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/core/video/sdl/renderbackendsdl.h Fri Nov 05 15:21:10 2010 +0000 @@ -50,6 +50,21 @@ void endFrame(); void init(const std::string& driver); void clearBackBuffer(); + void setLightingModel(unsigned int lighting); + unsigned int getLightingModel() const; + void enableLighting(); + void disableLighting(); + void setLighting(float red, float green, float blue, float alpha); + void resetLighting(); + void enableStencilTest(); + void disableStencilTest(); + void setStencilTest(uint8_t stencil_ref, unsigned int stencil_op, unsigned int stencil_func); + void resetStencilBuffer(uint8_t buffer); + uint8_t getStencilRef() const; + void enableAlphaTest(); + void disableAlphaTest(); + void setAlphaTest(float ref_alpha); + void changeBlending(int scr, int dst); Image* createMainScreen(const ScreenMode& mode, const std::string& title, const std::string& icon); Image* setScreenMode(const ScreenMode& mode); @@ -62,6 +77,7 @@ void fillRectangle(const Point& p, uint16_t w, uint16_t h, uint8_t r, uint8_t g, uint8_t b, uint8_t a = 255); void drawQuad(const Point& p1, const Point& p2, const Point& p3, const Point& p4, int r, int g, int b, int a = 255); void drawVertex(const Point& p, const uint8_t size, int r, int g, int b, int a = 255); + void drawLightPrimitive(const Point& p, uint8_t intensity, float radius, int subdivisions, float xstretch, float ystretch, uint8_t red, uint8_t green, uint8_t blue); }; } diff -r b0733d998d0f -r e3140f01749d engine/core/video/sdl/sdlimage.cpp --- a/engine/core/video/sdl/sdlimage.cpp Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/core/video/sdl/sdlimage.cpp Fri Nov 05 15:21:10 2010 +0000 @@ -807,6 +807,9 @@ drawLine(p4, p1, r, g, b, a); } + void SDLImage::drawLightPrimitive(const Point& p, uint8_t intensity, float radius, int subdivisions, float xstretch, float ystretch, uint8_t red, uint8_t green, uint8_t blue) { + } + void SDLImage::saveImage(const std::string& filename) { if(m_surface) { const unsigned int swidth = getWidth(); diff -r b0733d998d0f -r e3140f01749d engine/core/video/sdl/sdlimage.h --- a/engine/core/video/sdl/sdlimage.h Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/core/video/sdl/sdlimage.h Fri Nov 05 15:21:10 2010 +0000 @@ -52,6 +52,7 @@ void fillRectangle(const Point& p, uint16_t w, uint16_t h, uint8_t r, uint8_t g, uint8_t b, uint8_t a = 255); void drawQuad(const Point& p1, const Point& p2, const Point& p3, const Point& p4, int r, int g, int b, int a = 255); void drawVertex(const Point& p, const uint8_t size, int r, int g, int b, int a = 255); + void drawLightPrimitive(const Point& p, uint8_t intensity, float radius, int subdivisions, float xstretch, float ystretch, uint8_t red, uint8_t green, uint8_t blue); protected: void setClipArea(const Rect& cliparea, bool clear); diff -r b0733d998d0f -r e3140f01749d engine/core/video/video.i --- a/engine/core/video/video.i Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/core/video/video.i Fri Nov 05 15:21:10 2010 +0000 @@ -64,6 +64,7 @@ virtual void drawRectangle(const Point& p, uint16_t w, uint16_t h, uint8_t r, uint8_t g, uint8_t b, uint8_t a = 255) = 0; virtual void fillRectangle(const Point& p, uint16_t w, uint16_t h, uint8_t r, uint8_t g, uint8_t b, uint8_t a = 255) = 0; virtual void drawQuad(const Point& p1, const Point& p2, const Point& p3, const Point& p4, int r, int g, int b, int a = 255) = 0; + virtual void drawLightPrimitive(const Point& p, uint8_t intensity, float radius, int subdivisions, float xstretch, float ystretch, uint8_t red, uint8_t green, uint8_t blue); virtual void pushClipArea(const Rect& cliparea, bool clear=true) = 0; virtual void popClipArea() = 0; virtual const Rect& getClipArea() const = 0; @@ -173,6 +174,7 @@ void fillRectangle(const Point& p, uint16_t w, uint16_t h, uint8_t r, uint8_t g, uint8_t b, uint8_t a = 255); void drawQuad(const Point& p1, const Point& p2, const Point& p3, const Point& p4, int r, int g, int b, int a = 255); void drawVertex(const Point& p, int size, int r, int g, int b, int a = 255); + void drawLightPrimitive(const Point& p, uint8_t intensity, float radius, int subdivisions, float xstretch, float ystretch, uint8_t red, uint8_t green, uint8_t blue); void pushClipArea(const Rect& cliparea, bool clear=true); void popClipArea(); const Rect& getClipArea() const; diff -r b0733d998d0f -r e3140f01749d engine/core/view/camera.cpp --- a/engine/core/view/camera.cpp Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/core/view/camera.cpp Fri Nov 05 15:21:10 2010 +0000 @@ -105,7 +105,9 @@ m_renderbackend(renderbackend), m_ipool(ipool), m_apool(apool), - m_layer_to_instances() { + m_layer_to_instances(), + m_lighting(false), + m_light_colors() { m_viewport = viewport; m_map_observer = new MapObserver(this); @@ -630,6 +632,29 @@ m_layer_to_instances.erase(layer); } + void Camera::setLightingColor(float red, float green, float blue, float alpha) { + m_lighting = true; + m_light_colors.clear(); + m_light_colors.push_back(red); + m_light_colors.push_back(green); + m_light_colors.push_back(blue); + m_light_colors.push_back(alpha); + } + + std::vector Camera::getLightingColor() { + if(m_light_colors.empty()) { + for(int colors = 0; colors != 4; ++colors) { + m_light_colors.push_back(1.0f); + } + } + return m_light_colors; + } + + void Camera::resetLightingColor() { + m_lighting = false; + m_renderbackend->resetLighting(); + } + void Camera::render() { Transform transform = NormalTransform; if(m_iswarped) @@ -645,13 +670,22 @@ // return; //} + if (m_renderbackend->getLightingModel() != 0) { + m_renderbackend->resetStencilBuffer(0); + if (m_lighting) { + m_renderbackend->setLighting(m_light_colors[0], m_light_colors[1], m_light_colors[2], m_light_colors[3]); + } + } + if(m_backendSDL) { m_renderbackend->pushClipArea(getViewPort()); } else { m_renderbackend->pushClipArea(getViewPort(), testRenderedViewPort()); } + // update each layer // m_layer_to_instances.clear(); + const std::list& layers = map->getLayers(); std::list::const_iterator layer_it = layers.begin(); for (;layer_it != layers.end(); ++layer_it) { @@ -671,6 +705,11 @@ } } } + + if (m_lighting) { + m_renderbackend->resetLighting(); + } + m_renderbackend->popClipArea(); resetUpdates(); m_updated = true; diff -r b0733d998d0f -r e3140f01749d engine/core/view/camera.h --- a/engine/core/view/camera.h Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/core/view/camera.h Fri Nov 05 15:21:10 2010 +0000 @@ -283,6 +283,10 @@ */ bool testRenderedViewPort(); + void setLightingColor(float red, float green, float blue, float alpha); + void resetLightingColor(); + std::vector getLightingColor(); + /** Renders camera */ void render(); @@ -356,6 +360,11 @@ std::map m_cache; MapObserver* m_map_observer; Map* m_map; + + // is lighting enable + bool m_lighting; + // caches the light color for the camera + std::vector m_light_colors; }; } #endif diff -r b0733d998d0f -r e3140f01749d engine/core/view/camera.i --- a/engine/core/view/camera.i Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/core/view/camera.i Fri Nov 05 15:21:10 2010 +0000 @@ -63,6 +63,10 @@ void getMatchingInstances(Location& loc, std::list& instances, bool use_exactcoordinates=false); RendererBase* getRenderer(const std::string& name); void resetRenderers(); + + void setLightingColor(float red, float green, float blue, float alpha); + void resetLightingColor(); + std::vector getLightingColor(); void refresh(); private: @@ -71,4 +75,4 @@ %clear std::list& instances; } -%clear InstanceLst& instances; +%clear InstanceLst& instances; \ No newline at end of file diff -r b0733d998d0f -r e3140f01749d engine/core/view/rendererbase.i --- a/engine/core/view/rendererbase.i Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/core/view/rendererbase.i Fri Nov 05 15:21:10 2010 +0000 @@ -43,6 +43,7 @@ void removeActiveLayer(Layer* layer); void clearActiveLayers(); void activateAllLayers(Map* map); + std::list getActiveLayers() const {return m_active_layers;} }; class IRendererContainer { diff -r b0733d998d0f -r e3140f01749d engine/core/view/renderers/cellselectionrenderer.cpp --- a/engine/core/view/renderers/cellselectionrenderer.cpp Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/core/view/renderers/cellselectionrenderer.cpp Fri Nov 05 15:21:10 2010 +0000 @@ -109,6 +109,8 @@ continue; } + m_renderbackend->disableLighting(); + std::vector vertices; cg->getVertices(vertices, loc.getLayerCoordinates()); std::vector::const_iterator it = vertices.begin(); @@ -125,6 +127,7 @@ pt1 = pt2; } m_renderbackend->drawLine(pt2, Point(firstpt.x, firstpt.y), m_color.r, m_color.g, m_color.b); + m_renderbackend->enableLighting(); } } diff -r b0733d998d0f -r e3140f01749d engine/core/view/renderers/floatingtextrenderer.cpp --- a/engine/core/view/renderers/floatingtextrenderer.cpp Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/core/view/renderers/floatingtextrenderer.cpp Fri Nov 05 15:21:10 2010 +0000 @@ -78,10 +78,16 @@ RenderList::const_iterator instance_it = instances.begin(); const std::string* saytext = NULL; + unsigned int lm = m_renderbackend->getLightingModel(); SDL_Color old_color = m_font->getColor(); if(m_font_color) { m_font->setColor(m_color.r, m_color.g, m_color.b, m_color.unused); } + if(lm != 0) { + m_renderbackend->disableLighting(); + m_renderbackend->setStencilTest(255, 2, 7); + m_renderbackend->setAlphaTest(0.0); + } for (;instance_it != instances.end(); ++instance_it) { Instance* instance = (*instance_it)->instance; saytext = instance->getSayText(); @@ -110,6 +116,11 @@ img->render(r); } } + if(lm != 0) { + m_renderbackend->disableAlphaTest(); + m_renderbackend->disableStencilTest(); + m_renderbackend->enableLighting(); + } if(m_font_color) { m_font->setColor(old_color.r, old_color.g, old_color.b, old_color.unused); } diff -r b0733d998d0f -r e3140f01749d engine/core/view/renderers/floatingtextrenderer.h --- a/engine/core/view/renderers/floatingtextrenderer.h Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/core/view/renderers/floatingtextrenderer.h Fri Nov 05 15:21:10 2010 +0000 @@ -89,6 +89,10 @@ */ static FloatingTextRenderer* getInstance(IRendererContainer* cnt); + /** Provides access point to the RenderBackend + */ + RenderBackend* getRenderBackend() const {return m_renderbackend;} + private: RenderBackend* m_renderbackend; AbstractFont* m_font; diff -r b0733d998d0f -r e3140f01749d engine/core/view/renderers/genericrenderer.cpp --- a/engine/core/view/renderers/genericrenderer.cpp Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/core/view/renderers/genericrenderer.cpp Fri Nov 05 15:21:10 2010 +0000 @@ -377,11 +377,36 @@ r.y = p.y-img->getHeight()/2; r.w = img->getWidth(); r.h = img->getHeight(); - if(r.intersects(viewport)) + if(r.intersects(viewport)) { + renderbackend->disableLighting(); img->render(r); + renderbackend->enableLighting(); + } } } + GenericRendererResizeInfo::GenericRendererResizeInfo(GenericRendererNode anchor, int image, int width, int height): + GenericRendererElementInfo(), + m_anchor(anchor), + m_image(image), + m_width(width), + m_height(height){ + } + void GenericRendererResizeInfo::render(Camera* cam, Layer* layer, RenderList& instances, RenderBackend* renderbackend, ImagePool* imagepool, AnimationPool* animpool) { + Point p = m_anchor.getCalculatedPoint(cam, layer); + if(m_anchor.getLayer() == layer) { + Image* img = &imagepool->getImage(m_image); + Rect r; + r.x = p.x-m_width/2; + r.y = p.y-m_height/2; + r.w = m_width; + r.h = m_height; + renderbackend->disableLighting(); + img->render(r); + renderbackend->enableLighting(); + } + } + GenericRenderer* GenericRenderer::getInstance(IRendererContainer* cnt) { return dynamic_cast(cnt->getRenderer("GenericRenderer")); } @@ -440,7 +465,10 @@ GenericRendererElementInfo* info = new GenericRendererAnimationInfo(n, animation); m_groups[group].push_back(info); } - + void GenericRenderer::resizeImage(const std::string &group, GenericRendererNode n, int image, int width, int height) { + GenericRendererElementInfo* info = new GenericRendererResizeInfo(n, image, width, height); + m_groups[group].push_back(info); + } void GenericRenderer::removeAll(const std::string &group) { std::vector::const_iterator info_it = m_groups[group].begin(); for (;info_it != m_groups[group].end(); ++info_it) { diff -r b0733d998d0f -r e3140f01749d engine/core/view/renderers/genericrenderer.h --- a/engine/core/view/renderers/genericrenderer.h Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/core/view/renderers/genericrenderer.h Fri Nov 05 15:21:10 2010 +0000 @@ -188,6 +188,17 @@ AbstractFont* m_font; std::string m_text; }; + class GenericRendererResizeInfo : public GenericRendererElementInfo { + public: + void render(Camera* cam, Layer* layer, RenderList& instances, RenderBackend* renderbackend, ImagePool* imagepool, AnimationPool* animpool); + GenericRendererResizeInfo(GenericRendererNode n, int image, int width, int height); + virtual ~GenericRendererResizeInfo() {}; + private: + GenericRendererNode m_anchor; + int m_image; + int m_width; + int m_height; + }; class GenericRenderer: public RendererBase { public: /** constructor. @@ -218,6 +229,7 @@ void addText(const std::string &group, GenericRendererNode n, AbstractFont* font, const std::string &text); void addImage(const std::string &group, GenericRendererNode n, int image); void addAnimation(const std::string &group, GenericRendererNode n, int animation); + void resizeImage(const std::string &group, GenericRendererNode n, int image, int width, int height); void removeAll(const std::string &group); private: diff -r b0733d998d0f -r e3140f01749d engine/core/view/renderers/genericrenderer.i --- a/engine/core/view/renderers/genericrenderer.i Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/core/view/renderers/genericrenderer.i Fri Nov 05 15:21:10 2010 +0000 @@ -164,6 +164,16 @@ AbstractFont* m_font; std::string m_text; }; + class GenericRendererResizeInfo : public GenericRendererElementInfo { + public: + GenericRendererResizeInfo(GenericRendererNode n, int image, int width, int height); + virtual ~GenericRendererResizeInfo() {}; + private: + GenericRendererNode m_anchor; + int m_image; + int m_width; + int m_height; + }; class GenericRenderer: public RendererBase { public: GenericRenderer(RenderBackend* renderbackend, int position, ImagePool* imagepool, AnimationPool* animpool); @@ -178,6 +188,7 @@ void addText(const std::string &group, GenericRendererNode n, AbstractFont* font, const std::string &text); void addImage(const std::string &group, GenericRendererNode n, int image); void addAnimation(const std::string &group, GenericRendererNode n, int animation); + void resizeImage(const std::string &group, GenericRendererNode n, int image, int width, int height); void removeAll(const std::string &group); }; } diff -r b0733d998d0f -r e3140f01749d engine/core/view/renderers/gridrenderer.cpp --- a/engine/core/view/renderers/gridrenderer.cpp Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/core/view/renderers/gridrenderer.cpp Fri Nov 05 15:21:10 2010 +0000 @@ -73,6 +73,7 @@ FL_WARN(_log, "No cellgrid assigned to layer, cannot draw grid"); return; } + m_renderbackend->disableLighting(); // // // //render elev_coord box @@ -180,6 +181,7 @@ } } } + m_renderbackend->enableLighting(); } void GridRenderer::setColor(Uint8 r, Uint8 g, Uint8 b) { diff -r b0733d998d0f -r e3140f01749d engine/core/view/renderers/instancerenderer.cpp --- a/engine/core/view/renderers/instancerenderer.cpp Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/core/view/renderers/instancerenderer.cpp Fri Nov 05 15:21:10 2010 +0000 @@ -40,11 +40,13 @@ #include "model/structures/instance.h" #include "model/structures/layer.h" #include "model/structures/location.h" +#include "video/opengl/fife_opengl.h" #include "view/camera.h" #include "view/visual.h" #include "instancerenderer.h" + namespace { unsigned int scale(unsigned int val, double factor) { return static_cast(ceil(static_cast(val) * factor)); @@ -129,6 +131,8 @@ } const bool any_effects = !(m_instance_outlines.empty() && m_instance_colorings.empty()); + const bool unlit = !m_unlit_groups.empty(); + unsigned int lm = m_renderbackend->getLightingModel(); m_area_layer = false; if(!m_instance_areas.empty()) { @@ -185,17 +189,56 @@ if (any_effects) { InstanceToOutlines_t::iterator outline_it = m_instance_outlines.find(instance); if (outline_it != m_instance_outlines.end()) { + if (lm != 0) { + m_renderbackend->disableLighting(); + m_renderbackend->setStencilTest(255, 2, 7); + m_renderbackend->setAlphaTest(0.0); + bindOutline(outline_it->second, vc, cam)->render(vc.dimensions, vc.transparency); + m_renderbackend->enableLighting(); + m_renderbackend->setStencilTest(0, 2, 7); + vc.image->render(vc.dimensions, vc.transparency); + m_renderbackend->disableAlphaTest(); + m_renderbackend->disableStencilTest(); + continue; + } bindOutline(outline_it->second, vc, cam)->render(vc.dimensions, vc.transparency); } InstanceToColoring_t::iterator coloring_it = m_instance_colorings.find(instance); if (coloring_it != m_instance_colorings.end()) { + m_renderbackend->disableLighting(); bindColoring(coloring_it->second, vc, cam)->render(vc.dimensions, vc.transparency); + m_renderbackend->enableLighting(); continue; // Skip normal rendering after drawing overlay } } + if(lm != 0) { + if(unlit) { + bool found = false; + std::string lit_name = instance->getObject()->getNamespace(); + std::list::iterator unlit_it = m_unlit_groups.begin(); + for(;unlit_it != m_unlit_groups.end(); ++unlit_it) { + if(lit_name.find(*unlit_it) != -1) { + m_renderbackend->setStencilTest(255, 2, 7); + found = true; + break; + } + } + // This is very expensiv, we have to change it + if(!found) + m_renderbackend->setStencilTest(0, 1, 7); + m_renderbackend->setAlphaTest(0.0); + vc.image->render(vc.dimensions, vc.transparency); + continue; + } + } vc.image->render(vc.dimensions, vc.transparency); + + } + if(lm != 0) { + m_renderbackend->disableAlphaTest(); + m_renderbackend->disableStencilTest(); } } @@ -422,10 +465,37 @@ m_instance_areas.clear(); } + void InstanceRenderer::addIgnoreLight(const std::list &groups) { + std::list::const_iterator group_it = groups.begin(); + for(;group_it != groups.end(); ++group_it) { + m_unlit_groups.push_back(*group_it); + } + m_unlit_groups.sort(); + m_unlit_groups.unique(); + } + + void InstanceRenderer::removeIgnoreLight(const std::list &groups) { + std::list::const_iterator group_it = groups.begin(); + for(;group_it != groups.end(); ++group_it) { + std::list::iterator unlit_it = m_unlit_groups.begin(); + for(;unlit_it != m_unlit_groups.end(); ++unlit_it) { + if((*group_it).find(*unlit_it) != -1) { + m_unlit_groups.remove(*unlit_it); + break; + } + } + } + } + + void InstanceRenderer::removeAllIgnoreLight() { + m_unlit_groups.clear(); + } + void InstanceRenderer::reset() { removeAllOutlines(); removeAllColored(); removeAllTransparentAreas(); + removeAllIgnoreLight(); } } diff -r b0733d998d0f -r e3140f01749d engine/core/view/renderers/instancerenderer.h --- a/engine/core/view/renderers/instancerenderer.h Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/core/view/renderers/instancerenderer.h Fri Nov 05 15:21:10 2010 +0000 @@ -95,9 +95,26 @@ */ void removeAllTransparentAreas(); + /** Add groups(Namespaces) into a list. All instances, whose namespace is in the list + * will not lighted from the LightRenderer. + */ + void addIgnoreLight(const std::list &groups); + + /** Removes groups(Namespaces) from the list + */ + void removeIgnoreLight(const std::list &groups); + + /** Removes all groups(Namespaces) + */ + void removeAllIgnoreLight(); + /** Gets instance for interface access */ static InstanceRenderer* getInstance(IRendererContainer* cnt); + + /** Provides access point to the RenderBackend + */ + RenderBackend* getRenderBackend() const {return m_renderbackend;} void reset(); @@ -105,6 +122,7 @@ ImagePool* m_imagepool; AnimationPool* m_animationpool; bool m_area_layer; + std::list m_unlit_groups; // contains per-instance information for outline drawing class OutlineInfo { diff -r b0733d998d0f -r e3140f01749d engine/core/view/renderers/instancerenderer.i --- a/engine/core/view/renderers/instancerenderer.i Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/core/view/renderers/instancerenderer.i Fri Nov 05 15:21:10 2010 +0000 @@ -43,6 +43,9 @@ void addTransparentArea(Instance* instance, const std::list &groups, unsigned int w, unsigned int h, unsigned char trans, bool front = true); void removeTransparentArea(Instance* instance); void removeAllTransparentAreas(); + void addIgnoreLight(const std::list &groups); + void removeIgnoreLight(const std::list &groups); + void removeAllIgnoreLight(); static InstanceRenderer* getInstance(IRendererContainer* cnt); private: InstanceRenderer(RenderBackend* renderbackend, int position, ImagePool* imagepool, AnimationPool* animpool); diff -r b0733d998d0f -r e3140f01749d engine/core/view/renderers/lightrenderer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/engine/core/view/renderers/lightrenderer.cpp Fri Nov 05 15:21:10 2010 +0000 @@ -0,0 +1,555 @@ +/*************************************************************************** + * Copyright (C) 2005-2008 by the FIFE team * + * http://www.fifengine.de * + * This file is part of FIFE. * + * * + * FIFE is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +// Standard C++ library includes +#include + +// 3rd party library includes + +// FIFE includes +// These includes are split up in two parts, separated by one empty line +// First block: files included from the FIFE root src directory +// Second block: files included from the same folder +#include "video/renderbackend.h" +#include "video/imagepool.h" +#include "video/animation.h" +#include "video/animationpool.h" +#include "video/fonts/abstractfont.h" +#include "video/image.h" +#include "video/opengl/glimage.h" +#include "util/math/fife_math.h" +#include "util/log/logger.h" +#include "util/time/timemanager.h" +#include "model/metamodel/grids/cellgrid.h" +#include "model/metamodel/timeprovider.h" +#include "model/structures/instance.h" +#include "model/structures/layer.h" +#include "model/structures/location.h" + +#include "view/camera.h" +#include "lightrenderer.h" + + +namespace FIFE { + static Logger _log(LM_VIEWVIEW); + + LightRendererNode::LightRendererNode(Instance* attached_instance, const Location &relative_location, Layer* relative_layer, const Point &relative_point): + m_instance(attached_instance), + m_location(relative_location), + m_layer(relative_layer), + m_point(relative_point) { + } + LightRendererNode::LightRendererNode(Instance* attached_instance, const Location &relative_location, const Point &relative_point): + m_instance(attached_instance), + m_location(relative_location), + m_layer(NULL), + m_point(relative_point) { + } + LightRendererNode::LightRendererNode(Instance* attached_instance, Layer* relative_layer, const Point &relative_point): + m_instance(attached_instance), + m_location(NULL), + m_layer(relative_layer), + m_point(relative_point) { + } + LightRendererNode::LightRendererNode(Instance* attached_instance, const Point &relative_point): + m_instance(attached_instance), + m_location(NULL), + m_layer(NULL), + m_point(relative_point) { + } + LightRendererNode::LightRendererNode(const Location &attached_location, Layer* relative_layer, const Point &relative_point): + m_instance(NULL), + m_location(attached_location), + m_layer(relative_layer), + m_point(relative_point) { + } + LightRendererNode::LightRendererNode(const Location &attached_location, const Point &relative_point): + m_instance(NULL), + m_location(attached_location), + m_layer(NULL), + m_point(relative_point) { + } + LightRendererNode::LightRendererNode(Layer* attached_layer, const Point &relative_point): + m_instance(NULL), + m_location(NULL), + m_layer(attached_layer), + m_point(relative_point) { + } + LightRendererNode::LightRendererNode(const Point &attached_point): + m_instance(NULL), + m_location(NULL), + m_layer(NULL), + m_point(attached_point) { + } + LightRendererNode::~LightRendererNode() { + } + + void LightRendererNode::setAttached(Instance* attached_instance, const Location &relative_location, const Point &relative_point) { + m_instance = attached_instance; + m_location = relative_location; + m_point = relative_point; + } + void LightRendererNode::setAttached(Instance* attached_instance, const Location &relative_location) { + m_instance = attached_instance; + m_location = relative_location; + } + void LightRendererNode::setAttached(Instance* attached_instance, const Point &relative_point) { + m_instance = attached_instance; + m_point = relative_point; + } + void LightRendererNode::setAttached(Instance* attached_instance) { + m_instance = attached_instance; + } + void LightRendererNode::setAttached(const Location &attached_location, const Point &relative_point) { + m_instance = NULL; + m_location = attached_location; + m_point = relative_point; + } + void LightRendererNode::setAttached(const Location &attached_location) { + m_instance = NULL; + m_location = attached_location; + } + void LightRendererNode::setAttached(Layer* attached_layer) { + m_layer = attached_layer; + } + void LightRendererNode::setAttached(const Point &attached_point) { + m_instance = NULL; + m_location = NULL; + m_point = attached_point; + } + + void LightRendererNode::setRelative(const Location &relative_location) { + if(m_instance == NULL) { + throw NotSupported("No instance attached."); + } + m_location = relative_location; + } + void LightRendererNode::setRelative(const Location &relative_location, Point relative_point) { + if(m_instance == NULL) { + throw NotSupported("No instance attached."); + } + m_location = relative_location; + m_point = relative_point; + } + void LightRendererNode::setRelative(const Point &relative_point) { + if(m_instance == NULL || m_location == NULL) { + throw NotSupported("No instance or location attached."); + } + m_point = relative_point; + } + + Instance* LightRendererNode::getAttachedInstance() { + if(m_instance == NULL) { + throw NotSupported("No instance attached."); + } + return m_instance; + } + Location LightRendererNode::getAttachedLocation() { + if(m_instance != NULL || m_location == NULL) { + throw NotSupported("No location attached."); + } + return m_location; + } + Layer* LightRendererNode::getAttachedLayer() { + if(m_layer == NULL) { + throw NotSupported("No layer attached."); + } + return m_layer; + } + Point LightRendererNode::getAttachedPoint() { + if(m_instance != NULL || m_location != NULL) { + throw NotSupported("No point attached."); + } + return m_point; + } + + Location LightRendererNode::getOffsetLocation() { + if(m_instance == NULL || m_location == NULL) { + throw NotSupported("No location as offset used."); + } + return m_location; + } + Point LightRendererNode::getOffsetPoint() { + if(m_instance == NULL && m_location == NULL) { + throw NotSupported("No point as offset used."); + } + return m_point; + } + + Instance* LightRendererNode::getInstance() { + return m_instance; + } + Location LightRendererNode::getLocation() { + return m_location; + } + Layer* LightRendererNode::getLayer() { + return m_layer; + } + Point LightRendererNode::getPoint() { + return m_point; + } + + Point LightRendererNode::getCalculatedPoint(Camera* cam, Layer* layer) { + ScreenPoint p; + if(m_instance != NULL) { + if(m_layer == NULL) { + m_layer = m_instance->getLocation().getLayer(); + } + if(m_location != NULL) { + p = cam->toScreenCoordinates(m_instance->getLocationRef().getMapCoordinates() + m_location.getMapCoordinates()); + } else { + p = cam->toScreenCoordinates(m_instance->getLocation().getMapCoordinates()); + } + } else if(m_location != NULL) { + if(m_layer == NULL) { + m_layer = m_location.getLayer(); + } + p = cam->toScreenCoordinates(m_location.getMapCoordinates()); + } else if(m_layer == NULL) { + const std::list& layers = cam->getRenderer("LightRenderer")->getActiveLayers(); + std::list::const_reverse_iterator layer_it = layers.rbegin(); + setAttached(*layer_it); + } + return Point(m_point.x + p.x, m_point.y + p.y); + } + + LightRendererImageInfo::LightRendererImageInfo(LightRendererNode anchor, int image, int src, int dst): + LightRendererElementInfo(), + m_anchor(anchor), + m_image(image), + m_src(src), + m_dst(dst), + m_stencil(false), + m_stencil_ref(0), + m_alpha_ref(0.0) { + } + void LightRendererImageInfo::render(Camera* cam, Layer* layer, RenderList& instances, RenderBackend* renderbackend, ImagePool* imagepool, AnimationPool* animpool) { + Point p = m_anchor.getCalculatedPoint(cam, layer); + if(m_anchor.getLayer() == layer) { + Image* img = &imagepool->getImage(m_image); + Rect r; + Rect viewport = cam->getViewPort(); + r.x = p.x-img->getWidth()/2; + r.y = p.y-img->getHeight()/2; + r.w = img->getWidth(); + r.h = img->getHeight(); + renderbackend->changeBlending(m_src, m_dst); + if(r.intersects(viewport)) + img->render(r); + } + } + void LightRendererImageInfo::setStencil(uint8_t stencil_ref, float alpha_ref) { + m_stencil = true; + m_stencil_ref = stencil_ref; + m_alpha_ref = alpha_ref; + } + int LightRendererImageInfo::getStencil() { + if(!m_stencil) { + return -1; + } + return m_stencil_ref; + } + float LightRendererImageInfo::getAlpha() { + return m_alpha_ref; + } + void LightRendererImageInfo::removeStencil() { + m_stencil = false; + m_stencil_ref = 0; + m_alpha_ref = 0.0; + } + + LightRendererAnimationInfo::LightRendererAnimationInfo(LightRendererNode anchor, int animation, int src, int dst): + LightRendererElementInfo(), + m_anchor(anchor), + m_animation(animation), + m_src(src), + m_dst(dst), + m_start_time(TimeManager::instance()->getTime()), + m_time_scale(1.0), + m_stencil(false), + m_stencil_ref(0), + m_alpha_ref(0.0) { + } + void LightRendererAnimationInfo::render(Camera* cam, Layer* layer, RenderList& instances, RenderBackend* renderbackend, ImagePool* imagepool, AnimationPool* animpool) { + Point p = m_anchor.getCalculatedPoint(cam, layer); + if(m_anchor.getLayer() == layer) { + Animation& animation = animpool->getAnimation(m_animation); + int animtime = scaleTime(m_time_scale, TimeManager::instance()->getTime() - m_start_time) % animation.getDuration(); + Image* img = animation.getFrameByTimestamp(animtime); + Rect r; + Rect viewport = cam->getViewPort(); + r.x = p.x-img->getWidth()/2; + r.y = p.y-img->getHeight()/2; + r.w = img->getWidth(); + r.h = img->getHeight(); + renderbackend->changeBlending(m_src, m_dst); + if(r.intersects(viewport)) + img->render(r); + } + } + void LightRendererAnimationInfo::setStencil(uint8_t stencil_ref, float alpha_ref) { + m_stencil = true; + m_stencil_ref = stencil_ref; + m_alpha_ref = alpha_ref; + } + int LightRendererAnimationInfo::getStencil() { + if(!m_stencil) { + return -1; + } + return m_stencil_ref; + } + float LightRendererAnimationInfo::getAlpha() { + return m_alpha_ref; + } + void LightRendererAnimationInfo::removeStencil() { + m_stencil = false; + m_stencil_ref = 0; + m_alpha_ref = 0.0; + } + + LightRendererResizeInfo::LightRendererResizeInfo(LightRendererNode anchor, int image, int width, int height, int src, int dst): + LightRendererElementInfo(), + m_anchor(anchor), + m_image(image), + m_width(width), + m_height(height), + m_src(src), + m_dst(dst), + m_stencil(false), + m_stencil_ref(0), + m_alpha_ref(0.0) { + } + void LightRendererResizeInfo::render(Camera* cam, Layer* layer, RenderList& instances, RenderBackend* renderbackend, ImagePool* imagepool, AnimationPool* animpool) { + Point p = m_anchor.getCalculatedPoint(cam, layer); + if(m_anchor.getLayer() == layer) { + Image* img = &imagepool->getImage(m_image); + Rect r; + Rect viewport = cam->getViewPort(); + r.x = p.x-m_width/2; + r.y = p.y-m_height/2; + r.w = m_width; + r.h = m_height; + renderbackend->changeBlending(m_src, m_dst); + if(r.intersects(viewport)) + img->render(r); + } + } + void LightRendererResizeInfo::setStencil(uint8_t stencil_ref, float alpha_ref) { + m_stencil = true; + m_stencil_ref = stencil_ref; + m_alpha_ref = alpha_ref; + } + int LightRendererResizeInfo::getStencil() { + if(!m_stencil) { + return -1; + } + return m_stencil_ref; + } + float LightRendererResizeInfo::getAlpha() { + return m_alpha_ref; + } + void LightRendererResizeInfo::removeStencil() { + m_stencil = false; + m_stencil_ref = 0; + m_alpha_ref = 0.0; + } + + LightRendererSimpleLightInfo::LightRendererSimpleLightInfo(LightRendererNode anchor, uint8_t intensity, float radius, int subdivisions, float xstretch, float ystretch, uint8_t r, uint8_t g, uint8_t b, int src, int dst): + LightRendererElementInfo(), + m_anchor(anchor), + m_intensity(intensity), + m_radius(radius), + m_subdivisions(subdivisions), + m_xstretch(xstretch), + m_ystretch(ystretch), + m_red(r), + m_green(g), + m_blue(b), + m_src(src), + m_dst(dst), + m_stencil(false), + m_stencil_ref(0), + m_alpha_ref(0.0) { + } + void LightRendererSimpleLightInfo::render(Camera* cam, Layer* layer, RenderList& instances, RenderBackend* renderbackend, ImagePool* imagepool, AnimationPool* animpool) { + Point p = m_anchor.getCalculatedPoint(cam, layer); + if(m_anchor.getLayer() == layer) { + renderbackend->changeBlending(m_src, m_dst); + renderbackend->drawLightPrimitive(p, m_intensity, m_radius, m_subdivisions, m_xstretch, m_ystretch, m_red, m_green, m_blue); + } + } + void LightRendererSimpleLightInfo::setStencil(uint8_t stencil_ref, float alpha_ref) { + m_stencil = true; + m_stencil_ref = stencil_ref; + m_alpha_ref = alpha_ref; + } + int LightRendererSimpleLightInfo::getStencil() { + if(!m_stencil) { + return -1; + } + return m_stencil_ref; + } + float LightRendererSimpleLightInfo::getAlpha() { + return m_alpha_ref; + } + void LightRendererSimpleLightInfo::removeStencil() { + m_stencil = false; + m_stencil_ref = 0; + m_alpha_ref = 0.0; + } + std::vector LightRendererSimpleLightInfo::getColor() { + std::vector colors; + colors.push_back(m_red); + colors.push_back(m_green); + colors.push_back(m_blue); + colors.push_back(m_intensity); + return colors; + } + + LightRenderer* LightRenderer::getInstance(IRendererContainer* cnt) { + return dynamic_cast(cnt->getRenderer("LightRenderer")); + } + + LightRenderer::LightRenderer(RenderBackend* renderbackend, int position, ImagePool* imagepool, AnimationPool* animpool): + RendererBase(renderbackend, position), + m_imagepool(imagepool), + m_animationpool(animpool), + m_groups() { + setEnabled(false); + } + + LightRenderer::LightRenderer(const LightRenderer& old): + RendererBase(old), + m_imagepool(old.m_imagepool), + m_animationpool(old.m_animationpool), + m_groups() { + setEnabled(false); + } + + RendererBase* LightRenderer::clone() { + return new LightRenderer(*this); + } + + LightRenderer::~LightRenderer() { + } + // Add a static lightmap + void LightRenderer::addImage(const std::string &group, LightRendererNode n, int image, int src, int dst) { + LightRendererElementInfo* info = new LightRendererImageInfo(n, image, src, dst); + m_groups[group].push_back(info); + } + // Add a animation lightmap + void LightRenderer::addAnimation(const std::string &group, LightRendererNode n, int animation, int src, int dst) { + LightRendererElementInfo* info = new LightRendererAnimationInfo(n, animation, src, dst); + m_groups[group].push_back(info); + } + // Add a simple light + void LightRenderer::addSimpleLight(const std::string &group, LightRendererNode n, uint8_t intensity, float radius, int subdivisions, float xstretch, float ystretch, uint8_t r, uint8_t g, uint8_t b, int src, int dst) { + LightRendererElementInfo* info = new LightRendererSimpleLightInfo(n, intensity, radius, subdivisions, xstretch, ystretch, r, g, b, src, dst); + m_groups[group].push_back(info); + } + // Resize an Image + void LightRenderer::resizeImage(const std::string &group, LightRendererNode n, int image, int width, int height, int src, int dst) { + LightRendererElementInfo* info = new LightRendererResizeInfo(n, image, width, height, src, dst); + m_groups[group].push_back(info); + } + // Enable stencil test for the group + void LightRenderer::addStencilTest(const std::string &group, uint8_t stencil_ref, float alpha_ref) { + std::vector::const_iterator info_it = m_groups[group].begin(); + for (;info_it != m_groups[group].end(); ++info_it) { + (*info_it)->setStencil(stencil_ref, alpha_ref); + } + } + // Disable stencil test for the group + void LightRenderer::removeStencilTest(const std::string &group) { + std::vector::const_iterator info_it = m_groups[group].begin(); + for (;info_it != m_groups[group].end(); ++info_it) { + (*info_it)->removeStencil(); + } + } + // Return a list of all groups + std::list LightRenderer::getGroups() { + std::list groups; + std::map >::iterator group_it = m_groups.begin(); + for(; group_it != m_groups.end(); ++group_it) { + groups.push_back(group_it->first); + } + groups.sort(); + groups.unique(); + return groups; + } + // Return a vector of all LightElementInfos + std::vector LightRenderer::getLightInfo(const std::string &group) { + std::vector info; + std::vector::const_iterator info_it = m_groups[group].begin(); + for (;info_it != m_groups[group].end(); ++info_it) { + info.push_back(*info_it); + } + return info; + } + // Remove the group + void LightRenderer::removeAll(const std::string &group) { + std::vector::const_iterator info_it = m_groups[group].begin(); + for (;info_it != m_groups[group].end(); ++info_it) { + delete *info_it; + } + m_groups[group].clear(); + m_groups.erase(group); + } + // Render + void LightRenderer::render(Camera* cam, Layer* layer, RenderList& instances) { + uint8_t lm = m_renderbackend->getLightingModel(); + + if (!layer->areInstancesVisible()) { + return; + } + m_renderbackend->disableLighting(); + std::map >::iterator group_it = m_groups.begin(); + for (; group_it != m_groups.end(); ++group_it) { + std::vector::const_iterator info_it = group_it->second.begin(); + for (;info_it != group_it->second.end(); ++info_it) { + if (lm != 0) { + if ((*info_it)->getStencil() != -1) { + uint8_t sref = (*info_it)->getStencil(); + float aref = (*info_it)->getAlpha(); + if(info_it != group_it->second.begin()) + sref += 1; + m_renderbackend->setStencilTest(sref, 3, 4); + m_renderbackend->setAlphaTest(aref); + } else if(lm == 1) { + m_renderbackend->setStencilTest(255, 0, 6); + m_renderbackend->setAlphaTest(0); + } else if(lm == 2) { + m_renderbackend->setStencilTest(1, 2, 4); + m_renderbackend->setAlphaTest(0); + } + (*info_it)->render(cam, layer, instances, m_renderbackend, m_imagepool, m_animationpool); + m_renderbackend->disableAlphaTest(); + m_renderbackend->disableStencilTest(); + } else { + (*info_it)->render(cam, layer, instances, m_renderbackend, m_imagepool, m_animationpool); + } + } + } + m_renderbackend->changeBlending(4, 5); + m_renderbackend->enableLighting(); + } + +} \ No newline at end of file diff -r b0733d998d0f -r e3140f01749d engine/core/view/renderers/lightrenderer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/engine/core/view/renderers/lightrenderer.h Fri Nov 05 15:21:10 2010 +0000 @@ -0,0 +1,255 @@ +/*************************************************************************** + * Copyright (C) 2005-2008 by the FIFE team * + * http://www.fifengine.de * + * This file is part of FIFE. * + * * + * FIFE is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef FIFE_LIGHTRENDERER_H +#define FIFE_LIGHTRENDERER_H + +// Standard C++ library includes +#include + +// 3rd party library includes + +// FIFE includes +// These includes are split up in two parts, separated by one empty line +// First block: files included from the FIFE root src directory +// Second block: files included from the same folder +#include "view/rendererbase.h" + +namespace FIFE { + class RenderBackend; + class AbstractFont; + class ImagePool; + class AnimationPool; + + class LightRendererNode { + public: + LightRendererNode(Instance* attached_instance, const Location &relative_location, Layer* relative_layer, const Point &relative_point = Point(0,0)); + LightRendererNode(Instance* attached_instance, const Location &relative_location, const Point &relative_point = Point(0,0)); + LightRendererNode(Instance* attached_instance, Layer* relative_layer, const Point &relative_point = Point(0,0)); + LightRendererNode(Instance* attached_instance, const Point &relative_point = Point(0,0)); + LightRendererNode(const Location &attached_location, Layer* relative_layer, const Point &relative_point = Point(0,0)); + LightRendererNode(const Location &attached_location, const Point &relative_point = Point(0,0)); + LightRendererNode(Layer* attached_layer, const Point &relative_point = Point(0,0)); + LightRendererNode(const Point &attached_point); + ~LightRendererNode(); + + void setAttached(Instance* attached_instance, const Location &relative_location, const Point &relative_point); + void setAttached(Instance* attached_instance, const Location &relative_location); + void setAttached(Instance* attached_instance, const Point &relative_point); + void setAttached(Instance* attached_instance); + void setAttached(const Location &attached_location, const Point &relative_point); + void setAttached(const Location &attached_location); + void setAttached(Layer* attached_layer); + void setAttached(const Point &attached_point); + + void setRelative(const Location &relative_location); + void setRelative(const Location &relative_location, Point relative_point); + void setRelative(const Point &relative_point); + + Instance* getAttachedInstance(); + Location getAttachedLocation(); + Layer* getAttachedLayer(); + Point getAttachedPoint(); + + Location getOffsetLocation(); + Point getOffsetPoint(); + + Instance* getInstance(); + Location getLocation(); + Layer* getLayer(); + Point getPoint(); + + Point getCalculatedPoint(Camera* cam, Layer* layer); + private: + Instance* m_instance; + Location m_location; + Layer* m_layer; + Point m_point; + }; + + class LightRendererElementInfo { + public: + virtual void render(Camera* cam, Layer* layer, RenderList& instances, RenderBackend* renderbackend, ImagePool* imagepool, AnimationPool* animpool) {}; + virtual std::string getName() { return 0; }; + virtual LightRendererNode* getNode() { return NULL; }; + virtual int getId() { return -1; }; + virtual int getSrcBlend() { return -1; }; + virtual int getDstBlend() { return -1; }; + virtual void setStencil(uint8_t stencil_ref, float alpha_ref) {}; + virtual int getStencil() { return 0; }; + virtual float getAlpha() { return 0; }; + virtual void removeStencil() {}; + virtual std::vector getColor() {}; + virtual float getRadius() { return 0; }; + virtual int getSubdivisions() { return 0; }; + virtual float getXStretch() { return 0; }; + virtual float getYStretch() { return 0; }; + virtual ~LightRendererElementInfo() {}; + }; + + class LightRendererImageInfo : public LightRendererElementInfo { + public: + void render(Camera* cam, Layer* layer, RenderList& instances, RenderBackend* renderbackend, ImagePool* imagepool, AnimationPool* animpool); + std::string getName() { return "image"; }; + LightRendererNode* getNode() { return &m_anchor; }; + int getId() { return m_image; }; + int getSrcBlend() { return m_src; }; + int getDstBlend() { return m_dst; }; + void setStencil(uint8_t stencil_ref, float alpha_ref); + int getStencil(); + float getAlpha(); + void removeStencil(); + LightRendererImageInfo(LightRendererNode n, int image, int src, int dst); + virtual ~LightRendererImageInfo() {}; + private: + LightRendererNode m_anchor; + int m_image; + int m_src; + int m_dst; + bool m_stencil; + uint8_t m_stencil_ref; + float m_alpha_ref; + }; + class LightRendererAnimationInfo : public LightRendererElementInfo { + public: + void render(Camera* cam, Layer* layer, RenderList& instances, RenderBackend* renderbackend, ImagePool* imagepool, AnimationPool* animpool); + std::string getName() { return "animation"; }; + LightRendererNode* getNode() { return &m_anchor; }; + int getId() { return m_animation; }; + int getSrcBlend() { return m_src; }; + int getDstBlend() { return m_dst; }; + void setStencil(uint8_t stencil_ref, float alpha_ref); + int getStencil(); + float getAlpha(); + void removeStencil(); + LightRendererAnimationInfo(LightRendererNode n, int animation, int src, int dst); + virtual ~LightRendererAnimationInfo() {}; + private: + LightRendererNode m_anchor; + int m_animation; + int m_src; + int m_dst; + unsigned int m_start_time; + float m_time_scale; + bool m_stencil; + uint8_t m_stencil_ref; + float m_alpha_ref; + }; + class LightRendererSimpleLightInfo : public LightRendererElementInfo { + public: + void render(Camera* cam, Layer* layer, RenderList& instances, RenderBackend* renderbackend, ImagePool* imagepool, AnimationPool* animpool); + std::string getName() { return "simple"; }; + LightRendererNode* getNode() { return &m_anchor; }; + int getSrcBlend() { return m_src; }; + int getDstBlend() { return m_dst; }; + void setStencil(uint8_t stencil_ref, float alpha_ref); + int getStencil(); + float getAlpha(); + void removeStencil(); + std::vector getColor(); + float getRadius() { return m_radius; }; + int getSubdivisions() { return m_subdivisions; }; + float getXStretch() { return m_xstretch; }; + float getYStretch() { return m_ystretch; }; + LightRendererSimpleLightInfo(LightRendererNode n, uint8_t intensity, float radius, int subdivisions, float xstretch, float ystretch, uint8_t r, uint8_t g, uint8_t b, int src, int dst); + virtual ~LightRendererSimpleLightInfo() {}; + private: + LightRendererNode m_anchor; + uint8_t m_intensity; + float m_radius; + int m_subdivisions; + float m_xstretch; + float m_ystretch; + uint8_t m_red; + uint8_t m_green; + uint8_t m_blue; + int m_src; + int m_dst; + bool m_stencil; + uint8_t m_stencil_ref; + float m_alpha_ref; + }; + class LightRendererResizeInfo : public LightRendererElementInfo { + public: + void render(Camera* cam, Layer* layer, RenderList& instances, RenderBackend* renderbackend, ImagePool* imagepool, AnimationPool* animpool); + std::string getName() { return "resize"; }; + LightRendererNode* getNode() { return &m_anchor; }; + int getId() { return m_image; }; + int getSrcBlend() { return m_src; }; + int getDstBlend() { return m_dst; }; + void setStencil(uint8_t stencil_ref, float alpha_ref); + int getStencil(); + float getAlpha(); + void removeStencil(); + LightRendererResizeInfo(LightRendererNode n, int image, int width, int height, int src, int dst); + virtual ~LightRendererResizeInfo() {}; + private: + LightRendererNode m_anchor; + int m_image; + int m_width; + int m_height; + int m_src; + int m_dst; + bool m_stencil; + uint8_t m_stencil_ref; + float m_alpha_ref; + }; + class LightRenderer: public RendererBase { + public: + /** constructor. + * @param renderbackend to use + * @param position position for this renderer in rendering pipeline + */ + LightRenderer(RenderBackend* renderbackend, int position, ImagePool* imagepool, AnimationPool* animpool); + + LightRenderer(const LightRenderer& old); + + RendererBase* clone(); + + /** Destructor. + */ + virtual ~LightRenderer(); + void render(Camera* cam, Layer* layer, RenderList& instances); + std::string getName() { return "LightRenderer"; } + + /** Gets instance for interface access + */ + static LightRenderer* getInstance(IRendererContainer* cnt); + + void addImage(const std::string &group, LightRendererNode n, int image, int src=-1, int dst=-1); + void addAnimation(const std::string &group, LightRendererNode n, int animation, int src=-1, int dst=-1); + void addSimpleLight(const std::string &group, LightRendererNode n, uint8_t intensity, float radius, int subdivisions, float xstretch, float ystretch, uint8_t r, uint8_t g, uint8_t b, int src=-1, int dst=-1); + void resizeImage(const std::string &group, LightRendererNode n, int image, int width, int height, int src=-1, int dst=-1); + void addStencilTest(const std::string &group, uint8_t stencil_ref=0, float alpha_ref=0.0); + void removeStencilTest(const std::string &group); + std::list getGroups(); + std::vector getLightInfo(const std::string &group); + void removeAll(const std::string &group); + + private: + ImagePool* m_imagepool; + AnimationPool* m_animationpool; + std::map > m_groups; + }; + +} + +#endif diff -r b0733d998d0f -r e3140f01749d engine/core/view/renderers/lightrenderer.i --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/engine/core/view/renderers/lightrenderer.i Fri Nov 05 15:21:10 2010 +0000 @@ -0,0 +1,175 @@ +/*************************************************************************** + * Copyright (C) 2005-2008 by the FIFE team * + * http://www.fifengine.de * + * This file is part of FIFE. * + * * + * FIFE is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +%module fife +%{ +#include "view/renderers/lightrenderer.h" +%} + +namespace FIFE { + class RenderBackend; + + class LightRendererNode { + public: + LightRendererNode(Instance* attached_instance, const Location &relative_location, Layer* relative_layer, const Point &relative_point = Point(0,0)); + LightRendererNode(Instance* attached_instance, const Location &relative_location, const Point &relative_point = Point(0,0)); + LightRendererNode(Instance* attached_instance, Layer* relative_layer, const Point &relative_point = Point(0,0)); + LightRendererNode(Instance* attached_instance, const Point &relative_point = Point(0,0)); + LightRendererNode(const Location &attached_location, Layer* relative_layer, const Point &relative_point = Point(0,0)); + LightRendererNode(const Location &attached_location, const Point &relative_point = Point(0,0)); + LightRendererNode(Layer* attached_layer, const Point &relative_point = Point(0,0)); + LightRendererNode(const Point &attached_point); + ~LightRendererNode(); + + void setAttached(Instance* attached_instance, const Location &relative_location, const Point &relative_point); + void setAttached(Instance* attached_instance, const Location &relative_location); + void setAttached(Instance* attached_instance, const Point &relative_point); + void setAttached(Instance* attached_instance); + void setAttached(const Location &attached_location, const Point &relative_point); + void setAttached(const Location &attached_location); + void setAttached(Layer* attached_layer); + void setAttached(const Point &attached_point); + + void setRelative(const Location &relative_location); + void setRelative(const Location &relative_location, Point relative_point); + void setRelative(const Point &relative_point); + + Instance* getAttachedInstance(); + Location getAttachedLocation(); + Layer* getAttachedLayer(); + Point getAttachedPoint(); + + Location getOffsetLocation(); + Point getOffsetPoint(); + + Instance* getInstance(); + Location getLocation(); + Layer* getLayer(); + Point getPoint(); + + Point getCalculatedPoint(Camera* cam, Layer* layer); + private: + Instance* m_instance; + Location m_location; + Layer* m_layer; + Point m_point; + }; + class LightRendererElementInfo { + public: + virtual std::string getName() { return 0; }; + virtual LightRendererNode* getNode() { return NULL; }; + virtual int getId() { return -1; }; + virtual int getSrcBlend() { return -1; }; + virtual int getDstBlend() { return -1; }; + virtual void setStencil(uint8_t stencil_ref, float alpha_ref) {}; + virtual int getStencil() { return 0; }; + virtual float getAlpha() { return 0; }; + virtual void removeStencil() {}; + virtual std::vector getColor() {}; + virtual float getRadius() { return 0; }; + virtual int getSubdivisions() { return 0; }; + virtual float getXStretch() { return 0; }; + virtual float getYStretch() { return 0; }; + virtual ~LightRendererElementInfo() {}; + }; + + class LightRendererImageInfo : public LightRendererElementInfo { + public: + LightRendererImageInfo(LightRendererNode n, int image, int src, int dst); + virtual ~LightRendererImageInfo() {}; + private: + LightRendererNode m_anchor; + int m_image; + int m_src; + int m_dst; + bool m_stencil; + uint8_t m_stencil_ref; + float m_alpha_ref; + }; + class LightRendererAnimationInfo : public LightRendererElementInfo { + public: + LightRendererAnimationInfo(LightRendererNode n, int animation, int src, int dst); + virtual ~LightRendererAnimationInfo() {}; + private: + LightRendererNode m_anchor; + int m_animation; + int m_src; + int m_dst; + bool m_stencil; + uint8_t m_stencil_ref; + float m_alpha_ref; + }; + class LightRendererSimpleLightInfo : public LightRendererElementInfo { + public: + LightRendererSimpleLightInfo(LightRendererNode n, uint8_t intensity, float radius, int subdivisions, float xstretch, float ystretch, uint8_t r, uint8_t g, uint8_t b, int src, int dst); + virtual ~LightRendererSimpleLightInfo() {}; + private: + LightRendererNode m_anchor; + uint8_t m_intensity; + float m_radius; + int m_subdivisions; + float m_xstretch; + float m_ystretch; + uint8_t m_red; + uint8_t m_green; + uint8_t m_blue; + int m_src; + int m_dst; + bool m_stencil; + uint8_t m_stencil_ref; + float m_alpha_ref; + }; + class LightRendererResizeInfo : public LightRendererElementInfo { + public: + LightRendererResizeInfo(LightRendererNode n, int image, int width, int height, int src, int dst); + virtual ~LightRendererResizeInfo() {}; + private: + LightRendererNode m_anchor; + int m_image; + int m_width; + int m_height; + int m_src; + int m_dst; + bool m_stencil; + uint8_t m_stencil_ref; + float m_alpha_ref; + }; + class LightRenderer: public RendererBase { + public: + LightRenderer(RenderBackend* renderbackend, int position, ImagePool* imagepool, AnimationPool* animpool); + ~LightRenderer(); + std::string getName(); + static LightRenderer* getInstance(IRendererContainer* cnt); + void addImage(const std::string &group, LightRendererNode n, int image, int src=-1, int dst=-1); + void addAnimation(const std::string &group, LightRendererNode n, int animation, int src=-1, int dst=-1); + void addSimpleLight(const std::string &group, LightRendererNode n, uint8_t intensity, float radius, int subdivisions, float xstretch, float ystretch, uint8_t r, uint8_t g, uint8_t b, int src=-1, int dst=-1); + void resizeImage(const std::string &group, LightRendererNode n, int image, int width, int height, int src=-1, int dst=-1); + void addStencilTest(const std::string &group, uint8_t stencil_ref=0, float alpha_ref=0.0); + void removeStencilTest(const std::string &group); + std::list getGroups(); + std::vector getLightInfo(const std::string &group); + void removeAll(const std::string &group); + }; +} + +namespace std { + %template(LightRendererElementInfoVector) vector; +} \ No newline at end of file diff -r b0733d998d0f -r e3140f01749d engine/core/view/renderers/quadtreerenderer.cpp --- a/engine/core/view/renderers/quadtreerenderer.cpp Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/core/view/renderers/quadtreerenderer.cpp Fri Nov 05 15:21:10 2010 +0000 @@ -90,10 +90,12 @@ emc= cg->toMapCoordinates(ExactModelCoordinate( x+size,y+size) ); ScreenPoint scrpt4 =m_camera->toScreenCoordinates( emc ); + m_renderbackend->disableLighting(); m_renderbackend->drawLine( Point(scrpt1.x,scrpt1.y) , Point(scrpt2.x,scrpt2.y), 255, 255, 255); m_renderbackend->drawLine(Point(scrpt1.x,scrpt1.y), Point(scrpt3.x,scrpt3.y), 255, 255, 255); m_renderbackend->drawLine(Point(scrpt3.x,scrpt3.y), Point(scrpt4.x,scrpt4.y), 255, 255, 255); m_renderbackend->drawLine(Point(scrpt2.x,scrpt2.y), Point(scrpt4.x,scrpt4.y), 255, 255, 255); + m_renderbackend->enableLighting(); return true; } diff -r b0733d998d0f -r e3140f01749d engine/core/view/visual.h --- a/engine/core/view/visual.h Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/core/view/visual.h Fri Nov 05 15:21:10 2010 +0000 @@ -127,6 +127,7 @@ type_angle2id m_angle2img; }; + /** Instance visual contains data that is needed to visualize the instance on screen */ class InstanceVisual: public Visual2DGfx { diff -r b0733d998d0f -r e3140f01749d engine/python/fife/extensions/basicapplication.py --- a/engine/python/fife/extensions/basicapplication.py Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/python/fife/extensions/basicapplication.py Fri Nov 05 15:21:10 2010 +0000 @@ -113,6 +113,7 @@ engineSetting.setRenderBackend(self._setting.get("FIFE", "RenderBackend", "OpenGL")) engineSetting.setFullScreen(self._setting.get("FIFE", "FullScreen", False)) engineSetting.setVideoDriver(self._setting.get("FIFE", "VideoDriver", "")) + engineSetting.setLightingModel(self._setting.get("FIFE", "Lighting", 0)) try: engineSetting.setColorKeyEnabled(self._setting.get("FIFE", "ColorKeyEnabled", False)) diff -r b0733d998d0f -r e3140f01749d engine/python/fife/extensions/fife_settings.py --- a/engine/python/fife/extensions/fife_settings.py Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/python/fife/extensions/fife_settings.py Fri Nov 05 15:21:10 2010 +0000 @@ -44,10 +44,12 @@ + @@ -140,6 +142,7 @@ #default settings self._resolutions = ['640x480', '800x600', '1024x768', '1280x800', '1440x900'] self._renderbackends = ['OpenGL', 'SDL'] + self._lightingmodels = [0, 1, 2] #Used to stylize the options gui self._gui_style = "default" @@ -168,6 +171,8 @@ requiresrestart=True) self.createAndAddEntry(FIFE_MODULE, "RenderBackend", "render_backend", initialdata = self._renderbackends, requiresrestart=True) + self.createAndAddEntry(FIFE_MODULE, "Lighting", "lighting_model", initialdata = self._lightingmodels, + requiresrestart=True) def createAndAddEntry(self, module, name, widgetname, applyfunction=None, initialdata=None, requiresrestart=False): """" diff -r b0733d998d0f -r e3140f01749d engine/python/fife/extensions/loaders.py --- a/engine/python/fife/extensions/loaders.py Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/python/fife/extensions/loaders.py Fri Nov 05 15:21:10 2010 +0000 @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- - # #################################################################### -# Copyright (C) 2005-2009 by the FIFE team +# Copyright (C) 2005-2010 by the FIFE team # http://www.fifengine.de # This file is part of FIFE. # @@ -21,113 +20,44 @@ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # #################################################################### -# Loader interface for FIFE's native xml format. +""" Loader interface for FIFE's native xml format """ import os.path from fife import fife - from fife.extensions.serializers.xmlmap import XMLMapLoader -from fife.extensions.serializers import WrongFileType, NameClash -from fife.extensions.serializers.xmlobject import XMLObjectLoader - -objectFileMapping = { 'xml' : XMLObjectLoader } mapFileMapping = { 'xml' : XMLMapLoader} fileExtensions = ('xml',) mapFileExtensions = ('xml',) -def loadMapFile(path, engine, callback=None, debug=True): +def loadMapFile(path, engine, callback=None, debug=True, extensions={}): """ load map file and get (an optional) callback if major stuff is done: - - map creation - - parsed imports - - parsed layers - - parsed cameras - the callback will send both a string and a float (which shows - the overall process), callback(string, float) - + + - map creation + - parsed imports + - parsed layers + - parsed cameras + + the callback will send both a string and a float (which shows + the overall process), callback(string, float) + @type engine: object @param engine: FIFE engine instance @type callback: function @param callback: callback for maploading progress @type debug: bool @param debug: flag to activate / deactivate print statements - + @type map: object @return map: FIFE map object """ (filename, extension) = os.path.splitext(path) - map_loader = mapFileMapping[extension[1:]](engine, callback, debug) + map_loader = mapFileMapping[extension[1:]](engine, callback, debug, extensions) map = map_loader.loadResource(fife.ResourceLocation(path)) if debug: print "--- Loading map took: ", map_loader.time_to_load, " seconds." return map - -def loadImportFile(path, engine, debug=False): - """ uses XMLObjectLoader to load import files from path - - @type path: string - @param path: path to import file - @type engine: object - @param engine: FIFE engine instance - @type debug: bool - @param debug: flag to activate / deactivate print statements - """ - (filename, extension) = os.path.splitext(path) - object_loader = objectFileMapping[extension[1:]](engine.getImagePool(), engine.getAnimationPool(), engine.getModel(), engine.getVFS()) - res = None - try: - res = object_loader.loadResource(fife.ResourceLocation(path)) - if debug: print 'imported object file ' + path - except WrongFileType: - pass -# print 'ignored non-object file ' + path - except NameClash: - pass -# print 'ignored already loaded file ' + path - return res - -def loadImportDir(path, engine, debug=False): - """ helper function to call loadImportFile on a directory - - @type path: string - @param path: path to import directory - @type engine: object - @param engine: FIFE engine instance - @type debug: bool - @param debug: flag to activate / deactivate print statements - """ - for file in filter(lambda f: f.split('.')[-1] == 'xml', engine.getVFS().listFiles(path)): - loadImportFile('/'.join([path, file]), engine, debug) - -def loadImportDirRec(path, engine, debug=False): - """ helper function to call loadImportFile recursive on a directory - - @type path: string - @param path: path to import directory - @type engine: object - @param engine: FIFE engine instance - @type debug: bool - @param debug: flag to activate / deactivate print statements - """ - loadImportDir(path, engine, debug) - - for dir in filter(lambda d: not d.startswith('.'), engine.getVFS().listDirectories(path)): - loadImportDirRec('/'.join([path, dir]), engine, debug) - - -def addObjectFileLoader(fileExtension, loaderClass): - """Add a new loader for fileextension - @type fileExtension: string - @param fileExtension: The file extension the loader is registered for - @type loaderClass: object - @param loaderClass: A fife.ResourceLoader implementation that loads objects - from files with the given fileExtension - """ - objectFileMapping[fileExtension] = loaderClass - _updateFileExtenions() - - def addMapLoader(fileExtension, loaderClass): """Add a new loader for fileextension @type fileExtension: string @@ -139,8 +69,5 @@ mapFileMapping[fileExtension] = loaderClass _updateMapFileExtensions() -def _updateFileExtensions(): - fileExtensions = set(objectFileMapping.keys()) - def _updateMapFileExtensions(): mapFileExtensions = set(mapFileMapping.keys()) \ No newline at end of file diff -r b0733d998d0f -r e3140f01749d engine/python/fife/extensions/savers.py --- a/engine/python/fife/extensions/savers.py Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/python/fife/extensions/savers.py Fri Nov 05 15:21:10 2010 +0000 @@ -174,6 +174,7 @@ attrs = AttributesNSImpl(attr_vals, attr_names) self.startElement('layer', attrs) self.write_instances(layer) + self.write_lights(layer) self.endElement('layer') def write_instances(self, layer): @@ -222,6 +223,102 @@ self.endElement('instances') + def write_lights(self, layer): + attrs = AttributesNSImpl({}, {}) + self.startElement('lights', attrs) + + cameras = layer.getMap().getCameras() + for cam in cameras: + hit = False + layers = cam.getRenderer("LightRenderer").getActiveLayers(); + for lay in layers: + if lay.getId() == layer.getId(): + hit = True + + if hit == False: continue + + renderer = fife.LightRenderer.getInstance(cam) + groups = renderer.getGroups() + for group in groups: + infos = renderer.getLightInfo(group) + for info in infos: + attr_vals = {} + attr_names = {} + type = info.getName() + attr_vals[(None, 'group')] = str(group) + attr_names[(None, 'group')] = 'group' + attr_vals[(None, 'type')] = str(type) + attr_names[(None, 'type')] = 'type' + attr_vals[(None, 'instance')] = str(info.getNode().getInstance().getId()) + attr_names[(None, 'instance')] = 'instance' + if info.getSrcBlend() > -1: + attr_vals[(None, 'src')] = str(info.getSrcBlend()) + attr_names[(None, 'src')] = 'src' + if info.getDstBlend() > -1: + attr_vals[(None, 'dst')] = str(info.getDstBlend()) + attr_names[(None, 'dst')] = 'dst' + if info.getStencil() > -1: + attr_vals[(None, 's_ref')] = str(info.getStencil()) + attr_names[(None, 's_ref')] = 's_ref' + attr_vals[(None, 'a_ref')] = str(info.getAlpha()) + attr_names[(None, 'a_ref')] = 'a_ref' + + if type == 'simple': + if info.getRadius() > 0: + attr_vals[(None, 'radius')] = str(info.getRadius()) + attr_names[(None, 'radius')] = 'radius' + if info.getColor(): + color = info.getColor() + attr_vals[(None, 'color')] = '%d,%d,%d' % (color[0], color[1], color[2]) + attr_vals[(None, 'intensity')] = str(color[3]) + attr_names[(None, 'color')] = 'color' + attr_names[(None, 'intensity')] = 'intensity' + + if info.getSubdivisions() is not 32: + attr_vals[(None, 'subdivisions')] = str(info.getSubdivisions()) + attr_names[(None, 'subdivisions')] = 'subdivisions' + if info.getXStretch() > 1.001 or info.getXStretch() < 0.999: + attr_vals[(None, 'xstretch')] = str(info.getXStretch()) + attr_names[(None, 'xstretch')] = 'xstretch' + if info.getYStretch() > 1.001 or info.getYStretch() < 0.999: + attr_vals[(None, 'ystretch')] = str(info.getYStretch()) + attr_names[(None, 'ystretch')] = 'ystretch' + + elif type == 'image': + if info.getId() == -1: continue + img = self.pool.getImage(info.getId()); + name = img.getResourceFile() + attr_vals[(None, 'image')] = str('../' + name) + attr_names[(None, 'image')] = 'image' + + elif type == 'animation': + if info.getId() == -1: continue + ani = self.anim_pool.getAnimation(info.getId()); + count = 0 + newstr = '' + image = ani.getFrame(ani.getActionFrame()) + fname = image.getResourceFile() + strings = ([str(s) for s in fname.split('/')]) + leng = len(strings) -1 + while count < leng: + newstr = str(newstr + strings[count] + '/') + count += 1 + + name = str('../' + newstr + 'animation.' + fileExtensions[0]) + attr_vals[(None, 'animation')] = str(name) + attr_names[(None, 'animation')] = 'animation' + + else: + continue + + attrs = AttributesNSImpl(attr_vals, attr_names) + self.file.write(self.indent_level) + self.xmlout.startElementNS((None, 'l'), 'l', attrs) + self.xmlout.endElementNS((None, 'l'), 'l') + self.file.write('\n') + + self.endElement('lights') + # Save the linked camera of a map. def write_camera( self, map ): cameralist = map.getCameras() @@ -256,6 +353,10 @@ attr_names[(None,'viewport')] = 'viewport' attr_vals[(None,'viewport')] = '%d,%d,%d,%d' % (viewport.x, viewport.y, viewport.w, viewport.h) + colors = cam.getLightingColor() + if colors[0] < 1.0 or colors[1] < 1.0 or colors[2] < 1.0 or colors[3] < 1.0: + attr_names[(None,'light_color')] = 'light_color' + attr_vals[(None,'light_color')] = '%f,%f,%f,%f' % (colors[0], colors[1], colors[2], colors[3]) attrs = AttributesNSImpl( attr_vals, attr_names ) self.startElement( 'camera', attrs ); self.endElement( 'camera' ); diff -r b0733d998d0f -r e3140f01749d engine/python/fife/extensions/serializers/__init__.py --- a/engine/python/fife/extensions/serializers/__init__.py Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/python/fife/extensions/serializers/__init__.py Fri Nov 05 15:21:10 2010 +0000 @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- - # #################################################################### -# Copyright (C) 2005-2009 by the FIFE team +# Copyright (C) 2005-2010 by the FIFE team # http://www.fifengine.de # This file is part of FIFE. # @@ -28,7 +27,7 @@ try: import xml.etree.cElementTree as ET -except: +except ImportError: import xml.etree.ElementTree as ET class SerializerError(Exception): @@ -105,3 +104,70 @@ return path return '/'.join(path.split(os.path.sep)) + +def loadImportFile(loader, path, engine, debug=False): + """ uses XMLObjectLoader to load import files from path + + @type path: string + @param path: path to import file + @type debug: bool + @param debug: flag to activate / deactivate print statements + """ + loader.loadResource(fife.ResourceLocation(path)) + if debug: print 'imported object file ' + path + +def loadImportDir(loader, path, engine, debug=False): + """ helper function to call loadImportFile on a directory + + @type path: string + @param path: path to import directory + @type debug: bool + @param debug: flag to activate / deactivate print statements + """ + for _file in filter(lambda f: f.split('.')[-1] == 'xml', engine.getVFS().listFiles(path)): + loadImportFile(loader, '/'.join([path, _file]), engine, debug) + +def loadImportDirRec(loader, path, engine, debug=False): + """ helper function to call loadImportFile recursive on a directory + + @type path: string + @param path: path to import directory + @type debug: bool + @param debug: flag to activate / deactivate print statements + """ + loadImportDir(loader, path, engine, debug) + + for _dir in filter(lambda d: not d.startswith('.'), engine.getVFS().listDirectories(path)): + loadImportDirRec(loader, '/'.join([path, _dir]), engine, debug) + +def root_subfile(masterfile, subfile): + """ + Returns new path for given subfile (path), which is rooted against masterfile + E.g. if masterfile is ./../foo/bar.xml and subfile is ./../foo2/subfoo.xml, + returned path is ../foo2/subfoo.xml + NOTE: masterfile is expected to be *file*, not directory. subfile can be either + """ + s = '/' + + masterfile = norm_path(os.path.abspath(masterfile)) + subfile = norm_path(os.path.abspath(subfile)) + + master_fragments = masterfile.split(s) + sub_fragments = subfile.split(s) + + master_leftovers = [] + sub_leftovers = [] + + for i in xrange(len(master_fragments)): + try: + if master_fragments[i] == sub_fragments[i]: + master_leftovers = master_fragments[i+1:] + sub_leftovers = sub_fragments[i+1:] + except IndexError: + break + + pathstr = '' + for f in master_leftovers[:-1]: + pathstr += '..' + s + pathstr += s.join(sub_leftovers) + return pathstr diff -r b0733d998d0f -r e3140f01749d engine/python/fife/extensions/serializers/xml_loader_tools.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/engine/python/fife/extensions/serializers/xml_loader_tools.py Fri Nov 05 15:21:10 2010 +0000 @@ -0,0 +1,144 @@ +# -*- coding: utf-8 -*- +# #################################################################### +# Copyright (C) 2005-2010 by the FIFE team +# http://www.fifengine.de +# This file is part of FIFE. +# +# FIFE is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +# #################################################################### + +""" utilities for xml maploading process """ + +import sys, os + +from fife import fife +import math + +def loadImportFile(loader, path, engine, debug=False): + """ uses XMLObjectLoader to load import files from path + + @type path: string + @param path: path to import file + @type debug: bool + @param debug: flag to activate / deactivate print statements + """ + loader.loadResource(fife.ResourceLocation(path)) + if debug: print 'imported object file ' + path + +def loadImportDir(loader, path, engine, debug=False): + """ helper function to call loadImportFile on a directory + + @type path: string + @param path: path to import directory + @type debug: bool + @param debug: flag to activate / deactivate print statements + """ + for _file in filter(lambda f: f.split('.')[-1] == 'xml', engine.getVFS().listFiles(path)): + loadImportFile(loader, '/'.join([path, _file]), engine, debug) + +def loadImportDirRec(loader, path, engine, debug=False): + """ helper function to call loadImportFile recursive on a directory + + @type path: string + @param path: path to import directory + @type debug: bool + @param debug: flag to activate / deactivate print statements + """ + loadImportDir(loader, path, engine, debug) + + for _dir in filter(lambda d: not d.startswith('.'), engine.getVFS().listDirectories(path)): + loadImportDirRec(loader, '/'.join([path, _dir]), engine, debug) + +def root_subfile(masterfile, subfile): + """ + Returns new path for given subfile (path), which is rooted against masterfile + E.g. if masterfile is ./../foo/bar.xml and subfile is ./../foo2/subfoo.xml, + returned path is ../foo2/subfoo.xml + NOTE: masterfile is expected to be *file*, not directory. subfile can be either + """ + s = '/' + + masterfile = norm_path(os.path.abspath(masterfile)) + subfile = norm_path(os.path.abspath(subfile)) + + master_fragments = masterfile.split(s) + sub_fragments = subfile.split(s) + + master_leftovers = [] + sub_leftovers = [] + + for i in xrange(len(master_fragments)): + try: + if master_fragments[i] == sub_fragments[i]: + master_leftovers = master_fragments[i+1:] + sub_leftovers = sub_fragments[i+1:] + except IndexError: + break + + pathstr = '' + for f in master_leftovers[:-1]: + pathstr += '..' + s + pathstr += s.join(sub_leftovers) + return pathstr + +def reverse_root_subfile(masterfile, subfile): + """ + does inverse operation to root_subfile. E.g. + E.g. if masterfile is ./../foo/bar.xml and subfile is ../foo2/subfoo.xml, + returned path ./../foo2/subfoo.xml + Usually this function is used to convert saved paths into engine relative paths + NOTE: masterfile is expected to be *file*, not directory. subfile can be either + """ + s = '/' + + masterfile = norm_path(os.path.abspath(masterfile)).split(s)[:-1] + subfile = norm_path(os.path.abspath( s.join(masterfile) + s + subfile )) + masterfile = norm_path(os.getcwd()) + s + 'foo.bar' # cheat a little to satisfy root_subfile + return root_subfile(masterfile, subfile) + +def norm_path(path): + """ + Makes the path use '/' delimited separators. FIFE always uses these delimiters, but some os-related + routines will default to os.path.sep. + """ + if os.path.sep == '/': + return path + + return '/'.join(path.split(os.path.sep)) + + +def frange(limit1, limit2 = None, increment = 1.): + """ source: + http://code.activestate.com/recipes/66472-frange-a-range-function-with-float-increments/ + + Range function that accepts floats (and integers). + + Usage: + frange(-2, 2, 0.1) + frange(10) + frange(10, increment = 0.5) + + The returned value is an iterator. Use list(frange) for a list. + """ + + if limit2 is None: + limit2, limit1 = limit1, 0. + else: + limit1 = float(limit1) + + count = int(math.ceil(limit2 - limit1)/increment) + return (limit1 + n*increment for n in range(count)) + diff -r b0733d998d0f -r e3140f01749d engine/python/fife/extensions/serializers/xmlanimation.py --- a/engine/python/fife/extensions/serializers/xmlanimation.py Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/python/fife/extensions/serializers/xmlanimation.py Fri Nov 05 15:21:10 2010 +0000 @@ -22,7 +22,7 @@ # #################################################################### from fife import fife -from fife.extensions.serializers import * +from fife.extensions.serializers import ET class XMLAnimationLoader(fife.ResourceLoader): def __init__(self, imagepool, vfs): diff -r b0733d998d0f -r e3140f01749d engine/python/fife/extensions/serializers/xmlmap.py --- a/engine/python/fife/extensions/serializers/xmlmap.py Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/python/fife/extensions/serializers/xmlmap.py Fri Nov 05 15:21:10 2010 +0000 @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- - # #################################################################### -# Copyright (C) 2005-2009 by the FIFE team +# Copyright (C) 2005-2010 by the FIFE team # http://www.fifengine.de # This file is part of FIFE. # @@ -21,33 +20,43 @@ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # #################################################################### -from fife import fife -try: - import xml.etree.cElementTree as ET -except: - import xml.etree.ElementTree as ET - -from fife.extensions.serializers import * +""" main xml parser class for xml map loading """ import time +from fife import fife + +from fife.extensions.serializers import ET +from fife.extensions.serializers import SerializerError, InvalidFormat +from fife.extensions.serializers import NameClash, NotFound, WrongFileType + +from fife.extensions.serializers.xmlobject import XMLObjectLoader +from fife.extensions.serializers.xmlanimation import XMLAnimationLoader +from fife.extensions.serializers.xml_loader_tools import loadImportFile, loadImportDir +from fife.extensions.serializers.xml_loader_tools import loadImportDirRec +from fife.extensions.serializers.xml_loader_tools import root_subfile, reverse_root_subfile + + FORMAT = '1.0' class XMLMapLoader(fife.ResourceLoader): - def __init__(self, engine, callback, debug): - """ The XMLMapLoader parses the xml map using several section. - Each section fires a callback (if given) which can e. g. be - used to show a progress bar. - - The callback sends two values, a string and a float (which shows - the overall process): callback(string, float) - + """ The B{XMLMapLoader} parses the xml map using several section. + Each section fires a callback (if given) which can e. g. be + used to show a progress bar. + + The callback sends two values, a string and a float (which shows + the overall process): callback(string, float) + """ + def __init__(self, engine, callback, debug, extensions): + """ @type engine: object @param engine: a pointer to fife.engine @type callback: function @param callback: a callback with two arguments, optional @type debug: bool @param debug: flag to activate / deactivate print statements + @type extensions: dict + @param extensions: information package which extension should be activated (lights, sounds) """ fife.ResourceLoader.__init__(self) self.thisown = 0 @@ -60,16 +69,45 @@ self.model = self.engine.getModel() self.pool = self.engine.getImagePool() self.anim_pool = self.engine.getAnimationPool() + + self.obj_loader = XMLObjectLoader( + engine.getImagePool(), + engine.getAnimationPool(), + engine.getModel(), + engine.getVFS() + ) + self.map = None self.source = None self.time_to_load = 0 self.nspace = None + + self.msg = {} + self.msg['map'] = 'created map' + self.msg['imports'] = 'loaded imports' + self.msg['layer'] = 'loaded layer: %s' + self.msg['camera'] = 'loaded camera: %s' + + if 'sound' not in extensions: + extensions['sound'] = False + if 'lights' not in extensions: + extensions['lights'] = False + + self.light_data = {} + self.extensions = extensions def _err(self, msg): raise SyntaxError(''.join(['File: ', self.source, ' . ', msg])) def loadResource(self, location): + """ overwrite of B{fife.ResourceLoader} + + @type location: object + @param location: path to a map file as a fife.ResourceLocation + @type map: object + @return map: FIFE map object + """ start_time = time.time() self.source = location.getFilename() f = self.vfs.open(self.source) @@ -82,80 +120,108 @@ return map def parse_map(self, mapelt): + """ start parsing the xml structure and + call submethods for turning found tags + into FIFE objects and create the map + + @type mapelt: object + @param mapelt: ElementTree root + @type map: object + @return map: FIFE map object + """ if not mapelt: self._err('No element found at top level of map file definition.') - id,format = mapelt.get('id'),mapelt.get('format') + _id, format = mapelt.get('id'), mapelt.get('format') if not format == FORMAT: self._err(''.join(['This file has format ', format, ' but this loader has format ', FORMAT])) - if not id: self._err('Map declared without an identifier.') + if not _id: self._err('Map declared without an identifier.') map = None try: - self.map = self.model.createMap(str(id)) + self.map = self.model.createMap(str(_id)) self.map.setResourceFile(self.source) except fife.Exception, e: # NameClash appears as general fife.Exception; any ideas? print e.getMessage() - print ''.join(['File: ', self.source, '. The map ', str(id), ' already exists! Ignoring map definition.']) - return None + print ''.join(['File: ', self.source, '. The map ', str(_id), ' already exists! Ignoring map definition.']) + return map # xml-specific directory imports. This is used by xml savers. self.map.importDirs = [] if self.callback is not None: - self.callback('created map', float(0.25) ) + self.callback(self.msg['map'], float(0.25) ) self.parse_imports(mapelt, self.map) + self.parse_layers(mapelt, self.map) + self.parse_cameras(mapelt, self.map) - self.parse_layers(mapelt, self.map) - - self.parse_cameras(mapelt, self.map) + # create light nodes + if self.light_data: + self.create_light_nodes(self.map) return self.map def parse_imports(self, mapelt, map): + """ load all objects defined as import into memory + + @type mapelt: object + @param mapelt: ElementTree root + @type map: object + @map map: FIFE map object + """ parsedImports = {} - from fife.extensions import loaders + if self.callback: tmplist = mapelt.findall('import') i = float(0) for item in mapelt.findall('import'): - file = item.get('file') - if file: - file = reverse_root_subfile(self.source, file) - dir = item.get('dir') - if dir: - dir = reverse_root_subfile(self.source, dir) - + _file = item.get('file') + if _file: + _file = reverse_root_subfile(self.source, _file) + _dir = item.get('dir') + if _dir: + _dir = reverse_root_subfile(self.source, _dir) + # Don't parse duplicate imports - if (dir,file) in parsedImports: - if self.debug: print "Duplicate import:" ,(dir,file) + if (_dir,_file) in parsedImports: + if self.debug: print "Duplicate import:" ,(_dir, _file) continue - parsedImports[(dir,file)] = 1 + parsedImports[(_dir,_file)] = 1 - if file and dir: - loaders.loadImportFile('/'.join(dir, file), self.engine, self.debug) - elif file: - loaders.loadImportFile(file, self.engine, self.debug) - elif dir: - loaders.loadImportDirRec(dir, self.engine, self.debug) - map.importDirs.append(dir) + if _file and _dir: + loadImportFile(self.obj_loader, '/'.join(_dir, _file), self.engine, self.debug) + elif _file: + loadImportFile(self.obj_loader, _file, self.engine, self.debug) + elif _dir: + loadImportDirRec(self.obj_loader, _dir, self.engine, self.debug) + map.importDirs.append(_dir) else: if self.debug: print 'Empty import statement?' if self.callback: i += 1 - self.callback('loaded imports', float( i / float(len(tmplist)) * 0.25 + 0.25 ) ) - + self.callback(self.msg['imports'], float( i / float(len(tmplist)) * 0.25 + 0.25 ) ) def parse_layers(self, mapelt, map): + """ create all layers and their instances + + @type mapelt: object + @param mapelt: ElementTree root + @type map: object + @map map: FIFE map object + """ if self.callback is not None: tmplist = mapelt.findall('layer') i = float(0) for layer in mapelt.findall('layer'): - id = layer.get('id') + _id = layer.get('id') grid_type = layer.get('grid_type') + + if not _id: self._err(' declared with no id attribute.') + if not grid_type: self._err(''.join(['Layer ', str(_id), ' has no grid_type attribute.'])) + x_scale = layer.get('x_scale') y_scale = layer.get('y_scale') rotation = layer.get('rotation') @@ -175,9 +241,6 @@ else: transparency = int(transparency) - if not id: self._err(' declared with no id attribute.') - if not grid_type: self._err(''.join(['Layer ', str(id), ' has no grid_type attribute.'])) - cellgrid = self.model.getCellGrid(grid_type) if not cellgrid: self._err(' declared with invalid cellgrid type. (%s)' % grid_type) @@ -189,10 +252,10 @@ layer_obj = None try: - layer_obj = map.createLayer(str(id), cellgrid) + layer_obj = map.createLayer(str(_id), cellgrid) except fife.Exception, e: print e.getMessage() - print 'The layer ' + str(id) + ' already exists! Ignoring this layer.' + print 'The layer ' + str(_id) + ' already exists! Ignoring this layer.' continue strgy = fife.CELL_EDGES_ONLY @@ -200,86 +263,240 @@ strgy = fife.CELL_EDGES_AND_DIAGONALS if pathing == "freeform": strgy = fife.FREEFORM + layer_obj.setPathingStrategy(strgy) - layer_obj.setLayerTransparency(transparency) self.parse_instances(layer, layer_obj) + + if self.extensions['lights']: + self.parse_lights(layer, layer_obj) + if self.extensions['sound']: + self.parse_sounds(layer, layer_obj) if self.callback is not None: i += 1 - self.callback('loaded layer :' + str(id), float( i / float(len(tmplist)) * 0.25 + 0.5 ) ) + self.callback(self.msg['layer'] % str(_id), float( i / float(len(tmplist)) * 0.25 + 0.5 ) ) # cleanup if self.callback is not None: del tmplist del i + def parse_lights(self, layerelt, layer): + """ create light nodes + + @type layerelt: object + @param layerelt: ElementTree layer branch + @type layer: object + @map layer: FIFE layer object + """ + _LIGHT_DEFAULT_BLENDING_SRC = -1 + _LIGHT_DEFAULT_BLENDING_DST = -1 + _LIGHT_DEFAULT_SUBDIVISIONS = 32 + _LIGHT_DEFAULT_CAM_ID = 'default' + _LIGHT_DEFAULT_INTENSITY = 128 + _LIGHT_DEFAULT_RADIUS = 10.0 + + print "Processing lights ... " + lightelt = layerelt.find('lights') + if not lightelt: + print "\tno lights found on layer %s" % layer.getId() + return + + lights = [] + for attr in ('l', 'light', 'lgt'): + lights.extend(lightelt.findall(attr)) + + for light in lights: + group = light.get('group') + if not group: + print "Light has no group. Omitting..." + continue + + blending_src = light.get('src') + if not blending_src: + blending_src = _LIGHT_DEFAULT_BLENDING_SRC + blending_dst = light.get('dst') + if not blending_dst: + blending_dst = _LIGHT_DEFAULT_BLENDING_DST + + _x = light.get('x') + if not _x: _x = 0 + _y = light.get('y') + if not _y: _y = 0 + _z = light.get('y') + if not _z: _z = 0 + + node = {} + node['blending_src'] = int(blending_src) + node['blending_dst'] = int(blending_dst) + node['layer'] = layer.getId() + node['position'] = int(_x), int(_y), int(_z) + + # where is the light? *sing* + instance_id = light.get('instance') + node['instance'] = None + if instance_id and layer.getInstance(instance_id): + node['instance'] = instance_id + + type = light.get('type') + if type: + s_ref = light.get('s_ref') + if not s_ref: s_ref = -1 + node['s_ref'] = int(s_ref) + a_ref = light.get('a_ref') + if not a_ref: a_ref = 0.0 + node['a_ref'] = float(a_ref) + + if type == 'image': + image = light.get('image') + if not image: + print "Light has no image. Omitting..." + continue + node['type'] = 'image' + image = reverse_root_subfile(self.source, image) + img_id = self.pool.addResourceFromFile(image) + node['image'] = int(img_id) + elif type == 'animation': + animation = light.get('animation') + if not animation: + print "Light has no animation. Omitting..." + continue + node['type'] = 'animation' + animation = reverse_root_subfile(self.source, animation) + rloc = fife.ResourceLocation(animation) + ani_id = self.anim_pool.addResourceFromLocation(rloc) + node['animation'] = int(ani_id) + elif type == 'simple': + node['type'] = type + radius = light.get('radius') + if not radius: radius = _LIGHT_DEFAULT_RADIUS + node['radius'] = float(radius) + + subdivisions = light.get('subdivisions') + if not subdivisions: + subdivisions = _LIGHT_DEFAULT_SUBDIVISIONS + node['subdivisions'] = int(subdivisions) + + intensity = light.get('intensity') + if not intensity: + intensity = _LIGHT_DEFAULT_INTENSITY + node['intensity'] = int(intensity) + + xstretch = light.get('xstretch') + if not xstretch: xstretch = 1.0 + ystretch = light.get('ystretch') + if not ystretch: ystretch = 1.0 + node['stretch'] = float(xstretch), float(ystretch) + + color = light.get('color') + if not color: color = '%d,%d,%d' % (255, 255, 255) + node['color'] = ([int(c) for c in color.split(',')]) + + else: + continue + + cam_id = light.get('camera_id') + if not cam_id: cam_id = _LIGHT_DEFAULT_CAM_ID + + if not cam_id in self.light_data: + self.light_data[cam_id] = {} + if group not in self.light_data[cam_id]: + self.light_data[cam_id][group] = [] + + self.light_data[cam_id][group].append(node) + + for camera, groups in self.light_data.iteritems(): + print "Lights for camera %s" % camera + for group, lights in groups.iteritems(): + print group, lights + + def parse_sounds(self, layerelt, layer): + """ create sound emitter + + FIXME: + - FIFE has a hard limit of sound emitters + how should we load emitters here? + - my first thought: collect a list of sound + files & data for emitter creation, + then let the client decide what to do with it + + @type layerelt: object + @param layerelt: ElementTree layer branch + @type layer: object + @map layer: FIFE layer object + """ + # to be continued + pass + def parse_instances(self, layerelt, layer): + """ create all layers and their instances + + @type layerelt: object + @param layerelt: ElementTree layer branch + @type layer: object + @map layer: FIFE layer object + """ instelt = layerelt.find('instances') - instances = instelt.findall('i') - instances.extend(instelt.findall('inst')) - instances.extend(instelt.findall('instance')) + instances = [] + for attr in ('i', 'inst', 'instance'): + instances.extend(instelt.findall(attr)) + for instance in instances: - - objectID = instance.get('object') - if not objectID: - objectID = instance.get('obj') - if not objectID: - objectID = instance.get('o') - - if not objectID: self._err(' does not specify an object attribute.') - - nspace = instance.get('namespace') - if not nspace: - nspace = instance.get('ns') - if not nspace: + _id = instance.get('id') + # check for istance id name clashes + if _id: + if bool(layer.getInstance(_id)): + print "Instance with id=%s, already exists. Omitting..." % _id + continue + _id = str(_id) + else: + _id = '' + + objectID = '' + for attr in ('o', 'object', 'obj'): + objectID = instance.get(attr) + if objectID: break + if not objectID: self._err(' %s does not specify an object attribute.' % str(objectID)) + objectID = str(objectID) + + nspace = '' + for attr in ('namespace', 'ns'): + nspace = instance.get(attr) + if nspace: break + # try to reuse the previous namespace + if not nspace and self.nspace: nspace = self.nspace - - if not nspace: self._err(' %s does not specify an object namespace, and no default is available.' % str(objectID)) - + if not nspace and not self.nspace: self._err(' %s does not specify an object namespace, and no default is available.' % str(objectID)) + nspace = str(nspace) self.nspace = nspace - object = self.model.getObject(str(objectID), str(nspace)) + # check if there is an object for this instance available, if not -> skip this one + object = self.model.getObject(objectID, nspace) if not object: - print ''.join(['Object with id=', str(objectID), ' ns=', str(nspace), ' could not be found. Omitting...']) + print "Object with id=%s, ns=%s could not be found. Omitting..." % (objectID, nspace) continue x = instance.get('x') - y = instance.get('y') - z = instance.get('z') - stackpos = instance.get('stackpos') - id = instance.get('id') + if x: self.x = x = float(x) + else: x = self.x - if x: - x = float(x) - self.x = x - else: - self.x = self.x + 1 - x = self.x + y = instance.get('y') + if y: self.y = y = float(y) + else: y = self.y - if y: - y = float(y) - self.y = y - else: - y = self.y - - if z: - z = float(z) - else: - z = 0.0 + z = instance.get('z') + if z: z = float(z) + else: z = 0.0 - if not id: - id = '' - else: - id = str(id) + inst = layer.createInstance(object, fife.ExactModelCoordinate(x,y,z), _id) - inst = layer.createInstance(object, fife.ExactModelCoordinate(x,y,z), str(id)) - - rotation = instance.get('r') - if not rotation: - rotation = instance.get('rotation') + rotation = 0 + for attr in ('r', 'rotation'): + rotation = instance.get(attr) + if rotation: break if not rotation: angles = object.get2dGfxVisual().getStaticImageAngles() if angles: @@ -291,7 +508,9 @@ inst.setRotation(rotation) fife.InstanceVisual.create(inst) - if (stackpos): + + stackpos = instance.get('stackpos') + if stackpos: inst.get2dGfxVisual().setStackPosition(int(stackpos)) if (object.getAction('default')): @@ -299,12 +518,24 @@ inst.act('default', target, True) def parse_cameras(self, mapelt, map): + """ create all cameras and activate them + + FIXME: + - should the cameras really be enabled here? + IMO that's part of the setup within a client + (we just _load_ things here) + + @type mapelt: object + @param mapelt: ElementTree root + @type map: object + @map map: FIFE map object + """ if self.callback: tmplist = mapelt.findall('camera') i = float(0) for camera in mapelt.findall('camera'): - id = camera.get('id') + _id = camera.get('id') zoom = camera.get('zoom') tilt = camera.get('tilt') rotation = camera.get('rotation') @@ -312,35 +543,221 @@ ref_cell_width = camera.get('ref_cell_width') ref_cell_height = camera.get('ref_cell_height') viewport = camera.get('viewport') + light_color = camera.get('light_color') if not zoom: zoom = 1 if not tilt: tilt = 0 if not rotation: rotation = 0 - if not id: self._err('Camera declared without an id.') - if not ref_layer_id: self._err(''.join(['Camera ', str(id), ' declared with no reference layer.'])) - if not (ref_cell_width and ref_cell_height): self._err(''.join(['Camera ', str(id), ' declared without reference cell dimensions.'])) + if not _id: self._err('Camera declared without an id.') + if not ref_layer_id: self._err(''.join(['Camera ', str(_id), ' declared with no reference layer.'])) + if not (ref_cell_width and ref_cell_height): self._err(''.join(['Camera ', str(_id), ' declared without reference cell dimensions.'])) try: if viewport: - cam = map.addCamera(str(id), map.getLayer(str(ref_layer_id)),fife.Rect(*[int(c) for c in viewport.split(',')])) + cam = map.addCamera(str(_id), map.getLayer(str(ref_layer_id)),fife.Rect(*[int(c) for c in viewport.split(',')])) else: screen = self.engine.getRenderBackend() - cam = map.addCamera(str(id), map.getLayer(str(ref_layer_id)),fife.Rect(0,0,screen.getScreenWidth(),screen.getScreenHeight())) - - cam.setCellImageDimensions(int(ref_cell_width), int(ref_cell_height)) - cam.setRotation(float(rotation)) - cam.setTilt(float(tilt)) - cam.setZoom(float(zoom)) + cam = map.addCamera(str(_id), map.getLayer(str(ref_layer_id)),fife.Rect(0,0,screen.getScreenWidth(),screen.getScreenHeight())) renderer = fife.InstanceRenderer.getInstance(cam) renderer.activateAllLayers(map) except fife.Exception, e: print e.getMessage() + + if light_color: cam.setLightingColor(*[float(c) for c in light_color.split(',')]) + cam.setCellImageDimensions(int(ref_cell_width), int(ref_cell_height)) + cam.setRotation(float(rotation)) + cam.setTilt(float(tilt)) + cam.setZoom(float(zoom)) + + renderer = fife.InstanceRenderer.getInstance(cam) + renderer.activateAllLayers(map) if self.callback: i += 1 - self.callback('loaded camera: ' + str(id), float( i / len(tmplist) * 0.25 + 0.75 ) ) + self.callback(self.msg['camera'] % str(_id), float( i / len(tmplist) * 0.25 + 0.75 ) ) + + def create_light_nodes(self, map): + """ loop through all preloaded lights and create them + according to their data + + @type map: object + @param map: FIFE map object + """ + cameras = [i.getId() for i in map.getCameras()] + renderers = {} + default_cam = map.getCameras()[0].getId() + + def add_simple_light(group, renderer, node, data): + """ add a node as simple light to the renderer + + @type group: string + @param group: name of the light group + @type renderer: object + @param renderer: fife.LightRenderer instance + @type node: object + @param node: fife.LightRendererNode instance + @type data: dict + @param data: all data for the light type creation + """ + if not node: return + if not group: return + renderer.addSimpleLight( + group, + node, + data['intensity'], + data['radius'], + data['subdivisions'], + data['stretch'][0], + data['stretch'][1], + data['color'][0], + data['color'][1], + data['color'][2], + data['blending_src'], + data['blending_dst'], + ) + if data['s_ref'] is not -1: + add_stencil_test(group, renderer, data) + def add_animated_lightmap(group, renderer, node, data): + """ add a node as animated lightmap to the renderer + + @type group: string + @param group: name of the light group + @type renderer: object + @param renderer: fife.LightRenderer instance + @type node: object + @param node: fife.LightRendererNode instance + @type data: dict + @param data: all data for the light type creation + """ + if not node: return + if not group: return + renderer.addAnimation( + group, + node, + data['animation'], + data['blending_src'], + data['blending_dst'], + ) + if data['s_ref'] is not -1: + add_stencil_test(group, renderer, data) + def add_lightmap(group, renderer, node, data): + """ add a node as lightmap to the renderer + + @type group: string + @param group: name of the light group + @type renderer: object + @param renderer: fife.LightRenderer instance + @type node: object + @param node: fife.LightRendererNode instance + @type data: dict + @param data: all data for the light type creation + """ + if not node: return + if not group: return + renderer.addImage( + group, + node, + data['image'], + data['blending_src'], + data['blending_dst'], + ) + if data['s_ref'] is not -1: + add_stencil_test(group, renderer, data) + def add_stencil_test(group, renderer, data): + """ add a stencil test to a group + + @type group: string + @param group: name of the light group + @type renderer: object + @param renderer: fife.LightRenderer instance + @type data: dict + @param data: all data for the light type creation + """ + if not group: return + renderer.addStencilTest( + group, + data['s_ref'], + data['a_ref'], + ) + + def create_node(instance=None, point=None, layer=None): + """ creates a node of one of these types: + + - attached to an instance + - attached to an instance with offset + - attached to a point + + FIXME: + - add location node + + @type: instance: object + @param instance: fife instance object + @type point: tuple + @param point: x,y,z tuple + @type layer: object + @param layer: fife layer object + """ + node = None + if not layer: return node + + # node at layer coordinates + if point and not instance: + point = fife.Point(point[0], point[1]) + node = fife.LightRendererNode(point); + # node with offset + if instance and point: + node = fife.LightRendererNode(instance, layer, fife.Point(point[0], point[1])) + # node attached to instance + if instance and not point: + node = fife.LightRendererNode(instance, layer) + if node: + node.thisown = 0 + + return node + + def dump_data(): + """ dump all loaded data """ + for camera, groups in self.light_data.iteritems(): + print "Lights for camera %s" % camera + for group, lights in groups.iteritems(): + print group, lights + + # fetch all renderer instances for available cameras + for _id in cameras: + camera = map.getCamera(_id) + renderers[_id] = fife.LightRenderer.getInstance(camera) + + # parse data and create the lights + for camera, groups in self.light_data.iteritems(): + for group, lights in groups.iteritems(): + for light in lights: + instance = None + layer = map.getLayer(light['layer']) + if light['instance']: + instance = layer.getInstance(light['instance']) + position = light['position'] + node = create_node(instance, position, layer) + + # some guards + if not node: continue + + if camera == 'default': + renderer = renderers[default_cam] + else: + renderer = renderers[camera] + + if light['type'] == 'simple': + add_simple_light(group, renderer, node, light) + elif light['type'] == 'image': + add_lightmap(group, renderer, node, light) + elif light['type'] == 'animation': + add_animated_lightmap(group, renderer, node, light) + +# dump_data() + + diff -r b0733d998d0f -r e3140f01749d engine/python/fife/extensions/serializers/xmlobject.py --- a/engine/python/fife/extensions/serializers/xmlobject.py Wed Nov 03 13:44:12 2010 +0000 +++ b/engine/python/fife/extensions/serializers/xmlobject.py Fri Nov 05 15:21:10 2010 +0000 @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- - # #################################################################### -# Copyright (C) 2005-2009 by the FIFE team +# Copyright (C) 2005-2010 by the FIFE team # http://www.fifengine.de # This file is part of FIFE. # @@ -21,17 +20,34 @@ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # #################################################################### +""" submodule for xml map parsing """ + from fife import fife -from fife.extensions.serializers import * -from fife.extensions.fife_utils import * + +from fife.extensions.serializers import ET +from fife.extensions.serializers import SerializerError, InvalidFormat +from fife.extensions.serializers import NameClash, NotFound, WrongFileType class ObjectLocation(fife.ResourceLocation): + """ + + + """ def __init__(self, file, node=None): + """ + + """ fife.ResourceLocation.__init__(self, file) self.node = node class XMLObjectLoader(fife.ResourceLoader): + """ + + """ def __init__(self, image_pool, anim_pool, model, vfs=None): + """ + + """ self.image_pool = image_pool self.anim_pool = anim_pool self.model = model @@ -40,6 +56,9 @@ self.filename = '' def loadResource(self, location): + """ + + """ self.source = location self.filename = self.source.getFilename() self.node = None @@ -61,26 +80,36 @@ isobjectfile = False if not isobjectfile: + return raise WrongFileType('Tried to open non-object file %s with XMLObjectLoader.' % self.filename) + self.do_load_resource(f) def do_load_resource(self, file): + """ + + """ if file: tree = ET.parse(file) self.node = tree.getroot() self.parse_object(self.node) def parse_object(self, object): + """ + + """ if self.node.tag != 'object': raise InvalidFormat('Expected tag, but found <%s>.' % self.node.tag) - id = object.get('id') - if not id: + _id = object.get('id') + if not _id: raise InvalidFormat(' declared without an id attribute.') + _id = str(_id) nspace = object.get('namespace') if not nspace: - raise InvalidFormat(' %s declared without a namespace attribute.' % str(id)) + raise InvalidFormat(' %s declared without a namespace attribute.' % str(_id)) + nspace = str(nspace) obj = None parent = object.get('parent', None) @@ -92,12 +121,12 @@ raise NameClash('%d objects found with identifier %s.' % (len(query), str(parent))) parent = query[0] - try: - obj = self.model.createObject(str(id), str(nspace), parent) - except RuntimeError, e: - if is_fife_exc(fife.NameClash, e): - raise NameClash('Tried to create already existing object, ignoring') - raise + # check if model already has this object + if not bool(self.model.getObject(_id, nspace)): + obj = self.model.createObject(_id, nspace, parent) + else: + print NameClash('Tried to create already existing object \n\t...ignoring: %s, %s' % (_id, nspace)) + return obj.setResourceLocation(self.source) fife.ObjectVisual.create(obj) @@ -111,6 +140,9 @@ self.parse_actions(object, obj) def parse_images(self, objelt, object): + """ + + """ for image in objelt.findall('image'): source = image.get('source') if not source: @@ -126,9 +158,11 @@ image_location .setYShift(int( image.get('y_offset', 0) )) id = self.image_pool.addResourceFromLocation(image_location) object.get2dGfxVisual().addStaticImage(int( image.get('direction', 0) ), id) - #img = self.image_pool.getImage(id) def parse_actions(self, objelt, object): + """ + + """ for action in objelt.findall('action'): id = action.get('id') if not id: @@ -139,6 +173,9 @@ self.parse_animations(action, act_obj) def parse_animations(self, actelt, action): + """ + + """ for anim in actelt.findall('animation'): source = anim.get('source') if not source: