diff --git a/drape_frontend/backend_renderer.cpp b/drape_frontend/backend_renderer.cpp index 60d1a5600d..4db2d97631 100644 --- a/drape_frontend/backend_renderer.cpp +++ b/drape_frontend/backend_renderer.cpp @@ -39,6 +39,11 @@ BackendRenderer::BackendRenderer(Params const & params) m_commutator->PostMessage(ThreadsCommutator::RenderThread, make_unique_dp(move(routeData)), MessagePriority::Normal); + }, [this](drape_ptr && routeSignData) + { + m_commutator->PostMessage(ThreadsCommutator::RenderThread, + make_unique_dp(move(routeSignData)), + MessagePriority::Normal); }); StartThread(); @@ -186,6 +191,12 @@ void BackendRenderer::AcceptMessage(ref_ptr message) m_routeBuilder->Build(msg->GetRoutePolyline(), msg->GetTurns(), msg->GetColor(), m_texMng); break; } + case Message::CacheRouteSign: + { + ref_ptr msg = message; + m_routeBuilder->BuildSign(msg->GetPosition(), msg->IsStart(), msg->IsValid(), m_texMng); + break; + } case Message::RemoveRoute: { ref_ptr msg = message; diff --git a/drape_frontend/drape_engine.cpp b/drape_frontend/drape_engine.cpp index d08c0897c7..7d77d1fac1 100644 --- a/drape_frontend/drape_engine.cpp +++ b/drape_frontend/drape_engine.cpp @@ -402,6 +402,13 @@ void DrapeEngine::DeactivateRouteFollowing() MessagePriority::Normal); } +void DrapeEngine::SetRoutePoint(m2::PointD const & position, bool isStart, bool isValid) +{ + m_threadCommutator->PostMessage(ThreadsCommutator::ResourceUploadThread, + make_unique_dp(position, isStart, isValid), + MessagePriority::Normal); +} + void DrapeEngine::SetWidgetLayout(gui::TWidgetsLayoutInfo && info) { m_widgetsLayout = move(info); diff --git a/drape_frontend/drape_engine.hpp b/drape_frontend/drape_engine.hpp index a3ce76ecc2..437341f822 100644 --- a/drape_frontend/drape_engine.hpp +++ b/drape_frontend/drape_engine.hpp @@ -109,6 +109,7 @@ public: void RemoveRoute(bool deactivateFollowing); void FollowRoute(int preferredZoomLevel); void DeactivateRouteFollowing(); + void SetRoutePoint(m2::PointD const & position, bool isStart, bool isValid); void SetWidgetLayout(gui::TWidgetsLayoutInfo && info); gui::TWidgetsSizeInfo const & GetWidgetSizes(); diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index f3fa3f4937..7a7053ff97 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -321,12 +321,36 @@ void FrontendRenderer::AcceptMessage(ref_ptr message) { ref_ptr msg = message; drape_ptr routeData = msg->AcceptRouteData(); + m2::PointD startPoint = routeData->m_sourcePolyline.Front(); + m2::PointD finishPoint = routeData->m_sourcePolyline.Back(); m_routeRenderer->SetRouteData(move(routeData), make_ref(m_gpuProgramManager)); + if (!m_routeRenderer->GetStartPoint()) + { + m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread, + make_unique_dp(startPoint, true /* isStart */, + true /* isValid */), + MessagePriority::High); + } + if (!m_routeRenderer->GetFinishPoint()) + { + m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread, + make_unique_dp(finishPoint, false /* isStart */, + true /* isValid */), + MessagePriority::High); + } m_myPositionController->ActivateRouting(); break; } + case Message::FlushRouteSign: + { + ref_ptr msg = message; + drape_ptr routeSignData = msg->AcceptRouteSignData(); + m_routeRenderer->SetRouteSign(move(routeSignData), make_ref(m_gpuProgramManager)); + break; + } + case Message::RemoveRoute: { ref_ptr msg = message; @@ -369,6 +393,23 @@ void FrontendRenderer::AcceptMessage(ref_ptr message) blocker.Wait(); // Invalidate route. + if (m_routeRenderer->GetStartPoint()) + { + m2::PointD const & position = m_routeRenderer->GetStartPoint()->m_position; + m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread, + make_unique_dp(position, true /* isStart */, + true /* isValid */), + MessagePriority::High); + } + if (m_routeRenderer->GetFinishPoint()) + { + m2::PointD const & position = m_routeRenderer->GetFinishPoint()->m_position; + m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread, + make_unique_dp(position, false /* isStart */, + true /* isValid */), + MessagePriority::High); + } + auto const & routeData = m_routeRenderer->GetRouteData(); if (routeData != nullptr) { diff --git a/drape_frontend/message.hpp b/drape_frontend/message.hpp index d31f949e4a..bc5b7a4492 100644 --- a/drape_frontend/message.hpp +++ b/drape_frontend/message.hpp @@ -35,8 +35,10 @@ public: GetSelectedObject, GetMyPosition, AddRoute, + CacheRouteSign, RemoveRoute, FlushRoute, + FlushRouteSign, DeactivateRouteFollowing, UpdateMapStyle, InvalidateTextures, diff --git a/drape_frontend/message_subclasses.hpp b/drape_frontend/message_subclasses.hpp index d5c2182707..83288f03e8 100644 --- a/drape_frontend/message_subclasses.hpp +++ b/drape_frontend/message_subclasses.hpp @@ -539,6 +539,27 @@ private: vector m_turns; }; +class CacheRouteSignMessage : public Message +{ +public: + CacheRouteSignMessage(m2::PointD const & pos, bool isStart, bool isValid) + : m_position(pos) + , m_isStart(isStart) + , m_isValid(isValid) + {} + + Type GetType() const override { return Message::CacheRouteSign; } + + m2::PointD const & GetPosition() const { return m_position; } + bool IsStart() const { return m_isStart; } + bool IsValid() const { return m_isValid; } + +private: + m2::PointD m_position; + bool m_isStart; + bool m_isValid; +}; + class RemoveRouteMessage : public Message { public: @@ -568,6 +589,20 @@ private: drape_ptr m_routeData; }; +class FlushRouteSignMessage : public Message +{ +public: + FlushRouteSignMessage(drape_ptr && routeSignData) + : m_routeSignData(move(routeSignData)) + {} + + Type GetType() const override { return Message::FlushRouteSign; } + drape_ptr && AcceptRouteSignData() { return move(m_routeSignData); } + +private: + drape_ptr m_routeSignData; +}; + class UpdateMapStyleMessage : public BaseBlockingMessage { public: diff --git a/drape_frontend/route_builder.cpp b/drape_frontend/route_builder.cpp index 6e0bb23a56..f98e5f5e41 100644 --- a/drape_frontend/route_builder.cpp +++ b/drape_frontend/route_builder.cpp @@ -5,8 +5,10 @@ namespace df { -RouteBuilder::RouteBuilder(RouteBuilder::TFlushRouteFn const & flushRouteFn) +RouteBuilder::RouteBuilder(TFlushRouteFn const & flushRouteFn, + TFlushRouteSignFn const & flushRouteSignFn) : m_flushRouteFn(flushRouteFn) + , m_flushRouteSignFn(flushRouteSignFn) {} void RouteBuilder::Build(m2::PolylineD const & routePolyline, vector const & turns, @@ -27,4 +29,24 @@ void RouteBuilder::Build(m2::PolylineD const & routePolyline, vector con m_flushRouteFn(move(routeData)); } +void RouteBuilder::BuildSign(m2::PointD const & pos, bool isStart, bool isValid, + ref_ptr textures) +{ + drape_ptr routeSignData = make_unique_dp(); + routeSignData->m_isStart = isStart; + routeSignData->m_position = pos; + routeSignData->m_isValid = isValid; + if (isValid) + { + CommonViewParams params; + params.m_minVisibleScale = 1; + params.m_rank = 0; + params.m_depth = 0.0f; + RouteShape(params).CacheRouteSign(textures, *routeSignData.get()); + } + + if (m_flushRouteSignFn != nullptr) + m_flushRouteSignFn(move(routeSignData)); +} + } // namespace df diff --git a/drape_frontend/route_builder.hpp b/drape_frontend/route_builder.hpp index 6a1b105052..0a6bedd78f 100644 --- a/drape_frontend/route_builder.hpp +++ b/drape_frontend/route_builder.hpp @@ -16,14 +16,20 @@ class RouteBuilder { public: using TFlushRouteFn = function &&)>; + using TFlushRouteSignFn = function &&)>; - RouteBuilder(TFlushRouteFn const & flushRouteFn); + RouteBuilder(TFlushRouteFn const & flushRouteFn, + TFlushRouteSignFn const & flushRouteSignFn); void Build(m2::PolylineD const & routePolyline, vector const & turns, dp::Color const & color, ref_ptr textures); + void BuildSign(m2::PointD const & pos, bool isStart, bool isValid, + ref_ptr textures); + private: TFlushRouteFn m_flushRouteFn; + TFlushRouteSignFn m_flushRouteSignFn; }; } // namespace df diff --git a/drape_frontend/route_renderer.cpp b/drape_frontend/route_renderer.cpp index 9d75c2a7b3..857076eeee 100644 --- a/drape_frontend/route_renderer.cpp +++ b/drape_frontend/route_renderer.cpp @@ -219,24 +219,35 @@ void RouteRenderer::RenderRoute(ScreenBase const & screen, ref_ptr mng, dp::UniformValuesStorage const & commonUniforms) { - if (!m_routeData) - return; - - // render end of route + if (m_startRouteSign) { - dp::GLState const & state = m_routeData->m_endOfRouteSign.m_state; - - dp::UniformValuesStorage uniforms = commonUniforms; - uniforms.SetFloatValue("u_opacity", 1.0); - - ref_ptr program = mng->GetProgram(state.GetProgramIndex()); - program->Bind(); - dp::ApplyState(m_routeData->m_endOfRouteSign.m_state, program); - dp::ApplyUniforms(uniforms, program); - - for (drape_ptr const & bucket : m_routeData->m_endOfRouteSign.m_buckets) - bucket->Render(screen); + ASSERT(m_startRouteSign->m_isValid, ()); + RenderRouteSign(m_startRouteSign, screen, mng, commonUniforms); } + + if (m_finishRouteSign) + { + ASSERT(m_finishRouteSign->m_isValid, ()); + RenderRouteSign(m_finishRouteSign, screen, mng, commonUniforms); + } +} + +void RouteRenderer::RenderRouteSign(drape_ptr const & sign, ScreenBase const & screen, + ref_ptr mng, + dp::UniformValuesStorage const & commonUniforms) +{ + dp::GLState const & state = sign->m_sign.m_state; + + dp::UniformValuesStorage uniforms = commonUniforms; + uniforms.SetFloatValue("u_opacity", 1.0); + + ref_ptr program = mng->GetProgram(state.GetProgramIndex()); + program->Bind(); + dp::ApplyState(sign->m_sign.m_state, program); + dp::ApplyUniforms(uniforms, program); + + for (drape_ptr const & bucket : sign->m_sign.m_buckets) + bucket->Render(screen); } void RouteRenderer::RenderArrow(ref_ptr prg, drape_ptr const & property, @@ -284,13 +295,48 @@ void RouteRenderer::SetRouteData(drape_ptr && routeData, ref_ptrm_route, mng); - BuildBuckets(m_routeData->m_endOfRouteSign, mng); for (drape_ptr const & arrow : m_routeData->m_arrows) BuildBuckets(arrow->m_arrow, mng); m_distanceFromBegin = 0.0; } +void RouteRenderer::SetRouteSign(drape_ptr && routeSignData, ref_ptr mng) +{ + if (routeSignData->m_isStart) + { + if (!routeSignData->m_isValid) + { + m_startRouteSign.reset(); + return; + } + + m_startRouteSign = move(routeSignData); + BuildBuckets(m_startRouteSign->m_sign, mng); + } + else + { + if (!routeSignData->m_isValid) + { + m_finishRouteSign.reset(); + return; + } + + m_finishRouteSign = move(routeSignData); + BuildBuckets(m_finishRouteSign->m_sign, mng); + } +} + +drape_ptr const & RouteRenderer::GetStartPoint() const +{ + return m_startRouteSign; +} + +drape_ptr const & RouteRenderer::GetFinishPoint() const +{ + return m_finishRouteSign; +} + drape_ptr const & RouteRenderer::GetRouteData() const { return m_routeData; @@ -299,6 +345,8 @@ drape_ptr const & RouteRenderer::GetRouteData() const void RouteRenderer::Clear(bool keepDistanceFromBegin) { m_routeData.reset(); + m_startRouteSign.reset(); + m_finishRouteSign.reset(); m_arrowBorders.clear(); m_routeSegments.clear(); diff --git a/drape_frontend/route_renderer.hpp b/drape_frontend/route_renderer.hpp index 0a6d10d550..5f3f32603c 100644 --- a/drape_frontend/route_renderer.hpp +++ b/drape_frontend/route_renderer.hpp @@ -46,6 +46,10 @@ public: void SetRouteData(drape_ptr && routeData, ref_ptr mng); drape_ptr const & GetRouteData() const; + void SetRouteSign(drape_ptr && routeSignData, ref_ptr mng); + drape_ptr const & GetStartPoint() const; + drape_ptr const & GetFinishPoint() const; + void Clear(bool keepDistanceFromBegin = false); void UpdateDistanceFromBegin(double distanceFromBegin); @@ -58,12 +62,17 @@ private: void RenderArrow(ref_ptr prg, drape_ptr const & property, float halfWidth, ScreenBase const & screen); void InterpolateByZoom(ScreenBase const & screen, float & halfWidth, float & alpha, double & zoom) const; + void RenderRouteSign(drape_ptr const & sign, ScreenBase const & screen, + ref_ptr mng, dp::UniformValuesStorage const & commonUniforms); double m_distanceFromBegin; drape_ptr m_routeData; vector m_arrowBorders; vector m_routeSegments; + + drape_ptr m_startRouteSign; + drape_ptr m_finishRouteSign; }; } // namespace df diff --git a/drape_frontend/route_shape.cpp b/drape_frontend/route_shape.cpp index c7c0ace462..9a35d67117 100644 --- a/drape_frontend/route_shape.cpp +++ b/drape_frontend/route_shape.cpp @@ -280,15 +280,15 @@ void RouteShape::PrepareGeometry(bool isRoute, vector const & path, } } -void RouteShape::CacheEndOfRouteSign(ref_ptr mng, RouteData & routeData) +void RouteShape::CacheRouteSign(ref_ptr mng, RouteSignData & routeSignData) { dp::TextureManager::SymbolRegion symbol; - mng->GetSymbolRegion("route_to", symbol); + mng->GetSymbolRegion(routeSignData.m_isStart ? "route_from" : "route_to", symbol); m2::RectF const & texRect = symbol.GetTexRect(); m2::PointF halfSize = m2::PointF(symbol.GetPixelSize()) * 0.5f; - glsl::vec2 const pos = glsl::ToVec2(routeData.m_sourcePolyline.Back()); + glsl::vec2 const pos = glsl::ToVec2(routeSignData.m_position); glsl::vec3 const pivot = glsl::vec3(pos.x, pos.y, m_params.m_depth); gpu::SolidTexturingVertex data[4]= { @@ -303,10 +303,10 @@ void RouteShape::CacheEndOfRouteSign(ref_ptr mng, RouteData { dp::Batcher batcher(dp::Batcher::IndexPerQuad, dp::Batcher::VertexPerQuad); - dp::SessionGuard guard(batcher, [&routeData](dp::GLState const & state, drape_ptr && b) + dp::SessionGuard guard(batcher, [&routeSignData](dp::GLState const & state, drape_ptr && b) { - routeData.m_endOfRouteSign.m_buckets.push_back(move(b)); - routeData.m_endOfRouteSign.m_state = state; + routeSignData.m_sign.m_buckets.push_back(move(b)); + routeSignData.m_sign.m_state = state; }); dp::AttributeProvider provider(1 /* stream count */, dp::Batcher::VertexPerQuad); @@ -352,9 +352,6 @@ void RouteShape::Draw(ref_ptr textures, RouteData & routeDat BatchGeometry(state, geometry, joinsGeometry, renderProperty->m_arrow); } } - - // end of route sign - CacheEndOfRouteSign(textures, routeData); } void RouteShape::BatchGeometry(dp::GLState const & state, TGeometryBuffer & geometry, diff --git a/drape_frontend/route_shape.hpp b/drape_frontend/route_shape.hpp index 5061360ef7..ad806642f6 100644 --- a/drape_frontend/route_shape.hpp +++ b/drape_frontend/route_shape.hpp @@ -49,20 +49,27 @@ struct RouteData double m_length; RouteRenderProperty m_route; vector> m_arrows; - RouteRenderProperty m_endOfRouteSign; +}; + +struct RouteSignData +{ + RouteRenderProperty m_sign; + bool m_isStart; + bool m_isValid; + m2::PointD m_position; }; class RouteShape { public: RouteShape(CommonViewParams const & params); + void CacheRouteSign(ref_ptr mng, RouteSignData & routeSignData); void Draw(ref_ptr textures, RouteData & routeData); private: using RV = gpu::RouteVertex; using TGeometryBuffer = buffer_vector; - void CacheEndOfRouteSign(ref_ptr mng, RouteData & routeData); void PrepareGeometry(bool isRoute, vector const & path, TGeometryBuffer & geometry, TGeometryBuffer & joinsGeometry, vector & joinsBounds, double & outputLength); diff --git a/iphone/Maps/Classes/CustomViews/MapViewControls/MWMMapViewControlsManager.mm b/iphone/Maps/Classes/CustomViews/MapViewControls/MWMMapViewControlsManager.mm index d6101d1c1f..95cd491adc 100644 --- a/iphone/Maps/Classes/CustomViews/MapViewControls/MWMMapViewControlsManager.mm +++ b/iphone/Maps/Classes/CustomViews/MapViewControls/MWMMapViewControlsManager.mm @@ -474,6 +474,7 @@ extern NSString * const kAlohalyticsTapEventKey; GetFramework().SetRouteStartPoint(self.routeSource.Point(), self.routeSource != MWMRoutePoint::MWMRoutePointZero()); + GetFramework().SetRouteFinishPoint(self.routeDestination.Point(), self.routeDestination != MWMRoutePoint::MWMRoutePointZero()); } diff --git a/map/framework.cpp b/map/framework.cpp index 8f6a600099..76b1203427 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -2040,10 +2040,12 @@ void Framework::SetLastUsedRouter(RouterType type) void Framework::SetRouteStartPoint(m2::PointD const & pt, bool isValid) { - //m_bmManager.SetRouteStartPoint(pt); + if (m_drapeEngine != nullptr) + m_drapeEngine->SetRoutePoint(pt, true /* isStart */, isValid); } void Framework::SetRouteFinishPoint(m2::PointD const & pt, bool isValid) { - //m_bmManager.SetRouteFinishPoint(pt); + if (m_drapeEngine != nullptr) + m_drapeEngine->SetRoutePoint(pt, false /* isStart */, isValid); }