diff --git a/engine/core/view/camera.cpp b/engine/core/view/camera.cpp index 88155b776..8560a07e8 100644 --- a/engine/core/view/camera.cpp +++ b/engine/core/view/camera.cpp @@ -745,10 +745,12 @@ namespace FIFE { m_cache[layer] = new LayerCache(this); m_cache[layer]->setLayer(layer); m_layerToInstances[layer] = RenderList(); + m_cacheUpdates[m_cache[layer]] = true; refresh(); } void Camera::removeLayer(Layer* layer) { + m_cacheUpdates.erase(m_cache[layer]); delete m_cache[layer]; m_cache.erase(layer); m_layerToInstances.erase(layer); @@ -970,7 +972,8 @@ namespace FIFE { if ((*layer_it)->isStatic() && m_transform == NoneTransform) { continue; } - cache->update(m_transform, instancesToRender); + bool update = cache->update(m_transform, instancesToRender); + m_cacheUpdates[cache] = update; } resetUpdates(); } @@ -1045,4 +1048,9 @@ namespace FIFE { } m_renderbackend->popClipArea(); } + + bool Camera::isLayerCacheUpdated(Layer* layer) { + bool update = m_cacheUpdates[m_cache[layer]]; + return update; + } } diff --git a/engine/core/view/camera.h b/engine/core/view/camera.h index 5592d2f66..e7a713411 100644 --- a/engine/core/view/camera.h +++ b/engine/core/view/camera.h @@ -407,6 +407,8 @@ namespace FIFE { */ void render(); + bool isLayerCacheUpdated(Layer* layer); + private: friend class MapObserver; void addLayer(Layer* layer); @@ -493,6 +495,7 @@ namespace FIFE { t_layer_to_instances m_layerToInstances; std::map m_cache; + std::map m_cacheUpdates; MapObserver* m_map_observer; // is lighting enable diff --git a/engine/core/view/layercache.cpp b/engine/core/view/layercache.cpp index f1e8377b3..2f68d57bc 100644 --- a/engine/core/view/layercache.cpp +++ b/engine/core/view/layercache.cpp @@ -366,7 +366,7 @@ namespace FIFE { } } - void LayerCache::update(Camera::Transform transform, RenderList& renderlist) { + bool LayerCache::update(Camera::Transform transform, RenderList& renderlist) { // this is only a bit faster, but works without this block too. if(!m_layer->areInstancesVisible()) { FL_DBG(_log, "Layer instances hidden"); @@ -378,13 +378,13 @@ namespace FIFE { } m_entriesToUpdate.clear(); renderlist.clear(); - return; + return true; } // if transform is none then we have only to update the instances with an update info. if (transform == Camera::NoneTransform) { if (!m_entriesToUpdate.empty()) { std::set entryToRemove; - updateEntries(entryToRemove, renderlist); + bool update = updateEntries(entryToRemove, renderlist); //std::cout << "update entries: " << int32_t(m_entriesToUpdate.size()) << " remove entries: " << int32_t(entryToRemove.size()) <<"\n"; if (!entryToRemove.empty()) { std::set::iterator entry_it = entryToRemove.begin(); @@ -392,7 +392,9 @@ namespace FIFE { m_entriesToUpdate.erase(*entry_it); } } + return update; } + return false; } else { m_zoom = m_camera->getZoom(); m_zoomed = !Mathd::Equal(m_zoom, 1.0); @@ -455,6 +457,7 @@ namespace FIFE { sortRenderList(renderlist); } } + return true; } void LayerCache::fullUpdate(Camera::Transform transform) { @@ -500,7 +503,8 @@ namespace FIFE { } } - void LayerCache::updateEntries(std::set& removes, RenderList& renderlist) { + bool LayerCache::updateEntries(std::set& removes, RenderList& renderlist) { + bool update = false; RenderList needSorting; Rect viewport = m_camera->getViewPort(); std::set::const_iterator entry_it = m_entriesToUpdate.begin(); @@ -531,6 +535,7 @@ namespace FIFE { // remove from renderlist for (RenderList::iterator it = renderlist.begin(); it != renderlist.end(); ++it) { if ((*it)->instance == item->instance) { + update = true; renderlist.erase(it); break; } @@ -551,12 +556,14 @@ namespace FIFE { } if (!needSorting.empty()) { + update = true; if (m_needSorting) { sortRenderList(renderlist); } else { sortRenderList(needSorting); } } + return update; } bool LayerCache::updateVisual(Entry* entry) { diff --git a/engine/core/view/layercache.h b/engine/core/view/layercache.h index 8df613cc9..35f45ff31 100644 --- a/engine/core/view/layercache.h +++ b/engine/core/view/layercache.h @@ -55,7 +55,7 @@ namespace FIFE { void setLayer(Layer* layer); - void update(Camera::Transform transform, RenderList& renderlist); + bool update(Camera::Transform transform, RenderList& renderlist); void addInstance(Instance* instance); void removeInstance(Instance* instance); @@ -92,7 +92,7 @@ namespace FIFE { void reset(); void fullUpdate(Camera::Transform transform); void fullCoordinateUpdate(Camera::Transform transform); - void updateEntries(std::set& removes, RenderList& renderlist); + bool updateEntries(std::set& removes, RenderList& renderlist); bool updateVisual(Entry* entry); void updatePosition(Entry* entry); void updateScreenCoordinate(RenderItem* item, bool changedZoom = true); diff --git a/engine/core/view/rendererbase.h b/engine/core/view/rendererbase.h index 9b5c84f98..0810f8a7e 100644 --- a/engine/core/view/rendererbase.h +++ b/engine/core/view/rendererbase.h @@ -141,19 +141,19 @@ namespace FIFE { /** Adds active layer to renderer. Only active layers are rendered */ - void addActiveLayer(Layer* layer); + virtual void addActiveLayer(Layer* layer); /** Removes active layer from renderer. */ - void removeActiveLayer(Layer* layer); + virtual void removeActiveLayer(Layer* layer); /** Clears all active layers from renderer */ - void clearActiveLayers(); + virtual void clearActiveLayers(); /** Activates all layers from given elevation */ - void activateAllLayers(Map* elevation); + virtual void activateAllLayers(Map* elevation); /** Returns if given layer is currently activated */ diff --git a/engine/core/view/renderers/blockinginforenderer.cpp b/engine/core/view/renderers/blockinginforenderer.cpp index 81a6fda18..ddad2ad18 100644 --- a/engine/core/view/renderers/blockinginforenderer.cpp +++ b/engine/core/view/renderers/blockinginforenderer.cpp @@ -72,6 +72,26 @@ namespace FIFE { return dynamic_cast(cnt->getRenderer("BlockingInfoRenderer")); } + void BlockingInfoRenderer::setEnabled(bool enabled) { + RendererBase::setEnabled(enabled); + if (!enabled) { + m_bufferMap.clear(); + } + } + + void BlockingInfoRenderer::removeActiveLayer(Layer* layer) { + RendererBase::removeActiveLayer(layer); + std::map >::iterator it = m_bufferMap.find(layer); + if (it != m_bufferMap.end()) { + m_bufferMap.erase(it); + } + } + + void BlockingInfoRenderer::clearActiveLayers() { + RendererBase::clearActiveLayers(); + m_bufferMap.clear(); + } + void BlockingInfoRenderer::render(Camera* cam, Layer* layer, RenderList& instances) { CellGrid* cg = layer->getCellGrid(); if (!cg) { @@ -79,49 +99,45 @@ namespace FIFE { return; } - Rect cv = cam->getViewPort(); + // Only render if nothing has changed. + if (!cam->isUpdated() && !cam->isLayerCacheUpdated(layer)) { + if (m_bufferMap.find(layer) != m_bufferMap.end()) { + renderBuffer(layer); + return; + } + } + + std::vector& data = m_bufferMap[layer]; + // clear buffer + data.clear(); CellCache* cache = layer->getCellCache(); if (cache) { - const std::vector >& cells = cache->getCells(); - std::vector >::const_iterator it = cells.begin(); - for (; it != cells.end(); ++it) { - std::vector::const_iterator cit = (*it).begin(); - for (; cit != (*it).end(); ++cit) { - ExactModelCoordinate emc = FIFE::intPt2doublePt((*cit)->getLayerCoordinates()); - ScreenPoint sp = cam->toScreenCoordinates(cg->toMapCoordinates(emc)); - // if it is not in cameras view continue - if (sp.x < cv.x || sp.x > cv.x + cv.w || - sp.y < cv.y || sp.y > cv.y + cv.h) { - continue; - } - if ((*cit)->getCellType() != CTYPE_NO_BLOCKER) { - std::vector vertices; - cg->getVertices(vertices, (*cit)->getLayerCoordinates()); - std::vector::const_iterator it = vertices.begin(); - int32_t halfind = vertices.size() / 2; - ScreenPoint firstpt = cam->toScreenCoordinates(cg->toMapCoordinates(*it)); - Point pt1(firstpt.x, firstpt.y); - Point pt2; - ++it; - for (; it != vertices.end(); it++) { - ScreenPoint pts = cam->toScreenCoordinates(cg->toMapCoordinates(*it)); - pt2.x = pts.x; - pt2.y = pts.y; - m_renderbackend->drawLine(pt1, pt2, m_color.r, m_color.g, m_color.b); - pt1 = pt2; - } - m_renderbackend->drawLine(pt2, Point(firstpt.x, firstpt.y), m_color.r, m_color.g, m_color.b); - ScreenPoint spt1 = cam->toScreenCoordinates(cg->toMapCoordinates(vertices[0])); - Point pt3(spt1.x, spt1.y); - ScreenPoint spt2 = cam->toScreenCoordinates(cg->toMapCoordinates(vertices[halfind])); - Point pt4(spt2.x, spt2.y); - m_renderbackend->drawLine(pt3, pt4, m_color.r, m_color.g, m_color.b); - } + // fill buffer with cell data + Rect layerView = cam->getLayerViewPort(layer); + std::vector cells = cache->getCellsInRect(layerView); + std::vector::iterator cit = cells.begin(); + for (; cit != cells.end(); ++cit) { + if ((*cit)->getCellType() == CTYPE_NO_BLOCKER) { + continue; + } + std::vector vertices; + cg->getVertices(vertices, (*cit)->getLayerCoordinates()); + std::vector::const_iterator it = vertices.begin(); + ScreenPoint firstpt = cam->toScreenCoordinates(cg->toMapCoordinates(*it)); + Point pt(firstpt.x, firstpt.y); + data.push_back(pt); + ++it; + for (; it != vertices.end(); ++it) { + ScreenPoint pts = cam->toScreenCoordinates(cg->toMapCoordinates(*it)); + pt.x = pts.x; + pt.y = pts.y; + data.push_back(pt); } } } else { + // fill buffer with instance data RenderList::const_iterator instance_it = instances.begin(); - for (;instance_it != instances.end(); ++instance_it) { + for (; instance_it != instances.end(); ++instance_it) { Instance* instance = (*instance_it)->instance; if (!instance->getObject()->isBlocking() || !instance->isBlocking()) { continue; @@ -129,26 +145,20 @@ namespace FIFE { std::vector vertices; cg->getVertices(vertices, instance->getLocationRef().getLayerCoordinates()); std::vector::const_iterator it = vertices.begin(); - int32_t halfind = vertices.size() / 2; ScreenPoint firstpt = cam->toScreenCoordinates(cg->toMapCoordinates(*it)); - Point pt1(firstpt.x, firstpt.y); - Point pt2; + Point pt(firstpt.x, firstpt.y); + data.push_back(pt); ++it; - for (; it != vertices.end(); it++) { + for (; it != vertices.end(); ++it) { ScreenPoint pts = cam->toScreenCoordinates(cg->toMapCoordinates(*it)); - pt2.x = pts.x; - pt2.y = pts.y; - m_renderbackend->drawLine(pt1, pt2, m_color.r, m_color.g, m_color.b); - pt1 = pt2; + pt.x = pts.x; + pt.y = pts.y; + data.push_back(pt); } - m_renderbackend->drawLine(pt2, Point(firstpt.x, firstpt.y), m_color.r, m_color.g, m_color.b); - ScreenPoint spt1 = cam->toScreenCoordinates(cg->toMapCoordinates(vertices[0])); - Point pt3(spt1.x, spt1.y); - ScreenPoint spt2 = cam->toScreenCoordinates(cg->toMapCoordinates(vertices[halfind])); - Point pt4(spt2.x, spt2.y); - m_renderbackend->drawLine(pt3, pt4, m_color.r, m_color.g, m_color.b); } } + // render + renderBuffer(layer); } void BlockingInfoRenderer::setColor(uint8_t r, uint8_t g, uint8_t b) { @@ -156,4 +166,34 @@ namespace FIFE { m_color.g = g; m_color.b = b; } + + void BlockingInfoRenderer::renderBuffer(Layer* layer) { + std::vector& data = m_bufferMap[layer]; + uint32_t index = 0; + uint32_t indexEnd = data.size(); + if (layer->getCellGrid()->getType() == "square") { + while (index != indexEnd) { + m_renderbackend->drawLine(data[index], data[index + 1], m_color.r, m_color.g, m_color.b); + m_renderbackend->drawLine(data[index + 1], data[index + 2], m_color.r, m_color.g, m_color.b); + m_renderbackend->drawLine(data[index + 2], data[index + 3], m_color.r, m_color.g, m_color.b); + m_renderbackend->drawLine(data[index + 3], data[index], m_color.r, m_color.g, m_color.b); + + m_renderbackend->drawLine(data[index], data[index + 2], m_color.r, m_color.g, m_color.b); + index += 4; + } + } + else { + while (index != indexEnd) { + m_renderbackend->drawLine(data[index], data[index + 1], m_color.r, m_color.g, m_color.b); + m_renderbackend->drawLine(data[index + 1], data[index + 2], m_color.r, m_color.g, m_color.b); + m_renderbackend->drawLine(data[index + 2], data[index + 3], m_color.r, m_color.g, m_color.b); + m_renderbackend->drawLine(data[index + 3], data[index + 4], m_color.r, m_color.g, m_color.b); + m_renderbackend->drawLine(data[index + 4], data[index + 5], m_color.r, m_color.g, m_color.b); + m_renderbackend->drawLine(data[index + 5], data[index], m_color.r, m_color.g, m_color.b); + + m_renderbackend->drawLine(data[index], data[index + 3], m_color.r, m_color.g, m_color.b); + index += 6; + } + } + } } diff --git a/engine/core/view/renderers/blockinginforenderer.h b/engine/core/view/renderers/blockinginforenderer.h index 27bf017f3..ea24b2151 100644 --- a/engine/core/view/renderers/blockinginforenderer.h +++ b/engine/core/view/renderers/blockinginforenderer.h @@ -63,7 +63,7 @@ namespace FIFE { */ std::string getName() { return "BlockingInfoRenderer"; } - /** This method is called by the view to ask renderer to draw its rendering aspect based on + /** This method is called by the camera to ask renderer to draw its rendering aspect based on * given parameters. * * @param cam Camera view to draw @@ -84,7 +84,27 @@ namespace FIFE { */ static BlockingInfoRenderer* getInstance(IRendererContainer* cnt); + /** Enables renderer + */ + void setEnabled(bool enabled); + + /** Removes active layer from renderer. + * + * @param layer The layer to be removed. + */ + void removeActiveLayer(Layer* layer); + + /** Clears all active layers from renderer + */ + void clearActiveLayers(); + private: + /** Sends the buffered data to the backend. + */ + void renderBuffer(Layer* layer); + + //! Buffers the lines per Layer. + std::map > m_bufferMap; //! currently used color SDL_Color m_color; }; diff --git a/engine/core/view/renderers/cellrenderer.cpp b/engine/core/view/renderers/cellrenderer.cpp index e2724b665..96930fec5 100644 --- a/engine/core/view/renderers/cellrenderer.cpp +++ b/engine/core/view/renderers/cellrenderer.cpp @@ -49,17 +49,10 @@ namespace FIFE { static Logger _log(LM_VIEWVIEW); CellRenderer::CellRenderer(RenderBackend* renderbackend, int32_t position): - RendererBase(renderbackend, position) { + RendererBase(renderbackend, position), + m_costsUpdate(false) { setEnabled(false); - m_blockerColor.r = 255; - m_blockerColor.g = 0; - m_blockerColor.b = 0; - m_pathColor.r = 0; - m_pathColor.g = 0; - m_pathColor.b = 255; - m_blockingEnabled = false; m_fowEnabled = false; - m_pathVisualEnabled = false; m_targetRenderer = m_renderbackend->isFramebufferEnabled() ? new TargetRenderer(m_renderbackend) : NULL; m_fowLayer = NULL; m_font = NULL; @@ -68,12 +61,9 @@ namespace FIFE { CellRenderer::CellRenderer(const CellRenderer& old): RendererBase(old), - m_blockerColor(old.m_blockerColor), - m_pathColor(old.m_pathColor){ + m_costsUpdate(false) { setEnabled(false); - m_blockingEnabled = false; m_fowEnabled = false; - m_pathVisualEnabled = false; m_targetRenderer = m_renderbackend->isFramebufferEnabled() ? new TargetRenderer(m_renderbackend) : NULL; m_fowLayer = NULL; m_font = NULL; @@ -108,137 +98,21 @@ namespace FIFE { } const bool fow = m_fowEnabled && (m_fowLayer == layer); - bool fow_update = fow && (cam->isUpdated() || cache->isUpdated()); + const bool fow_update = fow && (cam->isUpdated() || cache->isUpdated()); if (!m_fowImage.get() && fow) { createFowMap(cam, layer); } - const bool render_costs = (!m_visualCosts.empty() && m_font); - const bool zoomed = !Mathd::Equal(1.0, cam->getZoom()); - - Rect layerView = cam->getLayerViewPort(layer); - std::vector cells = cache->getCellsInRect(layerView); - std::vector::iterator cit = cells.begin(); - for (; cit != cells.end(); ++cit) { - if (m_blockingEnabled) { - if ((*cit)->getCellType() != CTYPE_NO_BLOCKER) { - std::vector vertices; - cg->getVertices(vertices, (*cit)->getLayerCoordinates()); - std::vector::const_iterator it = vertices.begin(); - int32_t halfind = vertices.size() / 2; - ScreenPoint firstpt = cam->toScreenCoordinates(cg->toMapCoordinates(*it)); - Point pt1(firstpt.x, firstpt.y); - Point pt2; - ++it; - for (; it != vertices.end(); it++) { - ScreenPoint pts = cam->toScreenCoordinates(cg->toMapCoordinates(*it)); - pt2.x = pts.x; - pt2.y = pts.y; - m_renderbackend->drawLine(pt1, pt2, m_blockerColor.r, m_blockerColor.g, m_blockerColor.b); - pt1 = pt2; - } - m_renderbackend->drawLine(pt2, Point(firstpt.x, firstpt.y), m_blockerColor.r, m_blockerColor.g, m_blockerColor.b); - ScreenPoint spt1 = cam->toScreenCoordinates(cg->toMapCoordinates(vertices[0])); - Point pt3(spt1.x, spt1.y); - ScreenPoint spt2 = cam->toScreenCoordinates(cg->toMapCoordinates(vertices[halfind])); - Point pt4(spt2.x, spt2.y); - m_renderbackend->drawLine(pt3, pt4, m_blockerColor.r, m_blockerColor.g, m_blockerColor.b); - } - } - - if (render_costs) { - bool match = false; - double cost; - std::set::iterator cost_it = m_visualCosts.begin(); - for (; cost_it != m_visualCosts.end(); ++cost_it) { - std::vector cell_costs = cache->getCellCosts(*cit); - std::vector::iterator cc_it = cell_costs.begin(); - for (; cc_it != cell_costs.end(); ++cc_it) { - if (*cc_it == *cost_it) { - match = true; - cost = cache->getCost(*cost_it); - break; - } - } - if (match) { - break; - } - } - if (match) { - Location loc(layer); - loc.setLayerCoordinates((*cit)->getLayerCoordinates()); - ScreenPoint drawpt = cam->toScreenCoordinates(loc.getMapCoordinates()); - - std::stringstream stream; - stream << cost; - Image* img = m_font->getAsImage(stream.str()); - - Rect r; - if (zoomed) { - double zoom = cam->getZoom(); - r.x = drawpt.x - (img->getWidth()/2) * zoom; - r.y = drawpt.y - (img->getHeight()/2) * zoom; - r.w = img->getWidth() * zoom; - r.h = img->getHeight() * zoom; - img->render(r); - } else { - r.x = drawpt.x - img->getWidth()/2; - r.y = drawpt.y - img->getHeight()/2; - r.w = img->getWidth(); - r.h = img->getHeight(); - img->render(r); - } - } - } - - if (fow_update || (fow && !m_targetRenderer)) { - ScreenPoint sp = cam->toScreenCoordinates(cg->toMapCoordinates( - FIFE::intPt2doublePt((*cit)->getLayerCoordinates()))); - CellVisualEffect cve = (*cit)->getFoWType(); - if (cve == CELLV_CONCEALED) { - if (m_concealImage.get()) { - addImageToMap(cam, Point(sp.x, sp.y), m_concealImage, "c_img"); - } - } else if (cve == CELLV_MASKED) { - if (m_maskImage.get()) { - addImageToMap(cam, Point(sp.x, sp.y), m_maskImage, "b_img"); - } - } + if (render_costs) { + if (cam->isUpdated() || m_costsUpdate) { + updateCellCosts(cam, layer); + m_costsUpdate = false; } + renderBuffer(layer); } - if (m_pathVisualEnabled && !m_visualPaths.empty()) { - std::vector::iterator it = m_visualPaths.begin(); - for (; it != m_visualPaths.end(); ++it) { - Route* route = (*it)->getRoute(); - if (route) { - Path path = route->getPath(); - if (!path.empty()) { - Path::iterator pit = path.begin(); - for (; pit != path.end(); ++pit) { - if ((*pit).getLayer() != layer) { - continue; - } - std::vector vertices; - cg->getVertices(vertices, (*pit).getLayerCoordinates()); - std::vector::const_iterator it = vertices.begin(); - int32_t halfind = vertices.size() / 2; - ScreenPoint firstpt = cam->toScreenCoordinates(cg->toMapCoordinates(*it)); - Point pt1(firstpt.x, firstpt.y); - Point pt2; - ++it; - for (; it != vertices.end(); it++) { - ScreenPoint pts = cam->toScreenCoordinates(cg->toMapCoordinates(*it)); - pt2.x = pts.x; - pt2.y = pts.y; - m_renderbackend->drawLine(pt1, pt2, m_pathColor.r, m_pathColor.g, m_pathColor.b); - pt1 = pt2; - } - m_renderbackend->drawLine(pt2, Point(firstpt.x, firstpt.y), m_pathColor.r, m_pathColor.g, m_pathColor.b); - } - } - } - } + if (fow_update || (fow && !m_targetRenderer)) { + updateFoW(cam, layer); } if (fow && m_targetRenderer) { @@ -249,29 +123,9 @@ namespace FIFE { } } - void CellRenderer::setBlockerColor(uint8_t r, uint8_t g, uint8_t b) { - m_blockerColor.r = r; - m_blockerColor.g = g; - m_blockerColor.b = b; - } - - void CellRenderer::setPathColor(uint8_t r, uint8_t g, uint8_t b) { - m_pathColor.r = r; - m_pathColor.g = g; - m_pathColor.b = b; - } - void CellRenderer::setFogOfWarLayer(Layer* layer) { m_fowLayer = layer; } - - void CellRenderer::setEnabledBlocking(bool enabled) { - m_blockingEnabled = enabled; - } - - bool CellRenderer::isEnabledBlocking() { - return m_blockingEnabled; - } void CellRenderer::setEnabledFogOfWar(bool enabled) { m_fowEnabled = enabled; @@ -281,14 +135,6 @@ namespace FIFE { return m_fowEnabled; } - void CellRenderer::setEnabledPathVisual(bool enabled) { - m_pathVisualEnabled = enabled; - } - - bool CellRenderer::isEnabledPathVisual() { - return m_pathVisualEnabled; - } - void CellRenderer::createFowMap(Camera* cam, Layer* layer) { if (!m_targetRenderer) { return; @@ -343,6 +189,7 @@ namespace FIFE { void CellRenderer::setFont(IFont* font) { m_font = font; + m_costsUpdate = true; } IFont* CellRenderer::getFont() { @@ -356,27 +203,13 @@ namespace FIFE { m_fowTarget->removeAll("c_img"); } - void CellRenderer::addPathVisual(Instance* instance) { - m_visualPaths.push_back(instance); - } - - void CellRenderer::removePathVisual(Instance* instance) { - for (std::vector::iterator it = m_visualPaths.begin(); - it != m_visualPaths.end(); ++it) { - - if (*it == instance) { - m_visualPaths.erase(it); - break; - } - } - } - void CellRenderer::setEnabledCost(const std::string& costId, bool enabled) { if (enabled) { m_visualCosts.insert(costId); } else { m_visualCosts.erase(costId); } + m_costsUpdate = true; } bool CellRenderer::isEnabledCost(const std::string& costId) { @@ -386,4 +219,90 @@ namespace FIFE { } return false; } + + void CellRenderer::updateFoW(Camera* cam, Layer* layer) { + CellGrid* cg = layer->getCellGrid(); + CellCache* cache = layer->getCellCache(); + Rect layerView = cam->getLayerViewPort(layer); + std::vector cells = cache->getCellsInRect(layerView); + std::vector::iterator cit = cells.begin(); + for (; cit != cells.end(); ++cit) { + ScreenPoint sp = cam->toScreenCoordinates(cg->toMapCoordinates( + FIFE::intPt2doublePt((*cit)->getLayerCoordinates()))); + CellVisualEffect cve = (*cit)->getFoWType(); + if (cve == CELLV_CONCEALED) { + if (m_concealImage.get()) { + addImageToMap(cam, Point(sp.x, sp.y), m_concealImage, "c_img"); + } + } else if (cve == CELLV_MASKED) { + if (m_maskImage.get()) { + addImageToMap(cam, Point(sp.x, sp.y), m_maskImage, "b_img"); + } + } + } + } + + void CellRenderer::updateCellCosts(Camera* cam, Layer* layer) { + const bool zoomed = !Mathd::Equal(1.0, cam->getZoom()); + const double zoom = cam->getZoom(); + // clear old data + std::vector& data = m_bufferMap[layer]; + data.clear(); + Data dat; + + Rect layerView = cam->getLayerViewPort(layer); + CellCache* cache = layer->getCellCache(); + std::vector cells = cache->getCellsInRect(layerView); + std::vector::iterator cit = cells.begin(); + for (; cit != cells.end(); ++cit) { + bool match = false; + double cost; + std::set::iterator cost_it = m_visualCosts.begin(); + for (; cost_it != m_visualCosts.end(); ++cost_it) { + std::vector cell_costs = cache->getCellCosts(*cit); + std::vector::iterator cc_it = cell_costs.begin(); + for (; cc_it != cell_costs.end(); ++cc_it) { + if (*cc_it == *cost_it) { + match = true; + cost = cache->getCost(*cost_it); + break; + } + } + if (match) { + break; + } + } + if (match) { + Location loc(layer); + loc.setLayerCoordinates((*cit)->getLayerCoordinates()); + ScreenPoint drawpt = cam->toScreenCoordinates(loc.getMapCoordinates()); + + std::stringstream stream; + stream << cost; + Image* img = m_font->getAsImage(stream.str()); + + if (zoomed) { + dat.rect.x = drawpt.x - (img->getWidth() / 2) * zoom; + dat.rect.y = drawpt.y - (img->getHeight() / 2) * zoom; + dat.rect.w = img->getWidth() * zoom; + dat.rect.h = img->getHeight() * zoom; + } else { + dat.rect.x = drawpt.x - img->getWidth() / 2; + dat.rect.y = drawpt.y - img->getHeight() / 2; + dat.rect.w = img->getWidth(); + dat.rect.h = img->getHeight(); + } + dat.image = img; + data.push_back(dat); + } + } + } + + void CellRenderer::renderBuffer(Layer* layer) { + std::vector& data = m_bufferMap[layer]; + std::vector::iterator it = data.begin(); + for (; it != data.end(); ++it) { + (*it).image->render((*it).rect); + } + } } diff --git a/engine/core/view/renderers/cellrenderer.h b/engine/core/view/renderers/cellrenderer.h index c4d973def..28d8cbf54 100644 --- a/engine/core/view/renderers/cellrenderer.h +++ b/engine/core/view/renderers/cellrenderer.h @@ -36,7 +36,6 @@ namespace FIFE { class RenderBackend; - class Cell; class IFont; class CellRenderer: public RendererBase { @@ -76,34 +75,6 @@ namespace FIFE { */ void render(Camera* cam, Layer* layer, RenderList& instances); - /** Sets color that is used to visualize blocker. - * - * @param r The value for red, range 0-255. - * @param g The value for green, range 0-255. - * @param b The value for blue, range 0-255. - */ - void setBlockerColor(uint8_t r, uint8_t g, uint8_t b); - - /** Sets color that is used to visualize paths. - * - * @param r The value for red, range 0-255. - * @param g The value for green, range 0-255. - * @param b The value for blue, range 0-255. - */ - void setPathColor(uint8_t r, uint8_t g, uint8_t b); - - /** Enables blocking visualization. - * - * @param enabled A bool that enables or disables the visualization. - */ - void setEnabledBlocking(bool enabled); - - /** Gets whether blocking visualization is enabled. - * - * @return A bool, true if visualization is enabled, otherwise false. - */ - bool isEnabledBlocking(); - /** Enables Fog of War visualization. * * @param enabled A bool that enables or disables the visualization. @@ -115,18 +86,6 @@ namespace FIFE { * @return A bool, true if visualization is enabled, otherwise false. */ bool isEnabledFogOfWar(); - - /** Enables path visualization. - * - * @param enabled A bool that enables or disables the visualization. - */ - void setEnabledPathVisual(bool enabled); - - /** Gets whether path visualization is enabled. - * - * @return A bool, true if visualization is enabled, otherwise false. - */ - bool isEnabledPathVisual(); /** Sets the layer that is used for Fog of War visualization. * @@ -146,18 +105,6 @@ namespace FIFE { */ void setMaskImage(ImagePtr image); - /** Adds a instance to path visualization. The current path is automatically rendered. - * - * @param instance The instance's path is visualized. - */ - void addPathVisual(Instance* instance); - - /** Removes a instance from path visualization. - * - * @param instance The instance's path is visualized. - */ - void removePathVisual(Instance* instance); - /** Creates render target for Fog of War. * * @param cam The used camera. @@ -215,12 +162,22 @@ namespace FIFE { static CellRenderer* getInstance(IRendererContainer* cnt); private: - SDL_Color m_blockerColor; - SDL_Color m_pathColor; - bool m_blockingEnabled; - bool m_fowEnabled; - bool m_pathVisualEnabled; + /** Updates FoW. + */ + void updateFoW(Camera* cam, Layer* layer); + + /** Updates cached cell costs. + */ + void updateCellCosts(Camera* cam, Layer* layer); + + /** Sends the buffered cell cost data to the backend. + * + * @param layer Current layer to be rendered + */ + void renderBuffer(Layer* layer); + // FoW stuff + bool m_fowEnabled; TargetRenderer* m_targetRenderer; RenderTargetPtr m_fowTarget; Layer* m_fowLayer; @@ -229,8 +186,16 @@ namespace FIFE { ImagePtr m_fowImage; IFont* m_font; - std::vector m_visualPaths; + // Visualize cell costs + bool m_costsUpdate; std::set m_visualCosts; + + struct Data { + Rect rect; + Image* image; + }; + //! Buffers the cost images per Layer. + std::map > m_bufferMap; }; } diff --git a/engine/core/view/renderers/cellrenderer.i b/engine/core/view/renderers/cellrenderer.i index 02d1930c6..9abe2d2c8 100644 --- a/engine/core/view/renderers/cellrenderer.i +++ b/engine/core/view/renderers/cellrenderer.i @@ -32,19 +32,11 @@ namespace FIFE { public: virtual ~CellRenderer(); std::string getName(); - void setBlockerColor(uint8_t r, uint8_t g, uint8_t b); - void setPathColor(uint8_t r, uint8_t g, uint8_t b); - void setEnabledBlocking(bool enabled); - bool isEnabledBlocking(); void setEnabledFogOfWar(bool enabled); bool isEnabledFogOfWar(); - void setEnabledPathVisual(bool enabled); - bool isEnabledPathVisual(); void setFogOfWarLayer(Layer* layer); void setConcealImage(ImagePtr image); void setMaskImage(ImagePtr image); - void addPathVisual(Instance* instance); - void removePathVisual(Instance* instance); void setEnabledCost(const std::string& costId, bool enabled); bool isEnabledCost(const std::string& costId); void setFont(IFont* font); diff --git a/engine/core/view/renderers/cellselectionrenderer.cpp b/engine/core/view/renderers/cellselectionrenderer.cpp index cf82135a5..ade970752 100644 --- a/engine/core/view/renderers/cellselectionrenderer.cpp +++ b/engine/core/view/renderers/cellselectionrenderer.cpp @@ -70,20 +70,50 @@ namespace FIFE { return dynamic_cast(cnt->getRenderer("CellSelectionRenderer")); } + void CellSelectionRenderer::setEnabled(bool enabled) { + RendererBase::setEnabled(enabled); + if (!enabled) { + m_bufferMap.clear(); + m_updates.clear(); + } + } + + void CellSelectionRenderer::removeActiveLayer(Layer* layer) { + RendererBase::removeActiveLayer(layer); + std::map >::iterator it = m_bufferMap.find(layer); + if (it != m_bufferMap.end()) { + m_bufferMap.erase(it); + } + + std::map::iterator uit = m_updates.find(layer); + if (uit != m_updates.end()) { + m_updates.erase(uit); + } + } + + void CellSelectionRenderer::clearActiveLayers() { + RendererBase::clearActiveLayers(); + m_bufferMap.clear(); + m_updates.clear(); + } + void CellSelectionRenderer::reset() { m_locations.clear(); + m_bufferMap.clear(); + m_updates.clear(); } void CellSelectionRenderer::selectLocation(const Location* loc) { if (loc) { std::vector::const_iterator it = m_locations.begin(); for (; it != m_locations.end(); it++) { - if ((*it).getLayerCoordinates() == loc->getLayerCoordinates()) { + if ((*it).getLayerCoordinates() == loc->getLayerCoordinates() && (*it).getLayer() == loc->getLayer()) { return; } } m_locations.push_back(Location(*loc)); + m_updates[loc->getLayer()] = true; } } @@ -91,8 +121,9 @@ namespace FIFE { if (loc) { std::vector::iterator it = m_locations.begin(); for (; it != m_locations.end(); it++) { - if ((*it).getLayerCoordinates() == loc->getLayerCoordinates()) { + if ((*it).getLayerCoordinates() == loc->getLayerCoordinates() && (*it).getLayer() == loc->getLayer()) { m_locations.erase(it); + m_updates[loc->getLayer()] = true; break; } } @@ -104,6 +135,23 @@ namespace FIFE { return; } + CellGrid* cg = layer->getCellGrid(); + if (!cg) { + FL_WARN(_log, "No cellgrid assigned to layer, cannot draw selection"); + return; + } + + // Only render if nothing has changed. + if (!cam->isUpdated() && !cam->isLayerCacheUpdated(layer) && !m_updates[layer]) { + if (m_bufferMap.find(layer) != m_bufferMap.end()) { + renderBuffer(layer); + return; + } + } + + std::vector& data = m_bufferMap[layer]; + data.clear(); + // fill buffer std::vector::const_iterator locit = m_locations.begin(); for (; locit != m_locations.end(); locit++) { const Location loc = *locit; @@ -111,29 +159,23 @@ namespace FIFE { continue; } - CellGrid* cg = layer->getCellGrid(); - if (!cg) { - FL_WARN(_log, "No cellgrid assigned to layer, cannot draw selection"); - continue; - } - std::vector vertices; cg->getVertices(vertices, loc.getLayerCoordinates()); std::vector::const_iterator it = vertices.begin(); ScreenPoint firstpt = cam->toScreenCoordinates(cg->toMapCoordinates(*it)); - Point pt1(firstpt.x, firstpt.y); - Point pt2; + Point pt(firstpt.x, firstpt.y); + data.push_back(pt); ++it; - for (; it != vertices.end(); it++) { + for (; it != vertices.end(); ++it) { ScreenPoint pts = cam->toScreenCoordinates(cg->toMapCoordinates(*it)); - pt2.x = pts.x; pt2.y = pts.y; - Point cpt1 = pt1; - Point cpt2 = pt2; - m_renderbackend->drawLine(cpt1, cpt2, m_color.r, m_color.g, m_color.b); - pt1 = pt2; + pt.x = pts.x; + pt.y = pts.y; + data.push_back(pt); } - m_renderbackend->drawLine(pt2, Point(firstpt.x, firstpt.y), m_color.r, m_color.g, m_color.b); } + m_updates[layer] = false; + // render + renderBuffer(layer); } void CellSelectionRenderer::setColor(uint8_t r, uint8_t g, uint8_t b) { @@ -141,4 +183,29 @@ namespace FIFE { m_color.g = g; m_color.b = b; } + + void CellSelectionRenderer::renderBuffer(Layer* layer) { + std::vector& data = m_bufferMap[layer]; + uint32_t index = 0; + uint32_t indexEnd = data.size(); + if (layer->getCellGrid()->getType() == "square") { + while (index != indexEnd) { + m_renderbackend->drawLine(data[index], data[index + 1], m_color.r, m_color.g, m_color.b); + m_renderbackend->drawLine(data[index + 1], data[index + 2], m_color.r, m_color.g, m_color.b); + m_renderbackend->drawLine(data[index + 2], data[index + 3], m_color.r, m_color.g, m_color.b); + m_renderbackend->drawLine(data[index + 3], data[index], m_color.r, m_color.g, m_color.b); + index += 4; + } + } else { + while (index != indexEnd) { + m_renderbackend->drawLine(data[index], data[index + 1], m_color.r, m_color.g, m_color.b); + m_renderbackend->drawLine(data[index + 1], data[index + 2], m_color.r, m_color.g, m_color.b); + m_renderbackend->drawLine(data[index + 2], data[index + 3], m_color.r, m_color.g, m_color.b); + m_renderbackend->drawLine(data[index + 3], data[index + 4], m_color.r, m_color.g, m_color.b); + m_renderbackend->drawLine(data[index + 4], data[index + 5], m_color.r, m_color.g, m_color.b); + m_renderbackend->drawLine(data[index + 5], data[index], m_color.r, m_color.g, m_color.b); + index += 6; + } + } + } } diff --git a/engine/core/view/renderers/cellselectionrenderer.h b/engine/core/view/renderers/cellselectionrenderer.h index f8b9b4d19..c3020889d 100644 --- a/engine/core/view/renderers/cellselectionrenderer.h +++ b/engine/core/view/renderers/cellselectionrenderer.h @@ -79,6 +79,20 @@ namespace FIFE { */ static CellSelectionRenderer* getInstance(IRendererContainer* cnt); + /** Enables renderer + */ + void setEnabled(bool enabled); + + /** Removes active layer from renderer. + * + * @param layer The layer to be removed. + */ + void removeActiveLayer(Layer* layer); + + /** Clears all active layers from renderer + */ + void clearActiveLayers(); + /** Deselects all locations. */ void reset(); @@ -110,6 +124,18 @@ namespace FIFE { void setColor(uint8_t r, uint8_t g, uint8_t b); private: + /** Sends the buffered data to the backend. + * + * @param layer Current layer to be rendered + */ + void renderBuffer(Layer* layer); + + //! Buffers the lines per Layer. + std::map > m_bufferMap; + + //! Stores updates + std::map m_updates; + //! selected locations std::vector m_locations; diff --git a/engine/core/view/renderers/coordinaterenderer.cpp b/engine/core/view/renderers/coordinaterenderer.cpp index 71e35881b..42b5e14f8 100644 --- a/engine/core/view/renderers/coordinaterenderer.cpp +++ b/engine/core/view/renderers/coordinaterenderer.cpp @@ -51,22 +51,20 @@ namespace FIFE { CoordinateRenderer::CoordinateRenderer(RenderBackend* renderbackend, int32_t position): RendererBase(renderbackend, position), - m_layer_area(), + m_layerArea(), m_tmploc(), m_c(), m_font(0), - m_font_color(false), m_zoom(true) { setEnabled(false); } CoordinateRenderer::CoordinateRenderer(const CoordinateRenderer& old): RendererBase(old), - m_layer_area(), + m_layerArea(), m_tmploc(), m_c(), m_font(old.m_font), - m_font_color(false), m_color(old.m_color), m_zoom(old.m_zoom) { setEnabled(false); @@ -83,13 +81,33 @@ namespace FIFE { return dynamic_cast(cnt->getRenderer("CoordinateRenderer")); } + void CoordinateRenderer::setEnabled(bool enabled) { + RendererBase::setEnabled(enabled); + if (!enabled) { + m_bufferMap.clear(); + } + } + + void CoordinateRenderer::removeActiveLayer(Layer* layer) { + RendererBase::removeActiveLayer(layer); + std::map >::iterator it = m_bufferMap.find(layer); + if (it != m_bufferMap.end()) { + m_bufferMap.erase(it); + } + } + + void CoordinateRenderer::clearActiveLayers() { + RendererBase::clearActiveLayers(); + m_bufferMap.clear(); + } + void CoordinateRenderer::adjustLayerArea() { m_tmploc.setMapCoordinates(m_c); ModelCoordinate c = m_tmploc.getLayerCoordinates(); - m_layer_area.x = std::min(c.x, m_layer_area.x); - m_layer_area.w = std::max(c.x, m_layer_area.w); - m_layer_area.y = std::min(c.y, m_layer_area.y); - m_layer_area.h = std::max(c.y, m_layer_area.h); + m_layerArea.x = std::min(c.x, m_layerArea.x); + m_layerArea.w = std::max(c.x, m_layerArea.w); + m_layerArea.y = std::min(c.y, m_layerArea.y); + m_layerArea.h = std::max(c.y, m_layerArea.h); } const int32_t MIN_COORD = -9999999; @@ -99,15 +117,22 @@ namespace FIFE { //no font selected.. nothing to render return; } - Rect r = Rect(); + + if (!cam->isUpdated()) { + if (m_bufferMap.find(layer) != m_bufferMap.end()) { + renderBuffer(layer); + return; + } + } + const bool zoomed = (!Mathd::Equal(1.0, cam->getZoom()) && m_zoom); Rect cv = cam->getViewPort(); m_tmploc.setLayer(layer); - m_layer_area.x = MAX_COORD; - m_layer_area.y = MAX_COORD; - m_layer_area.w = MIN_COORD; - m_layer_area.h = MIN_COORD; + m_layerArea.x = MAX_COORD; + m_layerArea.y = MAX_COORD; + m_layerArea.w = MIN_COORD; + m_layerArea.h = MIN_COORD; m_c = cam->toMapCoordinates(ScreenPoint(cv.x, cv.y), false); adjustLayerArea(); @@ -118,13 +143,17 @@ namespace FIFE { m_c = cam->toMapCoordinates(ScreenPoint(cv.x+cv.w, cv.y+cv.h), false); adjustLayerArea(); - SDL_Color old_color = m_font->getColor(); - if(old_color.r != m_color.r || old_color.g != m_color.g || old_color.b != m_color.b) { + SDL_Color oldColor = m_font->getColor(); + bool fontColor = false; + if(oldColor.r != m_color.r || oldColor.g != m_color.g || oldColor.b != m_color.b) { m_font->setColor(m_color.r, m_color.g, m_color.b); - m_font_color = true; + fontColor = true; } - for (int32_t x = m_layer_area.x-1; x < m_layer_area.w+1; x++) { - for (int32_t y = m_layer_area.y-1; y < m_layer_area.h+1; y++) { + std::vector& data = m_bufferMap[layer]; + data.clear(); + Data dat; + for (int32_t x = m_layerArea.x-1; x < m_layerArea.w+1; x++) { + for (int32_t y = m_layerArea.y-1; y < m_layerArea.h+1; y++) { ModelCoordinate mc(x, y); m_tmploc.setLayerCoordinates(mc); ScreenPoint drawpt = cam->toScreenCoordinates(m_tmploc.getMapCoordinates()); @@ -146,41 +175,71 @@ namespace FIFE { if (zoomed) { double zoom = cam->getZoom(); - r.x = drawpt.x - ((imgx->getWidth() + imgc->getWidth() + imgy->getWidth())/2) * zoom; - r.y = drawpt.y - (imgx->getHeight()/2) * zoom; - r.w = imgx->getWidth() * zoom; - r.h = imgx->getHeight() * zoom; - imgx->render(r); - r.x += r.w; - r.w = imgc->getWidth() * zoom; - imgc->render(r); - r.x += r.w; - r.w = imgy->getWidth() * zoom; - imgy->render(r); + dat.rect.x = drawpt.x - ((imgx->getWidth() + imgc->getWidth() + imgy->getWidth())/2) * zoom; + dat.rect.y = drawpt.y - (imgx->getHeight()/2) * zoom; + dat.rect.w = imgx->getWidth() * zoom; + dat.rect.h = imgx->getHeight() * zoom; + dat.image = imgx; + data.push_back(dat); + + dat.rect.x += dat.rect.w; + dat.rect.w = imgc->getWidth() * zoom; + dat.image = imgc; + data.push_back(dat); + + dat.rect.x += dat.rect.w; + dat.rect.w = imgy->getWidth() * zoom; + dat.image = imgy; + data.push_back(dat); } else { - r.x = drawpt.x - (imgx->getWidth() + imgc->getWidth() + imgy->getWidth())/2; - r.y = drawpt.y - imgx->getHeight()/2; - r.w = imgx->getWidth(); - r.h = imgx->getHeight(); - imgx->render(r); - r.x += r.w; - r.w = imgc->getWidth(); - imgc->render(r); - r.x += r.w; - r.w = imgy->getWidth(); - imgy->render(r); + dat.rect.x = drawpt.x - (imgx->getWidth() + imgc->getWidth() + imgy->getWidth())/2; + dat.rect.y = drawpt.y - imgx->getHeight()/2; + dat.rect.w = imgx->getWidth(); + dat.rect.h = imgx->getHeight(); + dat.image = imgx; + data.push_back(dat); + + dat.rect.x += dat.rect.w; + dat.rect.w = imgc->getWidth(); + dat.image = imgc; + data.push_back(dat); + + dat.rect.x += dat.rect.w; + dat.rect.w = imgy->getWidth(); + dat.image = imgy; + data.push_back(dat); } } } - if(m_font_color) { - m_font->setColor(old_color.r, old_color.g, old_color.b); - m_font_color = false; + if (fontColor) { + m_font->setColor(oldColor.r, oldColor.g, oldColor.b); } + // render + renderBuffer(layer); } void CoordinateRenderer::setColor(uint8_t r, uint8_t g, uint8_t b) { m_color.r = r; m_color.g = g; m_color.b = b; + m_bufferMap.clear(); + } + + void CoordinateRenderer::setFont(IFont* font) { + m_font = font; + m_bufferMap.clear(); + } + + void CoordinateRenderer::setZoom(bool enable) { + m_zoom = enable; + m_bufferMap.clear(); + } + + void CoordinateRenderer::renderBuffer(Layer* layer) { + std::vector& data = m_bufferMap[layer]; + std::vector::iterator it = data.begin(); + for (; it != data.end(); ++it) { + (*it).image->render((*it).rect); + } } } diff --git a/engine/core/view/renderers/coordinaterenderer.h b/engine/core/view/renderers/coordinaterenderer.h index 9e6aa6c9a..1737234fa 100644 --- a/engine/core/view/renderers/coordinaterenderer.h +++ b/engine/core/view/renderers/coordinaterenderer.h @@ -87,26 +87,54 @@ namespace FIFE { * * @param font Pointer to the font */ - void setFont(IFont* font) { m_font = font; } + void setFont(IFont* font); /** Enables / disables zooming for coordinate images, by default it is enabled. */ - void setZoom(bool enable) { m_zoom = enable; } + void setZoom(bool enable); /** Gets instance for interface access. */ static CoordinateRenderer* getInstance(IRendererContainer* cnt); + /** Enables renderer + */ + void setEnabled(bool enabled); + + /** Removes active layer from renderer. + * + * @param layer The layer to be removed. + */ + void removeActiveLayer(Layer* layer); + + /** Clears all active layers from renderer + */ + void clearActiveLayers(); + private: + /** Prepares the used area. + */ void adjustLayerArea(); - Rect m_layer_area; + /** Sends the buffered data to the backend. + * + * @param layer Current layer to be rendered + */ + void renderBuffer(Layer* layer); + + Rect m_layerArea; Location m_tmploc; ExactModelCoordinate m_c; IFont* m_font; - bool m_font_color; SDL_Color m_color; bool m_zoom; + + struct Data { + Rect rect; + Image* image; + }; + //! Buffers the coordinate images per Layer. + std::map > m_bufferMap; }; } diff --git a/engine/core/view/renderers/floatingtextrenderer.cpp b/engine/core/view/renderers/floatingtextrenderer.cpp index 6c068e7cb..ad303d8ec 100644 --- a/engine/core/view/renderers/floatingtextrenderer.cpp +++ b/engine/core/view/renderers/floatingtextrenderer.cpp @@ -49,9 +49,8 @@ namespace FIFE { FloatingTextRenderer::FloatingTextRenderer(RenderBackend* renderbackend, int32_t position): RendererBase(renderbackend, position), - m_renderbackend(renderbackend), m_font(0), - m_font_color(false), + m_fontColor(false), m_background(false), m_backborder(false) { setEnabled(false); @@ -59,9 +58,8 @@ namespace FIFE { FloatingTextRenderer::FloatingTextRenderer(const FloatingTextRenderer& old): RendererBase(old), - m_renderbackend(old.m_renderbackend), m_font(old.m_font), - m_font_color(old.m_font_color), + m_fontColor(old.m_fontColor), m_color(old.m_color), m_background(old.m_background), m_backborder(old.m_backborder) { @@ -75,6 +73,23 @@ namespace FIFE { FloatingTextRenderer::~FloatingTextRenderer() { } + FloatingTextRenderer* FloatingTextRenderer::getInstance(IRendererContainer* cnt) { + return dynamic_cast(cnt->getRenderer("FloatingTextRenderer")); + } + + void FloatingTextRenderer::removeActiveLayer(Layer* layer) { + RendererBase::removeActiveLayer(layer); + std::map >::iterator it = m_bufferMap.find(layer); + if (it != m_bufferMap.end()) { + m_bufferMap.erase(it); + } + } + + void FloatingTextRenderer::clearActiveLayers() { + RendererBase::clearActiveLayers(); + m_bufferMap.clear(); + } + void FloatingTextRenderer::render(Camera* cam, Layer* layer, RenderList& instances) { if (!m_font) { //no font selected.. nothing to render @@ -82,11 +97,12 @@ namespace FIFE { } RenderList::const_iterator instance_it = instances.begin(); - uint32_t lm = m_renderbackend->getLightingModel(); SDL_Color old_color = m_font->getColor(); - if(m_font_color) { + if(m_fontColor) { m_font->setColor(m_color.r, m_color.g, m_color.b, m_color.a); } + std::map& instanceMap = m_bufferMap[layer]; + instanceMap.clear(); for (;instance_it != instances.end(); ++instance_it) { Instance* instance = (*instance_it)->instance; const std::string* saytext = instance->getSayText(); @@ -105,35 +121,30 @@ namespace FIFE { r.bottom() < 0 || r.y > static_cast(m_renderbackend->getHeight())) { continue; } + + Data& data = instanceMap[instance]; + data.image = img; + data.imageRec = r; + if(m_background || m_backborder) { const int32_t overdraw = 5; - Point p = Point(r.x-overdraw, r.y-overdraw); - - if(m_background) { - m_renderbackend->fillRectangle(p, r.w+2*overdraw, r.h+2*overdraw, m_backcolor.r, m_backcolor.g, m_backcolor.b, m_backcolor.a); - } - - if(m_backborder) { - m_renderbackend->drawRectangle(p, r.w+2*overdraw, r.h+2*overdraw, m_backbordercolor.r, m_backbordercolor.g, m_backbordercolor.b, m_backbordercolor.a); - } - } - img->render(r); - if(lm > 0) { - uint16_t elements = 1; - if (m_background) { - ++elements; - } - if (m_backborder) { - ++elements; - } - m_renderbackend->changeRenderInfos(RENDER_DATA_WITHOUT_Z, elements, 4, 5, false, true, 255, REPLACE, ALWAYS); + data.backgroundRec.x = p.x; + data.backgroundRec.y = p.y; + data.backgroundRec.w = r.w + 2 * overdraw; + data.backgroundRec.h = r.h + 2 * overdraw; } } } - if(m_font_color) { + if(m_fontColor) { m_font->setColor(old_color.r, old_color.g, old_color.b, old_color.a); } + renderBuffer(layer); + } + + void FloatingTextRenderer::setFont(IFont* font) { + m_font = font; + m_bufferMap.clear(); } void FloatingTextRenderer::setColor(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { @@ -141,25 +152,23 @@ namespace FIFE { m_color.g = g; m_color.b = b; m_color.a = a; - - m_font_color = true; + m_fontColor = true; + m_bufferMap.clear(); } - void FloatingTextRenderer::setBackground(uint8_t br, uint8_t bg, uint8_t bb, uint8_t ba) { - m_backcolor.r = br; - m_backcolor.g = bg; - m_backcolor.b = bb; - m_backcolor.a = ba; - + void FloatingTextRenderer::setBackground(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { + m_backcolor.r = r; + m_backcolor.g = g; + m_backcolor.b = b; + m_backcolor.a = a; m_background = true; } - void FloatingTextRenderer::setBorder(uint8_t bbr, uint8_t bbg, uint8_t bbb, uint8_t bba) { - m_backbordercolor.r = bbr; - m_backbordercolor.g = bbg; - m_backbordercolor.b = bbb; - m_backbordercolor.a = bba; - + void FloatingTextRenderer::setBorder(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { + m_backbordercolor.r = r; + m_backbordercolor.g = g; + m_backbordercolor.b = b; + m_backbordercolor.a = a; m_backborder = true; } @@ -171,7 +180,28 @@ namespace FIFE { m_backborder = false; } - FloatingTextRenderer* FloatingTextRenderer::getInstance(IRendererContainer* cnt) { - return dynamic_cast(cnt->getRenderer("FloatingTextRenderer")); + void FloatingTextRenderer::renderBuffer(Layer* layer) { + std::map& instanceMap = m_bufferMap[layer]; + std::map::iterator it = instanceMap.begin(); + uint16_t elements = 0; + for (; it != instanceMap.end(); ++it) { + Data& data = (*it).second; + Rect& rec = data.backgroundRec; + + if (m_background) { + m_renderbackend->fillRectangle(Point(rec.x, rec.y), rec.w, rec.h, m_backcolor.r, m_backcolor.g, m_backcolor.b, m_backcolor.a); + ++elements; + } + if (m_backborder) { + m_renderbackend->drawRectangle(Point(rec.x, rec.y), rec.w, rec.h, m_backbordercolor.r, m_backbordercolor.g, m_backbordercolor.b, m_backbordercolor.a); + ++elements; + } + rec = data.imageRec; + data.image->render(rec); + ++elements; + } + if (m_renderbackend->getLightingModel() > 0) { + m_renderbackend->changeRenderInfos(RENDER_DATA_WITHOUT_Z, elements, 4, 5, false, true, 255, REPLACE, ALWAYS); + } } } diff --git a/engine/core/view/renderers/floatingtextrenderer.h b/engine/core/view/renderers/floatingtextrenderer.h index 1ad00d73b..b44b7c0fd 100644 --- a/engine/core/view/renderers/floatingtextrenderer.h +++ b/engine/core/view/renderers/floatingtextrenderer.h @@ -33,7 +33,6 @@ #include "view/rendererbase.h" namespace FIFE { - class RenderBackend; class IFont; class FloatingTextRenderer: public RendererBase { @@ -58,6 +57,18 @@ namespace FIFE { */ virtual ~FloatingTextRenderer(); + /** Gets renderer instance for interface access. + */ + static FloatingTextRenderer* getInstance(IRendererContainer* cnt); + + /** Removes active layer from renderer. + */ + void removeActiveLayer(Layer* layer); + + /** Clears all active layers from renderer + */ + void clearActiveLayers(); + /** This method is called by the view to ask renderer to draw its rendering aspect based on * given parameters. * @@ -76,7 +87,7 @@ namespace FIFE { /** Changes default font in the renderer * Note that this does not change the font ownership */ - void setFont(IFont* font) { m_font = font; } + void setFont(IFont* font); /** Changes default font color * Only useful for .ttf fonts @@ -86,12 +97,12 @@ namespace FIFE { /** Set default background quad * r,g,b,a values for background */ - void setBackground(uint8_t br, uint8_t bg, uint8_t bb, uint8_t ba = 255); + void setBackground(uint8_t r, uint8_t g, uint8_t b, uint8_t a = 255); /** Set default border * r,g,b,a values for border */ - void setBorder(uint8_t bbr, uint8_t bbg, uint8_t bbb, uint8_t bba = 255); + void setBorder(uint8_t r, uint8_t g, uint8_t b, uint8_t a = 255); /** Disable the default background */ @@ -101,23 +112,29 @@ namespace FIFE { */ void resetBorder(); - /** Gets instance for interface access. - */ - static FloatingTextRenderer* getInstance(IRendererContainer* cnt); - - /** Provides access point to the RenderBackend + private: + /** Sends the buffered data to the backend. + * + * @param layer Current layer to be rendered */ - RenderBackend* getRenderBackend() const {return m_renderbackend;} + void renderBuffer(Layer* layer); - private: - RenderBackend* m_renderbackend; IFont* m_font; - bool m_font_color; + bool m_fontColor; SDL_Color m_color; bool m_background; bool m_backborder; SDL_Color m_backcolor; SDL_Color m_backbordercolor; + + // Struct to store data + struct Data { + Image* image; + Rect imageRec; + Rect backgroundRec; + }; + //! Buffers the data per Layer. + std::map > m_bufferMap; }; } diff --git a/engine/core/view/renderers/gridrenderer.cpp b/engine/core/view/renderers/gridrenderer.cpp index aac6c55fd..e624fd0c5 100644 --- a/engine/core/view/renderers/gridrenderer.cpp +++ b/engine/core/view/renderers/gridrenderer.cpp @@ -70,127 +70,98 @@ namespace FIFE { return dynamic_cast(cnt->getRenderer("GridRenderer")); } + void GridRenderer::setEnabled(bool enabled) { + RendererBase::setEnabled(enabled); + if (!enabled) { + m_bufferMap.clear(); + } + } + + void GridRenderer::removeActiveLayer(Layer* layer) { + RendererBase::removeActiveLayer(layer); + std::map >::iterator it = m_bufferMap.find(layer); + if (it != m_bufferMap.end()) { + m_bufferMap.erase(it); + } + } + + void GridRenderer::clearActiveLayers() { + RendererBase::clearActiveLayers(); + m_bufferMap.clear(); + } + void GridRenderer::render(Camera* cam, Layer* layer, RenderList& instances) { CellGrid* cg = layer->getCellGrid(); if (!cg) { FL_WARN(_log, "No cellgrid assigned to layer, cannot draw grid"); return; } - -// -// //render elev_coord box -// //draw front quad -// // 1,1,1 -// //1,-1,1 -// //-1,-1,1 -// //-1,1,1 - //We don't need the elevation box atm -// Point a,b,c,d; -// -// -// ScreenPoint copt1 =cam->toScreenCoordinates(ExactModelCoordinate(1,1,1) ); -// ScreenPoint copt2 =cam->toScreenCoordinates(ExactModelCoordinate(1,-1,1) ); -// Point coptt1(copt1.x,copt1.y); -// Point coptt2(copt2.x,copt2.y); -// m_renderbackend->drawLine(coptt1,coptt2 ,15, 15, 200); -// a = coptt1; -// -// copt1 =cam->toScreenCoordinates(ExactModelCoordinate(1,-1,1) ); -// copt2 =cam->toScreenCoordinates(ExactModelCoordinate(-1,-1,1) ); -// coptt1 = Point(copt1.x,copt1.y); -// coptt2 = Point(copt2.x,copt2.y); -// m_renderbackend->drawLine(coptt1,coptt2 ,15, 15, 200); -// b = coptt1; -// -// copt1 =cam->toScreenCoordinates(ExactModelCoordinate(-1,-1,1) ); -// copt2 =cam->toScreenCoordinates(ExactModelCoordinate(-1,1,1) ); -// coptt1 = Point(copt1.x,copt1.y); -// coptt2 = Point(copt2.x,copt2.y); -// m_renderbackend->drawLine(coptt1,coptt2 ,15, 15, 200); -// c = coptt1; -// -// copt1 =cam->toScreenCoordinates(ExactModelCoordinate(-1,1,1) ); -// copt2 =cam->toScreenCoordinates(ExactModelCoordinate(1,1,1) ); -// coptt1 = Point(copt1.x,copt1.y); -// coptt2 = Point(copt2.x,copt2.y); -// m_renderbackend->drawLine(coptt1,coptt2 ,15, 15, 20); -// d = coptt1; -// -// m_renderbackend->drawQuad(a,b,c,d,15, 15, 200); -// -// -// //draw back quad -// copt1 =cam->toScreenCoordinates(ExactModelCoordinate(-1,-1,-1) ); -// copt2 =cam->toScreenCoordinates(ExactModelCoordinate(-1,1,-1) ); -// coptt1 = Point(copt1.x,copt1.y); -// coptt2 = Point(copt2.x,copt2.y); -// m_renderbackend->drawLine(coptt1,coptt2 ,200, 200, 200); -// -// copt1 =cam->toScreenCoordinates(ExactModelCoordinate(-1,1,-1) ); -// copt2 =cam->toScreenCoordinates(ExactModelCoordinate(1,1,-1) ); -// coptt1 = Point(copt1.x,copt1.y); -// coptt2 = Point(copt2.x,copt2.y); -// m_renderbackend->drawLine(coptt1,coptt2 ,200, 200, 200); -// -// copt1 =cam->toScreenCoordinates(ExactModelCoordinate(1,1,-1) ); -// copt2 =cam->toScreenCoordinates(ExactModelCoordinate(1,-1,-1) ); -// coptt1 = Point(copt1.x,copt1.y); -// coptt2 = Point(copt2.x,copt2.y); -// m_renderbackend->drawLine(coptt1,coptt2 ,200, 200, 200); -// -// copt1 =cam->toScreenCoordinates(ExactModelCoordinate(1,-1,-1) ); -// copt2 =cam->toScreenCoordinates(ExactModelCoordinate(-1,-1,-1) ); -// coptt1 = Point(copt1.x,copt1.y); -// coptt2 = Point(copt2.x,copt2.y); -// m_renderbackend->drawLine(coptt1,coptt2 ,200, 200, 200); - - - // make the viewport 25% larger - Rect cv = cam->getViewPort(); - int32_t cvx2 = round((cv.x+cv.w) * 1.25); - int32_t cvy2 = round((cv.y+cv.h) * 1.25); - cv.x -= round((cv.x+cv.w) * 0.125); - cv.y -= round((cv.y+cv.h) * 0.125); + // Only render if nothing has changed. + if (!cam->isUpdated() && !cam->isLayerCacheUpdated(layer)) { + if (m_bufferMap.find(layer) != m_bufferMap.end()) { + renderBuffer(layer); + return; + } + } + uint32_t index = 0; + // prepare buffer for square or hexgrid + std::vector& data = m_bufferMap[layer]; + if (layer->getCellGrid()->getType() == "square") { + data.resize(instances.size() * 4); + } else { + data.resize(instances.size() * 6); + } + // fill buffer RenderList::const_iterator instance_it = instances.begin(); - for (;instance_it != instances.end(); ++instance_it) { + for (; instance_it != instances.end(); ++instance_it) { Instance* instance = (*instance_it)->instance; std::vector vertices; cg->getVertices(vertices, instance->getLocationRef().getLayerCoordinates()); std::vector::const_iterator it = vertices.begin(); ScreenPoint firstpt = cam->toScreenCoordinates(cg->toMapCoordinates(*it)); - Point pt1(firstpt.x, firstpt.y); - Point pt2; + Point pt(firstpt.x, firstpt.y); + data[index] = pt; ++it; - for (; it != vertices.end(); it++) { + for (; it != vertices.end(); ++it) { ScreenPoint pts = cam->toScreenCoordinates(cg->toMapCoordinates(*it)); - pt2.x = pts.x; - pt2.y = pts.y; - Point cpt1 = pt1; - Point cpt2 = pt2; - - if (cpt1.x < cv.x) cpt1.x = cv.x; - if (cpt2.x < cv.x) cpt2.x = cv.x; - if (cpt1.y < cv.y) cpt1.y = cv.y; - if (cpt2.y < cv.y) cpt2.y = cv.y; - if (cpt1.x > cvx2) cpt1.x = cvx2; - if (cpt2.x > cvx2) cpt2.x = cvx2; - if (cpt1.y > cvy2) cpt1.y = cvy2; - if (cpt2.y > cvy2) cpt2.y = cvy2; - - m_renderbackend->drawLine(cpt1, cpt2, m_color.r, m_color.g, m_color.b); - pt1 = pt2; - } - if ((pt2.x >= cv.x) && (pt2.x <= cvx2) && (pt2.y >= cv.y) && (pt2.y <= cvy2)) { - if ((firstpt.x >= cv.x) && (firstpt.x <= cvx2) && (firstpt.y >= cv.y) && (firstpt.y <= cvy2)) { - m_renderbackend->drawLine(pt2, Point(firstpt.x, firstpt.y), m_color.r, m_color.g, m_color.b); - } + Point& p = data[++index]; + p.x = pts.x; + p.y = pts.y; } + ++index; } + // render + renderBuffer(layer); } - void GridRenderer::setColor(Uint8 r, Uint8 g, Uint8 b) { + void GridRenderer::setColor(uint8_t r, uint8_t g, uint8_t b) { m_color.r = r; m_color.g = g; m_color.b = b; } + + void GridRenderer::renderBuffer(Layer* layer) { + std::vector& data = m_bufferMap[layer]; + uint32_t index = 0; + uint32_t indexEnd = data.size(); + if (layer->getCellGrid()->getType() == "square") { + while (index != indexEnd) { + m_renderbackend->drawLine(data[index], data[index + 1], m_color.r, m_color.g, m_color.b); + m_renderbackend->drawLine(data[index + 1], data[index + 2], m_color.r, m_color.g, m_color.b); + m_renderbackend->drawLine(data[index + 2], data[index + 3], m_color.r, m_color.g, m_color.b); + m_renderbackend->drawLine(data[index + 3], data[index], m_color.r, m_color.g, m_color.b); + index += 4; + } + } else { + while (index != indexEnd) { + m_renderbackend->drawLine(data[index], data[index + 1], m_color.r, m_color.g, m_color.b); + m_renderbackend->drawLine(data[index + 1], data[index + 2], m_color.r, m_color.g, m_color.b); + m_renderbackend->drawLine(data[index + 2], data[index + 3], m_color.r, m_color.g, m_color.b); + m_renderbackend->drawLine(data[index + 3], data[index + 4], m_color.r, m_color.g, m_color.b); + m_renderbackend->drawLine(data[index + 4], data[index + 5], m_color.r, m_color.g, m_color.b); + m_renderbackend->drawLine(data[index + 5], data[index], m_color.r, m_color.g, m_color.b); + index += 6; + } + } + } } diff --git a/engine/core/view/renderers/gridrenderer.h b/engine/core/view/renderers/gridrenderer.h index 4bc925d69..f8409b2b5 100644 --- a/engine/core/view/renderers/gridrenderer.h +++ b/engine/core/view/renderers/gridrenderer.h @@ -37,27 +37,75 @@ namespace FIFE { class GridRenderer: public RendererBase { public: - /** constructor. + /** Constructor. * @param renderbackend to use * @param position position for this renderer in rendering pipeline */ GridRenderer(RenderBackend* renderbackend, int32_t position); + /** Copy Constructor. + */ GridRenderer(const GridRenderer& old); + /** Makes copy of this renderer. + */ RendererBase* clone(); /** Destructor. */ virtual ~GridRenderer(); + /** This method is called by the camera to ask renderer to draw its rendering aspect based on + * given parameters. + * + * @param cam Camera view to draw + * @param layer Current layer to be rendered + * @param instances Instances on the current layer + */ void render(Camera* cam, Layer* layer, RenderList& instances); + + /** Returns the renderer name. + * + * @return The name as string. + */ std::string getName() { return "GridRenderer"; } - void setColor(Uint8 r, Uint8 g, Uint8 b); + /** Changes the used color. + * + * @param r The value for red, range 0-255. + * @param g The value for green, range 0-255. + * @param b The value for blue, range 0-255. + */ + void setColor(uint8_t r, uint8_t g, uint8_t b); + + /** Gets instance for interface access. + */ static GridRenderer* getInstance(IRendererContainer* cnt); + /** Enables renderer + */ + void setEnabled(bool enabled); + + /** Removes active layer from renderer. + * + * @param layer The layer to be removed. + */ + void removeActiveLayer(Layer* layer); + + /** Clears all active layers from renderer + */ + void clearActiveLayers(); + private: + /** Sends the buffered data to the backend. + * + * @param layer Current layer to be rendered + */ + void renderBuffer(Layer* layer); + + //! Buffers the lines per Layer. + std::map > m_bufferMap; + //! currently used color SDL_Color m_color; }; }