forked from organicmaps/organicmaps
added CompassArrow GUI element.
This commit is contained in:
parent
378ba050ee
commit
9ca2c102b9
12 changed files with 380 additions and 12 deletions
162
map/compass_arrow.cpp
Normal file
162
map/compass_arrow.cpp
Normal file
|
@ -0,0 +1,162 @@
|
|||
#include "compass_arrow.hpp"
|
||||
#include "framework.hpp"
|
||||
#include "rotate_screen_task.hpp"
|
||||
|
||||
#include "../anim/controller.hpp"
|
||||
|
||||
#include "../gui/controller.hpp"
|
||||
|
||||
#include "../geometry/any_rect2d.hpp"
|
||||
#include "../geometry/transformations.hpp"
|
||||
|
||||
#include "../yg/display_list.hpp"
|
||||
#include "../yg/screen.hpp"
|
||||
#include "../yg/skin.hpp"
|
||||
|
||||
CompassArrow::CompassArrow(Params const & p)
|
||||
: base_t(p),
|
||||
m_boundRects(1)
|
||||
{
|
||||
m_arrowWidth = p.m_arrowWidth;
|
||||
m_arrowHeight = p.m_arrowHeight;
|
||||
m_northColor = p.m_northColor;
|
||||
m_southColor = p.m_southColor;
|
||||
m_framework = p.m_framework;
|
||||
m_angle = 0;
|
||||
}
|
||||
|
||||
void CompassArrow::setAngle(double angle)
|
||||
{
|
||||
m_angle = angle;
|
||||
m_drawM = math::Shift(math::Rotate(math::Identity<double, 3>(), m_angle), pivot() * visualScale());
|
||||
|
||||
setIsDirtyRect(true);
|
||||
}
|
||||
|
||||
vector<m2::AnyRectD> const & CompassArrow::boundRects() const
|
||||
{
|
||||
if (isDirtyRect())
|
||||
{
|
||||
double k = visualScale();
|
||||
|
||||
m2::PointD pv = pivot() * k;
|
||||
double halfW = m_arrowWidth / 2.0 * k;
|
||||
double halfH = m_arrowHeight / 2.0 * k;
|
||||
|
||||
m_boundRects[0] = m2::AnyRectD(pv,
|
||||
-math::pi / 2 + m_angle,
|
||||
m2::RectD(-halfW, -halfH, halfW, halfH));
|
||||
|
||||
setIsDirtyRect(false);
|
||||
}
|
||||
|
||||
return m_boundRects;
|
||||
}
|
||||
|
||||
void CompassArrow::draw(yg::gl::OverlayRenderer * r,
|
||||
math::Matrix<double, 3, 3> const & m) const
|
||||
{
|
||||
if (isVisible())
|
||||
{
|
||||
checkDirtyDrawing();
|
||||
m_displayList->draw(m_drawM * m);
|
||||
}
|
||||
}
|
||||
|
||||
void CompassArrow::cache()
|
||||
{
|
||||
yg::gl::Screen * cacheScreen = m_controller->GetCacheScreen();
|
||||
|
||||
m_displayList.reset();
|
||||
m_displayList.reset(cacheScreen->createDisplayList());
|
||||
|
||||
cacheScreen->beginFrame();
|
||||
cacheScreen->setDisplayList(m_displayList.get());
|
||||
|
||||
double k = visualScale();
|
||||
|
||||
double halfW = m_arrowWidth / 2.0 * k;
|
||||
double halfH = m_arrowHeight / 2.0 * k;
|
||||
|
||||
m2::PointF northPts[3] = {
|
||||
m2::PointF(-halfW, 0),
|
||||
m2::PointF(0, -halfH),
|
||||
m2::PointF(halfW, 0)
|
||||
};
|
||||
|
||||
cacheScreen->drawConvexPolygon(northPts, 3, m_northColor, depth());
|
||||
|
||||
m2::PointF southPts[3] = {
|
||||
m2::PointF(-halfW, 0),
|
||||
m2::PointF(halfW, 0),
|
||||
m2::PointF(0, halfH),
|
||||
};
|
||||
|
||||
cacheScreen->drawConvexPolygon(southPts, 3, m_southColor, 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)
|
||||
};
|
||||
|
||||
yg::PenInfo outlinePenInfo(yg::Color(32, 32, 32, 255), 1, 0, 0, 0);
|
||||
|
||||
cacheScreen->drawPath(outlinePts, sizeof(outlinePts) / sizeof(m2::PointD), 0, cacheScreen->skin()->mapPenInfo(outlinePenInfo), depth());
|
||||
|
||||
m_drawM = math::Shift(math::Rotate(math::Identity<double, 3>(), m_angle), pivot() * k);
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
bool CompassArrow::onTapEnded(m2::PointD const & pt)
|
||||
{
|
||||
shared_ptr<anim::Controller> animController = m_framework->GetRenderPolicy()->GetAnimController();
|
||||
animController->Lock();
|
||||
|
||||
if (m_rotateScreenTask
|
||||
&& !m_rotateScreenTask->IsEnded()
|
||||
&& !m_rotateScreenTask->IsCancelled())
|
||||
m_rotateScreenTask->Cancel();
|
||||
m_rotateScreenTask.reset();
|
||||
|
||||
double startAngle = m_framework->GetNavigator().Screen().GetAngle();
|
||||
double endAngle = 0;
|
||||
|
||||
double period = 2 * math::pi;
|
||||
|
||||
startAngle -= floor(startAngle / period) * period;
|
||||
endAngle -= floor(endAngle / period) * period;
|
||||
|
||||
if (fabs(startAngle - endAngle) > math::pi)
|
||||
startAngle -= 2 * math::pi;
|
||||
|
||||
m_rotateScreenTask.reset(new RotateScreenTask(m_framework,
|
||||
startAngle,
|
||||
endAngle,
|
||||
1));
|
||||
animController->AddTask(m_rotateScreenTask);
|
||||
|
||||
animController->Unlock();
|
||||
|
||||
m_framework->Invalidate();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CompassArrow::hitTest(m2::PointD const & pt) const
|
||||
{
|
||||
return pt.Length(pivot() * visualScale()) < max(m_arrowWidth / 2, m_arrowHeight / 2);
|
||||
}
|
69
map/compass_arrow.hpp
Normal file
69
map/compass_arrow.hpp
Normal file
|
@ -0,0 +1,69 @@
|
|||
#pragma once
|
||||
|
||||
#include "../gui/element.hpp"
|
||||
|
||||
#include "../yg/color.hpp"
|
||||
|
||||
#include "../geometry/any_rect2d.hpp"
|
||||
|
||||
#include "../std/shared_ptr.hpp"
|
||||
|
||||
namespace yg
|
||||
{
|
||||
namespace gl
|
||||
{
|
||||
class DisplayList;
|
||||
}
|
||||
}
|
||||
|
||||
class RotateScreenTask;
|
||||
class Framework;
|
||||
|
||||
/// Compass Arrow, which shows up when the screen is rotated,
|
||||
/// and rotates screen back to straight orientation when beeing pressed
|
||||
class CompassArrow : public gui::Element
|
||||
{
|
||||
private:
|
||||
|
||||
typedef gui::Element base_t;
|
||||
|
||||
unsigned m_arrowWidth;
|
||||
unsigned m_arrowHeight;
|
||||
yg::Color m_northColor;
|
||||
yg::Color m_southColor;
|
||||
double m_angle;
|
||||
|
||||
shared_ptr<yg::gl::DisplayList> m_displayList;
|
||||
shared_ptr<RotateScreenTask> m_rotateScreenTask;
|
||||
|
||||
mutable vector<m2::AnyRectD> m_boundRects;
|
||||
|
||||
math::Matrix<double, 3, 3> m_drawM;
|
||||
|
||||
Framework * m_framework;
|
||||
|
||||
void cache();
|
||||
void purge();
|
||||
|
||||
public:
|
||||
|
||||
struct Params : public base_t::Params
|
||||
{
|
||||
unsigned m_arrowWidth;
|
||||
unsigned m_arrowHeight;
|
||||
yg::Color m_northColor;
|
||||
yg::Color m_southColor;
|
||||
Framework * m_framework;
|
||||
};
|
||||
|
||||
CompassArrow(Params const & p);
|
||||
|
||||
void setAngle(double angle);
|
||||
|
||||
vector<m2::AnyRectD> const & boundRects() const;
|
||||
void draw(yg::gl::OverlayRenderer * r, math::Matrix<double, 3, 3> const & m) const;
|
||||
|
||||
bool onTapEnded(m2::PointD const & pt);
|
||||
|
||||
bool hitTest(m2::PointD const & pt) const;
|
||||
};
|
|
@ -571,6 +571,8 @@ void Framework::DrawAdditionalInfo(shared_ptr<PaintEvent> const & e)
|
|||
m_informationDisplay.setEmptyCountryName(m_renderPolicy->GetCountryName());
|
||||
|
||||
m_informationDisplay.enableCountryStatusDisplay(isEmptyModel);
|
||||
m_informationDisplay.enableCompassArrow(m_navigator.Screen().GetAngle() != 0);
|
||||
m_informationDisplay.setCompassArrowAngle(m_navigator.Screen().GetAngle());
|
||||
|
||||
m_informationDisplay.setScreen(m_navigator.Screen());
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "information_display.hpp"
|
||||
#include "drawer_yg.hpp"
|
||||
#include "country_status_display.hpp"
|
||||
#include "compass_arrow.hpp"
|
||||
#include "framework.hpp"
|
||||
|
||||
#include "../indexer/mercator.hpp"
|
||||
|
@ -37,6 +38,19 @@ InformationDisplay::InformationDisplay(Framework * framework)
|
|||
|
||||
m_countryStatusDisplay.reset(new CountryStatusDisplay(p));
|
||||
|
||||
CompassArrow::Params cap;
|
||||
|
||||
cap.m_position = yg::EPosCenter;
|
||||
cap.m_depth = yg::maxDepth;
|
||||
cap.m_arrowHeight = 60;
|
||||
cap.m_arrowWidth = 20;
|
||||
cap.m_pivot = m2::PointD(10 + cap.m_arrowHeight / 2, 10 + cap.m_arrowHeight / 2);
|
||||
cap.m_northColor = yg::Color(255, 0, 0, 255);
|
||||
cap.m_southColor = yg::Color(255, 255, 255, 255);
|
||||
cap.m_framework = framework;
|
||||
|
||||
m_compassArrow.reset(new CompassArrow(cap));
|
||||
|
||||
location::State::Params lsp;
|
||||
|
||||
lsp.m_position = yg::EPosCenter;
|
||||
|
@ -57,6 +71,7 @@ InformationDisplay::InformationDisplay(Framework * framework)
|
|||
enableMemoryWarning(false);
|
||||
enableBenchmarkInfo(false);
|
||||
enableCountryStatusDisplay(false);
|
||||
enableCompassArrow(false);
|
||||
|
||||
for (int i = 0; i < sizeof(m_DebugPts) / sizeof(m2::PointD); ++i)
|
||||
m_DebugPts[i] = m2::PointD(0, 0);
|
||||
|
@ -68,6 +83,7 @@ void InformationDisplay::setController(gui::Controller *controller)
|
|||
{
|
||||
m_controller = controller;
|
||||
m_controller->AddElement(m_countryStatusDisplay);
|
||||
m_controller->AddElement(m_compassArrow);
|
||||
m_controller->AddElement(m_locationState);
|
||||
}
|
||||
|
||||
|
@ -368,6 +384,16 @@ void InformationDisplay::drawLog(DrawerYG * drawer)
|
|||
}
|
||||
*/
|
||||
|
||||
void InformationDisplay::enableCompassArrow(bool doEnable)
|
||||
{
|
||||
m_compassArrow->setIsVisible(doEnable);
|
||||
}
|
||||
|
||||
void InformationDisplay::setCompassArrowAngle(double angle)
|
||||
{
|
||||
m_compassArrow->setAngle(angle);
|
||||
}
|
||||
|
||||
void InformationDisplay::enableCountryStatusDisplay(bool doEnable)
|
||||
{
|
||||
m_countryStatusDisplay->setIsVisible(doEnable);
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace gui
|
|||
|
||||
class Framework;
|
||||
class CountryStatusDisplay;
|
||||
class CompassArrow;
|
||||
|
||||
/// Class, which displays additional information on the primary layer.
|
||||
/// like rules, coordinates, GPS position and heading
|
||||
|
@ -80,6 +81,7 @@ private:
|
|||
static WindowHandle * s_windowHandle;
|
||||
*/
|
||||
shared_ptr<CountryStatusDisplay> m_countryStatusDisplay;
|
||||
shared_ptr<CompassArrow> m_compassArrow;
|
||||
shared_ptr<location::State> m_locationState;
|
||||
|
||||
public:
|
||||
|
@ -126,6 +128,9 @@ public:
|
|||
void setLogSize(size_t logSize);
|
||||
void drawLog(DrawerYG * pDrawer);
|
||||
|
||||
void enableCompassArrow(bool doEnable);
|
||||
void setCompassArrowAngle(double angle);
|
||||
|
||||
shared_ptr<location::State> const & locationState() const;
|
||||
|
||||
void enableCountryStatusDisplay(bool doEnable);
|
||||
|
|
|
@ -48,7 +48,8 @@ HEADERS += \
|
|||
tile_set.hpp \
|
||||
geourl_process.hpp \
|
||||
country_status_display.hpp \
|
||||
rotate_screen_task.hpp
|
||||
rotate_screen_task.hpp \
|
||||
compass_arrow.hpp
|
||||
|
||||
SOURCES += \
|
||||
feature_vec_model.cpp \
|
||||
|
@ -88,7 +89,8 @@ SOURCES += \
|
|||
geourl_process.cpp \
|
||||
bookmark.cpp \
|
||||
country_status_display.cpp \
|
||||
rotate_screen_task.cpp
|
||||
rotate_screen_task.cpp \
|
||||
compass_arrow.cpp
|
||||
|
||||
!iphone*:!bada*:!android* {
|
||||
HEADERS += qgl_render_context.hpp
|
||||
|
@ -105,3 +107,5 @@ SOURCES += \
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -36,10 +36,55 @@ namespace yg
|
|||
base_t::endFrame();
|
||||
}
|
||||
|
||||
void AreaRenderer::drawTrianglesFan(m2::PointF const * points,
|
||||
size_t pointsCount,
|
||||
uint32_t styleID,
|
||||
double depth)
|
||||
{
|
||||
++m_areasCount;
|
||||
m_trianglesCount += (pointsCount - 2);
|
||||
|
||||
if (!m_drawAreas)
|
||||
return;
|
||||
|
||||
ResourceStyle const * style = skin()->fromID(styleID);
|
||||
|
||||
if (style == 0)
|
||||
{
|
||||
LOG(LINFO, ("drawTrianglesFan: styleID=", styleID, " wasn't found on current skin."));
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT_GREATER_OR_EQUAL(pointsCount, 2, ());
|
||||
|
||||
float texX = style->m_texRect.minX() + 1.0f;
|
||||
float texY = style->m_texRect.minY() + 1.0f;
|
||||
|
||||
shared_ptr<BaseTexture> texture = skin()->getPage(style->m_pipelineID)->texture();
|
||||
|
||||
if (!texture)
|
||||
{
|
||||
LOG(LDEBUG, ("returning as no texture is reserved"));
|
||||
return;
|
||||
}
|
||||
|
||||
texture->mapPixel(texX, texY);
|
||||
|
||||
m2::PointF texCoord(texX, texY);
|
||||
m2::PointF normal(0, 0);
|
||||
|
||||
addTexturedFanStrided(points, sizeof(m2::PointF),
|
||||
&normal, 0,
|
||||
&texCoord, 0,
|
||||
pointsCount,
|
||||
depth,
|
||||
style->m_pipelineID);
|
||||
}
|
||||
|
||||
void AreaRenderer::drawTrianglesList(m2::PointD const * points, size_t pointsCount, uint32_t styleID, double depth)
|
||||
{
|
||||
++m_areasCount;
|
||||
m_trianglesCount += pointsCount;
|
||||
m_trianglesCount += pointsCount / 3;
|
||||
|
||||
if (!m_drawAreas)
|
||||
return;
|
||||
|
|
|
@ -32,6 +32,11 @@ namespace yg
|
|||
uint32_t styleID,
|
||||
double depth);
|
||||
|
||||
void drawTrianglesFan(m2::PointF const * points,
|
||||
size_t pointsCount,
|
||||
uint32_t styleID,
|
||||
double depth);
|
||||
|
||||
void beginFrame();
|
||||
void endFrame();
|
||||
};
|
||||
|
|
|
@ -19,6 +19,7 @@ namespace yg
|
|||
m_isVisible(true),
|
||||
m_isValid(true),
|
||||
m_isDirtyRect(true),
|
||||
m_isDirtyDrawing(true),
|
||||
m_isDirtyRoughRect(true)
|
||||
{}
|
||||
|
||||
|
|
|
@ -82,8 +82,8 @@ namespace yg
|
|||
bool isValid() const;
|
||||
void setIsValid(bool flag);
|
||||
|
||||
bool hitTest(m2::PointD const & pt) const;
|
||||
bool roughHitTest(m2::PointD const & pt) const;
|
||||
virtual bool hitTest(m2::PointD const & pt) const;
|
||||
virtual bool roughHitTest(m2::PointD const & pt) const;
|
||||
|
||||
m2::RectD const & roughBoundRect() const;
|
||||
};
|
||||
|
|
|
@ -17,6 +17,19 @@ namespace yg
|
|||
{
|
||||
}
|
||||
|
||||
void ShapeRenderer::drawConvexPolygon(m2::PointF const * pts, size_t ptsCount, yg::Color const & color, double depth)
|
||||
{
|
||||
uint32_t styleID = skin()->mapColor(color);
|
||||
|
||||
if (styleID == skin()->invalidHandle())
|
||||
{
|
||||
LOG(LINFO, ("cannot map color"));
|
||||
return;
|
||||
}
|
||||
|
||||
drawTrianglesFan(pts, ptsCount, styleID, depth);
|
||||
}
|
||||
|
||||
void ShapeRenderer::drawArc(m2::PointD const & center, double startA, double endA, double r, yg::Color const & c, double depth)
|
||||
{
|
||||
vector<m2::PointD> pts;
|
||||
|
|
|
@ -16,14 +16,50 @@ namespace yg
|
|||
|
||||
ShapeRenderer(base_t::Params const & params);
|
||||
|
||||
static void approximateArc(m2::PointD const & center, double startA, double endA, double r, vector<m2::PointD> & pts);
|
||||
void drawArc(m2::PointD const & center, double startA, double endA, double r, yg::Color const & c, double depth);
|
||||
void drawSector(m2::PointD const & center, double startA, double endA, double r, yg::Color const & c, double depth);
|
||||
void fillSector(m2::PointD const & center, double startA, double endA, double r, yg::Color const & c, double depth);
|
||||
void drawConvexPolygon(m2::PointF const * points,
|
||||
size_t pointsCount,
|
||||
yg::Color const & color,
|
||||
double depth);
|
||||
|
||||
void drawRectangle(m2::AnyRectD const & r, yg::Color const & c, double depth);
|
||||
void drawRectangle(m2::RectD const & r, yg::Color const & c, double depth);
|
||||
void drawRoundedRectangle(m2::RectD const & r, double rad, yg::Color const & c, double depth);
|
||||
static void approximateArc(m2::PointD const & center,
|
||||
double startA,
|
||||
double endA,
|
||||
double r,
|
||||
vector<m2::PointD> & pts);
|
||||
|
||||
void drawArc(m2::PointD const & center,
|
||||
double startA,
|
||||
double endA,
|
||||
double r,
|
||||
yg::Color const & c,
|
||||
double depth);
|
||||
|
||||
void drawSector(m2::PointD const & center,
|
||||
double startA,
|
||||
double endA,
|
||||
double r,
|
||||
yg::Color const & c,
|
||||
double depth);
|
||||
|
||||
void fillSector(m2::PointD const & center,
|
||||
double startA,
|
||||
double endA,
|
||||
double r,
|
||||
yg::Color const & c,
|
||||
double depth);
|
||||
|
||||
void drawRectangle(m2::AnyRectD const & r,
|
||||
yg::Color const & c,
|
||||
double depth);
|
||||
|
||||
void drawRectangle(m2::RectD const & r,
|
||||
yg::Color const & c,
|
||||
double depth);
|
||||
|
||||
void drawRoundedRectangle(m2::RectD const & r,
|
||||
double rad,
|
||||
yg::Color const & c,
|
||||
double depth);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue