moved location handling from Framework into location::State and added "follow compass" mode.

This commit is contained in:
rachytski 2012-08-16 12:49:37 +03:00 committed by Alex Zolotarev
parent 96c0658a68
commit a164270834
15 changed files with 451 additions and 209 deletions

View file

@ -35,9 +35,8 @@ size_t BasicTilingRenderPolicy::CalculateTileSize(size_t screenWidth, size_t scr
}
BasicTilingRenderPolicy::BasicTilingRenderPolicy(Params const & p,
bool doSupportRotation,
bool doUseQueuedRenderer)
: RenderPolicy(p, doSupportRotation, GetPlatform().CpuCores()),
: RenderPolicy(p, true, GetPlatform().CpuCores()),
m_DrawScale(0),
m_IsEmptyModel(false),
m_DoRecreateCoverage(false),
@ -73,7 +72,7 @@ void BasicTilingRenderPolicy::DrawFrame(shared_ptr<PaintEvent> const & e, Screen
if (doForceUpdate)
m_CoverageGenerator->InvalidateTiles(GetInvalidRect(), scales::GetUpperWorldScale() + 1);
if (!m_IsNavigating)
if (!m_IsNavigating && (!IsAnimating()))
m_CoverageGenerator->AddCoverScreenTask(s,
m_DoRecreateCoverage || (doForceUpdate && doIntersectInvalidRect));

View file

@ -47,7 +47,6 @@ protected:
public:
BasicTilingRenderPolicy(Params const & p,
bool doSupportRotation,
bool doUseQueuedRenderer);
void BeginFrame(shared_ptr<PaintEvent> const & ev, ScreenBase const & s);

View file

@ -15,6 +15,8 @@
#include "../indexer/feature.hpp"
#include "../indexer/scales.hpp"
#include "../anim/controller.hpp"
#include "../gui/controller.hpp"
#include "../platform/settings.hpp"
@ -63,89 +65,25 @@ void Framework::RemoveMap(string const & datFile)
void Framework::SkipLocationCentering()
{
m_centeringMode = ESkipLocationCentering;
m_locationState.SkipLocationCentering();
}
void Framework::OnLocationStatusChanged(location::TLocationStatus newStatus)
{
switch (newStatus)
{
case location::EStarted:
case location::EFirstEvent:
if (m_centeringMode != ESkipLocationCentering)
{
// set centering mode for the first location
m_centeringMode = ECenterAndScale;
}
break;
default:
m_centeringMode = EDoNothing;
m_locationState.TurnOff();
Invalidate();
}
m_locationState.OnLocationStatusChanged(newStatus);
}
void Framework::OnGpsUpdate(location::GpsInfo const & info)
{
double lon = info.m_longitude;
double lat = info.m_latitude;
#ifdef FIXED_LOCATION
m_fixedPos.GetLon(lon);
m_fixedPos.GetLat(lat);
location::GpsInfo rInfo(info);
m_fixedPos.GetLon(rInfo.m_longitude);
m_fixedPos.GetLat(rInfo.m_latitude);
#else
location::GpsInfo const & rInfo = info;
#endif
m2::RectD rect = MercatorBounds::MetresToXY(lon, lat, info.m_horizontalAccuracy);
m2::PointD const center = rect.Center();
m_locationState.UpdateGps(rect);
switch (m_centeringMode)
{
case ECenterAndScale:
{
int const rectScale = scales::GetScaleLevel(rect);
int setScale = -1;
// correct rect scale if country isn't downloaded
int const upperScale = scales::GetUpperWorldScale();
if (rectScale > upperScale && !IsCountryLoaded(center))
{
setScale = upperScale;
}
else
{
// correct rect scale for best user experience
int const bestScale = scales::GetUpperScale() - 1;
if (rectScale > bestScale)
setScale = bestScale;
}
if (setScale != -1)
rect = scales::GetRectForLevel(setScale, center, 1.0);
double a = m_navigator.Screen().GetAngle();
double dx = rect.SizeX();
double dy = rect.SizeY();
ShowRectFixed(m2::AnyRectD(rect.Center(), a, m2::RectD(-dx/2, -dy/2, dx/2, dy/2)));
m_centeringMode = ECenterOnly;
break;
}
case ECenterOnly:
SetViewportCenter(center);
break;
case ESkipLocationCentering:
m_centeringMode = EDoNothing;
break;
case EDoNothing:
break;
}
m_locationState.OnGpsUpdate(rInfo);
}
void Framework::OnCompassUpdate(location::CompassInfo const & info)
@ -157,8 +95,7 @@ void Framework::OnCompassUpdate(location::CompassInfo const & info)
location::CompassInfo const & rInfo = info;
#endif
m_locationState.UpdateCompass(rInfo);
Invalidate();
m_locationState.OnCompassUpdate(rInfo);
}
InformationDisplay & Framework::GetInformationDisplay()
@ -193,7 +130,7 @@ Framework::Framework()
#endif
m_width(0),
m_height(0),
m_centeringMode(EDoNothing),
m_locationState(this),
m_informationDisplay(&m_storage),
m_lowestMapVersion(-1),
m_benchmarkEngine(0)
@ -212,6 +149,8 @@ Framework::Framework()
m_stringsBundle.SetDefaultString("try_again", "Try Again");
m_stringsBundle.SetDefaultString("not_enough_free_space_on_sdcard", "Not enough space\nfor downloading");
m_animController.reset(new anim::Controller());
// Init GUI controller.
m_guiController.reset(new gui::Controller());
m_guiController->SetStringsBundle(&m_stringsBundle);
@ -646,7 +585,7 @@ void Framework::DrawAdditionalInfo(shared_ptr<PaintEvent> const & e)
m_informationDisplay.doDraw(pDrawer);
m_locationState.DrawMyPosition(*pDrawer, m_navigator);
m_locationState.Draw(*pDrawer);
if (m_drawPlacemark)
m_informationDisplay.drawPlacemark(pDrawer, "placemark", m_navigator.GtoP(m_placemark));
@ -845,6 +784,8 @@ void Framework::StartDrag(DragEvent const & e)
if (m_renderPolicy)
m_renderPolicy->StartDrag();
m_dragCompassProcessMode = m_locationState.CompassProcessMode();
}
void Framework::DoDrag(DragEvent const & e)
@ -856,6 +797,9 @@ void Framework::DoDrag(DragEvent const & e)
#endif
m_navigator.DoDrag(pt, ElapsedSeconds());
m_locationState.SetCompassProcessMode(location::ECompassDoNothing);
if (m_renderPolicy)
m_renderPolicy->DoDrag();
}
@ -870,12 +814,17 @@ void Framework::StopDrag(DragEvent const & e)
m_informationDisplay.setDebugPoint(0, pt);
#endif
if (m_centeringMode != EDoNothing)
if (m_locationState.LocationProcessMode() != location::ELocationDoNothing)
{
// reset GPS centering mode if we have dragged far from current location
ScreenBase const & s = m_navigator.Screen();
if (GetPixelCenter().Length(s.GtoP(m_locationState.Position())) >= s.GetMinPixelRectSize() / 2.0)
m_centeringMode = EDoNothing;
{
m_locationState.SetLocationProcessMode(location::ELocationDoNothing);
m_locationState.SetCompassProcessMode(location::ECompassDoNothing);
}
else
m_locationState.SetCompassProcessMode(m_dragCompassProcessMode);
}
if (m_renderPolicy)
@ -921,7 +870,7 @@ void Framework::Move(double azDir, double factor)
//@{
void Framework::ScaleToPoint(ScaleToPointEvent const & e)
{
m2::PointD const pt = (m_centeringMode == EDoNothing) ?
m2::PointD const pt = (m_locationState.LocationProcessMode() == location::ELocationDoNothing) ?
m_navigator.ShiftPoint(e.Pt()) : GetPixelCenter();
m_navigator.ScaleToPoint(pt, e.ScaleFactor(), ElapsedSeconds());
@ -946,7 +895,7 @@ void Framework::CalcScalePoints(ScaleEvent const & e, m2::PointD & pt1, m2::Poin
pt1 = m_navigator.ShiftPoint(e.Pt1());
pt2 = m_navigator.ShiftPoint(e.Pt2());
if ((m_locationState & location::State::EGps) && (m_centeringMode == ECenterOnly))
if (m_locationState.HasPosition() && (m_locationState.LocationProcessMode() == location::ELocationCenterOnly))
{
m2::PointD const ptC = (pt1 + pt2) / 2;
m2::PointD const ptDiff = GetPixelCenter() - ptC;
@ -978,6 +927,12 @@ void Framework::DoScale(ScaleEvent const & e)
m_navigator.DoScale(pt1, pt2, ElapsedSeconds());
if (m_renderPolicy)
m_renderPolicy->DoScale();
if (m_navigator.IsRotatingDuringScale() && (m_locationState.CompassProcessMode() == location::ECompassFollow))
{
m_locationState.StopAnimation();
m_locationState.SetCompassProcessMode(location::ECompassDoNothing);
}
}
void Framework::StopScale(ScaleEvent const & e)
@ -1031,23 +986,12 @@ void Framework::PrepareSearch(bool hasPt, double lat, double lon)
bool Framework::Search(search::SearchParams const & params)
{
#ifdef FIXED_LOCATION
search::SearchParams rParams(params);
if (params.m_validPos)
{
m_fixedPos.GetLat(rParams.m_lat);
m_fixedPos.GetLon(rParams.m_lon);
}
#else
search::SearchParams const & rParams = params;
#endif
return GetSearchEngine()->Search(rParams, GetCurrentViewport());
return GetSearchEngine()->Search(params, GetCurrentViewport());
}
bool Framework::GetCurrentPosition(double & lat, double & lon) const
{
if (m_locationState.IsValidPosition())
if (m_locationState.HasPosition())
{
m2::PointD const pos = m_locationState.Position();
lat = MercatorBounds::YToLat(pos.y);
@ -1081,12 +1025,6 @@ void Framework::GetDistanceAndAzimut(search::Result const & res,
double lat, double lon, double north,
string & distance, double & azimut)
{
#ifdef FIXED_LOCATION
m_fixedPos.GetLat(lat);
m_fixedPos.GetLon(lon);
m_fixedPos.GetNorth(north);
#endif
m2::PointD const center = res.GetFeatureCenter();
double const d = ms::DistanceOnEarth(lat, lon,
@ -1152,22 +1090,6 @@ void Framework::SetRenderPolicy(RenderPolicy * renderPolicy)
if (m_benchmarkEngine)
m_benchmarkEngine->Start();
/*
if (m_hasPendingInvalidate)
{
m_renderPolicy->SetForceUpdate(m_doForceUpdate);
m_renderPolicy->SetInvalidRect(m_invalidRect);
m_renderPolicy->GetWindowHandle()->invalidate();
m_hasPendingInvalidate = false;
}
if (m_hasPendingShowRectFixed)
{
ShowRectFixed(m_pendingFixedRect);
m_hasPendingShowRectFixed = false;
}
*/
}
}
@ -1221,6 +1143,11 @@ gui::Controller * Framework::GetGuiController() const
return m_guiController.get();
}
anim::Controller * Framework::GetAnimController() const
{
return m_animController.get();
}
bool Framework::SetViewportByURL(string const & url)
{
using namespace url_scheme;
@ -1272,3 +1199,8 @@ void Framework::SaveFacebookDialogResult(int result)
break;
}
}
Navigator & Framework::GetNavigator()
{
return m_navigator;
}

View file

@ -37,6 +37,7 @@
namespace search { class Result; }
namespace gui { class Controller; }
namespace anim { class Controller; }
class CountryStatusDisplay;
class BenchmarkEngine;
@ -95,21 +96,14 @@ protected:
int m_width;
int m_height;
enum TGpsCenteringMode
{
EDoNothing,
ECenterAndScale,
ECenterOnly,
ESkipLocationCentering
};
TGpsCenteringMode m_centeringMode;
location::State m_locationState;
location::ECompassProcessMode m_dragCompassProcessMode;
//mutable threads::Mutex m_modelSyn;
storage::Storage m_storage;
scoped_ptr<gui::Controller> m_guiController;
scoped_ptr<anim::Controller> m_animController;
InformationDisplay m_informationDisplay;
/// This function is called by m_storage to notify that country downloading is finished.
@ -352,6 +346,8 @@ public:
//@}
gui::Controller * GetGuiController() const;
anim::Controller * GetAnimController() const;
Navigator & GetNavigator();
/// Set the localized strings bundle
inline void AddString(string const & name, string const & value)
@ -371,6 +367,7 @@ public:
void SaveFacebookDialogResult(int result);
/// @}
private:
/// Checks, whether the country which contains
/// the specified point is loaded
bool IsCountryLoaded(m2::PointD const & pt) const;
};

View file

@ -1,82 +1,248 @@
#include "location_state.hpp"
#include "drawer_yg.hpp"
#include "navigator.hpp"
#include "framework.hpp"
#include "rotate_screen_task.hpp"
#include "../anim/controller.hpp"
#include "../platform/location.hpp"
#include "../platform/platform.hpp"
#include "../indexer/mercator.hpp"
#include "../geometry/rect2d.hpp"
#include "../indexer/mercator.hpp"
namespace location
{
State::State() : m_flags(ENone)
State::State(Framework * fw)
: m_hasPosition(false),
m_hasCompass(false),
m_locationProcessMode(ELocationDoNothing),
m_compassProcessMode(ECompassDoNothing),
m_fw(fw)
{
}
void State::UpdateGps(m2::RectD const & rect)
bool State::HasPosition() const
{
m_flags |= EGps;
m_positionMercator = rect.Center();
//m_errorRadiusMercator = sqrt(my::sq(rect.SizeX()) + my::sq(rect.SizeY())) / 2;
m_errorRadiusMercator = rect.SizeX() / 2.0;
return m_hasPosition;
}
void State::UpdateCompass(CompassInfo const & info)
bool State::HasCompass() const
{
m_flags |= ECompass;
return m_hasCompass;
}
void State::TurnOff()
{
m_hasPosition = false;
m_hasCompass = false;
}
void State::SkipLocationCentering()
{
m_locationProcessMode = ELocationSkipCentering;
}
ELocationProcessMode State::LocationProcessMode() const
{
return m_locationProcessMode;
}
void State::SetLocationProcessMode(ELocationProcessMode mode)
{
m_locationProcessMode = mode;
}
ECompassProcessMode State::CompassProcessMode() const
{
return m_compassProcessMode;
}
void State::SetCompassProcessMode(ECompassProcessMode mode)
{
m_compassProcessMode = mode;
}
void State::OnLocationStatusChanged(location::TLocationStatus newStatus)
{
switch (newStatus)
{
case location::EStarted:
if (m_locationProcessMode != ELocationSkipCentering)
m_locationProcessMode = ELocationCenterAndScale;
break;
case location::EFirstEvent:
if (m_locationProcessMode != ELocationSkipCentering)
{
// set centering mode for the first location
m_locationProcessMode = ELocationCenterAndScale;
m_compassProcessMode = ECompassFollow;
}
break;
default:
m_locationProcessMode = ELocationDoNothing;
TurnOff();
}
m_fw->Invalidate();
}
void State::OnGpsUpdate(location::GpsInfo const & info)
{
double lon = info.m_longitude;
double lat = info.m_latitude;
m2::RectD rect = MercatorBounds::MetresToXY(lon, lat, info.m_horizontalAccuracy);
m2::PointD const center = rect.Center();
m_hasPosition = true;
m_position = center;
m_errorRadius = rect.SizeX() / 2;
switch (m_locationProcessMode)
{
case ELocationCenterAndScale:
{
int const rectScale = scales::GetScaleLevel(rect);
int setScale = -1;
// correct rect scale if country isn't downloaded
int const upperScale = scales::GetUpperWorldScale();
if (rectScale > upperScale && !m_fw->IsCountryLoaded(center))
setScale = upperScale;
else
{
// correct rect scale for best user experience
int const bestScale = scales::GetUpperScale() - 1;
if (rectScale > bestScale)
setScale = bestScale;
}
if (setScale != -1)
rect = scales::GetRectForLevel(setScale, center, 1.0);
double a = m_fw->GetNavigator().Screen().GetAngle();
double dx = rect.SizeX();
double dy = rect.SizeY();
m_fw->ShowRectFixed(m2::AnyRectD(rect.Center(), a, m2::RectD(-dx/2, -dy/2, dx/2, dy/2)));
m_locationProcessMode = ELocationCenterOnly;
break;
}
case ELocationCenterOnly:
m_fw->SetViewportCenter(center);
break;
case ELocationSkipCentering:
m_locationProcessMode = ELocationDoNothing;
break;
case ELocationDoNothing:
break;
}
m_fw->Invalidate();
}
void State::OnCompassUpdate(location::CompassInfo const & info)
{
m_hasCompass = true;
m_headingRad = ((info.m_trueHeading >= 0.0) ? info.m_trueHeading : info.m_magneticHeading);
// 0 angle is for North ("up"), but in our coordinates it's to the right.
m_headingRad = m_headingRad - math::pi / 2.0;
// Avoid situations when offset between magnetic north and true north is too small
static double const MIN_SECTOR_RAD = math::pi / 18.0;
m_headingHalfSectorRad = (info.m_accuracy < MIN_SECTOR_RAD ? MIN_SECTOR_RAD : info.m_accuracy);
m_headingHalfErrorRad = (info.m_accuracy < MIN_SECTOR_RAD ? MIN_SECTOR_RAD : info.m_accuracy);
if (m_compassProcessMode == ECompassFollow)
FollowCompass();
m_fw->Invalidate();
}
void State::DrawMyPosition(DrawerYG & drawer, Navigator const & nav)
void State::Draw(DrawerYG & drawer)
{
if ((m_flags & State::EGps) || (m_flags & State::ECompass))
if (m_hasPosition)
{
m2::PointD const pxPosition = nav.GtoP(Position());
double const pxErrorRadius = pxPosition.Length(nav.GtoP(Position() + m2::PointD(m_errorRadiusMercator, 0.0)));
m2::PointD const pxPosition = m_fw->GetNavigator().GtoP(Position());
double const pxErrorRadius = pxPosition.Length(m_fw->GetNavigator().GtoP(Position() + m2::PointD(m_errorRadius, 0.0)));
if (m_flags & State::EGps)
// my position symbol
drawer.drawSymbol(pxPosition, "current-position", yg::EPosCenter, yg::maxDepth);
// my position circle
drawer.screen()->fillSector(pxPosition, 0, 2.0 * math::pi, pxErrorRadius,
yg::Color(0, 0, 255, 32),
yg::maxDepth - 3);
// display compass only if position is available
double orientationRadius = max(pxErrorRadius, 30.0 * drawer.VisualScale());
double screenAngle = m_fw->GetNavigator().Screen().GetAngle();
// 0 angle is for North ("up"), but in our coordinates it's to the right.
double headingRad = m_headingRad - math::pi / 2.0;
if (m_hasCompass)
{
// my position symbol
drawer.drawSymbol(pxPosition, "current-position", yg::EPosCenter, yg::maxDepth);
drawer.screen()->drawSector(pxPosition,
screenAngle + headingRad - m_headingHalfErrorRad,
screenAngle + headingRad + m_headingHalfErrorRad,
orientationRadius,
yg::Color(255, 255, 255, 192),
yg::maxDepth);
// my position circle
drawer.screen()->fillSector(pxPosition, 0, 2.0 * math::pi, pxErrorRadius,
yg::Color(0, 0, 255, 32),
yg::maxDepth - 3);
// display compass only if position is available
double orientationRadius = max(pxErrorRadius, 30.0 * drawer.VisualScale());
double screenAngle = nav.Screen().GetAngle();
if (m_flags & State::ECompass)
{
drawer.screen()->drawSector(pxPosition,
screenAngle + m_headingRad - m_headingHalfSectorRad,
screenAngle + m_headingRad + m_headingHalfSectorRad,
orientationRadius,
yg::Color(255, 255, 255, 192),
yg::maxDepth);
drawer.screen()->fillSector(pxPosition,
screenAngle + m_headingRad - m_headingHalfSectorRad,
screenAngle + m_headingRad + m_headingHalfSectorRad,
orientationRadius,
yg::Color(255, 255, 255, 96),
yg::maxDepth - 1);
}
drawer.screen()->fillSector(pxPosition,
screenAngle + headingRad - m_headingHalfErrorRad,
screenAngle + headingRad + m_headingHalfErrorRad,
orientationRadius,
yg::Color(255, 255, 255, 96),
yg::maxDepth - 1);
}
}
}
void State::FollowCompass()
{
if (!m_fw->GetNavigator().DoSupportRotation())
return;
StopAnimation();
double startAngle = m_fw->GetNavigator().Screen().GetAngle();
double endAngle = -m_headingRad;
double period = 2 * math::pi;
startAngle -= floor(startAngle / period) * period;
endAngle -= floor(endAngle / period) * period;
if (fabs(startAngle - endAngle) > 20.0 / 180.0 * math::pi)
{
if (fabs(startAngle - endAngle) > math::pi)
startAngle -= 2 * math::pi;
m_rotateScreenTask.reset(new RotateScreenTask(m_fw,
startAngle,
endAngle,
1));
m_fw->GetAnimController()->AddTask(m_rotateScreenTask);
}
}
void State::StopAnimation()
{
if (m_rotateScreenTask && !m_rotateScreenTask->IsFinished())
m_rotateScreenTask->Finish();
m_rotateScreenTask.reset();
}
}

View file

@ -1,52 +1,85 @@
#pragma once
#include "../platform/location.hpp"
#include "../geometry/point2d.hpp"
#include "../geometry/rect2d.hpp"
#include "../std/shared_ptr.hpp"
class DrawerYG;
class Navigator;
class Framework;
class RotateScreenTask;
namespace location
{
class GpsInfo;
class CompassInfo;
enum ELocationProcessMode
{
ELocationDoNothing,
ELocationCenterAndScale,
ELocationCenterOnly,
ELocationSkipCentering
};
enum ECompassProcessMode
{
ECompassDoNothing,
ECompassFollow
};
// Class, that handles position and compass updates,
// centers, scales and rotates map according to this updates
// and draws location and compass marks.
class State
{
double m_errorRadiusMercator;
m2::PointD m_positionMercator;
private:
double m_errorRadius; //< error radius in mercator
m2::PointD m_position; //< position in mercator
double m_headingRad;
/// Angle to the left and to the right from the North
double m_headingHalfSectorRad;
double m_headingRad; //< direction in radians
double m_headingHalfErrorRad; //< direction error in radians
int m_flags; ///< stores flags from SymbolType
bool m_hasPosition;
bool m_hasCompass;
ELocationProcessMode m_locationProcessMode;
ECompassProcessMode m_compassProcessMode;
shared_ptr<RotateScreenTask> m_rotateScreenTask;
Framework * m_fw;
void FollowCompass();
public:
enum SymbolType
{
ENone = 0x0,
EGps = 0x1,
ECompass = 0x2
};
State();
State(Framework * framework);
/// @return GPS center point in mercator
m2::PointD Position() const { return m_positionMercator; }
m2::PointD const & Position() const { return m_position; }
inline bool IsValidPosition() const { return ((m_flags & EGps) != 0); }
inline void TurnOff() { m_flags = ENone; }
bool HasPosition() const;
bool HasCompass() const;
/// @param[in] rect Bound rect for circle with position center and error radius.
void UpdateGps(m2::RectD const & rect);
void UpdateCompass(CompassInfo const & info);
ELocationProcessMode LocationProcessMode() const;
void SetLocationProcessMode(ELocationProcessMode mode);
void DrawMyPosition(DrawerYG & drawer, Navigator const & nav);
ECompassProcessMode CompassProcessMode() const;
void SetCompassProcessMode(ECompassProcessMode mode);
operator int() const
{
return m_flags;
}
void TurnOff();
void Draw(DrawerYG & drawer);
void StopAnimation();
/// @name GPS location updates routine.
//@{
void SkipLocationCentering();
void OnLocationStatusChanged(location::TLocationStatus newStatus);
void OnGpsUpdate(location::GpsInfo const & info);
void OnCompassUpdate(location::CompassInfo const & info);
//@}
};
}

View file

@ -550,6 +550,11 @@ void Navigator::StopScale(m2::PointD const & pt1, m2::PointD const & pt2, double
// m_StartScreen = m_Screen;
}
bool Navigator::IsRotatingDuringScale() const
{
return m_IsRotatingDuringScale;
}
void Navigator::Scale(double scale)
{
ScaleToPoint(m_Screen.PixelRect().Center(), scale, 0);
@ -577,3 +582,7 @@ void Navigator::SetSupportRotation(bool flag)
m_DoSupportRotation = flag;
}
bool Navigator::DoSupportRotation() const
{
return m_DoSupportRotation;
}

View file

@ -41,6 +41,7 @@ public:
void DoScale(m2::PointD const & org, m2::PointD const & p1, m2::PointD const & p2);
void DoScale(m2::PointD const & pt1, m2::PointD const & pt2, double timeInSec);
void StopScale(m2::PointD const & pt1, m2::PointD const & pt2, double timeInSec);
bool IsRotatingDuringScale() const;
void ScaleToPoint(m2::PointD const & pt, double factor, double timeInSec);
@ -54,8 +55,10 @@ public:
bool InAction() const;
/// enabling/disabling screen rotation handling
void SetSupportRotation(bool flag);
/// checking, whether the navigator supports rotation
bool DoSupportRotation() const;
/// Our surface is a square which is bigger than visible screen area on the device,
/// so we should take it into an account
m2::PointD ShiftPoint(m2::PointD const & pt) const;

View file

@ -36,7 +36,8 @@ RenderPolicy::RenderPolicy(Params const & p,
m_doSupportRotation(doSupportRotation),
m_doForceUpdate(false),
m_visualScale(p.m_visualScale),
m_skinName(p.m_skinName)
m_skinName(p.m_skinName),
m_isAnimating(false)
{
LOG(LDEBUG, ("each BaseRule will hold up to", idCacheSize, "cached values"));
drule::rules().ResizeCaches(idCacheSize);
@ -208,6 +209,16 @@ void RenderPolicy::JoinBenchmarkFence(int fenceID)
{
}
void RenderPolicy::SetIsAnimating(bool flag)
{
m_isAnimating = flag;
}
bool RenderPolicy::IsAnimating() const
{
return m_isAnimating;
}
RenderPolicy * CreateRenderPolicy(RenderPolicy::Params const & params)
{
#ifdef OMIM_OS_ANDROID

View file

@ -54,6 +54,7 @@ protected:
m2::AnyRectD m_invalidRect;
double m_visualScale;
string m_skinName;
bool m_isAnimating;
public:
@ -113,6 +114,9 @@ public:
bool DoForceUpdate() const;
void SetForceUpdate(bool flag);
void SetIsAnimating(bool flag);
bool IsAnimating() const;
void SetInvalidRect(m2::AnyRectD const & glbRect);
m2::AnyRectD const & GetInvalidRect() const;

View file

@ -0,0 +1,57 @@
#include "rotate_screen_task.hpp"
#include "framework.hpp"
RotateScreenTask::RotateScreenTask(Framework * framework,
double startAngle,
double endAngle,
double interval)
: m_framework(framework),
m_startAngle(startAngle),
m_endAngle(endAngle),
m_interval(interval)
{
m_startTime = 0;
m_isFinished = false;
}
void RotateScreenTask::OnStart(double ts)
{
m_startTime = ts;
m_curAngle = m_startAngle;
m_framework->GetRenderPolicy()->SetIsAnimating(true);
}
void RotateScreenTask::OnStep(double ts)
{
if (ts - m_startTime > m_interval)
{
m_isFinished = true;
return;
}
if (IsFinished())
return;
double elapsedSec = ts - m_startTime;
double angle = m_startAngle + (m_endAngle - m_startAngle) * elapsedSec / m_interval;
m_framework->GetNavigator().Rotate(angle - m_curAngle);
m_curAngle = angle;
m_framework->GetRenderPolicy()->GetWindowHandle()->invalidate();
}
void RotateScreenTask::OnEnd(double ts)
{
m_framework->GetRenderPolicy()->SetIsAnimating(false);
}
bool RotateScreenTask::IsFinished()
{
return m_isFinished;
}
void RotateScreenTask::Finish()
{
m_isFinished = true;
}

View file

@ -0,0 +1,34 @@
#pragma once
#include "../anim/task.hpp"
class Framework;
class RotateScreenTask : public anim::Task
{
private:
Framework * m_framework;
double m_startTime;
double m_startAngle;
double m_endAngle;
double m_interval;
double m_curAngle;
bool m_isFinished;
public:
RotateScreenTask(Framework * framework,
double startAngle,
double endAngle,
double interval);
void OnStart(double ts);
void OnStep(double ts);
void OnEnd(double ts);
bool IsFinished();
void Finish();
};

View file

@ -227,8 +227,8 @@ void Ruler::update()
double a = ang::AngleTo(pt0, pt1);
m2::RectD r = MercatorBounds::RectByCenterXYAndSizeInMeters(glbPivot.x,
glbPivot.y,
cos(a) * m_metresDiff / 2,
sin(a) * m_metresDiff / 2);
abs(cos(a) * m_metresDiff / 2),
abs(sin(a) * m_metresDiff / 2));
pt0 = m_screen.GtoP(m2::PointD(r.minX(), r.minY()));
pt1 = m_screen.GtoP(m2::PointD(r.maxX(), r.maxY()));

View file

@ -11,7 +11,6 @@
TilingRenderPolicyMT::TilingRenderPolicyMT(Params const & p)
: BasicTilingRenderPolicy(p,
false,
false)
{
yg::ResourceManager::Params rmp = p.m_rmParams;

View file

@ -12,7 +12,6 @@
TilingRenderPolicyST::TilingRenderPolicyST(Params const & p)
: BasicTilingRenderPolicy(p,
true,
true)
{
int cpuCores = GetPlatform().CpuCores();