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
00031 #include "model/metamodel/grids/cellgrid.h"
00032 #include "model/metamodel/action.h"
00033 #include "model/metamodel/timeprovider.h"
00034 #include "model/structures/map.h"
00035 #include "model/structures/layer.h"
00036 #include "model/structures/instancetree.h"
00037 #include "model/structures/instance.h"
00038 #include "model/structures/location.h"
00039 #include "util/log/logger.h"
00040 #include "util/math/fife_math.h"
00041 #include "util/math/angles.h"
00042 #include "util/time/timemanager.h"
00043 #include "video/renderbackend.h"
00044 #include "video/image.h"
00045 #include "video/animation.h"
00046 #include "video/imagemanager.h"
00047
00048 #include "camera.h"
00049 #include "layercache.h"
00050 #include "visual.h"
00051
00052
00053 namespace FIFE {
00054 static Logger _log(LM_CAMERA);
00055
00056 class MapObserver : public MapChangeListener {
00057 Camera* m_camera;
00058
00059 public:
00060 MapObserver(Camera* camera) {
00061 m_camera = camera;
00062 }
00063 virtual ~MapObserver() {}
00064
00065 virtual void onMapChanged(Map* map, std::vector<Layer*>& changedLayers) {
00066 }
00067
00068 virtual void onLayerCreate(Map* map, Layer* layer) {
00069 m_camera->addLayer(layer);
00070 }
00071
00072 virtual void onLayerDelete(Map* map, Layer* layer) {
00073 m_camera->removeLayer(layer);
00074 }
00075 };
00076
00077 Camera::Camera(const std::string& id,
00078 Layer *layer,
00079 const Rect& viewport,
00080 RenderBackend* renderbackend):
00081 m_id(id),
00082 m_matrix(),
00083 m_inverse_matrix(),
00084 m_tilt(0),
00085 m_rotation(0),
00086 m_zoom(1),
00087 m_location(),
00088 m_cur_origo(ScreenPoint(0,0,0)),
00089 m_viewport(),
00090 m_screen_cell_width(1),
00091 m_screen_cell_height(1),
00092 m_reference_scale(1),
00093 m_enabled(true),
00094 m_attachedto(NULL),
00095 m_image_dimensions(),
00096 m_iswarped(false),
00097 m_renderers(),
00098 m_pipeline(),
00099 m_updated(false),
00100 m_renderbackend(renderbackend),
00101 m_layer_to_instances(),
00102 m_lighting(false),
00103 m_light_colors(),
00104 m_col_overlay(false),
00105 m_img_overlay(false),
00106 m_ani_overlay(false) {
00107 m_viewport = viewport;
00108 m_map_observer = new MapObserver(this);
00109 m_map = 0;
00110 Location location;
00111 location.setLayer(layer);
00112 setLocation(location);
00113 }
00114
00115 Camera::~Camera() {
00116
00117 updateMap(NULL);
00118
00119 std::map<std::string, RendererBase*>::iterator r_it = m_renderers.begin();
00120 for(; r_it != m_renderers.end(); ++r_it) {
00121 r_it->second->reset();
00122 delete r_it->second;
00123 }
00124 m_renderers.clear();
00125 delete m_map_observer;
00126 }
00127
00128 void Camera::setTilt(double tilt) {
00129 if (!Mathd::Equal(m_tilt, tilt)) {
00130 m_tilt = tilt;
00131 updateReferenceScale();
00132 updateMatrices();
00133 m_iswarped = true;
00134 }
00135 }
00136
00137 double Camera::getTilt() const {
00138 return m_tilt;
00139 }
00140
00141 void Camera::setRotation(double rotation) {
00142 if (!Mathd::Equal(m_rotation, rotation)) {
00143 m_rotation = rotation;
00144 updateReferenceScale();
00145 updateMatrices();
00146 m_iswarped = true;
00147 }
00148 }
00149
00150 double Camera::getRotation() const {
00151 return m_rotation;
00152 }
00153
00154 void Camera::setZoom(double zoom) {
00155 if (!Mathd::Equal(m_zoom, zoom)) {
00156 m_zoom = zoom;
00157 if (m_zoom < 0.001) {
00158 m_zoom = 0.001;
00159 }
00160 updateMatrices();
00161 m_updated = false;
00162 }
00163 }
00164
00165 double Camera::getZoom() const {
00166 return m_zoom;
00167 }
00168
00169 void Camera::setCellImageDimensions(uint32_t width, uint32_t height) {
00170 m_screen_cell_width = width;
00171 m_screen_cell_height = height;
00172 updateReferenceScale();
00173 updateMatrices();
00174 m_iswarped = true;
00175 }
00176
00177 void Camera::setLocation(const Location& location) {
00178 if (m_location == location ) {
00179 return;
00180 }
00181
00182 CellGrid* cell_grid = NULL;
00183 if (location.getLayer()) {
00184 cell_grid = location.getLayer()->getCellGrid();
00185 } else {
00186 throw Exception("Location without layer given to Camera::setLocation");
00187 }
00188 if (!cell_grid) {
00189 throw Exception("Camera layer has no cellgrid specified");
00190 }
00191
00192 m_location = location;
00193 updateMatrices();
00194
00195 ExactModelCoordinate emc = m_location.getMapCoordinates();
00196 m_cur_origo = toScreenCoordinates(emc);
00197
00198
00199
00200
00201
00202
00203 updateMap(m_location.getMap());
00204
00205 m_updated = false;
00206 }
00207
00208 void Camera::updateMap(Map* map) {
00209 if(m_map == map) {
00210 return;
00211 }
00212 if(m_map) {
00213 m_map->removeChangeListener(m_map_observer);
00214 const std::list<Layer*>& layers = m_map->getLayers();
00215 for(std::list<Layer*>::const_iterator i = layers.begin(); i !=layers.end(); ++i) {
00216 removeLayer(*i);
00217 }
00218 }
00219 if(map) {
00220 map->addChangeListener(m_map_observer);
00221 const std::list<Layer*>& layers = map->getLayers();
00222 for(std::list<Layer*>::const_iterator i = layers.begin(); i !=layers.end(); ++i) {
00223 addLayer(*i);
00224 }
00225 }
00226 m_map = map;
00227 }
00228
00229 Point Camera::getCellImageDimensions() {
00230 return getCellImageDimensions(m_location.getLayer());
00231 }
00232
00233 Point Camera::getCellImageDimensions(Layer* layer) {
00234 if (layer == m_location.getLayer()) {
00235 return Point( m_screen_cell_width, m_screen_cell_height );
00236 }
00237 std::map<Layer*, Point>::iterator it = m_image_dimensions.find(layer);
00238 if (it != m_image_dimensions.end()) {
00239 return it->second;
00240 }
00241 Point p;
00242 CellGrid* cg = layer->getCellGrid();
00243 assert(cg);
00244 DoublePoint dimensions = getLogicalCellDimensions(layer);
00245 p.x = static_cast<int32_t>(round(m_reference_scale * dimensions.x));
00246 p.y = static_cast<int32_t>(round(m_reference_scale * dimensions.y));
00247 m_image_dimensions[layer] = p;
00248 return p;
00249 }
00250
00251 Location Camera::getLocation() const {
00252 return m_location;
00253 }
00254
00255 Location& Camera::getLocationRef() {
00256 return m_location;
00257 }
00258
00259 void Camera::setViewPort(const Rect& viewport) {
00260 m_viewport = viewport;
00261 }
00262
00263 const Rect& Camera::getViewPort() const {
00264 return m_viewport;
00265 }
00266
00267 void Camera::setEnabled(bool enabled) {
00268 m_enabled = enabled;
00269 }
00270
00271 bool Camera::isEnabled() {
00272 return m_enabled;
00273 }
00274
00275 Point3D Camera::getOrigin() const {
00276 return m_cur_origo;
00277 }
00278
00279 void Camera::updateMatrices() {
00280 double scale = m_reference_scale;
00281 m_matrix.loadScale(scale, scale, scale);
00282 m_vs_matrix.loadScale(scale,scale,scale);
00283 if (m_location.getLayer()) {
00284 CellGrid* cg = m_location.getLayer()->getCellGrid();
00285 if (cg) {
00286 ExactModelCoordinate pt = m_location.getMapCoordinates();
00287 m_matrix.applyTranslate( -pt.x *m_reference_scale,-pt.y *m_reference_scale, -pt.z*m_reference_scale);
00288 }
00289 }
00290 scale = m_zoom;
00291 m_matrix.applyScale(scale, scale, scale);
00292 m_matrix.applyRotate(-m_rotation, 0.0, 0.0, 1.0);
00293 m_matrix.applyRotate(-m_tilt, 1.0, 0.0, 0.0);
00294 m_matrix.applyTranslate(+m_viewport.x+m_viewport.w/2, +m_viewport.y+m_viewport.h/2, 0);
00295 m_inverse_matrix = m_matrix.inverse();
00296
00297 m_vs_matrix.applyRotate(-m_rotation, 0.0, 0.0, 1.0);
00298 m_vs_matrix.applyRotate(-m_tilt, 1.0, 0.0, 0.0);
00299 m_vs_inverse_matrix = m_vs_matrix.inverse();
00300
00301
00302
00303 m_vscreen_2_screen = m_matrix;
00304
00305 m_vscreen_2_screen.mult4by4(m_vs_inverse_matrix);
00306
00307 const int32_t N=4;
00308 for(int32_t i=0; i!=N; ++i) {
00309 m_vscreen_2_screen[2*N + i] = 0;
00310 m_vscreen_2_screen[i*N + 2] = 0;
00311 }
00312 m_vscreen_2_screen[2*N + 2] = 1;
00313 m_screen_2_vscreen = m_vscreen_2_screen.inverse();
00314
00315
00316
00317 }
00318
00319 void Camera::calculateZValue(ScreenPoint& screen_coords) {
00320 int32_t dy = -(screen_coords.y - toScreenCoordinates(m_location.getMapCoordinates()).y);
00321 screen_coords.z = static_cast<int32_t>(Mathd::Tan(m_tilt * (Mathd::pi() / 180.0)) * static_cast<double>(dy));
00322 }
00323
00324 ExactModelCoordinate Camera::toMapCoordinates(ScreenPoint screen_coords, bool z_calculated) {
00325 if (!z_calculated) {
00326 calculateZValue(screen_coords);
00327 }
00328 return m_inverse_matrix * intPt2doublePt(screen_coords);
00329 }
00330
00331 ScreenPoint Camera::toScreenCoordinates(const ExactModelCoordinate& elevation_coords) {
00332 ScreenPoint pt = doublePt2intPt(m_matrix * elevation_coords);
00333 return pt;
00334 }
00335
00336 DoublePoint3D Camera::toVirtualScreenCoordinates(const ExactModelCoordinate& elevation_coords) {
00337 DoublePoint3D pt = (m_vs_matrix * elevation_coords);
00338 return pt;
00339 }
00340
00341 ScreenPoint Camera::virtualScreenToScreen(const DoublePoint3D& p) {
00342 return doublePt2intPt(m_vscreen_2_screen * p);
00343 }
00344
00345 DoublePoint3D Camera::screenToVirtualScreen(const ScreenPoint& p) {
00346 return m_screen_2_vscreen * intPt2doublePt(p);
00347 }
00348
00349 DoublePoint Camera::getLogicalCellDimensions(Layer* layer) {
00350 CellGrid* cg = NULL;
00351 if (layer) {
00352 cg = layer->getCellGrid();
00353 }
00354 assert(cg);
00355
00356 ModelCoordinate cell(0,0);
00357 std::vector<ExactModelCoordinate> vertices;
00358 cg->getVertices(vertices, cell);
00359
00360 DoubleMatrix mtx;
00361 mtx.loadRotate(m_rotation, 0.0, 0.0, 1.0);
00362 mtx.applyRotate(m_tilt, 1.0, 0.0, 0.0);
00363
00364 double x1 = 0;
00365 double x2 = 0;
00366 double y1 = 0;
00367 double y2 = 0;
00368
00369 for (uint32_t i = 0; i < vertices.size(); i++) {
00370 vertices[i] = cg->toMapCoordinates(vertices[i]);
00371 vertices[i] = mtx * vertices[i];
00372 if (i == 0) {
00373 x1 = x2 = vertices[0].x;
00374 y1 = y2 = vertices[0].y;
00375 } else {
00376 x1 = std::min(vertices[i].x, x1);
00377 x2 = std::max(vertices[i].x, x2);
00378 y1 = std::min(vertices[i].y, y1);
00379 y2 = std::max(vertices[i].y, y2);
00380 }
00381 }
00382 return DoublePoint( x2 - x1, y2 - y1 );
00383 }
00384
00385 Point Camera::getRealCellDimensions(Layer* layer) {
00386 CellGrid* cg = NULL;
00387 if (layer) {
00388 cg = layer->getCellGrid();
00389 }
00390 assert(cg);
00391
00392 Location loc(layer);
00393 ModelCoordinate cell(0,0);
00394 loc.setLayerCoordinates(cell);
00395 ScreenPoint sp1 = toScreenCoordinates(loc.getMapCoordinates());
00396 ++cell.y;
00397 loc.setLayerCoordinates(cell);
00398 ScreenPoint sp2 = toScreenCoordinates(loc.getMapCoordinates());
00399
00400 Point p(ABS(sp2.x - sp1.x), ABS(sp2.y - sp1.y));
00401 if (p.x == 0) {
00402 p.x = 1;
00403 }
00404 if (p.y == 0) {
00405 p.y = 1;
00406 }
00407 return p;
00408 }
00409
00410 Point3D Camera::getZOffset(Layer* layer) {
00411 CellGrid* cg = NULL;
00412 if (layer) {
00413 cg = layer->getCellGrid();
00414 }
00415 assert(cg);
00416
00417 Location loc(layer);
00418 ModelCoordinate cell(0,0,0);
00419 loc.setLayerCoordinates(cell);
00420 ScreenPoint sp1 = toScreenCoordinates(loc.getMapCoordinates());
00421 ++cell.z;
00422 loc.setLayerCoordinates(cell);
00423 ScreenPoint sp2 = toScreenCoordinates(loc.getMapCoordinates());
00424
00425 return Point3D(sp2.x - sp1.x, sp2.y - sp1.y, sp2.z - sp1.z);
00426 }
00427
00428 void Camera::updateReferenceScale() {
00429 DoublePoint dim = getLogicalCellDimensions(m_location.getLayer());
00430 m_reference_scale = static_cast<double>(m_screen_cell_width) / dim.x;
00431
00432 FL_DBG(_log, "Updating reference scale");
00433 FL_DBG(_log, LMsg(" tilt=") << m_tilt << " rot=" << m_rotation);
00434 FL_DBG(_log, LMsg(" m_screen_cell_width=") << m_screen_cell_width);
00435 }
00436
00437 void Camera::cacheUpdate(Layer* layer) {
00438 Map* map = m_location.getMap();
00439 if (!map) {
00440 FL_ERR(_log, "No map for camera found");
00441 return;
00442 }
00443
00444 if (m_iswarped || !m_updated) {
00445 updateRenderLists();
00446 } else {
00447 LayerCache* cache = m_cache[layer];
00448 if(!cache) {
00449 addLayer(layer);
00450 cache = m_cache[layer];
00451 FL_ERR(_log, LMsg("Layer Cache miss! (This shouldn't happen!)") << layer->getId());
00452 }
00453
00454 if (cache->needUpdate()) {
00455 Transform transform = NormalTransform;
00456 if (m_iswarped) {
00457 transform = WarpedTransform;
00458 }
00459 RenderList& instances_to_render = m_layer_to_instances[layer];
00460 cache->update(transform, instances_to_render);
00461 }
00462 }
00463 }
00464
00465 void Camera::getMatchingInstances(ScreenPoint screen_coords, Layer& layer, std::list<Instance*>& instances, uint8_t alpha) {
00466 instances.clear();
00467 bool zoomed = !Mathd::Equal(m_zoom, 1.0);
00468 bool special_alpha = alpha != 0;
00469 cacheUpdate(&layer);
00470 const RenderList& layer_instances = m_layer_to_instances[&layer];
00471 RenderList::const_iterator instance_it = layer_instances.end();
00472 while (instance_it != layer_instances.begin()) {
00473 --instance_it;
00474 Instance* i = (*instance_it)->instance;
00475 const RenderItem& vc = **instance_it;
00476 if ((vc.dimensions.contains(Point(screen_coords.x, screen_coords.y)))) {
00477 if(vc.image->isSharedImage()) {
00478 vc.image->forceLoadInternal();
00479 }
00480 uint8_t r, g, b, a = 0;
00481 int32_t x = screen_coords.x - vc.dimensions.x;
00482 int32_t y = screen_coords.y - vc.dimensions.y;
00483 if (zoomed) {
00484 double fx = static_cast<double>(x);
00485 double fy = static_cast<double>(y);
00486 double fow = static_cast<double>(vc.image->getWidth());
00487 double foh = static_cast<double>(vc.image->getHeight());
00488 double fsw = static_cast<double>(vc.dimensions.w);
00489 double fsh = static_cast<double>(vc.dimensions.h);
00490 x = static_cast<int32_t>(round(fx / fsw * fow));
00491 y = static_cast<int32_t>(round(fy / fsh * foh));
00492 }
00493 vc.image->getPixelRGBA(x, y, &r, &g, &b, &a);
00494
00495 if (a == 0 || (special_alpha && a < alpha)) {
00496 continue;
00497 }
00498 instances.push_back(i);
00499 }
00500 }
00501 }
00502
00503 void Camera::getMatchingInstances(Rect screen_rect, Layer& layer, std::list<Instance*>& instances, uint8_t alpha) {
00504 instances.clear();
00505 bool zoomed = !Mathd::Equal(m_zoom, 1.0);
00506 bool special_alpha = alpha != 0;
00507 cacheUpdate(&layer);
00508
00509 const RenderList& layer_instances = m_layer_to_instances[&layer];
00510 RenderList::const_iterator instance_it = layer_instances.end();
00511 while (instance_it != layer_instances.begin()) {
00512 --instance_it;
00513 Instance* i = (*instance_it)->instance;;
00514 const RenderItem& vc = **instance_it;
00515 if ((vc.dimensions.intersects(screen_rect))) {
00516 if(vc.image->isSharedImage()) {
00517 vc.image->forceLoadInternal();
00518 }
00519 uint8_t r, g, b, a = 0;
00520 for(int32_t xx = screen_rect.x; xx < screen_rect.x + screen_rect.w; xx++) {
00521 for(int32_t yy = screen_rect.y; yy < screen_rect.y + screen_rect.h; yy++) {
00522 if ((vc.dimensions.contains(Point(xx, yy)))) {
00523 int32_t x = xx - vc.dimensions.x;
00524 int32_t y = yy - vc.dimensions.y;
00525 if (zoomed) {
00526 double fx = static_cast<double>(x);
00527 double fy = static_cast<double>(y);
00528 double fow = static_cast<double>(vc.image->getWidth());
00529 double foh = static_cast<double>(vc.image->getHeight());
00530 double fsw = static_cast<double>(vc.dimensions.w);
00531 double fsh = static_cast<double>(vc.dimensions.h);
00532 x = static_cast<int32_t>(round(fx / fsw * fow));
00533 y = static_cast<int32_t>(round(fy / fsh * foh));
00534 }
00535 vc.image->getPixelRGBA(x, y, &r, &g, &b, &a);
00536
00537 if (a == 0 || (special_alpha && a < alpha)) {
00538 continue;
00539 }
00540
00541 instances.push_back(i);
00542 goto found_non_transparent_pixel;
00543 }
00544 }
00545 }
00546 found_non_transparent_pixel:;
00547 }
00548 }
00549 }
00550
00551 void Camera::getMatchingInstances(Location& loc, std::list<Instance*>& instances, bool use_exactcoordinates) {
00552 instances.clear();
00553 Layer* layer = loc.getLayer();
00554 if(!layer) {
00555 return;
00556 }
00557
00558 cacheUpdate(layer);
00559 const RenderList& layer_instances = m_layer_to_instances[layer];
00560 RenderList::const_iterator instance_it = layer_instances.end();
00561 while (instance_it != layer_instances.begin()) {
00562 --instance_it;
00563 Instance* i = (*instance_it)->instance;
00564 if (use_exactcoordinates) {
00565 if (i->getLocationRef().getExactLayerCoordinatesRef() == loc.getExactLayerCoordinatesRef()) {
00566 instances.push_back(i);
00567 }
00568 } else {
00569 if (i->getLocationRef().getLayerCoordinates() == loc.getLayerCoordinates()) {
00570 instances.push_back(i);
00571 }
00572 }
00573 }
00574 }
00575
00576 void Camera::attach(Instance *instance) {
00577
00578 if (m_location.getLayer()->getId() != instance->getLocation().getLayer()->getId()) {
00579 FL_WARN(_log, "Tried to attach camera to instance on different layer.");
00580 return ;
00581 }
00582 m_attachedto = instance;
00583 }
00584
00585 void Camera::detach() {
00586 m_attachedto = NULL;
00587 }
00588
00589 void Camera::update() {
00590 if( !m_attachedto ) {
00591 return;
00592 }
00593 Location loc(m_location);
00594 loc.setExactLayerCoordinates( m_attachedto->getLocationRef().getExactLayerCoordinates(m_location.getLayer()) );
00595 setLocation(loc);
00596 updateMatrices();
00597 }
00598
00599 void Camera::refresh() {
00600 updateMatrices();
00601 m_iswarped = true;
00602 }
00603
00604 void Camera::resetUpdates() {
00605 m_iswarped = false;
00606 m_updated = true;
00607 }
00608
00609 bool pipelineSort(const RendererBase* lhs, const RendererBase* rhs) {
00610 return (lhs->getPipelinePosition() < rhs->getPipelinePosition());
00611 }
00612
00613 void Camera::addRenderer(RendererBase* renderer) {
00614 renderer->setRendererListener(this);
00615 m_renderers[renderer->getName()] = renderer;
00616 if (renderer->isEnabled()) {
00617 m_pipeline.push_back(renderer);
00618 }
00619 m_pipeline.sort(pipelineSort);
00620 }
00621
00622 void Camera::onRendererPipelinePositionChanged(RendererBase* renderer) {
00623 m_pipeline.sort(pipelineSort);
00624 }
00625
00626 void Camera::onRendererEnabledChanged(RendererBase* renderer) {
00627 assert(m_renderers[renderer->getName()]);
00628 if (renderer->isEnabled()) {
00629 FL_LOG(_log, LMsg("Enabling renderer ") << renderer->getName());
00630 m_pipeline.push_back(renderer);
00631 m_pipeline.sort(pipelineSort);
00632 } else {
00633 m_pipeline.remove(renderer);
00634 }
00635 }
00636
00637 RendererBase* Camera::getRenderer(const std::string& name) {
00638 return m_renderers[name];
00639 }
00640
00641 void Camera::resetRenderers() {
00642 std::map<std::string, RendererBase*>::iterator r_it = m_renderers.begin();
00643 for (; r_it != m_renderers.end(); ++r_it) {
00644 r_it->second->reset();
00645 }
00646 }
00647
00648 void Camera::addLayer(Layer* layer) {
00649 m_cache[layer] = new LayerCache(this);
00650 m_cache[layer]->setLayer(layer);
00651 m_layer_to_instances[layer] = RenderList();
00652 }
00653
00654 void Camera::removeLayer(Layer* layer) {
00655 delete m_cache[layer];
00656 m_cache.erase(layer);
00657 m_layer_to_instances.erase(layer);
00658 }
00659
00660 void Camera::setLightingColor(float red, float green, float blue) {
00661 m_lighting = true;
00662 m_light_colors.clear();
00663 m_light_colors.push_back(red);
00664 m_light_colors.push_back(green);
00665 m_light_colors.push_back(blue);
00666 }
00667
00668 std::vector<float> Camera::getLightingColor() {
00669 if(m_light_colors.empty()) {
00670 for(int32_t colors = 0; colors != 3; ++colors) {
00671 m_light_colors.push_back(1.0f);
00672 }
00673 }
00674 return m_light_colors;
00675 }
00676
00677 void Camera::resetLightingColor() {
00678 m_lighting = false;
00679 m_renderbackend->resetLighting();
00680 }
00681
00682 void Camera::setOverlayColor(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha) {
00683 m_col_overlay = true;
00684 m_overlay_color.r = red;
00685 m_overlay_color.g = green;
00686 m_overlay_color.b = blue;
00687 m_overlay_color.unused = alpha;
00688 }
00689
00690 std::vector<uint8_t> Camera::getOverlayColor() {
00691 std::vector<uint8_t> colors;
00692 if (m_col_overlay) {
00693 colors.push_back(m_overlay_color.r);
00694 colors.push_back(m_overlay_color.g);
00695 colors.push_back(m_overlay_color.b);
00696 colors.push_back(m_overlay_color.unused);
00697 } else {
00698 for(uint8_t cc = 0; cc != 4; ++cc) {
00699 colors.push_back(255);
00700 }
00701 }
00702 return colors;
00703 }
00704
00705 void Camera::resetOverlayColor() {
00706 m_col_overlay = false;
00707 }
00708
00709 void Camera::setOverlayImage(int32_t id, bool fill) {
00710 m_img_overlay = true;
00711 m_img_id = id;
00712 m_img_fill = fill;
00713 }
00714
00715 int32_t Camera::getOverlayImage() {
00716 int32_t id = -1;
00717 if (m_img_overlay) {
00718 id = m_img_id;
00719 }
00720 return id;
00721 }
00722
00723 void Camera::resetOverlayImage() {
00724 m_img_overlay = false;
00725 m_img_id = -1;
00726 }
00727
00728 void Camera::setOverlayAnimation(AnimationPtr anim, bool fill) {
00729 m_ani_overlay = true;
00730 m_ani_ptr = anim;
00731 m_ani_fill = fill;
00732 m_start_time = 0;
00733 }
00734
00735 AnimationPtr Camera::getOverlayAnimation() {
00736 return m_ani_ptr;
00737 }
00738
00739 void Camera::resetOverlayAnimation() {
00740 m_ani_overlay = false;
00741 m_ani_ptr.reset();
00742 }
00743
00744 void Camera::renderOverlay() {
00745 if (!m_col_overlay && !m_img_overlay && !m_ani_overlay) {
00746 return;
00747 }
00748 uint16_t width = m_viewport.w;
00749 uint16_t height = m_viewport.h;
00750 Point pm = Point(m_viewport.x + width/2, m_viewport.y + height/2);
00751 Rect r;
00752
00753
00754 if (m_col_overlay) {
00755 Point p = Point(m_viewport.x, m_viewport.y);
00756 m_renderbackend->fillRectangle(p, width, height, m_overlay_color.r, m_overlay_color.g, m_overlay_color.b, m_overlay_color.unused);
00757 }
00758
00759 if (m_img_overlay) {
00760 ImagePtr resptr = ImageManager::instance()->get(m_img_id);
00761 Image* img = resptr.get();
00762 if (img) {
00763 if (m_img_fill) {
00764 r.w = width;
00765 r.h = height;
00766 } else {
00767 r.w = img->getWidth();
00768 r.h = img->getHeight();
00769 }
00770 r.x = pm.x-r.w/2;
00771 r.y = pm.y-r.h/2;
00772 img->render(r);
00773 }
00774 }
00775
00776 if (m_ani_overlay) {
00777 assert(m_ani_ptr != 0);
00778
00779 if (m_start_time == 0) {
00780 m_start_time = TimeManager::instance()->getTime();
00781 }
00782 uint32_t animtime = scaleTime(1.0, TimeManager::instance()->getTime() - m_start_time) % m_ani_ptr->getDuration();
00783 ImagePtr img = m_ani_ptr->getFrameByTimestamp(animtime);
00784 if (img) {
00785 if (m_ani_fill) {
00786 r.w = width;
00787 r.h = height;
00788 } else {
00789 r.w = img->getWidth();
00790 r.h = img->getHeight();
00791 }
00792 r.x = pm.x-r.w/2;
00793 r.y = pm.y-r.h/2;
00794 img->render(r);
00795 }
00796 }
00797 }
00798
00799 void Camera::updateRenderLists() {
00800 Map* map = m_location.getMap();
00801 if (!map) {
00802 FL_ERR(_log, "No map for camera found");
00803 return;
00804 }
00805
00806 Transform transform = NormalTransform;
00807 if (m_iswarped) {
00808 transform = WarpedTransform;
00809 }
00810 const std::list<Layer*>& layers = map->getLayers();
00811 std::list<Layer*>::const_iterator layer_it = layers.begin();
00812 for (;layer_it != layers.end(); ++layer_it) {
00813 LayerCache* cache = m_cache[*layer_it];
00814 if(!cache) {
00815 addLayer(*layer_it);
00816 cache = m_cache[*layer_it];
00817 FL_ERR(_log, LMsg("Layer Cache miss! (This shouldn't happen!)") << (*layer_it)->getId());
00818 }
00819 RenderList& instances_to_render = m_layer_to_instances[*layer_it];
00820 if (m_iswarped || !m_updated || cache->needUpdate()) {
00821 cache->update(transform, instances_to_render);
00822 }
00823 }
00824 resetUpdates();
00825 }
00826
00827 void Camera::render() {
00828 static bool renderbackendOpenGLe = (m_renderbackend->getName() == "OpenGLe");
00829 updateRenderLists();
00830 Map* map = m_location.getMap();
00831 if (!map) {
00832 return;
00833 }
00834
00835 uint32_t lm = m_renderbackend->getLightingModel();
00836 if (lm != 0) {
00837 m_renderbackend->resetStencilBuffer(0);
00838 if (m_lighting) {
00839 m_renderbackend->setLighting(m_light_colors[0], m_light_colors[1], m_light_colors[2]);
00840 }
00841 }
00842
00843 m_renderbackend->pushClipArea(getViewPort());
00844
00845 const std::list<Layer*>& layers = map->getLayers();
00846 std::list<Layer*>::const_iterator layer_it = layers.begin();
00847 for ( ; layer_it != layers.end(); ++layer_it) {
00848 RenderList& instances_to_render = m_layer_to_instances[*layer_it];
00849 std::list<RendererBase*>::iterator r_it = m_pipeline.begin();
00850 for (; r_it != m_pipeline.end(); ++r_it) {
00851 if ((*r_it)->isActivedLayer(*layer_it)) {
00852 (*r_it)->render(this, *layer_it, instances_to_render);
00853 }
00854 }
00855 if (renderbackendOpenGLe) {
00856 m_renderbackend->renderVertexArrays();
00857 }
00858 }
00859
00860 renderOverlay();
00861 m_renderbackend->renderVertexArrays();
00862 if (m_lighting && lm != 0) {
00863 m_renderbackend->resetLighting();
00864 }
00865 m_renderbackend->popClipArea();
00866 }
00867 }