diff --git a/android/src/com/mapswithme/maps/MapFragment.java b/android/src/com/mapswithme/maps/MapFragment.java index 27fbeee3c6..0d63b99fb2 100644 --- a/android/src/com/mapswithme/maps/MapFragment.java +++ b/android/src/com/mapswithme/maps/MapFragment.java @@ -42,7 +42,7 @@ public class MapFragment extends BaseMwmFragment private static final int WIDGET_RULER = 0x01; private static final int WIDGET_COMPASS = 0x02; private static final int WIDGET_COPYRIGHT = 0x04; - private static final int WIDGET_SCALE_LABEL = 0x08; + private static final int WIDGET_SCALE_FPS_LABEL = 0x08; private static final int WIDGET_WATERMARK = 0x10; // Should correspond to dp::Anchor from drape_global.hpp @@ -95,13 +95,10 @@ public class MapFragment extends BaseMwmFragment setupRuler(0, false); setupWatermark(0, false); - if (BuildConfig.DEBUG) - { - nativeSetupWidget(WIDGET_SCALE_LABEL, - UiUtils.dimen(R.dimen.margin_base), - UiUtils.dimen(R.dimen.margin_base), - ANCHOR_LEFT_TOP); - } + nativeSetupWidget(WIDGET_SCALE_FPS_LABEL, + UiUtils.dimen(R.dimen.margin_base), + UiUtils.dimen(R.dimen.margin_base), + ANCHOR_LEFT_TOP); setupCompass(UiUtils.getCompassYOffset(getContext()), false); } diff --git a/drape/drape_routine.hpp b/drape/drape_routine.hpp index 2bdb30403b..b51257ec7d 100644 --- a/drape/drape_routine.hpp +++ b/drape/drape_routine.hpp @@ -76,6 +76,22 @@ public: return result; } + template + static ResultPtr RunDelayed(base::WorkerThread::Duration const & duration, Task && t) + { + ResultPtr result(new Result(Instance().GetNextId())); + bool const success = Instance().m_workerThread.PushDelayed(duration, [result, t]() mutable + { + t(); + Instance().Notify(result->Finish()); + }); + + if (!success) + return {}; + + return result; + } + private: static DrapeRoutine & Instance() { diff --git a/drape/overlay_tree.cpp b/drape/overlay_tree.cpp index 32cc336554..9530534d65 100644 --- a/drape/overlay_tree.cpp +++ b/drape/overlay_tree.cpp @@ -78,7 +78,7 @@ OverlayTree::OverlayTree(double visualScale) void OverlayTree::Clear() { - m_frameCounter = kInvalidFrame; + InvalidateOnNextFrame(); TBase::Clear(); m_handlesCache.clear(); for (auto & handles : m_handles) @@ -105,7 +105,7 @@ bool OverlayTree::Frame() m_frameCounter++; if (m_frameCounter >= static_cast(m_frameUpdatePeriod)) - m_frameCounter = kInvalidFrame; + InvalidateOnNextFrame(); return IsNeedUpdate(); } @@ -115,6 +115,11 @@ bool OverlayTree::IsNeedUpdate() const return m_frameCounter == kInvalidFrame; } +void OverlayTree::InvalidateOnNextFrame() +{ + m_frameCounter = kInvalidFrame; +} + void OverlayTree::StartOverlayPlacing(ScreenBase const & screen, int zoomLevel) { ASSERT(IsNeedUpdate(), ()); @@ -131,7 +136,7 @@ void OverlayTree::Remove(ref_ptr handle) return; if (m_handlesCache.find(handle) != m_handlesCache.end()) - m_frameCounter = kInvalidFrame; + InvalidateOnNextFrame(); } void OverlayTree::Add(ref_ptr handle) @@ -154,7 +159,7 @@ void OverlayTree::Add(ref_ptr handle) // Skip not-ready handles. if (!handle->Update(modelView)) { - m_frameCounter = kInvalidFrame; + InvalidateOnNextFrame(); handle->SetReady(false); return; } @@ -435,7 +440,7 @@ void OverlayTree::SetDisplacementEnabled(bool enabled) if (m_isDisplacementEnabled == enabled) return; m_isDisplacementEnabled = enabled; - m_frameCounter = kInvalidFrame; + InvalidateOnNextFrame(); } void OverlayTree::SetSelectedFeature(FeatureID const & featureID) diff --git a/drape/overlay_tree.hpp b/drape/overlay_tree.hpp index 2d94bfd7b6..c5c71b45c8 100644 --- a/drape/overlay_tree.hpp +++ b/drape/overlay_tree.hpp @@ -58,11 +58,12 @@ class OverlayTree : public m4::Tree, detail::OverlayTrait public: using HandlesCache = std::unordered_set, detail::OverlayHasher>; - OverlayTree(double visualScale); + explicit OverlayTree(double visualScale); void Clear(); bool Frame(); bool IsNeedUpdate() const; + void InvalidateOnNextFrame(); void StartOverlayPlacing(ScreenBase const & screen, int zoomLevel); void Add(ref_ptr handle); diff --git a/drape/texture_manager.cpp b/drape/texture_manager.cpp index 31d1e67013..8cdc0983e8 100644 --- a/drape/texture_manager.cpp +++ b/drape/texture_manager.cpp @@ -254,8 +254,14 @@ void TextureManager::Release() bool TextureManager::UpdateDynamicTextures() { + // For some reasons OpenGL can not update textures immediately. + // Here we use some timeout to allow to do it. + double const kUploadTimeoutInSeconds = 2.0; + if (!HasAsyncRoutines() && m_nothingToUpload.test_and_set()) - return false; + return m_uploadTimer.ElapsedSeconds() < kUploadTimeoutInSeconds; + + m_uploadTimer.Reset(); m_colorTexture->UpdateState(); m_stipplePenTexture->UpdateState(); diff --git a/drape/texture_manager.hpp b/drape/texture_manager.hpp index e7a9675085..faded6a29d 100644 --- a/drape/texture_manager.hpp +++ b/drape/texture_manager.hpp @@ -8,6 +8,7 @@ #include "drape/font_texture.hpp" #include "base/string_utils.hpp" +#include "base/timer.hpp" #include #include @@ -251,6 +252,7 @@ private: buffer_vector m_glyphGroups; buffer_vector m_hybridGlyphGroups; + my::Timer m_uploadTimer; std::atomic_flag m_nothingToUpload; std::mutex m_calcGlyphsMutex; }; diff --git a/drape_frontend/CMakeLists.txt b/drape_frontend/CMakeLists.txt index c6195c49a2..3682aadc0d 100644 --- a/drape_frontend/CMakeLists.txt +++ b/drape_frontend/CMakeLists.txt @@ -73,6 +73,8 @@ set( drape_engine.hpp drape_engine_safe_ptr.hpp drape_hints.hpp + drape_notifier.cpp + drape_notifier.hpp drape_measurer.cpp drape_measurer.hpp engine_context.cpp @@ -101,6 +103,7 @@ set( gui/ruler.hpp gui/ruler_helper.cpp gui/ruler_helper.hpp + gui/scale_fps_helper.hpp gui/shape.cpp gui/shape.hpp gui/skin.cpp diff --git a/drape_frontend/animation_system.cpp b/drape_frontend/animation_system.cpp index 90a8d260f2..70106f3b9e 100644 --- a/drape_frontend/animation_system.cpp +++ b/drape_frontend/animation_system.cpp @@ -346,10 +346,10 @@ void AnimationSystem::FinishObjectAnimations(Animation::Object object, bool rewi rewind, finishAll); } -void AnimationSystem::Advance(double elapsedSeconds) +bool AnimationSystem::Advance(double elapsedSeconds) { if (m_animationChain.empty()) - return; + return false; TAnimationList finishedAnimations; TAnimationList & frontList = *(m_animationChain.front()); @@ -373,6 +373,8 @@ void AnimationSystem::Advance(double elapsedSeconds) } if (frontList.empty()) StartNextAnimations(); + + return true; } #ifdef DEBUG_ANIMATIONS diff --git a/drape_frontend/animation_system.hpp b/drape_frontend/animation_system.hpp index dcaf42bfd9..7247e60040 100644 --- a/drape_frontend/animation_system.hpp +++ b/drape_frontend/animation_system.hpp @@ -60,7 +60,7 @@ public: return nullptr; } - void Advance(double elapsedSeconds); + bool Advance(double elapsedSeconds); ScreenBase const & GetLastScreen() { return m_lastScreen; } void SaveAnimationResult(Animation const & animation); diff --git a/drape_frontend/backend_renderer.cpp b/drape_frontend/backend_renderer.cpp index f4588b298e..9561214ab2 100644 --- a/drape_frontend/backend_renderer.cpp +++ b/drape_frontend/backend_renderer.cpp @@ -539,6 +539,13 @@ void BackendRenderer::AcceptMessage(ref_ptr message) break; } + case Message::NotifyRenderThread: + { + ref_ptr msg = message; + msg->InvokeFunctor(); + break; + } + default: ASSERT(false, ()); break; diff --git a/drape_frontend/drape_engine.cpp b/drape_frontend/drape_engine.cpp index ffc50bd433..f907ae9f6e 100644 --- a/drape_frontend/drape_engine.cpp +++ b/drape_frontend/drape_engine.cpp @@ -823,6 +823,13 @@ void DrapeEngine::RunFirstLaunchAnimation() MessagePriority::Normal); } +void DrapeEngine::ShowDebugInfo(bool shown) +{ + m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread, + make_unique_dp(shown), + MessagePriority::Normal); +} + drape_ptr DrapeEngine::GenerateMarkRenderInfo(UserPointMark const * mark) { auto renderInfo = make_unique_dp(); diff --git a/drape_frontend/drape_engine.hpp b/drape_frontend/drape_engine.hpp index a3d6277a4d..70f815073a 100644 --- a/drape_frontend/drape_engine.hpp +++ b/drape_frontend/drape_engine.hpp @@ -224,6 +224,8 @@ public: void RunFirstLaunchAnimation(); + void ShowDebugInfo(bool shown); + private: void AddUserEvent(drape_ptr && e); void PostUserEvent(drape_ptr && e); diff --git a/drape_frontend/drape_frontend_tests/user_event_stream_tests.cpp b/drape_frontend/drape_frontend_tests/user_event_stream_tests.cpp index e79148ff47..d5ef07ce2b 100644 --- a/drape_frontend/drape_frontend_tests/user_event_stream_tests.cpp +++ b/drape_frontend/drape_frontend_tests/user_event_stream_tests.cpp @@ -36,7 +36,7 @@ public: void CorrectScalePoint(m2::PointD & pt1, m2::PointD & pt2) const override {} void CorrectGlobalScalePoint(m2::PointD & pt) const override {} void OnScaleEnded() override {} - void OnTouchMapAction() override {} + void OnTouchMapAction(TouchEvent::ETouchType touchType) override {} void OnAnimatedScaleEnded() override {} bool OnNewVisibleViewport(m2::RectD const & oldViewport, m2::RectD const & newViewport, m2::PointD & gOffset) override diff --git a/drape_frontend/drape_notifier.cpp b/drape_frontend/drape_notifier.cpp new file mode 100644 index 0000000000..3af746dc32 --- /dev/null +++ b/drape_frontend/drape_notifier.cpp @@ -0,0 +1,36 @@ +#include "drape_frontend/drape_notifier.hpp" +#include "drape_frontend/message_subclasses.hpp" + +#include "drape/drape_routine.hpp" + +namespace df +{ +DrapeNotifier::DrapeNotifier(ref_ptr commutator) + : m_commutator(commutator) + , m_counter(kInvalidId + 1) +{} + +uint64_t DrapeNotifier::Notify(ThreadsCommutator::ThreadName threadName, + base::WorkerThread::Duration const & duration, bool repeating, + Functor && functor) +{ + uint64_t const notifyId = m_counter++; + NotifyImpl(threadName, duration, repeating, notifyId, std::move(functor)); + return notifyId; +} + +void DrapeNotifier::NotifyImpl(ThreadsCommutator::ThreadName threadName, + base::WorkerThread::Duration const & duration, bool repeating, + uint64_t notifyId, Functor && functor) +{ + dp::DrapeRoutine::RunDelayed(duration, + [this, threadName, duration, repeating, notifyId, functor = std::move(functor)]() mutable + { + m_commutator->PostMessage(threadName, + make_unique_dp(std::move(functor), notifyId), + MessagePriority::Normal); + if (repeating) + NotifyImpl(threadName, duration, repeating, notifyId, std::move(functor)); + }); +} +} // namespace df diff --git a/drape_frontend/drape_notifier.hpp b/drape_frontend/drape_notifier.hpp new file mode 100644 index 0000000000..bf319c3ee3 --- /dev/null +++ b/drape_frontend/drape_notifier.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include "drape_frontend/threads_commutator.hpp" + +#include "drape/pointers.hpp" + +#include "base/worker_thread.hpp" + +#include +#include +#include + +namespace df +{ +class DrapeNotifier +{ +public: + static uint64_t constexpr kInvalidId = 0; + using Functor = std::function; + + explicit DrapeNotifier(ref_ptr commutator); + + uint64_t Notify(ThreadsCommutator::ThreadName threadName, + base::WorkerThread::Duration const & duration, + bool repeating, Functor && functor); + +private: + void NotifyImpl(ThreadsCommutator::ThreadName threadName, + base::WorkerThread::Duration const & duration, bool repeating, + uint64_t notifyId, Functor && functor); + + ref_ptr m_commutator; + std::atomic m_counter; +}; +} // namespace df diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index 5cf22ffa33..43cd71ee38 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -3,6 +3,7 @@ #include "drape_frontend/animation_system.hpp" #include "drape_frontend/batch_merge_helper.hpp" #include "drape_frontend/drape_measurer.hpp" +#include "drape_frontend/drape_notifier.hpp" #include "drape_frontend/gui/drape_gui.hpp" #include "drape_frontend/gui/ruler_helper.hpp" #include "drape_frontend/message_subclasses.hpp" @@ -146,6 +147,7 @@ FrontendRenderer::FrontendRenderer(Params && params) #ifdef SCENARIO_ENABLE , m_scenarioManager(new ScenarioManager(this)) #endif + , m_notifier(make_unique_dp(params.m_commutator)) { #ifdef DEBUG m_isTeardowned = false; @@ -170,7 +172,8 @@ FrontendRenderer::FrontendRenderer(Params && params) MessagePriority::Normal); }); - m_myPositionController = make_unique_dp(std::move(params.m_myPositionParams)); + m_myPositionController = make_unique_dp( + std::move(params.m_myPositionParams), make_ref(m_notifier)); #ifndef OMIM_OS_IPHONE_SIMULATOR for (auto const & effect : params.m_enabledEffects) @@ -872,6 +875,20 @@ void FrontendRenderer::AcceptMessage(ref_ptr message) break; } + case Message::ShowDebugInfo: + { + ref_ptr msg = message; + gui::DrapeGui::Instance().GetScaleFpsHelper().SetVisible(msg->IsShown()); + break; + } + + case Message::NotifyRenderThread: + { + ref_ptr msg = message; + msg->InvokeFunctor(); + break; + } + default: ASSERT(false, ()); } @@ -1603,6 +1620,7 @@ void FrontendRenderer::ResolveZoomLevel(ScreenBase const & screen) { int const prevZoomLevel = m_currentZoomLevel; m_currentZoomLevel = GetDrawTileScale(screen); + gui::DrapeGui::Instance().GetScaleFpsHelper().SetScale(m_currentZoomLevel); if (prevZoomLevel != m_currentZoomLevel) UpdateCanBeDeletedStatus(); @@ -1741,9 +1759,12 @@ void FrontendRenderer::OnAnimatedScaleEnded() m_firstLaunchAnimationInterrupted = true; } -void FrontendRenderer::OnTouchMapAction() +void FrontendRenderer::OnTouchMapAction(TouchEvent::ETouchType touchType) { - m_myPositionController->ResetRoutingNotFollowTimer(); + // Here we block timer on start of touch actions. Timer will be unblocked on + // the completion of touch actions. It helps to prevent the creation of redundant checks. + auto const blockTimer = (touchType == TouchEvent::TOUCH_DOWN || touchType == TouchEvent::TOUCH_MOVE); + m_myPositionController->ResetRoutingNotFollowTimer(blockTimer); } bool FrontendRenderer::OnNewVisibleViewport(m2::RectD const & oldViewport, m2::RectD const & newViewport, m2::PointD & gOffset) @@ -1971,25 +1992,28 @@ void FrontendRenderer::Routine::Do() m_renderer.OnContextCreate(); - double const kMaxInactiveSeconds = 2.0; - double const kShowOverlaysEventsPeriod = 5.0; - my::Timer timer; - my::Timer activityTimer; - my::Timer showOverlaysEventsTimer; - double frameTime = 0.0; bool modelViewChanged = true; bool viewportChanged = true; bool invalidContext = false; + uint32_t inactiveFramesCounter = 0; dp::OGLContext * context = m_renderer.m_contextFactory->getDrawContext(); +#ifdef DEBUG + gui::DrapeGui::Instance().GetScaleFpsHelper().SetVisible(true); +#endif + + m_renderer.ScheduleOverlayCollecting(); + while (!IsCancelled()) { if (context->validate()) { invalidContext = false; + timer.Reset(); + ScreenBase modelView = m_renderer.ProcessEvents(modelViewChanged, viewportChanged); if (viewportChanged) m_renderer.OnResize(modelView); @@ -2000,70 +2024,74 @@ void FrontendRenderer::Routine::Do() if (isActiveFrame) m_renderer.PrepareScene(modelView); - isActiveFrame |= m_renderer.m_myPositionController->IsWaitingForTimers(); isActiveFrame |= m_renderer.m_texMng->UpdateDynamicTextures(); m_renderer.m_routeRenderer->UpdatePreview(modelView); m_renderer.RenderScene(modelView); - if (modelViewChanged || m_renderer.m_forceUpdateScene || m_renderer.m_forceUpdateUserMarks) + auto const hasForceUpdate = m_renderer.m_forceUpdateScene || m_renderer.m_forceUpdateUserMarks; + isActiveFrame |= hasForceUpdate; + + if (modelViewChanged || hasForceUpdate) m_renderer.UpdateScene(modelView); isActiveFrame |= InterpolationHolder::Instance().Advance(frameTime); - AnimationSystem::Instance().Advance(frameTime); - + isActiveFrame |= AnimationSystem::Instance().Advance(frameTime); isActiveFrame |= m_renderer.m_userEventStream.IsWaitingForActionCompletion(); - if (isActiveFrame) - activityTimer.Reset(); + // On the first inactive frame we invalidate overlay tree. + if (!isActiveFrame) + { + if (inactiveFramesCounter == 0) + m_renderer.m_overlayTree->InvalidateOnNextFrame(); + inactiveFramesCounter++; + } + else + { + inactiveFramesCounter = 0; + } - bool isValidFrameTime = true; - if (activityTimer.ElapsedSeconds() > kMaxInactiveSeconds) + bool const canSuspend = inactiveFramesCounter > 2; + if (canSuspend) { // Process a message or wait for a message. // IsRenderingEnabled() can return false in case of rendering disabling and we must prevent // possibility of infinity waiting in ProcessSingleMessage. m_renderer.ProcessSingleMessage(m_renderer.IsRenderingEnabled()); - activityTimer.Reset(); timer.Reset(); - isValidFrameTime = false; + inactiveFramesCounter = 0; } else { - double availableTime = kVSyncInterval - timer.ElapsedSeconds(); + auto availableTime = kVSyncInterval - timer.ElapsedSeconds(); do { if (!m_renderer.ProcessSingleMessage(false /* waitForMessage */)) break; - - activityTimer.Reset(); + inactiveFramesCounter = 0; availableTime = kVSyncInterval - timer.ElapsedSeconds(); } while (availableTime > 0.0); } context->present(); - frameTime = timer.ElapsedSeconds(); - timer.Reset(); // Limit fps in following mode. double constexpr kFrameTime = 1.0 / 30.0; - if (isValidFrameTime && frameTime < kFrameTime && + auto const ft = timer.ElapsedSeconds(); + if (!canSuspend && ft < kFrameTime && m_renderer.m_myPositionController->IsRouteFollowingActive()) { - auto const ms = static_cast((kFrameTime - frameTime) * 1000); + auto const ms = static_cast((kFrameTime - ft) * 1000); std::this_thread::sleep_for(std::chrono::milliseconds(ms)); } - if (m_renderer.m_overlaysTracker->IsValid() && - showOverlaysEventsTimer.ElapsedSeconds() > kShowOverlaysEventsPeriod) - { - m_renderer.CollectShowOverlaysEvents(); - showOverlaysEventsTimer.Reset(); - } + frameTime = timer.ElapsedSeconds(); + gui::DrapeGui::Instance().GetScaleFpsHelper().SetFrameTime(frameTime, inactiveFramesCounter < 1); } else { + inactiveFramesCounter = 0; if (!invalidContext) { LOG(LINFO, ("Invalid context. Rendering is stopped.")); @@ -2236,6 +2264,17 @@ void FrontendRenderer::CheckAndRunFirstLaunchAnimation() false /* trackVisibleViewport */)); } +void FrontendRenderer::ScheduleOverlayCollecting() +{ + auto const kCollectingEventsPeriod = std::chrono::seconds(10); + m_notifier->Notify(ThreadsCommutator::RenderThread, kCollectingEventsPeriod, + true /* repeating */, [this](uint64_t) + { + if (m_overlaysTracker->IsValid()) + CollectShowOverlaysEvents(); + }); +} + void FrontendRenderer::RenderLayer::Sort(ref_ptr overlayTree) { if (!m_isDirty) diff --git a/drape_frontend/frontend_renderer.hpp b/drape_frontend/frontend_renderer.hpp index 8f7022606f..80b6f977f6 100755 --- a/drape_frontend/frontend_renderer.hpp +++ b/drape_frontend/frontend_renderer.hpp @@ -48,6 +48,7 @@ class RenderBucket; namespace df { +class DrapeNotifier; class ScenarioManager; class ScreenQuadRenderer; class SelectionShape; @@ -201,7 +202,7 @@ private: void CorrectGlobalScalePoint(m2::PointD & pt) const override; void OnScaleEnded() override; void OnAnimatedScaleEnded() override; - void OnTouchMapAction() override; + void OnTouchMapAction(TouchEvent::ETouchType touchType) override; bool OnNewVisibleViewport(m2::RectD const & oldViewport, m2::RectD const & newViewport, m2::PointD & gOffset) override; @@ -251,6 +252,8 @@ private: void CheckAndRunFirstLaunchAnimation(); + void ScheduleOverlayCollecting(); + drape_ptr m_gpuProgramManager; std::array m_layers; @@ -337,6 +340,8 @@ private: bool m_finishTexturesInitialization = false; drape_ptr m_transitBackground; + drape_ptr m_notifier; + #ifdef DEBUG bool m_isTeardowned; #endif diff --git a/drape_frontend/gui/drape_gui.hpp b/drape_frontend/gui/drape_gui.hpp index eb87360687..9e222328e5 100644 --- a/drape_frontend/gui/drape_gui.hpp +++ b/drape_frontend/gui/drape_gui.hpp @@ -1,7 +1,8 @@ #pragma once -#include "skin.hpp" -#include "compass.hpp" +#include "drape_frontend/gui/compass.hpp" +#include "drape_frontend/gui/scale_fps_helper.hpp" +#include "drape_frontend/gui/skin.hpp" #include "storage/index.hpp" #include "storage/storage_defines.hpp" @@ -39,12 +40,13 @@ public: void ConnectOnCompassTappedHandler(Shape::TTapHandler const & handler); void CallOnCompassTappedHandler(); + ScaleFpsHelper & GetScaleFpsHelper() { return m_scaleFpsHelper; } + ScaleFpsHelper const & GetScaleFpsHelper() const { return m_scaleFpsHelper; } + private: DrapeGui(); - RulerHelper & GetRulerHelperImpl(); -private: struct Impl; std::unique_ptr m_impl; bool m_isCopyrightActive = true; @@ -53,5 +55,6 @@ private: m2::PointF m_surfaceSize; mutable std::mutex m_surfaceSizeMutex; bool m_inUserAction = false; + ScaleFpsHelper m_scaleFpsHelper; }; } // namespace gui diff --git a/drape_frontend/gui/layer_render.cpp b/drape_frontend/gui/layer_render.cpp index 25ef0bfb28..a2718ee0f2 100644 --- a/drape_frontend/gui/layer_render.cpp +++ b/drape_frontend/gui/layer_render.cpp @@ -154,11 +154,11 @@ bool LayerRenderer::HasWidget(EWidget widget) const namespace { -class ScaleLabelHandle : public MutableLabelHandle +class ScaleFpsLabelHandle : public MutableLabelHandle { using TBase = MutableLabelHandle; public: - ScaleLabelHandle(uint32_t id, ref_ptr textures) + ScaleFpsLabelHandle(uint32_t id, ref_ptr textures) : TBase(id, dp::LeftBottom, m2::PointF::Zero(), textures), m_scale(0) { SetIsVisible(true); @@ -166,11 +166,20 @@ public: bool Update(ScreenBase const & screen) override { - int const newScale = df::GetDrawTileScale(screen); - if (m_scale != newScale) + auto & helper = gui::DrapeGui::Instance().GetScaleFpsHelper(); + if (!helper.IsVisible()) + return false; + + if (m_scale != helper.GetScale() || m_fps != helper.GetFps() || m_isPaused != helper.IsPaused()) { - m_scale = newScale; - SetContent("Scale : " + strings::to_string(m_scale)); + m_scale = helper.GetScale(); + m_fps = helper.GetFps(); + m_isPaused = helper.IsPaused(); + std::stringstream ss; + ss << "Scale: " << m_scale << " / FPS: " << m_fps; + if (m_isPaused) + ss << " (PAUSED)"; + SetContent(ss.str()); } auto const vs = static_cast(df::VisualParams::Instance().GetVisualScale()); @@ -181,7 +190,9 @@ public: } private: - int m_scale; + int m_scale = 1; + uint32_t m_fps = 0; + bool m_isPaused = false; }; } // namespace @@ -194,7 +205,7 @@ drape_ptr LayerCacher::RecacheWidgets(TWidgetsInitInfo const & in std::make_pair(WIDGET_COMPASS, std::bind(&LayerCacher::CacheCompass, this, _1, _2, _3)), std::make_pair(WIDGET_RULER, std::bind(&LayerCacher::CacheRuler, this, _1, _2, _3)), std::make_pair(WIDGET_COPYRIGHT, std::bind(&LayerCacher::CacheCopyright, this, _1, _2, _3)), - std::make_pair(WIDGET_SCALE_LABEL, std::bind(&LayerCacher::CacheScaleLabel, this, _1, _2, _3)), + std::make_pair(WIDGET_SCALE_FPS_LABEL, std::bind(&LayerCacher::CacheScaleFpsLabel, this, _1, _2, _3)), std::make_pair(WIDGET_WATERMARK, std::bind(&LayerCacher::CacheWatermark, this, _1, _2, _3))}; drape_ptr renderer = make_unique_dp(); @@ -349,25 +360,25 @@ m2::PointF LayerCacher::CacheCopyright(Position const & position, ref_ptr renderer, - ref_ptr textures) +m2::PointF LayerCacher::CacheScaleFpsLabel(Position const & position, ref_ptr renderer, + ref_ptr textures) { MutableLabelDrawer::Params params; - params.m_alphabet = "Scale: 1234567890"; - params.m_maxLength = 10; + params.m_alphabet = "FPSAUEDcale: 1234567890/()"; + params.m_maxLength = 30; params.m_anchor = position.m_anchor; params.m_font = DrapeGui::GetGuiTextFont(); params.m_pivot = position.m_pixelPivot; params.m_handleCreator = [textures](dp::Anchor, m2::PointF const &) { - return make_unique_dp(EGuiHandle::GuiHandleScaleLabel, textures); + return make_unique_dp(EGuiHandle::GuiHandleScaleLabel, textures); }; drape_ptr scaleRenderer = make_unique_dp(); m2::PointF size = MutableLabelDrawer::Draw(params, textures, std::bind(&ShapeRenderer::AddShape, scaleRenderer.get(), _1, _2)); - renderer->AddShapeRenderer(WIDGET_SCALE_LABEL, std::move(scaleRenderer)); + renderer->AddShapeRenderer(WIDGET_SCALE_FPS_LABEL, std::move(scaleRenderer)); return size; } diff --git a/drape_frontend/gui/layer_render.hpp b/drape_frontend/gui/layer_render.hpp index ad0d60e0d5..42a73813a1 100644 --- a/drape_frontend/gui/layer_render.hpp +++ b/drape_frontend/gui/layer_render.hpp @@ -67,8 +67,8 @@ private: 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); + m2::PointF CacheScaleFpsLabel(Position const & position, ref_ptr renderer, + ref_ptr textures); m2::PointF CacheWatermark(Position const & position, ref_ptr renderer, ref_ptr textures); }; diff --git a/drape_frontend/gui/scale_fps_helper.hpp b/drape_frontend/gui/scale_fps_helper.hpp new file mode 100644 index 0000000000..a59acfa341 --- /dev/null +++ b/drape_frontend/gui/scale_fps_helper.hpp @@ -0,0 +1,56 @@ +#pragma once + +#include "base/timer.hpp" + +#include + +namespace gui +{ +class ScaleFpsHelper +{ +public: + uint32_t GetFps() const + { + if (m_frameTime == 0.0) + return 0; + return static_cast(1.0 / m_frameTime); + } + + bool IsPaused() const + { + return m_isPaused; + } + + void SetFrameTime(double frameTime, bool isActiveFrame) + { + m_isPaused = !isActiveFrame; + m_framesCounter++; + m_aggregatedFrameTime += frameTime; + + double constexpr kAggregationPeriod = 0.5; + if (m_isPaused || m_fpsAggregationTimer.ElapsedSeconds() >= kAggregationPeriod) + { + m_frameTime = m_aggregatedFrameTime / m_framesCounter; + m_aggregatedFrameTime = 0.0; + m_framesCounter = 0; + m_fpsAggregationTimer.Reset(); + } + } + + int GetScale() const { return m_scale; } + void SetScale(int scale) { m_scale = scale; } + + void SetVisible(bool isVisible) { m_isVisible = isVisible; } + bool IsVisible() const { return m_isVisible; } + +private: + double m_frameTime = 0.0; + int m_scale = 1; + bool m_isVisible = false; + + my::Timer m_fpsAggregationTimer; + double m_aggregatedFrameTime = 0.0; + uint32_t m_framesCounter = 1; + bool m_isPaused = false; +}; +} // namespace gui diff --git a/drape_frontend/gui/skin.hpp b/drape_frontend/gui/skin.hpp index 72a194a5d9..76deead8ca 100644 --- a/drape_frontend/gui/skin.hpp +++ b/drape_frontend/gui/skin.hpp @@ -18,7 +18,7 @@ enum EWidget WIDGET_RULER = 0x1, WIDGET_COMPASS = 0x2, WIDGET_COPYRIGHT = 0x4, - WIDGET_SCALE_LABEL = 0x8, + WIDGET_SCALE_FPS_LABEL = 0x8, WIDGET_WATERMARK = 0x10, /// Following widgets controlled by rendering kernel. Don't use them in platform code WIDGET_CHOOSE_POSITION_MARK = 0x8000, diff --git a/drape_frontend/message.hpp b/drape_frontend/message.hpp index 3d292d6de0..bb2075a307 100644 --- a/drape_frontend/message.hpp +++ b/drape_frontend/message.hpp @@ -2,7 +2,6 @@ namespace df { - class Message { public: @@ -91,12 +90,11 @@ public: ClearTransitSchemeData, RegenerateTransitScheme, FlushTransitScheme, - FlushTransitMarkers, - FlushTransitText, - FlushTransitStubs, + ShowDebugInfo, + NotifyRenderThread }; - virtual ~Message() {} + virtual ~Message() = default; virtual Type GetType() const { return Unknown; } virtual bool IsGLContextDependent() const { return false; } }; @@ -116,5 +114,4 @@ enum class MessagePriority // This priority allows to process messages after any other messages in queue. Low }; - -} // namespace df +} // namespace df diff --git a/drape_frontend/message_subclasses.hpp b/drape_frontend/message_subclasses.hpp index 3a5fcab0f1..a2569584aa 100644 --- a/drape_frontend/message_subclasses.hpp +++ b/drape_frontend/message_subclasses.hpp @@ -1250,4 +1250,43 @@ class FinishTexturesInitializationMessage : public Message public: Type GetType() const override { return Message::FinishTexturesInitialization; } }; + +class ShowDebugInfoMessage : public Message +{ +public: + explicit ShowDebugInfoMessage(bool shown) + : m_shown(shown) + {} + + Type GetType() const override { return Message::ShowDebugInfo; } + bool IsShown() const { return m_shown; } + +private: + bool const m_shown; +}; + +class NotifyRenderThreadMessage : public Message +{ +public: + using Functor = std::function; + NotifyRenderThreadMessage(Functor const & functor, uint64_t notifyId) + : m_functor(functor) + , m_notifyId(notifyId) + {} + + // We can not notify render threads without active OpenGL context. + bool IsGLContextDependent() const override { return true; } + + Type GetType() const override { return Message::NotifyRenderThread; } + + void InvokeFunctor() + { + if (m_functor) + m_functor(m_notifyId); + } + +private: + Functor m_functor; + uint64_t const m_notifyId; +}; } // namespace df diff --git a/drape_frontend/my_position_controller.cpp b/drape_frontend/my_position_controller.cpp index d4f026bb49..268aa5c666 100644 --- a/drape_frontend/my_position_controller.cpp +++ b/drape_frontend/my_position_controller.cpp @@ -1,9 +1,11 @@ #include "drape_frontend/my_position_controller.hpp" + +#include "drape_frontend/animation/arrow_animation.hpp" #include "drape_frontend/animation_system.hpp" #include "drape_frontend/animation_utils.hpp" -#include "drape_frontend/visual_params.hpp" +#include "drape_frontend/drape_notifier.hpp" #include "drape_frontend/user_event_stream.hpp" -#include "drape_frontend/animation/arrow_animation.hpp" +#include "drape_frontend/visual_params.hpp" #include "indexer/scales.hpp" @@ -14,6 +16,7 @@ #include "3party/Alohalytics/src/alohalytics.h" #include +#include #include #include #include @@ -123,8 +126,9 @@ double CalculateZoomBySpeed(double speed, bool isPerspectiveAllowed) } } // namespace -MyPositionController::MyPositionController(Params && params) - : m_mode(location::PendingPosition) +MyPositionController::MyPositionController(Params && params, ref_ptr notifier) + : m_notifier(notifier) + , m_mode(location::PendingPosition) , m_desiredInitMode(params.m_initMode) , m_modeChangeCallback(std::move(params.m_myPositionModeCallback)) , m_hints(params.m_hints) @@ -154,6 +158,10 @@ MyPositionController::MyPositionController(Params && params) , m_positionIsObsolete(false) , m_needBlockAutoZoom(false) , m_notFollowAfterPending(false) + , m_locationWaitingNotifyId(DrapeNotifier::kInvalidId) + , m_routingNotFollowNotifyId(DrapeNotifier::kInvalidId) + , m_blockAutoZoomNotifyId(DrapeNotifier::kInvalidId) + , m_updateLocationNotifyId(DrapeNotifier::kInvalidId) { if (m_hints.m_isFirstLaunch) { @@ -261,10 +269,14 @@ void MyPositionController::Rotated() m_wasRotationInScaling = true; } -void MyPositionController::ResetRoutingNotFollowTimer() +void MyPositionController::ResetRoutingNotFollowTimer(bool blockTimer) { if (m_isInRouting) + { m_routingNotFollowTimer.Reset(); + m_blockRoutingNotFollowTimer = blockTimer; + m_routingNotFollowNotifyId = DrapeNotifier::kInvalidId; + } } void MyPositionController::ResetBlockAutoZoomTimer() @@ -273,6 +285,7 @@ void MyPositionController::ResetBlockAutoZoomTimer() { m_needBlockAutoZoom = true; m_blockAutoZoomTimer.Reset(); + m_blockAutoZoomNotifyId = DrapeNotifier::kInvalidId; } } @@ -326,6 +339,7 @@ void MyPositionController::NextMode(ScreenBase const & screen) if (m_mode == location::NotFollowNoPosition) { m_pendingTimer.Reset(); + m_locationWaitingNotifyId = DrapeNotifier::kInvalidId; ChangeMode(location::PendingPosition); return; } @@ -408,8 +422,7 @@ void MyPositionController::OnLocationUpdate(location::GpsInfo const & info, bool if (m_notFollowAfterPending && m_mode == location::PendingPosition) { ChangeMode(location::NotFollow); - if (m_isInRouting) - m_routingNotFollowTimer.Reset(); + ResetRoutingNotFollowTimer(); m_notFollowAfterPending = false; } else if (!m_isPositionAssigned) @@ -471,6 +484,7 @@ void MyPositionController::OnLocationUpdate(location::GpsInfo const & info, bool { m_lastLocationTimestamp = info.m_timestamp; m_updateLocationTimer.Reset(); + m_updateLocationNotifyId = DrapeNotifier::kInvalidId; } } @@ -525,34 +539,13 @@ void MyPositionController::Render(ScreenBase const & screen, int zoomLevel, ref_ptr mng, FrameValues const & frameValues) { - if (IsWaitingForLocation()) - { - if (m_pendingTimer.ElapsedSeconds() >= kMaxPendingLocationTimeSec) - ChangeMode(location::NotFollowNoPosition); - } - - if (IsInRouting() && m_mode == location::NotFollow && - m_routingNotFollowTimer.ElapsedSeconds() >= kMaxNotFollowRoutingTimeSec) - { - ChangeMode(location::FollowAndRotate); - UpdateViewport(kDoNotChangeZoom); - } + CheckIsWaitingForLocation(); + CheckNotFollowRouting(); if (m_shape != nullptr && IsVisible() && IsModeHasPosition()) { - if (m_needBlockAutoZoom && - m_blockAutoZoomTimer.ElapsedSeconds() >= kMaxBlockAutoZoomTimeSec) - { - m_needBlockAutoZoom = false; - m_isDirtyAutoZoom = true; - } - - if (!m_positionIsObsolete && - m_updateLocationTimer.ElapsedSeconds() >= kMaxUpdateLocationInvervalSec) - { - m_positionIsObsolete = true; - m_autoScale2d = m_autoScale3d = kUnknownAutoZoom; - } + CheckBlockAutoZoom(); + CheckUpdateLocation(); if ((m_isDirtyViewport || m_isDirtyAutoZoom) && !m_needBlockAnimation) { @@ -621,11 +614,6 @@ bool MyPositionController::IsWaitingForLocation() const return m_mode == location::PendingPosition; } -bool MyPositionController::IsWaitingForTimers() const -{ - return IsWaitingForLocation() || (IsInRouting() && m_mode == location::NotFollow); -} - void MyPositionController::StopLocationFollow() { if (m_mode == location::Follow || m_mode == location::FollowAndRotate) @@ -634,9 +622,8 @@ void MyPositionController::StopLocationFollow() if (m_mode == location::PendingPosition) m_notFollowAfterPending = true; - - if (m_isInRouting) - m_routingNotFollowTimer.Reset(); + + ResetRoutingNotFollowTimer(); } void MyPositionController::SetTimeInBackground(double time) @@ -816,7 +803,6 @@ void MyPositionController::ActivateRouting(int zoomLevel, bool enableAutoZoom) if (!m_isInRouting) { m_isInRouting = true; - m_routingNotFollowTimer.Reset(); m_enableAutoZoomInRouting = enableAutoZoom; ChangeMode(location::FollowAndRotate); @@ -826,7 +812,7 @@ void MyPositionController::ActivateRouting(int zoomLevel, bool enableAutoZoom) { UpdateViewport(kDoNotChangeZoom); }); - + ResetRoutingNotFollowTimer(); } } @@ -842,4 +828,71 @@ void MyPositionController::DeactivateRouting() ChangeModelView(m_position, 0.0, m_visiblePixelRect.Center(), kDoNotChangeZoom); } } + +// This code schedules the execution of checkFunction on FR after timeout. Additionally +// there is the protection from multiple scheduling. +#define CHECK_ON_TIMEOUT(id, timeout, checkFunction) \ + if (id == DrapeNotifier::kInvalidId) \ + { \ + id = m_notifier->Notify(ThreadsCommutator::RenderThread, \ + std::chrono::seconds(static_cast(timeout)), false /* repeating */, \ + [this](uint64_t notifyId) \ + { \ + if (notifyId != id) \ + return; \ + checkFunction(); \ + id = DrapeNotifier::kInvalidId; \ + }); \ + } + +void MyPositionController::CheckIsWaitingForLocation() +{ + if (IsWaitingForLocation()) + { + CHECK_ON_TIMEOUT(m_locationWaitingNotifyId, kMaxPendingLocationTimeSec, CheckIsWaitingForLocation); + if (m_pendingTimer.ElapsedSeconds() >= kMaxPendingLocationTimeSec) + ChangeMode(location::NotFollowNoPosition); + } +} + +void MyPositionController::CheckNotFollowRouting() +{ + if (!m_blockRoutingNotFollowTimer && IsInRouting() && m_mode == location::NotFollow) + { + CHECK_ON_TIMEOUT(m_routingNotFollowNotifyId, kMaxNotFollowRoutingTimeSec, CheckNotFollowRouting); + if (m_routingNotFollowTimer.ElapsedSeconds() >= kMaxNotFollowRoutingTimeSec) + { + ChangeMode(location::FollowAndRotate); + UpdateViewport(kDoNotChangeZoom); + } + } +} + +void MyPositionController::CheckBlockAutoZoom() +{ + if (m_needBlockAutoZoom) + { + CHECK_ON_TIMEOUT(m_blockAutoZoomNotifyId, kMaxBlockAutoZoomTimeSec, CheckBlockAutoZoom); + if (m_blockAutoZoomTimer.ElapsedSeconds() >= kMaxBlockAutoZoomTimeSec) + { + m_needBlockAutoZoom = false; + m_isDirtyAutoZoom = true; + } + } +} + +void MyPositionController::CheckUpdateLocation() +{ + if (!m_positionIsObsolete) + { + CHECK_ON_TIMEOUT(m_updateLocationNotifyId, kMaxUpdateLocationInvervalSec, CheckUpdateLocation); + if (m_updateLocationTimer.ElapsedSeconds() >= kMaxUpdateLocationInvervalSec) + { + m_positionIsObsolete = true; + m_autoScale2d = m_autoScale3d = kUnknownAutoZoom; + } + } +} + +#undef CHECK_ON_TIMEOUT } // namespace df diff --git a/drape_frontend/my_position_controller.hpp b/drape_frontend/my_position_controller.hpp index 19136b6203..b95e83fceb 100644 --- a/drape_frontend/my_position_controller.hpp +++ b/drape_frontend/my_position_controller.hpp @@ -5,6 +5,8 @@ #include "drape_frontend/drape_hints.hpp" #include "drape_frontend/my_position.hpp" +#include "drape/pointers.hpp" + #include "shaders/program_manager.hpp" #include "platform/location.hpp" @@ -13,12 +15,15 @@ #include "base/timer.hpp" +#include #include namespace df { using TAnimationCreator = std::function(ref_ptr)>; +class DrapeNotifier; + class MyPositionController { public: @@ -66,7 +71,7 @@ public: location::TMyPositionModeChanged m_myPositionModeCallback; }; - explicit MyPositionController(Params && params); + MyPositionController(Params && params, ref_ptr notifier); void UpdatePosition(); void OnUpdateScreen(ScreenBase const & screen); @@ -88,7 +93,7 @@ public: void Rotated(); - void ResetRoutingNotFollowTimer(); + void ResetRoutingNotFollowTimer(bool blockTimer = false); void ResetBlockAutoZoomTimer(); void CorrectScalePoint(m2::PointD & pt) const; @@ -111,7 +116,6 @@ public: void SetTimeInBackground(double time); void OnCompassTapped(); - void OnLocationUpdate(location::GpsInfo const & info, bool isNavigable, ScreenBase const & screen); void OnCompassUpdate(location::CompassInfo const & info, ScreenBase const & screen); @@ -121,7 +125,6 @@ public: bool IsRotationAvailable() const { return m_isDirectionAssigned; } bool IsInRouting() const { return m_isInRouting; } bool IsRouteFollowingActive() const; - bool IsWaitingForTimers() const; bool IsModeChangeViewport() const; bool IsWaitingForLocation() const; @@ -154,7 +157,13 @@ private: bool AlmostCurrentPosition(m2::PointD const & pos) const; bool AlmostCurrentAzimut(double azimut) const; -private: + void CheckIsWaitingForLocation(); + void CheckNotFollowRouting(); + void CheckBlockAutoZoom(); + void CheckUpdateLocation(); + + ref_ptr m_notifier; + location::EMyPositionMode m_mode; location::EMyPositionMode m_desiredInitMode; location::TMyPositionModeChanged m_modeChangeCallback; @@ -183,6 +192,7 @@ private: my::Timer m_lastGPSBearing; my::Timer m_pendingTimer; my::Timer m_routingNotFollowTimer; + bool m_blockRoutingNotFollowTimer = false; my::Timer m_blockAutoZoomTimer; my::Timer m_updateLocationTimer; double m_lastLocationTimestamp; @@ -206,5 +216,10 @@ private: bool m_needBlockAutoZoom; bool m_notFollowAfterPending; + + uint64_t m_locationWaitingNotifyId; + uint64_t m_routingNotFollowNotifyId; + uint64_t m_blockAutoZoomNotifyId; + uint64_t m_updateLocationNotifyId; }; } // namespace df diff --git a/drape_frontend/user_event_stream.cpp b/drape_frontend/user_event_stream.cpp index 3870727736..c1eed0a19f 100644 --- a/drape_frontend/user_event_stream.cpp +++ b/drape_frontend/user_event_stream.cpp @@ -703,7 +703,7 @@ bool UserEventStream::ProcessTouch(TouchEvent const & touch) bool UserEventStream::TouchDown(array const & touches) { if (m_listener) - m_listener->OnTouchMapAction(); + m_listener->OnTouchMapAction(TouchEvent::TOUCH_DOWN); size_t touchCount = GetValidTouchesCount(touches); bool isMapTouch = true; @@ -771,7 +771,7 @@ bool UserEventStream::CheckDrag(array const & touches, double threshol bool UserEventStream::TouchMove(array const & touches) { if (m_listener) - m_listener->OnTouchMapAction(); + m_listener->OnTouchMapAction(TouchEvent::TOUCH_MOVE); double const kDragThreshold = pow(VisualParams::Instance().GetDragThreshold(), 2); size_t touchCount = GetValidTouchesCount(touches); @@ -855,7 +855,7 @@ bool UserEventStream::TouchMove(array const & touches) bool UserEventStream::TouchCancel(array const & touches) { if (m_listener) - m_listener->OnTouchMapAction(); + m_listener->OnTouchMapAction(TouchEvent::TOUCH_CANCEL); size_t touchCount = GetValidTouchesCount(touches); UNUSED_VALUE(touchCount); @@ -899,7 +899,7 @@ bool UserEventStream::TouchCancel(array const & touches) bool UserEventStream::TouchUp(array const & touches) { if (m_listener) - m_listener->OnTouchMapAction(); + m_listener->OnTouchMapAction(TouchEvent::TOUCH_UP); size_t touchCount = GetValidTouchesCount(touches); bool isMapTouch = true; diff --git a/drape_frontend/user_event_stream.hpp b/drape_frontend/user_event_stream.hpp index 6eeda65ab8..9282245282 100644 --- a/drape_frontend/user_event_stream.hpp +++ b/drape_frontend/user_event_stream.hpp @@ -351,7 +351,7 @@ public: virtual void OnScaleEnded() = 0; virtual void OnAnimatedScaleEnded() = 0; - virtual void OnTouchMapAction() = 0; + virtual void OnTouchMapAction(TouchEvent::ETouchType touchType) = 0; virtual bool OnNewVisibleViewport(m2::RectD const & oldViewport, m2::RectD const & newViewport, m2::PointD & gOffset) = 0; diff --git a/iphone/Maps/Classes/Widgets/MWMMapWidgets.mm b/iphone/Maps/Classes/Widgets/MWMMapWidgets.mm index 49f798781d..1d5b4f904d 100644 --- a/iphone/Maps/Classes/Widgets/MWMMapWidgets.mm +++ b/iphone/Maps/Classes/Widgets/MWMMapWidgets.mm @@ -26,9 +26,7 @@ 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; }); -#ifdef DEBUG - p.m_widgetsInitInfo[gui::WIDGET_SCALE_LABEL] = gui::Position(dp::LeftBottom); -#endif + p.m_widgetsInitInfo[gui::WIDGET_SCALE_FPS_LABEL] = gui::Position(dp::LeftBottom); } - (void)resize:(CGSize)size @@ -62,7 +60,7 @@ case gui::WIDGET_WATERMARK: case gui::WIDGET_COPYRIGHT: pivot += rulerOffset; break; case gui::WIDGET_COMPASS: pivot += compassOffset; break; - case gui::WIDGET_SCALE_LABEL: + case gui::WIDGET_SCALE_FPS_LABEL: case gui::WIDGET_CHOOSE_POSITION_MARK: break; } layout[w] = pivot; diff --git a/map/framework.cpp b/map/framework.cpp index ff1c9b04bf..3b349856ae 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -2694,6 +2694,16 @@ bool Framework::ParseDrapeDebugCommand(string const & query) EnableTransitScheme(false /* enable */); return true; } + if (query == "?debug-info") + { + m_drapeEngine->ShowDebugInfo(true /* shown */); + return true; + } + if (query == "?no-debug-info") + { + m_drapeEngine->ShowDebugInfo(false /* shown */); + return true; + } return false; } diff --git a/qt/qt_common/map_widget.cpp b/qt/qt_common/map_widget.cpp index 5004280d82..304958789f 100644 --- a/qt/qt_common/map_widget.cpp +++ b/qt/qt_common/map_widget.cpp @@ -95,7 +95,7 @@ void MapWidget::CreateEngine() m_skin->ForEach( [&p](gui::EWidget widget, gui::Position const & pos) { p.m_widgetsInitInfo[widget] = pos; }); - p.m_widgetsInitInfo[gui::WIDGET_SCALE_LABEL] = gui::Position(dp::LeftBottom); + p.m_widgetsInitInfo[gui::WIDGET_SCALE_FPS_LABEL] = gui::Position(dp::LeftBottom); m_framework.CreateDrapeEngine(make_ref(m_contextFactory), std::move(p)); m_framework.SetViewportListener([this](ScreenBase const & /* screen */) { diff --git a/xcode/drape_frontend/drape_frontend.xcodeproj/project.pbxproj b/xcode/drape_frontend/drape_frontend.xcodeproj/project.pbxproj index e29f7582f8..13c98380d0 100644 --- a/xcode/drape_frontend/drape_frontend.xcodeproj/project.pbxproj +++ b/xcode/drape_frontend/drape_frontend.xcodeproj/project.pbxproj @@ -55,11 +55,14 @@ 45A3781E20B324E6005FBDBB /* watermark.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 45A3781A20B324E6005FBDBB /* watermark.cpp */; }; 45A3781F20B324E6005FBDBB /* debug_label.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 45A3781B20B324E6005FBDBB /* debug_label.cpp */; }; 45A3782020B324E6005FBDBB /* debug_label.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 45A3781C20B324E6005FBDBB /* debug_label.hpp */; }; + 45B241AE20EF9D0500A759D6 /* scale_fps_helper.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 45B241AD20EF9D0400A759D6 /* scale_fps_helper.hpp */; }; 45B4B8CB1CF5C16B00A54761 /* screen_animations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 45B4B8C71CF5C16B00A54761 /* screen_animations.cpp */; }; 45B4B8CC1CF5C16B00A54761 /* screen_animations.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 45B4B8C81CF5C16B00A54761 /* screen_animations.hpp */; }; 45B4B8CD1CF5C16B00A54761 /* screen_operations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 45B4B8C91CF5C16B00A54761 /* screen_operations.cpp */; }; 45B4B8CE1CF5C16B00A54761 /* screen_operations.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 45B4B8CA1CF5C16B00A54761 /* screen_operations.hpp */; }; 45BE604E20E504FC00A456AE /* frame_values.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 45BE604D20E504FC00A456AE /* frame_values.hpp */; }; + 45F1DA8420F3B274006E8CB3 /* drape_notifier.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 45F1DA8220F3B274006E8CB3 /* drape_notifier.hpp */; }; + 45F1DA8520F3B274006E8CB3 /* drape_notifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 45F1DA8320F3B274006E8CB3 /* drape_notifier.cpp */; }; 56BF56DA1C7608C0006DD7CB /* choose_position_mark.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 56BF56D81C7608C0006DD7CB /* choose_position_mark.cpp */; }; 56BF56DB1C7608C0006DD7CB /* choose_position_mark.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 56BF56D91C7608C0006DD7CB /* choose_position_mark.hpp */; }; 56D545661C74A44900E3719C /* overlay_batcher.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 56D545641C74A44900E3719C /* overlay_batcher.cpp */; }; @@ -271,6 +274,7 @@ 45A3781A20B324E6005FBDBB /* watermark.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = watermark.cpp; sourceTree = ""; }; 45A3781B20B324E6005FBDBB /* debug_label.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_label.cpp; sourceTree = ""; }; 45A3781C20B324E6005FBDBB /* debug_label.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = debug_label.hpp; sourceTree = ""; }; + 45B241AD20EF9D0400A759D6 /* scale_fps_helper.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = scale_fps_helper.hpp; sourceTree = ""; }; 45B4B8C71CF5C16B00A54761 /* screen_animations.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = screen_animations.cpp; sourceTree = ""; }; 45B4B8C81CF5C16B00A54761 /* screen_animations.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = screen_animations.hpp; sourceTree = ""; }; 45B4B8C91CF5C16B00A54761 /* screen_operations.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = screen_operations.cpp; sourceTree = ""; }; @@ -329,6 +333,8 @@ 45BB02591EB8BE2B00FE5C0C /* user_mark_billboard.vsh.glsl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = user_mark_billboard.vsh.glsl; path = shaders/user_mark_billboard.vsh.glsl; sourceTree = ""; }; 45BB025A1EB8BE2B00FE5C0C /* user_mark.vsh.glsl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = user_mark.vsh.glsl; path = shaders/user_mark.vsh.glsl; sourceTree = ""; }; 45BE604D20E504FC00A456AE /* frame_values.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = frame_values.hpp; sourceTree = ""; }; + 45F1DA8220F3B274006E8CB3 /* drape_notifier.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = drape_notifier.hpp; sourceTree = ""; }; + 45F1DA8320F3B274006E8CB3 /* drape_notifier.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = drape_notifier.cpp; sourceTree = ""; }; 56BF56D81C7608C0006DD7CB /* choose_position_mark.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = choose_position_mark.cpp; sourceTree = ""; }; 56BF56D91C7608C0006DD7CB /* choose_position_mark.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = choose_position_mark.hpp; sourceTree = ""; }; 56D545641C74A44900E3719C /* overlay_batcher.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = overlay_batcher.cpp; sourceTree = ""; }; @@ -583,84 +589,55 @@ 670947411BDF9B99005014C0 /* drape_frontend */ = { isa = PBXGroup; children = ( - 45BE604D20E504FC00A456AE /* frame_values.hpp */, - BB59CED120BF6E46008A9ADF /* transit_scheme_builder.cpp */, - BB59CED420BF6E46008A9ADF /* transit_scheme_builder.hpp */, - BB59CED220BF6E46008A9ADF /* transit_scheme_renderer.cpp */, - BB59CED320BF6E46008A9ADF /* transit_scheme_renderer.hpp */, - 454B9A391F4591AC003FAE7A /* drape_engine_safe_ptr.hpp */, - 453FEDAA1F34C257005C1BB4 /* render_state.cpp */, - 453FEDAB1F34C257005C1BB4 /* render_state.hpp */, - EB2B78011EEDD439002697B6 /* read_metaline_task.cpp */, - EB2B78021EEDD439002697B6 /* read_metaline_task.hpp */, - EB2B77FD1EEDD418002697B6 /* metaline_manager.cpp */, - EB2B77FE1EEDD418002697B6 /* metaline_manager.hpp */, + 670948051BDF9C0D005014C0 /* animation */, + 454C19B81CCE3EC0002A2C86 /* animation_constants.hpp */, + 454C19B91CCE3EC0002A2C86 /* animation_system.cpp */, + 454C19BA1CCE3EC0002A2C86 /* animation_system.hpp */, + 3492DA0C1CA2D9BF00C1F3B3 /* animation_utils.cpp */, + 3492DA0D1CA2D9BF00C1F3B3 /* animation_utils.hpp */, + 670947E81BDF9BF5005014C0 /* apply_feature_functors.cpp */, + 670947E91BDF9BF5005014C0 /* apply_feature_functors.hpp */, + 670947EA1BDF9BF5005014C0 /* area_shape.cpp */, + 670947EB1BDF9BF5005014C0 /* area_shape.hpp */, + 6743D3671C3A9F090095054B /* arrow3d.cpp */, + 6743D3681C3A9F090095054B /* arrow3d.hpp */, + 670947EC1BDF9BF5005014C0 /* backend_renderer.cpp */, + 670947ED1BDF9BF5005014C0 /* backend_renderer.hpp */, + 670947EE1BDF9BF5005014C0 /* base_renderer.cpp */, + 670947EF1BDF9BF5005014C0 /* base_renderer.hpp */, + 670E39361C46C59000E9C0A6 /* batch_merge_helper.cpp */, + 670E39371C46C59000E9C0A6 /* batch_merge_helper.hpp */, + 670947F11BDF9BF5005014C0 /* batchers_pool.hpp */, 451A2A801EE8464E003E05A4 /* circles_pack_shape.cpp */, 451A2A811EE8464E003E05A4 /* circles_pack_shape.hpp */, - BB7D67CF1F34A62C002FD122 /* custom_features_context.hpp */, - 456B3F971ED464FE009B3D1F /* postprocess_renderer.cpp */, - 456B3F981ED464FE009B3D1F /* postprocess_renderer.hpp */, - 45BB02221EB8BE1400FE5C0C /* shaders */, - 672D24981E892768004BB7B1 /* overlays_tracker.cpp */, - 672D24991E892768004BB7B1 /* overlays_tracker.hpp */, + 670E39381C46C59000E9C0A6 /* color_constants.cpp */, + 670E39391C46C59000E9C0A6 /* color_constants.hpp */, 453EEA6B1E3A28F400505E09 /* colored_symbol_shape.cpp */, 453EEA6C1E3A28F400505E09 /* colored_symbol_shape.hpp */, + BB7D67CF1F34A62C002FD122 /* custom_features_context.hpp */, 347F52071DC2334A0064B273 /* drape_api_builder.cpp */, 347F52081DC2334A0064B273 /* drape_api_builder.hpp */, 347F52091DC2334A0064B273 /* drape_api_renderer.cpp */, 347F520A1DC2334A0064B273 /* drape_api_renderer.hpp */, 347F520B1DC2334A0064B273 /* drape_api.cpp */, 347F520C1DC2334A0064B273 /* drape_api.hpp */, + 454B9A391F4591AC003FAE7A /* drape_engine_safe_ptr.hpp */, + 670947F41BDF9BF5005014C0 /* drape_engine.cpp */, + 670947F51BDF9BF5005014C0 /* drape_engine.hpp */, BBD8F8781E96A51A00BAEB72 /* drape_hints.hpp */, BB035F6D1E3A2AAE00519962 /* drape_measurer.cpp */, BB035F6E1E3A2AAE00519962 /* drape_measurer.hpp */, - 34C624BF1DABDB0400510300 /* traffic_generator.cpp */, - 34C624C01DABDB0400510300 /* traffic_generator.hpp */, - 34C624C11DABDB0400510300 /* traffic_renderer.cpp */, - 34C624C21DABDB0400510300 /* traffic_renderer.hpp */, - 45B4B8C71CF5C16B00A54761 /* screen_animations.cpp */, - 45B4B8C81CF5C16B00A54761 /* screen_animations.hpp */, - 45B4B8C91CF5C16B00A54761 /* screen_operations.cpp */, - 45B4B8CA1CF5C16B00A54761 /* screen_operations.hpp */, - 452FE5C11EB2004F00EE470C /* screen_quad_renderer.cpp */, - 452FE5C21EB2004F00EE470C /* screen_quad_renderer.hpp */, - 454C19B81CCE3EC0002A2C86 /* animation_constants.hpp */, - 454C19B91CCE3EC0002A2C86 /* animation_system.cpp */, - 454C19BA1CCE3EC0002A2C86 /* animation_system.hpp */, - 3492DA0C1CA2D9BF00C1F3B3 /* animation_utils.cpp */, - 3492DA0D1CA2D9BF00C1F3B3 /* animation_utils.hpp */, - 56D545641C74A44900E3719C /* overlay_batcher.cpp */, - 56D545651C74A44900E3719C /* overlay_batcher.hpp */, - 670E39361C46C59000E9C0A6 /* batch_merge_helper.cpp */, - 670E39371C46C59000E9C0A6 /* batch_merge_helper.hpp */, - 670E39381C46C59000E9C0A6 /* color_constants.cpp */, - 670E39391C46C59000E9C0A6 /* color_constants.hpp */, - 6743D3671C3A9F090095054B /* arrow3d.cpp */, - 6743D3681C3A9F090095054B /* arrow3d.hpp */, - 45580AB91E28DB2600CD535D /* scenario_manager.hpp */, - 45580AB81E28DB2600CD535D /* scenario_manager.cpp */, + 45F1DA8320F3B274006E8CB3 /* drape_notifier.cpp */, + 45F1DA8220F3B274006E8CB3 /* drape_notifier.hpp */, + 670947E01BDF9BEC005014C0 /* engine_context.cpp */, + 670947E11BDF9BEC005014C0 /* engine_context.hpp */, + 45BE604D20E504FC00A456AE /* frame_values.hpp */, + 670947E21BDF9BEC005014C0 /* frontend_renderer.cpp */, + 670947E31BDF9BEC005014C0 /* frontend_renderer.hpp */, F6B2830B1C1B04680081957A /* gps_track_point.hpp */, F6B2830C1C1B04680081957A /* gps_track_renderer.cpp */, F6B2830D1C1B04680081957A /* gps_track_renderer.hpp */, - 677A2DE31C0DD55D00635A00 /* requested_tiles.cpp */, - 677A2DE41C0DD55D00635A00 /* requested_tiles.hpp */, 670948061BDF9C15005014C0 /* gui */, - 670948051BDF9C0D005014C0 /* animation */, - 670947E81BDF9BF5005014C0 /* apply_feature_functors.cpp */, - 670947E91BDF9BF5005014C0 /* apply_feature_functors.hpp */, - 670947EA1BDF9BF5005014C0 /* area_shape.cpp */, - 670947EB1BDF9BF5005014C0 /* area_shape.hpp */, - 670947EC1BDF9BF5005014C0 /* backend_renderer.cpp */, - 670947ED1BDF9BF5005014C0 /* backend_renderer.hpp */, - 670947EE1BDF9BF5005014C0 /* base_renderer.cpp */, - 670947EF1BDF9BF5005014C0 /* base_renderer.hpp */, - 670947F11BDF9BF5005014C0 /* batchers_pool.hpp */, - 670947F41BDF9BF5005014C0 /* drape_engine.cpp */, - 670947F51BDF9BF5005014C0 /* drape_engine.hpp */, - 670947E01BDF9BEC005014C0 /* engine_context.cpp */, - 670947E11BDF9BEC005014C0 /* engine_context.hpp */, - 670947E21BDF9BEC005014C0 /* frontend_renderer.cpp */, - 670947E31BDF9BEC005014C0 /* frontend_renderer.hpp */, 670947431BDF9BE0005014C0 /* kinetic_scroller.cpp */, 670947441BDF9BE0005014C0 /* kinetic_scroller.hpp */, 670947451BDF9BE0005014C0 /* line_shape_helper.cpp */, @@ -676,12 +653,18 @@ 670947511BDF9BE0005014C0 /* message_queue.hpp */, 670947521BDF9BE0005014C0 /* message_subclasses.hpp */, 670947531BDF9BE0005014C0 /* message.hpp */, + EB2B77FD1EEDD418002697B6 /* metaline_manager.cpp */, + EB2B77FE1EEDD418002697B6 /* metaline_manager.hpp */, 670947541BDF9BE0005014C0 /* my_position_controller.cpp */, 670947551BDF9BE0005014C0 /* my_position_controller.hpp */, 670947561BDF9BE0005014C0 /* my_position.cpp */, 670947571BDF9BE0005014C0 /* my_position.hpp */, 670947581BDF9BE0005014C0 /* navigator.cpp */, 670947591BDF9BE0005014C0 /* navigator.hpp */, + 56D545641C74A44900E3719C /* overlay_batcher.cpp */, + 56D545651C74A44900E3719C /* overlay_batcher.hpp */, + 672D24981E892768004BB7B1 /* overlays_tracker.cpp */, + 672D24991E892768004BB7B1 /* overlays_tracker.hpp */, 6709475A1BDF9BE0005014C0 /* path_symbol_shape.cpp */, 6709475B1BDF9BE0005014C0 /* path_symbol_shape.hpp */, BB7D67D01F34A62C002FD122 /* path_text_handle.cpp */, @@ -690,13 +673,21 @@ 6709475D1BDF9BE0005014C0 /* path_text_shape.hpp */, 6709475E1BDF9BE0005014C0 /* poi_symbol_shape.cpp */, 6709475F1BDF9BE0005014C0 /* poi_symbol_shape.hpp */, + 456B3F971ED464FE009B3D1F /* postprocess_renderer.cpp */, + 456B3F981ED464FE009B3D1F /* postprocess_renderer.hpp */, 670947601BDF9BE0005014C0 /* read_manager.cpp */, 670947611BDF9BE0005014C0 /* read_manager.hpp */, + EB2B78011EEDD439002697B6 /* read_metaline_task.cpp */, + EB2B78021EEDD439002697B6 /* read_metaline_task.hpp */, 670947621BDF9BE0005014C0 /* read_mwm_task.cpp */, 670947631BDF9BE0005014C0 /* read_mwm_task.hpp */, 670947641BDF9BE0005014C0 /* render_group.cpp */, 670947651BDF9BE0005014C0 /* render_group.hpp */, 670947671BDF9BE0005014C0 /* render_node.hpp */, + 453FEDAA1F34C257005C1BB4 /* render_state.cpp */, + 453FEDAB1F34C257005C1BB4 /* render_state.hpp */, + 677A2DE31C0DD55D00635A00 /* requested_tiles.cpp */, + 677A2DE41C0DD55D00635A00 /* requested_tiles.hpp */, 670947681BDF9BE0005014C0 /* route_builder.cpp */, 670947691BDF9BE0005014C0 /* route_builder.hpp */, 6709476A1BDF9BE0005014C0 /* route_renderer.cpp */, @@ -705,8 +696,17 @@ 6709476D1BDF9BE0005014C0 /* route_shape.hpp */, 6709476E1BDF9BE0005014C0 /* rule_drawer.cpp */, 6709476F1BDF9BE0005014C0 /* rule_drawer.hpp */, + 45580AB81E28DB2600CD535D /* scenario_manager.cpp */, + 45580AB91E28DB2600CD535D /* scenario_manager.hpp */, + 45B4B8C71CF5C16B00A54761 /* screen_animations.cpp */, + 45B4B8C81CF5C16B00A54761 /* screen_animations.hpp */, + 45B4B8C91CF5C16B00A54761 /* screen_operations.cpp */, + 45B4B8CA1CF5C16B00A54761 /* screen_operations.hpp */, + 452FE5C11EB2004F00EE470C /* screen_quad_renderer.cpp */, + 452FE5C21EB2004F00EE470C /* screen_quad_renderer.hpp */, 670947701BDF9BE0005014C0 /* selection_shape.cpp */, 670947711BDF9BE0005014C0 /* selection_shape.hpp */, + 45BB02221EB8BE1400FE5C0C /* shaders */, 670947721BDF9BE0005014C0 /* shape_view_params.hpp */, 670947731BDF9BE0005014C0 /* stylist.cpp */, 670947741BDF9BE0005014C0 /* stylist.hpp */, @@ -724,6 +724,14 @@ 670947801BDF9BE0005014C0 /* tile_key.hpp */, 670947851BDF9BE0005014C0 /* tile_utils.cpp */, 670947861BDF9BE0005014C0 /* tile_utils.hpp */, + 34C624BF1DABDB0400510300 /* traffic_generator.cpp */, + 34C624C01DABDB0400510300 /* traffic_generator.hpp */, + 34C624C11DABDB0400510300 /* traffic_renderer.cpp */, + 34C624C21DABDB0400510300 /* traffic_renderer.hpp */, + BB59CED120BF6E46008A9ADF /* transit_scheme_builder.cpp */, + BB59CED420BF6E46008A9ADF /* transit_scheme_builder.hpp */, + BB59CED220BF6E46008A9ADF /* transit_scheme_renderer.cpp */, + BB59CED320BF6E46008A9ADF /* transit_scheme_renderer.hpp */, 670947871BDF9BE0005014C0 /* user_event_stream.cpp */, 670947881BDF9BE0005014C0 /* user_event_stream.hpp */, BBD9E2D11F009D9E00DF189A /* user_mark_generator.cpp */, @@ -794,6 +802,7 @@ 670948321BDF9C48005014C0 /* ruler_helper.hpp */, 670948331BDF9C48005014C0 /* ruler.cpp */, 670948341BDF9C48005014C0 /* ruler.hpp */, + 45B241AD20EF9D0400A759D6 /* scale_fps_helper.hpp */, 670948351BDF9C48005014C0 /* shape.cpp */, 670948361BDF9C48005014C0 /* shape.hpp */, 670948371BDF9C48005014C0 /* skin.cpp */, @@ -829,6 +838,7 @@ 452C9ED51CEDCF3200A55E57 /* animation.hpp in Headers */, 45B4B8CE1CF5C16B00A54761 /* screen_operations.hpp in Headers */, 670947C71BDF9BE1005014C0 /* text_layout.hpp in Headers */, + 45F1DA8420F3B274006E8CB3 /* drape_notifier.hpp in Headers */, 451A2A831EE8464E003E05A4 /* circles_pack_shape.hpp in Headers */, 670947FF1BDF9BF5005014C0 /* batchers_pool.hpp in Headers */, 670947C01BDF9BE1005014C0 /* selection_shape.hpp in Headers */, @@ -882,6 +892,7 @@ 670E393B1C46C59000E9C0A6 /* batch_merge_helper.hpp in Headers */, 670947931BDF9BE1005014C0 /* kinetic_scroller.hpp in Headers */, 670947E71BDF9BEC005014C0 /* frontend_renderer.hpp in Headers */, + 45B241AE20EF9D0500A759D6 /* scale_fps_helper.hpp in Headers */, 670947F71BDF9BF5005014C0 /* apply_feature_functors.hpp in Headers */, BB59CED720BF6E46008A9ADF /* transit_scheme_renderer.hpp in Headers */, 670947CD1BDF9BE1005014C0 /* tile_info.hpp in Headers */, @@ -1035,6 +1046,7 @@ 670947C21BDF9BE1005014C0 /* stylist.cpp in Sources */, 670947AD1BDF9BE1005014C0 /* poi_symbol_shape.cpp in Sources */, BB59CED620BF6E46008A9ADF /* transit_scheme_renderer.cpp in Sources */, + 45F1DA8520F3B274006E8CB3 /* drape_notifier.cpp in Sources */, 6709479F1BDF9BE1005014C0 /* message_queue.cpp in Sources */, 452C9EE41CEDCF3200A55E57 /* sequence_animation.cpp in Sources */, BB7D67D31F34A62C002FD122 /* path_text_handle.cpp in Sources */,