From 98dfc2620803940267581e576edf56a6a2794cff Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Thu, 17 Dec 2020 07:27:29 -0800 Subject: [PATCH] [glass] Fix plots (#2943) --- glass/src/app/native/cpp/main.cpp | 7 +++- glass/src/lib/native/cpp/Context.cpp | 5 +++ glass/src/lib/native/cpp/other/Plot.cpp | 40 +++++-------------- glass/src/lib/native/include/glass/Context.h | 10 +++++ .../native/include/glass/ContextInternal.h | 3 ++ .../src/lib/native/include/glass/other/Plot.h | 9 ----- 6 files changed, 34 insertions(+), 40 deletions(-) diff --git a/glass/src/app/native/cpp/main.cpp b/glass/src/app/native/cpp/main.cpp index 44ce0c294e..e7fca2b655 100644 --- a/glass/src/app/native/cpp/main.cpp +++ b/glass/src/app/native/cpp/main.cpp @@ -93,7 +93,7 @@ int main() { gui::ConfigurePlatformSaveFile("glass.ini"); gPlotProvider->GlobalInit(); - gui::AddInit([] { gPlotProvider->ResetTime(); }); + gui::AddInit([] { glass::ResetTime(); }); gNtProvider->GlobalInit(); gui::AddInit(NtInitialize); @@ -102,6 +102,10 @@ int main() { gui::AddLateExecute([] { ImGui::BeginMainMenuBar(); gui::EmitViewMenu(); + if (ImGui::BeginMenu("View")) { + if (ImGui::MenuItem("Reset Time")) glass::ResetTime(); + ImGui::EndMenu(); + } if (ImGui::BeginMenu("NetworkTables")) { if (gNetworkTablesSettingsWindow) gNetworkTablesSettingsWindow->DisplayMenuItem("NetworkTables Settings"); @@ -116,7 +120,6 @@ int main() { if (ImGui::MenuItem("Pause All Plots", nullptr, &paused)) { gPlotProvider->SetPaused(paused); } - if (ImGui::MenuItem("Reset Plot Time")) gPlotProvider->ResetTime(); ImGui::Separator(); gPlotProvider->DisplayMenu(); ImGui::EndMenu(); diff --git a/glass/src/lib/native/cpp/Context.cpp b/glass/src/lib/native/cpp/Context.cpp index cac280d84b..efbf209e98 100644 --- a/glass/src/lib/native/cpp/Context.cpp +++ b/glass/src/lib/native/cpp/Context.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include "glass/ContextInternal.h" @@ -211,6 +212,10 @@ Context* glass::GetCurrentContext() { return gContext; } void glass::SetCurrentContext(Context* ctx) { gContext = ctx; } +void glass::ResetTime() { gContext->zeroTime = wpi::Now(); } + +uint64_t glass::GetZeroTime() { return gContext->zeroTime; } + Storage::Value& Storage::GetValue(wpi::StringRef key) { auto it = std::find(m_keys.begin(), m_keys.end(), key); if (it == m_keys.end()) { diff --git a/glass/src/lib/native/cpp/other/Plot.cpp b/glass/src/lib/native/cpp/other/Plot.cpp index 0b3a20eadc..44201c14ee 100644 --- a/glass/src/lib/native/cpp/other/Plot.cpp +++ b/glass/src/lib/native/cpp/other/Plot.cpp @@ -55,8 +55,6 @@ class PlotSeries { void SetSource(DataSource* source); DataSource* GetSource() const { return m_source; } - void Clear() { m_size = 0; } - bool ReadIni(wpi::StringRef name, wpi::StringRef value); void WriteIni(ImGuiTextBuffer* out); @@ -110,8 +108,6 @@ class Plot { bool ReadIni(wpi::StringRef name, wpi::StringRef value); void WriteIni(ImGuiTextBuffer* out); - void Clear(); - void DragDropTarget(PlotView& view, size_t i, bool inPlot); void EmitPlot(PlotView& view, double now, bool paused, size_t i); void EmitSettings(size_t i); @@ -146,8 +142,6 @@ class PlotView : public View { public: explicit PlotView(PlotProvider* provider) : m_provider{provider} {} - void Clear(); - void Display() override; void MovePlot(PlotView* fromView, size_t fromIndex, size_t toIndex); @@ -312,20 +306,24 @@ PlotSeries::Action PlotSeries::EmitPlot(PlotView& view, double now, size_t i, // we handle the offset logic ourselves to avoid wrap issues with size + 1 struct GetterData { double now; + double zeroTime; ImPlotPoint* data; int size; int offset; }; - GetterData getterData = {now, m_data, size, offset}; + GetterData getterData = {now, GetZeroTime() * 1.0e-6, m_data, size, offset}; auto getter = [](void* data, int idx) { auto d = static_cast(data); if (idx == d->size) return ImPlotPoint{ - d->now, d->data[d->offset == 0 ? d->size - 1 : d->offset - 1].y}; + d->now - d->zeroTime, + d->data[d->offset == 0 ? d->size - 1 : d->offset - 1].y}; + ImPlotPoint* point; if (d->offset + idx < d->size) - return d->data[d->offset + idx]; + point = &d->data[d->offset + idx]; else - return d->data[d->offset + idx - d->size]; + point = &d->data[d->offset + idx - d->size]; + return ImPlotPoint{point->x - d->zeroTime, point->y}; }; if (m_color.w == IMPLOT_AUTO_COL.w) m_color = ImPlot::GetColormapColor(i); @@ -543,10 +541,6 @@ void Plot::WriteIni(ImGuiTextBuffer* out) { } } -void Plot::Clear() { - for (auto&& series : m_series) series->Clear(); -} - void Plot::DragDropTarget(PlotView& view, size_t i, bool inPlot) { if (!ImGui::BeginDragDropTarget()) return; // handle dragging onto a specific Y axis @@ -601,8 +595,9 @@ void Plot::EmitPlot(PlotView& view, double now, bool paused, size_t i) { ImGuiCond_Always); } else { // also force-pause plots if overall timing is paused + double zeroTime = GetZeroTime() * 1.0e-6; ImPlot::SetNextPlotLimitsX( - now - m_viewTime, now, + now - zeroTime - m_viewTime, now - zeroTime, (paused || m_paused) ? ImGuiCond_Once : ImGuiCond_Always); } @@ -688,10 +683,6 @@ void Plot::EmitSettings(size_t i) { } } -void PlotView::Clear() { - for (auto&& plot : m_plots) plot->Clear(); -} - void PlotView::Display() { if (ImGui::BeginPopupContextItem()) { if (ImGui::Button("Add plot")) @@ -760,7 +751,7 @@ void PlotView::Display() { } } - double now = (wpi::Now() - m_provider->GetStartTime()) * 1.0e-6; + double now = wpi::Now() * 1.0e-6; for (size_t i = 0; i < m_plots.size(); ++i) { ImGui::PushID(i); m_plots[i]->EmitPlot(*this, now, m_provider->IsPaused(), i); @@ -821,15 +812,6 @@ void PlotProvider::GlobalInit() { }); } -void PlotProvider::ResetTime() { - m_startTime = wpi::Now(); - for (auto&& window : m_windows) { - if (auto view = static_cast(window->GetView())) { - view->Clear(); - } - } -} - void PlotProvider::DisplayMenu() { for (size_t i = 0; i < m_windows.size(); ++i) { m_windows[i]->DisplayMenuItem(); diff --git a/glass/src/lib/native/include/glass/Context.h b/glass/src/lib/native/include/glass/Context.h index 64ead2d8bd..c5a55598e9 100644 --- a/glass/src/lib/native/include/glass/Context.h +++ b/glass/src/lib/native/include/glass/Context.h @@ -25,6 +25,16 @@ void DestroyContext(Context* ctx = nullptr); Context* GetCurrentContext(); void SetCurrentContext(Context* ctx); +/** + * Resets zero time to current time. + */ +void ResetTime(); + +/** + * Gets the zero time. + */ +uint64_t GetZeroTime(); + /** * Storage provides both persistent and non-persistent key/value storage for * widgets. diff --git a/glass/src/lib/native/include/glass/ContextInternal.h b/glass/src/lib/native/include/glass/ContextInternal.h index c187ffd75f..262a0947b7 100644 --- a/glass/src/lib/native/include/glass/ContextInternal.h +++ b/glass/src/lib/native/include/glass/ContextInternal.h @@ -7,6 +7,8 @@ #pragma once +#include + #include #include @@ -42,6 +44,7 @@ struct Context { wpi::StringMap> storage; wpi::StringMap deviceHidden; IniSaverString sources{"Data Sources"}; + uint64_t zeroTime = 0; }; extern Context* gContext; diff --git a/glass/src/lib/native/include/glass/other/Plot.h b/glass/src/lib/native/include/glass/other/Plot.h index 590c222836..e7f7e4d53e 100644 --- a/glass/src/lib/native/include/glass/other/Plot.h +++ b/glass/src/lib/native/include/glass/other/Plot.h @@ -31,14 +31,6 @@ class PlotProvider : private WindowManager { */ bool IsPaused() { return m_paused; } - /** - * Resets time on all plots such that 0 = time when this function is called. - * Also clears the plot data. - */ - void ResetTime(); - - uint64_t GetStartTime() const { return m_startTime; } - void DisplayMenu() override; private: @@ -60,7 +52,6 @@ class PlotProvider : private WindowManager { IniSaver m_plotSaver; IniSaver m_seriesSaver; - uint64_t m_startTime = 0; bool m_paused = false; };