diff options
author | Roman Kuznetsov <r.kuznetsow@gmail.com> | 2016-07-08 18:21:29 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-07-08 18:21:29 +0300 |
commit | 55857f993fc2a4641b92bd899bceb09d2f996dd3 (patch) | |
tree | ca84f3370566dddc2c01abe73ede4ff1f2fcd7d6 /drape_frontend | |
parent | 124f14016768bc03cf807820ba9bd05299aaaad7 (diff) | |
parent | 6c6ff08f9dd685135cff652c966cabb9dcf99879 (diff) |
Merge pull request #3734 from darina/smooth-perspective
Smooth perspective
Diffstat (limited to 'drape_frontend')
41 files changed, 644 insertions, 867 deletions
diff --git a/drape_frontend/animation/animation.hpp b/drape_frontend/animation/animation.hpp index 57c96764df..3153dcf37b 100644 --- a/drape_frontend/animation/animation.hpp +++ b/drape_frontend/animation/animation.hpp @@ -19,7 +19,6 @@ public: MapLinear, MapScale, MapFollow, - MapPerspective, Arrow, KineticScroll }; @@ -35,28 +34,7 @@ public: { Position, Scale, - Angle, - AnglePerspective, - SwitchPerspective - }; - - struct SwitchPerspectiveParams - { - SwitchPerspectiveParams() = default; - - SwitchPerspectiveParams(bool enable, - double startAngle, double endAngle, - double angleFOV) - : m_enable(enable) - , m_startAngle(startAngle) - , m_endAngle(endAngle) - , m_angleFOV(angleFOV) - {} - - bool m_enable = false; - double m_startAngle = 0.0; - double m_endAngle = 0.0; - double m_angleFOV = 0.0; + Angle }; struct PropertyValue @@ -64,8 +42,7 @@ public: enum Type { ValueD, - ValuePointD, - ValuePerspectiveParams + ValuePointD }; PropertyValue() @@ -81,18 +58,11 @@ public: , m_valuePointD(value) {} - explicit PropertyValue(SwitchPerspectiveParams const & params) - : m_type(ValuePerspectiveParams) - { - m_valuePerspectiveParams = params; - } - Type m_type; union { m2::PointD m_valuePointD; double m_valueD; - SwitchPerspectiveParams m_valuePerspectiveParams; }; }; diff --git a/drape_frontend/animation/follow_animation.cpp b/drape_frontend/animation/follow_animation.cpp index 4c387fcecd..ccf359c87e 100644 --- a/drape_frontend/animation/follow_animation.cpp +++ b/drape_frontend/animation/follow_animation.cpp @@ -1,28 +1,31 @@ #include "follow_animation.hpp" +#include "animation_constants.hpp" #include "animation_system.hpp" #include "base/assert.hpp" +#include "base/logging.hpp" namespace df { -MapFollowAnimation::MapFollowAnimation(m2::PointD const & globalPosition, - double startScale, double endScale, - double startAngle, double endAngle, - m2::PointD const & startPixelPosition, +MapFollowAnimation::MapFollowAnimation(ScreenBase const & screen, + m2::PointD const & globalUserPosition, m2::PointD const & endPixelPosition, - m2::RectD const & pixelRect) + double startScale, double endScale, + double startAngle, double endAngle) : Animation(true /* couldBeInterrupted */, true /* couldBeBlended */) , m_scaleInterpolator(startScale, endScale) - , m_pixelPosInterpolator(startPixelPosition, endPixelPosition, pixelRect) , m_angleInterpolator(startAngle, endAngle) - , m_globalPosition(globalPosition) + , m_globalPosition(globalUserPosition) + , m_endPixelPosition(endPixelPosition) { double const duration = CalculateDuration(); m_scaleInterpolator.SetMinDuration(duration); m_angleInterpolator.SetMinDuration(duration); - m_pixelPosInterpolator.SetMinDuration(duration); + + m_offset = screen.PtoG(screen.P3dtoP(m_endPixelPosition)) - m_globalPosition; + m_offsetInterpolator = PositionInterpolator(duration, 0.0, m_offset, m2::PointD(0.0, 0.0)); m_objects.insert(Animation::MapPlane); @@ -30,7 +33,7 @@ MapFollowAnimation::MapFollowAnimation(m2::PointD const & globalPosition, m_properties.insert(Animation::Scale); if (m_angleInterpolator.IsActive()) m_properties.insert(Animation::Angle); - if (m_pixelPosInterpolator.IsActive()) + if (m_offsetInterpolator.IsActive() || m_scaleInterpolator.IsActive() || m_angleInterpolator.IsActive()) m_properties.insert(Animation::Position); } @@ -51,8 +54,8 @@ void MapFollowAnimation::Advance(double elapsedSeconds) m_angleInterpolator.Advance(elapsedSeconds); if (m_scaleInterpolator.IsActive()) m_scaleInterpolator.Advance(elapsedSeconds); - if (m_pixelPosInterpolator.IsActive()) - m_pixelPosInterpolator.Advance(elapsedSeconds); + if (m_offsetInterpolator.IsActive()) + m_offsetInterpolator.Advance(elapsedSeconds); } void MapFollowAnimation::Finish() @@ -61,8 +64,8 @@ void MapFollowAnimation::Finish() m_angleInterpolator.Finish(); if (m_scaleInterpolator.IsActive()) m_scaleInterpolator.Finish(); - if (m_pixelPosInterpolator.IsActive()) - m_pixelPosInterpolator.Finish(); + if (m_offsetInterpolator.IsActive()) + m_offsetInterpolator.Finish(); Animation::Finish(); } @@ -72,8 +75,8 @@ void MapFollowAnimation::SetMaxDuration(double maxDuration) m_angleInterpolator.SetMaxDuration(maxDuration); if (m_scaleInterpolator.IsActive()) m_scaleInterpolator.SetMaxDuration(maxDuration); - if (m_pixelPosInterpolator.IsActive()) - m_pixelPosInterpolator.SetMaxDuration(maxDuration); + if (m_offsetInterpolator.IsActive()) + m_offsetInterpolator.SetMaxDuration(maxDuration); } double MapFollowAnimation::GetDuration() const @@ -83,33 +86,13 @@ double MapFollowAnimation::GetDuration() const double MapFollowAnimation::CalculateDuration() const { - return max(max(m_pixelPosInterpolator.GetDuration(), - m_angleInterpolator.GetDuration()), m_scaleInterpolator.GetDuration()); + return max(m_offsetInterpolator.GetDuration(), + max(m_angleInterpolator.GetDuration(), m_scaleInterpolator.GetDuration())); } bool MapFollowAnimation::IsFinished() const { - return m_pixelPosInterpolator.IsFinished() && m_angleInterpolator.IsFinished() && - m_scaleInterpolator.IsFinished(); -} - -// static -m2::PointD MapFollowAnimation::CalculateCenter(ScreenBase const & screen, m2::PointD const & userPos, - m2::PointD const & pixelPos, double azimuth) -{ - double const scale = screen.GlobalRect().GetLocalRect().SizeX() / screen.PixelRect().SizeX(); - return CalculateCenter(scale, screen.PixelRect(), userPos, pixelPos, azimuth); -} - -// static -m2::PointD MapFollowAnimation::CalculateCenter(double scale, m2::RectD const & pixelRect, - m2::PointD const & userPos, m2::PointD const & pixelPos, - double azimuth) -{ - m2::PointD formingVector = (pixelRect.Center() - pixelPos) * scale; - formingVector.y = -formingVector.y; - formingVector.Rotate(azimuth); - return userPos + formingVector; + return m_angleInterpolator.IsFinished() && m_scaleInterpolator.IsFinished() && m_offsetInterpolator.IsFinished(); } bool MapFollowAnimation::GetProperty(TObject object, TProperty property, PropertyValue & value) const @@ -126,17 +109,24 @@ bool MapFollowAnimation::GetProperty(TObject object, TProperty property, bool ta { if (property == Animation::Position) { - m2::RectD const pixelRect = AnimationSystem::Instance().GetLastScreen().PixelRect(); + ScreenBase tmp = AnimationSystem::Instance().GetLastScreen(); if (targetValue) { - value = PropertyValue(CalculateCenter(m_scaleInterpolator.GetTargetScale(), pixelRect, m_globalPosition, - m_pixelPosInterpolator.GetTargetPosition(), m_angleInterpolator.GetTargetAngle())); + tmp.SetFromParams(m_globalPosition, m_angleInterpolator.GetTargetAngle(), m_scaleInterpolator.GetTargetScale()); + tmp.MatchGandP3d(m_globalPosition, m_endPixelPosition); } else { - value = PropertyValue(CalculateCenter(m_scaleInterpolator.GetScale(), pixelRect, m_globalPosition, - m_pixelPosInterpolator.GetPosition(), m_angleInterpolator.GetAngle())); + double const scale = m_scaleInterpolator.GetScale() / m_scaleInterpolator.GetStartScale(); + double const angle = m_angleInterpolator.GetAngle() - m_angleInterpolator.GetStartAngle(); + m2::PointD offset = m_offsetInterpolator.GetPosition() * scale; + offset.Rotate(angle); + m2::PointD pos = m_globalPosition + offset; + + tmp.SetFromParams(m_globalPosition, m_angleInterpolator.GetAngle(), m_scaleInterpolator.GetScale()); + tmp.MatchGandP3d(pos, m_endPixelPosition); } + value = PropertyValue(tmp.GetOrg()); return true; } if (property == Animation::Angle) @@ -160,7 +150,7 @@ bool MapFollowAnimation::HasScale() const bool MapFollowAnimation::HasPixelOffset() const { - return m_pixelPosInterpolator.IsActive(); + return m_offsetInterpolator.IsActive(); } } // namespace df diff --git a/drape_frontend/animation/follow_animation.hpp b/drape_frontend/animation/follow_animation.hpp index fdfd38634b..a1da305f19 100644 --- a/drape_frontend/animation/follow_animation.hpp +++ b/drape_frontend/animation/follow_animation.hpp @@ -9,18 +9,11 @@ namespace df class MapFollowAnimation : public Animation { public: - MapFollowAnimation(m2::PointD const & globalPosition, - double startScale, double endScale, - double startAngle, double endAngle, - m2::PointD const & startPixelPosition, + MapFollowAnimation(ScreenBase const & screen, + m2::PointD const & globalUserPosition, m2::PointD const & endPixelPosition, - m2::RectD const & pixelRect); - - static m2::PointD CalculateCenter(ScreenBase const & screen, m2::PointD const & userPos, - m2::PointD const & pixelPos, double azimuth); - - static m2::PointD CalculateCenter(double scale, m2::RectD const & pixelRect, - m2::PointD const & userPos, m2::PointD const & pixelPos, double azimuth); + double startScale, double endScale, + double startAngle, double endAngle); Animation::Type GetType() const override { return Animation::MapFollow; } @@ -55,10 +48,13 @@ private: double CalculateDuration() const; ScaleInterpolator m_scaleInterpolator; - PositionInterpolator m_pixelPosInterpolator; AngleInterpolator m_angleInterpolator; + PositionInterpolator m_offsetInterpolator; m2::PointD const m_globalPosition; + m2::PointD const m_endPixelPosition; + + m2::PointD m_offset; TObjectProperties m_properties; TAnimObjects m_objects; diff --git a/drape_frontend/animation/interpolators.cpp b/drape_frontend/animation/interpolators.cpp index 7570d5ee20..f933953be7 100644 --- a/drape_frontend/animation/interpolators.cpp +++ b/drape_frontend/animation/interpolators.cpp @@ -87,8 +87,7 @@ PositionInterpolator::PositionInterpolator() {} PositionInterpolator::PositionInterpolator(double duration, double delay, - m2::PointD const & startPosition, - m2::PointD const & endPosition) + m2::PointD const & startPosition, m2::PointD const & endPosition) : Interpolator(duration, delay) , m_startPosition(startPosition) , m_endPosition(endPosition) @@ -97,14 +96,13 @@ PositionInterpolator::PositionInterpolator(double duration, double delay, SetActive(m_startPosition != m_endPosition); } -PositionInterpolator::PositionInterpolator(m2::PointD const & startPosition, - m2::PointD const & endPosition, +PositionInterpolator::PositionInterpolator(m2::PointD const & startPosition, m2::PointD const & endPosition, ScreenBase const & convertor) : PositionInterpolator(0.0 /* delay */, startPosition, endPosition, convertor) {} -PositionInterpolator::PositionInterpolator(double delay, m2::PointD const & startPosition, - m2::PointD const & endPosition, +PositionInterpolator::PositionInterpolator(double delay, + m2::PointD const & startPosition, m2::PointD const & endPosition, ScreenBase const & convertor) : Interpolator(PositionInterpolator::GetMoveDuration(startPosition, endPosition, convertor), delay) , m_startPosition(startPosition) @@ -114,46 +112,36 @@ PositionInterpolator::PositionInterpolator(double delay, m2::PointD const & star SetActive(m_startPosition != m_endPosition); } -PositionInterpolator::PositionInterpolator(m2::PointD const & startPxPosition, - m2::PointD const & endPxPosition, - m2::RectD const & pixelRect) - : PositionInterpolator(0.0 /* delay */, startPxPosition, endPxPosition, pixelRect) +PositionInterpolator::PositionInterpolator(m2::PointD const & startPosition, m2::PointD const & endPosition, + m2::RectD const & viewportRect, double scale) + : PositionInterpolator(0.0 /* delay */, startPosition, endPosition, viewportRect, scale) {} -PositionInterpolator::PositionInterpolator(double delay, m2::PointD const & startPxPosition, - m2::PointD const & endPxPosition, m2::RectD const & pixelRect) - : Interpolator(PositionInterpolator::GetPixelMoveDuration(startPxPosition, endPxPosition, pixelRect), delay) - , m_startPosition(startPxPosition) - , m_endPosition(endPxPosition) - , m_position(startPxPosition) +PositionInterpolator::PositionInterpolator(double delay, + m2::PointD const & startPosition, m2::PointD const & endPosition, + m2::RectD const & viewportRect, double scale) + : Interpolator(PositionInterpolator::GetMoveDuration(startPosition, endPosition, viewportRect, scale), delay) + , m_startPosition(startPosition) + , m_endPosition(endPosition) + , m_position(startPosition) { SetActive(m_startPosition != m_endPosition); } //static -double PositionInterpolator::GetMoveDuration(m2::PointD const & startPosition, - m2::PointD const & endPosition, - ScreenBase const & convertor) -{ - return GetPixelMoveDuration(convertor.GtoP(startPosition), - convertor.GtoP(endPosition), - convertor.PixelRect()); -} - -double PositionInterpolator::GetPixelMoveDuration(m2::PointD const & startPosition, - m2::PointD const & endPosition, - m2::RectD const & pixelRect) +double PositionInterpolator::GetMoveDuration(m2::PointD const & startPosition, m2::PointD const & endPosition, + m2::RectD const & viewportRect, double scale) { double const kMinMoveDuration = 0.2; double const kMinSpeedScalar = 0.2; double const kMaxSpeedScalar = 7.0; double const kEps = 1e-5; - double const pixelLength = endPosition.Length(startPosition); + double const pixelLength = endPosition.Length(startPosition) / scale; if (pixelLength < kEps) return 0.0; - double const minSize = min(pixelRect.SizeX(), pixelRect.SizeY()); + double const minSize = min(viewportRect.SizeX(), viewportRect.SizeY()); if (pixelLength < kMinSpeedScalar * minSize) return kMinMoveDuration; @@ -161,6 +149,15 @@ double PositionInterpolator::GetPixelMoveDuration(m2::PointD const & startPositi return CalcAnimSpeedDuration(pixelLength, pixelSpeed); } +//static +double PositionInterpolator::GetMoveDuration(m2::PointD const & startPosition, + m2::PointD const & endPosition, + ScreenBase const & convertor) +{ + return GetMoveDuration(startPosition, endPosition, convertor.PixelRectIn3d(), convertor.GetScale()); +} + + void PositionInterpolator::Advance(double elapsedSeconds) { TBase::Advance(elapsedSeconds); diff --git a/drape_frontend/animation/interpolators.hpp b/drape_frontend/animation/interpolators.hpp index 501cda1017..66892f2c4e 100644 --- a/drape_frontend/animation/interpolators.hpp +++ b/drape_frontend/animation/interpolators.hpp @@ -40,25 +40,27 @@ class PositionInterpolator: public Interpolator public: PositionInterpolator(); PositionInterpolator(double duration, double delay, - m2::PointD const & startPosition, - m2::PointD const & endPosition); - PositionInterpolator(m2::PointD const & startPosition, - m2::PointD const & endPosition, + m2::PointD const & startPosition, m2::PointD const & endPosition); + + PositionInterpolator(m2::PointD const & startPosition, m2::PointD const & endPosition, ScreenBase const & convertor); - PositionInterpolator(double delay, m2::PointD const & startPosition, - m2::PointD const & endPosition, + + PositionInterpolator(double delay, + m2::PointD const & startPosition, m2::PointD const & endPosition, ScreenBase const & convertor); - PositionInterpolator(m2::PointD const & startPxPosition, - m2::PointD const & endPxPosition, - m2::RectD const & pixelRect); - PositionInterpolator(double delay, m2::PointD const & startPxPosition, - m2::PointD const & endPxPosition, - m2::RectD const & pixelRect); - - static double GetMoveDuration(m2::PointD const & startPosition, - m2::PointD const & endPosition, ScreenBase const & convertor); - static double GetPixelMoveDuration(m2::PointD const & startPosition, - m2::PointD const & endPosition, m2::RectD const & pixelRect); + + PositionInterpolator(m2::PointD const & startPosition, m2::PointD const & endPosition, + m2::RectD const & viewportRect, double scale); + + PositionInterpolator(double delay, + m2::PointD const & startPosition, m2::PointD const & endPosition, + m2::RectD const & viewportRect, double scale); + + static double GetMoveDuration(m2::PointD const & startPosition, m2::PointD const & endPosition, + m2::RectD const & viewportRect, double scale); + + static double GetMoveDuration(m2::PointD const & startPosition, m2::PointD const & endPosition, + ScreenBase const & convertor); // Interpolator overrides: void Advance(double elapsedSeconds) override; @@ -89,6 +91,7 @@ public: void Finish() override; double GetScale() const { return m_scale; } + double GetStartScale() const { return m_startScale; } double GetTargetScale() const { return m_endScale; } private: @@ -114,6 +117,7 @@ public: void Finish() override; double GetAngle() const { return m_angle; } + double GetStartAngle() const { return m_startAngle; } double GetTargetAngle() const { return m_endAngle; } private: diff --git a/drape_frontend/animation/linear_animation.cpp b/drape_frontend/animation/linear_animation.cpp index 7ff23dcdb0..048196cfc8 100644 --- a/drape_frontend/animation/linear_animation.cpp +++ b/drape_frontend/animation/linear_animation.cpp @@ -39,6 +39,14 @@ void MapLinearAnimation::SetMove(m2::PointD const & startPos, m2::PointD const & m_properties.insert(Animation::Position); } +void MapLinearAnimation::SetMove(m2::PointD const & startPos, m2::PointD const & endPos, + m2::RectD const & viewportRect, double scale) +{ + m_positionInterpolator = PositionInterpolator(startPos, endPos, viewportRect, scale); + if (m_positionInterpolator.IsActive()) + m_properties.insert(Animation::Position); +} + void MapLinearAnimation::SetRotate(double startAngle, double endAngle) { m_angleInterpolator = AngleInterpolator(startAngle, endAngle); diff --git a/drape_frontend/animation/linear_animation.hpp b/drape_frontend/animation/linear_animation.hpp index 2fadc13e9c..61e3e0ba59 100644 --- a/drape_frontend/animation/linear_animation.hpp +++ b/drape_frontend/animation/linear_animation.hpp @@ -15,6 +15,7 @@ public: MapLinearAnimation(); void SetMove(m2::PointD const & startPos, m2::PointD const & endPos, ScreenBase const & convertor); + void SetMove(m2::PointD const & startPos, m2::PointD const & endPos, m2::RectD const & viewportRect, double scale); void SetRotate(double startAngle, double endAngle); void SetScale(double startScale, double endScale); diff --git a/drape_frontend/animation/perspective_animation.cpp b/drape_frontend/animation/perspective_animation.cpp deleted file mode 100644 index 73feabbaba..0000000000 --- a/drape_frontend/animation/perspective_animation.cpp +++ /dev/null @@ -1,121 +0,0 @@ -#include "perspective_animation.hpp" - -namespace df -{ - -PerspectiveSwitchAnimation::PerspectiveSwitchAnimation(double startAngle, double endAngle, double angleFOV) - : Animation(false /* couldBeInterrupted */, false /* couldBeBlended */) - , m_angleInterpolator(GetRotateDuration(startAngle, endAngle), startAngle, endAngle) - , m_startAngle(startAngle) - , m_endAngle(endAngle) - , m_angleFOV(angleFOV) - , m_isEnablePerspectiveAnim(m_endAngle > 0.0) - , m_needPerspectiveSwitch(false) -{ - m_objects.insert(Animation::MapPlane); - m_properties.insert(Animation::AnglePerspective); - m_properties.insert(Animation::SwitchPerspective); -} - -// static -double PerspectiveSwitchAnimation::GetRotateDuration(double startAngle, double endAngle) -{ - double const kScalar = 0.5; - return kScalar * fabs(endAngle - startAngle) / math::pi4; -} - -Animation::TObjectProperties const & PerspectiveSwitchAnimation::GetProperties(TObject object) const -{ - ASSERT_EQUAL(object, Animation::MapPlane, ()); - return m_properties; -} - -bool PerspectiveSwitchAnimation::HasProperty(TObject object, TProperty property) const -{ - return HasObject(object) && m_properties.find(property) != m_properties.end(); -} - -bool PerspectiveSwitchAnimation::HasTargetProperty(TObject object, TProperty property) const -{ - return HasObject(object) && property == Animation::SwitchPerspective; -} - -void PerspectiveSwitchAnimation::Advance(double elapsedSeconds) -{ - m_angleInterpolator.Advance(elapsedSeconds); -} - -void PerspectiveSwitchAnimation::Finish() -{ - m_angleInterpolator.Finish(); - Animation::Finish(); -} - -void PerspectiveSwitchAnimation::OnStart() -{ - if (m_isEnablePerspectiveAnim) - m_needPerspectiveSwitch = true; - Animation::OnStart(); -} - -void PerspectiveSwitchAnimation::OnFinish() -{ - if (!m_isEnablePerspectiveAnim) - m_needPerspectiveSwitch = true; - Animation::OnFinish(); -} - -void PerspectiveSwitchAnimation::SetMaxDuration(double maxDuration) -{ - m_angleInterpolator.SetMaxDuration(maxDuration); -} - -double PerspectiveSwitchAnimation::GetDuration() const -{ - return m_angleInterpolator.GetDuration(); -} - -bool PerspectiveSwitchAnimation::IsFinished() const -{ - return m_angleInterpolator.IsFinished(); -} - -bool PerspectiveSwitchAnimation::GetTargetProperty(TObject object, TProperty property, PropertyValue & value) const -{ - ASSERT_EQUAL(object, Animation::MapPlane, ()); - - if (property == Animation::SwitchPerspective) - { - value = PropertyValue(SwitchPerspectiveParams(m_isEnablePerspectiveAnim, m_endAngle, m_endAngle, m_angleFOV)); - return true; - } - - ASSERT(false, ("Wrong property:", property)); - return false; -} - -bool PerspectiveSwitchAnimation::GetProperty(TObject object, TProperty property, PropertyValue & value) const -{ - ASSERT_EQUAL(object, Animation::MapPlane, ()); - - switch (property) - { - case Animation::AnglePerspective: - value = PropertyValue(m_angleInterpolator.GetAngle()); - return true; - case Animation::SwitchPerspective: - if (m_needPerspectiveSwitch) - { - m_needPerspectiveSwitch = false; - value = PropertyValue(SwitchPerspectiveParams(m_isEnablePerspectiveAnim, m_startAngle, m_endAngle, m_angleFOV)); - return true; - } - return false; - default: - ASSERT(false, ("Wrong property:", property)); - } - - return false; -} - -} // namespace df diff --git a/drape_frontend/animation/perspective_animation.hpp b/drape_frontend/animation/perspective_animation.hpp deleted file mode 100644 index 00671a450d..0000000000 --- a/drape_frontend/animation/perspective_animation.hpp +++ /dev/null @@ -1,58 +0,0 @@ -#pragma once - -#include "animation.hpp" -#include "interpolators.hpp" - -namespace df -{ - -class PerspectiveSwitchAnimation : public Animation -{ -public: - PerspectiveSwitchAnimation(double startAngle, double endAngle, double angleFOV); - - static double GetRotateDuration(double startAngle, double endAngle); - - Animation::Type GetType() const override { return Animation::MapPerspective; } - - TAnimObjects const & GetObjects() const override - { - return m_objects; - } - - bool HasObject(TObject object) const override - { - return m_objects.find(object) != m_objects.end(); - } - - TObjectProperties const & GetProperties(TObject object) const override; - bool HasProperty(TObject object, TProperty property) const override; - bool HasTargetProperty(TObject object, TProperty property) const override; - - void Advance(double elapsedSeconds) override; - void Finish() override; - - void OnStart() override; - void OnFinish() override; - - void SetMaxDuration(double maxDuration) override; - double GetDuration() const override; - bool IsFinished() const override; - - bool GetProperty(TObject object, TProperty property, PropertyValue & value) const override; - bool GetTargetProperty(TObject object, TProperty property, PropertyValue & value) const override; - -private: - AngleInterpolator m_angleInterpolator; - double m_startAngle; - double m_endAngle; - double m_angleFOV; - - bool m_isEnablePerspectiveAnim; - mutable bool m_needPerspectiveSwitch; - TAnimObjects m_objects; - TObjectProperties m_properties; -}; - -} // namespace df - diff --git a/drape_frontend/animation/scale_animation.cpp b/drape_frontend/animation/scale_animation.cpp index 92f814df1d..e0257e953c 100644 --- a/drape_frontend/animation/scale_animation.cpp +++ b/drape_frontend/animation/scale_animation.cpp @@ -8,10 +8,10 @@ namespace df { MapScaleAnimation::MapScaleAnimation(double startScale, double endScale, m2::PointD const & globalScaleCenter, - m2::PointD const & pixelCenterOffset) + m2::PointD const & pxScaleCenter) : Animation(true /* couldBeInterrupted */, true /* couldBeBlended */) , m_scaleInterpolator(startScale, endScale) - , m_pixelCenterOffset(pixelCenterOffset) + , m_pxScaleCenter(pxScaleCenter) , m_globalScaleCenter(globalScaleCenter) { m_objects.insert(Animation::MapPlane); @@ -64,7 +64,8 @@ bool MapScaleAnimation::GetProperty(TObject object, TProperty property, bool tar { ScreenBase screen = AnimationSystem::Instance().GetLastScreen(); screen.SetScale(targetValue ? m_scaleInterpolator.GetTargetScale() : m_scaleInterpolator.GetScale()); - value = PropertyValue(screen.PtoG(screen.GtoP(m_globalScaleCenter) + m_pixelCenterOffset)); + m2::PointD const pixelOffset = screen.PixelRect().Center() - screen.P3dtoP(m_pxScaleCenter); + value = PropertyValue(screen.PtoG(screen.GtoP(m_globalScaleCenter) + pixelOffset)); return true; } if (property == Animation::Scale) diff --git a/drape_frontend/animation/scale_animation.hpp b/drape_frontend/animation/scale_animation.hpp index 07706c604a..44b53c54a8 100644 --- a/drape_frontend/animation/scale_animation.hpp +++ b/drape_frontend/animation/scale_animation.hpp @@ -10,7 +10,7 @@ class MapScaleAnimation : public Animation { public: MapScaleAnimation(double startScale, double endScale, - m2::PointD const & globalScaleCenter, m2::PointD const & pixelCenterOffset); + m2::PointD const & globalScaleCenter, m2::PointD const & pxScaleCenter); Animation::Type GetType() const override { return Animation::MapScale; } @@ -41,7 +41,7 @@ private: bool GetProperty(TObject object, TProperty property, bool targetValue, PropertyValue & value) const; ScaleInterpolator m_scaleInterpolator; - m2::PointD const m_pixelCenterOffset; + m2::PointD const m_pxScaleCenter; m2::PointD const m_globalScaleCenter; TObjectProperties m_properties; TAnimObjects m_objects; diff --git a/drape_frontend/animation_system.cpp b/drape_frontend/animation_system.cpp index 886441d148..fd8e6b039b 100644 --- a/drape_frontend/animation_system.cpp +++ b/drape_frontend/animation_system.cpp @@ -18,14 +18,6 @@ public: void Blend(Animation::PropertyValue const & value) { - // Now perspective parameters can't be blended. - if (value.m_type == Animation::PropertyValue::ValuePerspectiveParams) - { - m_value = value; - m_counter = 1; - return; - } - if (m_counter != 0) { // New value type resets current blended value. @@ -75,17 +67,22 @@ private: } // namespace -bool AnimationSystem::GetRect(ScreenBase const & currentScreen, m2::AnyRectD & rect) +void AnimationSystem::UpdateLastScreen(ScreenBase const & currentScreen) { - return GetRect(currentScreen, bind(&AnimationSystem::GetProperty, this, _1, _2, _3), rect); + m_lastScreen = currentScreen; } -void AnimationSystem::GetTargetRect(ScreenBase const & currentScreen, m2::AnyRectD & rect) +bool AnimationSystem::GetScreen(ScreenBase const & currentScreen, ScreenBase & screen) { - GetRect(currentScreen, bind(&AnimationSystem::GetTargetProperty, this, _1, _2, _3), rect); + return GetScreen(currentScreen, bind(&AnimationSystem::GetProperty, this, _1, _2, _3), screen); } -bool AnimationSystem::GetRect(ScreenBase const & currentScreen, TGetPropertyFn const & getPropertyFn, m2::AnyRectD & rect) +void AnimationSystem::GetTargetScreen(ScreenBase const & currentScreen, ScreenBase & screen) +{ + GetScreen(currentScreen, bind(&AnimationSystem::GetTargetProperty, this, _1, _2, _3), screen); +} + +bool AnimationSystem::GetScreen(ScreenBase const & currentScreen, TGetPropertyFn const & getPropertyFn, ScreenBase & screen) { ASSERT(getPropertyFn != nullptr, ()); @@ -105,36 +102,12 @@ bool AnimationSystem::GetRect(ScreenBase const & currentScreen, TGetPropertyFn c if (getPropertyFn(Animation::MapPlane, Animation::Position, value)) pos = value.m_valuePointD; - m2::RectD localRect = currentScreen.PixelRect(); - localRect.Offset(-localRect.Center()); - localRect.Scale(scale); - rect = m2::AnyRectD(pos, angle, localRect); + screen = currentScreen; + screen.SetFromParams(pos, angle, scale); return true; } -bool AnimationSystem::GetPerspectiveAngle(double & angle) -{ - Animation::PropertyValue value; - if (GetProperty(Animation::MapPlane, Animation::AnglePerspective, value)) - { - angle = value.m_valueD; - return true; - } - return false; -} - -bool AnimationSystem::SwitchPerspective(Animation::SwitchPerspectiveParams & params) -{ - Animation::PropertyValue value; - if (GetProperty(Animation::MapPlane, Animation::SwitchPerspective, value)) - { - params = value.m_valuePerspectiveParams; - return true; - } - return false; -} - bool AnimationSystem::GetArrowPosition(m2::PointD & position) { Animation::PropertyValue value; diff --git a/drape_frontend/animation_system.hpp b/drape_frontend/animation_system.hpp index 7a23337e1a..d92982d6ed 100644 --- a/drape_frontend/animation_system.hpp +++ b/drape_frontend/animation_system.hpp @@ -19,11 +19,9 @@ class AnimationSystem : private noncopyable public: static AnimationSystem & Instance(); - bool GetRect(ScreenBase const & currentScreen, m2::AnyRectD & rect); - void GetTargetRect(ScreenBase const & currentScreen, m2::AnyRectD & rect); - - bool SwitchPerspective(Animation::SwitchPerspectiveParams & params); - bool GetPerspectiveAngle(double & angle); + void UpdateLastScreen(ScreenBase const & currentScreen); + bool GetScreen(ScreenBase const & currentScreen, ScreenBase & screen); + void GetTargetScreen(ScreenBase const & currentScreen, ScreenBase & screen); bool GetArrowPosition(m2::PointD & position); bool GetArrowAngle(double & angle); @@ -66,7 +64,7 @@ private: using TGetPropertyFn = function<bool (Animation::TObject object, Animation::TProperty property, Animation::PropertyValue & value)>; - bool GetRect(ScreenBase const & currentScreen, TGetPropertyFn const & getPropertyFn, m2::AnyRectD & rect); + bool GetScreen(ScreenBase const & currentScreen, TGetPropertyFn const & getPropertyFn, ScreenBase & screen); bool GetProperty(Animation::TObject object, Animation::TProperty property, Animation::PropertyValue & value) const; diff --git a/drape_frontend/backend_renderer.cpp b/drape_frontend/backend_renderer.cpp index cf0c5818b2..e022e72bab 100644 --- a/drape_frontend/backend_renderer.cpp +++ b/drape_frontend/backend_renderer.cpp @@ -76,6 +76,15 @@ void BackendRenderer::RecacheGui(gui::TWidgetsInitInfo const & initInfo, bool ne m_commutator->PostMessage(ThreadsCommutator::RenderThread, move(outputMsg), MessagePriority::Normal); } +#ifdef RENRER_DEBUG_INFO_LABELS +void BackendRenderer::RecacheDebugLabels() +{ + drape_ptr<gui::LayerRenderer> layerRenderer = m_guiCacher.RecacheDebugLabels(m_texMng); + drape_ptr<Message> outputMsg = make_unique_dp<GuiLayerRecachedMessage>(move(layerRenderer), false); + m_commutator->PostMessage(ThreadsCommutator::RenderThread, move(outputMsg), MessagePriority::Normal); +} +#endif + void BackendRenderer::RecacheChoosePositionMark() { drape_ptr<gui::LayerRenderer> layerRenderer = m_guiCacher.RecacheChoosePositionMark(m_texMng); @@ -117,6 +126,10 @@ void BackendRenderer::AcceptMessage(ref_ptr<Message> message) { ref_ptr<GuiRecacheMessage> msg = message; RecacheGui(msg->GetInitInfo(), msg->NeedResetOldGui()); + +#ifdef RENRER_DEBUG_INFO_LABELS + RecacheDebugLabels(); +#endif break; } case Message::GuiLayerLayout: diff --git a/drape_frontend/backend_renderer.hpp b/drape_frontend/backend_renderer.hpp index 3c92d9d5a5..8222f674a7 100644 --- a/drape_frontend/backend_renderer.hpp +++ b/drape_frontend/backend_renderer.hpp @@ -63,6 +63,10 @@ private: void RecacheChoosePositionMark(); void RecacheMapShapes(); +#ifdef RENRER_DEBUG_INFO_LABELS + void RecacheDebugLabels(); +#endif + void AcceptMessage(ref_ptr<Message> message) override; class Routine : public threads::IRoutine diff --git a/drape_frontend/drape_engine.cpp b/drape_frontend/drape_engine.cpp index d45db5ef08..8ad2631e88 100644 --- a/drape_frontend/drape_engine.cpp +++ b/drape_frontend/drape_engine.cpp @@ -265,11 +265,10 @@ void DrapeEngine::StopLocationFollow() MessagePriority::High); } -void DrapeEngine::FollowRoute(int preferredZoomLevel, int preferredZoomLevel3d, double rotationAngle, double angleFOV) +void DrapeEngine::FollowRoute(int preferredZoomLevel, int preferredZoomLevel3d) { m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread, - make_unique_dp<FollowRouteMessage>(preferredZoomLevel, preferredZoomLevel3d, - rotationAngle, angleFOV), + make_unique_dp<FollowRouteMessage>(preferredZoomLevel, preferredZoomLevel3d), MessagePriority::High); } @@ -380,22 +379,21 @@ void DrapeEngine::SetWidgetLayout(gui::TWidgetsLayoutInfo && info) MessagePriority::Normal); } -void DrapeEngine::Allow3dMode(bool allowPerspectiveInNavigation, bool allow3dBuildings, double rotationAngle, double angleFOV) +void DrapeEngine::Allow3dMode(bool allowPerspectiveInNavigation, bool allow3dBuildings) { m_threadCommutator->PostMessage(ThreadsCommutator::ResourceUploadThread, make_unique_dp<Allow3dBuildingsMessage>(allow3dBuildings), MessagePriority::Normal); m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread, - make_unique_dp<Allow3dModeMessage>(allowPerspectiveInNavigation, allow3dBuildings, - rotationAngle, angleFOV), + make_unique_dp<Allow3dModeMessage>(allowPerspectiveInNavigation, allow3dBuildings), MessagePriority::Normal); } -void DrapeEngine::EnablePerspective(double rotationAngle, double angleFOV) +void DrapeEngine::EnablePerspective() { m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread, - make_unique_dp<EnablePerspectiveMessage>(rotationAngle, angleFOV), + make_unique_dp<EnablePerspectiveMessage>(), MessagePriority::Normal); } diff --git a/drape_frontend/drape_engine.hpp b/drape_frontend/drape_engine.hpp index 421509a1ea..b48cdb9d2d 100644 --- a/drape_frontend/drape_engine.hpp +++ b/drape_frontend/drape_engine.hpp @@ -124,14 +124,14 @@ public: void AddRoute(m2::PolylineD const & routePolyline, vector<double> const & turns, df::ColorConstant color, df::RoutePattern pattern = df::RoutePattern()); void RemoveRoute(bool deactivateFollowing); - void FollowRoute(int preferredZoomLevel, int preferredZoomLevel3d, double rotationAngle, double angleFOV); + void FollowRoute(int preferredZoomLevel, int preferredZoomLevel3d); void DeactivateRouteFollowing(); void SetRoutePoint(m2::PointD const & position, bool isStart, bool isValid); void SetWidgetLayout(gui::TWidgetsLayoutInfo && info); - void Allow3dMode(bool allowPerspectiveInNavigation, bool allow3dBuildings, double rotationAngle, double angleFOV); - void EnablePerspective(double rotationAngle, double angleFOV); + void Allow3dMode(bool allowPerspectiveInNavigation, bool allow3dBuildings); + void EnablePerspective(); void UpdateGpsTrackPoints(vector<df::GpsTrackPoint> && toAdd, vector<uint32_t> && toRemove); void ClearGpsTrackPoints(); diff --git a/drape_frontend/drape_frontend.pro b/drape_frontend/drape_frontend.pro index 137ae99d4e..514f82d1ab 100755 --- a/drape_frontend/drape_frontend.pro +++ b/drape_frontend/drape_frontend.pro @@ -23,12 +23,12 @@ SOURCES += \ animation/scale_animation.cpp \ animation/sequence_animation.cpp \ animation/parallel_animation.cpp \ - animation/perspective_animation.cpp \ animation/opacity_animation.cpp \ animation/show_hide_animation.cpp \ gui/choose_position_mark.cpp \ gui/compass.cpp \ gui/copyright_label.cpp \ + gui/debug_label.cpp \ gui/drape_gui.cpp \ gui/gui_text.cpp \ gui/layer_render.cpp \ @@ -115,13 +115,13 @@ HEADERS += \ animation/scale_animation.hpp \ animation/sequence_animation.hpp \ animation/parallel_animation.hpp \ - animation/perspective_animation.hpp \ animation/opacity_animation.hpp \ animation/show_hide_animation.hpp \ animation/value_mapping.hpp \ gui/choose_position_mark.hpp \ gui/compass.hpp \ gui/copyright_label.hpp \ + gui/debug_label.hpp \ gui/drape_gui.hpp \ gui/gui_text.hpp \ gui/layer_render.hpp \ diff --git a/drape_frontend/drape_frontend_tests/user_event_stream_tests.cpp b/drape_frontend/drape_frontend_tests/user_event_stream_tests.cpp index 8ce2d76bab..4858841d20 100644 --- a/drape_frontend/drape_frontend_tests/user_event_stream_tests.cpp +++ b/drape_frontend/drape_frontend_tests/user_event_stream_tests.cpp @@ -37,7 +37,6 @@ public: void CorrectGlobalScalePoint(m2::PointD & pt) const override {} void OnScaleEnded() override {} void OnAnimationStarted(ref_ptr<df::Animation> /* anim */) override {} - void OnPerspectiveSwitchRejected() override {} void OnTouchMapAction() override {} void OnAnimatedScaleEnded() override {} diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index 3b06a0adbf..560fe7a4b6 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -484,8 +484,7 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message) if (m_pendingFollowRoute != nullptr) { - FollowRoute(m_pendingFollowRoute->m_preferredZoomLevel, m_pendingFollowRoute->m_preferredZoomLevelIn3d, - m_pendingFollowRoute->m_rotationAngle, m_pendingFollowRoute->m_angleFOV); + FollowRoute(m_pendingFollowRoute->m_preferredZoomLevel, m_pendingFollowRoute->m_preferredZoomLevelIn3d); m_pendingFollowRoute.reset(); } break; @@ -522,13 +521,11 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message) if (m_routeRenderer->GetRouteData() == nullptr) { m_pendingFollowRoute.reset( - new FollowRouteData(msg->GetPreferredZoomLevel(), msg->GetPreferredZoomLevelIn3d(), - msg->GetRotationAngle(), msg->GetAngleFOV())); + new FollowRouteData(msg->GetPreferredZoomLevel(), msg->GetPreferredZoomLevelIn3d())); break; } - FollowRoute(msg->GetPreferredZoomLevel(), msg->GetPreferredZoomLevelIn3d(), - msg->GetRotationAngle(), msg->GetAngleFOV()); + FollowRoute(msg->GetPreferredZoomLevel(), msg->GetPreferredZoomLevelIn3d()); break; } @@ -613,9 +610,7 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message) case Message::EnablePerspective: { - ref_ptr<EnablePerspectiveMessage> const msg = message; - AddUserEvent(EnablePerspectiveEvent(msg->GetRotationAngle(), msg->GetAngleFOV(), - false /* animated */, true /* immediately start */)); + AddUserEvent(SetAutoPerspectiveEvent(true /* isAutoPerspective */)); break; } @@ -628,11 +623,7 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message) if (m_enablePerspectiveInNavigation == msg->AllowPerspective() && m_enablePerspectiveInNavigation != screen.isPerspective()) { - if (m_enablePerspectiveInNavigation) - AddUserEvent(EnablePerspectiveEvent(msg->GetRotationAngle(), msg->GetAngleFOV(), - false /* animated */, true /* immediately start */)); - else - AddUserEvent(DisablePerspectiveEvent()); + AddUserEvent(SetAutoPerspectiveEvent(m_enablePerspectiveInNavigation)); } #endif @@ -648,15 +639,7 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message) m_enablePerspectiveInNavigation = msg->AllowPerspective(); if (m_myPositionController->IsInRouting()) { - if (m_enablePerspectiveInNavigation && !screen.isPerspective() && !m_perspectiveDiscarded) - { - AddUserEvent(EnablePerspectiveEvent(msg->GetRotationAngle(), msg->GetAngleFOV(), - true /* animated */, true /* immediately start */)); - } - else if (!m_enablePerspectiveInNavigation && (screen.isPerspective() || m_perspectiveDiscarded)) - { - DisablePerspective(); - } + AddUserEvent(SetAutoPerspectiveEvent(m_enablePerspectiveInNavigation)); } } break; @@ -750,18 +733,14 @@ unique_ptr<threads::IRoutine> FrontendRenderer::CreateRoutine() return make_unique<Routine>(*this); } -void FrontendRenderer::FollowRoute(int preferredZoomLevel, int preferredZoomLevelIn3d, - double rotationAngle, double angleFOV) +void FrontendRenderer::FollowRoute(int preferredZoomLevel, int preferredZoomLevelIn3d) { m_myPositionController->ActivateRouting(!m_enablePerspectiveInNavigation ? preferredZoomLevel : preferredZoomLevelIn3d); if (m_enablePerspectiveInNavigation) - { - bool immediatelyStart = !m_myPositionController->IsRotationAvailable(); - AddUserEvent(EnablePerspectiveEvent(rotationAngle, angleFOV, true /* animated */, immediatelyStart)); - } + AddUserEvent(SetAutoPerspectiveEvent(true /* isAutoPerspective */)); m_overlayTree->SetFollowingMode(true); } @@ -811,17 +790,22 @@ void FrontendRenderer::InvalidateRect(m2::RectD const & gRect) void FrontendRenderer::OnResize(ScreenBase const & screen) { - m2::RectD const viewportRect = screen.isPerspective() ? screen.PixelRectIn3d() : screen.PixelRect(); + m2::RectD const viewportRect = screen.PixelRectIn3d(); + double const kEps = 1e-5; + bool const viewportChanged = !m2::IsEqualSize(m_lastReadedModelView.PixelRectIn3d(), viewportRect, kEps, kEps); m_myPositionController->UpdatePixelPosition(screen); - m_myPositionController->OnNewPixelRect(); - m_viewport.SetViewport(0, 0, viewportRect.SizeX(), viewportRect.SizeY()); - m_contextFactory->getDrawContext()->resize(viewportRect.SizeX(), viewportRect.SizeY()); + if (viewportChanged) + { + m_myPositionController->OnNewViewportRect(); + m_viewport.SetViewport(0, 0, viewportRect.SizeX(), viewportRect.SizeY()); + m_contextFactory->getDrawContext()->resize(viewportRect.SizeX(), viewportRect.SizeY()); + m_framebuffer->SetSize(viewportRect.SizeX(), viewportRect.SizeY()); + } + RefreshProjection(screen); RefreshPivotTransform(screen); - - m_framebuffer->SetSize(viewportRect.SizeX(), viewportRect.SizeY()); } void FrontendRenderer::AddToRenderGroup(dp::GLState const & state, @@ -1069,18 +1053,7 @@ void FrontendRenderer::RenderScene(ScreenBase const & modelView) modelView, make_ref(m_gpuProgramManager), m_generalUniforms); if (m_guiRenderer != nullptr) - { - if (isPerspective) - { - ScreenBase modelView2d = modelView; - modelView2d.ResetPerspective(); - m_guiRenderer->Render(make_ref(m_gpuProgramManager), modelView2d); - } - else - { - m_guiRenderer->Render(make_ref(m_gpuProgramManager), modelView); - } - } + m_guiRenderer->Render(make_ref(m_gpuProgramManager), modelView); GLFunctions::glEnable(gl_const::GLDepthTest); @@ -1232,7 +1205,18 @@ void FrontendRenderer::RefreshModelView(ScreenBase const & screen) m_generalUniforms.SetMatrix4x4Value("modelView", mv.m_data); - float const zScale = 2.0f / (screen.GetHeight() * screen.GetScale()); + float zScale; + if (screen.isPerspective()) + { + // TODO: Calculate exact value of zScale + double const averageScale3d = 3.0; + zScale = 2.0f / (screen.PixelRectIn3d().SizeY() * averageScale3d * screen.GetScale()); + } + else + { + zScale = 2.0f / (screen.GetHeight() * screen.GetScale()); + } + m_generalUniforms.SetFloatValue("zScale", zScale); } @@ -1266,8 +1250,7 @@ void FrontendRenderer::RefreshBgColor() void FrontendRenderer::DisablePerspective() { - m_perspectiveDiscarded = false; - AddUserEvent(DisablePerspectiveEvent()); + AddUserEvent(SetAutoPerspectiveEvent(false /* isAutoPerspective */)); } void FrontendRenderer::CheckIsometryMinScale(ScreenBase const & screen) @@ -1281,20 +1264,6 @@ void FrontendRenderer::CheckIsometryMinScale(ScreenBase const & screen) } } -void FrontendRenderer::CheckPerspectiveMinScale() -{ - if (!m_enablePerspectiveInNavigation || m_userEventStream.IsInPerspectiveAnimation()) - return; - - bool const switchTo2d = !IsScaleAllowableIn3d(m_currentZoomLevel); - if ((!switchTo2d && !m_perspectiveDiscarded) || - (switchTo2d && !m_userEventStream.GetCurrentScreen().isPerspective())) - return; - - m_perspectiveDiscarded = switchTo2d; - AddUserEvent(SwitchViewModeEvent(switchTo2d)); -} - void FrontendRenderer::ResolveZoomLevel(ScreenBase const & screen) { int const prevZoomLevel = m_currentZoomLevel; @@ -1304,7 +1273,6 @@ void FrontendRenderer::ResolveZoomLevel(ScreenBase const & screen) UpdateCanBeDeletedStatus(); CheckIsometryMinScale(screen); - CheckPerspectiveMinScale(); UpdateDisplacementEnabled(); } @@ -1432,12 +1400,6 @@ void FrontendRenderer::OnAnimationStarted(ref_ptr<Animation> anim) m_myPositionController->AnimationStarted(anim); } -void FrontendRenderer::OnPerspectiveSwitchRejected() -{ - if (m_perspectiveDiscarded) - m_perspectiveDiscarded = false; -} - void FrontendRenderer::OnTouchMapAction() { m_myPositionController->ResetRoutingNotFollowTimer(); diff --git a/drape_frontend/frontend_renderer.hpp b/drape_frontend/frontend_renderer.hpp index d4adc101f2..5f7459c7bb 100755 --- a/drape_frontend/frontend_renderer.hpp +++ b/drape_frontend/frontend_renderer.hpp @@ -174,7 +174,6 @@ private: TTilesCollection ResolveTileKeys(ScreenBase const & screen); void ResolveZoomLevel(ScreenBase const & screen); void UpdateDisplacementEnabled(); - void CheckPerspectiveMinScale(); void CheckIsometryMinScale(ScreenBase const & screen); void DisablePerspective(); @@ -195,7 +194,6 @@ private: void OnScaleEnded() override; void OnAnimatedScaleEnded() override; void OnAnimationStarted(ref_ptr<Animation> anim) override; - void OnPerspectiveSwitchRejected() override; void OnTouchMapAction() override; class Routine : public threads::IRoutine @@ -223,8 +221,7 @@ private: using TRenderGroupRemovePredicate = function<bool(drape_ptr<RenderGroup> const &)>; void RemoveRenderGroupsLater(TRenderGroupRemovePredicate const & predicate); - void FollowRoute(int preferredZoomLevel, int preferredZoomLevelIn3d, - double rotationAngle, double angleFOV); + void FollowRoute(int preferredZoomLevel, int preferredZoomLevelIn3d); void InvalidateRect(m2::RectD const & gRect); bool CheckTileGenerations(TileKey const & tileKey); void UpdateCanBeDeletedStatus(); @@ -296,8 +293,6 @@ private: TTilesCollection m_notFinishedTiles; int m_currentZoomLevel = -1; - - bool m_perspectiveDiscarded = false; ref_ptr<RequestedTiles> m_requestedTiles; uint64_t m_maxGeneration; @@ -306,19 +301,13 @@ private: struct FollowRouteData { FollowRouteData(int preferredZoomLevel, - int preferredZoomLevelIn3d, - double rotationAngle, - double angleFOV) + int preferredZoomLevelIn3d) : m_preferredZoomLevel(preferredZoomLevel) , m_preferredZoomLevelIn3d(preferredZoomLevelIn3d) - , m_rotationAngle(rotationAngle) - , m_angleFOV(angleFOV) {} int m_preferredZoomLevel; int m_preferredZoomLevelIn3d; - double m_rotationAngle; - double m_angleFOV; }; unique_ptr<FollowRouteData> m_pendingFollowRoute; diff --git a/drape_frontend/gui/choose_position_mark.cpp b/drape_frontend/gui/choose_position_mark.cpp index 5c7b87d20d..e08c350d28 100644 --- a/drape_frontend/gui/choose_position_mark.cpp +++ b/drape_frontend/gui/choose_position_mark.cpp @@ -37,7 +37,7 @@ public: bool Update(ScreenBase const & screen) override { - SetPivot(glsl::ToVec2(m2::PointF(screen.PixelRect().Center()))); + SetPivot(glsl::ToVec2(m2::PointF(screen.PixelRectIn3d().Center()))); return TBase::Update(screen); } }; diff --git a/drape_frontend/gui/debug_label.cpp b/drape_frontend/gui/debug_label.cpp new file mode 100644 index 0000000000..7b8c5116ef --- /dev/null +++ b/drape_frontend/gui/debug_label.cpp @@ -0,0 +1,94 @@ +#include "debug_label.hpp" + +#include "drape_gui.hpp" + +#include "std/bind.hpp" + +namespace gui +{ + +class DebugLabelHandle : public MutableLabelHandle +{ + using TBase = MutableLabelHandle; + +public: + DebugLabelHandle(uint32_t id, dp::Anchor anchor, m2::PointF const & pivot, + ref_ptr<dp::TextureManager> tex, TUpdateDebugLabelFn const & onUpdateFn) + : MutableLabelHandle(id, anchor, pivot) + , m_onUpdateFn(onUpdateFn) + { + SetTextureManager(tex); + } + + bool Update(ScreenBase const & screen) override + { + string content; + bool const isVisible = m_onUpdateFn(screen, content); + + SetIsVisible(isVisible); + SetContent(content); + + return TBase::Update(screen); + } + +private: + TUpdateDebugLabelFn m_onUpdateFn; +}; + +void AddSymbols(string const & str, set<char> & symbols) +{ + for (size_t i = 0, sz = str.length(); i < sz; ++i) + symbols.insert(str[i]); +} + +void DebugInfoLabels::AddLabel(ref_ptr<dp::TextureManager> tex, string const & caption, TUpdateDebugLabelFn const & onUpdateFn) +{ + string alphabet; + set<char> symbols; + AddSymbols(caption, symbols); + AddSymbols("0123456789.-e", symbols); + + alphabet.reserve(symbols.size()); + for (auto const & ch : symbols) + alphabet.push_back(ch); + + MutableLabelDrawer::Params params; + params.m_anchor = dp::LeftTop; + params.m_alphabet = alphabet; + params.m_maxLength = 100; + params.m_font = DrapeGui::GetGuiTextFont(); + params.m_font.m_color = dp::Color(0, 0, 255, 255); + params.m_font.m_size *= 1.2; + params.m_pivot = m_position.m_pixelPivot; + +#ifdef RENRER_DEBUG_INFO_LABELS + uint32_t const id = GuiHandleDebugLabel + m_labelsCount; + + params.m_handleCreator = [id, onUpdateFn, tex](dp::Anchor anchor, m2::PointF const & pivot) + { + return make_unique_dp<DebugLabelHandle>(id, anchor, pivot, tex, onUpdateFn); + }; +#endif + m_labelsParams.push_back(params); + ++m_labelsCount; +} + +drape_ptr<ShapeRenderer> DebugInfoLabels::Draw(ref_ptr<dp::TextureManager> tex) +{ + drape_ptr<ShapeRenderer> renderer = make_unique_dp<ShapeRenderer>(); + + m2::PointF pos = m_position.m_pixelPivot; + + for (auto & params : m_labelsParams) + { + params.m_pivot.y = pos.y; + m2::PointF textSize = MutableLabelDrawer::Draw(params, tex, bind(&ShapeRenderer::AddShape, renderer.get(), _1, _2)); + pos.y += 2 * textSize.y; + } + + m_labelsParams.clear(); + + return renderer; +} + +} // namespace gui diff --git a/drape_frontend/gui/debug_label.hpp b/drape_frontend/gui/debug_label.hpp new file mode 100644 index 0000000000..b4cf4917cb --- /dev/null +++ b/drape_frontend/gui/debug_label.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include "gui_text.hpp" +#include "shape.hpp" + +#include "std/vector.hpp" + +namespace gui +{ + +using TUpdateDebugLabelFn = function<bool(ScreenBase const & screen, string & content)>; + +class DebugInfoLabels : public Shape +{ +public: + DebugInfoLabels(gui::Position const & position) + : Shape(position) + {} + + void AddLabel(ref_ptr<dp::TextureManager> tex, string const & caption, TUpdateDebugLabelFn const & onUpdateFn); + drape_ptr<ShapeRenderer> Draw(ref_ptr<dp::TextureManager> tex); + +private: + vector<MutableLabelDrawer::Params> m_labelsParams; + uint32_t m_labelsCount = 0; +}; + +} // namespace gui diff --git a/drape_frontend/gui/layer_render.cpp b/drape_frontend/gui/layer_render.cpp index c2521dd38b..4406c04b01 100644 --- a/drape_frontend/gui/layer_render.cpp +++ b/drape_frontend/gui/layer_render.cpp @@ -1,6 +1,7 @@ #include "choose_position_mark.hpp" #include "compass.hpp" #include "copyright_label.hpp" +#include "debug_label.hpp" #include "drape_gui.hpp" #include "gui_text.hpp" #include "layer_render.hpp" @@ -12,6 +13,8 @@ #include "drape/batcher.hpp" #include "drape/render_bucket.hpp" +#include "geometry/mercator.hpp" + #include "base/stl_add.hpp" #include "std/bind.hpp" @@ -212,6 +215,100 @@ drape_ptr<LayerRenderer> LayerCacher::RecacheChoosePositionMark(ref_ptr<dp::Text return renderer; } +#ifdef RENRER_DEBUG_INFO_LABELS +drape_ptr<LayerRenderer> LayerCacher::RecacheDebugLabels(ref_ptr<dp::TextureManager> textures) +{ + drape_ptr<LayerRenderer> renderer = make_unique_dp<LayerRenderer>(); + + float const vs = df::VisualParams::Instance().GetVisualScale(); + DebugInfoLabels debugLabels = DebugInfoLabels(Position(m2::PointF(10.0f * vs, 50.0f * vs), dp::Center)); + + debugLabels.AddLabel(textures, "visible: km2, readed: km2, ratio:", + [](ScreenBase const & screen, string & content) -> bool + { + double const sizeX = screen.PixelRectIn3d().SizeX(); + double const sizeY = screen.PixelRectIn3d().SizeY(); + + m2::PointD const p0 = screen.PtoG(screen.P3dtoP(m2::PointD(0.0, 0.0))); + m2::PointD const p1 = screen.PtoG(screen.P3dtoP(m2::PointD(0.0, sizeY))); + m2::PointD const p2 = screen.PtoG(screen.P3dtoP(m2::PointD(sizeX, sizeY))); + m2::PointD const p3 = screen.PtoG(screen.P3dtoP(m2::PointD(sizeX, 0.0))); + + double const areaG = MercatorBounds::AreaOnEarth(p0, p1, p2) + + MercatorBounds::AreaOnEarth(p2, p3, p0); + + double const sizeX_2d = screen.PixelRect().SizeX(); + double const sizeY_2d = screen.PixelRect().SizeY(); + + m2::PointD const p0_2d = screen.PtoG(m2::PointD(0.0, 0.0)); + m2::PointD const p1_2d = screen.PtoG(m2::PointD(0.0, sizeY_2d)); + m2::PointD const p2_2d = screen.PtoG(m2::PointD(sizeX_2d, sizeY_2d)); + m2::PointD const p3_2d = screen.PtoG(m2::PointD(sizeX_2d, 0.0)); + + double const areaGTotal = MercatorBounds::AreaOnEarth(p0_2d, p1_2d, p2_2d) + + MercatorBounds::AreaOnEarth(p2_2d, p3_2d, p0_2d); + + ostringstream out; + out << fixed << setprecision(2) + << "visible: " << areaG / 1000000.0 << " km2" + << ", readed: " << areaGTotal / 1000000.0 << " km2" + << ", ratio: " << areaGTotal / areaG; + content.assign(out.str()); + return true; + }); + + debugLabels.AddLabel(textures, "scale2d: m/px, scale2d * vs: m/px", + [](ScreenBase const & screen, string & content) -> bool + { + double const distanceG = MercatorBounds::DistanceOnEarth(screen.PtoG(screen.PixelRect().LeftBottom()), + screen.PtoG(screen.PixelRect().RightBottom())); + + double const vs = df::VisualParams::Instance().GetVisualScale(); + double const scale = distanceG / screen.PixelRect().SizeX(); + + ostringstream out; + out << fixed << setprecision(2) + << "scale2d: " << scale << " m/px" + << ", scale2d * vs: " << scale * vs << " m/px"; + content.assign(out.str()); + return true; + }); + + debugLabels.AddLabel(textures, "distance: m", + [](ScreenBase const & screen, string & content) -> bool + { + double const sizeX = screen.PixelRectIn3d().SizeX(); + double const sizeY = screen.PixelRectIn3d().SizeY(); + + double const distance = MercatorBounds::DistanceOnEarth(screen.PtoG(screen.P3dtoP(m2::PointD(sizeX / 2.0, 0.0))), + screen.PtoG(screen.P3dtoP(m2::PointD(sizeX / 2.0, sizeY)))); + + ostringstream out; + out << fixed << setprecision(2) + << "distance: " << distance << " m"; + content.assign(out.str()); + return true; + }); + + debugLabels.AddLabel(textures, "angle: ", + [](ScreenBase const & screen, string & content) -> bool + { + ostringstream out; + out << fixed << setprecision(2) + << "angle: " << screen.GetRotationAngle() * 180.0 / math::pi; + content.assign(out.str()); + return true; + }); + + renderer->AddShapeRenderer(WIDGET_DEBUG_INFO, debugLabels.Draw(textures)); + + // Flush gui geometry. + GLFunctions::glFlush(); + + return renderer; +} +#endif + m2::PointF LayerCacher::CacheCompass(Position const & position, ref_ptr<LayerRenderer> renderer, ref_ptr<dp::TextureManager> textures) { diff --git a/drape_frontend/gui/layer_render.hpp b/drape_frontend/gui/layer_render.hpp index f48cf76c0c..fdd24e9575 100644 --- a/drape_frontend/gui/layer_render.hpp +++ b/drape_frontend/gui/layer_render.hpp @@ -58,6 +58,10 @@ public: ref_ptr<dp::TextureManager> textures); drape_ptr<LayerRenderer> RecacheChoosePositionMark(ref_ptr<dp::TextureManager> textures); +#ifdef RENRER_DEBUG_INFO_LABELS + drape_ptr<LayerRenderer> RecacheDebugLabels(ref_ptr<dp::TextureManager> textures); +#endif + private: m2::PointF CacheCompass(Position const & position, ref_ptr<LayerRenderer> renderer, ref_ptr<dp::TextureManager> textures); m2::PointF CacheRuler(Position const & position, ref_ptr<LayerRenderer> renderer, ref_ptr<dp::TextureManager> textures); diff --git a/drape_frontend/gui/shape.cpp b/drape_frontend/gui/shape.cpp index 794405dc26..3499b32b31 100644 --- a/drape_frontend/gui/shape.cpp +++ b/drape_frontend/gui/shape.cpp @@ -91,7 +91,7 @@ void ShapeRenderer::Build(ref_ptr<dp::GpuProgramManager> mng) void ShapeRenderer::Render(ScreenBase const & screen, ref_ptr<dp::GpuProgramManager> mng) { array<float, 16> m; - m2::RectD const & pxRect = screen.PixelRect(); + m2::RectD const & pxRect = screen.PixelRectIn3d(); dp::MakeProjection(m, 0.0f, pxRect.SizeX(), pxRect.SizeY(), 0.0f); dp::UniformValuesStorage uniformStorage; diff --git a/drape_frontend/gui/skin.hpp b/drape_frontend/gui/skin.hpp index c34965a026..d326a8e1d0 100644 --- a/drape_frontend/gui/skin.hpp +++ b/drape_frontend/gui/skin.hpp @@ -6,6 +6,8 @@ #include "std/map.hpp" +//#define RENRER_DEBUG_INFO_LABELS + namespace gui { @@ -16,7 +18,10 @@ enum EWidget WIDGET_COPYRIGHT = 0x4, WIDGET_SCALE_LABEL = 0x8, /// Following widgets controlled by rendering kernel. Don't use them in platform code - WIDGET_CHOOSE_POSITION_MARK = 0x8000 + WIDGET_CHOOSE_POSITION_MARK = 0x8000, +#ifdef RENRER_DEBUG_INFO_LABELS + WIDGET_DEBUG_INFO +#endif }; enum EGuiHandle @@ -34,7 +39,10 @@ enum EGuiHandle GuiHandleRetryButtonLabel, GuiHandleCancelButton, GuiHandleCancelButtonLabel, - GuiHandleChoosePositionMark + GuiHandleChoosePositionMark, +#ifdef RENRER_DEBUG_INFO_LABELS + GuiHandleDebugLabel = 100 +#endif }; struct Position diff --git a/drape_frontend/message_subclasses.hpp b/drape_frontend/message_subclasses.hpp index 49e327af05..67da3f47dd 100644 --- a/drape_frontend/message_subclasses.hpp +++ b/drape_frontend/message_subclasses.hpp @@ -645,24 +645,18 @@ public: class FollowRouteMessage : public Message { public: - FollowRouteMessage(int preferredZoomLevel, int preferredZoomLevelIn3d, double rotationAngle, double angleFOV) + FollowRouteMessage(int preferredZoomLevel, int preferredZoomLevelIn3d) : m_preferredZoomLevel(preferredZoomLevel) , m_preferredZoomLevelIn3d(preferredZoomLevelIn3d) - , m_rotationAngle(rotationAngle) - , m_angleFOV(angleFOV) {} Type GetType() const override { return Message::FollowRoute; } int GetPreferredZoomLevel() const { return m_preferredZoomLevel; } int GetPreferredZoomLevelIn3d() const { return m_preferredZoomLevelIn3d; } - double GetRotationAngle() const { return m_rotationAngle; } - double GetAngleFOV() const { return m_angleFOV; } private: int const m_preferredZoomLevel; int const m_preferredZoomLevelIn3d; - double const m_rotationAngle; - double const m_angleFOV; }; class InvalidateTexturesMessage : public BaseBlockingMessage @@ -694,24 +688,18 @@ public: class Allow3dModeMessage : public Message { public: - Allow3dModeMessage(bool allowPerspective, bool allow3dBuildings, double rotationAngle, double angleFOV) + Allow3dModeMessage(bool allowPerspective, bool allow3dBuildings) : m_allowPerspective(allowPerspective) , m_allow3dBuildings(allow3dBuildings) - , m_rotationAngle(rotationAngle) - , m_angleFOV(angleFOV) {} Type GetType() const override { return Message::Allow3dMode; } bool AllowPerspective() const { return m_allowPerspective; } bool Allow3dBuildings() const { return m_allow3dBuildings; } - double GetRotationAngle() const { return m_rotationAngle; } - double GetAngleFOV() const { return m_angleFOV; } private: bool const m_allowPerspective; bool const m_allow3dBuildings; - double const m_rotationAngle; - double const m_angleFOV; }; class Allow3dBuildingsMessage : public Message @@ -731,19 +719,9 @@ private: class EnablePerspectiveMessage : public Message { public: - EnablePerspectiveMessage(double rotationAngle, double angleFOV) - : m_rotationAngle(rotationAngle) - , m_angleFOV(angleFOV) - {} + EnablePerspectiveMessage() = default; Type GetType() const override { return Message::EnablePerspective; } - - double GetRotationAngle() const { return m_rotationAngle; } - double GetAngleFOV() const { return m_angleFOV; } - -private: - double const m_rotationAngle; - double const m_angleFOV; }; class CacheGpsTrackPointsMessage : public Message diff --git a/drape_frontend/my_position_controller.cpp b/drape_frontend/my_position_controller.cpp index 8c179fab77..0feaf86a64 100644 --- a/drape_frontend/my_position_controller.cpp +++ b/drape_frontend/my_position_controller.cpp @@ -52,7 +52,7 @@ string LocationModeStatisticsName(location::EMyPositionMode mode) int GetZoomLevel(ScreenBase const & screen) { - return my::clamp(fabs(log(screen.GetScale()) / log(2.0)), 1, scales::GetUpperStyleScale()); + return df::GetZoomLevel(screen.GetScale()); } int GetZoomLevel(ScreenBase const & screen, m2::PointD const & position, double errorRadius) @@ -63,6 +63,8 @@ int GetZoomLevel(ScreenBase const & screen, m2::PointD const & position, double return GetZoomLevel(s); } + + } // namespace MyPositionController::MyPositionController(location::EMyPositionMode initMode, double timeInBackground, @@ -103,7 +105,7 @@ MyPositionController::~MyPositionController() { } -void MyPositionController::OnNewPixelRect() +void MyPositionController::OnNewViewportRect() { UpdateViewport(kDoNotChangeZoom); } @@ -112,8 +114,6 @@ void MyPositionController::UpdatePixelPosition(ScreenBase const & screen) { m_pixelRect = screen.isPerspective() ? screen.PixelRectIn3d() : screen.PixelRect(); m_positionYOffset = screen.isPerspective() ? kPositionOffsetYIn3D : kPositionOffsetY; - m_centerPixelPositionRouting = screen.P3dtoP(GetRoutingRotationPixelCenter()); - m_centerPixelPosition = screen.P3dtoP(m_pixelRect.Center()); } void MyPositionController::SetListener(ref_ptr<MyPositionController::Listener> listener) @@ -266,7 +266,7 @@ void MyPositionController::NextMode(ScreenBase const & screen) if (!m_isInRouting) { ChangeMode(location::Follow); - ChangeModelView(m_position, 0.0, m_centerPixelPosition, preferredZoomLevel); + ChangeModelView(m_position, 0.0, m_pixelRect.Center(), preferredZoomLevel); } } } @@ -317,7 +317,7 @@ void MyPositionController::OnLocationUpdate(location::GpsInfo const & info, bool ChangeModelView(m_position, kDoNotChangeZoom); else if (m_mode == location::FollowAndRotate) ChangeModelView(m_position, m_drawDirection, - m_isInRouting ? m_centerPixelPositionRouting : m_centerPixelPosition, kDoNotChangeZoom); + m_isInRouting ? GetRoutingRotationPixelCenter() : m_pixelRect.Center(), kDoNotChangeZoom); } } else if (m_mode == location::PendingPosition || m_mode == location::NotFollowNoPosition) @@ -525,7 +525,7 @@ void MyPositionController::OnCompassTapped() if (m_mode == location::FollowAndRotate) { ChangeMode(location::Follow); - ChangeModelView(m_position, 0.0, m_centerPixelPosition, kDoNotChangeZoom); + ChangeModelView(m_position, 0.0, m_pixelRect.Center(), kDoNotChangeZoom); } else { @@ -567,7 +567,7 @@ void MyPositionController::UpdateViewport(int zoomLevel) ChangeModelView(m_position, zoomLevel); else if (m_mode == location::FollowAndRotate) ChangeModelView(m_position, m_drawDirection, - m_isInRouting ? m_centerPixelPositionRouting : m_centerPixelPosition, zoomLevel); + m_isInRouting ? GetRoutingRotationPixelCenter() : m_pixelRect.Center(), zoomLevel); } m2::PointD MyPositionController::GetRotationPixelCenter() const @@ -658,7 +658,7 @@ void MyPositionController::ActivateRouting(int zoomLevel) if (IsRotationAvailable()) { ChangeMode(location::FollowAndRotate); - ChangeModelView(m_position, m_drawDirection, m_centerPixelPositionRouting, zoomLevel); + ChangeModelView(m_position, m_drawDirection, GetRoutingRotationPixelCenter(), zoomLevel); } else { @@ -675,7 +675,7 @@ void MyPositionController::DeactivateRouting() m_isInRouting = false; ChangeMode(location::Follow); - ChangeModelView(m_position, 0.0, m_centerPixelPosition, kDoNotChangeZoom); + ChangeModelView(m_position, 0.0, m_pixelRect.Center(), kDoNotChangeZoom); } } diff --git a/drape_frontend/my_position_controller.hpp b/drape_frontend/my_position_controller.hpp index 997daa6f0e..f8516cdd88 100644 --- a/drape_frontend/my_position_controller.hpp +++ b/drape_frontend/my_position_controller.hpp @@ -47,7 +47,7 @@ public: bool isFirstLaunch, bool isRoutingActive); ~MyPositionController(); - void OnNewPixelRect(); + void OnNewViewportRect(); void UpdatePixelPosition(ScreenBase const & screen); void SetListener(ref_ptr<Listener> listener); @@ -153,8 +153,6 @@ private: double m_lastLocationTimestamp; m2::RectD m_pixelRect; - m2::PointD m_centerPixelPositionRouting; - m2::PointD m_centerPixelPosition; double m_positionYOffset; bool m_isVisible; diff --git a/drape_frontend/navigator.cpp b/drape_frontend/navigator.cpp index f695b9917e..08e7685980 100644 --- a/drape_frontend/navigator.cpp +++ b/drape_frontend/navigator.cpp @@ -19,54 +19,54 @@ namespace df { +double const kDefault3dScale = 1.0; + Navigator::Navigator() : m_InAction(false) { } -void Navigator::SetFromRects(m2::AnyRectD const & glbRect, m2::RectD const & pxRect) -{ - m2::RectD const & worldR = df::GetWorldRect(); - - m_Screen.SetFromRects(glbRect, pxRect); - m_Screen = ScaleInto(m_Screen, worldR); - - if (!m_InAction) - { - m_StartScreen.SetFromRects(glbRect, pxRect); - m_StartScreen = ScaleInto(m_StartScreen, worldR); - } -} - -void Navigator::SetFromRect(m2::AnyRectD const & r) +void Navigator::SetFromScreen(ScreenBase const & screen) { VisualParams const & p = VisualParams::Instance(); - SetFromRect(r, p.GetTileSize(), p.GetVisualScale()); + SetFromScreen(screen, p.GetTileSize(), p.GetVisualScale()); } -void Navigator::SetFromRect(m2::AnyRectD const & r, uint32_t tileSize, double visualScale) +void Navigator::SetFromScreen(ScreenBase const & screen, uint32_t tileSize, double visualScale) { - m2::RectD const & worldR = df::GetWorldRect(); + ScreenBase tmp = ScaleInto(screen, df::GetWorldRect()); - ScreenBase tmp = m_Screen; - - tmp.SetFromRect(r); - tmp = ScaleInto(tmp, worldR); if (!CheckMaxScale(tmp, tileSize, visualScale)) { int const scale = scales::GetUpperStyleScale() - 1; - m2::RectD newRect = df::GetRectForDrawScale(scale, r.Center()); - CheckMinMaxVisibleScale(newRect, scale); + m2::RectD newRect = df::GetRectForDrawScale(scale, screen.GetOrg()); + newRect.Scale(m_Screen.GetScale3d()); + CheckMinMaxVisibleScale(newRect, scale, m_Screen.GetScale3d()); tmp = m_Screen; tmp.SetFromRect(m2::AnyRectD(newRect)); + ASSERT(CheckMaxScale(tmp, tileSize, visualScale), ()); } + m_Screen = tmp; if (!m_InAction) m_StartScreen = tmp; } +void Navigator::SetFromRect(m2::AnyRectD const & r) +{ + VisualParams const & p = VisualParams::Instance(); + SetFromRect(r, p.GetTileSize(), p.GetVisualScale()); +} + +void Navigator::SetFromRect(m2::AnyRectD const & r, uint32_t tileSize, double visualScale) +{ + ScreenBase tmp = m_Screen; + tmp.SetFromRect(r); + SetFromScreen(tmp, tileSize, visualScale); +} + void Navigator::CenterViewport(m2::PointD const & p) { // Rounding center point to a pixel boundary to obtain crisp centered picture. @@ -85,25 +85,11 @@ void Navigator::OnSize(int w, int h) { m2::RectD const & worldR = df::GetWorldRect(); - double const fov = m_Screen.GetAngleFOV(); - double const rotation = m_Screen.GetRotationAngle(); - if (m_Screen.isPerspective()) - { - m_Screen.ResetPerspective(); - m_StartScreen.ResetPerspective(); - } - m_Screen.OnSize(0, 0, w, h); m_Screen = ShrinkAndScaleInto(m_Screen, worldR); m_StartScreen.OnSize(0, 0, w, h); m_StartScreen = ShrinkAndScaleInto(m_StartScreen, worldR); - - if (fov != 0.0) - { - m_Screen.ApplyPerspective(rotation, rotation, fov); - m_StartScreen.ApplyPerspective(rotation, rotation, fov); - } } m2::PointD Navigator::GtoP(m2::PointD const & pt) const @@ -194,6 +180,7 @@ bool Navigator::ScaleImpl(m2::PointD const & newPt1, m2::PointD const & newPt2, { m2::PointD const center3d = oldPt1; m2::PointD const center2d = screen.P3dtoP(center3d); + m2::PointD const centerG = screen.PtoG(center2d); m2::PointD const offset = center2d - center3d; math::Matrix<double, 3, 3> const newM = screen.GtoPMatrix() * ScreenBase::CalcTransform(oldPt1 + offset, oldPt2 + offset, @@ -201,6 +188,7 @@ bool Navigator::ScaleImpl(m2::PointD const & newPt1, m2::PointD const & newPt2, doRotateScreen); ScreenBase tmp = screen; tmp.SetGtoPMatrix(newM); + tmp.MatchGandP3d(centerG, center3d); if (!skipMinScaleAndBordersCheck && !CheckMinScale(tmp)) return false; @@ -291,9 +279,18 @@ bool Navigator::IsRotatingDuringScale() const return m_IsRotatingDuringScale; } -void Navigator::Enable3dMode(double currentRotationAngle, double maxRotationAngle, double angleFOV) +void Navigator::SetAutoPerspective(bool enable) { - m_Screen.ApplyPerspective(currentRotationAngle, maxRotationAngle, angleFOV); + m_Screen.SetAutoPerspective(enable); +} + +void Navigator::Enable3dMode() +{ + if (m_Screen.isPerspective()) + return; + double const angle = m_Screen.CalculateAutoPerspectiveAngle(m_Screen.GetScale()); + if (angle > 0) + m_Screen.ApplyPerspective(angle, angle, m_Screen.GetAngleFOV()); } void Navigator::SetRotationIn3dMode(double rotationAngle) @@ -317,36 +314,38 @@ m2::AnyRectD ToRotated(Navigator const & navigator, m2::RectD const & rect) m2::RectD(-dx/2, -dy/2, dx/2, dy/2)); } -void CheckMinGlobalRect(m2::RectD & rect, uint32_t tileSize, double visualScale) +void CheckMinGlobalRect(m2::RectD & rect, uint32_t tileSize, double visualScale, double scale3d) { - m2::RectD const minRect = df::GetRectForDrawScale(scales::GetUpperStyleScale(), rect.Center(), tileSize, visualScale); + m2::RectD minRect = df::GetRectForDrawScale(scales::GetUpperStyleScale(), rect.Center(), tileSize, visualScale); + minRect.Scale(scale3d); if (minRect.IsRectInside(rect)) rect = minRect; } -void CheckMinGlobalRect(m2::RectD & rect) +void CheckMinGlobalRect(m2::RectD & rect, double scale3d) { VisualParams const & p = VisualParams::Instance(); - CheckMinGlobalRect(rect, p.GetTileSize(), p.GetVisualScale()); + CheckMinGlobalRect(rect, p.GetTileSize(), p.GetVisualScale(), scale3d); } void CheckMinMaxVisibleScale(m2::RectD & rect, int maxScale, - uint32_t tileSize, double visualScale) + uint32_t tileSize, double visualScale, double scale3d) { - CheckMinGlobalRect(rect, tileSize, visualScale); + CheckMinGlobalRect(rect, tileSize, visualScale, scale3d); int scale = df::GetDrawTileScale(rect, tileSize, visualScale); if (maxScale != -1 && scale > maxScale) { // limit on passed maximal scale m2::PointD const c = rect.Center(); rect = df::GetRectForDrawScale(maxScale, c, tileSize, visualScale); + rect.Scale(scale3d); } } -void CheckMinMaxVisibleScale(m2::RectD & rect, int maxScale) +void CheckMinMaxVisibleScale(m2::RectD & rect, int maxScale, double scale3d) { VisualParams const & p = VisualParams::Instance(); - CheckMinMaxVisibleScale(rect, maxScale, p.GetTileSize(), p.GetVisualScale()); + CheckMinMaxVisibleScale(rect, maxScale, p.GetTileSize(), p.GetVisualScale(), scale3d); } } // namespace df diff --git a/drape_frontend/navigator.hpp b/drape_frontend/navigator.hpp index ba6773e442..209a7f8e8c 100644 --- a/drape_frontend/navigator.hpp +++ b/drape_frontend/navigator.hpp @@ -10,6 +10,8 @@ namespace df { +extern double const kDefault3dScale; + /// Calculates screen parameters in navigation (dragging, scaling, etc.). class Navigator { @@ -17,9 +19,10 @@ public: Navigator(); void SetFromRect(m2::AnyRectD const & r); - void CenterViewport(m2::PointD const & p); - void SetFromRects(m2::AnyRectD const & glbRect, m2::RectD const & pxRect); void SetFromRect(m2::AnyRectD const & r, uint32_t tileSize, double visualScale); + void SetFromScreen(ScreenBase const & screen); + void SetFromScreen(ScreenBase const & screen, uint32_t tileSize, double visualScale); + void CenterViewport(m2::PointD const & p); void OnSize(int w, int h); @@ -43,7 +46,8 @@ public: void Scale(m2::PointD const & pixelScaleCenter, double factor); bool InAction() const; - void Enable3dMode(double currentRotationAngle, double maxRotationAngle, double angleFOV); + void SetAutoPerspective(bool enable); + void Enable3dMode(); void SetRotationIn3dMode(double rotationAngle); void Disable3dMode(); @@ -75,10 +79,10 @@ private: }; m2::AnyRectD ToRotated(Navigator const & navigator, m2::RectD const & rect); -void CheckMinGlobalRect(m2::RectD & rect, uint32_t tileSize, double visualScale); -void CheckMinGlobalRect(m2::RectD & rect); +void CheckMinGlobalRect(m2::RectD & rect, uint32_t tileSize, double visualScale, double scale3d = kDefault3dScale); +void CheckMinGlobalRect(m2::RectD & rect, double scale3d = kDefault3dScale); -void CheckMinMaxVisibleScale(m2::RectD & rect, int maxScale/* = -1*/, uint32_t tileSize, double visualScale); -void CheckMinMaxVisibleScale(m2::RectD & rect, int maxScale/* = -1*/); +void CheckMinMaxVisibleScale(m2::RectD & rect, int maxScale/* = -1*/, uint32_t tileSize, double visualScale, double scale3d = kDefault3dScale); +void CheckMinMaxVisibleScale(m2::RectD & rect, int maxScale/* = -1*/, double scale3d = kDefault3dScale); } diff --git a/drape_frontend/rule_drawer.cpp b/drape_frontend/rule_drawer.cpp index a3b2ba949a..2a7a3a8102 100644 --- a/drape_frontend/rule_drawer.cpp +++ b/drape_frontend/rule_drawer.cpp @@ -203,10 +203,10 @@ void RuleDrawer::operator()(FeatureType const & f) double const lat = MercatorBounds::YToLat(featureCenter.y); m2::RectD rectMercator = MercatorBounds::MetresToXY(lon, lat, heightInMeters); - areaHeight = m2::PointD(rectMercator.SizeX(), rectMercator.SizeY()).Length(); + areaHeight = (rectMercator.SizeX() + rectMercator.SizeY()) / 2.0; rectMercator = MercatorBounds::MetresToXY(lon, lat, minHeigthInMeters); - areaMinHeight = m2::PointD(rectMercator.SizeX(), rectMercator.SizeY()).Length(); + areaMinHeight = (rectMercator.SizeX() + rectMercator.SizeY()) / 2.0; } bool applyPointStyle = s.PointStyleExists(); diff --git a/drape_frontend/screen_animations.cpp b/drape_frontend/screen_animations.cpp index e4119bbdbd..3f8dcb7824 100644 --- a/drape_frontend/screen_animations.cpp +++ b/drape_frontend/screen_animations.cpp @@ -13,6 +13,12 @@ namespace df string const kPrettyMoveAnim = "PrettyMove"; string const kPrettyFollowAnim = "PrettyFollow"; +drape_ptr<SequenceAnimation> GetPrettyMoveAnimation(ScreenBase const & startScreen, ScreenBase const & endScreen) +{ + return GetPrettyMoveAnimation(startScreen, startScreen.GetScale(), endScreen.GetScale(), + startScreen.GetOrg(), endScreen.GetOrg()); +} + drape_ptr<SequenceAnimation> GetPrettyMoveAnimation(ScreenBase const & screen, m2::AnyRectD const & startRect, m2::AnyRectD const & endRect) { @@ -25,7 +31,7 @@ drape_ptr<SequenceAnimation> GetPrettyMoveAnimation(ScreenBase const & screen, drape_ptr<SequenceAnimation> GetPrettyMoveAnimation(ScreenBase const & screen, double startScale, double endScale, m2::PointD const & startPt, m2::PointD const & endPt) { - double const moveDuration = PositionInterpolator::GetMoveDuration(startPt, endPt, screen); + double const moveDuration = PositionInterpolator::GetMoveDuration(startPt, endPt, screen.PixelRectIn3d(), startScale); double const scaleFactor = moveDuration / kMaxAnimationTimeSec * 2.0; auto sequenceAnim = make_unique_dp<SequenceAnimation>(); @@ -50,28 +56,36 @@ drape_ptr<SequenceAnimation> GetPrettyMoveAnimation(ScreenBase const & screen, d return sequenceAnim; } -drape_ptr<SequenceAnimation> GetPrettyFollowAnimation(ScreenBase const & screen, double startScale, double endScale, - m2::PointD const & startPt, m2::PointD const & userPos, +drape_ptr<SequenceAnimation> GetPrettyFollowAnimation(ScreenBase const & startScreen, m2::PointD const & userPos, double targetScale, double targetAngle, m2::PointD const & endPixelPos) { - double const moveDuration = PositionInterpolator::GetMoveDuration(startPt, userPos, screen); - double const scaleFactor = moveDuration / kMaxAnimationTimeSec * 2.0; - auto sequenceAnim = make_unique_dp<SequenceAnimation>(); sequenceAnim->SetCustomType(kPrettyFollowAnim); + m2::RectD const viewportRect = startScreen.PixelRectIn3d(); + + ScreenBase tmp = startScreen; + tmp.MatchGandP3d(userPos, viewportRect.Center()); + + double const moveDuration = PositionInterpolator::GetMoveDuration(startScreen.GetOrg(), tmp.GetOrg(), startScreen); + double const scaleFactor = moveDuration / kMaxAnimationTimeSec * 2.0; + + tmp = startScreen; + tmp.SetScale(startScreen.GetScale() * scaleFactor); + auto zoomOutAnim = make_unique_dp<MapLinearAnimation>(); - zoomOutAnim->SetScale(startScale, startScale * scaleFactor); + zoomOutAnim->SetScale(startScreen.GetScale(), tmp.GetScale()); zoomOutAnim->SetMaxDuration(kMaxAnimationTimeSec * 0.5); - //TODO (in future): Pass fixed duration instead of screen. + tmp.MatchGandP3d(userPos, viewportRect.Center()); + auto moveAnim = make_unique_dp<MapLinearAnimation>(); - moveAnim->SetMove(startPt, userPos, screen); + moveAnim->SetMove(startScreen.GetOrg(), tmp.GetOrg(), viewportRect, tmp.GetScale()); moveAnim->SetMaxDuration(kMaxAnimationTimeSec); - auto followAnim = make_unique_dp<MapFollowAnimation>(userPos, startScale * scaleFactor, endScale, - screen.GetAngle(), targetAngle, - screen.PixelRect().Center(), endPixelPos, screen.PixelRect()); + auto followAnim = make_unique_dp<MapFollowAnimation>(tmp, userPos, endPixelPos, + tmp.GetScale(), targetScale, + tmp.GetAngle(), targetAngle); followAnim->SetMaxDuration(kMaxAnimationTimeSec * 0.5); sequenceAnim->AddAnimation(move(zoomOutAnim)); @@ -80,6 +94,19 @@ drape_ptr<SequenceAnimation> GetPrettyFollowAnimation(ScreenBase const & screen, return sequenceAnim; } +drape_ptr<MapLinearAnimation> GetRectAnimation(ScreenBase const & startScreen, ScreenBase const & endScreen) +{ + auto anim = make_unique_dp<MapLinearAnimation>(); + + anim->SetRotate(startScreen.GetAngle(), endScreen.GetAngle()); + anim->SetMove(startScreen.GetOrg(), endScreen.GetOrg(), + startScreen.PixelRectIn3d(), (startScreen.GetScale() + endScreen.GetScale()) / 2.0); + anim->SetScale(startScreen.GetScale(), endScreen.GetScale()); + anim->SetMaxScaleDuration(kMaxAnimationTimeSec); + + return anim; +} + drape_ptr<MapLinearAnimation> GetSetRectAnimation(ScreenBase const & screen, m2::AnyRectD const & startRect, m2::AnyRectD const & endRect) { @@ -99,9 +126,8 @@ drape_ptr<MapLinearAnimation> GetSetRectAnimation(ScreenBase const & screen, drape_ptr<MapFollowAnimation> GetFollowAnimation(ScreenBase const & startScreen, m2::PointD const & userPos, double targetScale, double targetAngle, m2::PointD const & endPixelPos) { - auto anim = make_unique_dp<MapFollowAnimation>(userPos, startScreen.GetScale(), targetScale, - startScreen.GetAngle(), targetAngle, - startScreen.GtoP(userPos), endPixelPos, startScreen.PixelRect()); + auto anim = make_unique_dp<MapFollowAnimation>(startScreen, userPos, endPixelPos, startScreen.GetScale(), targetScale, + startScreen.GetAngle(), targetAngle); anim->SetMaxDuration(kMaxAnimationTimeSec); return anim; @@ -113,9 +139,8 @@ drape_ptr<MapScaleAnimation> GetScaleAnimation(ScreenBase const & startScreen, m ScreenBase endScreen = startScreen; ApplyScale(pxScaleCenter, factor, endScreen); - m2::PointD const offset = startScreen.PixelRect().Center() - startScreen.P3dtoP(pxScaleCenter); auto anim = make_unique_dp<MapScaleAnimation>(startScreen.GetScale(), endScreen.GetScale(), - glbScaleCenter, offset); + glbScaleCenter, pxScaleCenter); anim->SetMaxDuration(kMaxAnimationTimeSec); return anim; diff --git a/drape_frontend/screen_animations.hpp b/drape_frontend/screen_animations.hpp index b8a6d83622..9ccda398c1 100644 --- a/drape_frontend/screen_animations.hpp +++ b/drape_frontend/screen_animations.hpp @@ -15,15 +15,16 @@ class MapLinearAnimation; class MapFollowAnimation; class MapScaleAnimation; +drape_ptr<SequenceAnimation> GetPrettyMoveAnimation(ScreenBase const & startScreen, ScreenBase const & endScreen); drape_ptr<SequenceAnimation> GetPrettyMoveAnimation(ScreenBase const & screen, m2::AnyRectD const & startRect, m2::AnyRectD const & endRect); drape_ptr<SequenceAnimation> GetPrettyMoveAnimation(ScreenBase const & screen, double startScale, double endScale, m2::PointD const & startPt, m2::PointD const & endPt); -drape_ptr<SequenceAnimation> GetPrettyFollowAnimation(ScreenBase const & screen, double startScale, double endScale, - m2::PointD const & startPt, m2::PointD const & userPos, - double targetAngle, m2::PointD const & endPixelPos); +drape_ptr<SequenceAnimation> GetPrettyFollowAnimation(ScreenBase const & startScreen, m2::PointD const & userPos, + double targetScale, double targetAngle, m2::PointD const & endPixelPos); +drape_ptr<MapLinearAnimation> GetRectAnimation(ScreenBase const & startScreen, ScreenBase const & endScreen); drape_ptr<MapLinearAnimation> GetSetRectAnimation(ScreenBase const & screen, m2::AnyRectD const & startRect, m2::AnyRectD const & endRect); diff --git a/drape_frontend/screen_operations.cpp b/drape_frontend/screen_operations.cpp index acc083dedc..7e5dd93133 100644 --- a/drape_frontend/screen_operations.cpp +++ b/drape_frontend/screen_operations.cpp @@ -240,13 +240,10 @@ ScreenBase const ShrinkAndScaleInto(ScreenBase const & screen, m2::RectD boundRe bool ApplyScale(m2::PointD const & pixelScaleCenter, double factor, ScreenBase & screen) { m2::PointD const globalScaleCenter = screen.PtoG(screen.P3dtoP(pixelScaleCenter)); - m2::PointD const pixelCenterOffset = screen.PixelRect().Center() - screen.P3dtoP(pixelScaleCenter); ScreenBase tmp = screen; tmp.Scale(factor); - - m2::PointD newCenter = tmp.PtoG(tmp.GtoP(globalScaleCenter) + pixelCenterOffset); - tmp.SetOrg(newCenter); + tmp.MatchGandP3d(globalScaleCenter, pixelScaleCenter); if (!CheckMinScale(tmp)) return false; diff --git a/drape_frontend/user_event_stream.cpp b/drape_frontend/user_event_stream.cpp index 0a7cdc687f..6ad6f1c6c2 100644 --- a/drape_frontend/user_event_stream.cpp +++ b/drape_frontend/user_event_stream.cpp @@ -2,7 +2,6 @@ #include "drape_frontend/animation/linear_animation.hpp" #include "drape_frontend/animation/scale_animation.hpp" #include "drape_frontend/animation/follow_animation.hpp" -#include "drape_frontend/animation/perspective_animation.hpp" #include "drape_frontend/animation/sequence_animation.hpp" #include "drape_frontend/animation_constants.hpp" #include "drape_frontend/animation_system.hpp" @@ -147,12 +146,11 @@ ScreenBase const & UserEventStream::ProcessEvents(bool & modelViewChanged, bool swap(m_events, events); } + m2::RectD const prevPixelRect = GetCurrentScreen().PixelRect(); + m_modelViewChanged = !events.empty() || m_state == STATE_SCALE || m_state == STATE_DRAG; for (UserEvent const & e : events) { - if (m_perspectiveAnimation && FilterEventWhile3dAnimation(e.m_type)) - continue; - bool breakAnim = false; switch (e.m_type) @@ -163,7 +161,6 @@ ScreenBase const & UserEventStream::ProcessEvents(bool & modelViewChanged, bool break; case UserEvent::EVENT_RESIZE: m_navigator.OnSize(e.m_resize.m_width, e.m_resize.m_height); - m_viewportChanged = true; breakAnim = true; TouchCancel(m_touches); if (m_state == STATE_DOUBLE_TAP_HOLD) @@ -174,11 +171,6 @@ ScreenBase const & UserEventStream::ProcessEvents(bool & modelViewChanged, bool TouchCancel(m_touches); break; case UserEvent::EVENT_SET_RECT: - if (m_perspectiveAnimation) - { - m_pendingEvent.reset(new UserEvent(e.m_rectEvent)); - break; - } breakAnim = SetRect(e.m_rectEvent.m_rect, e.m_rectEvent.m_zoom, e.m_rectEvent.m_applyRotation, e.m_rectEvent.m_isAnim); TouchCancel(m_touches); break; @@ -194,8 +186,9 @@ ScreenBase const & UserEventStream::ProcessEvents(bool & modelViewChanged, bool ScreenBase const & screen = m_navigator.Screen(); if (screen.isPerspective()) { - m2::PointD pt = screen.P3dtoP(screen.PixelRectIn3d().Center()); - breakAnim = SetFollowAndRotate(screen.PtoG(pt), pt, e.m_rotate.m_targetAzimut, kDoNotChangeZoom, true); + m2::PointD pt = screen.PixelRectIn3d().Center(); + breakAnim = SetFollowAndRotate(screen.PtoG(screen.P3dtoP(pt)), pt, + e.m_rotate.m_targetAzimut, kDoNotChangeZoom, true); } else { @@ -211,27 +204,8 @@ ScreenBase const & UserEventStream::ProcessEvents(bool & modelViewChanged, bool e.m_followAndRotate.m_isAnim); TouchCancel(m_touches); break; - case UserEvent::EVENT_ENABLE_PERSPECTIVE: - SetEnable3dMode(e.m_enable3dMode.m_rotationAngle, e.m_enable3dMode.m_angleFOV, - e.m_enable3dMode.m_isAnim, e.m_enable3dMode.m_immediatelyStart); - m_discardedFOV = m_discardedAngle = 0.0; - break; - case UserEvent::EVENT_DISABLE_PERSPECTIVE: - SetDisable3dModeAnimation(); - m_discardedFOV = m_discardedAngle = 0.0; - break; - case UserEvent::EVENT_SWITCH_VIEW_MODE: - if (e.m_switchViewMode.m_to2d) - { - m_discardedFOV = m_navigator.Screen().GetAngleFOV(); - m_discardedAngle = m_navigator.Screen().GetRotationAngle(); - SetDisable3dModeAnimation(); - } - else if (m_discardedFOV > 0.0) - { - SetEnable3dMode(m_discardedAngle, m_discardedFOV, true /* isAnim */, true /* immediatelyStart */); - m_discardedFOV = m_discardedAngle = 0.0; - } + case UserEvent::EVENT_AUTO_PERSPECTIVE: + SetAutoPerspective(e.m_autoPerspective.m_isAutoPerspective); break; default: ASSERT(false, ()); @@ -244,21 +218,6 @@ ScreenBase const & UserEventStream::ProcessEvents(bool & modelViewChanged, bool ApplyAnimations(); - if (m_perspectiveAnimation) - { - TouchCancel(m_touches); - } - else - { - if (m_pendingEvent != nullptr && m_pendingEvent->m_type == UserEvent::EVENT_SET_RECT) - { - SetRect(m_pendingEvent->m_rectEvent.m_rect, m_pendingEvent->m_rectEvent.m_zoom, - m_pendingEvent->m_rectEvent.m_applyRotation, m_pendingEvent->m_rectEvent.m_isAnim); - m_pendingEvent.reset(); - m_modelViewChanged = true; - } - } - if (GetValidTouchesCount(m_touches) == 1) { if (m_state == STATE_WAIT_DOUBLE_TAP) @@ -267,10 +226,14 @@ ScreenBase const & UserEventStream::ProcessEvents(bool & modelViewChanged, bool DetectLongTap(m_touches[0]); } + if (m_modelViewChanged) + m_animationSystem.UpdateLastScreen(GetCurrentScreen()); + modelViewChanged = m_modelViewChanged; - viewportChanged = m_viewportChanged; + + double const kEps = 1e-5; + viewportChanged = !m2::IsEqualSize(prevPixelRect, GetCurrentScreen().PixelRect(), kEps, kEps); m_modelViewChanged = false; - m_viewportChanged = false; return m_navigator.Screen(); } @@ -279,31 +242,9 @@ void UserEventStream::ApplyAnimations() { if (m_animationSystem.AnimationExists(Animation::MapPlane)) { - m2::AnyRectD rect; - if (m_animationSystem.GetRect(GetCurrentScreen(), rect)) - m_navigator.SetFromRect(rect); - - Animation::SwitchPerspectiveParams switchPerspective; - if (m_animationSystem.SwitchPerspective(switchPerspective)) - { - if (switchPerspective.m_enable) - { - m_navigator.Enable3dMode(switchPerspective.m_startAngle, switchPerspective.m_endAngle, - switchPerspective.m_angleFOV); - } - else - { - m_navigator.Disable3dMode(); - } - m_viewportChanged = true; - } - - double perspectiveAngle; - if (m_animationSystem.GetPerspectiveAngle(perspectiveAngle) && - GetCurrentScreen().isPerspective()) - { - m_navigator.SetRotationIn3dMode(perspectiveAngle); - } + ScreenBase screen; + if (m_animationSystem.GetScreen(GetCurrentScreen(), screen)) + m_navigator.SetFromScreen(screen); m_modelViewChanged = true; } @@ -361,82 +302,35 @@ bool UserEventStream::SetScale(m2::PointD const & pxScaleCenter, double factor, bool UserEventStream::SetCenter(m2::PointD const & center, int zoom, bool isAnim) { - m2::PointD targetCenter = center; - ang::AngleD angle; - m2::RectD localRect; - - ScreenBase const & currentScreen = GetCurrentScreen(); - - ScreenBase screen = currentScreen; - bool finishIn2d = false; - bool finishIn3d = false; - if (zoom != kDoNotChangeZoom) - { - bool const isScaleAllowableIn3d = IsScaleAllowableIn3d(zoom); - finishIn3d = m_discardedFOV > 0.0 && isScaleAllowableIn3d; - finishIn2d = currentScreen.isPerspective() && !isScaleAllowableIn3d; - - if (finishIn3d) - screen.ApplyPerspective(m_discardedAngle, m_discardedAngle, m_discardedFOV); - else if (finishIn2d) - screen.ResetPerspective(); - } - - double const scale3d = screen.PixelRect().SizeX() / screen.PixelRectIn3d().SizeX(); - + ScreenBase screen = GetCurrentScreen(); if (zoom == kDoNotChangeZoom) { - m2::AnyRectD const r = GetTargetRect(); - angle = r.Angle(); - localRect = r.GetLocalRect(); + GetTargetScreen(screen); + screen.MatchGandP3d(center, screen.PixelRectIn3d().Center()); } else { - angle = screen.GlobalRect().Angle(); - - localRect = df::GetRectForDrawScale(zoom, center); - CheckMinGlobalRect(localRect); - CheckMinMaxVisibleScale(localRect, zoom); - - localRect.Offset(-center); - localRect.Scale(scale3d); - - double const aspectRatio = screen.PixelRect().SizeY() / screen.PixelRect().SizeX(); - if (aspectRatio > 1.0) - localRect.Inflate(0.0, localRect.SizeY() * 0.5 * aspectRatio); - else - localRect.Inflate(localRect.SizeX() * 0.5 / aspectRatio, 0.0); + screen.SetFromParams(center, screen.GetAngle(), GetScale(zoom)); + screen.MatchGandP3d(center, screen.PixelRectIn3d().Center()); } - if (screen.isPerspective()) - { - double const centerOffset3d = localRect.SizeY() * (1.0 - 1.0 / (scale3d * cos(screen.GetRotationAngle()))) * 0.5; - targetCenter = targetCenter.Move(centerOffset3d, angle.cos(), -angle.sin()); - } - - if (finishIn2d || finishIn3d) - { - double const scale = currentScreen.PixelRect().SizeX() / currentScreen.PixelRectIn3d().SizeX(); - double const scaleToCurrent = finishIn2d ? scale : 1.0 / scale3d; + ASSERT_GREATER_OR_EQUAL(zoom, scales::GetUpperWorldScale(), ()); + ASSERT_LESS_OR_EQUAL(zoom, scales::GetUpperStyleScale(), ()); - double const currentGSizeY = localRect.SizeY() * scaleToCurrent; - targetCenter = targetCenter.Move((currentGSizeY - localRect.SizeY()) * 0.5, - angle.cos(), -angle.sin()); - localRect.Scale(scaleToCurrent); - } + ShrinkAndScaleInto(screen, df::GetWorldRect()); - return SetRect(m2::AnyRectD(targetCenter, angle, localRect), isAnim); + return SetScreen(screen, isAnim); } bool UserEventStream::SetRect(m2::RectD rect, int zoom, bool applyRotation, bool isAnim) { - CheckMinGlobalRect(rect); - CheckMinMaxVisibleScale(rect, zoom); + CheckMinGlobalRect(rect, kDefault3dScale); + CheckMinMaxVisibleScale(rect, zoom, kDefault3dScale); m2::AnyRectD targetRect = applyRotation ? ToRotated(m_navigator, rect) : m2::AnyRectD(rect); return SetRect(targetRect, isAnim); } -bool UserEventStream::SetRect(m2::AnyRectD const & rect, bool isAnim) +bool UserEventStream::SetScreen(ScreenBase const & endScreen, bool isAnim) { if (isAnim) { @@ -446,17 +340,16 @@ bool UserEventStream::SetRect(m2::AnyRectD const & rect, bool isAnim) m_listener->OnAnimationStarted(animation); }; - m2::AnyRectD const startRect = GetCurrentRect(); ScreenBase const & screen = GetCurrentScreen(); - drape_ptr<Animation> anim = GetSetRectAnimation(screen, startRect, rect); + drape_ptr<Animation> anim = GetRectAnimation(screen, endScreen); if (!df::IsAnimationAllowed(anim->GetDuration(), screen)) { anim.reset(); - double const moveDuration = PositionInterpolator::GetMoveDuration(startRect.GlobalCenter(), - rect.GlobalCenter(), screen); + double const moveDuration = PositionInterpolator::GetMoveDuration(screen.GetOrg(), + endScreen.GetOrg(), screen); if (moveDuration > kMaxAnimationTimeSec) - anim = GetPrettyMoveAnimation(screen, startRect, rect); + anim = GetPrettyMoveAnimation(screen, endScreen); } if (anim != nullptr) @@ -468,10 +361,19 @@ bool UserEventStream::SetRect(m2::AnyRectD const & rect, bool isAnim) } ResetMapPlaneAnimations(); - m_navigator.SetFromRect(rect); + m_navigator.SetFromScreen(endScreen); return true; } +bool UserEventStream::SetRect(m2::AnyRectD const & rect, bool isAnim) +{ + ScreenBase tmp = GetCurrentScreen(); + tmp.SetFromRects(rect, tmp.PixelRectIn3d()); + tmp.MatchGandP3d(rect.GlobalCenter(), tmp.PixelRectIn3d().Center()); + + return SetScreen(tmp, isAnim); +} + bool UserEventStream::InterruptFollowAnimations(bool force) { Animation const * followAnim = m_animationSystem.FindAnimation<MapFollowAnimation>(Animation::MapFollow); @@ -497,22 +399,24 @@ bool UserEventStream::InterruptFollowAnimations(bool force) bool UserEventStream::SetFollowAndRotate(m2::PointD const & userPos, m2::PointD const & pixelPos, double azimuth, int preferredZoomLevel, bool isAnim) { - // Extract target local rect from current animation or calculate it from preferredZoomLevel - // to preserve final scale. - m2::RectD targetLocalRect; - if (preferredZoomLevel != kDoNotChangeZoom) + ScreenBase const & currentScreen = GetCurrentScreen(); + ScreenBase screen = currentScreen; + + if (preferredZoomLevel == kDoNotChangeZoom) { - ScreenBase newScreen = GetCurrentScreen(); - m2::RectD r = df::GetRectForDrawScale(preferredZoomLevel, m2::PointD::Zero()); - CheckMinGlobalRect(r); - CheckMinMaxVisibleScale(r, preferredZoomLevel); - newScreen.SetFromRect(m2::AnyRectD(r)); - targetLocalRect = newScreen.GlobalRect().GetLocalRect(); + GetTargetScreen(screen); + screen.SetAngle(-azimuth); } else { - targetLocalRect = GetTargetRect().GetLocalRect(); + screen.SetFromParams(userPos, -azimuth, GetScale(preferredZoomLevel)); } + screen.MatchGandP3d(userPos, pixelPos); + + ASSERT_GREATER_OR_EQUAL(preferredZoomLevel, scales::GetUpperWorldScale(), ()); + ASSERT_LESS_OR_EQUAL(preferredZoomLevel, scales::GetUpperStyleScale(), ()); + + ShrinkAndScaleInto(screen, df::GetWorldRect()); if (isAnim) { @@ -527,26 +431,21 @@ bool UserEventStream::SetFollowAndRotate(m2::PointD const & userPos, m2::PointD }; drape_ptr<Animation> anim; - - ScreenBase const & screen = m_navigator.Screen(); - double const targetScale = CalculateScale(screen.PixelRect(), targetLocalRect); - m2::PointD const startPt = GetCurrentRect().GlobalCenter(); - bool const changeZoom = preferredZoomLevel != kDoNotChangeZoom; - - double const moveDuration = PositionInterpolator::GetMoveDuration(startPt, userPos, screen); + double const moveDuration = PositionInterpolator::GetMoveDuration(currentScreen.GetOrg(), screen.GetOrg(), + currentScreen.PixelRectIn3d(), + (currentScreen.GetScale() + screen.GetScale()) / 2.0); if (moveDuration > kMaxAnimationTimeSec) { // Run pretty move animation if we are far from userPos. - double const startScale = CalculateScale(screen.PixelRect(), GetCurrentRect().GetLocalRect()); - anim = GetPrettyFollowAnimation(screen, startScale, targetScale, startPt, userPos, -azimuth, pixelPos); + anim = GetPrettyFollowAnimation(currentScreen, userPos, screen.GetScale(), -azimuth, pixelPos); } else { // Run follow-and-rotate animation. - anim = GetFollowAnimation(screen, userPos, targetScale, -azimuth, pixelPos); + anim = GetFollowAnimation(currentScreen, userPos, screen.GetScale(), -azimuth, pixelPos); } - if (changeZoom) + if (preferredZoomLevel != kDoNotChangeZoom) { anim->SetCouldBeInterrupted(false); anim->SetCouldBeBlended(false); @@ -558,70 +457,18 @@ bool UserEventStream::SetFollowAndRotate(m2::PointD const & userPos, m2::PointD } ResetMapPlaneAnimations(); - m2::PointD const center = MapFollowAnimation::CalculateCenter(m_navigator.Screen(), userPos, pixelPos, -azimuth); - m_navigator.SetFromRect(m2::AnyRectD(center, -azimuth, targetLocalRect)); + m_navigator.SetFromScreen(screen); return true; } -bool UserEventStream::FilterEventWhile3dAnimation(UserEvent::EEventType type) const +void UserEventStream::SetAutoPerspective(bool isAutoPerspective) { - return type != UserEvent::EVENT_RESIZE && type != UserEvent::EVENT_SET_RECT && - type != UserEvent::EVENT_ENABLE_PERSPECTIVE && - type != UserEvent::EVENT_DISABLE_PERSPECTIVE && - type != UserEvent::EVENT_SWITCH_VIEW_MODE; -} - -void UserEventStream::SetEnable3dMode(double maxRotationAngle, double angleFOV, - bool isAnim, bool immediatelyStart) -{ - ResetAnimationsBeforeSwitch3D(); - - if (immediatelyStart) - InterruptFollowAnimations(true /* force */); - - double const startAngle = isAnim ? 0.0 : maxRotationAngle; - double const endAngle = maxRotationAngle; - - auto anim = make_unique_dp<PerspectiveSwitchAnimation>(startAngle, endAngle, angleFOV); - anim->SetOnStartAction([this, startAngle, endAngle, angleFOV](ref_ptr<Animation>) - { - m_perspectiveAnimation = true; - }); - anim->SetOnFinishAction([this](ref_ptr<Animation>) - { - m_perspectiveAnimation = false; - }); - if (immediatelyStart) - m_animationSystem.CombineAnimation(move(anim)); + if (isAutoPerspective) + m_navigator.Enable3dMode(); else - m_animationSystem.PushAnimation(move(anim)); -} - -void UserEventStream::SetDisable3dModeAnimation() -{ - ResetAnimationsBeforeSwitch3D(); - InterruptFollowAnimations(true /* force */); - - if (m_discardedFOV > 0.0 && IsScaleAllowableIn3d(GetDrawTileScale(GetCurrentScreen()))) - { - m_discardedFOV = m_discardedAngle = 0.0; - m_listener->OnPerspectiveSwitchRejected(); - return; - } - - double const startAngle = m_navigator.Screen().GetRotationAngle(); - double const endAngle = 0.0; - - auto anim = make_unique_dp<PerspectiveSwitchAnimation>(startAngle, endAngle, m_navigator.Screen().GetAngleFOV()); - anim->SetOnStartAction([this](ref_ptr<Animation>) - { - m_perspectiveAnimation = true; - }); - anim->SetOnFinishAction([this](ref_ptr<Animation>) - { - m_perspectiveAnimation = false; - }); - m_animationSystem.CombineAnimation(move(anim)); + m_navigator.Disable3dMode(); + m_navigator.SetAutoPerspective(isAutoPerspective); + return; } void UserEventStream::ResetAnimations(Animation::Type animType, bool finishAll) @@ -648,24 +495,21 @@ void UserEventStream::ResetMapPlaneAnimations() ApplyAnimations(); } -void UserEventStream::ResetAnimationsBeforeSwitch3D() +m2::AnyRectD UserEventStream::GetCurrentRect() const { - ResetAnimations(Animation::MapLinear); - ResetAnimations(Animation::Sequence, kPrettyMoveAnim); - ResetAnimations(Animation::MapScale); - ResetAnimations(Animation::MapPerspective, true /* finishAll */); + return m_navigator.Screen().GlobalRect(); } -m2::AnyRectD UserEventStream::GetCurrentRect() const +void UserEventStream::GetTargetScreen(ScreenBase & screen) const { - return m_navigator.Screen().GlobalRect(); + m_animationSystem.GetTargetScreen(m_navigator.Screen(), screen); } m2::AnyRectD UserEventStream::GetTargetRect() const { - m2::AnyRectD targetRect; - m_animationSystem.GetTargetRect(m_navigator.Screen(), targetRect); - return targetRect; + ScreenBase targetScreen; + m_animationSystem.GetTargetScreen(m_navigator.Screen(), targetScreen); + return targetScreen.GlobalRect(); } bool UserEventStream::ProcessTouch(TouchEvent const & touch) @@ -1169,7 +1013,7 @@ void UserEventStream::EndTapDetector(Touch const & touch) void UserEventStream::CancelTapDetector() { TEST_CALL(CANCEL_TAP_DETECTOR); - ASSERT(m_state == STATE_TAP_DETECTION || m_state == STATE_WAIT_DOUBLE_TAP, ()); + ASSERT(m_state == STATE_TAP_DETECTION || m_state == STATE_WAIT_DOUBLE_TAP || m_state == STATE_WAIT_DOUBLE_TAP_HOLD, ()); m_state = STATE_EMPTY; } @@ -1219,7 +1063,7 @@ void UserEventStream::UpdateDoubleTapAndHold(Touch const & touch) TEST_CALL(DOUBLE_TAP_AND_HOLD); ASSERT_EQUAL(m_state, STATE_DOUBLE_TAP_HOLD, ()); float const kPowerModifier = 10.0f; - float const scaleFactor = exp(kPowerModifier * (touch.m_location.y - m_startDoubleTapAndHold.y) / GetCurrentScreen().PixelRect().SizeY()); + float const scaleFactor = exp(kPowerModifier * (touch.m_location.y - m_startDoubleTapAndHold.y) / GetCurrentScreen().PixelRectIn3d().SizeY()); m_startDoubleTapAndHold = touch.m_location; m2::PointD scaleCenter = m_startDragOrg; @@ -1247,11 +1091,6 @@ bool UserEventStream::IsWaitingForActionCompletion() const return m_state != STATE_EMPTY; } -bool UserEventStream::IsInPerspectiveAnimation() const -{ - return m_perspectiveAnimation; -} - void UserEventStream::SetKineticScrollEnabled(bool enabled) { m_kineticScrollEnabled = enabled; diff --git a/drape_frontend/user_event_stream.hpp b/drape_frontend/user_event_stream.hpp index ebb5cab618..c3ad87d6a2 100644 --- a/drape_frontend/user_event_stream.hpp +++ b/drape_frontend/user_event_stream.hpp @@ -145,32 +145,13 @@ struct FollowAndRotateEvent bool m_isAnim; }; -struct EnablePerspectiveEvent +struct SetAutoPerspectiveEvent { - EnablePerspectiveEvent(double rotationAngle, double angleFOV, - bool isAnim, bool immediatelyStart) - : m_isAnim(isAnim) - , m_immediatelyStart(immediatelyStart) - , m_rotationAngle(rotationAngle) - , m_angleFOV(angleFOV) + SetAutoPerspectiveEvent(bool isAutoPerspective) + : m_isAutoPerspective(isAutoPerspective) {} - bool m_isAnim; - bool m_immediatelyStart; - double m_rotationAngle; - double m_angleFOV; -}; - -struct DisablePerspectiveEvent -{ - DisablePerspectiveEvent() {} -}; - -struct SwitchViewModeEvent -{ - SwitchViewModeEvent(bool to2d): m_to2d(to2d) {} - - bool m_to2d; + bool m_isAutoPerspective; }; struct RotateEvent @@ -200,9 +181,7 @@ struct UserEvent EVENT_RESIZE, EVENT_ROTATE, EVENT_FOLLOW_AND_ROTATE, - EVENT_ENABLE_PERSPECTIVE, - EVENT_DISABLE_PERSPECTIVE, - EVENT_SWITCH_VIEW_MODE + EVENT_AUTO_PERSPECTIVE }; UserEvent(TouchEvent const & e) : m_type(EVENT_TOUCH) { m_touchEvent = e; } @@ -213,9 +192,7 @@ struct UserEvent UserEvent(ResizeEvent const & e) : m_type(EVENT_RESIZE) { m_resize = e; } UserEvent(RotateEvent const & e) : m_type(EVENT_ROTATE) { m_rotate = e; } UserEvent(FollowAndRotateEvent const & e) : m_type(EVENT_FOLLOW_AND_ROTATE) { m_followAndRotate = e; } - UserEvent(EnablePerspectiveEvent const & e) : m_type(EVENT_ENABLE_PERSPECTIVE) { m_enable3dMode = e; } - UserEvent(DisablePerspectiveEvent const & e) : m_type(EVENT_DISABLE_PERSPECTIVE) { m_disable3dMode = e; } - UserEvent(SwitchViewModeEvent const & e) : m_type(EVENT_SWITCH_VIEW_MODE) { m_switchViewMode = e; } + UserEvent(SetAutoPerspectiveEvent const & e) : m_type(EVENT_AUTO_PERSPECTIVE) { m_autoPerspective = e; } EEventType m_type; union @@ -228,9 +205,7 @@ struct UserEvent ResizeEvent m_resize; RotateEvent m_rotate; FollowAndRotateEvent m_followAndRotate; - EnablePerspectiveEvent m_enable3dMode; - DisablePerspectiveEvent m_disable3dMode; - SwitchViewModeEvent m_switchViewMode; + SetAutoPerspectiveEvent m_autoPerspective; }; }; @@ -259,7 +234,6 @@ public: virtual void OnAnimatedScaleEnded() = 0; virtual void OnAnimationStarted(ref_ptr<Animation> anim) = 0; - virtual void OnPerspectiveSwitchRejected() = 0; virtual void OnTouchMapAction() = 0; }; @@ -269,9 +243,9 @@ public: ScreenBase const & ProcessEvents(bool & modelViewChanged, bool & viewportChanged); ScreenBase const & GetCurrentScreen() const; + void GetTargetScreen(ScreenBase & screen) const; m2::AnyRectD GetTargetRect() const; bool IsInUserAction() const; - bool IsInPerspectiveAnimation() const; bool IsWaitingForActionCompletion() const; void SetListener(ref_ptr<Listener> listener) { m_listener = listener; } @@ -306,13 +280,10 @@ private: bool SetCenter(m2::PointD const & center, int zoom, bool isAnim); bool SetRect(m2::RectD rect, int zoom, bool applyRotation, bool isAnim); bool SetRect(m2::AnyRectD const & rect, bool isAnim); + bool SetScreen(ScreenBase const & screen, bool isAnim); bool SetFollowAndRotate(m2::PointD const & userPos, m2::PointD const & pixelPos, double azimuth, int preferredZoomLevel, bool isAnim); - - bool FilterEventWhile3dAnimation(UserEvent::EEventType type) const; - void SetEnable3dMode(double maxRotationAngle, double angleFOV, - bool isAnim, bool immediatelyStart); - void SetDisable3dModeAnimation(); + void SetAutoPerspective(bool isAutoPerspective); m2::AnyRectD GetCurrentRect() const; @@ -357,7 +328,6 @@ private: void ResetAnimations(Animation::Type animType, bool finishAll = false); void ResetAnimations(Animation::Type animType, string const & customType, bool finishAll = false); void ResetMapPlaneAnimations(); - void ResetAnimationsBeforeSwitch3D(); bool InterruptFollowAnimations(bool force); list<UserEvent> m_events; @@ -383,12 +353,8 @@ private: AnimationSystem & m_animationSystem; bool m_modelViewChanged = false; - bool m_viewportChanged = false; - bool m_perspectiveAnimation = false; unique_ptr<UserEvent> m_pendingEvent; - double m_discardedFOV = 0.0; - double m_discardedAngle = 0.0; ref_ptr<Listener> m_listener; diff --git a/drape_frontend/visual_params.cpp b/drape_frontend/visual_params.cpp index cf0de06c78..9f134ba03c 100644 --- a/drape_frontend/visual_params.cpp +++ b/drape_frontend/visual_params.cpp @@ -6,6 +6,8 @@ #include "geometry/mercator.hpp" +#include "indexer/scales.hpp" + #include "std/limits.hpp" #include "std/algorithm.hpp" @@ -270,4 +272,14 @@ int GetDrawTileScale(m2::RectD const & r) return GetDrawTileScale(r, p.GetTileSize(), p.GetVisualScale()); } +double GetZoomLevel(double scale) +{ + return my::clamp(fabs(log(scale) / log(2.0)), 1, scales::GetUpperStyleScale()); +} + +double GetScale(double zoomLevel) +{ + return pow(2.0, -zoomLevel); +} + } // namespace df diff --git a/drape_frontend/visual_params.hpp b/drape_frontend/visual_params.hpp index 5e912843d4..b61c723040 100644 --- a/drape_frontend/visual_params.hpp +++ b/drape_frontend/visual_params.hpp @@ -75,4 +75,7 @@ m2::RectD GetRectForDrawScale(double drawScale, m2::PointD const & center); int CalculateTileSize(int screenWidth, int screenHeight); +double GetZoomLevel(double scale); +double GetScale(double zoomLevel); + } // namespace df |