diff --git a/drape_frontend/user_mark_shapes.cpp b/drape_frontend/user_mark_shapes.cpp index 973fda6590..1cdc0084c3 100644 --- a/drape_frontend/user_mark_shapes.cpp +++ b/drape_frontend/user_mark_shapes.cpp @@ -90,6 +90,8 @@ void CacheUserPoints(UserMarksProvider const * provider, ref_ptrGetUserPointMark(i); + if (!userMark->IsVisible()) + continue; TileKey const tileKey = GetTileKeyByPoint(userMark->GetPivot(), kZoomLevel); marks[tileKey].push_back(userMark); } diff --git a/drape_frontend/user_marks_provider.hpp b/drape_frontend/user_marks_provider.hpp index 8a9b45e4a7..ea8efe2cb0 100644 --- a/drape_frontend/user_marks_provider.hpp +++ b/drape_frontend/user_marks_provider.hpp @@ -21,6 +21,7 @@ public: virtual dp::Anchor GetAnchor() const = 0; virtual float GetDepth() const = 0; virtual bool RunCreationAnim() const = 0; + virtual bool IsVisible() const { return true; } }; class UserLineMark diff --git a/map/bookmark_manager.cpp b/map/bookmark_manager.cpp index b210150e24..14703d3f7f 100644 --- a/map/bookmark_manager.cpp +++ b/map/bookmark_manager.cpp @@ -1,5 +1,6 @@ #include "map/bookmark_manager.hpp" #include "map/framework.hpp" +#include "map/routing_mark.hpp" #include "map/user_mark.hpp" #include "platform/platform.hpp" @@ -23,6 +24,7 @@ BookmarkManager::BookmarkManager(Framework & f) m_userMarkLayers.push_back(new SearchUserMarkContainer(0.0 /* activePinDepth */, m_framework)); m_userMarkLayers.push_back(new ApiUserMarkContainer(0.0 /* activePinDepth */, m_framework)); m_userMarkLayers.push_back(new DebugUserMarkContainer(0.0 /* debugDepth */, m_framework)); + m_userMarkLayers.push_back(new RouteUserMarkContainer(0.0 /* activePinDepth */, m_framework)); UserMarkContainer::InitStaticMarks(FindUserMarksContainer(UserMarkType::SEARCH_MARK)); } diff --git a/map/map.pro b/map/map.pro index 5d5c4f4b84..548d644b59 100644 --- a/map/map.pro +++ b/map/map.pro @@ -33,6 +33,7 @@ HEADERS += \ place_page_info.hpp \ reachable_by_taxi_checker.hpp \ routing_manager.hpp \ + routing_mark.hpp \ track.hpp \ traffic_manager.hpp \ user_mark.hpp \ @@ -63,6 +64,7 @@ SOURCES += \ place_page_info.cpp \ reachable_by_taxi_checker.cpp \ routing_manager.cpp \ + routing_mark.cpp \ track.cpp \ traffic_manager.cpp \ user_mark.cpp \ diff --git a/map/routing_mark.cpp b/map/routing_mark.cpp new file mode 100644 index 0000000000..5b2c067e14 --- /dev/null +++ b/map/routing_mark.cpp @@ -0,0 +1,192 @@ +#include "map/routing_mark.hpp" + +#include + +static int8_t const kMaxIntermediatePointsCount = 3; + +RouteMarkPoint::RouteMarkPoint(const m2::PointD & ptOrg, UserMarkContainer * container) + : UserMark(ptOrg, container) +{} + +bool RouteMarkPoint::IsVisible() const +{ + return m_isVisible; +} + +void RouteMarkPoint::SetIsVisible(bool isVisible) +{ + m_isVisible = isVisible; +} + +std::string RouteMarkPoint::GetSymbolName() const +{ + switch (m_pointType) + { + case RouteMarkType::Start: + return "placemark-blue"; + case RouteMarkType::Intermediate: + if (m_intermediateIndex == 0) + return "placemark-yellow"; + if (m_intermediateIndex == 1) + return "placemark-orange"; + return "placemark-red"; + case RouteMarkType::Finish: + return "placemark-green"; + } +} + +RouteUserMarkContainer::RouteUserMarkContainer(double layerDepth, Framework & fm) + : UserMarkContainer(layerDepth, UserMarkType::ROUTING_MARK, fm) +{ +} + +UserMark * RouteUserMarkContainer::AllocateUserMark(m2::PointD const & ptOrg) +{ + return new RouteMarkPoint(ptOrg, this); +} + +RoutePointsLayout::RoutePointsLayout(UserMarksController & routeMarks) + : m_routeMarks(routeMarks) +{} + +RouteMarkPoint * RoutePointsLayout::AddRoutePoint(m2::PointD const & ptOrg, RouteMarkType type, int8_t intermediateIndex) +{ + if (m_routeMarks.GetUserMarkCount() == kMaxIntermediatePointsCount + 2) + return nullptr; + + RouteMarkPoint * sameTypePoint = GetRoutePoint(type, intermediateIndex); + if (sameTypePoint != nullptr) + { + if (type == RouteMarkType::Finish) + { + int8_t const intermediatePointsCount = std::max((int)m_routeMarks.GetUserMarkCount() - 2, 0); + sameTypePoint->SetRoutePointType(RouteMarkType::Intermediate); + sameTypePoint->SetIntermediateIndex(intermediatePointsCount); + } + else + { + int8_t const offsetIndex = type == RouteMarkType::Start ? 0 : intermediateIndex; + + ForEachIntermediatePoint([offsetIndex](RouteMarkPoint * mark) + { + if (mark->GetIntermediateIndex() >= offsetIndex) + mark->SetIntermediateIndex(mark->GetIntermediateIndex() + 1); + }); + + if (type == RouteMarkType::Start) + { + sameTypePoint->SetRoutePointType(RouteMarkType::Intermediate); + sameTypePoint->SetIntermediateIndex(0); + } + } + } + RouteMarkPoint * newPoint = static_cast(m_routeMarks.CreateUserMark(ptOrg)); + newPoint->SetRoutePointType(type); + newPoint->SetIntermediateIndex(intermediateIndex); + + return newPoint; +} + + +bool RoutePointsLayout::RemoveRoutePoint(RouteMarkType type, int8_t intermediateIndex) +{ + RouteMarkPoint * point = nullptr; + size_t index = 0; + for (size_t sz = m_routeMarks.GetUserMarkCount(); index < sz; ++index) + { + RouteMarkPoint * mark = static_cast(m_routeMarks.GetUserMarkForEdit(index)); + if (mark->GetRoutePointType() == type && mark->GetIntermediateIndex() == intermediateIndex) + { + point = mark; + break; + } + } + + if (point == nullptr) + return false; + + if (type == RouteMarkType::Finish) + { + RouteMarkPoint * lastIntermediate = nullptr; + int8_t maxIntermediateIndex = -1; + ForEachIntermediatePoint([&lastIntermediate, &maxIntermediateIndex](RouteMarkPoint * mark) + { + if (mark->GetIntermediateIndex() > maxIntermediateIndex) + { + lastIntermediate = mark; + maxIntermediateIndex = mark->GetIntermediateIndex(); + } + }); + + if (lastIntermediate != nullptr) + lastIntermediate->SetRoutePointType(RouteMarkType::Finish); + } + else if (type == RouteMarkType::Start) + { + ForEachIntermediatePoint([](RouteMarkPoint * mark) + { + if (mark->GetIntermediateIndex() == 0) + mark->SetRoutePointType(RouteMarkType::Start); + else + mark->SetIntermediateIndex(mark->GetIntermediateIndex() - 1); + }); + } + else + { + ForEachIntermediatePoint([point](RouteMarkPoint * mark) + { + if (mark->GetIntermediateIndex() > point->GetIntermediateIndex()) + mark->SetIntermediateIndex(mark->GetIntermediateIndex() - 1); + }); + } + + m_routeMarks.DeleteUserMark(index); + return true; +} + +bool RoutePointsLayout::MoveRoutePoint(RouteMarkType currentType, int8_t currentIntermediateIndex, + RouteMarkType destType, int8_t destIntermediateIndex) +{ + RouteMarkPoint * point = GetRoutePoint(currentType, currentIntermediateIndex); + if (point == nullptr) + return false; + + m2::PointD const pt = point->GetPivot(); + bool const isVisible = point->IsVisible(); + + RemoveRoutePoint(currentType, currentIntermediateIndex); + RouteMarkPoint * point2 = AddRoutePoint(pt, destType, destIntermediateIndex); + point2->SetIsVisible(isVisible); + return true; +} + +RouteMarkPoint * RoutePointsLayout::GetRoutePoint(RouteMarkType type, int8_t intermediateIndex) +{ + for (size_t i = 0, sz = m_routeMarks.GetUserMarkCount(); i < sz; ++i) + { + RouteMarkPoint * mark = static_cast(m_routeMarks.GetUserMarkForEdit(i)); + if (mark->GetRoutePointType() != type) + continue; + + if (type == RouteMarkType::Intermediate) + { + if (mark->GetIntermediateIndex() == intermediateIndex) + return mark; + } + else + { + return mark; + } + } + return nullptr; +} + +void RoutePointsLayout::ForEachIntermediatePoint(TRoutePointCallback const & fn) +{ + for (size_t i = 0, sz = m_routeMarks.GetUserMarkCount(); i < sz; ++i) + { + RouteMarkPoint * mark = static_cast(m_routeMarks.GetUserMarkForEdit(i)); + if (mark->GetRoutePointType() == RouteMarkType::Intermediate) + fn(mark); + } +} diff --git a/map/routing_mark.hpp b/map/routing_mark.hpp new file mode 100644 index 0000000000..5ca157fd15 --- /dev/null +++ b/map/routing_mark.hpp @@ -0,0 +1,62 @@ +#pragma once + +#include "map/user_mark_container.hpp" + +#include + +enum class RouteMarkType +{ + Start, + Intermediate, + Finish +}; + +class RouteMarkPoint : public UserMark +{ +public: + RouteMarkPoint(m2::PointD const & ptOrg, UserMarkContainer * container); + virtual ~RouteMarkPoint() {} + + bool IsVisible() const override; + void SetIsVisible(bool isVisible); + + std::string GetSymbolName() const override; + UserMark::Type GetMarkType() const override { return Type::ROUTING; } + + RouteMarkType GetRoutePointType() const { return m_pointType; } + void SetRoutePointType(RouteMarkType type) { m_pointType = type; } + + void SetIntermediateIndex(int8_t index) { m_intermediateIndex = index; } + int8_t GetIntermediateIndex() { return m_intermediateIndex; } + +private: + RouteMarkType m_pointType; + int8_t m_intermediateIndex = 0; + bool m_isVisible = true; +}; + +class RouteUserMarkContainer : public UserMarkContainer +{ +public: + RouteUserMarkContainer(double layerDepth, Framework & fm); +protected: + UserMark * AllocateUserMark(m2::PointD const & ptOrg) override; +}; + +class RoutePointsLayout +{ +public: + RoutePointsLayout(UserMarksController & routeMarks); + + RouteMarkPoint * GetRoutePoint(RouteMarkType type, int8_t intermediateIndex); + RouteMarkPoint * AddRoutePoint(m2::PointD const & ptOrg, RouteMarkType type, int8_t intermediateIndex = 0); + bool RemoveRoutePoint(RouteMarkType type, int8_t intermediateIndex = 0); + bool MoveRoutePoint(RouteMarkType currentType, int8_t currentIntermediateIndex, + RouteMarkType destType, int8_t destIntermediateIndex); + +private: + using TRoutePointCallback = function; + void ForEachIntermediatePoint(TRoutePointCallback const & fn); + + UserMarksController & m_routeMarks; +}; diff --git a/map/user_mark.cpp b/map/user_mark.cpp index 66e80444c1..9679274b96 100644 --- a/map/user_mark.cpp +++ b/map/user_mark.cpp @@ -106,5 +106,6 @@ string DebugPrint(UserMark::Type type) case UserMark::Type::BOOKMARK: return "BOOKMARK"; case UserMark::Type::MY_POSITION: return "MY_POSITION"; case UserMark::Type::DEBUG_MARK: return "DEBUG_MARK"; + case UserMark::Type::ROUTING: return "ROUTING"; } } diff --git a/map/user_mark.hpp b/map/user_mark.hpp index d205fa7689..a78f277174 100644 --- a/map/user_mark.hpp +++ b/map/user_mark.hpp @@ -28,6 +28,7 @@ public: POI, BOOKMARK, MY_POSITION, + ROUTING, DEBUG_MARK }; diff --git a/map/user_mark_container.hpp b/map/user_mark_container.hpp index e9e95ac97d..860fea50a2 100644 --- a/map/user_mark_container.hpp +++ b/map/user_mark_container.hpp @@ -21,7 +21,8 @@ enum class UserMarkType SEARCH_MARK, API_MARK, DEBUG_MARK, - BOOKMARK_MARK + BOOKMARK_MARK, + ROUTING_MARK }; class UserMarksController