#include "drape/render_bucket.hpp" #include "drape/attribute_buffer_mutator.hpp" #include "drape/debug_renderer.hpp" #include "drape/overlay_handle.hpp" #include "drape/overlay_tree.hpp" #include "drape/vertex_array_buffer.hpp" #include "base/stl_helpers.hpp" namespace dp { RenderBucket::RenderBucket(drape_ptr && buffer) : m_buffer(std::move(buffer)) {} RenderBucket::~RenderBucket() {} ref_ptr RenderBucket::GetBuffer() { return make_ref(m_buffer); } drape_ptr && RenderBucket::MoveBuffer() { return std::move(m_buffer); } size_t RenderBucket::GetOverlayHandlesCount() const { return m_overlay.size(); } drape_ptr RenderBucket::PopOverlayHandle() { ASSERT(!m_overlay.empty(), ()); size_t lastElement = m_overlay.size() - 1; swap(m_overlay[0], m_overlay[lastElement]); drape_ptr h = move(m_overlay[lastElement]); m_overlay.pop_back(); return h; } ref_ptr RenderBucket::GetOverlayHandle(size_t index) { return make_ref(m_overlay[index]); } void RenderBucket::AddOverlayHandle(drape_ptr && handle) { m_overlay.push_back(move(handle)); } void RenderBucket::BeforeUpdate() { for (auto & overlayHandle : m_overlay) overlayHandle->BeforeUpdate(); } void RenderBucket::Update(ScreenBase const & modelView) { BeforeUpdate(); for (auto & overlayHandle : m_overlay) { if (overlayHandle->IsVisible()) overlayHandle->Update(modelView); } } void RenderBucket::CollectOverlayHandles(ref_ptr tree) { BeforeUpdate(); for (auto const & overlayHandle : m_overlay) tree->Add(make_ref(overlayHandle)); } bool RenderBucket::HasOverlayHandles() const { return !m_overlay.empty(); } void RenderBucket::RemoveOverlayHandles(ref_ptr tree) { for (auto const & overlayHandle : m_overlay) tree->Remove(make_ref(overlayHandle)); } void RenderBucket::SetOverlayVisibility(bool isVisible) { for (auto const & overlayHandle : m_overlay) overlayHandle->SetIsVisible(isVisible); } void RenderBucket::Render(ref_ptr context, bool drawAsLine) { ASSERT(m_buffer != nullptr, ()); if (!m_overlay.empty()) { // in simple case when overlay is symbol each element will be contains 6 indexes AttributeBufferMutator attributeMutator; IndexBufferMutator indexMutator(static_cast(6 * m_overlay.size())); ref_ptr rfpIndex = make_ref(&indexMutator); ref_ptr rfpAttrib = make_ref(&attributeMutator); bool hasIndexMutation = false; for (drape_ptr const & handle : m_overlay) { if (handle->IndexesRequired()) { if (handle->IsVisible()) handle->GetElementIndexes(rfpIndex); hasIndexMutation = true; } if (handle->HasDynamicAttributes()) handle->GetAttributeMutation(rfpAttrib); } m_buffer->ApplyMutation(context, hasIndexMutation ? rfpIndex : nullptr, rfpAttrib); } m_buffer->Render(context, drawAsLine); } void RenderBucket::SetFeatureMinZoom(int minZoom) { if (minZoom < m_featuresMinZoom) m_featuresMinZoom = minZoom; } void RenderBucket::RenderDebug(ref_ptr context, ScreenBase const & screen, ref_ptr debugRectRenderer) const { if (!debugRectRenderer || !debugRectRenderer->IsEnabled() || m_overlay.empty()) return; for (auto const & handle : m_overlay) { if (!screen.PixelRect().IsIntersect(handle->GetPixelRect(screen, false))) continue; auto const & rects = handle->GetExtendedPixelShape(screen); for (auto const & rect : rects) { if (screen.isPerspective() && !screen.PixelRectIn3d().IsIntersect(m2::RectD(rect))) continue; auto color = dp::Color::Green(); if (!handle->IsVisible()) color = handle->IsReady() ? dp::Color::Red() : dp::Color::Yellow(); debugRectRenderer->DrawRect(context, screen, rect, color); } } } } // namespace dp