From 76fa670f929d01afa607b5377299a110adc275ee Mon Sep 17 00:00:00 2001 From: Pepe Rivera Date: Mon, 16 Mar 2020 11:54:19 -0700 Subject: [PATCH] Support mouse gestures when active tracing is enabled (#1064) * Make the pointer follow the mouse * Only render when necessary * Move trace rendering to background thread --- src/GraphControl/Control/Grapher.cpp | 52 +++++++++++++++++-- src/GraphControl/Control/Grapher.h | 1 + src/GraphControl/DirectX/RenderMain.cpp | 66 +++++++++++++++++++++++-- src/GraphControl/DirectX/RenderMain.h | 9 +++- 4 files changed, 121 insertions(+), 7 deletions(-) diff --git a/src/GraphControl/Control/Grapher.cpp b/src/GraphControl/Control/Grapher.cpp index 4696cba..da71138 100644 --- a/src/GraphControl/Control/Grapher.cpp +++ b/src/GraphControl/Control/Grapher.cpp @@ -93,11 +93,19 @@ namespace GraphControl { if (auto renderer = m_graph->GetRenderer()) { + m_renderMain->GetCriticalSection().lock(); + if (SUCCEEDED(renderer->ScaleRange(centerX, centerY, scale))) { + m_renderMain->GetCriticalSection().unlock(); + m_renderMain->RunRenderPass(); GraphViewChangedEvent(this, ref new RoutedEventArgs()); } + else + { + m_renderMain->GetCriticalSection().unlock(); + } } } } @@ -612,9 +620,33 @@ namespace GraphControl { if (m_renderMain) { - PointerPoint ^ currPoint = e->GetCurrentPoint(/* relativeTo */ this); - m_renderMain->PointerLocation = currPoint->Position; - UpdateTracingChanged(); + Point currPosition = e->GetCurrentPoint(/* relativeTo */ this)->Position; + + if (m_renderMain->ActiveTracing) + { + PointerValueChangedEvent(currPosition); + ActiveTraceCursorPosition = currPosition; + + if (m_cachedCursor == nullptr) + { + m_cachedCursor = ::CoreWindow::GetForCurrentThread()->PointerCursor; + ::CoreWindow::GetForCurrentThread()->PointerCursor = nullptr; + } + } + else if (m_cachedCursor != nullptr) + { + m_renderMain->PointerLocation = currPosition; + + ::CoreWindow::GetForCurrentThread()->PointerCursor = m_cachedCursor; + m_cachedCursor = nullptr; + + UpdateTracingChanged(); + } + else + { + m_renderMain->PointerLocation = currPosition; + UpdateTracingChanged(); + } e->Handled = true; } @@ -628,6 +660,12 @@ namespace GraphControl TracingChangedEvent(false); e->Handled = true; } + + if (m_cachedCursor != nullptr) + { + ::CoreWindow::GetForCurrentThread()->PointerCursor = m_cachedCursor; + m_cachedCursor = nullptr; + } } void Grapher::OnPointerWheelChanged(PointerRoutedEventArgs ^ e) @@ -699,11 +737,15 @@ namespace GraphControl translationX /= -width; translationY /= height; + m_renderMain->GetCriticalSection().lock(); + if (FAILED(renderer->MoveRangeByRatio(translationX, translationY))) { + m_renderMain->GetCriticalSection().unlock(); return; } + m_renderMain->GetCriticalSection().unlock(); needsRenderPass = true; } @@ -717,11 +759,15 @@ namespace GraphControl const auto& pos = e->Position; const auto [centerX, centerY] = PointerPositionToGraphPosition(pos.X, pos.Y, width, height); + m_renderMain->GetCriticalSection().lock(); + if (FAILED(renderer->ScaleRange(centerX, centerY, scale))) { + m_renderMain->GetCriticalSection().unlock(); return; } + m_renderMain->GetCriticalSection().unlock(); needsRenderPass = true; } diff --git a/src/GraphControl/Control/Grapher.h b/src/GraphControl/Control/Grapher.h index 3cbaf1d..d1c443a 100644 --- a/src/GraphControl/Control/Grapher.h +++ b/src/GraphControl/Control/Grapher.h @@ -333,6 +333,7 @@ public bool m_KeysPressed[5]; bool m_Moving; Windows::UI::Xaml::DispatcherTimer ^ m_TracingTrackingTimer; + Windows::UI::Core::CoreCursor ^ m_cachedCursor; public: Windows::Storage::Streams::RandomAccessStreamReference ^ GetGraphBitmapStream(); diff --git a/src/GraphControl/DirectX/RenderMain.cpp b/src/GraphControl/DirectX/RenderMain.cpp index 169af46..8f27478 100644 --- a/src/GraphControl/DirectX/RenderMain.cpp +++ b/src/GraphControl/DirectX/RenderMain.cpp @@ -86,7 +86,12 @@ namespace GraphControl::DX { m_Tracing = false; } - RunRenderPass(); + + bool wasPointRendered = m_Tracing; + if (CanRenderPoint() || wasPointRendered) + { + RunRenderPassAsync(); + } } } @@ -95,7 +100,12 @@ namespace GraphControl::DX if (m_pointerLocation != location) { m_pointerLocation = location; - RunRenderPass(); + + bool wasPointRendered = m_Tracing; + if (CanRenderPoint() || wasPointRendered) + { + RunRenderPassAsync(); + } } } @@ -104,7 +114,12 @@ namespace GraphControl::DX if (m_drawActiveTracing != value) { m_drawActiveTracing = value; - RunRenderPass(); + + bool wasPointRendered = m_Tracing; + if (CanRenderPoint() || wasPointRendered) + { + RunRenderPassAsync(); + } } } @@ -127,6 +142,51 @@ namespace GraphControl::DX } } + bool RenderMain::CanRenderPoint() + { + if (m_drawNearestPoint || m_drawActiveTracing) + { + Point trackPoint = m_pointerLocation; + + if (m_drawActiveTracing) + { + trackPoint = m_activeTracingPointerLocation; + } + + if (!m_criticalSection.try_lock()) + { + return false; + } + + m_criticalSection.unlock(); + + critical_section::scoped_lock lock(m_criticalSection); + + int formulaId = -1; + float nearestPointLocationX, nearestPointLocationY; + double nearestPointValueX, nearestPointValueY, rhoValueOut, thetaValueOut, tValueOut; + m_Tracing = m_graph->GetRenderer()->GetClosePointData( + trackPoint.X, + trackPoint.Y, + formulaId, + nearestPointLocationX, + nearestPointLocationY, + nearestPointValueX, + nearestPointValueY, + rhoValueOut, + thetaValueOut, + tValueOut) + == S_OK; + m_Tracing = m_Tracing && !isnan(nearestPointLocationX) && !isnan(nearestPointLocationY); + } + else + { + m_Tracing = false; + } + + return m_Tracing; + } + bool RenderMain::RunRenderPass() { // Non async render passes cancel if they can't obtain the lock immediatly diff --git a/src/GraphControl/DirectX/RenderMain.h b/src/GraphControl/DirectX/RenderMain.h index f464711..96f18c0 100644 --- a/src/GraphControl/DirectX/RenderMain.h +++ b/src/GraphControl/DirectX/RenderMain.h @@ -45,6 +45,8 @@ namespace GraphControl::DX void CreateWindowSizeDependentResources(); + bool RenderMain::CanRenderPoint(); + bool RunRenderPass(); Windows::Foundation::IAsyncAction ^ RunRenderPassAsync(bool allowCancel = true); @@ -78,7 +80,12 @@ namespace GraphControl::DX if (m_activeTracingPointerLocation != newValue) { m_activeTracingPointerLocation = newValue; - RunRenderPass(); + + bool wasPointRendered = m_Tracing; + if (CanRenderPoint() || wasPointRendered) + { + RunRenderPassAsync(); + } } } }