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<SequenceAnimation> GetPrettyFollowAnimation(ScreenBase const & startScreen, m2::PointD const & userPos, double targetScale, double targetAngle, m2::PointD const & endPixelPos) { auto sequenceAnim = make_unique_dp<SequenceAnimation>(); sequenceAnim->SetCustomType(kPrettyFollowAnim); m2::RectD const viewportRect = startScreen.PixelRectIn3d(); ScreenBase tmp = startScreen; tmp.SetAngle(targetAngle); tmp.MatchGandP3d(userPos, viewportRect.Center()); double const moveDuration = PositionInterpolator::GetMoveDuration(startScreen.GetOrg(), tmp.GetOrg(), startScreen); ASSERT_GREATER(moveDuration, 0.0, ()); double const scaleFactor = moveDuration / kMaxAnimationTimeSec * 2.0; tmp = startScreen; if (moveDuration > 0.0) { tmp.SetScale(startScreen.GetScale() * scaleFactor); auto zoomOutAnim = make_unique_dp<MapLinearAnimation>(); zoomOutAnim->SetScale(startScreen.GetScale(), tmp.GetScale()); zoomOutAnim->SetMaxDuration(kMaxAnimationTimeSec * 0.5); sequenceAnim->AddAnimation(move(zoomOutAnim)); tmp.MatchGandP3d(userPos, viewportRect.Center()); auto moveAnim = make_unique_dp<MapLinearAnimation>(); moveAnim->SetMove(startScreen.GetOrg(), tmp.GetOrg(), viewportRect, tmp.GetScale()); moveAnim->SetMaxDuration(kMaxAnimationTimeSec); sequenceAnim->AddAnimation(move(moveAnim)); } auto followAnim = make_unique_dp<MapFollowAnimation>(tmp, userPos, endPixelPos, tmp.GetScale(), targetScale, tmp.GetAngle(), targetAngle, false /* isAutoZoom */); followAnim->SetMaxDuration(kMaxAnimationTimeSec * 0.5); sequenceAnim->AddAnimation(move(followAnim)); return sequenceAnim; }
void Navigator::SetFromScreen(ScreenBase const & screen, uint32_t tileSize, double visualScale) { ScreenBase tmp = ScaleInto(screen, df::GetWorldRect()); if (!CheckMaxScale(tmp, tileSize, visualScale)) { int const scale = scales::GetUpperStyleScale() - 1; 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), ()); }
bool MapFollowAnimation::GetProperty(TObject object, TProperty property, bool targetValue, PropertyValue & value) const { if (property == Animation::Position) { ScreenBase tmp = AnimationSystem::Instance().GetLastScreen(); if (targetValue) { tmp.SetFromParams(m_globalPosition, m_angleInterpolator.GetTargetAngle(), m_isAutoZoom ? m_scaleInterpolator.GetScale() : m_scaleInterpolator.GetTargetScale()); tmp.MatchGandP3d(m_globalPosition, m_endPixelPosition); } else { 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) { value = PropertyValue(targetValue ? m_angleInterpolator.GetTargetAngle() : m_angleInterpolator.GetAngle()); return true; } if (property == Animation::Scale) { value = PropertyValue((targetValue && !m_isAutoZoom) ? m_scaleInterpolator.GetTargetScale() : m_scaleInterpolator.GetScale()); return true; } ASSERT(false, ("Wrong property:", property)); return false; }
ScreenBase const ShrinkAndScaleInto(ScreenBase const & screen, m2::RectD boundRect) { ReduceRectHack(boundRect); ScreenBase res = screen; m2::RectD globalRect = res.ClipRect(); m2::PointD newOrg = res.GetOrg(); double scale = 1; double offs = 0; if (globalRect.minX() < boundRect.minX()) { offs = boundRect.minX() - globalRect.minX(); globalRect.Offset(offs, 0); newOrg.x += offs; if (globalRect.maxX() > boundRect.maxX()) { double k = boundRect.SizeX() / globalRect.SizeX(); scale /= k; /// scaling always occur pinpointed to the rect center... globalRect.Scale(k); /// ...so we should shift a rect after scale globalRect.Offset(boundRect.minX() - globalRect.minX(), 0); } } if (globalRect.maxX() > boundRect.maxX()) { offs = boundRect.maxX() - globalRect.maxX(); globalRect.Offset(offs, 0); newOrg.x += offs; if (globalRect.minX() < boundRect.minX()) { double k = boundRect.SizeX() / globalRect.SizeX(); scale /= k; globalRect.Scale(k); globalRect.Offset(boundRect.maxX() - globalRect.maxX(), 0); } } if (globalRect.minY() < boundRect.minY()) { offs = boundRect.minY() - globalRect.minY(); globalRect.Offset(0, offs); newOrg.y += offs; if (globalRect.maxY() > boundRect.maxY()) { double k = boundRect.SizeY() / globalRect.SizeY(); scale /= k; globalRect.Scale(k); globalRect.Offset(0, boundRect.minY() - globalRect.minY()); } } if (globalRect.maxY() > boundRect.maxY()) { offs = boundRect.maxY() - globalRect.maxY(); globalRect.Offset(0, offs); newOrg.y += offs; if (globalRect.minY() < boundRect.minY()) { double k = boundRect.SizeY() / globalRect.SizeY(); scale /= k; globalRect.Scale(k); globalRect.Offset(0, boundRect.maxY() - globalRect.maxY()); } } res.SetOrg(globalRect.Center()); res.Scale(scale); return res; }