From 4da09701875359b00d81ab00a09c5ddb70a7c83e Mon Sep 17 00:00:00 2001 From: "r.kuznetsov" Date: Fri, 22 May 2015 13:52:04 +0300 Subject: [PATCH] Added opacity animation --- drape/shaders/button_fragment_shader.fsh | 7 ++- drape/shaders/line_fragment_shader.fsh | 2 + drape/shaders/text_fragment_shader.fsh | 2 + drape/shaders/texturing_fragment_shader.fsh | 2 + .../animation/base_interpolator.hpp | 2 +- .../animation/opacity_animation.cpp | 21 +++++++ .../animation/opacity_animation.hpp | 26 +++++++++ drape_frontend/drape_frontend.pro | 2 + drape_frontend/frontend_renderer.cpp | 7 +++ drape_frontend/render_group.cpp | 58 ++++++++++++------- drape_frontend/render_group.hpp | 20 ++++--- drape_gui/shape.cpp | 1 + iphone/Maps/Classes/MapViewController.mm | 4 +- map/framework.cpp | 12 ++-- map/framework.hpp | 6 +- qt/draw_widget.cpp | 29 +++++++--- qt/draw_widget.hpp | 3 + qt/mainwindow.cpp | 4 +- 18 files changed, 155 insertions(+), 53 deletions(-) create mode 100644 drape_frontend/animation/opacity_animation.cpp create mode 100644 drape_frontend/animation/opacity_animation.hpp diff --git a/drape/shaders/button_fragment_shader.fsh b/drape/shaders/button_fragment_shader.fsh index c2db173581..9a704f9c87 100644 --- a/drape/shaders/button_fragment_shader.fsh +++ b/drape/shaders/button_fragment_shader.fsh @@ -1,9 +1,12 @@ uniform vec4 u_color; +uniform float u_opacity; void main(void) { - if (u_color.a < 0.1) + vec4 color = u_color; + if (color.a < 0.1) discard; - gl_FragColor = u_color; + color.a *= u_opacity; + gl_FragColor = color; } diff --git a/drape/shaders/line_fragment_shader.fsh b/drape/shaders/line_fragment_shader.fsh index 8c17753893..faa7afa94d 100644 --- a/drape/shaders/line_fragment_shader.fsh +++ b/drape/shaders/line_fragment_shader.fsh @@ -4,6 +4,7 @@ varying vec2 v_dxdy; uniform sampler2D u_colorTex; uniform sampler2D u_maskTex; +uniform float u_opacity; void main(void) { @@ -15,5 +16,6 @@ void main(void) if (mask < 0.1 || domen > 1.0) discard; + color.a *= u_opacity; gl_FragColor = color; } diff --git a/drape/shaders/text_fragment_shader.fsh b/drape/shaders/text_fragment_shader.fsh index fe1d2f3de4..a3757e267f 100755 --- a/drape/shaders/text_fragment_shader.fsh +++ b/drape/shaders/text_fragment_shader.fsh @@ -5,6 +5,7 @@ varying vec2 v_maskTexCoord; uniform sampler2D u_colorTex; uniform sampler2D u_maskTex; +uniform float u_opacity; const lowp float OUTLINE_MIN_VALUE0 = 0.41; const lowp float OUTLINE_MIN_VALUE1 = 0.565; @@ -56,5 +57,6 @@ void main (void) else finalColor = without_outline(base, 1.0 - alpha); + finalColor.a *= u_opacity; gl_FragColor = finalColor; } diff --git a/drape/shaders/texturing_fragment_shader.fsh b/drape/shaders/texturing_fragment_shader.fsh index 459b4dbfd5..8cce8ee43e 100644 --- a/drape/shaders/texturing_fragment_shader.fsh +++ b/drape/shaders/texturing_fragment_shader.fsh @@ -1,4 +1,5 @@ uniform sampler2D u_colorTex; +uniform float u_opacity; varying vec2 v_colorTexCoords; @@ -8,5 +9,6 @@ void main(void) if (finalColor.a < 0.1) discard; + finalColor.a *= u_opacity; gl_FragColor = finalColor; } diff --git a/drape_frontend/animation/base_interpolator.hpp b/drape_frontend/animation/base_interpolator.hpp index 33a0dbf53a..d6a127863f 100644 --- a/drape_frontend/animation/base_interpolator.hpp +++ b/drape_frontend/animation/base_interpolator.hpp @@ -10,7 +10,7 @@ public: virtual ~BaseInterpolator(); bool IsFinished() const; - void Advance(double elapsedSeconds); + virtual void Advance(double elapsedSeconds); protected: double GetT() const; diff --git a/drape_frontend/animation/opacity_animation.cpp b/drape_frontend/animation/opacity_animation.cpp new file mode 100644 index 0000000000..04d42524d4 --- /dev/null +++ b/drape_frontend/animation/opacity_animation.cpp @@ -0,0 +1,21 @@ +#include "drape_frontend/animation/opacity_animation.hpp" +#include "drape_frontend/animation/interpolations.hpp" + +namespace df +{ + +OpacityAnimation::OpacityAnimation(double duration, double startOpacity, double endOpacity) + : BaseInterpolator(duration) + , m_opacity(1.0) + , m_startOpacity(startOpacity) + , m_endOpacity(endOpacity) +{ +} + +void OpacityAnimation::Advance(double elapsedSeconds) +{ + TBase::Advance(elapsedSeconds); + m_opacity = InterpolateDouble(m_startOpacity, m_endOpacity, GetT()); +} + +} diff --git a/drape_frontend/animation/opacity_animation.hpp b/drape_frontend/animation/opacity_animation.hpp new file mode 100644 index 0000000000..a2798fc469 --- /dev/null +++ b/drape_frontend/animation/opacity_animation.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include "drape_frontend/animation/base_interpolator.hpp" + +#include "drape/uniform_values_storage.hpp" + +namespace df +{ + +class OpacityAnimation : public BaseInterpolator +{ + using TBase = BaseInterpolator; + +public: + OpacityAnimation(double duration, double startOpacity, double endOpacity); + + void Advance(double elapsedSeconds) override; + double GetOpacity() const { return m_opacity; } + +private: + double m_startOpacity; + double m_endOpacity; + double m_opacity; +}; + +} diff --git a/drape_frontend/drape_frontend.pro b/drape_frontend/drape_frontend.pro index e15d1b97c6..4d226bb61a 100755 --- a/drape_frontend/drape_frontend.pro +++ b/drape_frontend/drape_frontend.pro @@ -13,6 +13,7 @@ SOURCES += \ animation/interpolation_holder.cpp \ animation/interpolations.cpp \ animation/model_view_animation.cpp \ + animation/opacity_animation.cpp \ apply_feature_functors.cpp \ area_shape.cpp \ backend_renderer.cpp \ @@ -57,6 +58,7 @@ HEADERS += \ animation/interpolation_holder.hpp \ animation/interpolations.hpp \ animation/model_view_animation.hpp \ + animation/opacity_animation.hpp \ apply_feature_functors.hpp \ area_shape.hpp \ backend_renderer.hpp \ diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index c49710f161..219dd69eb8 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -289,7 +289,10 @@ void FrontendRenderer::OnRemoveTile(TileKey const & tileKey) for(auto const & group : m_renderGroups) { if (group->GetTileKey() == tileKey) + { group->DeleteLater(); + group->Disappear(); + } } auto removePredicate = [&tileKey](drape_ptr const & group) @@ -353,6 +356,7 @@ void FrontendRenderer::RenderScene(ScreenBase const & modelView) dp::GLState::DepthLayer prevLayer = dp::GLState::GeometryLayer; for (drape_ptr const & group : m_renderGroups) { + group->UpdateAnimation(); dp::GLState const & state = group->GetState(); dp::GLState::DepthLayer layer = state.GetDepthLayer(); if (prevLayer != layer && layer == dp::GLState::OverlayLayer) @@ -367,6 +371,7 @@ void FrontendRenderer::RenderScene(ScreenBase const & modelView) ref_ptr program = m_gpuProgramManager->GetProgram(state.GetProgramIndex()); program->Bind(); ApplyUniforms(m_generalUniforms, program); + ApplyUniforms(group->GetUniforms(), program); ApplyState(state, program); group->Render(modelView); @@ -377,12 +382,14 @@ void FrontendRenderer::RenderScene(ScreenBase const & modelView) for (drape_ptr const & group : m_userMarkRenderGroups) { ASSERT(group.get() != nullptr, ()); + group->UpdateAnimation(); if (m_userMarkVisibility.find(group->GetTileKey()) != m_userMarkVisibility.end()) { dp::GLState const & state = group->GetState(); ref_ptr program = m_gpuProgramManager->GetProgram(state.GetProgramIndex()); program->Bind(); ApplyUniforms(m_generalUniforms, program); + ApplyUniforms(group->GetUniforms(), program); ApplyState(state, program); group->Render(modelView); } diff --git a/drape_frontend/render_group.cpp b/drape_frontend/render_group.cpp index 6121199eb7..8998f9793c 100755 --- a/drape_frontend/render_group.cpp +++ b/drape_frontend/render_group.cpp @@ -8,6 +8,38 @@ namespace df { +void BaseRenderGroup::UpdateAnimation() +{ + double opactity = 1.0; + if (m_disappearAnimation != nullptr) + opactity = m_disappearAnimation->GetOpacity(); + + m_uniforms.SetFloatValue("u_opacity", opactity); +} + +double BaseRenderGroup::GetOpacity() const +{ + if (m_disappearAnimation != nullptr) + return m_disappearAnimation->GetOpacity(); + + return 1.0; +} + +bool BaseRenderGroup::IsAnimating() const +{ + if (m_disappearAnimation == nullptr || m_disappearAnimation->IsFinished()) + return false; + + return true; +} + +void BaseRenderGroup::Disappear() +{ + m_disappearAnimation = make_unique(0.25 /* duration */, + 1.0 /* startOpacity */, + 0.0 /* endOpacity */); +} + RenderGroup::RenderGroup(dp::GLState const & state, df::TileKey const & tileKey) : TBase(state, tileKey) , m_pendingOnDelete(false) @@ -33,7 +65,6 @@ void RenderGroup::CollectOverlay(ref_ptr tree) void RenderGroup::Render(ScreenBase const & screen) { - ASSERT(m_pendingOnDelete == false, ()); for(drape_ptr & renderBucket : m_renderBuckets) renderBucket->Render(screen); } @@ -53,26 +84,11 @@ bool RenderGroup::IsLess(RenderGroup const & other) const return m_state < other.m_state; } -RenderGroupComparator::RenderGroupComparator() - : m_needGroupMergeOperation(false) - , m_needBucketsMergeOperation(false) -{ -} - -void RenderGroupComparator::ResetInternalState() -{ - m_needBucketsMergeOperation = false; - m_needGroupMergeOperation = false; -} - bool RenderGroupComparator::operator()(drape_ptr const & l, drape_ptr const & r) { dp::GLState const & lState = l->GetState(); dp::GLState const & rState = r->GetState(); - TileKey const & lKey = l->GetTileKey(); - TileKey const & rKey = r->GetTileKey(); - if (!l->IsPendingOnDelete() && l->IsEmpty()) l->DeleteLater(); @@ -82,11 +98,13 @@ bool RenderGroupComparator::operator()(drape_ptr const & l, drape_p bool lPendingOnDelete = l->IsPendingOnDelete(); bool rPendingOnDelete = r->IsPendingOnDelete(); - if (lState == rState && lKey == rKey && !lPendingOnDelete) - m_needGroupMergeOperation = true; - if (rPendingOnDelete == lPendingOnDelete) - return lState < rState; + { + if (l->GetOpacity() == r->GetOpacity()) + return lState < rState; + else + return l->GetOpacity() > r->GetOpacity(); + } if (rPendingOnDelete) return true; diff --git a/drape_frontend/render_group.hpp b/drape_frontend/render_group.hpp index 0edc99e9c7..810e75fdbe 100755 --- a/drape_frontend/render_group.hpp +++ b/drape_frontend/render_group.hpp @@ -1,5 +1,6 @@ #pragma once +#include "drape_frontend/animation/opacity_animation.hpp" #include "drape_frontend/tile_utils.hpp" #include "drape/pointers.hpp" @@ -25,9 +26,18 @@ public: dp::GLState const & GetState() const { return m_state; } TileKey const & GetTileKey() const { return m_tileKey; } + dp::UniformValuesStorage const & GetUniforms() const { return m_uniforms; } + + double GetOpacity() const; + void UpdateAnimation(); + bool IsAnimating() const; + + void Disappear(); protected: dp::GLState m_state; + dp::UniformValuesStorage m_uniforms; + unique_ptr m_disappearAnimation; private: TileKey m_tileKey; @@ -49,7 +59,7 @@ public: bool IsEmpty() const { return m_renderBuckets.empty(); } void DeleteLater() const { m_pendingOnDelete = true; } - bool IsPendingOnDelete() const { return m_pendingOnDelete; } + bool IsPendingOnDelete() const { return m_pendingOnDelete && !IsAnimating(); } bool IsLess(RenderGroup const & other) const; @@ -65,15 +75,7 @@ private: class RenderGroupComparator { public: - RenderGroupComparator(); - - void ResetInternalState(); - bool operator()(drape_ptr const & l, drape_ptr const & r); - -private: - bool m_needGroupMergeOperation; - bool m_needBucketsMergeOperation; }; class UserMarkRenderGroup : public BaseRenderGroup diff --git a/drape_gui/shape.cpp b/drape_gui/shape.cpp index b8c1a5517f..2f0a928827 100644 --- a/drape_gui/shape.cpp +++ b/drape_gui/shape.cpp @@ -80,6 +80,7 @@ void ShapeRenderer::Render(ScreenBase const & screen, ref_ptrScale(Framework::SCALE_MAG); + m_framework->Scale(Framework::SCALE_MAG, true); } void DrawWidget::ScaleMinus() { - m_framework->Scale(Framework::SCALE_MIN); + m_framework->Scale(Framework::SCALE_MIN, true); } void DrawWidget::ScalePlusLight() { - m_framework->Scale(Framework::SCALE_MAG_LIGHT); + m_framework->Scale(Framework::SCALE_MAG_LIGHT, true); } void DrawWidget::ScaleMinusLight() { - m_framework->Scale(Framework::SCALE_MIN_LIGHT); + m_framework->Scale(Framework::SCALE_MIN_LIGHT, true); } void DrawWidget::ShowAll() @@ -152,10 +155,20 @@ bool IsLocationEmulation(QMouseEvent * e) { double const factor = m_pScale->GetScaleFactor(); if (factor != 1.0) - m_framework->Scale(factor); + m_framework->Scale(factor, false); } } + void DrawWidget::SliderPressed() + { + m_enableScaleUpdate = false; + } + + void DrawWidget::SliderReleased() + { + m_enableScaleUpdate = true; + } + void DrawWidget::OnActivateMark(unique_ptr pCopy) { UserMark const * pMark = pCopy->GetUserMark(); @@ -213,7 +226,7 @@ bool IsLocationEmulation(QMouseEvent * e) { TBase::mouseDoubleClickEvent(e); if (IsLeftButton(e)) - m_framework->Scale(Framework::SCALE_MAG_LIGHT, GetDevicePoint(e)); + m_framework->Scale(Framework::SCALE_MAG_LIGHT, GetDevicePoint(e), true); } void DrawWidget::mouseMoveEvent(QMouseEvent * e) @@ -385,7 +398,7 @@ bool IsLocationEmulation(QMouseEvent * e) void DrawWidget::UpdateScaleControl() { - if (m_pScale && isExposed()) + if (m_pScale && isExposed() && m_enableScaleUpdate) { // don't send ScaleChanged m_pScale->SetPosWithBlockedSignals(m_framework->GetDrawScale()); diff --git a/qt/draw_widget.hpp b/qt/draw_widget.hpp index b2e1c2db7d..a4dd8b7e4c 100644 --- a/qt/draw_widget.hpp +++ b/qt/draw_widget.hpp @@ -33,6 +33,8 @@ namespace qt void ShowAll(); void ScaleChanged(int action); + void SliderPressed(); + void SliderReleased(); public: DrawWidget(); @@ -95,6 +97,7 @@ namespace qt m2::PointD GetDevicePoint(QMouseEvent * e) const; QScaleSlider * m_pScale; + bool m_enableScaleUpdate; bool m_emulatingLocation; diff --git a/qt/mainwindow.cpp b/qt/mainwindow.cpp index c1d892a1b9..841623bd23 100644 --- a/qt/mainwindow.cpp +++ b/qt/mainwindow.cpp @@ -61,12 +61,12 @@ MainWindow::MainWindow() : m_locationService(CreateDesktopLocationService(*this) format.setMajorVersion(3); format.setMinorVersion(2); - format.setAlphaBufferSize(8); + format.setAlphaBufferSize(0); format.setBlueBufferSize(8); format.setGreenBufferSize(8); format.setRedBufferSize(8); format.setStencilBufferSize(0); - format.setSamples(8); + format.setSamples(0); format.setSwapBehavior(QSurfaceFormat::DoubleBuffer); format.setSwapInterval(1); format.setDepthBufferSize(16);