genericrenderer.cpp

00001 /***************************************************************************
00002  *   Copyright (C) 2005-2011 by the FIFE team                              *
00003  *   http://www.fifengine.de                                               *
00004  *   This file is part of FIFE.                                            *
00005  *                                                                         *
00006  *   FIFE is free software; you can redistribute it and/or                 *
00007  *   modify it under the terms of the GNU Lesser General Public            *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2.1 of the License, or (at your option) any later version.    *
00010  *                                                                         *
00011  *   This library is distributed in the hope that it will be useful,       *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00014  *   Lesser General Public License for more details.                       *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Lesser General Public      *
00017  *   License along with this library; if not, write to the                 *
00018  *   Free Software Foundation, Inc.,                                       *
00019  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
00020  ***************************************************************************/
00021 
00022 // Standard C++ library includes
00023 
00024 // 3rd party library includes
00025 
00026 // FIFE includes
00027 // These includes are split up in two parts, separated by one empty line
00028 // First block: files included from the FIFE root src directory
00029 // Second block: files included from the same folder
00030 #include "video/renderbackend.h"
00031 #include "video/animation.h"
00032 #include "video/fonts/ifont.h"
00033 #include "video/image.h"
00034 #include "video/imagemanager.h"
00035 #include "util/math/fife_math.h"
00036 #include "util/log/logger.h"
00037 #include "util/time/timemanager.h"
00038 #include "model/metamodel/grids/cellgrid.h"
00039 #include "model/metamodel/timeprovider.h"
00040 #include "model/structures/instance.h"
00041 #include "model/structures/layer.h"
00042 #include "model/structures/location.h"
00043 
00044 #include "view/camera.h"
00045 #include "genericrenderer.h"
00046 
00047 
00048 namespace FIFE {
00049     static Logger _log(LM_VIEWVIEW);
00050 
00051     GenericRendererLineInfo::GenericRendererLineInfo(RendererNode n1, RendererNode n2, uint8_t r, uint8_t g, uint8_t b, uint8_t a):
00052         GenericRendererElementInfo(),
00053         m_edge1(n1),
00054         m_edge2(n2),
00055         m_red(r),
00056         m_green(g),
00057         m_blue(b),
00058         m_alpha(a) {
00059     }
00060     void GenericRendererLineInfo::render(Camera* cam, Layer* layer, RenderList& instances, RenderBackend* renderbackend) {
00061         Point p1 = m_edge1.getCalculatedPoint(cam, layer);
00062         Point p2 = m_edge2.getCalculatedPoint(cam, layer);
00063         if(m_edge1.getLayer() == layer) {
00064             renderbackend->drawLine(p1, p2, m_red, m_green, m_blue, m_alpha);
00065         }
00066     }
00067 
00068     GenericRendererPointInfo::GenericRendererPointInfo(RendererNode anchor, uint8_t r, uint8_t g, uint8_t b, uint8_t a):
00069         GenericRendererElementInfo(),
00070         m_anchor(anchor),
00071         m_red(r),
00072         m_green(g),
00073         m_blue(b),
00074         m_alpha(a) {
00075     }
00076     void GenericRendererPointInfo::render(Camera* cam, Layer* layer, RenderList& instances, RenderBackend* renderbackend) {
00077         Point p = m_anchor.getCalculatedPoint(cam, layer);
00078         if(m_anchor.getLayer() == layer) {
00079             renderbackend->putPixel(p.x, p.y, m_red, m_green, m_blue, m_alpha);
00080         }
00081     }
00082 
00083     GenericRendererTriangleInfo::GenericRendererTriangleInfo(RendererNode n1, RendererNode n2, RendererNode n3, uint8_t r, uint8_t g, uint8_t b, uint8_t a):
00084         GenericRendererElementInfo(),
00085         m_edge1(n1),
00086         m_edge2(n2),
00087         m_edge3(n3),
00088         m_red(r),
00089         m_green(g),
00090         m_blue(b),
00091         m_alpha(a) {
00092     }
00093     void GenericRendererTriangleInfo::render(Camera* cam, Layer* layer, RenderList& instances, RenderBackend* renderbackend) {
00094         Point p1 = m_edge1.getCalculatedPoint(cam, layer);
00095         Point p2 = m_edge2.getCalculatedPoint(cam, layer);
00096         Point p3 = m_edge3.getCalculatedPoint(cam, layer);
00097         if(m_edge1.getLayer() == layer) {
00098             renderbackend->drawTriangle(p1, p2, p3, m_red, m_green, m_blue, m_alpha);
00099         }
00100     }
00101 
00102     GenericRendererQuadInfo::GenericRendererQuadInfo(RendererNode n1, RendererNode n2, RendererNode n3, RendererNode n4, uint8_t r, uint8_t g, uint8_t b, uint8_t a):
00103         GenericRendererElementInfo(),
00104         m_edge1(n1),
00105         m_edge2(n2),
00106         m_edge3(n3),
00107         m_edge4(n4),
00108         m_red(r),
00109         m_green(g),
00110         m_blue(b),
00111         m_alpha(a) {
00112     }
00113     void GenericRendererQuadInfo::render(Camera* cam, Layer* layer, RenderList& instances, RenderBackend* renderbackend) {
00114         Point p1 = m_edge1.getCalculatedPoint(cam, layer);
00115         Point p2 = m_edge2.getCalculatedPoint(cam, layer);
00116         Point p3 = m_edge3.getCalculatedPoint(cam, layer);
00117         Point p4 = m_edge4.getCalculatedPoint(cam, layer);
00118         if(m_edge1.getLayer() == layer) {
00119             renderbackend->drawQuad(p1, p2, p3, p4, m_red, m_green, m_blue, m_alpha);
00120         }
00121     }
00122 
00123     GenericRendererVertexInfo::GenericRendererVertexInfo(RendererNode center, int32_t size, uint8_t r, uint8_t g, uint8_t b, uint8_t a):
00124         GenericRendererElementInfo(),
00125         m_center(center),
00126         m_size(size),
00127         m_red(r),
00128         m_green(g),
00129         m_blue(b),
00130         m_alpha(a) {
00131     }
00132     void GenericRendererVertexInfo::render(Camera* cam, Layer* layer, RenderList& instances, RenderBackend* renderbackend) {
00133         Point p = m_center.getCalculatedPoint(cam, layer);
00134         if(m_center.getLayer() == layer) {
00135             renderbackend->drawVertex(p, m_size, m_red, m_green, m_blue, m_alpha);
00136         }
00137     }
00138 
00139     GenericRendererImageInfo::GenericRendererImageInfo(RendererNode anchor, ImagePtr image, bool zoomed):
00140         GenericRendererElementInfo(),
00141         m_anchor(anchor),
00142         m_image(image),
00143         m_zoomed(zoomed) {
00144     }
00145     void GenericRendererImageInfo::render(Camera* cam, Layer* layer, RenderList& instances, RenderBackend* renderbackend) {
00146         Point p = m_anchor.getCalculatedPoint(cam, layer, m_zoomed);
00147         if(m_anchor.getLayer() == layer) {
00148             Rect r;
00149             Rect viewport = cam->getViewPort();
00150             uint32_t width, height;
00151             if(m_zoomed) {
00152                 width = static_cast<uint32_t>(round(m_image->getWidth() * cam->getZoom()));
00153                 height = static_cast<uint32_t>(round(m_image->getHeight() * cam->getZoom()));
00154             }
00155             else {
00156                 width = m_image->getWidth();
00157                 height = m_image->getHeight();
00158             }
00159             r.x = p.x-width/2;
00160             r.y = p.y-height/2;
00161             r.w = width;
00162             r.h = height;
00163             if(r.intersects(viewport)) {
00164                 m_image->render(r);
00165             }
00166         }
00167     }
00168 
00169     GenericRendererAnimationInfo::GenericRendererAnimationInfo(RendererNode anchor, AnimationPtr animation, bool zoomed):
00170         GenericRendererElementInfo(),
00171         m_anchor(anchor),
00172         m_animation(animation),
00173         m_start_time(TimeManager::instance()->getTime()),
00174         m_time_scale(1.0),
00175         m_zoomed(zoomed) {
00176     }
00177     void GenericRendererAnimationInfo::render(Camera* cam, Layer* layer, RenderList& instances, RenderBackend* renderbackend) {
00178         Point p = m_anchor.getCalculatedPoint(cam, layer, m_zoomed);
00179         if(m_anchor.getLayer() == layer) {
00180             int32_t animtime = scaleTime(m_time_scale, TimeManager::instance()->getTime() - m_start_time) % m_animation->getDuration();
00181             ImagePtr img = m_animation->getFrameByTimestamp(animtime);
00182             Rect r;
00183             Rect viewport = cam->getViewPort();
00184             uint32_t width, height;
00185             if(m_zoomed) {
00186                 width = static_cast<uint32_t>(round(img->getWidth() * cam->getZoom()));
00187                 height = static_cast<uint32_t>(round(img->getHeight() * cam->getZoom()));
00188             } else {
00189                 width = img->getWidth();
00190                 height = img->getHeight();
00191             }
00192             r.x = p.x-width/2;
00193             r.y = p.y-height/2;
00194             r.w = width;
00195             r.h = height;
00196             if(r.intersects(viewport)) {
00197                 img->render(r);
00198             }
00199         }
00200     }
00201 
00202     GenericRendererTextInfo::GenericRendererTextInfo(RendererNode anchor, IFont* font, std::string text):
00203         GenericRendererElementInfo(),
00204         m_anchor(anchor),
00205         m_font(font),
00206         m_text(text) {
00207     }
00208     void GenericRendererTextInfo::render(Camera* cam, Layer* layer, RenderList& instances, RenderBackend* renderbackend) {
00209         Point p = m_anchor.getCalculatedPoint(cam, layer);
00210         if(m_anchor.getLayer() == layer) {
00211             Image* img = m_font->getAsImageMultiline(m_text);
00212             Rect r;
00213             Rect viewport = cam->getViewPort();
00214             r.x = p.x-img->getWidth()/2;
00215             r.y = p.y-img->getHeight()/2;
00216             r.w = img->getWidth();
00217             r.h = img->getHeight();
00218             if(r.intersects(viewport)) {
00219                 img->render(r);
00220                 if (renderbackend->getLightingModel() > 0) {
00221                     renderbackend->changeRenderInfos(1, 4, 5, false, false, 0, KEEP, ALWAYS);
00222                 }
00223             }
00224         }
00225     }
00226 
00227     GenericRendererResizeInfo::GenericRendererResizeInfo(RendererNode anchor, ImagePtr image, int32_t width, int32_t height, bool zoomed):
00228         GenericRendererElementInfo(),
00229         m_anchor(anchor),
00230         m_image(image),
00231         m_width(width),
00232         m_height(height),
00233         m_zoomed(zoomed) {
00234     }
00235     void GenericRendererResizeInfo::render(Camera* cam, Layer* layer, RenderList& instances, RenderBackend* renderbackend) {
00236         Point p = m_anchor.getCalculatedPoint(cam, layer, m_zoomed);
00237         if(m_anchor.getLayer() == layer) {
00238             Rect r;
00239             Rect viewport = cam->getViewPort();
00240             uint32_t width, height;
00241             if(m_zoomed) {
00242                 width = static_cast<uint32_t>(round(m_width * cam->getZoom()));
00243                 height = static_cast<uint32_t>(round(m_height * cam->getZoom()));
00244             } else {
00245                 width = m_width;
00246                 height = m_height;
00247             }
00248             r.x = p.x-width/2;
00249             r.y = p.y-height/2;
00250             r.w = width;
00251             r.h = height;
00252             if(r.intersects(viewport)) {
00253                 m_image->render(r);
00254             }
00255         }
00256     }
00257 
00258     GenericRenderer* GenericRenderer::getInstance(IRendererContainer* cnt) {
00259         return dynamic_cast<GenericRenderer*>(cnt->getRenderer("GenericRenderer"));
00260     }
00261 
00262     GenericRenderer::GenericRenderer(RenderBackend* renderbackend, int32_t position):
00263         RendererBase(renderbackend, position),
00264         m_groups() {
00265         setEnabled(false);
00266     }
00267 
00268     GenericRenderer::GenericRenderer(const GenericRenderer& old):
00269         RendererBase(old),
00270         m_groups() {
00271         setEnabled(false);
00272     }
00273 
00274     RendererBase* GenericRenderer::clone() {
00275         return new GenericRenderer(*this);
00276     }
00277 
00278     GenericRenderer::~GenericRenderer() {
00279     }
00280     void GenericRenderer::addLine(const std::string &group, RendererNode n1, RendererNode n2, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
00281         GenericRendererElementInfo* info = new GenericRendererLineInfo(n1, n2, r, g, b, a);
00282         m_groups[group].push_back(info);
00283     }
00284     void GenericRenderer::addPoint(const std::string &group, RendererNode n, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
00285         GenericRendererElementInfo* info = new GenericRendererPointInfo(n, r, g, b, a);
00286         m_groups[group].push_back(info);
00287     }
00288     void GenericRenderer::addTriangle(const std::string &group, RendererNode n1, RendererNode n2, RendererNode n3, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
00289         GenericRendererElementInfo* info = new GenericRendererTriangleInfo(n1, n2, n3, r, g, b, a);
00290         m_groups[group].push_back(info);
00291     }
00292     void GenericRenderer::addQuad(const std::string &group, RendererNode n1, RendererNode n2, RendererNode n3, RendererNode n4, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
00293         GenericRendererElementInfo* info = new GenericRendererQuadInfo(n1, n2, n3, n4, r, g, b, a);
00294         m_groups[group].push_back(info);
00295     }
00296     void GenericRenderer::addVertex(const std::string &group, RendererNode n, int32_t size, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
00297         GenericRendererElementInfo* info = new GenericRendererVertexInfo(n, size, r, g, b, a);
00298         m_groups[group].push_back(info);
00299     }
00300     void GenericRenderer::addText(const std::string &group, RendererNode n, IFont* font, const std::string &text) {
00301         GenericRendererElementInfo* info = new GenericRendererTextInfo(n, font, text);
00302         m_groups[group].push_back(info);
00303     }
00304     void GenericRenderer::addImage(const std::string &group, RendererNode n, ImagePtr image, bool zoomed) {
00305         GenericRendererElementInfo* info = new GenericRendererImageInfo(n, image, zoomed);
00306         m_groups[group].push_back(info);
00307     }
00308     void GenericRenderer::addAnimation(const std::string &group, RendererNode n, AnimationPtr animation, bool zoomed) {
00309         GenericRendererElementInfo* info = new GenericRendererAnimationInfo(n, animation, zoomed);
00310         m_groups[group].push_back(info);
00311     }
00312     void GenericRenderer::resizeImage(const std::string &group, RendererNode n, ImagePtr image, int32_t width, int32_t height, bool zoomed) {
00313         GenericRendererElementInfo* info = new GenericRendererResizeInfo(n, image, width, height, zoomed);
00314         m_groups[group].push_back(info);
00315     }
00316     void GenericRenderer::removeAll(const std::string &group) {
00317         std::vector<GenericRendererElementInfo*>::const_iterator info_it = m_groups[group].begin();
00318         for (;info_it != m_groups[group].end(); ++info_it) {
00319             delete *info_it;
00320         }
00321         m_groups[group].clear();
00322         m_groups.erase(group);
00323     }
00324     // Remove all groups
00325     void GenericRenderer::removeAll() {
00326         m_groups.clear();
00327     }
00328     // Clear all groups
00329     void GenericRenderer::reset() {
00330         removeAll();
00331     }
00332 
00333     void GenericRenderer::render(Camera* cam, Layer* layer, RenderList& instances) {
00334         std::map<std::string, std::vector<GenericRendererElementInfo*> >::iterator group_it = m_groups.begin();
00335         for(; group_it != m_groups.end(); ++group_it) {
00336             std::vector<GenericRendererElementInfo*>::const_iterator info_it = group_it->second.begin();
00337             for (;info_it != group_it->second.end(); ++info_it) {
00338                 (*info_it)->render(cam, layer, instances, m_renderbackend);
00339             }
00340         }
00341     }
00342 }