diff --git a/drape/overlay_handle.cpp b/drape/overlay_handle.cpp index 41bbb9a444..481b286a65 100644 --- a/drape/overlay_handle.cpp +++ b/drape/overlay_handle.cpp @@ -107,6 +107,14 @@ OverlayHandle::TOffsetNode const & OverlayHandle::GetOffsetNode(uint8_t bufferID return *it; } +void OverlayHandle::FinishTapEvent(bool executeAction) +{ + if (executeAction) + OnTap(); + + OnTapEnd(); +} + //////////////////////////////////////////////////////////////////////////////// SquareHandle::SquareHandle(FeatureID const & id, dp::Anchor anchor, diff --git a/drape/overlay_handle.hpp b/drape/overlay_handle.hpp index 2ee3bec2f7..2dca2863cc 100644 --- a/drape/overlay_handle.hpp +++ b/drape/overlay_handle.hpp @@ -13,9 +13,13 @@ #include "base/buffer_vector.hpp" +#include "std/function.hpp" + namespace dp { +using TOverlayHandler = function; + class OverlayHandle { public: @@ -34,9 +38,15 @@ public: virtual void Update(ScreenBase const & /*screen*/) {} virtual m2::RectD GetPixelRect(ScreenBase const & screen) const = 0; - virtual void GetPixelShape(ScreenBase const & screen, Rects & rects) const = 0; + virtual bool IsTapped(m2::PointD const & pt) const { return false; } + virtual void OnTapBegin(){} + virtual void OnTap(){} + virtual void OnTapEnd(){} + + void FinishTapEvent(bool executeAction); + bool IsIntersect(ScreenBase const & screen, ref_ptr const h) const; virtual bool IndexesRequired() const { return true; } diff --git a/drape_frontend/backend_renderer.cpp b/drape_frontend/backend_renderer.cpp index 4d5b7c649c..9ab479b8e1 100644 --- a/drape_frontend/backend_renderer.cpp +++ b/drape_frontend/backend_renderer.cpp @@ -24,6 +24,7 @@ namespace df BackendRenderer::BackendRenderer(Params const & params) : BaseRenderer(ThreadsCommutator::ResourceUploadThread, params) , m_model(params.m_model) + , m_guiHandlers(params.m_guiHandlers) , m_batchersPool(make_unique_dp(ReadManager::ReadCount(), bind(&BackendRenderer::FlushGeometry, this, _1))) , m_readManager(make_unique_dp(params.m_commutator, m_model)) , m_guiCacher("default") @@ -41,6 +42,8 @@ BackendRenderer::BackendRenderer(Params const & params) BackendRenderer::~BackendRenderer() { gui::DrapeGui::Instance().ClearRecacheSlot(); + m_guiHandlers.Reset(); + StopThread(); } @@ -51,7 +54,7 @@ unique_ptr BackendRenderer::CreateRoutine() void BackendRenderer::RecacheGui(gui::Skin::ElementName elements) { - drape_ptr layerRenderer = m_guiCacher.Recache(elements, m_texMng); + drape_ptr layerRenderer = m_guiCacher.Recache(elements, m_texMng, m_guiHandlers); drape_ptr outputMsg = make_unique_dp(move(layerRenderer)); m_commutator->PostMessage(ThreadsCommutator::RenderThread, move(outputMsg), MessagePriority::High); } diff --git a/drape_frontend/backend_renderer.hpp b/drape_frontend/backend_renderer.hpp index 8425246cd5..79ea717dd8 100644 --- a/drape_frontend/backend_renderer.hpp +++ b/drape_frontend/backend_renderer.hpp @@ -25,16 +25,19 @@ class ReadManager; class BackendRenderer : public BaseRenderer { public: + struct Params : BaseRenderer::Params { Params(ref_ptr commutator, ref_ptr factory, - ref_ptr texMng, MapDataProvider const & model) + ref_ptr texMng, MapDataProvider const & model, + gui::Handlers const & guiHandlers) : BaseRenderer::Params(commutator, factory, texMng) , m_model(model) - { - } + , m_guiHandlers(guiHandlers) + {} MapDataProvider const & m_model; + gui::Handlers m_guiHandlers; }; BackendRenderer(Params const & params); @@ -52,6 +55,7 @@ private: drape_ptr m_batchersPool; drape_ptr m_readManager; gui::LayerCacher m_guiCacher; + gui::Handlers m_guiHandlers; ///////////////////////////////////////// // MessageAcceptor // diff --git a/drape_frontend/drape_engine.cpp b/drape_frontend/drape_engine.cpp index 6df64faff9..047db57ca1 100644 --- a/drape_frontend/drape_engine.cpp +++ b/drape_frontend/drape_engine.cpp @@ -44,7 +44,8 @@ DrapeEngine::DrapeEngine(Params const & params) m_frontend = make_unique_dp(frParams); BackendRenderer::Params brParams(frParams.m_commutator, frParams.m_oglContextFactory, - frParams.m_texMng, params.m_model); + frParams.m_texMng, params.m_model, + params.m_guiHandlers); m_backend = make_unique_dp(brParams); } diff --git a/drape_frontend/drape_engine.hpp b/drape_frontend/drape_engine.hpp index 5c74d64d09..d549fc7939 100644 --- a/drape_frontend/drape_engine.hpp +++ b/drape_frontend/drape_engine.hpp @@ -5,6 +5,7 @@ #include "drape_frontend/threads_commutator.hpp" #include "drape/pointers.hpp" +#include "drape/overlay_handle.hpp" #include "drape/texture_manager.hpp" #include "geometry/screenbase.hpp" @@ -34,15 +35,16 @@ public: ref_ptr storageAccessor, Viewport const & viewport, MapDataProvider const & model, - double vs) + double vs, + gui::Handlers const & guiHandlers) : m_factory(factory) , m_stringsBundle(stringBundle) , m_storageAccessor(storageAccessor) , m_viewport(viewport) , m_model(model) , m_vs(vs) - { - } + , m_guiHandlers(guiHandlers) + {} ref_ptr m_factory; ref_ptr m_stringsBundle; @@ -50,6 +52,8 @@ public: Viewport m_viewport; MapDataProvider m_model; double m_vs; + + gui::Handlers m_guiHandlers; }; DrapeEngine(Params const & params); diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index d1ccf88856..7854b0d970 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -391,7 +391,21 @@ void FrontendRenderer::TapDetected(m2::PointD const & pt, bool isLongTap) bool FrontendRenderer::SingleTouchFiltration(m2::PointD const & pt, TouchEvent::ETouchType type) { - LOG(LINFO, ("Single Touch")); + if (type == TouchEvent::ETouchType::TOUCH_DOWN) + { + ASSERT(m_activeOverlay == nullptr, ()); + m_activeOverlay = m_guiRenderer->ProcessTapEvent(pt); + return true; // enable filtration + } + else + { + if (m_activeOverlay != nullptr) + { + m_activeOverlay->FinishTapEvent(type == TouchEvent::ETouchType::TOUCH_UP); + m_activeOverlay = nullptr; + } + } + return false; } diff --git a/drape_frontend/frontend_renderer.hpp b/drape_frontend/frontend_renderer.hpp index e399c67a28..028ab8b86f 100755 --- a/drape_frontend/frontend_renderer.hpp +++ b/drape_frontend/frontend_renderer.hpp @@ -42,6 +42,7 @@ class FrontendRenderer : public BaseRenderer public: using TModelViewChanged = function; using TIsCountryLoaded = TIsCountryLoaded; + struct Params : BaseRenderer::Params { Params(ref_ptr commutator, @@ -54,8 +55,7 @@ public: , m_viewport(viewport) , m_modelViewChangedFn(modelViewChangedFn) , m_isCountryLoadedFn(isCountryLoaded) - { - } + {} Viewport m_viewport; TModelViewChanged m_modelViewChangedFn; @@ -139,6 +139,7 @@ private: drape_ptr m_guiRenderer; drape_ptr m_myPositionMark; + ref_ptr m_activeOverlay; dp::UniformValuesStorage m_generalUniforms; diff --git a/drape_gui/button.cpp b/drape_gui/button.cpp index bf6e0007b4..0d077d9ac1 100644 --- a/drape_gui/button.cpp +++ b/drape_gui/button.cpp @@ -10,11 +10,86 @@ namespace gui { -void Button::Draw(Params const & params, ShapeControl & control, ref_ptr texture) +ButtonHandle::ButtonHandle(dp::Anchor anchor, m2::PointF const & size, + dp::TextureManager::ColorRegion const & normalColor, + dp::TextureManager::ColorRegion const & pressedColor, + dp::TOverlayHandler const & tapHandler) + : TBase(anchor, m2::PointF::Zero(), size, tapHandler) + , m_normalColor(normalColor) + , m_pressedColor(pressedColor) + , m_isInPressedState(false) + , m_isContentDirty(false) +{} + +void ButtonHandle::OnTapBegin() +{ + m_isInPressedState = true; + m_isContentDirty = true; +} + +void ButtonHandle::OnTapEnd() +{ + m_isInPressedState = false; + m_isContentDirty = true; +} + +void ButtonHandle::GetAttributeMutation(ref_ptr mutator, + ScreenBase const & screen) const +{ + UNUSED_VALUE(screen); + + if (!m_isContentDirty) + return; + + m_isContentDirty = false; + + size_t const byteCount = sizeof(Button::DynamicVertex) * Button::VerticesCount(); + Button::DynamicVertex * dataPointer = + reinterpret_cast(mutator->AllocateMutationBuffer(byteCount)); + for (int i = 0; i < Button::VerticesCount(); ++i) + dataPointer[i].m_texCoord = m_isInPressedState ? glsl::ToVec2(m_pressedColor.GetTexRect().Center()) : + glsl::ToVec2(m_normalColor.GetTexRect().Center()); + + dp::BindingInfo const & binding = Button::DynamicVertex::GetBindingInfo(); + dp::OverlayHandle::TOffsetNode offsetNode = GetOffsetNode(binding.GetID()); + + dp::MutateNode mutateNode; + mutateNode.m_data = make_ref(dataPointer); + mutateNode.m_region = offsetNode.second; + mutator->AddMutation(offsetNode.first, mutateNode); +} + +namespace +{ + +dp::TextureManager::ColorRegion GetNormalColor(ref_ptr texMgr) +{ + dp::Color const buttonColor = dp::Color(0x0, 0x0, 0x0, 0x99); + dp::TextureManager::ColorRegion region; + texMgr->GetColorRegion(buttonColor, region); + return region; +} + +dp::TextureManager::ColorRegion GetPressedColor(ref_ptr texMgr) +{ + dp::Color const buttonColor = dp::Color(0x0, 0x0, 0x0, 0xCC); + dp::TextureManager::ColorRegion region; + texMgr->GetColorRegion(buttonColor, region); + return region; +} + +} + +constexpr int Button::VerticesCount() +{ + return 4; +} + +void Button::Draw(Params const & params, ShapeControl & control, ref_ptr texMgr) { StaticLabel::LabelResult result; StaticLabel::CacheStaticText(params.m_label, StaticLabel::DefaultDelim, params.m_anchor, - params.m_labelFont, texture, result); + params.m_labelFont, texMgr, result); float textWidth = result.m_boundRect.SizeX(); float halfWidth = my::clamp(textWidth, params.m_minWidth, params.m_maxWidth) * 0.5f; @@ -24,21 +99,23 @@ void Button::Draw(Params const & params, ShapeControl & control, ref_ptrGetColorRegion(buttonColor, region); + dp::TextureManager::ColorRegion normalColor = GetNormalColor(texMgr); + dp::TextureManager::ColorRegion pressedColor = GetPressedColor(texMgr); dp::GLState state(gpu::TEXTURING_PROGRAM, dp::GLState::Gui); - state.SetColorTexture(region.GetTexture()); + state.SetColorTexture(normalColor.GetTexture()); glsl::vec3 position(0.0f, 0.0f, 0.0f); - glsl::vec2 texCoord(glsl::ToVec2(region.GetTexRect().Center())); + glsl::vec2 texCoord(glsl::ToVec2(normalColor.GetTexRect().Center())); - gpu::SolidTexturingVertex vertexes[]{ - gpu::SolidTexturingVertex(position, glsl::vec2(-halfWM, halfHM), texCoord), - gpu::SolidTexturingVertex(position, glsl::vec2(-halfWM, -halfHM), texCoord), - gpu::SolidTexturingVertex(position, glsl::vec2(halfWM, halfHM), texCoord), - gpu::SolidTexturingVertex(position, glsl::vec2(halfWM, -halfHM), texCoord)}; + int const verticesCount = VerticesCount(); + StaticVertex vertexes[verticesCount] + { + StaticVertex(position, glsl::vec2(-halfWM, halfHM)), + StaticVertex(position, glsl::vec2(-halfWM, -halfHM)), + StaticVertex(position, glsl::vec2(halfWM, halfHM)), + StaticVertex(position, glsl::vec2(halfWM, -halfHM)) + }; glsl::vec2 normalOffset(0.0f, 0.0f); if (params.m_anchor & dp::Left) @@ -51,19 +128,26 @@ void Button::Draw(Params const & params, ShapeControl & control, ref_ptr dynData; + for (int i = 0; i < verticesCount; ++i) + dynData.push_back(texCoord); + + dp::AttributeProvider provider(2 /* stream count */, verticesCount); + provider.InitStream(0 /*stream index*/, StaticVertex::GetBindingInfo(), make_ref(vertexes)); + provider.InitStream(1 /*stream index*/, DynamicVertex::GetBindingInfo(), + make_ref(dynData.data())); m2::PointF buttonSize(halfWM + halfWM, halfHM + halfHM); ASSERT(params.m_bodyHandleCreator, ()); dp::Batcher batcher(dp::Batcher::IndexPerQuad, dp::Batcher::VertexPerQuad); dp::SessionGuard guard(batcher, bind(&ShapeControl::AddShape, &control, _1, _2)); batcher.InsertTriangleStrip(state, make_ref(&provider), - params.m_bodyHandleCreator(params.m_anchor, buttonSize)); + params.m_bodyHandleCreator(params.m_anchor, buttonSize, + normalColor, pressedColor)); } // Cache text @@ -87,4 +171,49 @@ void Button::Draw(Params const & params, ShapeControl & control, ref_ptr info; + + if (info == nullptr) + { + info.reset(new dp::BindingInfo(2)); + + dp::BindingDecl & posDecl = info->GetBindingDecl(0); + posDecl.m_attributeName = "a_position"; + posDecl.m_componentCount = 3; + posDecl.m_componentType = gl_const::GLFloatType; + posDecl.m_offset = 0; + posDecl.m_stride = sizeof(StaticVertex); + + dp::BindingDecl & normalDecl = info->GetBindingDecl(1); + normalDecl.m_attributeName = "a_normal"; + normalDecl.m_componentCount = 2; + normalDecl.m_componentType = gl_const::GLFloatType; + normalDecl.m_offset = sizeof(glsl::vec3); + normalDecl.m_stride = posDecl.m_stride; + } + + return *info.get(); +} + +dp::BindingInfo const & Button::DynamicVertex::GetBindingInfo() +{ + static unique_ptr info; + + if (info == nullptr) + { + info.reset(new dp::BindingInfo(1, 1)); + + dp::BindingDecl & colorTexCoordDecl = info->GetBindingDecl(0); + colorTexCoordDecl.m_attributeName = "a_colorTexCoords"; + colorTexCoordDecl.m_componentCount = 2; + colorTexCoordDecl.m_componentType = gl_const::GLFloatType; + colorTexCoordDecl.m_offset = 0; + colorTexCoordDecl.m_stride = sizeof(DynamicVertex); + } + + return *info.get(); +} + } diff --git a/drape_gui/button.hpp b/drape_gui/button.hpp index e1b3a0c6b8..47e5a70452 100644 --- a/drape_gui/button.hpp +++ b/drape_gui/button.hpp @@ -7,11 +7,68 @@ namespace gui { + +class ButtonHandle : public TappableHandle +{ + typedef TappableHandle TBase; + +public: + ButtonHandle(dp::Anchor anchor, m2::PointF const & size, + dp::TextureManager::ColorRegion const & normalColor, + dp::TextureManager::ColorRegion const & pressedColor, + dp::TOverlayHandler const & tapHandler); + + void OnTapBegin() override; + void OnTapEnd() override; + + void GetAttributeMutation(ref_ptr mutator, + ScreenBase const & screen) const override; + +private: + dp::TextureManager::ColorRegion m_normalColor; + dp::TextureManager::ColorRegion m_pressedColor; + bool m_isInPressedState; + mutable bool m_isContentDirty; +}; + class Button { public: + struct StaticVertex + { + StaticVertex() = default; + StaticVertex(glsl::vec3 const & position, glsl::vec2 const & normal) + : m_position(position) + , m_normal(normal) + { + } + + static dp::BindingInfo const & GetBindingInfo(); + + glsl::vec3 m_position; + glsl::vec2 m_normal; + }; + + struct DynamicVertex + { + DynamicVertex() = default; + DynamicVertex(glsl::vec2 const & texCoord) + : m_texCoord(texCoord) + { + } + + static dp::BindingInfo const & GetBindingInfo(); + + glsl::vec2 m_texCoord; + }; + + static constexpr int VerticesCount(); + using TCreatorResult = drape_ptr; - using THandleCreator = function; + using TLabelHandleCreator = function; + using TBodyHandleCreator = function; struct Params { @@ -22,10 +79,10 @@ public: float m_minWidth = 0.0f; float m_maxWidth = 0.0f; float m_margin = 0.0f; - THandleCreator m_bodyHandleCreator; - THandleCreator m_labelHandleCreator; + TBodyHandleCreator m_bodyHandleCreator; + TLabelHandleCreator m_labelHandleCreator; }; - static void Draw(Params const & params, ShapeControl & control, ref_ptr texture); + static void Draw(Params const & params, ShapeControl & control, ref_ptr texMgr); }; } diff --git a/drape_gui/compass.cpp b/drape_gui/compass.cpp index 8c1f76e702..2cef9b082c 100644 --- a/drape_gui/compass.cpp +++ b/drape_gui/compass.cpp @@ -23,15 +23,14 @@ namespace glsl::vec2 m_texCoord; }; - class CompassHandle : public Handle + class CompassHandle : public TappableHandle { public: - CompassHandle(m2::PointF const & pivot, m2::PointF const & size) - : Handle(dp::Center, pivot, size) - { - } + CompassHandle(m2::PointF const & pivot, m2::PointF const & size, dp::TOverlayHandler const & tapHandler) + : TappableHandle(dp::Center, pivot, size, tapHandler) + {} - virtual void Update(ScreenBase const & screen) override + void Update(ScreenBase const & screen) override { float angle = ang::AngleIn2PI(screen.GetAngle()); if (angle < my::DegToRad(5.0) || angle > my::DegToRad(355.0)) @@ -87,7 +86,7 @@ drape_ptr Compass::Draw(ref_ptr tex) const provider.InitStream(0, info, make_ref(&vertexes)); m2::PointF compassSize = region.GetPixelSize(); - drape_ptr handle = make_unique_dp(m_position.m_pixelPivot, compassSize); + drape_ptr handle = make_unique_dp(m_position.m_pixelPivot, compassSize, m_tapHandler); drape_ptr renderer = make_unique_dp(); dp::Batcher batcher(dp::Batcher::IndexPerQuad, dp::Batcher::VertexPerQuad); diff --git a/drape_gui/compass.hpp b/drape_gui/compass.hpp index a646533dbe..d61711cf04 100644 --- a/drape_gui/compass.hpp +++ b/drape_gui/compass.hpp @@ -8,8 +8,14 @@ namespace gui class Compass : public Shape { public: - Compass(gui::Position const & position) : Shape(position) {} + Compass(gui::Position const & position, dp::TOverlayHandler const & tapHandler) + : Shape(position) + , m_tapHandler(tapHandler) + {} drape_ptr Draw(ref_ptr tex) const override; + +private: + dp::TOverlayHandler m_tapHandler; }; } diff --git a/drape_gui/country_status.cpp b/drape_gui/country_status.cpp index b6c357f62b..72b860c27d 100644 --- a/drape_gui/country_status.cpp +++ b/drape_gui/country_status.cpp @@ -14,16 +14,42 @@ namespace gui { namespace { -class CountryStatusHandle : public Handle + +class CountryStatusButtonHandle : public ButtonHandle { - typedef Handle TBase; + using TBase = ButtonHandle; public: - CountryStatusHandle(CountryStatusHelper::ECountryState const state, dp::Anchor anchor, m2::PointF const & size) - : Handle(anchor, m2::PointF::Zero(), size), m_state(state) + CountryStatusButtonHandle(CountryStatusHelper::ECountryState const state, + dp::Anchor anchor, m2::PointF const & size, + dp::TextureManager::ColorRegion const & normalColor, + dp::TextureManager::ColorRegion const & pressedColor, + dp::TOverlayHandler const & tapHandler) + : TBase(anchor, size, normalColor, pressedColor, tapHandler) + , m_state(state) + {} + + void Update(ScreenBase const & screen) override { + SetIsVisible(DrapeGui::GetCountryStatusHelper().IsVisibleForState(m_state)); + TBase::Update(screen); } +private: + CountryStatusHelper::ECountryState m_state; +}; + +class CountryStatusLabelHandle : public Handle +{ + using TBase = Handle; + +public: + CountryStatusLabelHandle(CountryStatusHelper::ECountryState const state, + dp::Anchor anchor, m2::PointF const & size) + : TBase(anchor, m2::PointF::Zero(), size) + , m_state(state) + {} + void Update(ScreenBase const & screen) override { SetIsVisible(DrapeGui::GetCountryStatusHelper().IsVisibleForState(m_state)); @@ -40,9 +66,8 @@ class CountryProgressHandle : public MutableLabelHandle public: CountryProgressHandle(dp::Anchor anchor, CountryStatusHelper::ECountryState const state) - : MutableLabelHandle(anchor, m2::PointF::Zero()), m_state(state) - { - } + : TBase(anchor, m2::PointF::Zero()), m_state(state) + {} void Update(ScreenBase const & screen) override { @@ -58,11 +83,21 @@ private: CountryStatusHelper::ECountryState m_state; }; -drape_ptr CreateHandle(CountryStatusHelper::ECountryState const state, - dp::Anchor anchor, - m2::PointF const & size) +drape_ptr CreateButtonHandle(CountryStatusHelper::ECountryState const state, + dp::Anchor anchor, + m2::PointF const & size, + dp::TextureManager::ColorRegion const & normalColor, + dp::TextureManager::ColorRegion const & pressedColor, + dp::TOverlayHandler const & tapHandler) { - return make_unique_dp(state, anchor, size); + return make_unique_dp(state, anchor, size, normalColor, pressedColor, tapHandler); +} + +drape_ptr CreateLabelHandle(CountryStatusHelper::ECountryState const state, + dp::Anchor anchor, + m2::PointF const & size) +{ + return make_unique_dp(state, anchor, size); } void DrawLabelControl(string const & text, dp::Anchor anchor, dp::Batcher::TFlushFn const & flushFn, @@ -82,7 +117,7 @@ void DrawLabelControl(string const & text, dp::Anchor anchor, dp::Batcher::TFlus dp::Batcher batcher(indexCount, vertexCount); dp::SessionGuard guard(batcher, flushFn); m2::PointF size(result.m_boundRect.SizeX(), result.m_boundRect.SizeY()); - drape_ptr handle = make_unique_dp(state, anchor, size); + drape_ptr handle = make_unique_dp(state, anchor, size); batcher.InsertListOfStrip(result.m_state, make_ref(&provider), move(handle), dp::Batcher::VertexPerQuad); } @@ -104,6 +139,7 @@ void DrawProgressControl(dp::Anchor anchor, dp::Batcher::TFlushFn const & flushF MutableLabelDrawer::Draw(params, mng, flushFn); } + } drape_ptr CountryStatus::Draw(ref_ptr tex) const @@ -125,7 +161,36 @@ drape_ptr CountryStatus::Draw(ref_ptr tex) co { case CountryStatusHelper::CONTROL_TYPE_BUTTON: { - Button::THandleCreator handleCreator = bind(&CreateHandle, state, _1, _2); + CountryStatusHelper::EButtonType buttonType = control.m_buttonType; + auto buttonHandleCreator = [this, buttonType, state](dp::Anchor anchor, m2::PointF const & size, + dp::TextureManager::ColorRegion const & normalColor, + dp::TextureManager::ColorRegion const & pressedColor) + -> drape_ptr + { + switch(buttonType) + { + case CountryStatusHelper::BUTTON_TYPE_MAP: + return CreateButtonHandle(state, anchor, size, + normalColor, pressedColor, + m_downloadMapHandler); + + case CountryStatusHelper::BUTTON_TYPE_MAP_ROUTING: + return CreateButtonHandle(state, anchor, size, + normalColor, pressedColor, + m_downloadMapRoutingHandler); + + case CountryStatusHelper::BUTTON_TRY_AGAIN: + return CreateButtonHandle(state, anchor, size, + normalColor, pressedColor, + m_tryAgainHandler); + default: + ASSERT(false, ()); + } + return nullptr; + }; + + auto labelHandleCreator = bind(&CreateLabelHandle, state, _1, _2); + ShapeControl shapeControl; Button::Params params; params.m_anchor = m_position.m_anchor; @@ -134,8 +199,8 @@ drape_ptr CountryStatus::Draw(ref_ptr tex) co params.m_minWidth = 300; params.m_maxWidth = 600; params.m_margin = 5.0f * DrapeGui::Instance().GetScaleFactor(); - params.m_bodyHandleCreator = handleCreator; - params.m_labelHandleCreator = handleCreator; + params.m_bodyHandleCreator = buttonHandleCreator; + params.m_labelHandleCreator = labelHandleCreator; Button::Draw(params, shapeControl, tex); renderer->AddShapeControl(move(shapeControl)); diff --git a/drape_gui/country_status.hpp b/drape_gui/country_status.hpp index 318261fbd0..c87264ff8e 100644 --- a/drape_gui/country_status.hpp +++ b/drape_gui/country_status.hpp @@ -7,8 +7,22 @@ namespace gui class CountryStatus : public Shape { public: - CountryStatus(Position const & position) : Shape(position) {} + CountryStatus(Position const & position, + dp::TOverlayHandler const & downloadMapHandler, + dp::TOverlayHandler const & downloadMapRoutingHandler, + dp::TOverlayHandler const & tryAgainHandler) + : Shape(position) + , m_downloadMapHandler(downloadMapHandler) + , m_downloadMapRoutingHandler(downloadMapRoutingHandler) + , m_tryAgainHandler(tryAgainHandler) + {} + drape_ptr Draw(ref_ptr tex) const override; + +private: + dp::TOverlayHandler m_downloadMapHandler; + dp::TOverlayHandler m_downloadMapRoutingHandler; + dp::TOverlayHandler m_tryAgainHandler; }; } // namespace gui diff --git a/drape_gui/layer_render.cpp b/drape_gui/layer_render.cpp index 09d0f70012..56b00b84f2 100644 --- a/drape_gui/layer_render.cpp +++ b/drape_gui/layer_render.cpp @@ -64,14 +64,15 @@ void LayerCacher::Resize(int w, int h) } drape_ptr LayerCacher::Recache(Skin::ElementName names, - ref_ptr textures) + ref_ptr textures, + Handlers const & handlers) { drape_ptr renderer = make_unique_dp(); if (names & Skin::Compass) { renderer->AddShapeRenderer(Skin::Compass, - Compass(GetPos(Skin::Compass)).Draw(textures)); + Compass(GetPos(Skin::Compass), handlers.m_onCompassTapped).Draw(textures)); } if (names & Skin::Ruler) @@ -83,7 +84,10 @@ drape_ptr LayerCacher::Recache(Skin::ElementName names, if (names & Skin::CountryStatus) { renderer->AddShapeRenderer(Skin::CountryStatus, - CountryStatus(GetPos(Skin::CountryStatus)).Draw(textures)); + CountryStatus(GetPos(Skin::CountryStatus), + handlers.m_onDownloadMapTapped, + handlers.m_onDownloadMapRoutingTapped, + handlers.m_onTryAgainTapped).Draw(textures)); } if (DrapeGui::Instance().IsCopyrightActive() && (names & Skin::Copyright)) @@ -119,6 +123,14 @@ Position LayerCacher::GetPos(Skin::ElementName name) return m_skin->ResolvePosition(name); } +void Handlers::Reset() +{ + m_onCompassTapped = nullptr; + m_onDownloadMapTapped = nullptr; + m_onDownloadMapRoutingTapped = nullptr; + m_onTryAgainTapped = nullptr; +} + ////////////////////////////////////////////////////////////////////////////////////////// LayerRenderer::~LayerRenderer() @@ -153,6 +165,18 @@ void LayerRenderer::Merge(ref_ptr other) other->m_renderers.clear(); } +ref_ptr LayerRenderer::ProcessTapEvent(m2::PointD const & pt) +{ + for (TRenderers::value_type & r : m_renderers) + { + ref_ptr handle = r.second->ProcessTapEvent(pt); + if (handle != nullptr) + return handle; + } + + return nullptr; +} + void LayerRenderer::DestroyRenderers() { m_renderers.clear(); diff --git a/drape_gui/layer_render.hpp b/drape_gui/layer_render.hpp index 9507b58aa6..cf5664e5aa 100644 --- a/drape_gui/layer_render.hpp +++ b/drape_gui/layer_render.hpp @@ -3,8 +3,9 @@ #include "skin.hpp" #include "shape.hpp" -#include "drape/texture_manager.hpp" #include "drape/gpu_program_manager.hpp" +#include "drape/overlay_handle.hpp" +#include "drape/texture_manager.hpp" #include "geometry/screenbase.hpp" @@ -30,6 +31,8 @@ public: void Render(ref_ptr mng, ScreenBase const & screen); void Merge(ref_ptr other); + ref_ptr ProcessTapEvent(m2::PointD const & pt); + private: void DestroyRenderers(); @@ -41,6 +44,16 @@ private: TRenderers m_renderers; }; +struct Handlers +{ + dp::TOverlayHandler m_onCompassTapped; + dp::TOverlayHandler m_onDownloadMapTapped; + dp::TOverlayHandler m_onDownloadMapRoutingTapped; + dp::TOverlayHandler m_onTryAgainTapped; + + void Reset(); +}; + class LayerCacher { public: @@ -48,7 +61,7 @@ public: void Resize(int w, int h); /// @param names - can be combinations of single flags, or equal AllElements - drape_ptr Recache(Skin::ElementName names, ref_ptr textures); + drape_ptr Recache(Skin::ElementName names, ref_ptr textures, Handlers const & handlers); private: Position GetPos(Skin::ElementName name); diff --git a/drape_gui/shape.cpp b/drape_gui/shape.cpp index b1cb00f40e..637dd15e73 100644 --- a/drape_gui/shape.cpp +++ b/drape_gui/shape.cpp @@ -3,6 +3,8 @@ #include "drape/glsl_func.hpp" #include "drape/utils/projection.hpp" +#include "base/logging.hpp" + namespace gui { Handle::Handle(dp::Anchor anchor, const m2::PointF & pivot, const m2::PointF & size) @@ -35,6 +37,31 @@ void Handle::GetPixelShape(const ScreenBase & screen, dp::OverlayHandle::Rects & UNUSED_VALUE(rects); } +bool TappableHandle::IsTapped(m2::PointD const & pt) const +{ + if (!IsVisible() || !IsValid()) + return false; + + if (m_anchor == dp::Anchor::Center) + { + m2::RectD rect(m_pivot.x - m_size.x * 0.5, m_pivot.y - m_size.y * 0.5, + m_pivot.x + m_size.x * 0.5, m_pivot.y + m_size.y * 0.5); + return rect.IsPointInside(pt); + } + else + { + LOG(LWARNING, ("Tapping on an overlay is not supported. Anchor type = ", m_anchor)); + } + + return false; +} + +void TappableHandle::OnTap() +{ + if (m_tapHandler != nullptr) + m_tapHandler(); +} + ShapeRenderer::~ShapeRenderer() { ForEachShapeInfo([](ShapeControl::ShapeInfo & info) @@ -109,6 +136,24 @@ void ShapeRenderer::ForEachShapeInfo(ShapeRenderer::TShapeInfoEditFn const & fn) }); } +ref_ptr ShapeRenderer::ProcessTapEvent(m2::PointD const & pt) +{ + ref_ptr resultHandle = nullptr; + ForEachShapeInfo([&resultHandle, &pt](ShapeControl::ShapeInfo & shapeInfo) + { + if (shapeInfo.m_handle->IsTapped(pt)) + { + ASSERT(resultHandle == nullptr, ("Overlays cannot be intersected")); + resultHandle = make_ref(shapeInfo.m_handle); + } + }); + + if (resultHandle != nullptr) + resultHandle->OnTapBegin(); + + return resultHandle; +} + ShapeControl::ShapeInfo::ShapeInfo(dp::GLState const & state, drape_ptr && buffer, drape_ptr && handle) diff --git a/drape_gui/shape.hpp b/drape_gui/shape.hpp index 18ac43392a..9c6b678d1a 100644 --- a/drape_gui/shape.hpp +++ b/drape_gui/shape.hpp @@ -35,6 +35,21 @@ protected: mutable m2::PointF m_size; }; +class TappableHandle : public Handle +{ +public: + TappableHandle(dp::Anchor anchor, m2::PointF const & pivot, m2::PointF const & size, dp::TOverlayHandler const & tapHandler) + : Handle(anchor, pivot, size) + , m_tapHandler(tapHandler) + {} + + bool IsTapped(m2::PointD const & pt) const override; + void OnTap() override; + +private: + dp::TOverlayHandler m_tapHandler; +}; + struct ShapeControl { ShapeControl() = default; @@ -74,6 +89,8 @@ public: void AddShape(dp::GLState const & state, drape_ptr && bucket); void AddShapeControl(ShapeControl && control); + ref_ptr ProcessTapEvent(m2::PointD const & pt); + private: friend void ArrangeShapes(ref_ptr, ShapeRenderer::TShapeControlEditFn const &); diff --git a/map/framework.cpp b/map/framework.cpp index a71c7b4517..24746645a0 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -1291,12 +1291,31 @@ void Framework::CreateDrapeEngine(ref_ptr contextFactory, TIsCountryLoadedFn isCountryLoadedFn = bind(&Framework::IsCountryLoaded, this, _1); + gui::Handlers guiHandlers; + guiHandlers.m_onCompassTapped = [this]() + { + LOG(LINFO, ("Compass tapped!")); + //m_informationDisplay.locationState()->OnCompassTaped(); + }; + guiHandlers.m_onDownloadMapTapped = [this]() + { + LOG(LINFO, ("Download map tapped!")); + }; + guiHandlers.m_onDownloadMapRoutingTapped = [this]() + { + LOG(LINFO, ("Download map and routing tapped!")); + }; + guiHandlers.m_onTryAgainTapped = [this]() + { + LOG(LINFO, ("Try again tapped!")); + }; + df::DrapeEngine::Params p(contextFactory, make_ref(&m_stringsBundle), make_ref(m_storageAccessor), df::Viewport(0, 0, w, h), df::MapDataProvider(idReadFn, featureReadFn, resolveCountry,isCountryLoadedFn), - vs); + vs, guiHandlers); m_drapeEngine = make_unique_dp(p); AddViewportListener([this](ScreenBase const & screen)