00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "video/renderbackend.h"
00031 #include "video/image.h"
00032 #include "video/sdl/sdlimage.h"
00033 #include "video/imagepool.h"
00034 #include "video/animation.h"
00035 #include "video/animationpool.h"
00036 #include "util/math/fife_math.h"
00037 #include "util/log/logger.h"
00038 #include "model/metamodel/grids/cellgrid.h"
00039 #include "model/metamodel/action.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 "view/visual.h"
00046 #include "instancerenderer.h"
00047
00048 namespace {
00049 unsigned int scale(unsigned int val, double factor) {
00050 return static_cast<unsigned int>(ceil(static_cast<double>(val) * factor));
00051 }
00052 }
00053
00054 namespace FIFE {
00055 static Logger _log(LM_VIEWVIEW);
00056
00057 InstanceRenderer::OutlineInfo::OutlineInfo():
00058 r(0),
00059 g(0),
00060 b(0),
00061 width(1),
00062 outline(NULL),
00063 curimg(NULL) {
00064 }
00065 InstanceRenderer::ColoringInfo::ColoringInfo():
00066 r(0),
00067 g(0),
00068 b(0),
00069 overlay(NULL),
00070 curimg(NULL) {
00071 }
00072
00073 InstanceRenderer::OutlineInfo::~OutlineInfo() {
00074 delete outline;
00075 }
00076
00077 InstanceRenderer::ColoringInfo::~ColoringInfo() {
00078 delete overlay;
00079 }
00080
00081 InstanceRenderer* InstanceRenderer::getInstance(IRendererContainer* cnt) {
00082 return dynamic_cast<InstanceRenderer*>(cnt->getRenderer("InstanceRenderer"));
00083 }
00084
00085 InstanceRenderer::InstanceRenderer(RenderBackend* renderbackend, int position, ImagePool* imagepool, AnimationPool* animpool):
00086 RendererBase(renderbackend, position),
00087 m_imagepool(imagepool),
00088 m_animationpool(animpool) {
00089 setEnabled(true);
00090 }
00091
00092 InstanceRenderer::InstanceRenderer(const InstanceRenderer& old):
00093 RendererBase(old),
00094 m_imagepool(old.m_imagepool),
00095 m_animationpool(old.m_animationpool) {
00096 setEnabled(true);
00097 }
00098
00099 RendererBase* InstanceRenderer::clone() {
00100 return new InstanceRenderer(*this);
00101 }
00102
00103 InstanceRenderer::~InstanceRenderer() {
00104 }
00105
00106 void InstanceRenderer::render(Camera* cam, Layer* layer, std::vector<Instance*>& instances) {
00107
00108 if (!layer->areInstancesVisible()) {
00109 FL_DBG(_log, "Layer instances hidden");
00110 return;
00111 }
00112
00113 FL_DBG(_log, "Iterating layer...");
00114 CellGrid* cg = layer->getCellGrid();
00115 if (!cg) {
00116 FL_WARN(_log, "No cellgrid assigned to layer, cannot draw instances");
00117 return;
00118 }
00119
00120 const bool any_effects = !(m_instance_outlines.empty() && m_instance_colorings.empty());
00121
00122 std::vector<Instance*>::const_iterator instance_it = instances.begin();
00123 for (;instance_it != instances.end(); ++instance_it) {
00124 FL_DBG(_log, "Iterating instances...");
00125 Instance* instance = (*instance_it);
00126 InstanceVisual* visual = instance->getVisual<InstanceVisual>();
00127
00128 unsigned char trans = visual->getTransparency();
00129
00135 if (trans == 0) {
00136 unsigned char layer_trans = layer->getLayerTransparency();
00137 trans = layer_trans;
00138 }
00139
00140 InstanceVisualCacheItem& vc = visual->getCacheItem(cam);
00141 FL_DBG(_log, LMsg("Instance layer coordinates = ") << instance->getLocationRef().getLayerCoordinates());
00142
00143 if (any_effects) {
00144 InstanceToOutlines_t::iterator outline_it = m_instance_outlines.find(instance);
00145 if (outline_it != m_instance_outlines.end()) {
00146 bindOutline(outline_it->second, vc, cam)->render(vc.dimensions, 255-trans);
00147 }
00148
00149 InstanceToColoring_t::iterator coloring_it = m_instance_colorings.find(instance);
00150 if (coloring_it != m_instance_colorings.end()) {
00151 bindColoring(coloring_it->second, vc, cam)->render(vc.dimensions, 255-trans);
00152 continue;
00153 }
00154 }
00155
00156 vc.image->render(vc.dimensions, 255-trans);
00157 }
00158 }
00159
00160 Image* InstanceRenderer::bindOutline(OutlineInfo& info, InstanceVisualCacheItem& vc, Camera* cam) {
00161 if (info.curimg == vc.image) {
00162 return info.outline;
00163 } else {
00164 info.curimg = vc.image;
00165 }
00166
00167 if (info.outline) {
00168 delete info.outline;
00169 info.outline = NULL;
00170 }
00171 SDL_Surface* surface = vc.image->getSurface();
00172 SDL_Surface* outline_surface = SDL_ConvertSurface(surface, surface->format, surface->flags);
00173
00174
00175 SDLImage* img = new SDLImage(outline_surface);
00176
00177
00178 uint8_t r, g, b, a = 0;
00179
00180
00181 for (unsigned int x = 0; x < img->getWidth(); x ++) {
00182 uint8_t prev_a = 0;
00183 for (unsigned int y = 0; y < img->getHeight(); y ++) {
00184 vc.image->getPixelRGBA(x, y, &r, &g, &b, &a);
00185 if ((a == 0 || prev_a == 0) && (a != prev_a)) {
00186 if (a < prev_a) {
00187 for (unsigned int yy = y; yy < y + info.width; yy++) {
00188 img->putPixel(x, yy, info.r, info.g, info.b);
00189 }
00190 } else {
00191 for (unsigned int yy = y - info.width; yy < y; yy++) {
00192 img->putPixel(x, yy, info.r, info.g, info.b);
00193 }
00194 }
00195 }
00196 prev_a = a;
00197 }
00198 }
00199
00200 for (unsigned int y = 0; y < img->getHeight(); y ++) {
00201 uint8_t prev_a = 0;
00202 for (unsigned int x = 0; x < img->getWidth(); x ++) {
00203 vc.image->getPixelRGBA(x, y, &r, &g, &b, &a);
00204 if ((a == 0 || prev_a == 0) && (a != prev_a)) {
00205 if (a < prev_a) {
00206 for (unsigned int xx = x; xx < x + info.width; xx++) {
00207 img->putPixel(xx, y, info.r, info.g, info.b);
00208 }
00209 } else {
00210 for (unsigned int xx = x - info.width; xx < x; xx++) {
00211 img->putPixel(xx, y, info.r, info.g, info.b);
00212 }
00213 }
00214 }
00215 prev_a = a;
00216 }
00217 }
00218
00219
00220 info.outline = m_renderbackend->createImage(img->detachSurface());
00221 delete img;
00222 return info.outline;
00223 }
00224
00225 Image* InstanceRenderer::bindColoring(ColoringInfo& info, InstanceVisualCacheItem& vc, Camera* cam) {
00226 if (info.curimg == vc.image) {
00227 return info.overlay;
00228 } else {
00229 info.curimg = vc.image;
00230 }
00231 if (info.overlay) {
00232 delete info.overlay;
00233 info.overlay = NULL;
00234 }
00235 SDL_Surface* surface = vc.image->getSurface();
00236 SDL_Surface* overlay_surface = SDL_ConvertSurface(surface, surface->format, surface->flags);
00237
00238
00239 SDLImage* img = new SDLImage(overlay_surface);
00240
00241 uint8_t r, g, b, a = 0;
00242
00243 for (unsigned int x = 0; x < img->getWidth(); x ++) {
00244 for (unsigned int y = 0; y < img->getHeight(); y ++) {
00245 vc.image->getPixelRGBA(x, y, &r, &g, &b, &a);
00246 if (a > 0) {
00247 img->putPixel(x, y, (r + info.r) >> 1, (g + info.g) >> 1, (b + info.b) >> 1);
00248 }
00249 }
00250 }
00251
00252
00253 info.overlay = m_renderbackend->createImage(img->detachSurface());
00254 delete img;
00255 return info.overlay;
00256 }
00257
00258 void InstanceRenderer::addOutlined(Instance* instance, int r, int g, int b, int width) {
00259 OutlineInfo info;
00260 info.r = r;
00261 info.g = g;
00262 info.b = b;
00263 info.width = width;
00264
00265 m_instance_outlines[instance] = info;
00266 }
00267
00268 void InstanceRenderer::addColored(Instance* instance, int r, int g, int b) {
00269 ColoringInfo info;
00270 info.r = r;
00271 info.g = g;
00272 info.b = b;
00273
00274 m_instance_colorings[instance] = info;
00275 }
00276
00277 void InstanceRenderer::removeOutlined(Instance* instance) {
00278 m_instance_outlines.erase(instance);
00279 }
00280
00281 void InstanceRenderer::removeColored(Instance* instance) {
00282 m_instance_colorings.erase(instance);
00283 }
00284
00285 void InstanceRenderer::removeAllOutlines() {
00286 m_instance_outlines.clear();
00287 }
00288
00289 void InstanceRenderer::removeAllColored() {
00290 m_instance_colorings.clear();
00291 }
00292
00293 void InstanceRenderer::reset() {
00294 removeAllOutlines();
00295 removeAllColored();
00296 }
00297
00298 }