From eba6b4900534aab61e520ee15f99f7a4a8d1b8a5 Mon Sep 17 00:00:00 2001 From: ExMix Date: Thu, 4 Jun 2015 20:41:27 +0300 Subject: [PATCH] [drape] object selection --- .../animation/show_hide_animation.cpp | 98 +++++++++++ .../animation/show_hide_animation.hpp | 39 ++++ drape_frontend/backend_renderer.cpp | 8 +- drape_frontend/drape_engine.cpp | 14 ++ drape_frontend/drape_engine.hpp | 3 + drape_frontend/drape_frontend.pro | 8 +- drape_frontend/frontend_renderer.cpp | 84 +++++++-- drape_frontend/frontend_renderer.hpp | 6 +- drape_frontend/message.hpp | 3 +- drape_frontend/message_subclasses.hpp | 33 +++- drape_frontend/my_position.cpp | 15 +- drape_frontend/my_position.hpp | 17 +- drape_frontend/render_node.cpp | 43 +++++ drape_frontend/render_node.hpp | 33 ++++ drape_frontend/selection_shape.cpp | 166 ++++++++++++++++++ drape_frontend/selection_shape.hpp | 55 ++++++ map/framework.cpp | 14 ++ qt/draw_widget.cpp | 4 + 18 files changed, 591 insertions(+), 52 deletions(-) create mode 100644 drape_frontend/animation/show_hide_animation.cpp create mode 100644 drape_frontend/animation/show_hide_animation.hpp create mode 100644 drape_frontend/render_node.cpp create mode 100644 drape_frontend/render_node.hpp create mode 100644 drape_frontend/selection_shape.cpp create mode 100644 drape_frontend/selection_shape.hpp diff --git a/drape_frontend/animation/show_hide_animation.cpp b/drape_frontend/animation/show_hide_animation.cpp new file mode 100644 index 0000000000..07afd0d4e1 --- /dev/null +++ b/drape_frontend/animation/show_hide_animation.cpp @@ -0,0 +1,98 @@ +#include "show_hide_animation.hpp" + +#include "base_interpolator.hpp" + +namespace df +{ + +class ShowHideAnimation::ShowHideInterpolator : public BaseInterpolator +{ +public: + ShowHideInterpolator(ShowHideAnimation::EState & state, double startT, double endT, double duration) + : BaseInterpolator(duration) + , m_state(state) + , m_startT(startT) + , m_endT(endT) + { + m_state = m_endT > m_startT ? ShowHideAnimation::STATE_SHOW_DIRECTION : ShowHideAnimation::STATE_HIDE_DIRECTION; + } + + void Advance(double elapsedSeconds) override + { + BaseInterpolator::Advance(elapsedSeconds); + if (IsFinished()) + m_state = m_endT > m_startT ? ShowHideAnimation::STATE_VISIBLE : ShowHideAnimation::STATE_INVISIBLE; + } + + double GetCurrentT() const + { + return m_startT + (m_endT - m_startT) * GetT(); + } + +private: + ShowHideAnimation::EState & m_state; + double m_startT; + double m_endT; +}; + +ShowHideAnimation::ShowHideAnimation(bool isInitialiVisible, double fullDuraction) + : m_state(isInitialiVisible ? STATE_VISIBLE : STATE_INVISIBLE) + , m_fullDuration(fullDuraction) +{ +} + +ShowHideAnimation::~ShowHideAnimation() +{ + m_interpolator.reset(); +} + +void ShowHideAnimation::Show() +{ + RefreshInterpolator({ STATE_VISIBLE, STATE_SHOW_DIRECTION }, 1.0); +} + +void ShowHideAnimation::Hide() +{ + //RefreshInterpolator({ STATE_INVISIBLE, STATE_HIDE_DIRECTION }, 0.0); + EState state = GetState(); + if (state == STATE_VISIBLE || state == STATE_SHOW_DIRECTION) + { + m_state = STATE_INVISIBLE; + m_interpolator.reset(); + } +} + +ShowHideAnimation::EState ShowHideAnimation::GetState() const +{ + return m_state; +} + +double ShowHideAnimation::GetT() const +{ + if (m_interpolator) + return m_interpolator->GetCurrentT(); + + ASSERT(m_state != STATE_SHOW_DIRECTION, ()); + ASSERT(m_state != STATE_HIDE_DIRECTION, ()); + + return m_state == STATE_VISIBLE ? 1.0 : 0.0; +} + +bool ShowHideAnimation::IsFinished() const +{ + return m_interpolator == nullptr || m_interpolator->IsFinished(); +} + +void ShowHideAnimation::RefreshInterpolator(array validStates, double endValue) +{ + EState state = GetState(); + if (state == validStates[0] || state == validStates[1]) + return; + + double start = GetT(); + double end = endValue; + double duration = (end - start) * m_fullDuration; + m_interpolator.reset(new ShowHideInterpolator(m_state, start, end, duration)); +} + +} // namespace df diff --git a/drape_frontend/animation/show_hide_animation.hpp b/drape_frontend/animation/show_hide_animation.hpp new file mode 100644 index 0000000000..7a72b63a29 --- /dev/null +++ b/drape_frontend/animation/show_hide_animation.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include "drape/pointers.hpp" + +#include "std/array.hpp" + +namespace df +{ + +class ShowHideAnimation +{ +public: + enum EState + { + STATE_INVISIBLE, + STATE_VISIBLE, + STATE_SHOW_DIRECTION, + STATE_HIDE_DIRECTION + }; + + ShowHideAnimation(bool isInitialiVisible, double fullDuraction); + ~ShowHideAnimation(); + + void Show(); + void Hide(); + EState GetState() const; + double GetT() const; + bool IsFinished() const; + +private: + void RefreshInterpolator(array validStates, double endValue); + class ShowHideInterpolator; + + drape_ptr m_interpolator; + ShowHideAnimation::EState m_state; + double m_fullDuration; +}; + +} // namespace df diff --git a/drape_frontend/backend_renderer.cpp b/drape_frontend/backend_renderer.cpp index 83b80d9bdf..41c0b3e659 100644 --- a/drape_frontend/backend_renderer.cpp +++ b/drape_frontend/backend_renderer.cpp @@ -213,10 +213,10 @@ void BackendRenderer::InitGLDependentResource() m_texMng->Init(params); - drape_ptr position = make_unique_dp(m_texMng); - m_commutator->PostMessage(ThreadsCommutator::RenderThread, - make_unique_dp(move(position)), - MessagePriority::High); + drape_ptr msg = make_unique_dp(make_unique_dp(m_texMng), + make_unique_dp(m_texMng)); + + m_commutator->PostMessage(ThreadsCommutator::RenderThread, move(msg), MessagePriority::High); } void BackendRenderer::FlushGeometry(drape_ptr && message) diff --git a/drape_frontend/drape_engine.cpp b/drape_frontend/drape_engine.cpp index 6a7b3e61d3..abe7a9f681 100644 --- a/drape_frontend/drape_engine.cpp +++ b/drape_frontend/drape_engine.cpp @@ -283,4 +283,18 @@ FeatureID DrapeEngine::GetVisiblePOI(m2::PointD const & glbPoint) return result; } +void DrapeEngine::SelectObject(SelectionShape::ESelectedObject obj, m2::PointD const & pt) +{ + m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread, + make_unique_dp(obj, pt), + MessagePriority::High); +} + +void DrapeEngine::DeselectObject() +{ + m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread, + make_unique_dp(SelectObjectMessage::DismissTag()), + MessagePriority::High); +} + } // namespace df diff --git a/drape_frontend/drape_engine.hpp b/drape_frontend/drape_engine.hpp index c3ea78ab19..5f5a7e0869 100644 --- a/drape_frontend/drape_engine.hpp +++ b/drape_frontend/drape_engine.hpp @@ -3,6 +3,7 @@ #include "drape_frontend/backend_renderer.hpp" #include "drape_frontend/frontend_renderer.hpp" #include "drape_frontend/threads_commutator.hpp" +#include "drape_frontend/selection_shape.hpp" #include "drape/pointers.hpp" #include "drape/texture_manager.hpp" @@ -89,6 +90,8 @@ public: void SetUserPositionListener(TUserPositionChangedFn const & fn); FeatureID GetVisiblePOI(m2::PointD const & glbPoint); + void SelectObject(SelectionShape::ESelectedObject obj, m2::PointD const & pt); + void DeselectObject(); private: void AddUserEvent(UserEvent const & e); diff --git a/drape_frontend/drape_frontend.pro b/drape_frontend/drape_frontend.pro index 4d226bb61a..7badf3de55 100755 --- a/drape_frontend/drape_frontend.pro +++ b/drape_frontend/drape_frontend.pro @@ -6,7 +6,7 @@ ROOT_DIR = .. include($$ROOT_DIR/common.pri) INCLUDEPATH *= $$ROOT_DIR/3party/protobuf/src -DEFINES += DRAW_INFO +#DEFINES += DRAW_INFO SOURCES += \ animation/base_interpolator.cpp \ @@ -52,6 +52,9 @@ SOURCES += \ user_marks_provider.cpp \ viewport.cpp \ visual_params.cpp \ + selection_shape.cpp \ + animation/show_hide_animation.cpp \ + render_node.cpp HEADERS += \ animation/base_interpolator.hpp \ @@ -102,3 +105,6 @@ HEADERS += \ user_marks_provider.hpp \ viewport.hpp \ visual_params.hpp \ + selection_shape.hpp \ + animation/show_hide_animation.hpp \ + render_node.hpp diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index f1322645df..f515bfd966 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -193,7 +193,11 @@ void FrontendRenderer::AcceptMessage(ref_ptr message) } case Message::MyPositionShape: - m_myPositionController->SetRenderShape(ref_ptr(message)->AcceptShape()); + { + ref_ptr msg = message; + m_myPositionController->SetRenderShape(msg->AcceptShape()); + m_selectionShape = msg->AcceptSelection(); + } break; case Message::ChangeMyPostitionMode: @@ -241,6 +245,24 @@ void FrontendRenderer::AcceptMessage(ref_ptr message) break; } + case Message::SelectObject: + { + ref_ptr msg = message; + ASSERT(m_selectionShape != nullptr, ()); + if (msg->IsDismiss()) + { + m_selectionShape->Hide(); + } + else + { + m_selectionShape->SetPosition(msg->GetPosition()); + m_selectionShape->SetSelectedObject(msg->GetSelectedObject()); + m_selectionShape->Hide(); + m_selectionShape->Show(); + } + break; + } + default: ASSERT(false, ()); } @@ -425,30 +447,45 @@ void FrontendRenderer::RenderScene(ScreenBase const & modelView) GLFunctions::glClear(); dp::GLState::DepthLayer prevLayer = dp::GLState::GeometryLayer; - for (drape_ptr const & group : m_renderGroups) + size_t currentRenderGroup = 0; + for (; currentRenderGroup < m_renderGroups.size(); ++currentRenderGroup) { - group->UpdateAnimation(); + drape_ptr const & group = m_renderGroups[currentRenderGroup]; + dp::GLState const & state = group->GetState(); dp::GLState::DepthLayer layer = state.GetDepthLayer(); if (prevLayer != layer && layer == dp::GLState::OverlayLayer) - { - GLFunctions::glClearDepth(); - m_myPositionController->Render(modelView, make_ref(m_gpuProgramManager), m_generalUniforms); - } + break; prevLayer = layer; - ASSERT_LESS_OR_EQUAL(prevLayer, layer, ()); - - ref_ptr program = m_gpuProgramManager->GetProgram(state.GetProgramIndex()); - program->Bind(); - ApplyUniforms(m_generalUniforms, program); - ApplyUniforms(group->GetUniforms(), program); - ApplyState(state, program); - - group->Render(modelView); + RenderSingleGroup(modelView, make_ref(group)); } GLFunctions::glClearDepth(); + if (m_selectionShape != nullptr) + { + SelectionShape::ESelectedObject selectedObject = m_selectionShape->GetSelectedObject(); + if (selectedObject == SelectionShape::OBJECT_MY_POSITION) + { + ASSERT(m_myPositionController->IsModeHasPosition(), ()); + m_selectionShape->SetPosition(m_myPositionController->Position()); + m_selectionShape->Render(modelView, make_ref(m_gpuProgramManager), m_generalUniforms); + } + else if (selectedObject == SelectionShape::OBJECT_POI) + m_selectionShape->Render(modelView, make_ref(m_gpuProgramManager), m_generalUniforms); + } + + m_myPositionController->Render(modelView, make_ref(m_gpuProgramManager), m_generalUniforms); + + for (; currentRenderGroup < m_renderGroups.size(); ++currentRenderGroup) + { + drape_ptr const & group = m_renderGroups[currentRenderGroup]; + RenderSingleGroup(modelView, make_ref(group)); + } + + GLFunctions::glClearDepth(); + if (m_selectionShape != nullptr && m_selectionShape->GetSelectedObject() == SelectionShape::OBJECT_USER_MARK) + m_selectionShape->Render(modelView, make_ref(m_gpuProgramManager), m_generalUniforms); for (drape_ptr const & group : m_userMarkRenderGroups) { @@ -475,6 +512,20 @@ void FrontendRenderer::RenderScene(ScreenBase const & modelView) #endif } +void FrontendRenderer::RenderSingleGroup(ScreenBase const & modelView, ref_ptr group) +{ + group->UpdateAnimation(); + 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); +} + void FrontendRenderer::RefreshProjection() { array m; @@ -702,6 +753,7 @@ void FrontendRenderer::ReleaseResources() m_userMarkRenderGroups.clear(); m_guiRenderer.reset(); m_myPositionController.reset(); + m_selectionShape.release(); m_gpuProgramManager.reset(); } diff --git a/drape_frontend/frontend_renderer.hpp b/drape_frontend/frontend_renderer.hpp index c39ac335ee..65b605cf39 100755 --- a/drape_frontend/frontend_renderer.hpp +++ b/drape_frontend/frontend_renderer.hpp @@ -14,9 +14,9 @@ #include "drape_frontend/tile_tree.hpp" #include "drape_frontend/backend_renderer.hpp" #include "drape_frontend/render_group.hpp" -#include "drape_frontend/my_position_controller.hpp" #include "drape_frontend/navigator.hpp" #include "drape_frontend/user_event_stream.hpp" +#include "drape_frontend/my_position_controller.hpp" #include "drape_gui/layer_render.hpp" @@ -43,6 +43,8 @@ namespace dp namespace df { +class SelectionShape; + struct TapInfo { m2::PointD const m_pixelPoint; @@ -125,6 +127,7 @@ protected: private: void OnResize(ScreenBase const & screen); void RenderScene(ScreenBase const & modelView); + void RenderSingleGroup(ScreenBase const & modelView, ref_ptr group); void RefreshProjection(); void RefreshModelView(ScreenBase const & screen); ScreenBase const & UpdateScene(bool & modelViewChanged); @@ -191,6 +194,7 @@ private: drape_ptr m_guiRenderer; drape_ptr m_myPositionController; + drape_ptr m_selectionShape; drape_ptr m_overlayTree; diff --git a/drape_frontend/message.hpp b/drape_frontend/message.hpp index b11ff99c53..95d7bb1236 100644 --- a/drape_frontend/message.hpp +++ b/drape_frontend/message.hpp @@ -29,7 +29,8 @@ public: ChangeMyPostitionMode, CompassInfo, GpsInfo, - FindVisiblePOI + FindVisiblePOI, + SelectObject }; virtual ~Message() {} diff --git a/drape_frontend/message_subclasses.hpp b/drape_frontend/message_subclasses.hpp index 989ab68dba..313ae6df17 100644 --- a/drape_frontend/message_subclasses.hpp +++ b/drape_frontend/message_subclasses.hpp @@ -1,6 +1,7 @@ #pragma once #include "drape_frontend/my_position.hpp" +#include "drape_frontend/selection_shape.hpp" #include "drape_frontend/message.hpp" #include "drape_frontend/viewport.hpp" #include "drape_frontend/tile_utils.hpp" @@ -274,16 +275,19 @@ private: class MyPositionShapeMessage : public Message { public: - MyPositionShapeMessage(drape_ptr && shape) + MyPositionShapeMessage(drape_ptr && shape, drape_ptr && selection) : m_shape(move(shape)) + , m_selection(move(selection)) {} Type GetType() const override { return Message::MyPositionShape; } drape_ptr && AcceptShape() { return move(m_shape); } + drape_ptr AcceptSelection() { return move(m_selection); } private: drape_ptr m_shape; + drape_ptr m_selection; }; class StopRenderingMessage : public Message @@ -414,4 +418,31 @@ private: FeatureID & m_featureID; }; +class SelectObjectMessage : public Message +{ +public: + struct DismissTag {}; + SelectObjectMessage(DismissTag) + : m_isDismiss(true) + { + } + + SelectObjectMessage(SelectionShape::ESelectedObject selectedObject, m2::PointD const & glbPoint) + : m_selected(selectedObject) + , m_glbPoint(glbPoint) + , m_isDismiss(false) + { + } + + Type GetType() const override { return SelectObject; } + m2::PointD const & GetPosition() const { return m_glbPoint; } + SelectionShape::ESelectedObject GetSelectedObject() const { return m_selected; } + bool IsDismiss() const { return m_isDismiss; } + +private: + SelectionShape::ESelectedObject m_selected; + m2::PointD m_glbPoint; + bool m_isDismiss; +}; + } // namespace df diff --git a/drape_frontend/my_position.cpp b/drape_frontend/my_position.cpp index f1eb1e60b5..12ffddb3bb 100644 --- a/drape_frontend/my_position.cpp +++ b/drape_frontend/my_position.cpp @@ -1,6 +1,5 @@ #include "my_position.hpp" -#include "drape/batcher.hpp" #include "drape/depth_constants.hpp" #include "drape/glsl_func.hpp" #include "drape/glsl_types.hpp" @@ -215,19 +214,7 @@ void MyPosition::RenderPart(ref_ptr mng, { TPart const & accuracy = m_parts[part]; RenderNode & node = m_nodes[accuracy.second]; - - ref_ptr prg = mng->GetProgram(node.m_state.GetProgramIndex()); - prg->Bind(); - if (!node.m_isBuilded) - { - node.m_buffer->Build(prg); - node.m_isBuilded = true; - } - - dp::ApplyUniforms(uniforms, prg); - dp::ApplyState(node.m_state, prg); - - node.m_buffer->RenderRange(accuracy.first); + node.Render(mng, uniforms, accuracy.first); } } diff --git a/drape_frontend/my_position.hpp b/drape_frontend/my_position.hpp index f1ff4c177f..a038166a9d 100644 --- a/drape_frontend/my_position.hpp +++ b/drape_frontend/my_position.hpp @@ -1,10 +1,13 @@ #pragma once +#include "render_node.hpp" + #include "drape/vertex_array_buffer.hpp" #include "drape/glstate.hpp" #include "drape/gpu_program_manager.hpp" #include "drape/texture_manager.hpp" #include "drape/uniform_values_storage.hpp" +#include "drape/batcher.hpp" #include "geometry/screenbase.hpp" @@ -31,20 +34,6 @@ private: void CachePointPosition(ref_ptr mng); private: - struct RenderNode - { - RenderNode(dp::GLState const & state, drape_ptr && buffer) - : m_state(state) - , m_buffer(move(buffer)) - , m_isBuilded(false) - { - } - - dp::GLState m_state; - drape_ptr m_buffer; - bool m_isBuilded; - }; - enum EMyPositionPart { // don't change order and values diff --git a/drape_frontend/render_node.cpp b/drape_frontend/render_node.cpp new file mode 100644 index 0000000000..f94c14509f --- /dev/null +++ b/drape_frontend/render_node.cpp @@ -0,0 +1,43 @@ +#include "render_node.hpp" + +#include "drape/vertex_array_buffer.hpp" +#include "drape/gpu_program_manager.hpp" + +namespace df +{ + +RenderNode::RenderNode(dp::GLState const & state, drape_ptr && buffer) + : m_state(state) + , m_buffer(move(buffer)) + , m_isBuilded(false) +{ +} + +void RenderNode::Render(ref_ptr mng, dp::UniformValuesStorage const & uniforms, + dp::IndicesRange const & range) +{ + Apply(mng, uniforms); + m_buffer->RenderRange(range); +} + +void RenderNode::Render(ref_ptr mng, dp::UniformValuesStorage const & uniforms) +{ + Apply(mng, uniforms); + m_buffer->Render(); +} + +void RenderNode::Apply(ref_ptr mng, dp::UniformValuesStorage const & uniforms) +{ + ref_ptr prg = mng->GetProgram(m_state.GetProgramIndex()); + prg->Bind(); + if (!m_isBuilded) + { + m_buffer->Build(prg); + m_isBuilded = true; + } + + dp::ApplyUniforms(uniforms, prg); + dp::ApplyState(m_state, prg); +} + +} diff --git a/drape_frontend/render_node.hpp b/drape_frontend/render_node.hpp new file mode 100644 index 0000000000..02e03a9ace --- /dev/null +++ b/drape_frontend/render_node.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include "drape/glstate.hpp" +#include "drape/pointers.hpp" + +namespace dp +{ + class VertexArrayBuffer; + class GpuProgramManager; + struct IndicesRange; +} + +namespace df +{ + +class RenderNode +{ +public: + RenderNode(dp::GLState const & state, drape_ptr && buffer); + + void Render(ref_ptr mng, dp::UniformValuesStorage const & uniforms); + void Render(ref_ptr mng, dp::UniformValuesStorage const & uniforms, dp::IndicesRange const & range); + +private: + void Apply(ref_ptr mng, dp::UniformValuesStorage const & uniforms); + +private: + dp::GLState m_state; + drape_ptr m_buffer; + bool m_isBuilded; +}; + +} diff --git a/drape_frontend/selection_shape.cpp b/drape_frontend/selection_shape.cpp new file mode 100644 index 0000000000..e8b8b2d266 --- /dev/null +++ b/drape_frontend/selection_shape.cpp @@ -0,0 +1,166 @@ +#include "selection_shape.hpp" +#include "visual_params.hpp" + +#include "drape/attribute_provider.hpp" +#include "drape/batcher.hpp" +#include "drape/binding_info.hpp" +#include "drape/glsl_func.hpp" +#include "drape/glsl_types.hpp" +#include "drape/gpu_program_manager.hpp" +#include "drape/shader_def.hpp" +#include "drape/texture_manager.hpp" +#include "drape/uniform_values_storage.hpp" + +namespace df +{ + +namespace +{ + +struct Vertex +{ + Vertex() = default; + Vertex(glsl::vec2 const & normal, glsl::vec2 const & texCoord) + : m_normal(normal) + , m_texCoord(texCoord) + { + } + + glsl::vec2 m_normal; + glsl::vec2 m_texCoord; +}; + +dp::BindingInfo GetBindingInfo() +{ + dp::BindingInfo info(2); + dp::BindingDecl & normal = info.GetBindingDecl(0); + normal.m_attributeName = "a_normal"; + normal.m_componentCount = 2; + normal.m_componentType = gl_const::GLFloatType; + normal.m_offset = 0; + normal.m_stride = sizeof(Vertex); + + dp::BindingDecl & texCoord = info.GetBindingDecl(1); + texCoord.m_attributeName = "a_colorTexCoords"; + texCoord.m_componentCount = 2; + texCoord.m_componentType = gl_const::GLFloatType; + texCoord.m_offset = sizeof(glsl::vec2); + texCoord.m_stride = sizeof(Vertex); + + return info; +} + +} // namespace + +SelectionShape::SelectionShape(ref_ptr mng) + : m_position(m2::PointD::Zero()) + , m_animation(false, 0.25) + , m_selectionRadius(15.0f * VisualParams::Instance().GetVisualScale()) +{ + int const TriangleCount = 40; + int const VertexCount = 3 * TriangleCount; + float const etalonSector = math::twicePi / static_cast(TriangleCount); + + dp::TextureManager::ColorRegion color; + mng->GetColorRegion(dp::Color(0x17, 0xBF, 0x8E, 0x6F), color); + glsl::vec2 colorCoord = glsl::ToVec2(color.GetTexRect().Center()); + + buffer_vector buffer; + + glsl::vec2 startNormal(0.0f, 1.0f); + + for (size_t i = 0; i < TriangleCount + 1; ++i) + { + glsl::vec2 normal = glsl::rotate(startNormal, i * etalonSector); + glsl::vec2 nextNormal = glsl::rotate(startNormal, (i + 1) * etalonSector); + + buffer.emplace_back(startNormal, colorCoord); + buffer.emplace_back(normal, colorCoord); + buffer.emplace_back(nextNormal, colorCoord); + } + + dp::GLState state(gpu::ACCURACY_PROGRAM, dp::GLState::OverlayLayer); + state.SetColorTexture(color.GetTexture()); + + { + dp::Batcher batcher(TriangleCount * dp::Batcher::IndexPerTriangle, VertexCount); + dp::SessionGuard guard(batcher, [this](dp::GLState const & state, drape_ptr && b) + { + drape_ptr bucket = move(b); + ASSERT(bucket->GetOverlayHandlesCount() == 0, ()); + m_renderNode = make_unique_dp(state, bucket->MoveBuffer()); + }); + + dp::AttributeProvider provider(1 /*stream count*/, VertexCount); + provider.InitStream(0 /*stream index*/, GetBindingInfo(), make_ref(buffer.data())); + + batcher.InsertTriangleList(state, make_ref(&provider), nullptr); + } +} + +void SelectionShape::SetPosition(m2::PointD const & position) +{ + m_position = position; +} + +void SelectionShape::Show() +{ + m_animation.Show(); +} + +void SelectionShape::Hide() +{ + m_animation.Hide(); +} + +void SelectionShape::Render(ScreenBase const & screen, ref_ptr mng, + dp::UniformValuesStorage const & commonUniforms) +{ + ShowHideAnimation::EState state = m_animation.GetState(); + if (state == ShowHideAnimation::STATE_VISIBLE || + state == ShowHideAnimation::STATE_SHOW_DIRECTION) + { + dp::UniformValuesStorage uniforms = commonUniforms; + uniforms.SetFloatValue("u_position", m_position.x, m_position.y, 0.0); + uniforms.SetFloatValue("u_accuracy", GetCurrentRadius()); + m_renderNode->Render(mng, uniforms); + } +} + +void SelectionShape::SetSelectedObject(SelectionShape::ESelectedObject obj) +{ + m_selectedObject = obj; +} + +SelectionShape::ESelectedObject SelectionShape::GetSelectedObject() const +{ + return m_selectedObject; +} + +double SelectionShape::GetCurrentRadius() const +{ + static double const firstT = 0.6; + static double const secondT = 0.85; + static double const thirdT = 1.0; + static double const dfsT = secondT - firstT; + static double const dstT = thirdT - secondT; + + static double const firstRadius = 1.3 * m_selectionRadius; + static double const secondRadius = 0.8 * m_selectionRadius; + static double const dfsRadius = secondRadius - firstRadius; + static double const dstRadius = m_selectionRadius - secondRadius; + + double t = m_animation.GetT(); + if (m_animation.IsFinished()) + return m_selectionRadius * t; + + if (t < firstT) + return firstRadius * (t / firstT); + + if (t < secondT) + return firstRadius + dfsRadius * (t - firstT) / dfsT; + + return secondRadius + dstRadius * (t - secondT)/ dstT; +} + +} // namespace df diff --git a/drape_frontend/selection_shape.hpp b/drape_frontend/selection_shape.hpp new file mode 100644 index 0000000000..c306b26122 --- /dev/null +++ b/drape_frontend/selection_shape.hpp @@ -0,0 +1,55 @@ +#pragma once + +#include "animation/show_hide_animation.hpp" +#include "render_node.hpp" + +#include "geometry/point2d.hpp" +#include "geometry/screenbase.hpp" + +namespace dp +{ + +class GpuProgramManager; +class UniformValuesStorage; +class TextureManager; + +} + +namespace df +{ + +class SelectionShape +{ +public: + enum ESelectedObject + { + OBJECT_POI, + OBJECT_USER_MARK, + OBJECT_MY_POSITION + }; + + SelectionShape(ref_ptr mng); + + void SetPosition(m2::PointD const & position); + void Show(); + void Hide(); + void Render(ScreenBase const & screen, + ref_ptr mng, + dp::UniformValuesStorage const & commonUniforms); + + void SetSelectedObject(ESelectedObject obj); + ESelectedObject GetSelectedObject() const; + +private: + double GetCurrentRadius() const; + +private: + m2::PointD m_position; + ShowHideAnimation m_animation; + ESelectedObject m_selectedObject; + + drape_ptr m_renderNode; + double const m_selectionRadius; +}; + +} // namespace df diff --git a/map/framework.cpp b/map/framework.cpp index 9c1e0c8c3c..281ab3c295 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -1632,11 +1632,25 @@ void Framework::ActivateUserMark(UserMark const * mark, bool needAnim) bool hasActive = activeMark != nullptr; activeMark = mark; if (mark) + { m_activateUserMarkFn(mark->Copy()); + m2::PointD pt = mark->GetPivot(); + df::SelectionShape::ESelectedObject object = df::SelectionShape::OBJECT_USER_MARK; + UserMark::Type type = mark->GetMarkType(); + if (type == UserMark::Type::MY_POSITION) + object = df::SelectionShape::OBJECT_MY_POSITION; + else if (type == UserMark::Type::POI) + object = df::SelectionShape::OBJECT_POI; + + CallDrapeFunction(bind(&df::DrapeEngine::SelectObject, _1, object, pt)); + } else { if (hasActive) + { m_activateUserMarkFn(nullptr); + CallDrapeFunction(bind(&df::DrapeEngine::DeselectObject, _1)); + } } } } diff --git a/qt/draw_widget.cpp b/qt/draw_widget.cpp index 2fa4a8e9d7..fe6f517ae5 100644 --- a/qt/draw_widget.cpp +++ b/qt/draw_widget.cpp @@ -78,6 +78,10 @@ bool IsLocationEmulation(QMouseEvent * e) QObject::connect(this, SIGNAL(heightChanged(int)), this, SLOT(sizeChanged(int))); QObject::connect(this, SIGNAL(widthChanged(int)), this, SLOT(sizeChanged(int))); + m_framework->SetUserMarkActivationListener([](unique_ptr mark) + { + }); + m_framework->SetRouteBuildingListener([] (routing::IRouter::ResultCode, vector const &) { });