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 #include <boost/bind.hpp>
00026
00027
00028
00029
00030
00031 #include "video/renderbackend.h"
00032 #include "video/image.h"
00033 #include "video/imagemanager.h"
00034 #include "video/sdl/sdlimage.h"
00035 #include "video/animation.h"
00036 #include "util/math/fife_math.h"
00037 #include "util/log/logger.h"
00038 #include "util/time/timemanager.h"
00039 #include "model/metamodel/grids/cellgrid.h"
00040 #include "model/metamodel/action.h"
00041 #include "model/structures/instance.h"
00042 #include "model/structures/layer.h"
00043 #include "model/structures/location.h"
00044 #include "model/structures/map.h"
00045 #include "video/opengl/fife_opengl.h"
00046
00047 #include "view/camera.h"
00048 #include "view/visual.h"
00049 #include "instancerenderer.h"
00050
00051 #include "video/opengle/gleimage.h"
00052
00053
00054 namespace {
00055 uint32_t scale(uint32_t val, double factor) {
00056 return static_cast<uint32_t>(ceil(static_cast<double>(val) * factor));
00057 }
00058 }
00059
00060 namespace FIFE {
00061 static Logger _log(LM_VIEWVIEW);
00062
00063 class InstanceRendererDeleteListener : public InstanceDeleteListener {
00064 public:
00065 InstanceRendererDeleteListener(InstanceRenderer* r) {
00066 m_renderer = r;
00067 }
00068 virtual ~InstanceRendererDeleteListener() {}
00069
00070 virtual void onInstanceDeleted(Instance* instance) {
00071 m_renderer->removeInstance(instance);
00072 }
00073
00074 private:
00075 InstanceRenderer* m_renderer;
00076 };
00077
00078 InstanceRenderer::OutlineInfo::OutlineInfo(InstanceRenderer* r):
00079 r(0),
00080 g(0),
00081 b(0),
00082 width(1),
00083 dirty(false),
00084 curimg(NULL),
00085 renderer(r) {
00086 }
00087 InstanceRenderer::ColoringInfo::ColoringInfo(InstanceRenderer* r):
00088 r(0),
00089 g(0),
00090 b(0),
00091 dirty(false),
00092 curimg(NULL),
00093 renderer(r) {
00094 }
00095
00096 InstanceRenderer::AreaInfo::AreaInfo():
00097 instance(NULL),
00098 groups(),
00099 w(1),
00100 h(1),
00101 trans(0),
00102 front(true),
00103 z(0) {
00104 }
00105
00106 InstanceRenderer::OutlineInfo::~OutlineInfo() {
00107 renderer->addToCheck(outline);
00108 }
00109
00110 InstanceRenderer::ColoringInfo::~ColoringInfo() {
00111 if (renderer->needColorBinding()) {
00112 renderer->addToCheck(overlay);
00113 }
00114 }
00115
00116 InstanceRenderer::AreaInfo::~AreaInfo() {
00117 }
00118
00119 InstanceRenderer* InstanceRenderer::getInstance(IRendererContainer* cnt) {
00120 return dynamic_cast<InstanceRenderer*>(cnt->getRenderer("InstanceRenderer"));
00121 }
00122
00123 InstanceRenderer::InstanceRenderer(RenderBackend* renderbackend, int32_t position):
00124 RendererBase(renderbackend, position),
00125 m_area_layer(false),
00126 m_interval(60*1000),
00127 m_timer_enabled(false) {
00128 setEnabled(true);
00129 if(m_renderbackend->getName() == "OpenGLe") {
00130 m_need_sorting = false;
00131 } else {
00132 m_need_sorting = true;
00133 if(m_renderbackend->getName() == "SDL") {
00134 m_need_bind_coloring = true;
00135 } else {
00136 m_need_bind_coloring = false;
00137 }
00138 }
00139
00140 m_timer.setInterval(m_interval);
00141 m_timer.setCallback(boost::bind(&InstanceRenderer::check, this));
00142
00143 m_delete_listener = new InstanceRendererDeleteListener(this);
00144 }
00145
00146 InstanceRenderer::InstanceRenderer(const InstanceRenderer& old):
00147 RendererBase(old),
00148 m_area_layer(false),
00149 m_interval(old.m_interval),
00150 m_timer_enabled(false) {
00151 setEnabled(true);
00152 if(m_renderbackend->getName() == "OpenGLe") {
00153 m_need_sorting = false;
00154 } else {
00155 m_need_sorting = true;
00156 if(m_renderbackend->getName() == "SDL") {
00157 m_need_bind_coloring = true;
00158 } else {
00159 m_need_bind_coloring = false;
00160 }
00161 }
00162
00163 m_timer.setInterval(m_interval);
00164 m_timer.setCallback(boost::bind(&InstanceRenderer::check, this));
00165
00166 m_delete_listener = new InstanceRendererDeleteListener(this);
00167 }
00168
00169 RendererBase* InstanceRenderer::clone() {
00170 return new InstanceRenderer(*this);
00171 }
00172
00173 InstanceRenderer::~InstanceRenderer() {
00174
00175 if (!m_assigned_instances.empty()) {
00176 reset();
00177 }
00178
00179 delete m_delete_listener;
00180 }
00181
00182 void InstanceRenderer::render(Camera* cam, Layer* layer, RenderList& instances) {
00183
00184 CellGrid* cg = layer->getCellGrid();
00185 if (!cg) {
00186 FL_WARN(_log, "No cellgrid assigned to layer, cannot draw instances");
00187 return;
00188 }
00189
00190 if(m_need_sorting) {
00191 renderAlreadySorted(cam, layer, instances);
00192 } else {
00193 renderUnsorted(cam, layer, instances);
00194 }
00195 }
00196
00197 void InstanceRenderer::renderUnsorted(Camera* cam, Layer* layer, RenderList& instances)
00198 {
00199
00200 const bool any_effects = !(m_instance_outlines.empty() && m_instance_colorings.empty());
00201 const bool unlit = !m_unlit_groups.empty();
00202 uint32_t lm = m_renderbackend->getLightingModel();
00203
00204
00205 Map* parent = layer->getMap();
00206 int num_layers = parent->getLayerCount();
00207 int this_layer = 1;
00208 const std::list<Layer*>& layers = parent->getLayers();
00209 std::list<Layer*>::const_iterator iter = layers.begin();
00210 for (; iter != layers.end(); ++iter, ++this_layer) {
00211 if (*iter == layer) {
00212 break;
00213 }
00214 }
00215
00216
00217 static const double global_z_min = -100.0;
00218 static const double global_z_max = 100.0;
00219 #if 0
00220 static const double depth_range = fabs(global_z_min - global_z_max);
00221
00222
00223
00224
00225
00226
00227
00228
00229 double layer_depth_range = depth_range / static_cast<double>(num_layers);
00230
00231 double layer_z_offset = global_z_min +
00232 layer_depth_range * static_cast<double>(this_layer) -
00233 layer_depth_range * 0.5;
00234 #else
00235
00236
00237 double layer_z_offset = global_z_max - (num_layers - (this_layer - 1)) * 20;
00238 #endif
00239
00240 std::multimap<float, RenderItem*> transparentInstances;
00241
00242 RenderList::iterator instance_it = instances.begin();
00243 for (;instance_it != instances.end(); ++instance_it) {
00244
00245 Instance* instance = (*instance_it)->instance;
00246 RenderItem& vc = **instance_it;
00247 float vertexZ = static_cast<float>(layer_z_offset + vc.screenpoint.z);
00248
00249
00250 if(vc.transparency == 255) {
00251 if (any_effects) {
00252 InstanceToOutlines_t::iterator outline_it = m_instance_outlines.find(instance);
00253 const bool outline = outline_it != m_instance_outlines.end();
00254 if (outline) {
00255 Image* outline = bindOutline(outline_it->second, vc, cam);
00256 outline->renderZ(vc.dimensions, vertexZ, 255, lm != 0 ? true : false);
00257 vc.image->renderZ(vc.dimensions, vertexZ, 255);
00258 }
00259
00260 InstanceToColoring_t::iterator coloring_it = m_instance_colorings.find(instance);
00261 const bool coloring = coloring_it != m_instance_colorings.end();
00262 if (coloring) {
00263 uint8_t rgb[3] = { coloring_it->second.r, coloring_it->second.g, coloring_it->second.b };
00264 vc.image->renderZ(vc.dimensions, vertexZ, 255, false, rgb);
00265 }
00266
00267 if (outline || coloring) {
00268 continue;
00269 }
00270 }
00271
00272
00273 if(lm != 0 && unlit) {
00274 bool found = false;
00275 std::string lit_name = instance->getObject()->getNamespace();
00276 std::list<std::string>::iterator unlit_it = m_unlit_groups.begin();
00277 for(;unlit_it != m_unlit_groups.end(); ++unlit_it) {
00278 if(lit_name.find(*unlit_it) != std::string::npos) {
00279 found = true;
00280 break;
00281 }
00282 }
00283
00284 vc.image->renderZ(vc.dimensions, vertexZ, 255, found ? true : false);
00285 continue;
00286 }
00287
00288 vc.image->renderZ(vc.dimensions, vertexZ, 255);
00289 } else {
00290 transparentInstances.insert(std::pair<float, RenderItem*>(vertexZ, &vc));
00291 }
00292 }
00293
00294
00295 if(!transparentInstances.empty()) {
00296 std::multimap<float, RenderItem*>::iterator it = transparentInstances.begin();
00297 for( ; it != transparentInstances.end(); ++it) {
00298 RenderItem& vc = *(it->second);
00299 uint8_t alpha = vc.transparency;
00300 float vertexZ = it->first;
00301
00302 if (any_effects) {
00303 InstanceToOutlines_t::iterator outline_it = m_instance_outlines.find(vc.instance);
00304 const bool outline = outline_it != m_instance_outlines.end();
00305 if (outline) {
00306 Image* outline = bindOutline(outline_it->second, vc, cam);
00307 outline->renderZ(vc.dimensions, vertexZ, alpha, lm != 0 ? true : false);
00308 vc.image->renderZ(vc.dimensions, vertexZ, alpha);
00309 }
00310
00311 InstanceToColoring_t::iterator coloring_it = m_instance_colorings.find(vc.instance);
00312 const bool coloring = coloring_it != m_instance_colorings.end();
00313 if (coloring) {
00314 uint8_t rgb[3] = { coloring_it->second.r, coloring_it->second.g, coloring_it->second.b };
00315 vc.image->renderZ(vc.dimensions, vertexZ, alpha, false, rgb);
00316 }
00317
00318 if (outline || coloring) {
00319 continue;
00320 }
00321 }
00322
00323
00324 if(lm != 0 && unlit) {
00325 bool found = false;
00326 std::string lit_name = vc.instance->getObject()->getNamespace();
00327 std::list<std::string>::iterator unlit_it = m_unlit_groups.begin();
00328 for(;unlit_it != m_unlit_groups.end(); ++unlit_it) {
00329 if(lit_name.find(*unlit_it) != std::string::npos) {
00330 found = true;
00331 break;
00332 }
00333 }
00334
00335 vc.image->renderZ(vc.dimensions, vertexZ, alpha, found ? true : false);
00336 continue;
00337 }
00338
00339 vc.image->renderZ(vc.dimensions, vertexZ, alpha);
00340 }
00341 }
00342 }
00343
00344 void InstanceRenderer::renderAlreadySorted(Camera* cam, Layer* layer, RenderList& instances) {
00345 const bool any_effects = !(m_instance_outlines.empty() && m_instance_colorings.empty());
00346 const bool unlit = !m_unlit_groups.empty();
00347 uint32_t lm = m_renderbackend->getLightingModel();
00348
00349 m_area_layer = false;
00350 if(!m_instance_areas.empty()) {
00351 InstanceToAreas_t::iterator area_it = m_instance_areas.begin();
00352 for(;area_it != m_instance_areas.end(); area_it++) {
00353 AreaInfo& info = area_it->second;
00354 if(info.instance->getLocation().getLayer() == layer) {
00355 if(info.front) {
00356 DoublePoint3D instance_posv = cam->toVirtualScreenCoordinates(info.instance->getLocation().getMapCoordinates());
00357 info.z = instance_posv.z;
00358 }
00359 m_area_layer = true;
00360 }
00361 }
00362 }
00363
00364 RenderList::iterator instance_it = instances.begin();
00365 for (;instance_it != instances.end(); ++instance_it) {
00366
00367 Instance* instance = (*instance_it)->instance;
00368 RenderItem& vc = **instance_it;
00369
00370 if(m_area_layer) {
00371 InstanceToAreas_t::iterator areas_it = m_instance_areas.begin();
00372 for(;areas_it != m_instance_areas.end(); areas_it++) {
00373 AreaInfo& infoa = areas_it->second;
00374 if(infoa.front) {
00375 if(infoa.z >= vc.screenpoint.z) {
00376 continue;
00377 }
00378 }
00379
00380 std::string str_name = instance->getObject()->getNamespace();
00381 std::list<std::string>::iterator group_it = infoa.groups.begin();
00382 for(;group_it != infoa.groups.end(); ++group_it) {
00383 if(str_name.find((*group_it)) != std::string::npos) {
00384 ScreenPoint p;
00385 Rect rec;
00386 p = cam->toScreenCoordinates(infoa.instance->getLocation().getMapCoordinates());
00387 rec.x = p.x - infoa.w / 2;
00388 rec.y = p.y - infoa.h / 2;
00389 rec.w = infoa.w;
00390 rec.h = infoa.h;
00391 if(infoa.instance != instance && vc.dimensions.intersects(rec)) {
00392 vc.transparency = 255 - infoa.trans;
00393 }
00394 }
00395 }
00396 }
00397 }
00398
00399
00400
00401 if (any_effects) {
00402 InstanceToOutlines_t::iterator outline_it = m_instance_outlines.find(instance);
00403 const bool outline = outline_it != m_instance_outlines.end();
00404 if (outline) {
00405 if (lm != 0) {
00406
00407
00408 vc.image->render(vc.dimensions, vc.transparency);
00409 bindOutline(outline_it->second, vc, cam)->render(vc.dimensions, vc.transparency);
00410 m_renderbackend->changeRenderInfos(1, 4, 5, false, true, 255, REPLACE, ALWAYS);
00411 } else {
00412 bindOutline(outline_it->second, vc, cam)->render(vc.dimensions, vc.transparency);
00413 vc.image->render(vc.dimensions, vc.transparency);
00414 }
00415 }
00416
00417 InstanceToColoring_t::iterator coloring_it = m_instance_colorings.find(instance);
00418 const bool coloring = coloring_it != m_instance_colorings.end();
00419 if (coloring) {
00420 if(m_need_bind_coloring) {
00421 bindColoring(coloring_it->second, vc, cam)->render(vc.dimensions, vc.transparency);
00422 m_renderbackend->changeRenderInfos(1, 4, 5, true, false, 0, KEEP, ALWAYS);
00423 } else {
00424 uint8_t rgb[3] = { coloring_it->second.r, coloring_it->second.g, coloring_it->second.b };
00425 vc.image->render(vc.dimensions, vc.transparency, rgb);
00426 m_renderbackend->changeRenderInfos(1, 4, 5, true, false, 0, KEEP, ALWAYS);
00427 }
00428 }
00429
00430 if (outline || coloring) {
00431 continue;
00432 }
00433 }
00434 if(lm != 0) {
00435 if(unlit) {
00436 bool found = false;
00437 std::string lit_name = instance->getObject()->getNamespace();
00438 std::list<std::string>::iterator unlit_it = m_unlit_groups.begin();
00439 for(;unlit_it != m_unlit_groups.end(); ++unlit_it) {
00440 if(lit_name.find(*unlit_it) != std::string::npos) {
00441 found = true;
00442 break;
00443 }
00444 }
00445 vc.image->render(vc.dimensions, vc.transparency);
00446 if (found) {
00447 m_renderbackend->changeRenderInfos(1, 4, 5, true, true, 255, REPLACE, ALWAYS);
00448 } else {
00449 m_renderbackend->changeRenderInfos(1, 4, 5, true, true, 0, ZERO, ALWAYS);
00450 }
00451 continue;
00452 }
00453 }
00454 vc.image->render(vc.dimensions, vc.transparency);
00455
00456 }
00457 }
00458
00459 inline bool aboveThreshold(int32_t threshold, int32_t alpha, int32_t prev_alpha) {
00460 if(threshold > 1) {
00461
00462 if (((alpha - threshold) >= 0 || (prev_alpha - threshold) >= 0) && (alpha != prev_alpha)) {
00463 return true;
00464 } else {
00465 return false;
00466 }
00467 } else {
00468
00469 if((alpha == 0 || prev_alpha == 0) && (alpha != prev_alpha)) {
00470 return true;
00471 } else {
00472 return false;
00473 }
00474 }
00475 }
00476
00477 Image* InstanceRenderer::bindOutline(OutlineInfo& info, RenderItem& vc, Camera* cam) {
00478 bool valid = isValidImage(info.outline);
00479 if (!info.dirty && info.curimg == vc.image.get() && valid) {
00480 removeFromCheck(info.outline);
00481
00482 return info.outline.get();
00483 } else {
00484 info.curimg = vc.image.get();
00485 }
00486
00487
00488 if (valid) {
00489 addToCheck(info.outline);
00490 }
00491
00492
00493
00494
00495
00496 bool found = false;
00497
00498 std::stringstream sts;
00499 sts << vc.image.get()->getName() << "," << static_cast<uint32_t>(info.r) << "," <<
00500 static_cast<uint32_t>(info.g) << "," << static_cast<uint32_t>(info.b) << "," << info.width;
00501
00502 if (ImageManager::instance()->exists(sts.str())) {
00503 info.outline = ImageManager::instance()->getPtr(sts.str());
00504 if (isValidImage(info.outline)) {
00505 removeFromCheck(info.outline);
00506
00507 info.dirty = false;
00508 return info.outline.get();
00509 }
00510 found = true;
00511 }
00512
00513
00514
00515
00516 if(vc.image->isSharedImage()) {
00517 vc.image->forceLoadInternal();
00518 }
00519
00520 SDL_Surface* surface = vc.image->getSurface();
00521 SDL_Surface* outline_surface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_SRCALPHA,
00522 vc.image->getWidth(), vc.image->getHeight(), 32,
00523 RMASK, GMASK, BMASK, AMASK);
00524
00525
00526 uint8_t r, g, b, a = 0;
00527
00528
00529 for (int32_t x = 0; x < outline_surface->w; x ++) {
00530 int32_t prev_a = 0;
00531 for (int32_t y = 0; y < outline_surface->h; y ++) {
00532 vc.image->getPixelRGBA(x, y, &r, &g, &b, &a);
00533 if (aboveThreshold(info.threshold, static_cast<int32_t>(a), prev_a)) {
00534 if (a < prev_a) {
00535 for (int32_t yy = y; yy < y + info.width; yy++) {
00536 Image::putPixel(outline_surface, x, yy, info.r, info.g, info.b);
00537 }
00538 } else {
00539 for (int32_t yy = y - info.width; yy < y; yy++) {
00540 Image::putPixel(outline_surface, x, yy, info.r, info.g, info.b);
00541 }
00542 }
00543 }
00544 prev_a = a;
00545 }
00546 }
00547
00548 for (int32_t y = 0; y < outline_surface->h; y ++) {
00549 int32_t prev_a = 0;
00550 for (int32_t x = 0; x < outline_surface->w; x ++) {
00551 vc.image->getPixelRGBA(x, y, &r, &g, &b, &a);
00552 if (aboveThreshold(info.threshold, static_cast<int32_t>(a), prev_a)) {
00553 if (a < prev_a) {
00554 for (int32_t xx = x; xx < x + info.width; xx++) {
00555 Image::putPixel(outline_surface, xx, y, info.r, info.g, info.b);
00556 }
00557 } else {
00558 for (int32_t xx = x - info.width; xx < x; xx++) {
00559 Image::putPixel(outline_surface, xx, y, info.r, info.g, info.b);
00560 }
00561 }
00562 }
00563 prev_a = a;
00564 }
00565 }
00566
00567
00568 Image* img = m_renderbackend->createImage(sts.str(), outline_surface);
00569 img->setState(IResource::RES_LOADED);
00570
00571 if (found) {
00572
00573 removeFromCheck(info.outline);
00574 ImagePtr temp(img);
00575 info.outline.get()->copySubimage(0, 0, temp);
00576 info.outline.get()->setState(IResource::RES_LOADED);
00577 } else {
00578
00579 info.outline = ImageManager::instance()->add(img);
00580 }
00581
00582 info.dirty = false;
00583
00584 return info.outline.get();
00585 }
00586
00587 Image* InstanceRenderer::bindColoring(ColoringInfo& info, RenderItem& vc, Camera* cam) {
00588 bool valid = isValidImage(info.overlay);
00589 if (!info.dirty && info.curimg == vc.image.get() && valid) {
00590 removeFromCheck(info.overlay);
00591
00592 return info.overlay.get();
00593 } else {
00594 info.curimg = vc.image.get();
00595 }
00596
00597
00598 if (valid) {
00599 addToCheck(info.overlay);
00600 }
00601
00602 bool found = false;
00603
00604 std::stringstream sts;
00605 sts << vc.image.get()->getName() << "," << static_cast<uint32_t>(info.r) << "," <<
00606 static_cast<uint32_t>(info.g) << "," << static_cast<uint32_t>(info.b);
00607
00608 if (ImageManager::instance()->exists(sts.str())) {
00609 info.overlay = ImageManager::instance()->getPtr(sts.str());
00610 valid = isValidImage(info.overlay);
00611 if (valid) {
00612 removeFromCheck(info.overlay);
00613
00614 info.dirty = false;
00615 return info.overlay.get();
00616 }
00617 found = true;
00618 }
00619
00620
00621
00622 if(vc.image->isSharedImage()) {
00623 vc.image->forceLoadInternal();
00624 }
00625
00626
00627 SDL_Surface* surface = vc.image->getSurface();
00628 SDL_Surface* overlay_surface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_SRCALPHA,
00629 vc.image->getWidth(), vc.image->getHeight(), 32,
00630 RMASK, GMASK, BMASK, AMASK);
00631
00632 uint8_t r, g, b, a = 0;
00633
00634 for (int32_t x = 0; x < overlay_surface->w; x ++) {
00635 for (int32_t y = 0; y < overlay_surface->h; y ++) {
00636 vc.image->getPixelRGBA(x, y, &r, &g, &b, &a);
00637 if (a > 0) {
00638 Image::putPixel(overlay_surface, x, y, (r + info.r) >> 1, (g + info.g) >> 1, (b + info.b) >> 1, a);
00639 }
00640 }
00641 }
00642
00643
00644 Image* img = m_renderbackend->createImage(sts.str(), overlay_surface);
00645
00646 if (found) {
00647
00648 removeFromCheck(info.overlay);
00649 ImagePtr temp(img);
00650 info.overlay.get()->copySubimage(0, 0, temp);
00651 info.overlay.get()->setState(IResource::RES_LOADED);
00652 } else {
00653
00654 img->setState(IResource::RES_LOADED);
00655 info.overlay = ImageManager::instance()->add(img);
00656 }
00657
00658 info.dirty = false;
00659
00660 return info.overlay.get();
00661 }
00662
00663 void InstanceRenderer::addOutlined(Instance* instance, int32_t r, int32_t g, int32_t b, int32_t width, int32_t threshold) {
00664 OutlineInfo newinfo(this);
00665 newinfo.r = r;
00666 newinfo.g = g;
00667 newinfo.b = b;
00668 newinfo.threshold = threshold;
00669 newinfo.width = width;
00670 newinfo.dirty = true;
00671
00672
00673
00674
00675
00676 std::pair<InstanceToOutlines_t::iterator, bool> insertiter = m_instance_outlines.insert(std::make_pair(instance, newinfo));
00677
00678 if (insertiter.second == false) {
00679
00680
00681 OutlineInfo& info = insertiter.first->second;
00682
00683 if (info.r != r || info.g != g || info.b != b || info.width != width) {
00684
00685
00686 info.r = r;
00687 info.b = b;
00688 info.g = g;
00689 info.width = width;
00690 info.threshold = threshold;
00691 info.dirty = true;
00692 }
00693 } else {
00694 std::pair<InstanceToEffects_t::iterator, bool> iter = m_assigned_instances.insert(std::make_pair(instance, OUTLINE));
00695 if (iter.second) {
00696 instance->addDeleteListener(m_delete_listener);
00697 } else {
00698 Effect& effect = iter.first->second;
00699 if ((effect & OUTLINE) != OUTLINE) {
00700 effect += OUTLINE;
00701 }
00702 }
00703 }
00704 }
00705
00706 void InstanceRenderer::addColored(Instance* instance, int32_t r, int32_t g, int32_t b) {
00707 ColoringInfo newinfo(this);
00708 newinfo.r = r;
00709 newinfo.g = g;
00710 newinfo.b = b;
00711 newinfo.dirty = true;
00712
00713
00714
00715
00716
00717 std::pair<InstanceToColoring_t::iterator, bool> insertiter = m_instance_colorings.insert(std::make_pair(instance, newinfo));
00718
00719 if (insertiter.second == false) {
00720
00721
00722 ColoringInfo& info = insertiter.first->second;
00723
00724 if (info.r != r || info.g != g || info.b != b) {
00725
00726 info.r = r;
00727 info.b = b;
00728 info.g = g;
00729 info.dirty = true;
00730 }
00731 } else {
00732 std::pair<InstanceToEffects_t::iterator, bool> iter = m_assigned_instances.insert(std::make_pair(instance, COLOR));
00733 if (iter.second) {
00734 instance->addDeleteListener(m_delete_listener);
00735 } else {
00736 Effect& effect = iter.first->second;
00737 if ((effect & COLOR) != COLOR) {
00738 effect += COLOR;
00739 }
00740 }
00741 }
00742 }
00743
00744 void InstanceRenderer::addTransparentArea(Instance* instance, const std::list<std::string> &groups, uint32_t w, uint32_t h, uint8_t trans, bool front) {
00745 AreaInfo newinfo;
00746 newinfo.instance = instance;
00747 newinfo.groups = groups;
00748
00749 newinfo.w = w;
00750 newinfo.h = h;
00751 newinfo.trans = trans;
00752 newinfo.front = front;
00753
00754
00755
00756
00757
00758
00759 std::pair<InstanceToAreas_t::iterator, bool> insertiter = m_instance_areas.insert(std::make_pair(instance, newinfo));
00760
00761 if (insertiter.second == false) {
00762
00763
00764 AreaInfo& info = insertiter.first->second;
00765 } else {
00766 std::pair<InstanceToEffects_t::iterator, bool> iter = m_assigned_instances.insert(std::make_pair(instance, AREA));
00767 if (iter.second) {
00768 instance->addDeleteListener(m_delete_listener);
00769 } else {
00770 Effect& effect = iter.first->second;
00771 if ((effect & AREA) != AREA) {
00772 effect += AREA;
00773 }
00774 }
00775 }
00776 }
00777
00778 void InstanceRenderer::removeOutlined(Instance* instance) {
00779 InstanceToEffects_t::iterator it = m_assigned_instances.find(instance);
00780 if (it != m_assigned_instances.end()) {
00781 if (it->second == OUTLINE) {
00782 instance->removeDeleteListener(m_delete_listener);
00783 m_instance_outlines.erase(instance);
00784 m_assigned_instances.erase(it);
00785 } else if ((it->second & OUTLINE) == OUTLINE) {
00786 it->second -= OUTLINE;
00787 m_instance_outlines.erase(instance);
00788 }
00789 }
00790 }
00791
00792 void InstanceRenderer::removeColored(Instance* instance) {
00793 InstanceToEffects_t::iterator it = m_assigned_instances.find(instance);
00794 if (it != m_assigned_instances.end()) {
00795 if (it->second == COLOR) {
00796 instance->removeDeleteListener(m_delete_listener);
00797 m_instance_colorings.erase(instance);
00798 m_assigned_instances.erase(it);
00799 } else if ((it->second & COLOR) == COLOR) {
00800 it->second -= COLOR;
00801 m_instance_colorings.erase(instance);
00802 }
00803 }
00804 }
00805
00806 void InstanceRenderer::removeTransparentArea(Instance* instance) {
00807 InstanceToEffects_t::iterator it = m_assigned_instances.find(instance);
00808 if (it != m_assigned_instances.end()) {
00809 if (it->second == AREA) {
00810 instance->removeDeleteListener(m_delete_listener);
00811 m_instance_areas.erase(instance);
00812 m_assigned_instances.erase(it);
00813 } else if ((it->second & AREA) == AREA) {
00814 it->second -= AREA;
00815 m_instance_areas.erase(instance);
00816 }
00817 }
00818 }
00819
00820 void InstanceRenderer::removeAllOutlines() {
00821 if (!m_instance_outlines.empty()) {
00822 InstanceToOutlines_t::iterator outline_it = m_instance_outlines.begin();
00823 for (; outline_it != m_instance_outlines.end(); ++outline_it) {
00824 InstanceToEffects_t::iterator it = m_assigned_instances.find((*outline_it).first);
00825 if (it != m_assigned_instances.end()) {
00826 if (it->second == OUTLINE) {
00827 (*outline_it).first->removeDeleteListener(m_delete_listener);
00828 m_assigned_instances.erase(it);
00829 } else if ((it->second & OUTLINE) == OUTLINE) {
00830 it->second -= OUTLINE;
00831 }
00832 }
00833 }
00834 m_instance_outlines.clear();
00835 }
00836 }
00837
00838 void InstanceRenderer::removeAllColored() {
00839 if (!m_instance_colorings.empty()) {
00840 InstanceToColoring_t::iterator color_it = m_instance_colorings.begin();
00841 for (; color_it != m_instance_colorings.end(); ++color_it) {
00842 InstanceToEffects_t::iterator it = m_assigned_instances.find((*color_it).first);
00843 if (it != m_assigned_instances.end()) {
00844 if (it->second == COLOR) {
00845 (*color_it).first->removeDeleteListener(m_delete_listener);
00846 m_assigned_instances.erase(it);
00847 } else if ((it->second & COLOR) == COLOR) {
00848 it->second -= COLOR;
00849 }
00850 }
00851 }
00852 m_instance_colorings.clear();
00853 }
00854 }
00855
00856 void InstanceRenderer::removeAllTransparentAreas() {
00857 if (!m_instance_areas.empty()) {
00858 InstanceToAreas_t::iterator area_it = m_instance_areas.begin();
00859 for (; area_it != m_instance_areas.end(); ++area_it) {
00860 InstanceToEffects_t::iterator it = m_assigned_instances.find((*area_it).first);
00861 if (it != m_assigned_instances.end()) {
00862 if (it->second == AREA) {
00863 (*area_it).first->removeDeleteListener(m_delete_listener);
00864 m_assigned_instances.erase(it);
00865 } else if ((it->second & AREA) == AREA) {
00866 it->second -= AREA;
00867 }
00868 }
00869 }
00870 m_instance_areas.clear();
00871 }
00872 }
00873
00874 void InstanceRenderer::addIgnoreLight(const std::list<std::string> &groups) {
00875 std::list<std::string>::const_iterator group_it = groups.begin();
00876 for(;group_it != groups.end(); ++group_it) {
00877 m_unlit_groups.push_back(*group_it);
00878 }
00879 m_unlit_groups.sort();
00880 m_unlit_groups.unique();
00881 }
00882
00883 void InstanceRenderer::removeIgnoreLight(const std::list<std::string> &groups) {
00884 std::list<std::string>::const_iterator group_it = groups.begin();
00885 for(;group_it != groups.end(); ++group_it) {
00886 std::list<std::string>::iterator unlit_it = m_unlit_groups.begin();
00887 for(;unlit_it != m_unlit_groups.end(); ++unlit_it) {
00888 if((*group_it).find(*unlit_it) != std::string::npos) {
00889 m_unlit_groups.remove(*unlit_it);
00890 break;
00891 }
00892 }
00893 }
00894 }
00895
00896 void InstanceRenderer::removeAllIgnoreLight() {
00897 m_unlit_groups.clear();
00898 }
00899
00900 void InstanceRenderer::reset() {
00901
00902 if (m_timer_enabled) {
00903 m_timer.stop();
00904 }
00905
00906 removeAllOutlines();
00907 removeAllColored();
00908 removeAllTransparentAreas();
00909 removeAllIgnoreLight();
00910
00911 m_check_images.clear();
00912 }
00913
00914 void InstanceRenderer::setRemoveInterval(uint32_t interval) {
00915 if (m_interval != interval*1000) {
00916 m_interval = interval*1000;
00917 m_timer.setInterval(m_interval);
00918 }
00919 }
00920
00921 uint32_t InstanceRenderer::getRemoveInterval() const {
00922 return m_interval/1000;
00923 }
00924
00925 void InstanceRenderer::addToCheck(const ImagePtr& image) {
00926 if (isValidImage(image)) {
00927
00928 ImagesToCheck_t::iterator it = m_check_images.begin();
00929 for (; it != m_check_images.end(); ++it) {
00930 if (it->image.get()->getName() == image.get()->getName()) {
00931 return;
00932 }
00933 }
00934 s_image_entry entry;
00935 entry.image = image;
00936 entry.timestamp = TimeManager::instance()->getTime();
00937 m_check_images.push_front(entry);
00938
00939 if (!m_timer_enabled) {
00940 m_timer_enabled = true;
00941 m_timer.start();
00942 }
00943 }
00944 }
00945
00946 void InstanceRenderer::check() {
00947 uint32_t now = TimeManager::instance()->getTime();
00948 ImagesToCheck_t::iterator it = m_check_images.begin();
00949
00950 while (it != m_check_images.end()) {
00951 if (now - it->timestamp > m_interval) {
00952 if (isValidImage(it->image)) {
00953 ImageManager::instance()->free(it->image.get()->getName());
00954 }
00955 it = m_check_images.erase(it);
00956 } else {
00957 ++it;
00958 }
00959 }
00960
00961 if (m_check_images.empty() && m_timer_enabled) {
00962 m_timer_enabled = false;
00963 m_timer.stop();
00964 }
00965 }
00966
00967 void InstanceRenderer::removeFromCheck(const ImagePtr& image) {
00968 if (isValidImage(image)) {
00969
00970 ImagesToCheck_t::iterator it = m_check_images.begin();
00971 for (; it != m_check_images.end(); ++it) {
00972 if (it->image.get()->getName() == image.get()->getName()) {
00973 m_check_images.erase(it);
00974 break;
00975 }
00976 }
00977
00978 if (m_check_images.empty() && m_timer_enabled) {
00979 m_timer_enabled = false;
00980 m_timer.stop();
00981 }
00982 }
00983 }
00984
00985 void InstanceRenderer::removeInstance(Instance* instance) {
00986 InstanceToEffects_t::iterator it = m_assigned_instances.find(instance);
00987 if (it != m_assigned_instances.end()) {
00988 m_instance_outlines.erase(instance);
00989 m_instance_colorings.erase(instance);
00990 m_instance_areas.erase(instance);
00991 instance->removeDeleteListener(m_delete_listener);
00992 m_assigned_instances.erase(it);
00993 }
00994 }
00995
00996 bool InstanceRenderer::isValidImage(const ImagePtr& image) {
00997 if (image.get()) {
00998 if (image.get()->getState() == IResource::RES_LOADED) {
00999 return true;
01000 }
01001 }
01002 return false;
01003 }
01004 }