new compass with animation

This commit is contained in:
ExMix 2014-03-05 16:37:05 +03:00 committed by Alex Zolotarev
parent 3f0c39f347
commit 085671af83
8 changed files with 246 additions and 108 deletions

View file

@ -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;
}

View file

@ -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();

View file

@ -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<PaintEvent> & 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<double, 3, 3> m = math::Shift(
math::Scale(math::Identity<double, 3>(),
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();
}

View file

@ -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<m2::AnyRectD> 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<double, 3, 3> drawM = math::Shift(
math::Rotate(
math::Identity<double, 3>(),
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<AlfaCompassAnim *>(m_animTask.get());
return a->IsHiding();
}
float CompassArrow::GetCurrentAlfa() const
{
if (m_animTask)
{
AlfaCompassAnim * a = static_cast<AlfaCompassAnim *>(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<gl::BaseTexture> 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();
}

View file

@ -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<graphics::DisplayList> m_displayList;
graphics::DisplayList * m_displayList;
shared_ptr<anim::Task> 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<m2::AnyRectD> 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<m2::AnyRectD> const & boundRects() const;
void draw(graphics::OverlayRenderer * r, math::Matrix<double, 3, 3> const & m) const;

View file

@ -784,8 +784,9 @@ void Framework::DrawAdditionalInfo(shared_ptr<PaintEvent> 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());

View file

@ -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)

View file

@ -135,6 +135,7 @@ public:
void drawLog(Drawer * pDrawer);
void enableCompassArrow(bool doEnable);
bool isCompassArrowEnabled() const;
void setCompassArrowAngle(double angle);
shared_ptr<location::State> const & locationState() const;