diff --git a/data/resources-default/default.ui b/data/resources-default/default.ui index 51b96c6f8e..f7f55ac059 100644 --- a/data/resources-default/default.ui +++ b/data/resources-default/default.ui @@ -35,16 +35,4 @@ - - - - - - - - - - - - diff --git a/drape/binding_info.hpp b/drape/binding_info.hpp index 8292e70e43..70e0a27402 100644 --- a/drape/binding_info.hpp +++ b/drape/binding_info.hpp @@ -1,6 +1,7 @@ #pragma once #include "drape/glfunctions.hpp" +#include "drape/glsl_types.hpp" #include "std/string.hpp" #include "std/shared_array.hpp" @@ -41,4 +42,17 @@ protected: uint16_t m_info; }; +template +uint8_t FillDecl(size_t index, string const & attrName, dp::BindingInfo & info, uint8_t offset) +{ + dp::BindingDecl & decl = info.GetBindingDecl(index); + decl.m_attributeName = attrName; + decl.m_componentCount = glsl::GetComponentCount(); + decl.m_componentType = gl_const::GLFloatType; + decl.m_offset = offset; + decl.m_stride = sizeof(TVertexType); + + return sizeof(TFieldType); +} + } // namespace dp diff --git a/drape/glyph_manager.cpp b/drape/glyph_manager.cpp index 3ab6f7fd62..a7f8d6c779 100644 --- a/drape/glyph_manager.cpp +++ b/drape/glyph_manager.cpp @@ -263,7 +263,9 @@ struct UnicodeBlock int GetFontOffset(int idx) const { - ASSERT(!m_fontsWeight.empty(), ()); + if (m_fontsWeight.empty()) + return -1; + int maxWight = 0; int upperBoundWeight = numeric_limits::max(); if (idx != -1) diff --git a/drape/shaders/ruler_vertex_shader.vsh b/drape/shaders/ruler_vertex_shader.vsh index 3bb107ed1c..3e2575c474 100644 --- a/drape/shaders/ruler_vertex_shader.vsh +++ b/drape/shaders/ruler_vertex_shader.vsh @@ -2,6 +2,7 @@ attribute vec2 a_position; attribute vec2 a_normal; attribute vec2 a_colorTexCoords; +uniform vec2 u_position; uniform float u_length; uniform mat4 projection; @@ -9,6 +10,6 @@ varying vec2 v_colorTexCoords; void main(void) { - gl_Position = vec4(a_position + u_length * a_normal, 0, 1) * projection; + gl_Position = vec4(u_position + a_position + u_length * a_normal, 0, 1) * projection; v_colorTexCoords = a_colorTexCoords; } diff --git a/drape_frontend/backend_renderer.cpp b/drape_frontend/backend_renderer.cpp index 42e68e1fdd..8de3005fa3 100644 --- a/drape_frontend/backend_renderer.cpp +++ b/drape_frontend/backend_renderer.cpp @@ -28,12 +28,11 @@ BackendRenderer::BackendRenderer(Params const & params) , m_model(params.m_model) , 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") { - gui::DrapeGui::Instance().SetRecacheSlot([this](gui::Skin::ElementName elements) + gui::DrapeGui::Instance().SetRecacheCountryStatusSlot([this]() { m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread, - make_unique_dp(elements), + make_unique_dp(), MessagePriority::High); }); @@ -50,7 +49,7 @@ BackendRenderer::BackendRenderer(Params const & params) BackendRenderer::~BackendRenderer() { - gui::DrapeGui::Instance().ClearRecacheSlot(); + gui::DrapeGui::Instance().ClearRecacheCountryStatusSlot(); StopThread(); } @@ -59,9 +58,16 @@ unique_ptr BackendRenderer::CreateRoutine() return make_unique(*this); } -void BackendRenderer::RecacheGui(gui::Skin::ElementName elements) +void BackendRenderer::RecacheGui(gui::TWidgetsInitInfo const & initInfo, gui::TWidgetsSizeInfo & sizeInfo) { - drape_ptr layerRenderer = m_guiCacher.Recache(elements, m_texMng); + drape_ptr layerRenderer = m_guiCacher.RecacheWidgets(initInfo, sizeInfo, m_texMng); + drape_ptr outputMsg = make_unique_dp(move(layerRenderer)); + m_commutator->PostMessage(ThreadsCommutator::RenderThread, move(outputMsg), MessagePriority::High); +} + +void BackendRenderer::RecacheCountryStatus() +{ + drape_ptr layerRenderer = m_guiCacher.RecacheCountryStatus(m_texMng); drape_ptr outputMsg = make_unique_dp(move(layerRenderer)); m_commutator->PostMessage(ThreadsCommutator::RenderThread, move(outputMsg), MessagePriority::High); } @@ -88,23 +94,29 @@ void BackendRenderer::AcceptMessage(ref_ptr message) break; } - case Message::Resize: - { - ref_ptr msg = message; - df::Viewport const & v = msg->GetViewport(); - m_guiCacher.Resize(v.GetWidth(), v.GetHeight()); - RecacheGui(gui::Skin::AllElements); - break; - } case Message::InvalidateReadManagerRect: { ref_ptr msg = message; m_readManager->Invalidate(msg->GetTilesForInvalidate()); break; } + case Message::CountryStatusRecache: + { + RecacheCountryStatus(); + break; + } case Message::GuiRecache: { - RecacheGui(static_cast>(message)->GetElements()); + ref_ptr msg = message; + RecacheGui(msg->GetInitInfo(), msg->GetSizeInfoMap()); + break; + } + case Message::GuiLayerLayout: + { + ref_ptr msg = message; + m_commutator->PostMessage(ThreadsCommutator::RenderThread, + make_unique_dp(msg->AcceptLayoutInfo()), + MessagePriority::Normal); break; } case Message::TileReadStarted: diff --git a/drape_frontend/backend_renderer.hpp b/drape_frontend/backend_renderer.hpp index eb34d21826..3fce7356fb 100644 --- a/drape_frontend/backend_renderer.hpp +++ b/drape_frontend/backend_renderer.hpp @@ -46,7 +46,8 @@ protected: unique_ptr CreateRoutine() override; private: - void RecacheGui(gui::Skin::ElementName elements); + void RecacheGui(gui::TWidgetsInitInfo const & initInfo, gui::TWidgetsSizeInfo & sizeInfo); + void RecacheCountryStatus(); private: MapDataProvider m_model; diff --git a/drape_frontend/drape_engine.cpp b/drape_frontend/drape_engine.cpp index 1f53804206..96cf0d9ead 100644 --- a/drape_frontend/drape_engine.cpp +++ b/drape_frontend/drape_engine.cpp @@ -34,7 +34,7 @@ string const LocationStateMode = "LastLocationStateMode"; } -DrapeEngine::DrapeEngine(Params const & params) +DrapeEngine::DrapeEngine(Params && params) : m_viewport(params.m_viewport) { VisualParams::Init(params.m_vs, df::CalculateTileSize(m_viewport.GetWidth(), m_viewport.GetHeight())); @@ -51,6 +51,7 @@ DrapeEngine::DrapeEngine(Params const & params) gui::DrapeGui & guiSubsystem = gui::DrapeGui::Instance(); guiSubsystem.Init(scaleFn, gnLvlFn); guiSubsystem.SetLocalizator(bind(&StringsBundle::GetString, params.m_stringsBundle.get(), _1)); + guiSubsystem.SetSurfaceSize(m2::PointF(m_viewport.GetWidth(), m_viewport.GetHeight())); ConnectDownloadFn(gui::CountryStatusHelper::BUTTON_TYPE_MAP, params.m_model.GetDownloadMapHandler()); ConnectDownloadFn(gui::CountryStatusHelper::BUTTON_TYPE_MAP_ROUTING, params.m_model.GetDownloadMapRoutingHandler()); @@ -77,6 +78,11 @@ DrapeEngine::DrapeEngine(Params const & params) BackendRenderer::Params brParams(frParams.m_commutator, frParams.m_oglContextFactory, frParams.m_texMng, params.m_model); m_backend = make_unique_dp(brParams); + + GuiRecacheMessage::Blocker blocker; + drape_ptr message( new GuiRecacheMessage(blocker, move(params.m_info), m_widgetSizes)); + m_threadCommutator->PostMessage(ThreadsCommutator::ResourceUploadThread, move(message), MessagePriority::High); + blocker.Wait(); } DrapeEngine::~DrapeEngine() @@ -92,8 +98,12 @@ DrapeEngine::~DrapeEngine() void DrapeEngine::Resize(int w, int h) { - m_viewport.SetViewport(0, 0, w, h); - AddUserEvent(ResizeEvent(w, h)); + if (m_viewport.GetHeight() != h || m_viewport.GetWidth() != w) + { + gui::DrapeGui::Instance().SetSurfaceSize(m2::PointF(w, h)); + m_viewport.SetViewport(0, 0, w, h); + AddUserEvent(ResizeEvent(w, h)); + } } void DrapeEngine::AddTouchEvent(TouchEvent const & event) @@ -323,4 +333,16 @@ void DrapeEngine::RemoveRoute(bool deactivateFollowing) MessagePriority::Normal); } +void DrapeEngine::SetWidgetLayout(gui::TWidgetsLayoutInfo && info) +{ + m_threadCommutator->PostMessage(ThreadsCommutator::ResourceUploadThread, + make_unique_dp(move(info)), + MessagePriority::Normal); +} + +gui::TWidgetsSizeInfo const & DrapeEngine::GetWidgetSizes() +{ + return m_widgetSizes; +} + } // namespace df diff --git a/drape_frontend/drape_engine.hpp b/drape_frontend/drape_engine.hpp index 640c54d7b0..6885da5608 100644 --- a/drape_frontend/drape_engine.hpp +++ b/drape_frontend/drape_engine.hpp @@ -37,12 +37,14 @@ public: ref_ptr stringBundle, Viewport const & viewport, MapDataProvider const & model, - double vs) + double vs, + gui::TWidgetsInitInfo && info) : m_factory(factory) , m_stringsBundle(stringBundle) , m_viewport(viewport) , m_model(model) , m_vs(vs) + , m_info(move(info)) { } @@ -51,9 +53,10 @@ public: Viewport m_viewport; MapDataProvider m_model; double m_vs; + gui::TWidgetsInitInfo m_info; }; - DrapeEngine(Params const & params); + DrapeEngine(Params && params); ~DrapeEngine(); void Resize(int w, int h); @@ -98,6 +101,9 @@ public: void AddRoute(m2::PolylineD const & routePolyline, dp::Color const & color); void RemoveRoute(bool deactivateFollowing); + void SetWidgetLayout(gui::TWidgetsLayoutInfo && info); + gui::TWidgetsSizeInfo const & GetWidgetSizes(); + private: void AddUserEvent(UserEvent const & e); void ModelViewChanged(ScreenBase const & screen); @@ -121,6 +127,8 @@ private: location::TMyPositionModeChanged m_myPositionModeChanged; TTapEventInfoFn m_tapListener; TUserPositionChangedFn m_userPositionChangedFn; + + gui::TWidgetsSizeInfo m_widgetSizes; }; } // namespace df diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index d1528a1f5f..dfb4a3c17b 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -187,6 +187,13 @@ void FrontendRenderer::AcceptMessage(ref_ptr message) break; } + case Message::GuiLayerLayout: + { + ASSERT(m_guiRenderer != nullptr, ()); + m_guiRenderer->SetLayout(ref_ptr(message)->GetLayoutInfo()); + break; + } + case Message::StopRendering: { ProcessStopRenderingMessage(); @@ -309,10 +316,6 @@ void FrontendRenderer::OnResize(ScreenBase const & screen) m_myPositionController->SetPixelRect(screen.PixelRect()); m_contextFactory->getDrawContext()->resize(m_viewport.GetWidth(), m_viewport.GetHeight()); RefreshProjection(); - - m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread, - make_unique_dp(m_viewport), - MessagePriority::High); } void FrontendRenderer::AddToRenderGroup(vector> & groups, diff --git a/drape_frontend/message.hpp b/drape_frontend/message.hpp index 7366e06e45..edd5de8c28 100644 --- a/drape_frontend/message.hpp +++ b/drape_frontend/message.hpp @@ -17,14 +17,15 @@ public: UpdateReadManager, InvalidateRect, InvalidateReadManagerRect, - Resize, ClearUserMarkLayer, ChangeUserMarkLayerVisibility, UpdateUserMarkLayer, GuiLayerRecached, GuiRecache, + GuiLayerLayout, MyPositionShape, CountryInfoUpdate, + CountryStatusRecache, StopRendering, ChangeMyPostitionMode, CompassInfo, diff --git a/drape_frontend/message_subclasses.hpp b/drape_frontend/message_subclasses.hpp index 53c34f61d3..c467a60148 100644 --- a/drape_frontend/message_subclasses.hpp +++ b/drape_frontend/message_subclasses.hpp @@ -30,6 +30,47 @@ namespace df { +class BaseBlockingMessage : public Message +{ +public: + struct Blocker + { + void Wait() + { + unique_lock lock(m_lock); + m_signal.wait(lock, [this]{return !m_blocked;} ); + } + + private: + friend class BaseBlockingMessage; + + void Signal() + { + lock_guard lock(m_lock); + m_blocked = false; + m_signal.notify_one(); + } + + private: + mutex m_lock; + condition_variable m_signal; + bool m_blocked = true; + }; + + BaseBlockingMessage(Blocker & blocker) + : m_blocker(blocker) + { + } + + ~BaseBlockingMessage() + { + m_blocker.Signal(); + } + +private: + Blocker & m_blocker; +}; + class BaseTileMessage : public Message { public: @@ -95,20 +136,6 @@ private: drape_ptr m_buffer; }; -class ResizeMessage : public Message -{ -public: - ResizeMessage(Viewport const & viewport) - : m_viewport(viewport) {} - - Type GetType() const override { return Message::Resize; } - - Viewport const & GetViewport() const { return m_viewport; } - -private: - Viewport m_viewport; -}; - class InvalidateRectMessage : public Message { public: @@ -237,19 +264,40 @@ private: drape_ptr m_renderer; }; -class GuiRecacheMessage : public Message +class GuiRecacheMessage : public BaseBlockingMessage { public: - GuiRecacheMessage(gui::Skin::ElementName elements) - : m_elements(elements) + GuiRecacheMessage(Blocker & blocker, gui::TWidgetsInitInfo && initInfo, gui::TWidgetsSizeInfo & resultInfo) + : BaseBlockingMessage(blocker) + , m_initInfo(move(initInfo)) + , m_sizeInfo(resultInfo) { } Type GetType() const override { return Message::GuiRecache;} - gui::Skin::ElementName GetElements() const { return m_elements; } + gui::TWidgetsInitInfo const & GetInitInfo() const { return m_initInfo; } + gui::TWidgetsSizeInfo & GetSizeInfoMap() const { return m_sizeInfo; } private: - gui::Skin::ElementName m_elements; + gui::TWidgetsInitInfo m_initInfo; + gui::TWidgetsSizeInfo & m_sizeInfo; +}; + +class GuiLayerLayoutMessage : public Message +{ +public: + GuiLayerLayoutMessage(gui::TWidgetsLayoutInfo && info) + : m_layoutInfo(move(info)) + { + } + + Type GetType() const override { return GuiLayerLayout; } + + gui::TWidgetsLayoutInfo const & GetLayoutInfo() const { return m_layoutInfo; } + gui::TWidgetsLayoutInfo AcceptLayoutInfo() { return move(m_layoutInfo); } + +private: + gui::TWidgetsLayoutInfo m_layoutInfo; }; class CountryInfoUpdateMessage : public Message @@ -273,6 +321,13 @@ private: bool m_isCountryLoaded; }; +class CountryStatusRecacheMessage : public Message +{ +public: + CountryStatusRecacheMessage() {} + Type GetType() const override { return Message::CountryStatusRecache ;} +}; + class MyPositionShapeMessage : public Message { public: @@ -356,47 +411,6 @@ private: location::RouteMatchingInfo const m_routeInfo; }; -class BaseBlockingMessage : public Message -{ -public: - struct Blocker - { - void Wait() - { - unique_lock lock(m_lock); - m_signal.wait(lock, [this]{return !m_blocked;} ); - } - - private: - friend class BaseBlockingMessage; - - void Signal() - { - lock_guard lock(m_lock); - m_blocked = false; - m_signal.notify_one(); - } - - private: - mutex m_lock; - condition_variable m_signal; - bool m_blocked = true; - }; - - BaseBlockingMessage(Blocker & blocker) - : m_blocker(blocker) - { - } - - ~BaseBlockingMessage() - { - m_blocker.Signal(); - } - -private: - Blocker & m_blocker; -}; - class FindVisiblePOIMessage : public BaseBlockingMessage { public: diff --git a/drape_frontend/user_mark_shapes.cpp b/drape_frontend/user_mark_shapes.cpp index 22ce3da0f1..91e5680152 100644 --- a/drape_frontend/user_mark_shapes.cpp +++ b/drape_frontend/user_mark_shapes.cpp @@ -73,19 +73,6 @@ void AlignVertical(float halfHeight, dp::Anchor anchor, AlignFormingNormals([&halfHeight]{ return glsl::vec2(0.0f, -halfHeight); }, anchor, dp::Top, dp::Bottom, up, down); } -template -uint8_t FillDecl(size_t index, string const & attrName, dp::BindingInfo & info, uint8_t offset) -{ - dp::BindingDecl & decl = info.GetBindingDecl(index); - decl.m_attributeName = attrName; - decl.m_componentCount = glsl::GetComponentCount(); - decl.m_componentType = gl_const::GLFloatType; - decl.m_offset = offset; - decl.m_stride = sizeof(TVertexType); - - return sizeof(TFieldType); -} - struct UserPointVertex : gpu::BaseVertex { UserPointVertex() = default; @@ -101,10 +88,10 @@ struct UserPointVertex : gpu::BaseVertex { dp::BindingInfo info(4); uint8_t offset = 0; - offset += FillDecl(0, "a_position", info, offset); - offset += FillDecl(1, "a_normal", info, offset); - offset += FillDecl(2, "a_colorTexCoords", info, offset); - offset += FillDecl(3, "a_animate", info, offset); + offset += dp::FillDecl(0, "a_position", info, offset); + offset += dp::FillDecl(1, "a_normal", info, offset); + offset += dp::FillDecl(2, "a_colorTexCoords", info, offset); + offset += dp::FillDecl(3, "a_animate", info, offset); return info; } diff --git a/drape_gui/compass.cpp b/drape_gui/compass.cpp index 181abf7f36..1e20274a92 100644 --- a/drape_gui/compass.cpp +++ b/drape_gui/compass.cpp @@ -57,7 +57,8 @@ namespace }; } -drape_ptr Compass::Draw(ref_ptr tex, TTapHandler const & tapHandler) const +drape_ptr Compass::Draw(m2::PointF & compassSize, ref_ptr tex, + TTapHandler const & tapHandler) const { dp::TextureManager::SymbolRegion region; tex->GetSymbolRegion("compass-image", region); @@ -95,7 +96,7 @@ drape_ptr Compass::Draw(ref_ptr tex, TTapHand provider.InitStream(0, info, make_ref(&vertexes)); - m2::PointF compassSize = region.GetPixelSize(); + compassSize = region.GetPixelSize(); drape_ptr handle = make_unique_dp(m_position.m_pixelPivot, compassSize, tapHandler); drape_ptr renderer = make_unique_dp(); diff --git a/drape_gui/compass.hpp b/drape_gui/compass.hpp index f178f0fba6..1a93c74b2d 100644 --- a/drape_gui/compass.hpp +++ b/drape_gui/compass.hpp @@ -12,7 +12,8 @@ public: : Shape(position) {} - drape_ptr Draw(ref_ptr tex, TTapHandler const & tapHandler) const; + drape_ptr Draw(m2::PointF & compassSize, ref_ptr tex, + TTapHandler const & tapHandler) const; }; } diff --git a/drape_gui/copyright_label.cpp b/drape_gui/copyright_label.cpp index 6a67e28c4f..c53900b1d0 100644 --- a/drape_gui/copyright_label.cpp +++ b/drape_gui/copyright_label.cpp @@ -56,7 +56,7 @@ CopyrightLabel::CopyrightLabel(Position const & position) { } -drape_ptr CopyrightLabel::Draw(ref_ptr tex) const +drape_ptr CopyrightLabel::Draw(m2::PointF & size, ref_ptr tex) const { StaticLabel::LabelResult result; StaticLabel::CacheStaticText("Map data © OpenStreetMap", "", m_position.m_anchor, @@ -70,7 +70,7 @@ drape_ptr CopyrightLabel::Draw(ref_ptr tex) c ASSERT(vertexCount % dp::Batcher::VertexPerQuad == 0, ()); size_t indexCount = dp::Batcher::IndexPerQuad * vertexCount / dp::Batcher::VertexPerQuad; - m2::PointF size(result.m_boundRect.SizeX(), result.m_boundRect.SizeY()); + size = m2::PointF(result.m_boundRect.SizeX(), result.m_boundRect.SizeY()); drape_ptr handle = make_unique_dp(m_position.m_anchor, m_position.m_pixelPivot, size); drape_ptr renderer = make_unique_dp(); diff --git a/drape_gui/copyright_label.hpp b/drape_gui/copyright_label.hpp index a0be48986e..9345b19849 100644 --- a/drape_gui/copyright_label.hpp +++ b/drape_gui/copyright_label.hpp @@ -10,7 +10,7 @@ class CopyrightLabel : public Shape using TBase = Shape; public: CopyrightLabel(gui::Position const & position); - drape_ptr Draw(ref_ptr tex) const; + drape_ptr Draw(m2::PointF & size, ref_ptr tex) const; }; } diff --git a/drape_gui/country_status_helper.cpp b/drape_gui/country_status_helper.cpp index c7f2981b01..5e5433bf1d 100644 --- a/drape_gui/country_status_helper.cpp +++ b/drape_gui/country_status_helper.cpp @@ -110,7 +110,7 @@ void CountryStatusHelper::SetState(ECountryState state) { m_state = state; FillControlsForState(); - DrapeGui::Instance().EmitRecacheSignal(Skin::CountryStatus); + DrapeGui::Instance().EmitRecacheCountryStatusSignal(); } CountryStatusHelper::ECountryState CountryStatusHelper::GetState() const diff --git a/drape_gui/drape_gui.cpp b/drape_gui/drape_gui.cpp index dffeb3d5c7..9369b4eb0f 100644 --- a/drape_gui/drape_gui.cpp +++ b/drape_gui/drape_gui.cpp @@ -13,7 +13,7 @@ struct DrapeGui::Impl DrapeGui::TGeneralizationLevelFn m_gnLvlFn; DrapeGui::TLocalizeStringFn m_localizeFn; - DrapeGui::TRecacheSlot m_recacheSlot; + DrapeGui::TRecacheCountryStatusSlot m_recacheSlot; RulerHelper m_rulerHelper; CountryStatusHelper m_countryHelper; @@ -55,6 +55,11 @@ void DrapeGui::Destroy() m_impl.reset(); } +void DrapeGui::SetSurfaceSize(m2::PointF const & size) +{ + m_surfaceSize = size; +} + void DrapeGui::SetLocalizator(const DrapeGui::TLocalizeStringFn & fn) { ASSERT(m_impl != nullptr, ()); @@ -73,22 +78,22 @@ int DrapeGui::GetGeneralization(ScreenBase const & screen) return m_impl->m_gnLvlFn(screen); } -void DrapeGui::SetRecacheSlot(DrapeGui::TRecacheSlot const & fn) +void DrapeGui::SetRecacheCountryStatusSlot(TRecacheCountryStatusSlot const & fn) { ASSERT(m_impl != nullptr, ()); m_impl->m_recacheSlot = fn; } -void DrapeGui::EmitRecacheSignal(Skin::ElementName elements) +void DrapeGui::EmitRecacheCountryStatusSignal() { ASSERT(m_impl != nullptr, ()); if (m_impl->m_recacheSlot) - m_impl->m_recacheSlot(elements); + m_impl->m_recacheSlot(); } -void DrapeGui::ClearRecacheSlot() +void DrapeGui::ClearRecacheCountryStatusSlot() { - SetRecacheSlot(TRecacheSlot()); + SetRecacheCountryStatusSlot(TRecacheCountryStatusSlot()); } string DrapeGui::GetLocalizedString(string const & stringID) const diff --git a/drape_gui/drape_gui.hpp b/drape_gui/drape_gui.hpp index 7e7fcea5d0..5590f7f87a 100644 --- a/drape_gui/drape_gui.hpp +++ b/drape_gui/drape_gui.hpp @@ -11,6 +11,7 @@ #include "std/function.hpp" #include "std/unique_ptr.hpp" +#include "std/atomic.hpp" class ScreenBase; @@ -23,7 +24,7 @@ class CountryStatusHelper; class DrapeGui { public: - using TRecacheSlot = function; + using TRecacheCountryStatusSlot = function; using TScaleFactorFn = function; using TGeneralizationLevelFn = function; using TLocalizeStringFn = function; @@ -37,14 +38,16 @@ public: void Init(TScaleFactorFn const & scaleFn, TGeneralizationLevelFn const & gnLvlFn); void SetLocalizator(TLocalizeStringFn const & fn); void Destroy(); + void SetSurfaceSize(m2::PointF const & size); + m2::PointF GetSurfaceSize() const { return m_surfaceSize; } double GetScaleFactor(); int GetGeneralization(ScreenBase const & screen); string GetLocalizedString(string const & stringID) const; - void SetRecacheSlot(TRecacheSlot const & fn); - void EmitRecacheSignal(Skin::ElementName elements); - void ClearRecacheSlot(); + void SetRecacheCountryStatusSlot(TRecacheCountryStatusSlot const & fn); + void EmitRecacheCountryStatusSignal(); + void ClearRecacheCountryStatusSlot(); bool IsCopyrightActive() const { return m_isCopyrightActive; } void DeactivateCopyright() { m_isCopyrightActive = false; } @@ -66,6 +69,7 @@ private: Shape::TTapHandler m_onCompassTappedHandler; CountryStatus::TButtonHandlers m_buttonHandlers; + atomic m_surfaceSize; }; } diff --git a/drape_gui/drape_gui_tests/skin_tests.cpp b/drape_gui/drape_gui_tests/skin_tests.cpp index c330b4cb5c..39c5dece8b 100644 --- a/drape_gui/drape_gui_tests/skin_tests.cpp +++ b/drape_gui/drape_gui_tests/skin_tests.cpp @@ -6,55 +6,44 @@ UNIT_TEST(ParseDefaultSkinTest) { - gui::DrapeGui::Instance().Init([]{ return 2.0; }, [] (ScreenBase const &) { return 6.0f; }); - gui::Skin skin(gui::ResolveGuiSkinFile("default")); + gui::Skin skin(gui::ResolveGuiSkinFile("default"), 2.0); float width = 600.0f; float height = 800.0f; skin.Resize(width, height); - gui::Position compassPos = skin.ResolvePosition(gui::Skin::ElementName::Compass); + gui::Position compassPos = skin.ResolvePosition(gui::WIDGET_COMPASS); TEST_EQUAL(compassPos.m_anchor, dp::Center, ()); TEST_ALMOST_EQUAL(compassPos.m_pixelPivot.x, 27.0f * 2.0f, ()); TEST_ALMOST_EQUAL(compassPos.m_pixelPivot.y, height - 57.0f * 2.0f, ()); - gui::Position rulerPos = skin.ResolvePosition(gui::Skin::ElementName::Ruler); + gui::Position rulerPos = skin.ResolvePosition(gui::WIDGET_RULER); TEST_EQUAL(rulerPos.m_anchor, dp::Right, ()); TEST_ALMOST_EQUAL(rulerPos.m_pixelPivot.x, width - 6.0f * 2.0f, ()); TEST_ALMOST_EQUAL(rulerPos.m_pixelPivot.y, height - 42.0f * 2.0f, ()); - gui::Position copyRightPos = skin.ResolvePosition(gui::Skin::ElementName::Copyright); + gui::Position copyRightPos = skin.ResolvePosition(gui::WIDGET_COPYRIGHT); TEST_EQUAL(copyRightPos.m_anchor, dp::Right, ()); TEST_ALMOST_EQUAL(copyRightPos.m_pixelPivot.x, width - 6.0f * 2.0f, ()); TEST_ALMOST_EQUAL(copyRightPos.m_pixelPivot.y, height - 42.0f * 2.0f, ()); - gui::Position countryStatusPos = skin.ResolvePosition(gui::Skin::ElementName::CountryStatus); - TEST_EQUAL(countryStatusPos.m_anchor, dp::Center, ()); - TEST_ALMOST_EQUAL(countryStatusPos.m_pixelPivot.x, width / 2.0f, ()); - TEST_ALMOST_EQUAL(countryStatusPos.m_pixelPivot.y, height / 2.0f, ()); - { width = 800.0f; height = 600.0f; skin.Resize(width, height); - gui::Position compassPos = skin.ResolvePosition(gui::Skin::ElementName::Compass); + gui::Position compassPos = skin.ResolvePosition(gui::WIDGET_COMPASS); TEST_EQUAL(compassPos.m_anchor, dp::Center, ()); TEST_ALMOST_EQUAL(compassPos.m_pixelPivot.x, 18.0f * 2.0f, ()); TEST_ALMOST_EQUAL(compassPos.m_pixelPivot.y, height - 11.4f * 2.0f, ()); - gui::Position rulerPos = skin.ResolvePosition(gui::Skin::ElementName::Ruler); + gui::Position rulerPos = skin.ResolvePosition(gui::WIDGET_RULER); TEST_EQUAL(rulerPos.m_anchor, dp::Right, ()); TEST_ALMOST_EQUAL(rulerPos.m_pixelPivot.x, width - 70.4f * 2.0f, ()); TEST_ALMOST_EQUAL(rulerPos.m_pixelPivot.y, height - 10.5f * 2.0f, ()); - gui::Position copyRightPos = skin.ResolvePosition(gui::Skin::ElementName::Copyright); + gui::Position copyRightPos = skin.ResolvePosition(gui::WIDGET_COPYRIGHT); TEST_EQUAL(copyRightPos.m_anchor, dp::Right, ()); TEST_ALMOST_EQUAL(copyRightPos.m_pixelPivot.x, width - 70.4f * 2.0f, ()); TEST_ALMOST_EQUAL(copyRightPos.m_pixelPivot.y, height - 10.5f * 2.0f, ()); - - gui::Position countryStatusPos = skin.ResolvePosition(gui::Skin::ElementName::CountryStatus); - TEST_EQUAL(countryStatusPos.m_anchor, dp::Center, ()); - TEST_ALMOST_EQUAL(countryStatusPos.m_pixelPivot.x, width / 2.0f, ()); - TEST_ALMOST_EQUAL(countryStatusPos.m_pixelPivot.y, height / 2.0f, ()); } } diff --git a/drape_gui/gui_text.cpp b/drape_gui/gui_text.cpp index f865498c0a..c95714bb45 100644 --- a/drape_gui/gui_text.cpp +++ b/drape_gui/gui_text.cpp @@ -112,8 +112,8 @@ StaticLabel::LabelResult::LabelResult() : m_state(gpu::TEXT_PROGRAM, dp::GLState char const * StaticLabel::DefaultDelim = "\n"; void StaticLabel::CacheStaticText(string const & text, char const * delim, - dp::Anchor anchor, dp::FontDecl const & font, - ref_ptr mng, LabelResult & result) + dp::Anchor anchor, dp::FontDecl const & font, + ref_ptr mng, LabelResult & result) { ASSERT(!text.empty(), ()); @@ -213,9 +213,11 @@ void StaticLabel::CacheStaticText(string const & text, char const * delim, else if (anchor & dp::Bottom) yOffset = 0.0f; + float maxLineLength = 0.0; size_t startIndex = 0; for (size_t i = 0; i < ranges.size(); ++i) { + maxLineLength = max(lineLengths[i], maxLineLength); float xOffset = -lineLengths[i] / 2.0f; if (anchor & dp::Left) xOffset = 0; @@ -345,6 +347,18 @@ void MutableLabel::Precache(PrecacheParams const & params, PrecacheResult & resu result.m_buffer[i + 3].m_position.z = depth; depth += 10.0f; } + + uint32_t maxGlyphWidth = 0.0; + uint32_t maxGlyphHeight = 0.0; + for (auto node : m_alphabet) + { + dp::TextureManager::GlyphRegion const & reg = node.second; + m2::PointU pixelSize = reg.GetPixelSize(); + maxGlyphWidth = max(maxGlyphWidth, pixelSize.x); + maxGlyphHeight = max(maxGlyphHeight, pixelSize.y); + } + + result.m_maxPixelSize = m2::PointF(m_maxLength * maxGlyphWidth, maxGlyphHeight); } void MutableLabel::SetText(LabelResult & result, string text) const @@ -481,8 +495,8 @@ void MutableLabelHandle::SetContent(string const & content) } } -void MutableLabelDrawer::Draw(Params const & params, ref_ptr mng, - dp::Batcher::TFlushFn const & flushFn) +m2::PointF MutableLabelDrawer::Draw(Params const & params, ref_ptr mng, + dp::Batcher::TFlushFn const & flushFn) { uint32_t vertexCount = dp::Batcher::VertexPerQuad * params.m_maxLength; uint32_t indexCount = dp::Batcher::IndexPerQuad * params.m_maxLength; @@ -517,6 +531,8 @@ void MutableLabelDrawer::Draw(Params const & params, ref_ptr batcher.InsertListOfStrip(staticData.m_state, make_ref(&provider), move(handle), dp::Batcher::VertexPerQuad); } + + return staticData.m_maxPixelSize; } } diff --git a/drape_gui/gui_text.hpp b/drape_gui/gui_text.hpp index b29e9b0bf1..5cc8c42468 100644 --- a/drape_gui/gui_text.hpp +++ b/drape_gui/gui_text.hpp @@ -49,9 +49,10 @@ public: m2::RectF m_boundRect; }; + /// return pixelSize of text static void CacheStaticText(string const & text, char const * delim, - dp::Anchor anchor, dp::FontDecl const & font, - ref_ptr mng, LabelResult & result); + dp::Anchor anchor, dp::FontDecl const & font, + ref_ptr mng, LabelResult & result); }; //////////////////////////////////////////////////////////////////////////////////////////////// @@ -106,6 +107,7 @@ public: dp::GLState m_state; buffer_vector m_buffer; + m2::PointF m_maxPixelSize; }; struct LabelResult @@ -173,7 +175,8 @@ public: THandleCreator m_handleCreator; }; - static void Draw(Params const & params, ref_ptr mng, - dp::Batcher::TFlushFn const & flushFn); + /// return maximum pixel size + static m2::PointF Draw(Params const & params, ref_ptr mng, + dp::Batcher::TFlushFn const & flushFn); }; } diff --git a/drape_gui/layer_render.cpp b/drape_gui/layer_render.cpp index 26addceac5..de6f96b362 100644 --- a/drape_gui/layer_render.cpp +++ b/drape_gui/layer_render.cpp @@ -17,6 +17,100 @@ namespace gui { +LayerRenderer::~LayerRenderer() +{ + DestroyRenderers(); +} + +void LayerRenderer::Build(ref_ptr mng) +{ + for (TRenderers::value_type & r : m_renderers) + r.second->Build(mng); +} + +void LayerRenderer::Render(ref_ptr mng, ScreenBase const & screen) +{ + DrapeGui::Instance().GetRulerHelper().Update(screen); + for (TRenderers::value_type & r : m_renderers) + r.second->Render(screen, mng); +} + +void LayerRenderer::Merge(ref_ptr other) +{ + for (TRenderers::value_type & r : other->m_renderers) + { + TRenderers::iterator it = m_renderers.find(r.first); + if (it != m_renderers.end()) + it->second = move(r.second); + else + m_renderers.insert(make_pair(r.first, move(r.second))); + } + + other->m_renderers.clear(); +} + +void LayerRenderer::SetLayout(TWidgetsLayoutInfo const & info) +{ + for (auto node : info) + { + auto renderer = m_renderers.find(node.first); + if (renderer != m_renderers.end()) + renderer->second->SetPivot(node.second); + } +} + +void LayerRenderer::DestroyRenderers() +{ + m_renderers.clear(); +} + +void LayerRenderer::AddShapeRenderer(EWidget widget, drape_ptr && shape) +{ + if (shape == nullptr) + return; + + VERIFY(m_renderers.insert(make_pair(widget, move(shape))).second, ()); +} + +bool LayerRenderer::OnTouchDown(m2::RectD const & touchArea) +{ + for (TRenderers::value_type & r : m_renderers) + { + m_activeOverlay = r.second->ProcessTapEvent(touchArea); + if (m_activeOverlay != nullptr) + { + m_activeOverlay->OnTapBegin(); + return true; + } + } + + return false; +} + +void LayerRenderer::OnTouchUp(m2::RectD const & touchArea) +{ + if (m_activeOverlay != nullptr) + { + if (m_activeOverlay->IsTapped(touchArea)) + m_activeOverlay->OnTap(); + + m_activeOverlay->OnTapEnd(); + m_activeOverlay = nullptr; + } +} + +void LayerRenderer::OnTouchCancel(m2::RectD const & touchArea) +{ + UNUSED_VALUE(touchArea); + if (m_activeOverlay != nullptr) + { + m_activeOverlay->OnTapEnd(); + m_activeOverlay = nullptr; + } +} + +//////////////////////////////////////////////////////////////////////////////////// + namespace { @@ -58,163 +152,97 @@ void RegisterButtonHandler(CountryStatus::TButtonHandlers & handlers, &DrapeGui::Instance(), buttonType); } -} +} // namespace -LayerCacher::LayerCacher(string const & deviceType) +drape_ptr LayerCacher::RecacheWidgets(TWidgetsInitInfo const & initInfo, + TWidgetsSizeInfo & sizeInfo, + ref_ptr textures) { - m_skin.reset(new Skin(ResolveGuiSkinFile(deviceType))); -} + using TCacheShape = function renderer, ref_ptr textures)>; + static map cacheFunctions + { + make_pair(WIDGET_COMPASS, bind(&LayerCacher::CacheCompass, this, _1, _2, _3)), + make_pair(WIDGET_RULER, bind(&LayerCacher::CacheRuler, this, _1, _2, _3)), + make_pair(WIDGET_COPYRIGHT, bind(&LayerCacher::CacheCopyright, this, _1, _2, _3)), + make_pair(WIDGET_SCALE_LABLE, bind(&LayerCacher::CacheScaleLabel, this, _1, _2, _3)) + }; -void LayerCacher::Resize(int w, int h) -{ - m_skin->Resize(w, h); -} - -drape_ptr LayerCacher::Recache(Skin::ElementName names, - ref_ptr textures) -{ drape_ptr renderer = make_unique_dp(); - - if (names & Skin::Compass) + for (auto node : initInfo) { - Compass compass = Compass(GetPos(Skin::Compass)); - renderer->AddShapeRenderer(Skin::Compass, compass.Draw(textures, bind(&DrapeGui::CallOnCompassTappedHandler, - &DrapeGui::Instance()))); + auto cacheFunction = cacheFunctions.find(node.first); + if (cacheFunction != cacheFunctions.end()) + sizeInfo[node.first] = cacheFunction->second(node.second, make_ref(renderer), textures); } - if (names & Skin::Ruler) - { - renderer->AddShapeRenderer(Skin::Ruler, - Ruler(GetPos(Skin::Ruler)).Draw(textures)); - } + return renderer; +} - if (names & Skin::CountryStatus) - { - CountryStatus countryStatus = CountryStatus(GetPos(Skin::CountryStatus)); +drape_ptr LayerCacher::RecacheCountryStatus(ref_ptr textures) +{ + m2::PointF surfSize = DrapeGui::Instance().GetSurfaceSize(); + drape_ptr renderer = make_unique_dp(); + CountryStatus countryStatus = CountryStatus(Position(surfSize * 0.5, dp::Center)); - CountryStatus::TButtonHandlers handlers; - RegisterButtonHandler(handlers, CountryStatusHelper::BUTTON_TYPE_MAP); - RegisterButtonHandler(handlers, CountryStatusHelper::BUTTON_TYPE_MAP_ROUTING); - RegisterButtonHandler(handlers, CountryStatusHelper::BUTTON_TRY_AGAIN); + CountryStatus::TButtonHandlers handlers; + RegisterButtonHandler(handlers, CountryStatusHelper::BUTTON_TYPE_MAP); + RegisterButtonHandler(handlers, CountryStatusHelper::BUTTON_TYPE_MAP_ROUTING); + RegisterButtonHandler(handlers, CountryStatusHelper::BUTTON_TRY_AGAIN); - renderer->AddShapeRenderer(Skin::CountryStatus, countryStatus.Draw(textures, handlers)); - } + renderer->AddShapeRenderer(WIDGET_COUNTRY_STATUS, countryStatus.Draw(textures, handlers)); + return renderer; +} - if (DrapeGui::Instance().IsCopyrightActive() && (names & Skin::Copyright)) - { - renderer->AddShapeRenderer(Skin::Copyright, - CopyrightLabel(GetPos(Skin::Copyright)).Draw(textures)); - } +m2::PointF LayerCacher::CacheCompass(Position const & position, ref_ptr renderer, + ref_ptr textures) +{ + m2::PointF compassSize; + Compass compass = Compass(position); + drape_ptr shape = compass.Draw(compassSize, textures, bind(&DrapeGui::CallOnCompassTappedHandler, + &DrapeGui::Instance())); + renderer->AddShapeRenderer(WIDGET_COMPASS, move(shape)); -#ifdef DEBUG + return compassSize; +} + +m2::PointF LayerCacher::CacheRuler(Position const & position, ref_ptr renderer, + ref_ptr textures) +{ + m2::PointF rulerSize; + renderer->AddShapeRenderer(WIDGET_RULER, + Ruler(position).Draw(rulerSize, textures)); + return rulerSize; +} + +m2::PointF LayerCacher::CacheCopyright(Position const & position, ref_ptr renderer, + ref_ptr textures) +{ + m2::PointF size; + renderer->AddShapeRenderer(WIDGET_COPYRIGHT, + CopyrightLabel(position).Draw(size, textures)); + + return size; +} + +m2::PointF LayerCacher::CacheScaleLabel(Position const & position, ref_ptr renderer, ref_ptr textures) +{ MutableLabelDrawer::Params params; params.m_alphabet = "Scale: 1234567890"; params.m_maxLength = 10; - params.m_anchor = dp::LeftBottom; + params.m_anchor = position.m_anchor; params.m_font = DrapeGui::GetGuiTextFont(); - params.m_pivot = m2::PointF::Zero(); + params.m_pivot = position.m_pixelPivot; params.m_handleCreator = [](dp::Anchor, m2::PointF const &) { return make_unique_dp(); }; drape_ptr scaleRenderer = make_unique_dp(); - MutableLabelDrawer::Draw(params, textures, bind(&ShapeRenderer::AddShape, scaleRenderer.get(), _1, _2)); + m2::PointF size = MutableLabelDrawer::Draw(params, textures, bind(&ShapeRenderer::AddShape, scaleRenderer.get(), _1, _2)); - renderer->AddShapeRenderer(Skin::ScaleLabel, move(scaleRenderer)); -#endif - - return renderer; -} - -Position LayerCacher::GetPos(Skin::ElementName name) -{ - return m_skin->ResolvePosition(name); -} - -////////////////////////////////////////////////////////////////////////////////////////// - -LayerRenderer::~LayerRenderer() -{ - DestroyRenderers(); -} - -void LayerRenderer::Build(ref_ptr mng) -{ - for (TRenderers::value_type & r : m_renderers) - r.second->Build(mng); -} - -void LayerRenderer::Render(ref_ptr mng, ScreenBase const & screen) -{ - DrapeGui::Instance().GetRulerHelper().Update(screen); - for (TRenderers::value_type & r : m_renderers) - r.second->Render(screen, mng); -} - -void LayerRenderer::Merge(ref_ptr other) -{ - for (TRenderers::value_type & r : other->m_renderers) - { - TRenderers::iterator it = m_renderers.find(r.first); - if (it != m_renderers.end()) - it->second = move(r.second); - else - m_renderers.insert(make_pair(r.first, move(r.second))); - } - - other->m_renderers.clear(); -} - -void LayerRenderer::DestroyRenderers() -{ - m_renderers.clear(); -} - -void LayerRenderer::AddShapeRenderer(Skin::ElementName name, drape_ptr && shape) -{ - if (shape == nullptr) - return; - - VERIFY(m_renderers.insert(make_pair(name, move(shape))).second, ()); -} - -bool LayerRenderer::OnTouchDown(m2::RectD const & touchArea) -{ - for (TRenderers::value_type & r : m_renderers) - { - m_activeOverlay = r.second->ProcessTapEvent(touchArea); - if (m_activeOverlay != nullptr) - { - m_activeOverlay->OnTapBegin(); - return true; - } - } - - return false; -} - -void LayerRenderer::OnTouchUp(m2::RectD const & touchArea) -{ - if (m_activeOverlay != nullptr) - { - if (m_activeOverlay->IsTapped(touchArea)) - m_activeOverlay->OnTap(); - - m_activeOverlay->OnTapEnd(); - m_activeOverlay = nullptr; - } -} - -void LayerRenderer::OnTouchCancel(m2::RectD const & touchArea) -{ - UNUSED_VALUE(touchArea); - if (m_activeOverlay != nullptr) - { - m_activeOverlay->OnTapEnd(); - m_activeOverlay = nullptr; - } + renderer->AddShapeRenderer(WIDGET_SCALE_LABLE, move(scaleRenderer)); + return size; } } diff --git a/drape_gui/layer_render.hpp b/drape_gui/layer_render.hpp index ea566ba732..9a48aa1aa8 100644 --- a/drape_gui/layer_render.hpp +++ b/drape_gui/layer_render.hpp @@ -29,6 +29,7 @@ public: void Build(ref_ptr mng); void Render(ref_ptr mng, ScreenBase const & screen); void Merge(ref_ptr other); + void SetLayout(gui::TWidgetsLayoutInfo const & info); bool OnTouchDown(m2::RectD const & touchArea); void OnTouchUp(m2::RectD const & touchArea); @@ -38,10 +39,10 @@ private: void DestroyRenderers(); friend class LayerCacher; - void AddShapeRenderer(Skin::ElementName name, drape_ptr && shape); + void AddShapeRenderer(EWidget widget, drape_ptr && shape); private: - typedef map > TRenderers; + typedef map > TRenderers; TRenderers m_renderers; ref_ptr m_activeOverlay; @@ -50,17 +51,16 @@ private: class LayerCacher { public: - LayerCacher(string const & deviceType); - - 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 RecacheWidgets(TWidgetsInitInfo const & initInfo, + TWidgetsSizeInfo & sizeInfo, + ref_ptr textures); + drape_ptr RecacheCountryStatus(ref_ptr texMng); private: - Position GetPos(Skin::ElementName name); - -private: - unique_ptr m_skin; + m2::PointF CacheCompass(Position const & position, ref_ptr renderer, ref_ptr textures); + m2::PointF CacheRuler(Position const & position, ref_ptr renderer, ref_ptr textures); + m2::PointF CacheCopyright(Position const & position, ref_ptr renderer, ref_ptr textures); + m2::PointF CacheScaleLabel(Position const & position, ref_ptr renderer, ref_ptr textures); }; } diff --git a/drape_gui/ruler.cpp b/drape_gui/ruler.cpp index 48599074fb..5bdfb22de4 100644 --- a/drape_gui/ruler.cpp +++ b/drape_gui/ruler.cpp @@ -33,26 +33,10 @@ struct RulerVertex dp::BindingInfo GetBindingInfo() { dp::BindingInfo info(3); - dp::BindingDecl & posDecl = info.GetBindingDecl(0); - posDecl.m_attributeName = "a_position"; - posDecl.m_componentCount = 2; - posDecl.m_componentType = gl_const::GLFloatType; - posDecl.m_offset = 0; - posDecl.m_stride = sizeof(RulerVertex); - - 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::vec2); - normalDecl.m_stride = posDecl.m_stride; - - dp::BindingDecl & texDecl = info.GetBindingDecl(2); - texDecl.m_attributeName = "a_colorTexCoords"; - texDecl.m_componentCount = 2; - texDecl.m_componentType = gl_const::GLFloatType; - texDecl.m_offset = 2 * sizeof(glsl::vec2); - texDecl.m_stride = posDecl.m_stride; + uint8_t offset = 0; + offset += dp::FillDecl(0, "a_position", info, offset); + offset += dp::FillDecl(1, "a_normal", info, offset); + offset += dp::FillDecl(2, "a_colorTexCoords", info, offset); return info; } @@ -74,6 +58,7 @@ public: { m_size = m2::PointF(helper.GetRulerPixelLength(), 2 * helper.GetRulerHalfHeight()); m_uniforms.SetFloatValue("u_length", helper.GetRulerPixelLength()); + m_uniforms.SetFloatValue("u_position", m_pivot.x, m_pivot.y); } } }; @@ -101,33 +86,40 @@ public: TBase::Update(screen); } + void SetPivot(glsl::vec2 const & pivot) override + { + RulerHelper & helper = DrapeGui::GetRulerHelper(); + TBase::SetPivot(pivot + glsl::vec2(0.0, helper.GetVerticalTextOffset() - helper.GetRulerHalfHeight())); + } + private: bool m_firstUpdate; }; } -drape_ptr Ruler::Draw(ref_ptr tex) const +drape_ptr Ruler::Draw(m2::PointF & size, ref_ptr tex) const { ShapeControl control; - DrawRuler(control, tex); - DrawText(control, tex); + size = m2::PointF::Zero(); + DrawRuler(size, control, tex); + DrawText(size, control, tex); drape_ptr renderer = make_unique_dp(); renderer->AddShapeControl(move(control)); return renderer; } -void Ruler::DrawRuler(ShapeControl & control, ref_ptr tex) const +void Ruler::DrawRuler(m2::PointF & size, ShapeControl & control, ref_ptr tex) const { buffer_vector data; dp::TextureManager::ColorRegion reg; tex->GetColorRegion(DrapeGui::GetGuiTextFont().m_color, reg); - glsl::vec2 pivot = glsl::ToVec2(m_position.m_pixelPivot); glsl::vec2 texCoord = glsl::ToVec2(reg.GetTexRect().Center()); float h = DrapeGui::GetRulerHelper().GetRulerHalfHeight(); + size += m2::PointF(DrapeGui::GetRulerHelper().GetMaxRulerPixelLength(), 2.0 * h); glsl::vec2 normals[] = { @@ -141,10 +133,10 @@ void Ruler::DrawRuler(ShapeControl & control, ref_ptr tex) c else if (anchor & dp::Right) normals[1] = glsl::vec2(0.0, 0.0); - data.push_back(RulerVertex(pivot + glsl::vec2(0.0, h), normals[0], texCoord)); - data.push_back(RulerVertex(pivot + glsl::vec2(0.0, -h), normals[0], texCoord)); - data.push_back(RulerVertex(pivot + glsl::vec2(0.0, h), normals[1], texCoord)); - data.push_back(RulerVertex(pivot + glsl::vec2(0.0, -h), normals[1], texCoord)); + data.push_back(RulerVertex(glsl::vec2(0.0, h), normals[0], texCoord)); + data.push_back(RulerVertex(glsl::vec2(0.0, -h), normals[0], texCoord)); + data.push_back(RulerVertex(glsl::vec2(0.0, h), normals[1], texCoord)); + data.push_back(RulerVertex(glsl::vec2(0.0, -h), normals[1], texCoord)); dp::GLState state(gpu::RULER_PROGRAM, dp::GLState::Gui); state.SetColorTexture(reg.GetTexture()); @@ -160,7 +152,7 @@ void Ruler::DrawRuler(ShapeControl & control, ref_ptr tex) c } } -void Ruler::DrawText(ShapeControl & control, ref_ptr tex) const +void Ruler::DrawText(m2::PointF & size, ShapeControl & control, ref_ptr tex) const { string alphabet; size_t maxTextLength; @@ -179,7 +171,8 @@ void Ruler::DrawText(ShapeControl & control, ref_ptr tex) co return make_unique_dp(anchor, pivot); }; - MutableLabelDrawer::Draw(params, tex, bind(&ShapeControl::AddShape, &control, _1, _2)); + m2::PointF textSize = MutableLabelDrawer::Draw(params, tex, bind(&ShapeControl::AddShape, &control, _1, _2)); + size.y += (textSize.y + abs(helper.GetVerticalTextOffset())); } } diff --git a/drape_gui/ruler.hpp b/drape_gui/ruler.hpp index 16a25d603f..1ec7b4d91a 100644 --- a/drape_gui/ruler.hpp +++ b/drape_gui/ruler.hpp @@ -9,11 +9,11 @@ class Ruler : public Shape { public: Ruler(gui::Position const & position) : Shape(position) {} - drape_ptr Draw(ref_ptr tex) const; + drape_ptr Draw(m2::PointF & size, ref_ptr tex) const; private: - void DrawRuler(ShapeControl & control, ref_ptr tex) const; - void DrawText(ShapeControl & control, ref_ptr tex) const; + void DrawRuler(m2::PointF & size, ShapeControl & control, ref_ptr tex) const; + void DrawText(m2::PointF & size, ShapeControl & control, ref_ptr tex) const; }; } diff --git a/drape_gui/ruler_helper.cpp b/drape_gui/ruler_helper.cpp index 383ce30f8e..f7b54c6041 100644 --- a/drape_gui/ruler_helper.cpp +++ b/drape_gui/ruler_helper.cpp @@ -149,6 +149,11 @@ float RulerHelper::GetRulerPixelLength() const return m_pixelLength; } +float RulerHelper::GetMaxRulerPixelLength() const +{ + return MinPixelWidth * 3.0 / 2.0; +} + int RulerHelper::GetVerticalTextOffset() const { return -5 * DrapeGui::Instance().GetScaleFactor(); diff --git a/drape_gui/ruler_helper.hpp b/drape_gui/ruler_helper.hpp index fd024dac35..338dffaa15 100644 --- a/drape_gui/ruler_helper.hpp +++ b/drape_gui/ruler_helper.hpp @@ -17,6 +17,7 @@ public: float GetRulerHalfHeight() const; float GetRulerPixelLength() const; + float GetMaxRulerPixelLength() const; int GetVerticalTextOffset() const; bool IsTextDirty() const; string const & GetRulerText() const; diff --git a/drape_gui/shape.cpp b/drape_gui/shape.cpp index 54d106a308..7c1ef4feec 100644 --- a/drape_gui/shape.cpp +++ b/drape_gui/shape.cpp @@ -118,6 +118,15 @@ void ShapeRenderer::AddShapeControl(ShapeControl && control) m_shapes.push_back(move(control)); } +void ShapeRenderer::SetPivot(m2::PointF const & pivot) +{ + for (ShapeControl & control : m_shapes) + { + for (ShapeControl::ShapeInfo & info : control.m_shapesInfo) + info.m_handle->SetPivot(glsl::ToVec2(pivot)); + } +} + void ShapeRenderer::ForEachShapeControl(TShapeControlEditFn const & fn) { for_each(m_shapes.begin(), m_shapes.end(), fn); diff --git a/drape_gui/shape.hpp b/drape_gui/shape.hpp index f9be811c79..3152a19ea3 100644 --- a/drape_gui/shape.hpp +++ b/drape_gui/shape.hpp @@ -32,7 +32,7 @@ public: virtual void GetPixelShape(ScreenBase const & screen, Rects & rects) const override; m2::PointF GetSize() const { return m_size; } - void SetPivot(glsl::vec2 const & pivot) { m_pivot = pivot; } + virtual void SetPivot(glsl::vec2 const & pivot) { m_pivot = pivot; } protected: dp::UniformValuesStorage m_uniforms; @@ -89,6 +89,8 @@ public: void AddShape(dp::GLState const & state, drape_ptr && bucket); void AddShapeControl(ShapeControl && control); + void SetPivot(m2::PointF const & pivot); + ref_ptr ProcessTapEvent(m2::RectD const & touchArea); private: diff --git a/drape_gui/skin.cpp b/drape_gui/skin.cpp index a606adde99..5d44f296a7 100644 --- a/drape_gui/skin.cpp +++ b/drape_gui/skin.cpp @@ -1,5 +1,4 @@ #include "skin.hpp" -#include "drape_gui.hpp" #include "platform/platform.hpp" #include "coding/parse_xml.hpp" @@ -118,7 +117,7 @@ private: class SkinLoader { public: - explicit SkinLoader(map > & skin) + explicit SkinLoader(map > & skin) : m_skin(skin) {} bool Push(string const & element) @@ -130,13 +129,11 @@ public: m_inElement = true; if (element == "ruler") - m_currentElement = Skin::ElementName::Ruler; + m_currentElement = WIDGET_RULER; else if (element == "compass") - m_currentElement = Skin::ElementName::Compass; + m_currentElement = WIDGET_COMPASS; else if (element == "copyright") - m_currentElement = Skin::ElementName::Copyright; - else if (element == "country_status") - m_currentElement = Skin::ElementName::CountryStatus; + m_currentElement = WIDGET_COPYRIGHT; else ASSERT(false, ()); } @@ -196,10 +193,10 @@ private: bool m_inConfiguration = false; bool m_inElement = false; - Skin::ElementName m_currentElement = Skin::ElementName::Ruler; + EWidget m_currentElement = WIDGET_RULER; ResolverParser m_parser; - map > & m_skin; + map > & m_skin; }; } @@ -247,7 +244,8 @@ void PositionResolver::SetOffsetY(float y) m_offset.y = y; } -Skin::Skin(ReaderPtr const & reader) +Skin::Skin(ReaderPtr const & reader, float visualScale) + : m_visualScale(visualScale) { SkinLoader loader(m_resolvers); ReaderSource > source(reader); @@ -255,13 +253,13 @@ Skin::Skin(ReaderPtr const & reader) LOG(LERROR, ("Error parsing gui skin")); } -Position Skin::ResolvePosition(ElementName name) +Position Skin::ResolvePosition(EWidget name) { // check that name have only one bit ASSERT((static_cast(name) & (static_cast(name) - 1)) == 0, ()); TResolversPair const & resolvers = m_resolvers[name]; PositionResolver const & resolver = (m_displayWidth < m_displayHeight) ? resolvers.first : resolvers.second; - return resolver.Resolve(m_displayWidth, m_displayHeight, DrapeGui::Instance().GetScaleFactor()); + return resolver.Resolve(m_displayWidth, m_displayHeight, m_visualScale); } void Skin::Resize(int w, int h) diff --git a/drape_gui/skin.hpp b/drape_gui/skin.hpp index 71b701033a..d1f059a417 100644 --- a/drape_gui/skin.hpp +++ b/drape_gui/skin.hpp @@ -9,9 +9,23 @@ namespace gui { +enum EWidget +{ + WIDGET_RULER = 0x1, + WIDGET_COMPASS = 0x2, + WIDGET_COPYRIGHT = 0x4, + WIDGET_SCALE_LABLE = 0x8, + /// WIDGET_COUNTRY_STATUS - controlled by rendering kernel. Don't use it in platform code + WIDGET_COUNTRY_STATUS = 0x8000 +}; + struct Position { Position() : m_pixelPivot(m2::PointF::Zero()), m_anchor(dp::Center) {} + explicit Position(dp::Anchor anchor) + : m_pixelPivot(m2::PointF::Zero()) + , m_anchor(anchor) {} + Position(m2::PointF const & pt, dp::Anchor anchor) : m_pixelPivot(pt) , m_anchor(anchor) {} @@ -20,6 +34,13 @@ struct Position dp::Anchor m_anchor; }; +/// TWidgetsInitInfo - static information about gui widgets (geometry align) +using TWidgetsInitInfo = map; +/// TWidgetsLayoutInfo - dynamic info. Pivot point of each widget in pixel coordinates +using TWidgetsLayoutInfo = map; +/// TWidgetsSizeInfo - info about widget pixel sizes +using TWidgetsSizeInfo = TWidgetsLayoutInfo; + class PositionResolver { public: @@ -38,33 +59,30 @@ private: class Skin { public: - enum ElementName - { - CountryStatus = 0x1, - Ruler = 0x2, - Compass = 0x4, - Copyright = 0x8, - AllElements = CountryStatus | Ruler | Compass | Copyright, - // It's drawing only in debug and not depend from elements flag. It's not part of "AllElements" - ScaleLabel = 0x8000 - }; - - explicit Skin(ReaderPtr const & reader); + Skin(ReaderPtr const & reader, float visualScale); /// @param name - must be single flag, not combination - Position ResolvePosition(ElementName name); + Position ResolvePosition(EWidget name); void Resize(int w, int h); int GetWidth() const { return m_displayWidth; } int GetHeight() const { return m_displayHeight; } + template + void ForEach(ToDo todo) + { + for (auto node : m_resolvers) + todo(node.first, ResolvePosition(node.first)); + } + private: /// TResolversPair.first - Portrait (when weight < height) /// TResolversPair.second - Landscape (when weight >= height) typedef pair TResolversPair; - map m_resolvers; + map m_resolvers; int m_displayWidth; int m_displayHeight; + float m_visualScale; }; ReaderPtr ResolveGuiSkinFile(string const & deviceType); diff --git a/map/framework.cpp b/map/framework.cpp index 90bff7cdcf..2b24d4bb99 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -1305,7 +1305,7 @@ bool Framework::GetDistanceAndAzimut(m2::PointD const & point, return (d < 25000.0); } -void Framework::CreateDrapeEngine(ref_ptr contextFactory, float vs, int w, int h) +void Framework::CreateDrapeEngine(ref_ptr contextFactory, DrapeCreationParams && params) { using TReadIDsFn = df::MapDataProvider::TReadIDsFn; using TReadFeaturesFn = df::MapDataProvider::TReadFeaturesFn; @@ -1347,19 +1347,20 @@ void Framework::CreateDrapeEngine(ref_ptr contextFactory, df::DrapeEngine::Params p(contextFactory, make_ref(&m_stringsBundle), - df::Viewport(0, 0, w, h), + df::Viewport(0, 0, params.m_surfaceWidth, params.m_surfaceHeight), df::MapDataProvider(idReadFn, featureReadFn, updateCountryIndex, isCountryLoadedFn, downloadMapFn, downloadMapRoutingFn, downloadRetryFn), - vs); + params.m_visualScale, + move(params.m_widgetsInitInfo)); - m_drapeEngine = make_unique_dp(p); + m_drapeEngine = make_unique_dp(move(p)); AddViewportListener([this](ScreenBase const & screen) { m_currentMovelView = screen; }); m_drapeEngine->SetTapEventInfoListener(bind(&Framework::OnTapEvent, this, _1, _2, _3, _4)); m_drapeEngine->SetUserPositionListener(bind(&Framework::OnUserPositionChanged, this, _1)); - OnSize(w, h); + OnSize(params.m_surfaceWidth, params.m_surfaceHeight); } ref_ptr Framework::GetDrapeEngine() @@ -1395,11 +1396,18 @@ void Framework::SetupMeasurementSystem() Settings::Get("Units", units); m_routingSession.SetTurnNotificationsUnits(units); +} +void Framework::SetWidgetLayout(gui::TWidgetsLayoutInfo && layout) +{ + ASSERT(m_drapeEngine != nullptr, ()); + m_drapeEngine->SetWidgetLayout(move(layout)); +} - //m_informationDisplay.measurementSystemChanged(); - ///@TODO UVR - //Invalidate(); +gui::TWidgetsSizeInfo const & Framework::GetWidgetSizes() +{ + ASSERT(m_drapeEngine != nullptr, ()); + return m_drapeEngine->GetWidgetSizes(); } string Framework::GetCountryCode(m2::PointD const & pt) const diff --git a/map/framework.hpp b/map/framework.hpp index 2fef96f2af..868318330f 100644 --- a/map/framework.hpp +++ b/map/framework.hpp @@ -11,6 +11,9 @@ #include "drape_frontend/drape_engine.hpp" #include "drape_frontend/user_event_stream.hpp" + +#include "drape_gui/skin.hpp" + #include "drape/oglcontextfactory.hpp" #include "indexer/data_header.hpp" @@ -264,16 +267,26 @@ private: //@} public: - void CreateDrapeEngine(ref_ptr contextFactory, float vs, int w, int h); + struct DrapeCreationParams + { + float m_visualScale; + int m_surfaceWidth; + int m_surfaceHeight; + + gui::TWidgetsInitInfo m_widgetsInitInfo; + }; + + void CreateDrapeEngine(ref_ptr contextFactory, DrapeCreationParams && params); ref_ptr GetDrapeEngine(); void DestroyDrapeEngine(); void SetMapStyle(MapStyle mapStyle); MapStyle GetMapStyle() const; - void PrepareToShutdown(); + void SetWidgetLayout(gui::TWidgetsLayoutInfo && layout); + const gui::TWidgetsSizeInfo & GetWidgetSizes(); - void SetupMeasurementSystem(); + void PrepareToShutdown(); private: void InitCountryInfoGetter(); diff --git a/qt/draw_widget.cpp b/qt/draw_widget.cpp index fe6f517ae5..fccd3e1266 100644 --- a/qt/draw_widget.cpp +++ b/qt/draw_widget.cpp @@ -109,7 +109,7 @@ bool IsLocationEmulation(QMouseEvent * e) void DrawWidget::UpdateAfterSettingsChanged() { - m_framework->SetupMeasurementSystem(); + m_framework->EnterForeground(); } void DrawWidget::LoadState() @@ -170,8 +170,21 @@ bool IsLocationEmulation(QMouseEvent * e) void DrawWidget::CreateEngine() { - m_framework->CreateDrapeEngine(make_ref(m_contextFactory), m_ratio, - m_ratio * width(), m_ratio * height()); + Framework::DrapeCreationParams p; + p.m_surfaceWidth = m_ratio * width(); + p.m_surfaceHeight = m_ratio * height(); + p.m_visualScale = m_ratio; + + m_skin.reset(new gui::Skin(gui::ResolveGuiSkinFile("default"), m_ratio)); + m_skin->Resize(p.m_surfaceWidth, p.m_surfaceHeight); + m_skin->ForEach([&p](gui::EWidget widget, gui::Position const & pos) + { + p.m_widgetsInitInfo[widget] = pos; + }); + + p.m_widgetsInitInfo[gui::WIDGET_SCALE_LABLE] = gui::Position(dp::LeftBottom); + + m_framework->CreateDrapeEngine(make_ref(m_contextFactory), move(p)); m_framework->AddViewportListener(bind(&DrawWidget::OnViewportChanged, this, _1)); } @@ -315,7 +328,21 @@ bool IsLocationEmulation(QMouseEvent * e) void DrawWidget::sizeChanged(int) { - m_framework->OnSize(m_ratio * width(), m_ratio * height()); + float w = m_ratio * width(); + float h = m_ratio * height(); + m_framework->OnSize(w, h); + if (m_skin) + { + m_skin->Resize(w, h); + + gui::TWidgetsLayoutInfo layout; + m_skin->ForEach([&layout](gui::EWidget w, gui::Position const & pos) + { + layout[w] = pos.m_pixelPivot; + }); + + m_framework->SetWidgetLayout(move(layout)); + } } void DrawWidget::SubmitFakeLocationPoint(m2::PointD const & pt) diff --git a/qt/draw_widget.hpp b/qt/draw_widget.hpp index 37dd51afdb..35276d9951 100644 --- a/qt/draw_widget.hpp +++ b/qt/draw_widget.hpp @@ -5,6 +5,7 @@ #include "map/framework.hpp" #include "drape_frontend/drape_engine.hpp" +#include "drape_gui/skin.hpp" #include "std/unique_ptr.hpp" @@ -99,5 +100,7 @@ namespace qt bool m_emulatingLocation; void InitRenderPolicy(); + + unique_ptr m_skin; }; } diff --git a/qt/mainwindow.cpp b/qt/mainwindow.cpp index 841623bd23..446a4195ed 100644 --- a/qt/mainwindow.cpp +++ b/qt/mainwindow.cpp @@ -386,7 +386,7 @@ void MainWindow::OnPreferences() PreferencesDialog dlg(this); dlg.exec(); - m_pDrawWidget->GetFramework().SetupMeasurementSystem(); + m_pDrawWidget->GetFramework().EnterForeground(); } #ifndef NO_DOWNLOADER