diff --git a/graphics/depth_constants.hpp b/graphics/depth_constants.hpp index b11faa8140..5183bd1ddd 100644 --- a/graphics/depth_constants.hpp +++ b/graphics/depth_constants.hpp @@ -18,6 +18,7 @@ namespace graphics static const int balloonBaseDepth = countryStatusDepth - (balloonContentInc + 10); static const int locationDepth = balloonBaseDepth - 10; - static const int poiAndBookmarkDepth = locationDepth - 10; + static const int activePinDepth = locationDepth - 10; + static const int poiAndBookmarkDepth = activePinDepth - 10; static const int tracksDepth = poiAndBookmarkDepth - 10; } diff --git a/gui/display_list_cache.cpp b/gui/display_list_cache.cpp index 80122db64d..8dd854555b 100644 --- a/gui/display_list_cache.cpp +++ b/gui/display_list_cache.cpp @@ -75,9 +75,16 @@ namespace gui m_CacheScreen->beginFrame(); m_CacheScreen->setDisplayList(dl.get()); + graphics::EPosition pos = graphics::EPosAbove; + if (strcmp(name, "search-result") == 0) + { + LOG(LINFO, ("Position checked")); + pos = graphics::EPosCenter; + } + /// @todo do not cache depth in display list. use separate vertex shader and uniform constant /// to specify it while rendering display list. - m_CacheScreen->drawSymbol(m2::PointD(0, 0), name, graphics::EPosAbove, graphics::poiAndBookmarkDepth); + m_CacheScreen->drawSymbol(m2::PointD(0, 0), name, pos, graphics::poiAndBookmarkDepth); m_CacheScreen->setDisplayList(0); m_CacheScreen->endFrame(); diff --git a/map/balloon_manager.cpp b/map/balloon_manager.cpp index 257a96ac99..bdc331d4c5 100644 --- a/map/balloon_manager.cpp +++ b/map/balloon_manager.cpp @@ -184,7 +184,7 @@ graphics::DisplayList * PinClickManager::GetSearchPinDL() cacheScreen->addTexturedStripStrided(coords, sizeof(m2::PointD), &normal, 0, texCoords, sizeof(m2::PointF), - 4, graphics::poiAndBookmarkDepth, res->m_pipelineID); + 4, graphics::activePinDepth, res->m_pipelineID); cacheScreen->setDisplayList(NULL); cacheScreen->endFrame(); @@ -288,10 +288,10 @@ void PinClickManager::DrawPin(const shared_ptr & e) if (glbRect.IsPointInside(m_pinGlobalLocation)) { m2::PointD pxPoint = navigator.GtoP(m_pinGlobalLocation); + pxPoint += m2::PointD(0.0, 4 * m_f.GetVisualScale()); graphics::DisplayList * dl = GetSearchPinDL(); double scale = GetCurrentPinScale(); - LOG(LINFO, ("Pin Scale = ", scale)); math::Matrix m = math::Shift( math::Scale(math::Identity(), scale, scale), @@ -331,25 +331,30 @@ void PinClickManager::OnActivateMyPosition() void PinClickManager::OnActivatePOI(m2::PointD const & globalPoint, search::AddressInfo const & info) { - m_poiListener(globalPoint, info); + if (m_poiListener) + m_poiListener(globalPoint, info); } void PinClickManager::OnActivateAPI(url_scheme::ResultPoint const & apiPoint) { - m_apiListener(apiPoint.GetPoint()); + if (m_apiListener) + m_apiListener(apiPoint.GetPoint()); } void PinClickManager::OnActivateBookmark(BookmarkAndCategory const & bmAndCat) { - m_bookmarkListener(bmAndCat); + if (m_bookmarkListener) + m_bookmarkListener(bmAndCat); } void PinClickManager::OnAdditonalLayer(size_t index) { - m_additionalLayerListener(index); + if (m_additionalLayerListener) + m_additionalLayerListener(index); } void PinClickManager::OnDismiss() { - m_dismissListener(); + if (m_dismissListener) + m_dismissListener(); } diff --git a/map/compass_arrow.cpp b/map/compass_arrow.cpp index 3965a090a4..e06556b892 100644 --- a/map/compass_arrow.cpp +++ b/map/compass_arrow.cpp @@ -3,50 +3,134 @@ #include "framework.hpp" #include "../anim/controller.hpp" +#include "../anim/task.hpp" #include "../gui/controller.hpp" #include "../geometry/any_rect2d.hpp" #include "../geometry/transformations.hpp" +#include "../graphics/display_list.hpp" #include "../graphics/display_list.hpp" #include "../graphics/screen.hpp" #include "../graphics/pen.hpp" +using namespace graphics; + +namespace +{ + class AlfaCompassAnim : public anim::Task + { + typedef anim::Task base_t; + public: + AlfaCompassAnim(double start, double end, double timeInterval, double timeOffset, Framework * f) + : m_start(start) + , m_end(end) + , m_current(start) + , m_timeInterval(timeInterval) + , m_timeOffset(timeOffset) + , m_f(f) + { + } + + bool IsHiding() const + { + return m_start > m_end; + } + + float GetCurrentAlfa() const + { + return m_current; + } + + virtual void OnStart(double ts) + { + m_timeStart = ts; + base_t::OnStart(ts); + m_f->Invalidate(); + } + + virtual void OnStep(double ts) + { + base_t::OnStep(ts); + double elapsed = ts - (m_timeStart + m_timeOffset); + if (elapsed >= 0.0) + { + double t = elapsed / m_timeInterval; + if (t > 1.0) + { + m_current = m_end; + End(); + } + else + m_current = m_start + t * (m_end - m_start); + } + + m_f->Invalidate(); + } + + private: + double m_start; + double m_end; + double m_current; + double m_timeInterval; + double m_timeOffset; + double m_timeStart; + + Framework * m_f; + }; +} + CompassArrow::Params::Params() - : m_arrowWidth(0), - m_arrowHeight(0), - m_framework(0) + : m_framework(0) {} CompassArrow::CompassArrow(Params const & p) : base_t(p), - m_arrowWidth(p.m_arrowWidth), - m_arrowHeight(p.m_arrowHeight), - m_northLeftColor(0xcc, 0x33, 0x00, 0xcc), - m_northRightColor(0xff, 0x33, 0x00, 0xcc), - m_southLeftColor(0xcc, 0xcc, 0xcc, 0xcc), - m_southRightColor(0xff, 0xff, 0xff, 0xcc), m_angle(0), + m_displayList(NULL), m_boundRects(1), m_framework(p.m_framework) { } +void CompassArrow::AnimateShow() +{ + if (!isVisible() && (m_animTask == NULL || IsHidingAnim())) + { + setIsVisible(true); + CreateAnim(0.1, 1.0, 0.2, 0.0, true); + } + + if (isVisible() && (m_animTask == NULL || IsHidingAnim())) + CreateAnim(GetCurrentAlfa(), 1.0, 0.2, 0.0, true); +} + +void CompassArrow::AnimateHide() +{ + if (isVisible() && (m_animTask == NULL || !IsHidingAnim())) + CreateAnim(1.0, 0.0, 0.3, 1.0, false); +} + void CompassArrow::SetAngle(double angle) { m_angle = angle; setIsDirtyRect(true); } +m2::PointD CompassArrow::GetPixelSize() const +{ + Resource const * res = GetCompassResource(); + return m2::PointD(res->m_texRect.SizeX(), res->m_texRect.SizeY()); +} + vector const & CompassArrow::boundRects() const { if (isDirtyRect()) { - double k = visualScale(); - - double halfW = m_arrowWidth / 2.0 * k; - double halfH = m_arrowHeight / 2.0 * k; + Resource const * res = GetCompassResource(); + double halfW = res->m_texRect.SizeX() / 2.0; + double halfH = res->m_texRect.SizeY() / 2.0; m_boundRects[0] = m2::AnyRectD(pivot(), -math::pi / 2 + m_angle, @@ -65,86 +149,114 @@ void CompassArrow::draw(graphics::OverlayRenderer * r, { checkDirtyLayout(); + UniformsHolder holder; + float a = GetCurrentAlfa(); + LOG(LINFO, ("Compass alfa = ", a)); + holder.insertValue(ETransparency, a); + math::Matrix drawM = math::Shift( math::Rotate( math::Identity(), m_angle), pivot()); - r->drawDisplayList(m_displayList.get(), drawM * m); + r->drawDisplayList(m_displayList, drawM * m, &holder); } } +void CompassArrow::AlfaAnimEnded(bool isVisible) +{ + setIsVisible(isVisible); + m_animTask.reset(); +} + +bool CompassArrow::IsHidingAnim() const +{ + ASSERT(m_animTask != NULL, ()); + AlfaCompassAnim * a = static_cast(m_animTask.get()); + return a->IsHiding(); +} + +float CompassArrow::GetCurrentAlfa() const +{ + if (m_animTask) + { + AlfaCompassAnim * a = static_cast(m_animTask.get()); + return a->GetCurrentAlfa(); + } + + return 1.0; +} + +void CompassArrow::CreateAnim(double startAlfa, double endAlfa, double timeInterval, double timeOffset, bool isVisibleAtEnd) +{ + if (m_framework->GetAnimController() == NULL) + return; + + if (m_animTask) + m_animTask->Cancel(); + m_animTask.reset(new AlfaCompassAnim(startAlfa, endAlfa, timeInterval, timeOffset, m_framework)); + m_animTask->AddCallback(anim::Task::EEnded, bind(&CompassArrow::AlfaAnimEnded, this, isVisibleAtEnd)); + m_framework->GetAnimController()->AddTask(m_animTask); +} + +const Resource * CompassArrow::GetCompassResource() const +{ + Screen * cacheScreen = m_controller->GetCacheScreen(); + Icon::Info icon("compass-image"); + Resource const * res = m_controller->GetCacheScreen()->fromID(cacheScreen->findInfo(icon)); + ASSERT(res, ("Commpass-image not founded")); + return res; +} + void CompassArrow::cache() { graphics::Screen * cacheScreen = m_controller->GetCacheScreen(); - m_displayList.reset(); - m_displayList.reset(cacheScreen->createDisplayList()); + purge(); + m_displayList = cacheScreen->createDisplayList(); cacheScreen->beginFrame(); - cacheScreen->setDisplayList(m_displayList.get()); + cacheScreen->setDisplayList(m_displayList); + cacheScreen->applyVarAlfaStates(); - double const k = visualScale(); + Resource const * res = GetCompassResource(); + shared_ptr texture = cacheScreen->pipeline(res->m_pipelineID).texture(); + m2::RectU rect = res->m_texRect; + double halfW = rect.SizeX() / 2.0; + double halfH = rect.SizeY() / 2.0; - double const halfW = m_arrowWidth / 2.0 * k; - double const halfH = m_arrowHeight / 2.0 * k; - - m2::PointF const northLeftPts[3] = { - m2::PointF(-halfW, 0), - m2::PointF(0, -halfH), - m2::PointF(0, 0) - }; - cacheScreen->drawConvexPolygon(northLeftPts, 3, m_northLeftColor, depth()); - - m2::PointF const northRightPts[3] = { - m2::PointF(0, 0), - m2::PointF(0, -halfH), - m2::PointF(halfW, 0) - }; - cacheScreen->drawConvexPolygon(northRightPts, 3, m_northRightColor, depth()); - - m2::PointF const southLeftPts[3] = { - m2::PointF(-halfW, 0), - m2::PointF(0, 0), - m2::PointF(0, halfH), - }; - cacheScreen->drawConvexPolygon(southLeftPts, 3, m_southLeftColor, depth()); - - m2::PointF const southRightPts[3] = { - m2::PointF(0, 0), - m2::PointF(halfW, 0), - m2::PointF(0, halfH), - }; - cacheScreen->drawConvexPolygon(southRightPts, 3, m_southRightColor, depth()); - - m2::PointD outlinePts[6] = { - m2::PointD(-halfW, 0), - m2::PointD(0, -halfH), - m2::PointD(halfW, 0), - m2::PointD(0, halfH), - m2::PointD(-halfW, 0), - m2::PointD(halfW, 0) + m2::PointD coords[] = + { + m2::PointD(-halfW, -halfH), + m2::PointD(-halfW, halfH), + m2::PointD(halfW, -halfH), + m2::PointD(halfW, halfH), }; - graphics::Pen::Info const outlinePenInfo(graphics::Color(0x66, 0x66, 0x66, 0xcc), 1, 0, 0, 0); + m2::PointF normal(0.0, 0.0); + m2::PointF texCoords[] = + { + texture->mapPixel(m2::PointF(rect.minX(), rect.minY())), + texture->mapPixel(m2::PointF(rect.minX(), rect.maxY())), + texture->mapPixel(m2::PointF(rect.maxX(), rect.minY())), + texture->mapPixel(m2::PointF(rect.maxX(), rect.maxY())), + }; + + cacheScreen->addTexturedStripStrided(coords, sizeof(m2::PointD), + &normal, 0, + texCoords, sizeof(m2::PointF), + 4, depth(), res->m_pipelineID); - cacheScreen->drawPath(outlinePts, - sizeof(outlinePts) / sizeof(m2::PointD), - 0, - cacheScreen->mapInfo(outlinePenInfo), - depth()); cacheScreen->setDisplayList(0); cacheScreen->endFrame(); - - // we should not call cacheScreen->completeCommands - // as the gui::Element::cache is called on the GUI thread. } void CompassArrow::purge() { - m_displayList.reset(); + delete m_displayList; + m_displayList = NULL; } bool CompassArrow::onTapEnded(m2::PointD const & pt) @@ -165,11 +277,6 @@ bool CompassArrow::onTapEnded(m2::PointD const & pt) return true; } -unsigned CompassArrow::GetArrowHeight() const -{ - return m_arrowHeight; -} - bool CompassArrow::roughHitTest(m2::PointD const & pt) const { return hitTest(pt); @@ -177,6 +284,7 @@ bool CompassArrow::roughHitTest(m2::PointD const & pt) const bool CompassArrow::hitTest(m2::PointD const & pt) const { - double rad = 1.5 * max(m_arrowWidth / 2, m_arrowHeight / 2); + Resource const * res = GetCompassResource(); + double rad = 1.5 * max(res->m_texRect.SizeX() / 2.0, res->m_texRect.SizeY() / 2.0); return pt.Length(pivot()) < rad * visualScale(); } diff --git a/map/compass_arrow.hpp b/map/compass_arrow.hpp index d92a166922..b375bfc3bc 100644 --- a/map/compass_arrow.hpp +++ b/map/compass_arrow.hpp @@ -1,13 +1,19 @@ #pragma once #include "../gui/element.hpp" - -#include "../graphics/color.hpp" -#include "../graphics/display_list.hpp" - #include "../geometry/any_rect2d.hpp" +#include "../std/shared_ptr.hpp" -#include "../std/scoped_ptr.hpp" +namespace anim +{ + class Task; +} + +namespace graphics +{ + class DisplayList; + struct Resource; +} class Framework; @@ -18,20 +24,21 @@ class CompassArrow : public gui::Element private: typedef gui::Element base_t; - - unsigned m_arrowWidth; - unsigned m_arrowHeight; - graphics::Color const m_northLeftColor; - graphics::Color const m_northRightColor; - graphics::Color const m_southLeftColor; - graphics::Color const m_southRightColor; double m_angle; - scoped_ptr m_displayList; + graphics::DisplayList * m_displayList; + + shared_ptr m_animTask; + + void AlfaAnimEnded(bool isVisible); + bool IsHidingAnim() const; + float GetCurrentAlfa() const; + void CreateAnim(double startAlfa, double endAlfa, double timeInterval, double timeOffset, bool isVisibleAtEnd); mutable vector m_boundRects; Framework * m_framework; + graphics::Resource const * GetCompassResource() const; void cache(); void purge(); @@ -40,17 +47,17 @@ public: struct Params : public base_t::Params { - unsigned m_arrowWidth; - unsigned m_arrowHeight; Framework * m_framework; Params(); }; CompassArrow(Params const & p); - void SetAngle(double angle); + void AnimateShow(); + void AnimateHide(); - unsigned GetArrowHeight() const; + void SetAngle(double angle); + m2::PointD GetPixelSize() const; vector const & boundRects() const; void draw(graphics::OverlayRenderer * r, math::Matrix const & m) const; diff --git a/map/framework.cpp b/map/framework.cpp index 22a63bee9d..8a7f600dec 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -784,8 +784,9 @@ void Framework::DrawAdditionalInfo(shared_ptr const & e) m_informationDisplay.enableCountryStatusDisplay(isEmptyModel); bool isCompassEnabled = ang::AngleIn2PI(m_navigator.Screen().GetAngle()) > my::DegToRad(3.0); - m_informationDisplay.enableCompassArrow(isCompassEnabled); -// m_informationDisplay.enableCompassArrow(!my::AlmostEqual(ang::AngleIn2PI(m_navigator.Screen().GetAngle()), 0.0)); + m_informationDisplay.enableCompassArrow(isCompassEnabled || + (m_informationDisplay.isCompassArrowEnabled() && m_navigator.InAction())); + m_informationDisplay.setCompassArrowAngle(m_navigator.Screen().GetAngle()); m_informationDisplay.setScreen(m_navigator.Screen()); diff --git a/map/information_display.cpp b/map/information_display.cpp index 950aa98246..3ef44fd125 100644 --- a/map/information_display.cpp +++ b/map/information_display.cpp @@ -30,6 +30,8 @@ namespace { static int const FONT_SIZE = 10; + static int const COMPASS_W_OFFSET = 13; + static int const COMPASS_H_OFFSET = 71; } InformationDisplay::InformationDisplay(Framework * fw) @@ -50,7 +52,7 @@ InformationDisplay::InformationDisplay(Framework * fw) enableMemoryWarning(false); enableBenchmarkInfo(false); enableCountryStatusDisplay(false); - enableCompassArrow(false); + m_compassArrow->setIsVisible(false); for (int i = 0; i < sizeof(m_DebugPts) / sizeof(m2::PointD); ++i) m_DebugPts[i] = m2::PointD(0, 0); @@ -87,8 +89,6 @@ void InformationDisplay::InitCompassArrow(Framework * fw) p.m_position = graphics::EPosCenter; p.m_depth = graphics::compassDepth; - p.m_arrowHeight = 50; - p.m_arrowWidth = 16; p.m_pivot = m2::PointD(0, 0); p.m_framework = fw; @@ -141,10 +141,10 @@ void InformationDisplay::setScreen(ScreenBase const & screen) } double k = m_controller->GetVisualScale(); - unsigned arrowHeight = m_compassArrow->GetArrowHeight(); + m2::PointD size = m_compassArrow->GetPixelSize(); - m_compassArrow->setPivot(m2::PointD(10 + arrowHeight / 2, - 10 + arrowHeight / 2) * k); + m_compassArrow->setPivot(m2::PointD(COMPASS_W_OFFSET * k + size.x / 2.0, + COMPASS_H_OFFSET * k + size.y / 2.0)); } void InformationDisplay::setBottomShift(double bottomShift) @@ -162,7 +162,7 @@ void InformationDisplay::setDisplayRect(m2::RectI const & rect) m_ruler->setPivot(pt); m2::PointD debugLabelPivot(m_displayRect.minX() + 10, - m_displayRect.minY() + 50 + 5 * m_visualScale); + m_displayRect.minY() + 30 + 5 * m_visualScale); m_debugLabel->setPivot(debugLabelPivot); } @@ -347,7 +347,15 @@ void InformationDisplay::drawLog(Drawer * drawer) void InformationDisplay::enableCompassArrow(bool doEnable) { - m_compassArrow->setIsVisible(doEnable); + if (doEnable) + m_compassArrow->AnimateShow(); + else + m_compassArrow->AnimateHide(); +} + +bool InformationDisplay::isCompassArrowEnabled() const +{ + return m_compassArrow->isVisible(); } void InformationDisplay::setCompassArrowAngle(double angle) diff --git a/map/information_display.hpp b/map/information_display.hpp index e274e77491..af7c833734 100644 --- a/map/information_display.hpp +++ b/map/information_display.hpp @@ -135,6 +135,7 @@ public: void drawLog(Drawer * pDrawer); void enableCompassArrow(bool doEnable); + bool isCompassArrowEnabled() const; void setCompassArrowAngle(double angle); shared_ptr const & locationState() const;