From 7be99a3400fe71edf62261e3d81fd2be044b49ff Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Thu, 1 Feb 2024 20:22:53 -0800 Subject: [PATCH 1/8] [glass] Replace Window/View with immediate mode --- glass/src/app/native/cpp/main.cpp | 102 +++++----- glass/src/lib/native/cpp/Window.cpp | 192 ++++++++++-------- glass/src/lib/native/cpp/WindowManager.cpp | 2 + glass/src/lib/native/cpp/other/Log.cpp | 10 +- glass/src/lib/native/include/glass/Window.h | 78 ++++++- .../src/lib/native/include/glass/other/Log.h | 10 +- glass/src/libnt/native/cpp/NetworkTables.cpp | 119 ++++++----- .../glass/networktables/NetworkTables.h | 44 ++-- outlineviewer/src/main/native/cpp/main.cpp | 8 +- .../main/native/cpp/NetworkTablesSimGui.cpp | 41 ++-- sysid/src/main/native/cpp/App.cpp | 58 ++++-- .../main/native/include/sysid/view/Analyzer.h | 7 +- .../native/include/sysid/view/DataSelector.h | 5 +- .../native/include/sysid/view/LogLoader.h | 7 +- 14 files changed, 394 insertions(+), 289 deletions(-) diff --git a/glass/src/app/native/cpp/main.cpp b/glass/src/app/native/cpp/main.cpp index 63715b25780..2ec8f10cb29 100644 --- a/glass/src/app/native/cpp/main.cpp +++ b/glass/src/app/native/cpp/main.cpp @@ -16,7 +16,7 @@ #include "glass/Context.h" #include "glass/MainMenuBar.h" #include "glass/Storage.h" -#include "glass/View.h" +#include "glass/Window.h" #include "glass/networktables/NetworkTables.h" #include "glass/networktables/NetworkTablesProvider.h" #include "glass/networktables/NetworkTablesSettings.h" @@ -43,10 +43,10 @@ static std::unique_ptr gNtProvider; static std::unique_ptr gNetworkTablesModel; static std::unique_ptr gNetworkTablesSettings; static glass::LogData gNetworkTablesLog; -static std::unique_ptr gNetworkTablesWindow; -static std::unique_ptr gNetworkTablesInfoWindow; -static std::unique_ptr gNetworkTablesSettingsWindow; -static std::unique_ptr gNetworkTablesLogWindow; +static glass::Window* gNetworkTablesWindow; +static glass::Window* gNetworkTablesInfoWindow; +static glass::Window* gNetworkTablesSettingsWindow; +static glass::Window* gNetworkTablesLogWindow; static glass::MainMenuBar gMainMenu; static bool gAbout = false; @@ -134,55 +134,34 @@ static void NtInitialize() { } }); - gNetworkTablesLogWindow = std::make_unique( - glass::GetStorageRoot().GetChild("NetworkTables Log"), - "NetworkTables Log", glass::Window::kHide); - gNetworkTablesLogWindow->SetView( - std::make_unique(&gNetworkTablesLog)); + gNetworkTablesLogWindow = glass::imm::CreateWindow("NetworkTables Log", false, + glass::Window::kHide); gNetworkTablesLogWindow->SetDefaultPos(250, 615); gNetworkTablesLogWindow->SetDefaultSize(600, 130); - gNetworkTablesLogWindow->DisableRenamePopup(); - gui::AddLateExecute([] { gNetworkTablesLogWindow->Display(); }); // NetworkTables table window gNetworkTablesModel = std::make_unique(); gui::AddEarlyExecute([] { gNetworkTablesModel->Update(); }); - gNetworkTablesWindow = std::make_unique( - glass::GetStorageRoot().GetChild("NetworkTables View"), "NetworkTables"); - gNetworkTablesWindow->SetView( - std::make_unique(gNetworkTablesModel.get())); + gNetworkTablesWindow = glass::imm::CreateWindow("NetworkTables View"); gNetworkTablesWindow->SetDefaultPos(250, 277); gNetworkTablesWindow->SetDefaultSize(750, 185); - gNetworkTablesWindow->DisableRenamePopup(); - gui::AddLateExecute([] { gNetworkTablesWindow->Display(); }); // NetworkTables info window - gNetworkTablesInfoWindow = std::make_unique( - glass::GetStorageRoot().GetChild("NetworkTables Info"), - "NetworkTables Info"); - gNetworkTablesInfoWindow->SetView(glass::MakeFunctionView( - [&] { glass::DisplayNetworkTablesInfo(gNetworkTablesModel.get()); })); + gNetworkTablesInfoWindow = glass::imm::CreateWindow( + "NetworkTables Info", false, glass::Window::kHide); gNetworkTablesInfoWindow->SetDefaultPos(250, 130); gNetworkTablesInfoWindow->SetDefaultSize(750, 145); - gNetworkTablesInfoWindow->SetDefaultVisibility(glass::Window::kHide); - gNetworkTablesInfoWindow->DisableRenamePopup(); - gui::AddLateExecute([] { gNetworkTablesInfoWindow->Display(); }); // NetworkTables settings window gNetworkTablesSettings = std::make_unique( "glass", glass::GetStorageRoot().GetChild("NetworkTables Settings")); gui::AddEarlyExecute([] { gNetworkTablesSettings->Update(); }); - gNetworkTablesSettingsWindow = std::make_unique( - glass::GetStorageRoot().GetChild("NetworkTables Settings"), - "NetworkTables Settings"); - gNetworkTablesSettingsWindow->SetView( - glass::MakeFunctionView([] { gNetworkTablesSettings->Display(); })); + gNetworkTablesSettingsWindow = + glass::imm::CreateWindow("NetworkTables Settings"); gNetworkTablesSettingsWindow->SetDefaultPos(30, 30); gNetworkTablesSettingsWindow->SetFlags(ImGuiWindowFlags_AlwaysAutoResize); - gNetworkTablesSettingsWindow->DisableRenamePopup(); - gui::AddLateExecute([] { gNetworkTablesSettingsWindow->Display(); }); gui::AddWindowScaler([](float scale) { // scale default window positions @@ -236,8 +215,6 @@ int main(int argc, char** argv) { glass::AddStandardNetworkTablesViews(*gNtProvider); - gui::AddLateExecute([] { gMainMenu.Display(); }); - gMainMenu.AddMainMenu([] { if (ImGui::BeginMenu("View")) { if (ImGui::MenuItem("Set Enter Key")) { @@ -249,18 +226,10 @@ int main(int argc, char** argv) { ImGui::EndMenu(); } if (ImGui::BeginMenu("NetworkTables")) { - if (gNetworkTablesSettingsWindow) { - gNetworkTablesSettingsWindow->DisplayMenuItem("NetworkTables Settings"); - } - if (gNetworkTablesWindow) { - gNetworkTablesWindow->DisplayMenuItem("NetworkTables View"); - } - if (gNetworkTablesInfoWindow) { - gNetworkTablesInfoWindow->DisplayMenuItem("NetworkTables Info"); - } - if (gNetworkTablesLogWindow) { - gNetworkTablesLogWindow->DisplayMenuItem("NetworkTables Log"); - } + gNetworkTablesSettingsWindow->DisplayMenuItem("NetworkTables Settings"); + gNetworkTablesWindow->DisplayMenuItem("NetworkTables View"); + gNetworkTablesInfoWindow->DisplayMenuItem("NetworkTables Info"); + gNetworkTablesLogWindow->DisplayMenuItem("NetworkTables Log"); ImGui::MenuItem("NetworkTables Debug Logging", nullptr, &gNetworkTablesDebugLog); ImGui::Separator(); @@ -295,6 +264,42 @@ int main(int argc, char** argv) { }); gui::AddLateExecute([] { + gMainMenu.Display(); + + if (glass::imm::BeginWindow(gNetworkTablesLogWindow)) { + auto& settings = glass::GetStorage().GetOrNewData( + &gNetworkTablesLog); + if (glass::imm::BeginWindowSettingsPopup()) { + settings.DisplayMenu(); + ImGui::EndPopup(); + } + glass::DisplayLog(&gNetworkTablesLog, settings.IsAutoScroll()); + } + glass::imm::EndWindow(); + + if (glass::imm::BeginWindow(gNetworkTablesWindow)) { + auto& settings = + glass::GetStorage().GetOrNewData(); + if (glass::imm::BeginWindowSettingsPopup()) { + settings.DisplayMenu(); + glass::DisplayNetworkTablesAddMenu(gNetworkTablesModel.get(), {}, + settings.GetFlags()); + ImGui::EndPopup(); + } + DisplayNetworkTables(gNetworkTablesModel.get(), settings.GetFlags()); + } + glass::imm::EndWindow(); + + if (glass::imm::BeginWindow(gNetworkTablesInfoWindow)) { + glass::DisplayNetworkTablesInfo(gNetworkTablesModel.get()); + } + glass::imm::EndWindow(); + + if (glass::imm::BeginWindow(gNetworkTablesSettingsWindow)) { + gNetworkTablesSettings->Display(); + } + glass::imm::EndWindow(); + if (gAbout) { ImGui::OpenPopup("About"); gAbout = false; @@ -359,9 +364,6 @@ int main(int argc, char** argv) { } gui::Main(); - gNetworkTablesSettingsWindow.reset(); - gNetworkTablesLogWindow.reset(); - gNetworkTablesWindow.reset(); gNetworkTablesModel.reset(); gNtProvider.reset(); gPlotProvider.reset(); diff --git a/glass/src/lib/native/cpp/Window.cpp b/glass/src/lib/native/cpp/Window.cpp index 64b043ffb1e..863cf1385cb 100644 --- a/glass/src/lib/native/cpp/Window.cpp +++ b/glass/src/lib/native/cpp/Window.cpp @@ -16,25 +16,17 @@ using namespace glass; -Window::Window(Storage& storage, std::string_view id, +Window::Window(Storage& storage, Storage& windowStorage, std::string_view id, Visibility defaultVisibility) - : m_id{id}, - m_name{storage.GetString("name")}, + : m_storage{storage}, + m_id{id}, + m_name{windowStorage.GetString("name")}, m_defaultName{id}, - m_visible{storage.GetBool("visible", defaultVisibility != kHide)}, - m_enabled{storage.GetBool("enabled", defaultVisibility != kDisabled)}, - m_defaultVisible{storage.GetValue("visible").boolDefault}, - m_defaultEnabled{storage.GetValue("enabled").boolDefault} {} - -void Window::SetVisibility(Visibility visibility) { - m_visible = visibility != kHide; - m_enabled = visibility != kDisabled; -} - -void Window::SetDefaultVisibility(Visibility visibility) { - m_defaultVisible = visibility != kHide; - m_defaultEnabled = visibility != kDisabled; -} + m_visible{windowStorage.GetBool("visible", defaultVisibility != kHide)}, + m_enabled{ + windowStorage.GetBool("enabled", defaultVisibility != kDisabled)}, + m_defaultVisible{windowStorage.GetValue("visible").boolDefault}, + m_defaultEnabled{windowStorage.GetValue("enabled").boolDefault} {} void Window::Display() { if (!m_view) { @@ -47,68 +39,11 @@ void Window::Display() { return; } - if (m_posCond != 0) { - ImGui::SetNextWindowPos(m_pos, m_posCond); - } - if (m_sizeCond != 0) { - ImGui::SetNextWindowSize(m_size, m_sizeCond); - } - if (m_setPadding) { - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, m_padding); - } - - std::string label; - if (m_name.empty()) { - label = fmt::format("{}###{}", m_defaultName, m_id); - } else { - label = fmt::format("{}###{}", m_name, m_id); - } - - if (Begin(label.c_str(), &m_visible, m_flags)) { + if (BeginWindow()) { if (m_renamePopupEnabled || m_view->HasSettings()) { - bool isClicked = (ImGui::IsMouseReleased(ImGuiMouseButton_Right) && - ImGui::IsItemHovered()); - ImGuiWindow* window = ImGui::GetCurrentWindow(); - - bool settingsButtonClicked = false; - // Not docked, and window has just enough for the circles not to be - // touching - if (!ImGui::IsWindowDocked() && - ImGui::GetWindowWidth() > (ImGui::GetFontSize() + 2) * 3 + - ImGui::GetStyle().FramePadding.x * 2) { - const ImGuiItemFlags itemFlagsRestore = - ImGui::GetCurrentContext()->CurrentItemFlags; - - ImGui::GetCurrentContext()->CurrentItemFlags |= - ImGuiItemFlags_NoNavDefaultFocus; - window->DC.NavLayerCurrent = ImGuiNavLayer_Menu; - - // Allow to draw outside of normal window - ImGui::PushClipRect(window->OuterRectClipped.Min, - window->OuterRectClipped.Max, false); - - const ImRect titleBarRect = ImGui::GetCurrentWindow()->TitleBarRect(); - const ImVec2 position = {titleBarRect.Max.x - - (ImGui::GetStyle().FramePadding.x * 3) - - (ImGui::GetFontSize() * 2), - titleBarRect.Min.y}; - settingsButtonClicked = - HamburgerButton(ImGui::GetID("#SETTINGS"), position); - - ImGui::PopClipRect(); - - ImGui::GetCurrentContext()->CurrentItemFlags = itemFlagsRestore; - } - if (settingsButtonClicked || isClicked) { - ImGui::OpenPopup(window->ID); - } - - if (ImGui::BeginPopupEx(window->ID, - ImGuiWindowFlags_AlwaysAutoResize | - ImGuiWindowFlags_NoTitleBar | - ImGuiWindowFlags_NoSavedSettings)) { + if (BeginWindowSettingsPopup()) { if (m_renamePopupEnabled) { - ItemEditName(&m_name); + EditName(); } m_view->Settings(); @@ -120,10 +55,7 @@ void Window::Display() { } else { m_view->Hidden(); } - End(); - if (m_setPadding) { - ImGui::PopStyleVar(); - } + EndWindow(); } bool Window::DisplayMenuItem(const char* label) { @@ -144,3 +76,101 @@ void Window::ScaleDefault(float scale) { m_size.y *= scale; } } + +bool Window::BeginWindow() { + PushStorageStack(m_storage); + + if (!m_visible || !m_enabled) { + return false; + } + m_inWindow = true; + + if (m_posCond != 0) { + ImGui::SetNextWindowPos(m_pos, m_posCond); + } + if (m_sizeCond != 0) { + ImGui::SetNextWindowSize(m_size, m_sizeCond); + } + if (m_setPadding) { + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, m_padding); + } + + std::string label; + if (m_name.empty()) { + label = fmt::format("{}###{}", m_defaultName, m_id); + } else { + label = fmt::format("{}###{}", m_name, m_id); + } + + return ImGui::Begin(label.c_str(), &m_visible, m_flags); +} + +void Window::EndWindow() { + PopStorageStack(); + if (!m_inWindow) { + return; + } + m_inWindow = false; + ImGui::End(); + if (m_setPadding) { + ImGui::PopStyleVar(); + } +} + +bool Window::BeginWindowSettingsPopup() { + bool isClicked = (ImGui::IsMouseReleased(ImGuiMouseButton_Right) && + ImGui::IsItemHovered()); + ImGuiWindow* window = ImGui::GetCurrentWindow(); + + bool settingsButtonClicked = false; + // Not docked, and window has just enough for the circles not to be touching + if (!ImGui::IsWindowDocked() && + ImGui::GetWindowWidth() > (ImGui::GetFontSize() + 2) * 3 + + ImGui::GetStyle().FramePadding.x * 2) { + const ImGuiItemFlags itemFlagsRestore = + ImGui::GetCurrentContext()->CurrentItemFlags; + + ImGui::GetCurrentContext()->CurrentItemFlags |= + ImGuiItemFlags_NoNavDefaultFocus; + window->DC.NavLayerCurrent = ImGuiNavLayer_Menu; + + // Allow to draw outside of normal window + ImGui::PushClipRect(window->OuterRectClipped.Min, + window->OuterRectClipped.Max, false); + + const ImRect titleBarRect = ImGui::GetCurrentWindow()->TitleBarRect(); + const ImVec2 position = {titleBarRect.Max.x - + (ImGui::GetStyle().FramePadding.x * 3) - + (ImGui::GetFontSize() * 2), + titleBarRect.Min.y}; + settingsButtonClicked = + HamburgerButton(ImGui::GetID("#SETTINGS"), position); + + ImGui::PopClipRect(); + + ImGui::GetCurrentContext()->CurrentItemFlags = itemFlagsRestore; + } + if (settingsButtonClicked || isClicked) { + ImGui::OpenPopup(window->ID); + } + + return ImGui::BeginPopupEx(window->ID, ImGuiWindowFlags_AlwaysAutoResize | + ImGuiWindowFlags_NoTitleBar | + ImGuiWindowFlags_NoSavedSettings); +} + +Window* imm::CreateWindow(Storage& root, std::string_view id, bool duplicateOk, + Window::Visibility defaultVisibility) { + Storage& storage = root.GetChild(id); + Storage& windowStorage = storage.GetChild("window"); + if (auto window = windowStorage.GetData()) { + if (!duplicateOk) { + fmt::print(stderr, "GUI: ignoring duplicate window '{}'\n", id); + return nullptr; + } + return window; + } + windowStorage.SetData( + std::make_shared(storage, id, defaultVisibility)); + return windowStorage.GetData(); +} diff --git a/glass/src/lib/native/cpp/WindowManager.cpp b/glass/src/lib/native/cpp/WindowManager.cpp index 3d90be5624b..3d25cfacd2f 100644 --- a/glass/src/lib/native/cpp/WindowManager.cpp +++ b/glass/src/lib/native/cpp/WindowManager.cpp @@ -12,9 +12,11 @@ #include #include #include +#include #include "glass/Context.h" #include "glass/Storage.h" +#include "imgui.h" using namespace glass; diff --git a/glass/src/lib/native/cpp/other/Log.cpp b/glass/src/lib/native/cpp/other/Log.cpp index 4209338526f..70bb37cf4b1 100644 --- a/glass/src/lib/native/cpp/other/Log.cpp +++ b/glass/src/lib/native/cpp/other/Log.cpp @@ -63,11 +63,7 @@ void glass::DisplayLog(LogData* data, bool autoScroll) { } } -void LogView::Display() { - DisplayLog(m_data, m_autoScroll); -} - -void LogView::Settings() { +void LogSettings::DisplayMenu() { ImGui::Checkbox("Auto-scroll", &m_autoScroll); if (ImGui::Selectable("Clear")) { m_data->Clear(); @@ -78,7 +74,3 @@ void LogView::Settings() { ImGui::SetClipboardText(buf.c_str()); } } - -bool LogView::HasSettings() { - return true; -} diff --git a/glass/src/lib/native/include/glass/Window.h b/glass/src/lib/native/include/glass/Window.h index 62b369cdd45..73e8f99002a 100644 --- a/glass/src/lib/native/include/glass/Window.h +++ b/glass/src/lib/native/include/glass/Window.h @@ -12,12 +12,12 @@ #define IMGUI_DEFINE_MATH_OPERATORS #include +#include "glass/Context.h" +#include "glass/Storage.h" #include "glass/View.h" namespace glass { -class Storage; - /** * Managed window information. * A Window owns the View that displays the window's contents. @@ -27,7 +27,8 @@ class Window { enum Visibility { kHide = 0, kShow, kDisabled }; Window(Storage& storage, std::string_view id, - Visibility defaultVisibility = kShow); + Visibility defaultVisibility = kShow) + : Window{storage, storage.GetChild("window"), id, defaultVisibility} {} std::string_view GetId() const { return m_id; } @@ -60,14 +61,20 @@ class Window { * * @param visibility 0=hide, 1=show, 2=disabled (force-hide) */ - void SetVisibility(Visibility visibility); + void SetVisibility(Visibility visibility) { + m_visible = visibility != kHide; + m_enabled = visibility != kDisabled; + } /** * Sets default visibility of window. * * @param visibility 0=hide, 1=show, 2=disabled (force-hide) */ - void SetDefaultVisibility(Visibility visibility); + void SetDefaultVisibility(Visibility visibility) { + m_defaultVisible = visibility != kHide; + m_defaultEnabled = visibility != kDisabled; + } /** * Sets default position of window. @@ -119,7 +126,19 @@ class Window { */ void ScaleDefault(float scale); + [[nodiscard]] + bool BeginWindow(); + void EndWindow(); + [[nodiscard]] + bool BeginWindowSettingsPopup(); + + bool EditName() { return ItemEditName(&m_name); } + private: + Window(Storage& storage, Storage& windowStorage, std::string_view id, + Visibility defaultVisibility); + + Storage& m_storage; std::string m_id; std::string& m_name; std::string m_defaultName; @@ -136,6 +155,55 @@ class Window { ImVec2 m_size; bool m_setPadding = false; ImVec2 m_padding; + bool m_inWindow = false; }; +namespace imm { +Window* CreateWindow( + Storage& root, std::string_view id, bool duplicateOk = false, + Window::Visibility defaultVisibility = Window::Visibility::kShow); + +inline Window* CreateWindow( + std::string_view id, bool duplicateOk = false, + Window::Visibility defaultVisibility = Window::Visibility::kShow) { + return CreateWindow(GetStorage(), id, duplicateOk, defaultVisibility); +} + +inline Window* GetWindow() { + return GetStorage().GetChild("window").GetData(); +} + +inline Window* GetWindow(std::string_view id) { + return GetStorage().GetChild(id).GetChild("window").GetData(); +} + +[[nodiscard]] +inline bool BeginWindow(Window* window) { + assert(window); + return window->BeginWindow(); +} + +[[nodiscard]] +inline bool BeginWindow() { + return BeginWindow(GetWindow()); +} + +[[nodiscard]] +inline bool BeginWindow(std::string_view id) { + return BeginWindow(GetWindow(id)); +} + +inline void EndWindow() { + Window* window = GetWindow(); + assert(window); + window->EndWindow(); +} + +[[nodiscard]] +inline bool BeginWindowSettingsPopup() { + return GetWindow()->BeginWindowSettingsPopup(); +} + +} // namespace imm + } // namespace glass diff --git a/glass/src/lib/native/include/glass/other/Log.h b/glass/src/lib/native/include/glass/other/Log.h index f054e6639c5..452ea79a81d 100644 --- a/glass/src/lib/native/include/glass/other/Log.h +++ b/glass/src/lib/native/include/glass/other/Log.h @@ -30,13 +30,13 @@ class LogData { void DisplayLog(LogData* data, bool autoScroll); -class LogView : public View { +class LogSettings { public: - explicit LogView(LogData* data) : m_data{data} {} + explicit LogSettings(LogData* data) : m_data{data} {} - void Display() override; - void Settings() override; - bool HasSettings() override; + void DisplayMenu(); + + bool IsAutoScroll() const { return m_autoScroll; } private: LogData* m_data; diff --git a/glass/src/libnt/native/cpp/NetworkTables.cpp b/glass/src/libnt/native/cpp/NetworkTables.cpp index d661ee5f05f..26e73078fc1 100644 --- a/glass/src/libnt/native/cpp/NetworkTables.cpp +++ b/glass/src/libnt/native/cpp/NetworkTables.cpp @@ -2054,30 +2054,28 @@ void glass::DisplayNetworkTables(NetworkTablesModel* model, } } -void NetworkTablesFlagsSettings::Update() { - if (!m_pTreeView) { - auto& storage = GetStorage(); - m_pTreeView = - &storage.GetBool("tree", m_defaultFlags & NetworkTablesFlags_TreeView); - m_pCombinedView = &storage.GetBool( - "combined", m_defaultFlags & NetworkTablesFlags_CombinedView); - m_pShowSpecial = &storage.GetBool( - "special", m_defaultFlags & NetworkTablesFlags_ShowSpecial); - m_pShowProperties = &storage.GetBool( - "properties", m_defaultFlags & NetworkTablesFlags_ShowProperties); - m_pShowTimestamp = &storage.GetBool( - "timestamp", m_defaultFlags & NetworkTablesFlags_ShowTimestamp); - m_pShowServerTimestamp = &storage.GetBool( - "serverTimestamp", - m_defaultFlags & NetworkTablesFlags_ShowServerTimestamp); - m_pCreateNoncanonicalKeys = &storage.GetBool( - "createNonCanonical", - m_defaultFlags & NetworkTablesFlags_CreateNoncanonicalKeys); - m_pPrecision = &storage.GetInt( - "precision", (m_defaultFlags & NetworkTablesFlags_Precision) >> - kNetworkTablesFlags_PrecisionBitShift); - } - +NetworkTablesFlagsSettings::NetworkTablesFlagsSettings( + Storage& storage, NetworkTablesFlags defaultFlags) + : m_treeView{storage.GetBool("tree", + defaultFlags & NetworkTablesFlags_TreeView)}, + m_combinedView{storage.GetBool( + "combined", defaultFlags & NetworkTablesFlags_CombinedView)}, + m_showSpecial{storage.GetBool( + "special", defaultFlags & NetworkTablesFlags_ShowSpecial)}, + m_showProperties{storage.GetBool( + "properties", defaultFlags & NetworkTablesFlags_ShowProperties)}, + m_showTimestamp{storage.GetBool( + "timestamp", defaultFlags & NetworkTablesFlags_ShowTimestamp)}, + m_showServerTimestamp{storage.GetBool( + "serverTimestamp", + defaultFlags & NetworkTablesFlags_ShowServerTimestamp)}, + m_createNoncanonicalKeys{storage.GetBool( + "createNonCanonical", + defaultFlags & NetworkTablesFlags_CreateNoncanonicalKeys)}, + m_precision{storage.GetInt( + "precision", (defaultFlags & NetworkTablesFlags_Precision) >> + kNetworkTablesFlags_PrecisionBitShift)}, + m_flags{defaultFlags} { m_flags &= ~( NetworkTablesFlags_TreeView | NetworkTablesFlags_CombinedView | NetworkTablesFlags_ShowSpecial | NetworkTablesFlags_ShowProperties | @@ -2085,53 +2083,52 @@ void NetworkTablesFlagsSettings::Update() { NetworkTablesFlags_ShowServerTimestamp | NetworkTablesFlags_CreateNoncanonicalKeys | NetworkTablesFlags_Precision); m_flags |= - (*m_pTreeView ? NetworkTablesFlags_TreeView : 0) | - (*m_pCombinedView ? NetworkTablesFlags_CombinedView : 0) | - (*m_pShowSpecial ? NetworkTablesFlags_ShowSpecial : 0) | - (*m_pShowProperties ? NetworkTablesFlags_ShowProperties : 0) | - (*m_pShowTimestamp ? NetworkTablesFlags_ShowTimestamp : 0) | - (*m_pShowServerTimestamp ? NetworkTablesFlags_ShowServerTimestamp : 0) | - (*m_pCreateNoncanonicalKeys ? NetworkTablesFlags_CreateNoncanonicalKeys - : 0) | - (*m_pPrecision << kNetworkTablesFlags_PrecisionBitShift); + (m_treeView ? NetworkTablesFlags_TreeView : 0) | + (m_combinedView ? NetworkTablesFlags_CombinedView : 0) | + (m_showSpecial ? NetworkTablesFlags_ShowSpecial : 0) | + (m_showProperties ? NetworkTablesFlags_ShowProperties : 0) | + (m_showTimestamp ? NetworkTablesFlags_ShowTimestamp : 0) | + (m_showServerTimestamp ? NetworkTablesFlags_ShowServerTimestamp : 0) | + (m_createNoncanonicalKeys ? NetworkTablesFlags_CreateNoncanonicalKeys + : 0) | + (m_precision << kNetworkTablesFlags_PrecisionBitShift); } +NetworkTablesFlagsSettings::NetworkTablesFlagsSettings( + NetworkTablesFlags defaultFlags) + : NetworkTablesFlagsSettings{GetStorage(), defaultFlags} {} + void NetworkTablesFlagsSettings::DisplayMenu() { - if (!m_pTreeView) { - return; - } - ImGui::MenuItem("Tree View", "", m_pTreeView); - ImGui::MenuItem("Combined View", "", m_pCombinedView); - ImGui::MenuItem("Show Special", "", m_pShowSpecial); - ImGui::MenuItem("Show Properties", "", m_pShowProperties); - ImGui::MenuItem("Show Timestamp", "", m_pShowTimestamp); - ImGui::MenuItem("Show Server Timestamp", "", m_pShowServerTimestamp); + auto Flag = [this](const char* label, bool& value, NetworkTablesFlags flag) { + if (ImGui::MenuItem(label, "", value)) { + if (value) { + m_flags |= flag; + } else { + m_flags &= ~flag; + } + } + }; + + Flag("Tree View", m_treeView, NetworkTablesFlags_TreeView); + Flag("Combined View", m_combinedView, NetworkTablesFlags_CombinedView); + Flag("Show Special", m_showSpecial, NetworkTablesFlags_ShowSpecial); + Flag("Show Properties", m_showProperties, NetworkTablesFlags_ShowProperties); + Flag("Show Timestamp", m_showTimestamp, NetworkTablesFlags_ShowTimestamp); + Flag("Show Server Timestamp", m_showServerTimestamp, + NetworkTablesFlags_ShowServerTimestamp); if (ImGui::BeginMenu("Decimal Precision")) { static const char* precisionOptions[] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"}; for (int i = 1; i <= 10; i++) { - if (ImGui::MenuItem(precisionOptions[i - 1], nullptr, - i == *m_pPrecision)) { - *m_pPrecision = i; + if (ImGui::MenuItem(precisionOptions[i - 1], nullptr, i == m_precision)) { + m_precision = i; + m_flags &= ~NetworkTablesFlags_Precision; + m_flags |= m_precision << kNetworkTablesFlags_PrecisionBitShift; } } ImGui::EndMenu(); } ImGui::Separator(); - ImGui::MenuItem("Allow creation of non-canonical keys", "", - m_pCreateNoncanonicalKeys); -} - -void NetworkTablesView::Display() { - m_flags.Update(); - DisplayNetworkTables(m_model, m_flags.GetFlags()); -} - -void NetworkTablesView::Settings() { - m_flags.DisplayMenu(); - DisplayNetworkTablesAddMenu(m_model, {}, m_flags.GetFlags()); -} - -bool NetworkTablesView::HasSettings() { - return true; + Flag("Allow creation of non-canonical keys", m_createNoncanonicalKeys, + NetworkTablesFlags_CreateNoncanonicalKeys); } diff --git a/glass/src/libnt/native/include/glass/networktables/NetworkTables.h b/glass/src/libnt/native/include/glass/networktables/NetworkTables.h index bca5a411925..50f525872f8 100644 --- a/glass/src/libnt/native/include/glass/networktables/NetworkTables.h +++ b/glass/src/libnt/native/include/glass/networktables/NetworkTables.h @@ -25,11 +25,11 @@ #endif #include "glass/Model.h" -#include "glass/View.h" namespace glass { class DataSource; +class Storage; class NetworkTablesModel : public Model { public: @@ -232,41 +232,25 @@ void DisplayNetworkTablesAddMenu( class NetworkTablesFlagsSettings { public: explicit NetworkTablesFlagsSettings( - NetworkTablesFlags defaultFlags = NetworkTablesFlags_Default) - : m_defaultFlags{defaultFlags}, m_flags{defaultFlags} {} + Storage& storage, + NetworkTablesFlags defaultFlags = NetworkTablesFlags_Default); + explicit NetworkTablesFlagsSettings( + NetworkTablesFlags defaultFlags = NetworkTablesFlags_Default); - void Update(); void DisplayMenu(); NetworkTablesFlags GetFlags() const { return m_flags; } private: - bool* m_pTreeView = nullptr; - bool* m_pCombinedView = nullptr; - bool* m_pShowSpecial = nullptr; - bool* m_pShowProperties = nullptr; - bool* m_pShowTimestamp = nullptr; - bool* m_pShowServerTimestamp = nullptr; - bool* m_pCreateNoncanonicalKeys = nullptr; - int* m_pPrecision = nullptr; - NetworkTablesFlags m_defaultFlags; // NOLINT - NetworkTablesFlags m_flags; // NOLINT -}; - -class NetworkTablesView : public View { - public: - explicit NetworkTablesView( - NetworkTablesModel* model, - NetworkTablesFlags defaultFlags = NetworkTablesFlags_Default) - : m_model{model}, m_flags{defaultFlags} {} - - void Display() override; - void Settings() override; - bool HasSettings() override; - - private: - NetworkTablesModel* m_model; - NetworkTablesFlagsSettings m_flags; + bool& m_treeView; + bool& m_combinedView; + bool& m_showSpecial; + bool& m_showProperties; + bool& m_showTimestamp; + bool& m_showServerTimestamp; + bool& m_createNoncanonicalKeys; + int& m_precision; + NetworkTablesFlags m_flags; // NOLINT }; } // namespace glass diff --git a/outlineviewer/src/main/native/cpp/main.cpp b/outlineviewer/src/main/native/cpp/main.cpp index 72c2b647424..16774700a12 100644 --- a/outlineviewer/src/main/native/cpp/main.cpp +++ b/outlineviewer/src/main/native/cpp/main.cpp @@ -36,7 +36,6 @@ std::string_view GetResource_ov_512_png(); static std::unique_ptr gModel; static std::unique_ptr gSettings; static glass::LogData gLog; -static glass::NetworkTablesFlagsSettings gFlagsSettings; static glass::MainMenuBar gMainMenu; static unsigned int gPrevMode = NT_NET_MODE_NONE; @@ -125,7 +124,8 @@ static void DisplayGui() { ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse); - gFlagsSettings.Update(); + auto& flagsSettings = + glass::GetStorage().GetOrNewData(); // can't create popups from within menu, so use flags bool settings = false; @@ -137,7 +137,7 @@ static void DisplayGui() { gMainMenu.WorkspaceMenu(); gui::EmitViewMenu(); if (ImGui::BeginMenu("View")) { - gFlagsSettings.DisplayMenu(); + flagsSettings.DisplayMenu(); glass::DisplayNetworkTablesAddMenu(gModel.get()); ImGui::EndMenu(); } @@ -223,7 +223,7 @@ static void DisplayGui() { // display table view glass::DisplayNetworkTablesInfo(gModel.get()); ImGui::Separator(); - glass::DisplayNetworkTables(gModel.get(), gFlagsSettings.GetFlags()); + glass::DisplayNetworkTables(gModel.get(), flagsSettings.GetFlags()); ImGui::End(); } diff --git a/simulation/halsim_gui/src/main/native/cpp/NetworkTablesSimGui.cpp b/simulation/halsim_gui/src/main/native/cpp/NetworkTablesSimGui.cpp index 763d28e8aab..45b7f895fa2 100644 --- a/simulation/halsim_gui/src/main/native/cpp/NetworkTablesSimGui.cpp +++ b/simulation/halsim_gui/src/main/native/cpp/NetworkTablesSimGui.cpp @@ -16,33 +16,42 @@ using namespace halsimgui; static std::unique_ptr gNetworkTablesModel; -static std::unique_ptr gNetworkTablesWindow; -static std::unique_ptr gNetworkTablesInfoWindow; +static glass::Window* gNetworkTablesWindow; +static glass::Window* gNetworkTablesInfoWindow; void NetworkTablesSimGui::Initialize() { gNetworkTablesModel = std::make_unique(); wpi::gui::AddEarlyExecute([] { gNetworkTablesModel->Update(); }); - gNetworkTablesWindow = std::make_unique( - glass::GetStorageRoot().GetChild("NetworkTables View"), "NetworkTables"); - gNetworkTablesWindow->SetView( - std::make_unique(gNetworkTablesModel.get())); + gNetworkTablesWindow = glass::imm::CreateWindow("NetworkTables View"); gNetworkTablesWindow->SetDefaultPos(250, 277); gNetworkTablesWindow->SetDefaultSize(750, 185); - gNetworkTablesWindow->DisableRenamePopup(); - wpi::gui::AddLateExecute([] { gNetworkTablesWindow->Display(); }); // NetworkTables info window - gNetworkTablesInfoWindow = std::make_unique( - glass::GetStorageRoot().GetChild("NetworkTables Info"), - "NetworkTables Info"); - gNetworkTablesInfoWindow->SetView(glass::MakeFunctionView( - [&] { glass::DisplayNetworkTablesInfo(gNetworkTablesModel.get()); })); + gNetworkTablesInfoWindow = glass::imm::CreateWindow( + "NetworkTables Info", false, glass::Window::kHide); gNetworkTablesInfoWindow->SetDefaultPos(250, 130); gNetworkTablesInfoWindow->SetDefaultSize(750, 145); - gNetworkTablesInfoWindow->SetDefaultVisibility(glass::Window::kHide); - gNetworkTablesInfoWindow->DisableRenamePopup(); - wpi::gui::AddLateExecute([] { gNetworkTablesInfoWindow->Display(); }); + + wpi::gui::AddLateExecute([] { + if (glass::imm::BeginWindow(gNetworkTablesWindow)) { + auto& settings = + glass::GetStorage().GetOrNewData(); + if (glass::imm::BeginWindowSettingsPopup()) { + settings.DisplayMenu(); + glass::DisplayNetworkTablesAddMenu(gNetworkTablesModel.get(), {}, + settings.GetFlags()); + ImGui::EndPopup(); + } + DisplayNetworkTables(gNetworkTablesModel.get(), settings.GetFlags()); + } + glass::imm::EndWindow(); + + if (glass::imm::BeginWindow(gNetworkTablesInfoWindow)) { + glass::DisplayNetworkTablesInfo(gNetworkTablesModel.get()); + } + glass::imm::EndWindow(); + }); wpi::gui::AddWindowScaler([](float scale) { // scale default window positions diff --git a/sysid/src/main/native/cpp/App.cpp b/sysid/src/main/native/cpp/App.cpp index 6d1b9285a32..765feff86ae 100644 --- a/sysid/src/main/native/cpp/App.cpp +++ b/sysid/src/main/native/cpp/App.cpp @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include @@ -31,8 +30,6 @@ namespace gui = wpi::gui; -static std::unique_ptr gWindowManager; - glass::Window* gLogLoaderWindow; glass::Window* gDataSelectorWindow; glass::Window* gAnalyzerWindow; @@ -98,8 +95,6 @@ void Application(std::string_view saveDir) { // Initialize window manager and add views. auto& storage = glass::GetStorageRoot().GetChild("SysId"); - gWindowManager = std::make_unique(storage); - gWindowManager->GlobalInit(); auto logLoader = std::make_unique(storage, gLogger); auto dataSelector = std::make_unique(storage, gLogger); @@ -111,16 +106,17 @@ void Application(std::string_view saveDir) { _analyzer->AnalyzeData(); }; - gLogLoaderWindow = - gWindowManager->AddWindow("Log Loader", std::move(logLoader)); - - gDataSelectorWindow = - gWindowManager->AddWindow("Data Selector", std::move(dataSelector)); - - gAnalyzerWindow = gWindowManager->AddWindow("Analyzer", std::move(analyzer)); + gLogLoaderWindow = glass::imm::CreateWindow(storage, "Log Loader"); + gDataSelectorWindow = glass::imm::CreateWindow(storage, "Data Selector"); + gAnalyzerWindow = glass::imm::CreateWindow(storage, "Analyzer"); + gProgramLogWindow = glass::imm::CreateWindow(storage, "Program Log"); - gProgramLogWindow = gWindowManager->AddWindow( - "Program Log", std::make_unique(&gLog)); + wpi::gui::AddWindowScaler([](float scale) { + gLogLoaderWindow->ScaleDefault(scale); + gDataSelectorWindow->ScaleDefault(scale); + gAnalyzerWindow->ScaleDefault(scale); + gProgramLogWindow->ScaleDefault(scale); + }); // Set default positions and sizes for windows. @@ -147,19 +143,21 @@ void Application(std::string_view saveDir) { sysid::kProgramLogWindowPos.y); gProgramLogWindow->SetDefaultSize(sysid::kProgramLogWindowSize.x, sysid::kProgramLogWindowSize.y); - gProgramLogWindow->DisableRenamePopup(); // Configure save file. gui::ConfigurePlatformSaveFile("sysid.ini"); // Add menu bar. - gui::AddLateExecute([] { + gui::AddLateExecute([&] { ImGui::BeginMainMenuBar(); gMainMenu.WorkspaceMenu(); gui::EmitViewMenu(); if (ImGui::BeginMenu("Widgets")) { - gWindowManager->DisplayMenu(); + gLogLoaderWindow->DisplayMenuItem(); + gDataSelectorWindow->DisplayMenuItem(); + gAnalyzerWindow->DisplayMenuItem(); + gProgramLogWindow->DisplayMenuItem(); ImGui::EndMenu(); } @@ -198,6 +196,32 @@ void Application(std::string_view saveDir) { } ImGui::EndPopup(); } + + if (glass::imm::BeginWindow(gLogLoaderWindow)) { + logLoader->Display(); + } + glass::imm::EndWindow(); + + if (glass::imm::BeginWindow(gDataSelectorWindow)) { + dataSelector->Display(); + } + glass::imm::EndWindow(); + + if (glass::imm::BeginWindow(gAnalyzerWindow)) { + analyzer->Display(); + } + glass::imm::EndWindow(); + + if (glass::imm::BeginWindow(gProgramLogWindow)) { + auto& settings = + glass::GetStorage().GetOrNewData(&gLog); + if (glass::imm::BeginWindowSettingsPopup()) { + settings.DisplayMenu(); + ImGui::EndPopup(); + } + glass::DisplayLog(&gLog, settings.IsAutoScroll()); + } + glass::imm::EndWindow(); }); gui::Initialize("System Identification", sysid::kAppWindowSize.x, diff --git a/sysid/src/main/native/include/sysid/view/Analyzer.h b/sysid/src/main/native/include/sysid/view/Analyzer.h index bb7763f26f8..caa3ca9c9a6 100644 --- a/sysid/src/main/native/include/sysid/view/Analyzer.h +++ b/sysid/src/main/native/include/sysid/view/Analyzer.h @@ -9,7 +9,6 @@ #include #include -#include #include #include #include @@ -34,7 +33,7 @@ namespace sysid { * load their data, visualize the data, adjust certain variables, and then view * the calculated gains. */ -class Analyzer : public glass::View { +class Analyzer { public: TestData m_data; /** @@ -82,9 +81,9 @@ class Analyzer : public glass::View { /** * Displays the analyzer widget */ - void Display() override; + void Display(); - ~Analyzer() override { AbortDataPrep(); }; + ~Analyzer() { AbortDataPrep(); }; /** * Analyzes the selected data. diff --git a/sysid/src/main/native/include/sysid/view/DataSelector.h b/sysid/src/main/native/include/sysid/view/DataSelector.h index 71732a7ed74..f6e26bc73c8 100644 --- a/sysid/src/main/native/include/sysid/view/DataSelector.h +++ b/sysid/src/main/native/include/sysid/view/DataSelector.h @@ -11,7 +11,6 @@ #include #include -#include #include #include @@ -30,7 +29,7 @@ namespace sysid { /** * Helps with loading datalog files. */ -class DataSelector : public glass::View { +class DataSelector { public: /** * Creates a data selector widget @@ -43,7 +42,7 @@ class DataSelector : public glass::View { /** * Displays the log loader window. */ - void Display() override; + void Display(); /** * Resets view. Must be called whenever the DataLogReader goes away, as this diff --git a/sysid/src/main/native/include/sysid/view/LogLoader.h b/sysid/src/main/native/include/sysid/view/LogLoader.h index 04ddd84dab3..8fc97b2c29e 100644 --- a/sysid/src/main/native/include/sysid/view/LogLoader.h +++ b/sysid/src/main/native/include/sysid/view/LogLoader.h @@ -9,7 +9,6 @@ #include #include -#include #include namespace glass { @@ -30,7 +29,7 @@ namespace sysid { /** * Helps with loading datalog files. */ -class LogLoader : public glass::View { +class LogLoader { public: /** * Creates a log loader widget @@ -39,12 +38,12 @@ class LogLoader : public glass::View { */ explicit LogLoader(glass::Storage& storage, wpi::Logger& logger); - ~LogLoader() override; + ~LogLoader(); /** * Displays the log loader window. */ - void Display() override; + void Display(); /** * Signal called when the current file is unloaded (invalidates any From fad6b68235efeec6fed743f6e3c75ae6f34cb11b Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Tue, 22 Oct 2024 08:51:52 -0600 Subject: [PATCH 2/8] Add missing include --- glass/src/lib/native/cpp/Window.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/glass/src/lib/native/cpp/Window.cpp b/glass/src/lib/native/cpp/Window.cpp index 863cf1385cb..3c0ad7c8cf9 100644 --- a/glass/src/lib/native/cpp/Window.cpp +++ b/glass/src/lib/native/cpp/Window.cpp @@ -4,6 +4,7 @@ #include "glass/Window.h" +#include #include #include From c77af7bd588b6f73e6ead4e7c22eb5f12bf47d39 Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Tue, 22 Oct 2024 08:52:23 -0600 Subject: [PATCH 3/8] Remove extraneous semicolon --- sysid/src/main/native/include/sysid/view/Analyzer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sysid/src/main/native/include/sysid/view/Analyzer.h b/sysid/src/main/native/include/sysid/view/Analyzer.h index caa3ca9c9a6..9e67f65cd08 100644 --- a/sysid/src/main/native/include/sysid/view/Analyzer.h +++ b/sysid/src/main/native/include/sysid/view/Analyzer.h @@ -83,7 +83,7 @@ class Analyzer { */ void Display(); - ~Analyzer() { AbortDataPrep(); }; + ~Analyzer() { AbortDataPrep(); } /** * Analyzes the selected data. From 595d91116b964274441216aa03b0e12177f50dfa Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Fri, 25 Oct 2024 15:04:41 -0700 Subject: [PATCH 4/8] Remove unnecessary includes --- glass/src/lib/native/cpp/WindowManager.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/glass/src/lib/native/cpp/WindowManager.cpp b/glass/src/lib/native/cpp/WindowManager.cpp index 3d25cfacd2f..3d90be5624b 100644 --- a/glass/src/lib/native/cpp/WindowManager.cpp +++ b/glass/src/lib/native/cpp/WindowManager.cpp @@ -12,11 +12,9 @@ #include #include #include -#include #include "glass/Context.h" #include "glass/Storage.h" -#include "imgui.h" using namespace glass; From 455e9e08c28190cdb0b7f65b639543a408a8a74b Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Mon, 28 Oct 2024 20:59:58 -0700 Subject: [PATCH 5/8] Update sim gui to remove HALProvider --- glass/src/lib/native/cpp/Model.cpp | 12 + glass/src/lib/native/cpp/Window.cpp | 4 +- .../native/include/glass/ContextInternal.h | 2 + glass/src/lib/native/include/glass/Model.h | 13 + glass/src/lib/native/include/glass/Window.h | 3 +- .../native/include/glass/hardware/Pneumatic.h | 15 +- .../main/native/cpp/AccelerometerSimGui.cpp | 14 +- .../src/main/native/cpp/AccelerometerSimGui.h | 9 +- .../src/main/native/cpp/AddressableLEDGui.cpp | 27 +- .../src/main/native/cpp/AddressableLEDGui.h | 9 +- .../src/main/native/cpp/AnalogGyroSimGui.cpp | 14 +- .../src/main/native/cpp/AnalogGyroSimGui.h | 9 +- .../src/main/native/cpp/AnalogInputSimGui.cpp | 36 +-- .../src/main/native/cpp/AnalogInputSimGui.h | 9 +- .../main/native/cpp/AnalogOutputSimGui.cpp | 14 +- .../src/main/native/cpp/AnalogOutputSimGui.h | 9 +- .../src/main/native/cpp/DIOSimGui.cpp | 44 ++-- .../src/main/native/cpp/DIOSimGui.h | 10 +- .../src/main/native/cpp/EncoderSimGui.cpp | 43 +-- .../src/main/native/cpp/EncoderSimGui.h | 6 +- .../src/main/native/cpp/HALProvider.cpp | 113 -------- .../src/main/native/cpp/HALSimGui.cpp | 27 +- .../src/main/native/cpp/PCMSimGui.cpp | 65 ++--- .../src/main/native/cpp/PCMSimGui.h | 16 +- .../src/main/native/cpp/PHSimGui.cpp | 63 ++--- .../halsim_gui/src/main/native/cpp/PHSimGui.h | 16 +- .../src/main/native/cpp/PWMSimGui.cpp | 36 +-- .../src/main/native/cpp/PWMSimGui.h | 9 +- .../native/cpp/PowerDistributionSimGui.cpp | 35 +-- .../main/native/cpp/PowerDistributionSimGui.h | 9 +- .../src/main/native/cpp/RelaySimGui.cpp | 36 +-- .../src/main/native/cpp/RelaySimGui.h | 9 +- .../src/main/native/cpp/RoboRioSimGui.cpp | 15 +- .../src/main/native/cpp/RoboRioSimGui.h | 9 +- .../src/main/native/cpp/SimDeviceGui.cpp | 104 +++----- .../src/main/native/cpp/SimDeviceGui.h | 50 ++++ .../src/main/native/cpp/TimingGui.cpp | 28 +- .../src/main/native/cpp/TimingGui.h | 5 +- .../halsim_gui/src/main/native/cpp/main.cpp | 248 ++++++++++++++---- .../src/main/native/include/HALProvider.h | 50 ---- .../src/main/native/include/HALSimGui.h | 28 +- .../src/main/native/include/SimDeviceGui.h | 23 -- 42 files changed, 581 insertions(+), 715 deletions(-) delete mode 100644 simulation/halsim_gui/src/main/native/cpp/HALProvider.cpp create mode 100644 simulation/halsim_gui/src/main/native/cpp/SimDeviceGui.h delete mode 100644 simulation/halsim_gui/src/main/native/include/HALProvider.h delete mode 100644 simulation/halsim_gui/src/main/native/include/SimDeviceGui.h diff --git a/glass/src/lib/native/cpp/Model.cpp b/glass/src/lib/native/cpp/Model.cpp index bee9086c86a..78408c4f6df 100644 --- a/glass/src/lib/native/cpp/Model.cpp +++ b/glass/src/lib/native/cpp/Model.cpp @@ -4,8 +4,20 @@ #include "glass/Model.h" +#include "glass/ContextInternal.h" + using namespace glass; bool Model::IsReadOnly() { return false; } + +Model* glass::AddModel(std::unique_ptr model) { + return gContext->models.emplace_back(std::move(model)).get(); +} + +void glass::UpdateModels() { + for (auto&& model : gContext->models) { + model->Update(); + } +} diff --git a/glass/src/lib/native/cpp/Window.cpp b/glass/src/lib/native/cpp/Window.cpp index 3c0ad7c8cf9..97320d43562 100644 --- a/glass/src/lib/native/cpp/Window.cpp +++ b/glass/src/lib/native/cpp/Window.cpp @@ -59,11 +59,11 @@ void Window::Display() { EndWindow(); } -bool Window::DisplayMenuItem(const char* label) { +bool Window::DisplayMenuItem(const char* label, bool enabled) { bool wasVisible = m_visible; ImGui::MenuItem( label ? label : (m_name.empty() ? m_id.c_str() : m_name.c_str()), nullptr, - &m_visible, m_enabled); + &m_visible, m_visible || (enabled && m_enabled)); return !wasVisible && m_visible; } diff --git a/glass/src/lib/native/include/glass/ContextInternal.h b/glass/src/lib/native/include/glass/ContextInternal.h index 965d8ddf248..5b53a14f9fb 100644 --- a/glass/src/lib/native/include/glass/ContextInternal.h +++ b/glass/src/lib/native/include/glass/ContextInternal.h @@ -14,6 +14,7 @@ #include #include "glass/Context.h" +#include "glass/Model.h" #include "glass/Storage.h" namespace glass { @@ -35,6 +36,7 @@ class Context { wpi::SmallVector storageStack; wpi::StringMap storageRoots; wpi::StringMap deviceHidden; + std::vector> models; wpi::StringMap sources; Storage& sourceNameStorage; uint64_t zeroTime = 0; diff --git a/glass/src/lib/native/include/glass/Model.h b/glass/src/lib/native/include/glass/Model.h index 28f546fe206..e36e1b11d38 100644 --- a/glass/src/lib/native/include/glass/Model.h +++ b/glass/src/lib/native/include/glass/Model.h @@ -4,6 +4,9 @@ #pragma once +#include +#include + namespace glass { class Model { @@ -19,4 +22,14 @@ class Model { virtual bool IsReadOnly(); }; +Model* AddModel(std::unique_ptr model); + +template T, typename... Args> +inline T* CreateModel(Args&&... args) { + return static_cast( + AddModel(std::make_unique(std::forward(args)...))); +} + +void UpdateModels(); + } // namespace glass diff --git a/glass/src/lib/native/include/glass/Window.h b/glass/src/lib/native/include/glass/Window.h index 73e8f99002a..44ca510fa06 100644 --- a/glass/src/lib/native/include/glass/Window.h +++ b/glass/src/lib/native/include/glass/Window.h @@ -117,9 +117,10 @@ class Window { * Displays menu item for the window. * @param label what to display as the menu item label; defaults to * window ID if nullptr + * @param enabled false to force-disable menu item (if window not visible) * @return True if window went from invisible to visible. */ - bool DisplayMenuItem(const char* label = nullptr); + bool DisplayMenuItem(const char* label = nullptr, bool enabled = true); /** * Scale default window position and size. diff --git a/glass/src/lib/native/include/glass/hardware/Pneumatic.h b/glass/src/lib/native/include/glass/hardware/Pneumatic.h index 0e9e525f261..cecdc773e30 100644 --- a/glass/src/lib/native/include/glass/hardware/Pneumatic.h +++ b/glass/src/lib/native/include/glass/hardware/Pneumatic.h @@ -48,24 +48,13 @@ class PneumaticControlModel : public Model { class PneumaticControlsModel : public Model { public: + virtual bool AnySolenoids() = 0; + virtual void ForEachPneumaticControl( wpi::function_ref func) = 0; }; -struct AllPneumaticControlsModel : public Model { - AllPneumaticControlsModel(std::unique_ptr pcms, - std::unique_ptr phs) - : pcms{std::move(pcms)}, phs{std::move(phs)} {}; - std::unique_ptr pcms; - std::unique_ptr phs; - void Update() override { - pcms->Update(); - phs->Update(); - }; - bool Exists() override { return true; } -}; - bool DisplayPneumaticControlSolenoids(PneumaticControlModel* model, int index, bool outputsEnabled); void DisplayPneumaticControlsSolenoids( diff --git a/simulation/halsim_gui/src/main/native/cpp/AccelerometerSimGui.cpp b/simulation/halsim_gui/src/main/native/cpp/AccelerometerSimGui.cpp index 115b4ecef50..be710610fc9 100644 --- a/simulation/halsim_gui/src/main/native/cpp/AccelerometerSimGui.cpp +++ b/simulation/halsim_gui/src/main/native/cpp/AccelerometerSimGui.cpp @@ -12,8 +12,6 @@ #include #include "HALDataSource.h" -#include "HALSimGui.h" -#include "SimDeviceGui.h" using namespace glass; using namespace halsimgui; @@ -54,10 +52,10 @@ class AccelerometerSimModel : public glass::AccelerometerModel { }; } // namespace -void AccelerometerSimGui::Initialize() { - SimDeviceGui::GetDeviceTree().Add( - std::make_unique(0), [](glass::Model* model) { - glass::DisplayAccelerometerDevice( - static_cast(model)); - }); +void halsimgui::InitializeAccelerometers(glass::DeviceTreeModel& deviceTree) { + deviceTree.Add(std::make_unique(0), + [](glass::Model* model) { + glass::DisplayAccelerometerDevice( + static_cast(model)); + }); } diff --git a/simulation/halsim_gui/src/main/native/cpp/AccelerometerSimGui.h b/simulation/halsim_gui/src/main/native/cpp/AccelerometerSimGui.h index 9028324c453..6f93a9649fa 100644 --- a/simulation/halsim_gui/src/main/native/cpp/AccelerometerSimGui.h +++ b/simulation/halsim_gui/src/main/native/cpp/AccelerometerSimGui.h @@ -4,11 +4,12 @@ #pragma once +namespace glass { +class DeviceTreeModel; +} // namespace glass + namespace halsimgui { -class AccelerometerSimGui { - public: - static void Initialize(); -}; +void InitializeAccelerometers(glass::DeviceTreeModel& deviceTree); } // namespace halsimgui diff --git a/simulation/halsim_gui/src/main/native/cpp/AddressableLEDGui.cpp b/simulation/halsim_gui/src/main/native/cpp/AddressableLEDGui.cpp index d7049362c8a..37a7f6c99ad 100644 --- a/simulation/halsim_gui/src/main/native/cpp/AddressableLEDGui.cpp +++ b/simulation/halsim_gui/src/main/native/cpp/AddressableLEDGui.cpp @@ -12,8 +12,6 @@ #include #include -#include "HALSimGui.h" - using namespace halsimgui; namespace { @@ -75,7 +73,7 @@ void AddressableLEDsModel::Update() { bool AddressableLEDsModel::Exists() { for (auto&& model : m_models) { - if (model && model->Exists()) { + if (model) { return true; } } @@ -91,25 +89,6 @@ void AddressableLEDsModel::ForEachLEDDisplay( } } -static bool AddressableLEDsExists() { - static const int numLED = HAL_GetNumAddressableLEDs(); - for (int i = 0; i < numLED; ++i) { - if (HALSIM_GetAddressableLEDInitialized(i)) { - return true; - } - } - return false; -} - -void AddressableLEDGui::Initialize() { - HALSimGui::halProvider->Register( - "Addressable LEDs", [] { return AddressableLEDsExists(); }, - [] { return std::make_unique(); }, - [](glass::Window* win, glass::Model* model) { - win->SetFlags(ImGuiWindowFlags_AlwaysAutoResize); - win->SetDefaultPos(290, 100); - return glass::MakeFunctionView([=] { - glass::DisplayLEDDisplays(static_cast(model)); - }); - }); +glass::LEDDisplaysModel* halsimgui::CreateAddressableLEDsModel() { + return glass::CreateModel(); } diff --git a/simulation/halsim_gui/src/main/native/cpp/AddressableLEDGui.h b/simulation/halsim_gui/src/main/native/cpp/AddressableLEDGui.h index 920b96513e1..b8a0c45087f 100644 --- a/simulation/halsim_gui/src/main/native/cpp/AddressableLEDGui.h +++ b/simulation/halsim_gui/src/main/native/cpp/AddressableLEDGui.h @@ -4,11 +4,12 @@ #pragma once +namespace glass { +class LEDDisplaysModel; +} // namespace glass + namespace halsimgui { -class AddressableLEDGui { - public: - static void Initialize(); -}; +glass::LEDDisplaysModel* CreateAddressableLEDsModel(); } // namespace halsimgui diff --git a/simulation/halsim_gui/src/main/native/cpp/AnalogGyroSimGui.cpp b/simulation/halsim_gui/src/main/native/cpp/AnalogGyroSimGui.cpp index 4bd328f4e46..ab5dfe08f51 100644 --- a/simulation/halsim_gui/src/main/native/cpp/AnalogGyroSimGui.cpp +++ b/simulation/halsim_gui/src/main/native/cpp/AnalogGyroSimGui.cpp @@ -14,8 +14,6 @@ #include #include "HALDataSource.h" -#include "HALSimGui.h" -#include "SimDeviceGui.h" using namespace halsimgui; @@ -88,10 +86,10 @@ void AnalogGyrosSimModel::ForEachAnalogGyro( } } -void AnalogGyroSimGui::Initialize() { - SimDeviceGui::GetDeviceTree().Add( - std::make_unique(), [](glass::Model* model) { - glass::DisplayAnalogGyrosDevice( - static_cast(model)); - }); +void halsimgui::InitializeAnalogGyros(glass::DeviceTreeModel& deviceTree) { + deviceTree.Add(std::make_unique(), + [](glass::Model* model) { + glass::DisplayAnalogGyrosDevice( + static_cast(model)); + }); } diff --git a/simulation/halsim_gui/src/main/native/cpp/AnalogGyroSimGui.h b/simulation/halsim_gui/src/main/native/cpp/AnalogGyroSimGui.h index 89f91ca7d09..905fd05ce5a 100644 --- a/simulation/halsim_gui/src/main/native/cpp/AnalogGyroSimGui.h +++ b/simulation/halsim_gui/src/main/native/cpp/AnalogGyroSimGui.h @@ -4,11 +4,12 @@ #pragma once +namespace glass { +class DeviceTreeModel; +} // namespace glass + namespace halsimgui { -class AnalogGyroSimGui { - public: - static void Initialize(); -}; +void InitializeAnalogGyros(glass::DeviceTreeModel& deviceTree); } // namespace halsimgui diff --git a/simulation/halsim_gui/src/main/native/cpp/AnalogInputSimGui.cpp b/simulation/halsim_gui/src/main/native/cpp/AnalogInputSimGui.cpp index 4a428b602ab..7184c3accb3 100644 --- a/simulation/halsim_gui/src/main/native/cpp/AnalogInputSimGui.cpp +++ b/simulation/halsim_gui/src/main/native/cpp/AnalogInputSimGui.cpp @@ -7,7 +7,6 @@ #include #include -#include #include #include #include @@ -15,7 +14,6 @@ #include #include "HALDataSource.h" -#include "HALSimGui.h" using namespace halsimgui; @@ -61,7 +59,7 @@ class AnalogInputsSimModel : public glass::AnalogInputsModel { void Update() override; - bool Exists() override { return true; } + bool Exists() override; void ForEachAnalogInput( wpi::function_ref func) @@ -87,6 +85,15 @@ void AnalogInputsSimModel::Update() { } } +bool AnalogInputsSimModel::Exists() { + for (auto&& model : m_models) { + if (model) { + return true; + } + } + return false; +} + void AnalogInputsSimModel::ForEachAnalogInput( wpi::function_ref func) { for (int32_t i = 0, iend = static_cast(m_models.size()); i < iend; @@ -97,25 +104,6 @@ void AnalogInputsSimModel::ForEachAnalogInput( } } -static bool AnalogInputsAnyInitialized() { - static const int32_t num = HAL_GetNumAnalogInputs(); - for (int32_t i = 0; i < num; ++i) { - if (HALSIM_GetAnalogInInitialized(i)) { - return true; - } - } - return false; -} - -void AnalogInputSimGui::Initialize() { - HALSimGui::halProvider->Register( - "Analog Inputs", AnalogInputsAnyInitialized, - [] { return std::make_unique(); }, - [](glass::Window* win, glass::Model* model) { - win->SetFlags(ImGuiWindowFlags_AlwaysAutoResize); - win->SetDefaultPos(640, 20); - return glass::MakeFunctionView([=] { - glass::DisplayAnalogInputs(static_cast(model)); - }); - }); +glass::AnalogInputsModel* halsimgui::CreateAnalogInputsModel() { + return glass::CreateModel(); } diff --git a/simulation/halsim_gui/src/main/native/cpp/AnalogInputSimGui.h b/simulation/halsim_gui/src/main/native/cpp/AnalogInputSimGui.h index ca358f4bef6..57ad09a4c1d 100644 --- a/simulation/halsim_gui/src/main/native/cpp/AnalogInputSimGui.h +++ b/simulation/halsim_gui/src/main/native/cpp/AnalogInputSimGui.h @@ -4,11 +4,12 @@ #pragma once +namespace glass { +class AnalogInputsModel; +} // namespace glass + namespace halsimgui { -class AnalogInputSimGui { - public: - static void Initialize(); -}; +glass::AnalogInputsModel* CreateAnalogInputsModel(); } // namespace halsimgui diff --git a/simulation/halsim_gui/src/main/native/cpp/AnalogOutputSimGui.cpp b/simulation/halsim_gui/src/main/native/cpp/AnalogOutputSimGui.cpp index 7a98bed575c..30f8a542c65 100644 --- a/simulation/halsim_gui/src/main/native/cpp/AnalogOutputSimGui.cpp +++ b/simulation/halsim_gui/src/main/native/cpp/AnalogOutputSimGui.cpp @@ -13,8 +13,6 @@ #include #include "HALDataSource.h" -#include "HALSimGui.h" -#include "SimDeviceGui.h" using namespace halsimgui; @@ -83,10 +81,10 @@ void AnalogOutputsSimModel::ForEachAnalogOutput( } } -void AnalogOutputSimGui::Initialize() { - SimDeviceGui::GetDeviceTree().Add( - std::make_unique(), [](glass::Model* model) { - glass::DisplayAnalogOutputsDevice( - static_cast(model)); - }); +void halsimgui::InitializeAnalogOutputs(glass::DeviceTreeModel& deviceTree) { + deviceTree.Add(std::make_unique(), + [](glass::Model* model) { + glass::DisplayAnalogOutputsDevice( + static_cast(model)); + }); } diff --git a/simulation/halsim_gui/src/main/native/cpp/AnalogOutputSimGui.h b/simulation/halsim_gui/src/main/native/cpp/AnalogOutputSimGui.h index f7a816b7072..2e482dd9623 100644 --- a/simulation/halsim_gui/src/main/native/cpp/AnalogOutputSimGui.h +++ b/simulation/halsim_gui/src/main/native/cpp/AnalogOutputSimGui.h @@ -4,11 +4,12 @@ #pragma once +namespace glass { +class DeviceTreeModel; +} // namespace glass + namespace halsimgui { -class AnalogOutputSimGui { - public: - static void Initialize(); -}; +void InitializeAnalogOutputs(glass::DeviceTreeModel& deviceTree); } // namespace halsimgui diff --git a/simulation/halsim_gui/src/main/native/cpp/DIOSimGui.cpp b/simulation/halsim_gui/src/main/native/cpp/DIOSimGui.cpp index 13ec169406b..907c644d66b 100644 --- a/simulation/halsim_gui/src/main/native/cpp/DIOSimGui.cpp +++ b/simulation/halsim_gui/src/main/native/cpp/DIOSimGui.cpp @@ -18,7 +18,6 @@ #include "EncoderSimGui.h" #include "HALDataSource.h" -#include "HALSimGui.h" using namespace halsimgui; @@ -129,19 +128,21 @@ class DIOSimModel : public glass::DIOModel { class DIOsSimModel : public glass::DIOsModel { public: - DIOsSimModel() - : m_dioModels(HAL_GetNumDigitalChannels()), + explicit DIOsSimModel(glass::EncodersModel& encodersModel) + : m_encodersModel{encodersModel}, + m_dioModels(HAL_GetNumDigitalChannels()), m_dpwmModels(HAL_GetNumDigitalPWMOutputs()), m_dutyCycleModels(HAL_GetNumDutyCycles()) {} void Update() override; - bool Exists() override { return true; } + bool Exists() override; void ForEachDIO( wpi::function_ref func) override; private: + glass::EncodersModel& m_encodersModel; // indexed by channel std::vector> m_dioModels; // indexed by index @@ -198,7 +199,7 @@ void DIOsSimModel::Update() { } } - EncoderSimGui::GetEncodersModel().ForEachEncoder([&](auto& encoder, int i) { + m_encodersModel.ForEachEncoder([&](auto& encoder, int i) { int channel = encoder.GetChannelA(); if (channel >= 0 && channel < numDIO && m_dioModels[channel]) { m_dioModels[channel]->SetEncoder(&encoder); @@ -210,6 +211,15 @@ void DIOsSimModel::Update() { }); } +bool DIOsSimModel::Exists() { + for (auto&& model : m_dioModels) { + if (model && model->Exists()) { + return true; + } + } + return false; +} + void DIOsSimModel::ForEachDIO( wpi::function_ref func) { const int32_t numDIO = m_dioModels.size(); @@ -220,25 +230,7 @@ void DIOsSimModel::ForEachDIO( } } -static bool DIOAnyInitialized() { - static const int32_t num = HAL_GetNumDigitalChannels(); - for (int32_t i = 0; i < num; ++i) { - if (HALSIM_GetDIOInitialized(i)) { - return true; - } - } - return false; -} - -void DIOSimGui::Initialize() { - HALSimGui::halProvider->Register( - "DIO", DIOAnyInitialized, [] { return std::make_unique(); }, - [](glass::Window* win, glass::Model* model) { - win->SetFlags(ImGuiWindowFlags_AlwaysAutoResize); - win->SetDefaultPos(470, 20); - return glass::MakeFunctionView([=] { - glass::DisplayDIOs(static_cast(model), - HALSimGui::halProvider->AreOutputsEnabled()); - }); - }); +glass::DIOsModel* halsimgui::CreateDIOsModel( + glass::EncodersModel& encodersModel) { + return glass::CreateModel(encodersModel); } diff --git a/simulation/halsim_gui/src/main/native/cpp/DIOSimGui.h b/simulation/halsim_gui/src/main/native/cpp/DIOSimGui.h index 9e9e52b5330..4d0221564c5 100644 --- a/simulation/halsim_gui/src/main/native/cpp/DIOSimGui.h +++ b/simulation/halsim_gui/src/main/native/cpp/DIOSimGui.h @@ -4,11 +4,13 @@ #pragma once +namespace glass { +class DIOsModel; +class EncodersModel; +} // namespace glass + namespace halsimgui { -class DIOSimGui { - public: - static void Initialize(); -}; +glass::DIOsModel* CreateDIOsModel(glass::EncodersModel& encodersModel); } // namespace halsimgui diff --git a/simulation/halsim_gui/src/main/native/cpp/EncoderSimGui.cpp b/simulation/halsim_gui/src/main/native/cpp/EncoderSimGui.cpp index 8e53c864d6f..b5a53b92886 100644 --- a/simulation/halsim_gui/src/main/native/cpp/EncoderSimGui.cpp +++ b/simulation/halsim_gui/src/main/native/cpp/EncoderSimGui.cpp @@ -12,14 +12,12 @@ #include #include +#include #include #include #include #include -#include "HALDataSource.h" -#include "HALSimGui.h" - using namespace halsimgui; namespace { @@ -200,7 +198,7 @@ class EncodersSimModel : public glass::EncodersModel { void Update() override; - bool Exists() override { return true; } + bool Exists() override; void ForEachEncoder( wpi::function_ref func) @@ -225,6 +223,15 @@ void EncodersSimModel::Update() { } } +bool EncodersSimModel::Exists() { + for (auto&& model : m_models) { + if (model) { + return true; + } + } + return false; +} + void EncodersSimModel::ForEachEncoder( wpi::function_ref func) { for (int32_t i = 0, iend = static_cast(m_models.size()); i < iend; @@ -235,30 +242,6 @@ void EncodersSimModel::ForEachEncoder( } } -static bool EncodersAnyInitialized() { - static const int32_t num = HAL_GetNumEncoders(); - for (int32_t i = 0; i < num; ++i) { - if (HALSIM_GetEncoderInitialized(i)) { - return true; - } - } - return false; -} - -void EncoderSimGui::Initialize() { - HALSimGui::halProvider->Register( - "Encoders", EncodersAnyInitialized, - [] { return std::make_unique(); }, - [](glass::Window* win, glass::Model* model) { - win->SetFlags(ImGuiWindowFlags_AlwaysAutoResize); - win->SetDefaultPos(5, 250); - return glass::MakeFunctionView( - [=] { DisplayEncoders(static_cast(model)); }); - }); -} - -glass::EncodersModel& EncoderSimGui::GetEncodersModel() { - static auto model = HALSimGui::halProvider->GetModel("Encoders"); - assert(model); - return *static_cast(model); +glass::EncodersModel* halsimgui::CreateEncodersModel() { + return glass::CreateModel(); } diff --git a/simulation/halsim_gui/src/main/native/cpp/EncoderSimGui.h b/simulation/halsim_gui/src/main/native/cpp/EncoderSimGui.h index f27d1801d6d..febb15b0c77 100644 --- a/simulation/halsim_gui/src/main/native/cpp/EncoderSimGui.h +++ b/simulation/halsim_gui/src/main/native/cpp/EncoderSimGui.h @@ -10,10 +10,6 @@ class EncodersModel; namespace halsimgui { -class EncoderSimGui { - public: - static void Initialize(); - static glass::EncodersModel& GetEncodersModel(); -}; +glass::EncodersModel* CreateEncodersModel(); } // namespace halsimgui diff --git a/simulation/halsim_gui/src/main/native/cpp/HALProvider.cpp b/simulation/halsim_gui/src/main/native/cpp/HALProvider.cpp deleted file mode 100644 index 7d36478b8f0..00000000000 --- a/simulation/halsim_gui/src/main/native/cpp/HALProvider.cpp +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -#include "HALProvider.h" - -#include -#include - -#include -#include -#include - -using namespace halsimgui; - -static bool gDisableOutputsOnDSDisable = true; - -HALProvider::HALProvider(glass::Storage& storage) : Provider{storage} { - storage.SetCustomApply([this] { - for (auto&& childIt : m_storage.GetChildren()) { - auto it = FindViewEntry(childIt.key()); - if (it != m_viewEntries.end() && (*it)->name == childIt.key()) { - Show(it->get(), nullptr); - } - } - for (auto&& entry : m_viewEntries) { - if (entry->showDefault) { - Show(entry.get(), entry->window); - } - } - }); - storage.SetCustomClear([this, &storage] { - for (auto&& entry : m_viewEntries) { - entry->window = nullptr; - } - m_windows.clear(); - storage.ClearValues(); - }); -} - -bool HALProvider::AreOutputsDisabled() { - return gDisableOutputsOnDSDisable && !HALSIM_GetDriverStationEnabled(); -} - -void HALProvider::DisplayMenu() { - ImGui::MenuItem("Disable outputs on DS disable", nullptr, - &gDisableOutputsOnDSDisable, true); - ImGui::Separator(); - - for (auto&& viewEntry : m_viewEntries) { - bool visible = viewEntry->window && viewEntry->window->IsVisible(); - bool wasVisible = visible; - bool exists = viewEntry->modelEntry->exists(); - if (ImGui::MenuItem(viewEntry->name.c_str(), nullptr, &visible, - visible || exists)) { - if (!wasVisible && visible) { - Show(viewEntry.get(), viewEntry->window); - if (viewEntry->window) { - viewEntry->window->SetVisible(true); - } - } else if (wasVisible && !visible && viewEntry->window) { - viewEntry->window->SetVisible(false); - } - } - } -} - -glass::Model* HALProvider::GetModel(std::string_view name) { - auto it = FindModelEntry(name); - if (it == m_modelEntries.end() || (*it)->name != name) { - return nullptr; - } - auto entry = it->get(); - - // get or create model - if (!entry->model) { - entry->model = entry->createModel(); - } - return entry->model.get(); -} - -void HALProvider::Show(ViewEntry* entry, glass::Window* window) { - // if there's already a window, we're done - if (entry->window) { - return; - } - - // get or create model - if (!entry->modelEntry->model) { - entry->modelEntry->model = entry->modelEntry->createModel(); - } - if (!entry->modelEntry->model) { - return; - } - - // the window might exist and we're just not associated to it yet - if (!window) { - window = GetOrAddWindow( - entry->name, true, - entry->showDefault ? glass::Window::kShow : glass::Window::kHide); - } - if (!window) { - return; - } - entry->window = window; - - // create view - auto view = entry->createView(window, entry->modelEntry->model.get()); - if (!view) { - return; - } - window->SetView(std::move(view)); -} diff --git a/simulation/halsim_gui/src/main/native/cpp/HALSimGui.cpp b/simulation/halsim_gui/src/main/native/cpp/HALSimGui.cpp index e6329c3b6e8..d89f2a6b16b 100644 --- a/simulation/halsim_gui/src/main/native/cpp/HALSimGui.cpp +++ b/simulation/halsim_gui/src/main/native/cpp/HALSimGui.cpp @@ -6,26 +6,26 @@ #include #include +#include "glass/MainMenuBar.h" #include #include +#include #include #include using namespace halsimgui; glass::MainMenuBar HALSimGui::mainMenu; +static bool gDisableOutputsOnDSDisable = true; + std::unique_ptr HALSimGui::manager; -std::unique_ptr HALSimGui::halProvider; std::unique_ptr HALSimGui::ntProvider; void HALSimGui::GlobalInit() { manager = std::make_unique( glass::GetStorageRoot().GetChild("SimWindow")); manager->GlobalInit(); - halProvider = std::make_unique( - glass::GetStorageRoot().GetChild("HALProvider")); - halProvider->GlobalInit(); ntProvider = std::make_unique( glass::GetStorageRoot().GetChild("NTProvider")); ntProvider->GlobalInit(); @@ -35,22 +35,27 @@ void HALSimGui::GlobalInit() { glass::AddStandardNetworkTablesViews(*ntProvider); } -namespace halsimgui { +void halsimgui::DisplayDisableMenuItem() { + ImGui::MenuItem("Disable outputs on DS disable", nullptr, + &gDisableOutputsOnDSDisable, true); +} -void AddGuiInit(std::function initialize) { +bool halsimgui::AreOutputsDisabled() { + return gDisableOutputsOnDSDisable && !HALSIM_GetDriverStationEnabled(); +} + +void halsimgui::AddGuiInit(std::function initialize) { wpi::gui::AddInit(std::move(initialize)); } -void AddGuiEarlyExecute(std::function execute) { +void halsimgui::AddGuiEarlyExecute(std::function execute) { wpi::gui::AddEarlyExecute(std::move(execute)); } -void AddGuiLateExecute(std::function execute) { +void halsimgui::AddGuiLateExecute(std::function execute) { wpi::gui::AddLateExecute(std::move(execute)); } -void GuiExit() { +void halsimgui::GuiExit() { wpi::gui::Exit(); } - -} // namespace halsimgui diff --git a/simulation/halsim_gui/src/main/native/cpp/PCMSimGui.cpp b/simulation/halsim_gui/src/main/native/cpp/PCMSimGui.cpp index 019a86c76cf..156684e379f 100644 --- a/simulation/halsim_gui/src/main/native/cpp/PCMSimGui.cpp +++ b/simulation/halsim_gui/src/main/native/cpp/PCMSimGui.cpp @@ -16,7 +16,6 @@ #include "HALDataSource.h" #include "HALSimGui.h" -#include "SimDeviceGui.h" using namespace halsimgui; @@ -99,7 +98,7 @@ class PCMSimModel : public glass::PneumaticControlModel { void Update() override; - bool Exists() override { return true; } + bool Exists() override { return HALSIM_GetCTREPCMInitialized(m_index); } CompressorSimModel* GetCompressor() override { return &m_compressor; } @@ -124,7 +123,9 @@ class PCMsSimModel : public glass::PneumaticControlsModel { void Update() override; - bool Exists() override { return true; } + bool Exists() override; + + bool AnySolenoids() override; void ForEachPneumaticControl( wpi::function_ref @@ -179,51 +180,43 @@ void PCMsSimModel::Update() { } } -void PCMsSimModel::ForEachPneumaticControl( - wpi::function_ref - func) { - int32_t numCTREPCMs = m_models.size(); - for (int32_t i = 0; i < numCTREPCMs; ++i) { - if (auto model = m_models[i].get()) { - func(*model, i); +bool PCMsSimModel::Exists() { + for (auto&& model : m_models) { + if (model) { + return true; } } + return false; } -bool PCMSimGui::PCMsAnyInitialized() { - static const int32_t num = HAL_GetNumCTREPCMModules(); - for (int32_t i = 0; i < num; ++i) { - if (HALSIM_GetCTREPCMInitialized(i)) { +bool PCMsSimModel::AnySolenoids() { + for (auto&& model : m_models) { + if (model && model->GetNumSolenoids() > 0) { return true; } } return false; } -bool PCMSimGui::PCMsAnySolenoids(glass::PneumaticControlsModel* model) { - bool any = false; - static_cast(model)->ForEachPneumaticControl( - [&](glass::PneumaticControlModel& CTREPCM, int) { - if (static_cast(&CTREPCM)->GetNumSolenoids() > 0) { - any = true; - } - }); - return any; +void PCMsSimModel::ForEachPneumaticControl( + wpi::function_ref + func) { + int32_t numCTREPCMs = m_models.size(); + for (int32_t i = 0; i < numCTREPCMs; ++i) { + if (auto model = m_models[i].get()) { + func(*model, i); + } + } } -std::unique_ptr PCMSimGui::GetPCMsModel() { - return std::make_unique(); +glass::PneumaticControlsModel* halsimgui::CreatePCMsModel() { + return glass::CreateModel(); } -void PCMSimGui::Initialize() { - HALSimGui::halProvider->RegisterModel( - "CTREPCMs", PCMSimGui::PCMsAnyInitialized, - [] { return std::make_unique(); }); - - SimDeviceGui::GetDeviceTree().Add( - HALSimGui::halProvider->GetModel("CTREPCMs"), [](glass::Model* model) { - glass::DisplayCompressorsDevice( - static_cast(model), - HALSimGui::halProvider->AreOutputsEnabled()); - }); +void halsimgui::InitializePCMs(glass::DeviceTreeModel& deviceTree, + glass::PneumaticControlsModel* model) { + deviceTree.Add(model, [](glass::Model* model) { + glass::DisplayCompressorsDevice(static_cast(model), + AreOutputsEnabled()); + }); } diff --git a/simulation/halsim_gui/src/main/native/cpp/PCMSimGui.h b/simulation/halsim_gui/src/main/native/cpp/PCMSimGui.h index d4842492671..6e943a2511f 100644 --- a/simulation/halsim_gui/src/main/native/cpp/PCMSimGui.h +++ b/simulation/halsim_gui/src/main/native/cpp/PCMSimGui.h @@ -3,18 +3,16 @@ // the WPILib BSD license file in the root directory of this project. #pragma once -#include -#include +namespace glass { +class DeviceTreeModel; +class PneumaticControlsModel; +} // namespace glass namespace halsimgui { -class PCMSimGui { - public: - static void Initialize(); - static bool PCMsAnyInitialized(); - static bool PCMsAnySolenoids(glass::PneumaticControlsModel* model); - static std::unique_ptr GetPCMsModel(); -}; +glass::PneumaticControlsModel* CreatePCMsModel(); +void InitializePCMs(glass::DeviceTreeModel& deviceTree, + glass::PneumaticControlsModel* model); } // namespace halsimgui diff --git a/simulation/halsim_gui/src/main/native/cpp/PHSimGui.cpp b/simulation/halsim_gui/src/main/native/cpp/PHSimGui.cpp index 0fc66914c7b..d3a7ee1aebb 100644 --- a/simulation/halsim_gui/src/main/native/cpp/PHSimGui.cpp +++ b/simulation/halsim_gui/src/main/native/cpp/PHSimGui.cpp @@ -16,7 +16,6 @@ #include "HALDataSource.h" #include "HALSimGui.h" -#include "SimDeviceGui.h" using namespace halsimgui; @@ -119,7 +118,9 @@ class PHsSimModel : public glass::PneumaticControlsModel { void Update() override; - bool Exists() override { return true; } + bool Exists() override; + + bool AnySolenoids() override; void ForEachPneumaticControl( wpi::function_ref @@ -174,51 +175,43 @@ void PHsSimModel::Update() { } } -void PHsSimModel::ForEachPneumaticControl( - wpi::function_ref - func) { - int32_t numREVPHs = m_models.size(); - for (int32_t i = 0; i < numREVPHs; ++i) { - if (auto model = m_models[i].get()) { - func(*model, i); +bool PHsSimModel::Exists() { + for (auto&& model : m_models) { + if (model) { + return true; } } + return false; } -bool PHSimGui::PHsAnyInitialized() { - static const int32_t num = HAL_GetNumREVPHModules(); - for (int32_t i = 0; i < num; ++i) { - if (HALSIM_GetREVPHInitialized(i)) { +bool PHsSimModel::AnySolenoids() { + for (auto&& model : m_models) { + if (model && model->GetNumSolenoids() > 0) { return true; } } return false; } -bool PHSimGui::PHsAnySolenoids(glass::PneumaticControlsModel* model) { - bool any = false; - static_cast(model)->ForEachPneumaticControl( - [&](glass::PneumaticControlModel& REVPH, int) { - if (static_cast(&REVPH)->GetNumSolenoids() > 0) { - any = true; - } - }); - return any; +void PHsSimModel::ForEachPneumaticControl( + wpi::function_ref + func) { + int32_t numREVPHs = m_models.size(); + for (int32_t i = 0; i < numREVPHs; ++i) { + if (auto model = m_models[i].get()) { + func(*model, i); + } + } } -std::unique_ptr PHSimGui::GetPHsModel() { - return std::make_unique(); +glass::PneumaticControlsModel* halsimgui::CreatePHsModel() { + return glass::CreateModel(); } -void PHSimGui::Initialize() { - HALSimGui::halProvider->RegisterModel( - "REVPHs", PHSimGui::PHsAnyInitialized, - [] { return std::make_unique(); }); - - SimDeviceGui::GetDeviceTree().Add( - HALSimGui::halProvider->GetModel("REVPHs"), [](glass::Model* model) { - glass::DisplayCompressorsDevice( - static_cast(model), - HALSimGui::halProvider->AreOutputsEnabled()); - }); +void halsimgui::InitializePHs(glass::DeviceTreeModel& deviceTree, + glass::PneumaticControlsModel* model) { + deviceTree.Add(model, [](glass::Model* model) { + glass::DisplayCompressorsDevice(static_cast(model), + AreOutputsEnabled()); + }); } diff --git a/simulation/halsim_gui/src/main/native/cpp/PHSimGui.h b/simulation/halsim_gui/src/main/native/cpp/PHSimGui.h index 348f6df963f..cd586622c93 100644 --- a/simulation/halsim_gui/src/main/native/cpp/PHSimGui.h +++ b/simulation/halsim_gui/src/main/native/cpp/PHSimGui.h @@ -3,18 +3,16 @@ // the WPILib BSD license file in the root directory of this project. #pragma once -#include -#include +namespace glass { +class DeviceTreeModel; +class PneumaticControlsModel; +} // namespace glass namespace halsimgui { -class PHSimGui { - public: - static void Initialize(); - static bool PHsAnyInitialized(); - static bool PHsAnySolenoids(glass::PneumaticControlsModel* model); - static std::unique_ptr GetPHsModel(); -}; +glass::PneumaticControlsModel* CreatePHsModel(); +void InitializePHs(glass::DeviceTreeModel& deviceTree, + glass::PneumaticControlsModel* model); } // namespace halsimgui diff --git a/simulation/halsim_gui/src/main/native/cpp/PWMSimGui.cpp b/simulation/halsim_gui/src/main/native/cpp/PWMSimGui.cpp index 2a60f9f4ef0..3a5a10b1d19 100644 --- a/simulation/halsim_gui/src/main/native/cpp/PWMSimGui.cpp +++ b/simulation/halsim_gui/src/main/native/cpp/PWMSimGui.cpp @@ -13,7 +13,6 @@ #include #include "HALDataSource.h" -#include "HALSimGui.h" using namespace halsimgui; @@ -47,7 +46,7 @@ class PWMsSimModel : public glass::PWMsModel { void Update() override; - bool Exists() override { return true; } + bool Exists() override; void ForEachPWM( wpi::function_ref func) override; @@ -83,6 +82,15 @@ void PWMsSimModel::Update() { } } +bool PWMsSimModel::Exists() { + for (auto&& model : m_sources) { + if (model && model->GetAddressableLED() == -1) { + return true; + } + } + return false; +} + void PWMsSimModel::ForEachPWM( wpi::function_ref func) { const int32_t numPWM = m_sources.size(); @@ -93,26 +101,6 @@ void PWMsSimModel::ForEachPWM( } } -static bool PWMsAnyInitialized() { - static const int32_t num = HAL_GetNumPWMChannels(); - for (int32_t i = 0; i < num; ++i) { - if (HALSIM_GetPWMInitialized(i)) { - return true; - } - } - return false; -} - -void PWMSimGui::Initialize() { - HALSimGui::halProvider->Register( - "PWM Outputs", PWMsAnyInitialized, - [] { return std::make_unique(); }, - [](glass::Window* win, glass::Model* model) { - win->SetFlags(ImGuiWindowFlags_AlwaysAutoResize); - win->SetDefaultPos(910, 20); - return glass::MakeFunctionView([=] { - glass::DisplayPWMs(static_cast(model), - HALSimGui::halProvider->AreOutputsEnabled()); - }); - }); +glass::PWMsModel* halsimgui::CreatePWMsModel() { + return glass::CreateModel(); } diff --git a/simulation/halsim_gui/src/main/native/cpp/PWMSimGui.h b/simulation/halsim_gui/src/main/native/cpp/PWMSimGui.h index d9476431a3f..b125d1ac3e6 100644 --- a/simulation/halsim_gui/src/main/native/cpp/PWMSimGui.h +++ b/simulation/halsim_gui/src/main/native/cpp/PWMSimGui.h @@ -4,11 +4,12 @@ #pragma once +namespace glass { +class PWMsModel; +} // namespace glass + namespace halsimgui { -class PWMSimGui { - public: - static void Initialize(); -}; +glass::PWMsModel* CreatePWMsModel(); } // namespace halsimgui diff --git a/simulation/halsim_gui/src/main/native/cpp/PowerDistributionSimGui.cpp b/simulation/halsim_gui/src/main/native/cpp/PowerDistributionSimGui.cpp index a3d4c2b3f72..b512839f584 100644 --- a/simulation/halsim_gui/src/main/native/cpp/PowerDistributionSimGui.cpp +++ b/simulation/halsim_gui/src/main/native/cpp/PowerDistributionSimGui.cpp @@ -14,7 +14,6 @@ #include #include "HALDataSource.h" -#include "HALSimGui.h" using namespace halsimgui; @@ -76,7 +75,7 @@ class PowerDistributionsSimModel : public glass::PowerDistributionsModel { void Update() override; - bool Exists() override { return true; } + bool Exists() override; void ForEachPowerDistribution( wpi::function_ref @@ -101,6 +100,15 @@ void PowerDistributionsSimModel::Update() { } } +bool PowerDistributionsSimModel::Exists() { + for (auto&& model : m_models) { + if (model) { + return true; + } + } + return false; +} + void PowerDistributionsSimModel::ForEachPowerDistribution( wpi::function_ref func) { @@ -112,25 +120,6 @@ void PowerDistributionsSimModel::ForEachPowerDistribution( } } -static bool PowerDistributionsAnyInitialized() { - static const int32_t num = HAL_GetNumREVPDHModules(); - for (int32_t i = 0; i < num; ++i) { - if (HALSIM_GetPowerDistributionInitialized(i)) { - return true; - } - } - return false; -} - -void PowerDistributionSimGui::Initialize() { - HALSimGui::halProvider->Register( - "PowerDistributions", PowerDistributionsAnyInitialized, - [] { return std::make_unique(); }, - [](glass::Window* win, glass::Model* model) { - win->SetDefaultPos(245, 155); - return glass::MakeFunctionView([=] { - DisplayPowerDistributions( - static_cast(model)); - }); - }); +glass::PowerDistributionsModel* halsimgui::CreatePowerDistributionsModel() { + return glass::CreateModel(); } diff --git a/simulation/halsim_gui/src/main/native/cpp/PowerDistributionSimGui.h b/simulation/halsim_gui/src/main/native/cpp/PowerDistributionSimGui.h index 10a78cc205f..b96e9dae466 100644 --- a/simulation/halsim_gui/src/main/native/cpp/PowerDistributionSimGui.h +++ b/simulation/halsim_gui/src/main/native/cpp/PowerDistributionSimGui.h @@ -4,11 +4,12 @@ #pragma once +namespace glass { +class PowerDistributionsModel; +} // namespace glass + namespace halsimgui { -class PowerDistributionSimGui { - public: - static void Initialize(); -}; +glass::PowerDistributionsModel* CreatePowerDistributionsModel(); } // namespace halsimgui diff --git a/simulation/halsim_gui/src/main/native/cpp/RelaySimGui.cpp b/simulation/halsim_gui/src/main/native/cpp/RelaySimGui.cpp index 1d163fbb32e..b75b269131e 100644 --- a/simulation/halsim_gui/src/main/native/cpp/RelaySimGui.cpp +++ b/simulation/halsim_gui/src/main/native/cpp/RelaySimGui.cpp @@ -55,7 +55,7 @@ class RelaysSimModel : public glass::RelaysModel { void Update() override; - bool Exists() override { return true; } + bool Exists() override; void ForEachRelay(wpi::function_ref func) override; @@ -81,6 +81,15 @@ void RelaysSimModel::Update() { } } +bool RelaysSimModel::Exists() { + for (auto&& model : m_models) { + if (model) { + return true; + } + } + return false; +} + void RelaysSimModel::ForEachRelay( wpi::function_ref func) { for (int32_t i = 0, iend = static_cast(m_models.size()); i < iend; @@ -91,27 +100,6 @@ void RelaysSimModel::ForEachRelay( } } -static bool RelayAnyInitialized() { - static const int32_t num = HAL_GetNumRelayHeaders(); - for (int32_t i = 0; i < num; ++i) { - if (HALSIM_GetRelayInitializedForward(i) || - HALSIM_GetRelayInitializedReverse(i)) { - return true; - } - } - return false; -} - -void RelaySimGui::Initialize() { - HALSimGui::halProvider->Register( - "Relays", RelayAnyInitialized, - [] { return std::make_unique(); }, - [](glass::Window* win, glass::Model* model) { - win->SetFlags(ImGuiWindowFlags_AlwaysAutoResize); - win->SetDefaultPos(180, 20); - return glass::MakeFunctionView([=] { - glass::DisplayRelays(static_cast(model), - HALSimGui::halProvider->AreOutputsEnabled()); - }); - }); +glass::RelaysModel* halsimgui::CreateRelaysModel() { + return glass::CreateModel(); } diff --git a/simulation/halsim_gui/src/main/native/cpp/RelaySimGui.h b/simulation/halsim_gui/src/main/native/cpp/RelaySimGui.h index cb270576dbe..67066f2084e 100644 --- a/simulation/halsim_gui/src/main/native/cpp/RelaySimGui.h +++ b/simulation/halsim_gui/src/main/native/cpp/RelaySimGui.h @@ -4,11 +4,12 @@ #pragma once +namespace glass { +class RelaysModel; +} // namespace glass + namespace halsimgui { -class RelaySimGui { - public: - static void Initialize(); -}; +glass::RelaysModel* CreateRelaysModel(); } // namespace halsimgui diff --git a/simulation/halsim_gui/src/main/native/cpp/RoboRioSimGui.cpp b/simulation/halsim_gui/src/main/native/cpp/RoboRioSimGui.cpp index 29fa7b4cf24..616558ba4dc 100644 --- a/simulation/halsim_gui/src/main/native/cpp/RoboRioSimGui.cpp +++ b/simulation/halsim_gui/src/main/native/cpp/RoboRioSimGui.cpp @@ -4,13 +4,10 @@ #include "RoboRioSimGui.h" -#include - #include #include #include "HALDataSource.h" -#include "HALSimGui.h" using namespace halsimgui; @@ -130,14 +127,6 @@ class RoboRioSimModel : public glass::RoboRioModel { }; } // namespace -void RoboRioSimGui::Initialize() { - HALSimGui::halProvider->Register( - "RoboRIO", [] { return true; }, - [] { return std::make_unique(); }, - [](glass::Window* win, glass::Model* model) { - win->SetFlags(ImGuiWindowFlags_AlwaysAutoResize); - win->SetDefaultPos(5, 125); - return glass::MakeFunctionView( - [=] { DisplayRoboRio(static_cast(model)); }); - }); +glass::RoboRioModel* halsimgui::CreateRoboRioModel() { + return glass::CreateModel(); } diff --git a/simulation/halsim_gui/src/main/native/cpp/RoboRioSimGui.h b/simulation/halsim_gui/src/main/native/cpp/RoboRioSimGui.h index 27999b58db8..7f8aa269480 100644 --- a/simulation/halsim_gui/src/main/native/cpp/RoboRioSimGui.h +++ b/simulation/halsim_gui/src/main/native/cpp/RoboRioSimGui.h @@ -4,11 +4,12 @@ #pragma once +namespace glass { +class RoboRioModel; +} // namespace glass + namespace halsimgui { -class RoboRioSimGui { - public: - static void Initialize(); -}; +glass::RoboRioModel* CreateRoboRioModel(); } // namespace halsimgui diff --git a/simulation/halsim_gui/src/main/native/cpp/SimDeviceGui.cpp b/simulation/halsim_gui/src/main/native/cpp/SimDeviceGui.cpp index aee5130e440..e267a8c40bb 100644 --- a/simulation/halsim_gui/src/main/native/cpp/SimDeviceGui.cpp +++ b/simulation/halsim_gui/src/main/native/cpp/SimDeviceGui.cpp @@ -7,66 +7,40 @@ #include #include -#include #include #include #include #include -#include #include -#include "HALDataSource.h" #include "HALSimGui.h" using namespace halsimgui; -namespace { -class SimValueSource : public glass::DataSource { - public: - explicit SimValueSource(HAL_SimValueHandle handle, const char* device, - const char* name) - : DataSource(fmt::format("{}-{}", device, name)), - m_callback{HALSIM_RegisterSimValueChangedCallback( - handle, this, CallbackFunc, true)} {} - ~SimValueSource() override { - if (m_callback != 0) { - HALSIM_CancelSimValueChangedCallback(m_callback); - } - } +SimValueSource::SimValueSource(HAL_SimValueHandle handle, const char* device, + const char* name) + : DataSource(fmt::format("{}-{}", device, name)), + m_callback{HALSIM_RegisterSimValueChangedCallback(handle, this, + CallbackFunc, true)} {} - private: - static void CallbackFunc(const char*, void* param, HAL_SimValueHandle, - int32_t, const HAL_Value* value) { - auto source = static_cast(param); - if (value->type == HAL_BOOLEAN) { - source->SetValue(value->data.v_boolean); - source->SetDigital(true); - } else if (value->type == HAL_DOUBLE) { - source->SetValue(value->data.v_double); - source->SetDigital(false); - } +SimValueSource::~SimValueSource() { + if (m_callback != 0) { + HALSIM_CancelSimValueChangedCallback(m_callback); } +} - int32_t m_callback; -}; - -class SimDevicesModel : public glass::Model { - public: - void Update() override; - bool Exists() override { return true; } - - glass::DataSource* GetSource(HAL_SimValueHandle handle) { - return m_sources[handle].get(); +void SimValueSource::CallbackFunc(const char*, void* param, HAL_SimValueHandle, + int32_t, const HAL_Value* value) { + auto source = static_cast(param); + if (value->type == HAL_BOOLEAN) { + source->SetValue(value->data.v_boolean); + source->SetDigital(true); + } else if (value->type == HAL_DOUBLE) { + source->SetValue(value->data.v_double); + source->SetDigital(false); } - - private: - wpi::DenseMap> m_sources; -}; -} // namespace - -static SimDevicesModel* gSimDevicesModel; -static bool gSimDevicesShowPrefix = false; +} void SimDevicesModel::Update() { HALSIM_EnumerateSimDevices( @@ -140,6 +114,8 @@ static void DisplaySimValue(const char* name, void* data, } } +static bool gSimDevicesShowPrefix = false; + static void DisplaySimDevice(const char* name, void* data, HAL_SimDeviceHandle handle) { std::string_view id{name}; @@ -157,38 +133,18 @@ static void DisplaySimDevice(const char* name, void* data, } } -void SimDeviceGui::Initialize() { - HALSimGui::halProvider->Register( - "Other Devices", [] { return true; }, - [] { return std::make_unique(); }, - [](glass::Window* win, glass::Model* model) { - win->SetDefaultPos(1025, 20); - win->SetDefaultSize(250, 695); - win->DisableRenamePopup(); - return glass::MakeFunctionView([=] { - if (ImGui::BeginPopupContextItem()) { - ImGui::Checkbox("Show prefix", &gSimDevicesShowPrefix); - ImGui::EndPopup(); - } - static_cast(model)->Display(); - }); - }); - HALSimGui::halProvider->ShowDefault("Other Devices"); - - auto model = std::make_unique(); - gSimDevicesModel = model.get(); - GetDeviceTree().Add(std::move(model), [](glass::Model* model) { +void halsimgui::InitializeDeviceTree(glass::DeviceTreeModel& deviceTree, + SimDevicesModel* model) { + deviceTree.Add(model, [](glass::Model* model) { HALSIM_EnumerateSimDevices("", static_cast(model), DisplaySimDevice); }); } -glass::DataSource* SimDeviceGui::GetValueSource(HAL_SimValueHandle handle) { - return gSimDevicesModel->GetSource(handle); -} - -glass::DeviceTreeModel& SimDeviceGui::GetDeviceTree() { - static auto model = HALSimGui::halProvider->GetModel("Other Devices"); - assert(model); - return *static_cast(model); +void halsimgui::DisplayDeviceTree(glass::DeviceTreeModel* model) { + if (ImGui::BeginPopupContextItem()) { + ImGui::Checkbox("Show prefix", &gSimDevicesShowPrefix); + ImGui::EndPopup(); + } + model->Display(); } diff --git a/simulation/halsim_gui/src/main/native/cpp/SimDeviceGui.h b/simulation/halsim_gui/src/main/native/cpp/SimDeviceGui.h new file mode 100644 index 00000000000..7fa42f8c9c0 --- /dev/null +++ b/simulation/halsim_gui/src/main/native/cpp/SimDeviceGui.h @@ -0,0 +1,50 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +#pragma once + +#include + +#include +#include +#include +#include + +namespace glass { +class DeviceTreeModel; +} // namespace glass + +namespace halsimgui { + +class SimValueSource : public glass::DataSource { + public: + SimValueSource(HAL_SimValueHandle handle, const char* device, + const char* name); + ~SimValueSource() override; + + private: + static void CallbackFunc(const char*, void* param, HAL_SimValueHandle, + int32_t, const HAL_Value* value); + + int32_t m_callback; +}; + +class SimDevicesModel : public glass::Model { + public: + void Update() override; + bool Exists() override { return true; } + + glass::DataSource* GetSource(HAL_SimValueHandle handle) { + return m_sources[handle].get(); + } + + private: + wpi::DenseMap> m_sources; +}; + +void InitializeDeviceTree(glass::DeviceTreeModel& deviceTree, + SimDevicesModel* model); +void DisplayDeviceTree(glass::DeviceTreeModel* model); + +} // namespace halsimgui diff --git a/simulation/halsim_gui/src/main/native/cpp/TimingGui.cpp b/simulation/halsim_gui/src/main/native/cpp/TimingGui.cpp index 043e360d571..e1cdfe63ac4 100644 --- a/simulation/halsim_gui/src/main/native/cpp/TimingGui.cpp +++ b/simulation/halsim_gui/src/main/native/cpp/TimingGui.cpp @@ -6,29 +6,16 @@ #include #include -#include #include -#include -#include #include #include #include #include -#include "HALSimGui.h" - using namespace halsimgui; -namespace { -class TimingModel : public glass::Model { - public: - void Update() override {} - bool Exists() override { return true; } -}; -} // namespace - -static void DisplayTiming() { +void halsimgui::DisplayTiming() { int32_t status = 0; uint64_t curTime = HAL_GetFPGATime(&status); @@ -69,16 +56,3 @@ static void DisplayTiming() { } ImGui::PopItemWidth(); } - -void TimingGui::Initialize() { - HALSimGui::halProvider->Register( - "Timing", [] { return true; }, - [] { return std::make_unique(); }, - [](glass::Window* win, glass::Model* model) { - win->DisableRenamePopup(); - win->SetFlags(ImGuiWindowFlags_AlwaysAutoResize); - win->SetDefaultPos(5, 150); - return glass::MakeFunctionView(DisplayTiming); - }); - HALSimGui::halProvider->ShowDefault("Timing"); -} diff --git a/simulation/halsim_gui/src/main/native/cpp/TimingGui.h b/simulation/halsim_gui/src/main/native/cpp/TimingGui.h index e87b7914f0e..fd9b3d2c7bc 100644 --- a/simulation/halsim_gui/src/main/native/cpp/TimingGui.h +++ b/simulation/halsim_gui/src/main/native/cpp/TimingGui.h @@ -6,9 +6,6 @@ namespace halsimgui { -class TimingGui { - public: - static void Initialize(); -}; +void DisplayTiming(); } // namespace halsimgui diff --git a/simulation/halsim_gui/src/main/native/cpp/main.cpp b/simulation/halsim_gui/src/main/native/cpp/main.cpp index 21fe17404f7..b36fab78240 100644 --- a/simulation/halsim_gui/src/main/native/cpp/main.cpp +++ b/simulation/halsim_gui/src/main/native/cpp/main.cpp @@ -7,8 +7,19 @@ #include #include +#include #include +#include +#include +#include +#include +#include +#include #include +#include +#include +#include +#include #include #include #include @@ -41,6 +52,39 @@ namespace gui = wpi::gui; static std::unique_ptr gPlotProvider; +static glass::AnalogInputsModel* gAnalogInputsModel; +static glass::DIOsModel* gDIOsModel; +static glass::EncodersModel* gEncodersModel; +static glass::LEDDisplaysModel* gLEDsModel; +static glass::PowerDistributionsModel* gPowerDistributionsModel; +static glass::PWMsModel* gPWMsModel; +static glass::RelaysModel* gRelaysModel; +static glass::RoboRioModel* gRoboRioModel; +static glass::PneumaticControlsModel* gPCMsModel; +static glass::PneumaticControlsModel* gPHsModel; +static SimDevicesModel* gSimDevicesModel; +static glass::DeviceTreeModel* gDeviceTreeModel; + +static glass::Window* gAnalogInputsWindow; +static glass::Window* gDIOsWindow; +static glass::Window* gEncodersWindow; +static glass::Window* gLEDsWindow; +static glass::Window* gPowerDistributionsWindow; +static glass::Window* gPWMsWindow; +static glass::Window* gRelaysWindow; +static glass::Window* gRoboRioWindow; +static glass::Window* gSolenoidsWindow; +static glass::Window* gTimingWindow; +static glass::Window* gDeviceTreeWindow; + +glass::DataSource* halsimgui::GetDeviceValueSource(HAL_SimValueHandle handle) { + return gSimDevicesModel->GetSource(handle); +} + +glass::DeviceTreeModel& halsimgui::GetDeviceTree() { + return *gDeviceTreeModel; +} + extern "C" { #if defined(WIN32) || defined(_WIN32) __declspec(dllexport) @@ -72,61 +116,107 @@ __declspec(dllexport) glass::GetStorageRoot().GetChild("Plot")); gPlotProvider->GlobalInit(); + glass::PushStorageStack("HAL"); + + // Models + // These need to initialize first - EncoderSimGui::Initialize(); - SimDeviceGui::Initialize(); - - AccelerometerSimGui::Initialize(); - AddressableLEDGui::Initialize(); - AnalogGyroSimGui::Initialize(); - AnalogInputSimGui::Initialize(); - AnalogOutputSimGui::Initialize(); - DIOSimGui::Initialize(); + gEncodersModel = CreateEncodersModel(); + gDeviceTreeModel = glass::CreateModel(); + gSimDevicesModel = glass::CreateModel(); + InitializeDeviceTree(*gDeviceTreeModel, gSimDevicesModel); + + InitializeAccelerometers(*gDeviceTreeModel); + gLEDsModel = CreateAddressableLEDsModel(); + InitializeAnalogGyros(*gDeviceTreeModel); + gAnalogInputsModel = CreateAnalogInputsModel(); + InitializeAnalogOutputs(*gDeviceTreeModel); + gDIOsModel = CreateDIOsModel(*gEncodersModel); NetworkTablesSimGui::Initialize(); - PCMSimGui::Initialize(); - PowerDistributionSimGui::Initialize(); - PWMSimGui::Initialize(); - RelaySimGui::Initialize(); - PHSimGui::Initialize(); - RoboRioSimGui::Initialize(); - TimingGui::Initialize(); - - HALSimGui::halProvider->RegisterModel( - "AllPneumaticControls", - [] { - return PCMSimGui::PCMsAnyInitialized() || PHSimGui::PHsAnyInitialized(); - }, - [] { - return std::make_unique( - PCMSimGui::GetPCMsModel(), PHSimGui::GetPHsModel()); - }); + gPCMsModel = CreatePCMsModel(); + InitializePCMs(*gDeviceTreeModel, gPCMsModel); + gPowerDistributionsModel = CreatePowerDistributionsModel(); + gPWMsModel = CreatePWMsModel(); + gRelaysModel = CreateRelaysModel(); + gPHsModel = CreatePHsModel(); + InitializePHs(*gDeviceTreeModel, gPHsModel); + gRoboRioModel = CreateRoboRioModel(); - HALSimGui::halProvider->RegisterView( - "Solenoids", "AllPneumaticControls", - [](glass::Model* model) { - auto pneumaticModel = - static_cast(model); - return PCMSimGui::PCMsAnySolenoids(pneumaticModel->pcms.get()) || - PHSimGui::PHsAnySolenoids(pneumaticModel->phs.get()); - }, - [](glass::Window* win, glass::Model* model) { - win->SetFlags(ImGuiWindowFlags_AlwaysAutoResize); - win->SetDefaultPos(290, 20); - return glass::MakeFunctionView([=] { - auto pneumaticModel = - static_cast(model); - glass::DisplayPneumaticControlsSolenoids( - pneumaticModel->pcms.get(), - HALSimGui::halProvider->AreOutputsEnabled()); - glass::DisplayPneumaticControlsSolenoids( - pneumaticModel->phs.get(), - HALSimGui::halProvider->AreOutputsEnabled()); - }); - }); + // Windows + gLEDsWindow = + glass::imm::CreateWindow("Addressable LEDs", false, glass::Window::kHide); + gLEDsWindow->SetFlags(ImGuiWindowFlags_AlwaysAutoResize); + gLEDsWindow->SetDefaultPos(290, 100); + + gAnalogInputsWindow = + glass::imm::CreateWindow("Analog Inputs", false, glass::Window::kHide); + gAnalogInputsWindow->SetFlags(ImGuiWindowFlags_AlwaysAutoResize); + gAnalogInputsWindow->SetDefaultPos(640, 20); + + gDIOsWindow = glass::imm::CreateWindow("DIO", false, glass::Window::kHide); + gDIOsWindow->SetFlags(ImGuiWindowFlags_AlwaysAutoResize); + gDIOsWindow->SetDefaultPos(470, 20); + + gEncodersWindow = + glass::imm::CreateWindow("Encoders", false, glass::Window::kHide); + gEncodersWindow->SetFlags(ImGuiWindowFlags_AlwaysAutoResize); + gEncodersWindow->SetDefaultPos(5, 250); + + gPowerDistributionsWindow = glass::imm::CreateWindow( + "Power Distributions", false, glass::Window::kHide); + gPowerDistributionsWindow->SetDefaultPos(245, 155); + + gPWMsWindow = + glass::imm::CreateWindow("PWM Outputs", false, glass::Window::kHide); + gPWMsWindow->SetFlags(ImGuiWindowFlags_AlwaysAutoResize); + gPWMsWindow->SetDefaultPos(910, 20); + + gRelaysWindow = + glass::imm::CreateWindow("Relays", false, glass::Window::kHide); + gRelaysWindow->SetFlags(ImGuiWindowFlags_AlwaysAutoResize); + gRelaysWindow->SetDefaultPos(180, 20); + + gRoboRioWindow = + glass::imm::CreateWindow("RoboRIO", false, glass::Window::kHide); + gRoboRioWindow->SetFlags(ImGuiWindowFlags_AlwaysAutoResize); + gRoboRioWindow->SetDefaultPos(5, 125); + + gSolenoidsWindow = + glass::imm::CreateWindow("Solenoids", false, glass::Window::kHide); + gSolenoidsWindow->SetFlags(ImGuiWindowFlags_AlwaysAutoResize); + gSolenoidsWindow->SetDefaultPos(290, 20); + + gTimingWindow = glass::imm::CreateWindow("Timing"); + gTimingWindow->DisableRenamePopup(); + gTimingWindow->SetFlags(ImGuiWindowFlags_AlwaysAutoResize); + gTimingWindow->SetDefaultPos(5, 150); + + gDeviceTreeWindow = glass::imm::CreateWindow("Other Devices"); + gDeviceTreeWindow->SetDefaultPos(1025, 20); + gDeviceTreeWindow->SetDefaultSize(250, 695); + gDeviceTreeWindow->DisableRenamePopup(); + + glass::PopStorageStack(); HALSimGui::mainMenu.AddMainMenu([] { if (ImGui::BeginMenu("Hardware")) { - HALSimGui::halProvider->DisplayMenu(); + DisplayDisableMenuItem(); + ImGui::Separator(); + gLEDsWindow->DisplayMenuItem(nullptr, gLEDsModel->Exists()); + gAnalogInputsWindow->DisplayMenuItem(nullptr, + gAnalogInputsModel->Exists()); + gDIOsWindow->DisplayMenuItem(nullptr, gDIOsModel->Exists()); + gEncodersWindow->DisplayMenuItem(nullptr, gEncodersModel->Exists()); + gPowerDistributionsWindow->DisplayMenuItem( + nullptr, gPowerDistributionsModel->Exists()); + gPWMsWindow->DisplayMenuItem(nullptr, gPWMsModel->Exists()); + gRelaysWindow->DisplayMenuItem(nullptr, gRelaysModel->Exists()); + gRoboRioWindow->DisplayMenuItem(nullptr, gRoboRioModel->Exists()); + gSolenoidsWindow->DisplayMenuItem( + nullptr, gPCMsModel->AnySolenoids() || gPHsModel->AnySolenoids()); + ImGui::Separator(); + gTimingWindow->DisplayMenuItem(); + gDeviceTreeWindow->DisplayMenuItem(); ImGui::EndMenu(); } if (ImGui::BeginMenu("NetworkTables")) { @@ -154,6 +244,66 @@ __declspec(dllexport) } }); + wpi::gui::AddEarlyExecute([] { glass::UpdateModels(); }); + + wpi::gui::AddLateExecute([] { + if (glass::imm::BeginWindow(gLEDsWindow)) { + glass::DisplayLEDDisplays(gLEDsModel); + } + glass::imm::EndWindow(); + + if (glass::imm::BeginWindow(gAnalogInputsWindow)) { + glass::DisplayAnalogInputs(gAnalogInputsModel); + } + glass::imm::EndWindow(); + + if (glass::imm::BeginWindow(gDIOsWindow)) { + glass::DisplayDIOs(gDIOsModel, AreOutputsEnabled()); + } + glass::imm::EndWindow(); + + if (glass::imm::BeginWindow(gEncodersWindow)) { + glass::DisplayEncoders(gEncodersModel); + } + glass::imm::EndWindow(); + + if (glass::imm::BeginWindow(gPowerDistributionsWindow)) { + DisplayPowerDistributions(gPowerDistributionsModel); + } + glass::imm::EndWindow(); + + if (glass::imm::BeginWindow(gPWMsWindow)) { + glass::DisplayPWMs(gPWMsModel, AreOutputsEnabled()); + } + glass::imm::EndWindow(); + + if (glass::imm::BeginWindow(gRelaysWindow)) { + glass::DisplayRelays(gRelaysModel, AreOutputsEnabled()); + } + glass::imm::EndWindow(); + + if (glass::imm::BeginWindow(gRoboRioWindow)) { + DisplayRoboRio(gRoboRioModel); + } + glass::imm::EndWindow(); + + if (glass::imm::BeginWindow(gSolenoidsWindow)) { + glass::DisplayPneumaticControlsSolenoids(gPCMsModel, AreOutputsEnabled()); + glass::DisplayPneumaticControlsSolenoids(gPHsModel, AreOutputsEnabled()); + } + glass::imm::EndWindow(); + + if (glass::imm::BeginWindow(gTimingWindow)) { + DisplayTiming(); + } + glass::imm::EndWindow(); + + if (glass::imm::BeginWindow(gDeviceTreeWindow)) { + DisplayDeviceTree(gDeviceTreeModel); + } + glass::imm::EndWindow(); + }); + if (!gui::Initialize("Robot Simulation", 1280, 720, ImGuiConfigFlags_DockingEnable)) { return 0; diff --git a/simulation/halsim_gui/src/main/native/include/HALProvider.h b/simulation/halsim_gui/src/main/native/include/HALProvider.h deleted file mode 100644 index 11372b11f45..00000000000 --- a/simulation/halsim_gui/src/main/native/include/HALProvider.h +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -#pragma once - -#include -#include -#include -#include -#include - -#include -#include - -namespace halsimgui { - -class HALProvider : private glass::Provider<> { - public: - explicit HALProvider(glass::Storage& storage); - - using Provider::GlobalInit; - using Provider::Register; - using Provider::RegisterModel; - using Provider::RegisterView; - using Provider::ShowDefault; - - void DisplayMenu() override; - - glass::Model* GetModel(std::string_view name); - - /** - * Returns true if outputs are disabled. - * - * @return true if outputs are disabled, false otherwise. - */ - static bool AreOutputsDisabled(); - - /** - * Returns true if outputs are enabled. - * - * @return true if outputs are enabled, false otherwise. - */ - static bool AreOutputsEnabled() { return !AreOutputsDisabled(); } - - private: - void Show(ViewEntry* entry, glass::Window* window) override; -}; - -} // namespace halsimgui diff --git a/simulation/halsim_gui/src/main/native/include/HALSimGui.h b/simulation/halsim_gui/src/main/native/include/HALSimGui.h index 50590e6b6cd..1391875b26c 100644 --- a/simulation/halsim_gui/src/main/native/include/HALSimGui.h +++ b/simulation/halsim_gui/src/main/native/include/HALSimGui.h @@ -10,8 +10,12 @@ #include #include #include +#include -#include "HALProvider.h" +namespace glass { +class DataSource; +class DeviceTreeModel; +} // namespace glass namespace halsimgui { @@ -22,10 +26,30 @@ class HALSimGui { static glass::MainMenuBar mainMenu; static std::unique_ptr manager; - static std::unique_ptr halProvider; static std::unique_ptr ntProvider; }; +void DisplayDisableMenuItem(); + +/** + * Returns true if outputs are disabled. + * + * @return true if outputs are disabled, false otherwise. + */ +bool AreOutputsDisabled(); + +/** + * Returns true if outputs are enabled. + * + * @return true if outputs are enabled, false otherwise. + */ +inline bool AreOutputsEnabled() { + return !AreOutputsDisabled(); +} + +glass::DataSource* GetDeviceValueSource(HAL_SimValueHandle handle); +glass::DeviceTreeModel& GetDeviceTree(); + void AddGuiInit(std::function initialize); void AddGuiLateExecute(std::function execute); void AddGuiEarlyExecute(std::function execute); diff --git a/simulation/halsim_gui/src/main/native/include/SimDeviceGui.h b/simulation/halsim_gui/src/main/native/include/SimDeviceGui.h deleted file mode 100644 index 84f432cbf13..00000000000 --- a/simulation/halsim_gui/src/main/native/include/SimDeviceGui.h +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -#pragma once - -#include - -namespace glass { -class DataSource; -class DeviceTreeModel; -} // namespace glass - -namespace halsimgui { - -class SimDeviceGui { - public: - static void Initialize(); - static glass::DataSource* GetValueSource(HAL_SimValueHandle handle); - static glass::DeviceTreeModel& GetDeviceTree(); -}; - -} // namespace halsimgui From 9fee4307958a106e74d191defdcf79c0ddfd3aa4 Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Mon, 28 Oct 2024 23:34:37 -0700 Subject: [PATCH 6/8] Merge NetworkTablesSimGui into simgui main --- .../main/native/cpp/NetworkTablesSimGui.cpp | 70 ------------------- .../src/main/native/cpp/NetworkTablesSimGui.h | 15 ---- .../halsim_gui/src/main/native/cpp/main.cpp | 43 +++++++++++- 3 files changed, 40 insertions(+), 88 deletions(-) delete mode 100644 simulation/halsim_gui/src/main/native/cpp/NetworkTablesSimGui.cpp delete mode 100644 simulation/halsim_gui/src/main/native/cpp/NetworkTablesSimGui.h diff --git a/simulation/halsim_gui/src/main/native/cpp/NetworkTablesSimGui.cpp b/simulation/halsim_gui/src/main/native/cpp/NetworkTablesSimGui.cpp deleted file mode 100644 index 45b7f895fa2..00000000000 --- a/simulation/halsim_gui/src/main/native/cpp/NetworkTablesSimGui.cpp +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -#include "NetworkTablesSimGui.h" - -#include - -#include -#include -#include -#include - -#include "HALSimGui.h" - -using namespace halsimgui; - -static std::unique_ptr gNetworkTablesModel; -static glass::Window* gNetworkTablesWindow; -static glass::Window* gNetworkTablesInfoWindow; - -void NetworkTablesSimGui::Initialize() { - gNetworkTablesModel = std::make_unique(); - wpi::gui::AddEarlyExecute([] { gNetworkTablesModel->Update(); }); - - gNetworkTablesWindow = glass::imm::CreateWindow("NetworkTables View"); - gNetworkTablesWindow->SetDefaultPos(250, 277); - gNetworkTablesWindow->SetDefaultSize(750, 185); - - // NetworkTables info window - gNetworkTablesInfoWindow = glass::imm::CreateWindow( - "NetworkTables Info", false, glass::Window::kHide); - gNetworkTablesInfoWindow->SetDefaultPos(250, 130); - gNetworkTablesInfoWindow->SetDefaultSize(750, 145); - - wpi::gui::AddLateExecute([] { - if (glass::imm::BeginWindow(gNetworkTablesWindow)) { - auto& settings = - glass::GetStorage().GetOrNewData(); - if (glass::imm::BeginWindowSettingsPopup()) { - settings.DisplayMenu(); - glass::DisplayNetworkTablesAddMenu(gNetworkTablesModel.get(), {}, - settings.GetFlags()); - ImGui::EndPopup(); - } - DisplayNetworkTables(gNetworkTablesModel.get(), settings.GetFlags()); - } - glass::imm::EndWindow(); - - if (glass::imm::BeginWindow(gNetworkTablesInfoWindow)) { - glass::DisplayNetworkTablesInfo(gNetworkTablesModel.get()); - } - glass::imm::EndWindow(); - }); - - wpi::gui::AddWindowScaler([](float scale) { - // scale default window positions - gNetworkTablesWindow->ScaleDefault(scale); - gNetworkTablesInfoWindow->ScaleDefault(scale); - }); -} - -void NetworkTablesSimGui::DisplayMenu() { - if (gNetworkTablesWindow) { - gNetworkTablesWindow->DisplayMenuItem("NetworkTables View"); - } - if (gNetworkTablesInfoWindow) { - gNetworkTablesInfoWindow->DisplayMenuItem("NetworkTables Info"); - } -} diff --git a/simulation/halsim_gui/src/main/native/cpp/NetworkTablesSimGui.h b/simulation/halsim_gui/src/main/native/cpp/NetworkTablesSimGui.h deleted file mode 100644 index d0d02b3342c..00000000000 --- a/simulation/halsim_gui/src/main/native/cpp/NetworkTablesSimGui.h +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -#pragma once - -namespace halsimgui { - -class NetworkTablesSimGui { - public: - static void Initialize(); - static void DisplayMenu(); -}; - -} // namespace halsimgui diff --git a/simulation/halsim_gui/src/main/native/cpp/main.cpp b/simulation/halsim_gui/src/main/native/cpp/main.cpp index b36fab78240..81c44c4ea07 100644 --- a/simulation/halsim_gui/src/main/native/cpp/main.cpp +++ b/simulation/halsim_gui/src/main/native/cpp/main.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -36,7 +37,6 @@ #include "EncoderSimGui.h" #include "HALSimGui.h" #include "HALSimGuiExt.h" -#include "NetworkTablesSimGui.h" #include "PCMSimGui.h" #include "PHSimGui.h" #include "PWMSimGui.h" @@ -52,6 +52,7 @@ namespace gui = wpi::gui; static std::unique_ptr gPlotProvider; +static glass::NetworkTablesModel* gNetworkTablesModel; static glass::AnalogInputsModel* gAnalogInputsModel; static glass::DIOsModel* gDIOsModel; static glass::EncodersModel* gEncodersModel; @@ -65,6 +66,8 @@ static glass::PneumaticControlsModel* gPHsModel; static SimDevicesModel* gSimDevicesModel; static glass::DeviceTreeModel* gDeviceTreeModel; +static glass::Window* gNetworkTablesWindow; +static glass::Window* gNetworkTablesInfoWindow; static glass::Window* gAnalogInputsWindow; static glass::Window* gDIOsWindow; static glass::Window* gEncodersWindow; @@ -116,6 +119,22 @@ __declspec(dllexport) glass::GetStorageRoot().GetChild("Plot")); gPlotProvider->GlobalInit(); + glass::PushStorageStack("NetworkTables"); + + gNetworkTablesModel = glass::CreateModel(); + + gNetworkTablesWindow = glass::imm::CreateWindow("NetworkTables View"); + gNetworkTablesWindow->SetDefaultPos(250, 277); + gNetworkTablesWindow->SetDefaultSize(750, 185); + + // NetworkTables info window + gNetworkTablesInfoWindow = glass::imm::CreateWindow( + "NetworkTables Info", false, glass::Window::kHide); + gNetworkTablesInfoWindow->SetDefaultPos(250, 130); + gNetworkTablesInfoWindow->SetDefaultSize(750, 145); + + glass::PopStorageStack(); + glass::PushStorageStack("HAL"); // Models @@ -132,7 +151,6 @@ __declspec(dllexport) gAnalogInputsModel = CreateAnalogInputsModel(); InitializeAnalogOutputs(*gDeviceTreeModel); gDIOsModel = CreateDIOsModel(*gEncodersModel); - NetworkTablesSimGui::Initialize(); gPCMsModel = CreatePCMsModel(); InitializePCMs(*gDeviceTreeModel, gPCMsModel); gPowerDistributionsModel = CreatePowerDistributionsModel(); @@ -220,7 +238,8 @@ __declspec(dllexport) ImGui::EndMenu(); } if (ImGui::BeginMenu("NetworkTables")) { - NetworkTablesSimGui::DisplayMenu(); + gNetworkTablesWindow->DisplayMenuItem(); + gNetworkTablesInfoWindow->DisplayMenuItem(); ImGui::Separator(); HALSimGui::ntProvider->DisplayMenu(); ImGui::EndMenu(); @@ -247,6 +266,24 @@ __declspec(dllexport) wpi::gui::AddEarlyExecute([] { glass::UpdateModels(); }); wpi::gui::AddLateExecute([] { + if (glass::imm::BeginWindow(gNetworkTablesWindow)) { + auto& settings = + glass::GetStorage().GetOrNewData(); + if (glass::imm::BeginWindowSettingsPopup()) { + settings.DisplayMenu(); + glass::DisplayNetworkTablesAddMenu(gNetworkTablesModel, {}, + settings.GetFlags()); + ImGui::EndPopup(); + } + DisplayNetworkTables(gNetworkTablesModel, settings.GetFlags()); + } + glass::imm::EndWindow(); + + if (glass::imm::BeginWindow(gNetworkTablesInfoWindow)) { + glass::DisplayNetworkTablesInfo(gNetworkTablesModel); + } + glass::imm::EndWindow(); + if (glass::imm::BeginWindow(gLEDsWindow)) { glass::DisplayLEDDisplays(gLEDsModel); } From 1382d8a05880cb93172d95a658f667e00ea82e75 Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Tue, 29 Oct 2024 22:46:57 -0700 Subject: [PATCH 7/8] Switch sim joysticks to immediate --- .../src/main/native/cpp/DriverStationGui.cpp | 122 +++++++++++------- .../src/main/native/cpp/DriverStationGui.h | 23 +--- .../halsim_gui/src/main/native/cpp/main.cpp | 18 +-- 3 files changed, 87 insertions(+), 76 deletions(-) diff --git a/simulation/halsim_gui/src/main/native/cpp/DriverStationGui.cpp b/simulation/halsim_gui/src/main/native/cpp/DriverStationGui.cpp index cb238d87e6a..5d5cbc7fd1c 100644 --- a/simulation/halsim_gui/src/main/native/cpp/DriverStationGui.cpp +++ b/simulation/halsim_gui/src/main/native/cpp/DriverStationGui.cpp @@ -12,10 +12,12 @@ #include #include +#define IMGUI_DEFINE_MATH_OPERATORS #include #include #include #include +#include #include #include #include @@ -276,10 +278,13 @@ static std::vector gRobotJoysticks; static std::unique_ptr gJoystickSources[HAL_kMaxJoysticks]; // FMS -static std::unique_ptr gFMSModel; +static FMSSimModel* gFMSModel; // Window management -std::unique_ptr DriverStationGui::dsManager; +static glass::Window* gFMSWindow; +static glass::Window* gJoysticksWindow; +static std::vector gKeyboardJoystickWindows; +static glass::Window* gSystemJoysticksWindow; static bool* gpDisableDS = nullptr; static bool* gpZeroDisconnectedJoysticks = nullptr; @@ -1252,8 +1257,8 @@ static void DisplaySystemJoysticks() { wpi::format_to_n_c_str(buf, sizeof(buf), "{} Settings", joy->GetName()); if (ImGui::MenuItem(buf)) { - if (auto win = DriverStationGui::dsManager->GetWindow(buf)) { - win->SetVisible(true); + if (i < gKeyboardJoystickWindows.size()) { + gKeyboardJoystickWindows[i]->SetVisible(true); } ImGui::CloseCurrentPopup(); } @@ -1378,7 +1383,7 @@ static void DisplayJoysticks() { ImGui::Columns(1); } -void DSManager::DisplayMenu() { +void halsimgui::DisplayDSMenu() { if (gpDSSocketConnected && *gpDSSocketConnected) { ImGui::MenuItem("Turn off DS (real DS connected)", nullptr, true, false); } else { @@ -1399,26 +1404,69 @@ void DSManager::DisplayMenu() { } ImGui::Separator(); - for (auto&& window : m_windows) { + gFMSWindow->DisplayMenuItem(); + gJoysticksWindow->DisplayMenuItem(); + for (auto window : gKeyboardJoystickWindows) { window->DisplayMenuItem(); } + gSystemJoysticksWindow->DisplayMenuItem(); } -void DriverStationGui::GlobalInit() { - auto& storageRoot = glass::GetStorageRoot("ds"); - dsManager = std::make_unique(storageRoot); +void halsimgui::DisplayDS() { + if (glass::imm::BeginWindow(gFMSWindow)) { + if (HALSIM_GetDriverStationDsAttached()) { + DisplayFMSReadOnly(gFMSModel); + } else { + DisplayFMS(gFMSModel, false); + } + } + glass::imm::EndWindow(); + + if (glass::imm::BeginWindow(gJoysticksWindow)) { + DisplayJoysticks(); + } + glass::imm::EndWindow(); + + for (size_t i = 0, end = gKeyboardJoystickWindows.size(); i < end; ++i) { + if (glass::imm::BeginWindow(gKeyboardJoystickWindows[i])) { + gKeyboardJoysticks[i]->SettingsDisplay(); + } + glass::imm::EndWindow(); + } + if (glass::imm::BeginWindow(gSystemJoysticksWindow)) { + DisplaySystemJoysticks(); + } + glass::imm::EndWindow(); +} + +void halsimgui::InitializeDS() { // set up system joysticks (both GLFW and keyboard) for (int i = 0; i <= GLFW_JOYSTICK_LAST; ++i) { gGlfwJoysticks.emplace_back(std::make_unique(i)); } - dsManager->GlobalInit(); - - gFMSModel = std::make_unique(); + gFMSModel = glass::CreateModel(); wpi::gui::AddEarlyExecute(DriverStationExecute); + gFMSWindow = glass::imm::CreateWindow("FMS"); + gFMSWindow->DisableRenamePopup(); + gFMSWindow->SetFlags(ImGuiWindowFlags_AlwaysAutoResize); + gFMSWindow->SetDefaultPos(5, 540); + + gSystemJoysticksWindow = glass::imm::CreateWindow("System Joysticks"); + gSystemJoysticksWindow->DisableRenamePopup(); + gSystemJoysticksWindow->SetFlags(ImGuiWindowFlags_AlwaysAutoResize); + gSystemJoysticksWindow->SetDefaultPos(5, 350); + + gJoysticksWindow = glass::imm::CreateWindow("Joysticks"); + gJoysticksWindow->DisableRenamePopup(); + gJoysticksWindow->SetFlags(ImGuiWindowFlags_AlwaysAutoResize); + gJoysticksWindow->SetDefaultPos(250, 465); + + auto& storageRoot = glass::GetStorageRoot("ds"); + storageRoot.SetCustomApply([&storageRoot] { gpDisableDS = &storageRoot.GetBool("disable", false); gpZeroDisconnectedJoysticks = @@ -1447,48 +1495,24 @@ void DriverStationGui::GlobalInit() { } int i = 0; + gKeyboardJoystickWindows.clear(); + gKeyboardJoystickWindows.reserve(gKeyboardJoysticks.size()); for (auto&& joy : gKeyboardJoysticks) { - char label[64]; - wpi::format_to_n_c_str(label, sizeof(label), "{} Settings", - joy->GetName()); - - if (auto win = dsManager->AddWindow( - label, [j = joy.get()] { j->SettingsDisplay(); }, - glass::Window::kHide)) { - win->DisableRenamePopup(); - win->SetDefaultPos(10 + 310 * i++, 50); - if (i > 3) { - i = 0; - } - win->SetDefaultSize(300, 560); - } - } - if (auto win = dsManager->AddWindow("FMS", [] { - if (HALSIM_GetDriverStationDsAttached()) { - DisplayFMSReadOnly(gFMSModel.get()); - } else { - DisplayFMS(gFMSModel.get(), false); - } - })) { - win->DisableRenamePopup(); - win->SetFlags(ImGuiWindowFlags_AlwaysAutoResize); - win->SetDefaultPos(5, 540); - } - if (auto win = - dsManager->AddWindow("System Joysticks", DisplaySystemJoysticks)) { + auto win = + glass::imm::CreateWindow(fmt::format("{} Settings", joy->GetName()), + false, glass::Window::kHide); win->DisableRenamePopup(); - win->SetFlags(ImGuiWindowFlags_AlwaysAutoResize); - win->SetDefaultPos(5, 350); - } - if (auto win = dsManager->AddWindow("Joysticks", DisplayJoysticks)) { - win->DisableRenamePopup(); - win->SetFlags(ImGuiWindowFlags_AlwaysAutoResize); - win->SetDefaultPos(250, 465); + win->SetDefaultPos(10 + 310 * i++, 50); + if (i > 3) { + i = 0; + } + win->SetDefaultSize(300, 560); + gKeyboardJoystickWindows.emplace_back(win); } }); storageRoot.SetCustomClear([&storageRoot] { - dsManager->EraseWindows(); + gKeyboardJoystickWindows.clear(); gKeyboardJoysticks.clear(); gRobotJoysticks.clear(); storageRoot.GetChildArray("keyboardJoysticks").clear(); @@ -1497,6 +1521,6 @@ void DriverStationGui::GlobalInit() { }); } -void DriverStationGui::SetDSSocketExtension(void* data) { +void halsimgui::SetDSSocketExtension(void* data) { gpDSSocketConnected = static_cast*>(data); } diff --git a/simulation/halsim_gui/src/main/native/cpp/DriverStationGui.h b/simulation/halsim_gui/src/main/native/cpp/DriverStationGui.h index 55c90a39f61..0f216059a56 100644 --- a/simulation/halsim_gui/src/main/native/cpp/DriverStationGui.h +++ b/simulation/halsim_gui/src/main/native/cpp/DriverStationGui.h @@ -4,26 +4,11 @@ #pragma once -#include -#include - -#include - namespace halsimgui { -class DSManager : public glass::WindowManager { - public: - explicit DSManager(glass::Storage& storage) : WindowManager{storage} {} - - void DisplayMenu() override; -}; - -class DriverStationGui { - public: - static void GlobalInit(); - static void SetDSSocketExtension(void* data); - - static std::unique_ptr dsManager; -}; +void InitializeDS(); +void DisplayDSMenu(); +void DisplayDS(); +void SetDSSocketExtension(void* data); } // namespace halsimgui diff --git a/simulation/halsim_gui/src/main/native/cpp/main.cpp b/simulation/halsim_gui/src/main/native/cpp/main.cpp index 81c44c4ea07..6c9d1d58f75 100644 --- a/simulation/halsim_gui/src/main/native/cpp/main.cpp +++ b/simulation/halsim_gui/src/main/native/cpp/main.cpp @@ -114,7 +114,7 @@ __declspec(dllexport) reinterpret_cast((GuiExitFn)&GuiExit)); HALSimGui::GlobalInit(); - DriverStationGui::GlobalInit(); + InitializeDS(); gPlotProvider = std::make_unique( glass::GetStorageRoot().GetChild("Plot")); gPlotProvider->GlobalInit(); @@ -245,7 +245,7 @@ __declspec(dllexport) ImGui::EndMenu(); } if (ImGui::BeginMenu("DS")) { - DriverStationGui::dsManager->DisplayMenu(); + DisplayDSMenu(); ImGui::EndMenu(); } if (ImGui::BeginMenu("Plot")) { @@ -339,18 +339,20 @@ __declspec(dllexport) DisplayDeviceTree(gDeviceTreeModel); } glass::imm::EndWindow(); + + DisplayDS(); }); if (!gui::Initialize("Robot Simulation", 1280, 720, ImGuiConfigFlags_DockingEnable)) { return 0; } - HAL_RegisterExtensionListener( - nullptr, [](void*, const char* name, void* data) { - if (std::string_view{name} == "ds_socket") { - DriverStationGui::SetDSSocketExtension(data); - } - }); + HAL_RegisterExtensionListener(nullptr, + [](void*, const char* name, void* data) { + if (std::string_view{name} == "ds_socket") { + SetDSSocketExtension(data); + } + }); HAL_SetMain( nullptr, [](void*) { From 6dd197729dafb82ed7345262190e347e38ff7e6b Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Fri, 1 Nov 2024 20:09:17 -0700 Subject: [PATCH 8/8] WIP --- glass/src/lib/native/cpp/Window.cpp | 4 +- glass/src/lib/native/include/glass/Window.h | 6 +- .../native/cpp/NetworkTablesProvider.cpp | 41 ++++++------ .../networktables/NetworkTablesProvider.h | 65 +++++++++---------- 4 files changed, 53 insertions(+), 63 deletions(-) diff --git a/glass/src/lib/native/cpp/Window.cpp b/glass/src/lib/native/cpp/Window.cpp index 97320d43562..3dc42cd4b0a 100644 --- a/glass/src/lib/native/cpp/Window.cpp +++ b/glass/src/lib/native/cpp/Window.cpp @@ -42,7 +42,7 @@ void Window::Display() { if (BeginWindow()) { if (m_renamePopupEnabled || m_view->HasSettings()) { - if (BeginWindowSettingsPopup()) { + if (imm::BeginWindowSettingsPopup()) { if (m_renamePopupEnabled) { EditName(); } @@ -118,7 +118,7 @@ void Window::EndWindow() { } } -bool Window::BeginWindowSettingsPopup() { +bool imm::BeginWindowSettingsPopup() { bool isClicked = (ImGui::IsMouseReleased(ImGuiMouseButton_Right) && ImGui::IsItemHovered()); ImGuiWindow* window = ImGui::GetCurrentWindow(); diff --git a/glass/src/lib/native/include/glass/Window.h b/glass/src/lib/native/include/glass/Window.h index 44ca510fa06..f1aab6e17aa 100644 --- a/glass/src/lib/native/include/glass/Window.h +++ b/glass/src/lib/native/include/glass/Window.h @@ -130,8 +130,6 @@ class Window { [[nodiscard]] bool BeginWindow(); void EndWindow(); - [[nodiscard]] - bool BeginWindowSettingsPopup(); bool EditName() { return ItemEditName(&m_name); } @@ -201,9 +199,7 @@ inline void EndWindow() { } [[nodiscard]] -inline bool BeginWindowSettingsPopup() { - return GetWindow()->BeginWindowSettingsPopup(); -} +bool BeginWindowSettingsPopup(); } // namespace imm diff --git a/glass/src/libnt/native/cpp/NetworkTablesProvider.cpp b/glass/src/libnt/native/cpp/NetworkTablesProvider.cpp index 36e892ecaa0..93af206e5e3 100644 --- a/glass/src/libnt/native/cpp/NetworkTablesProvider.cpp +++ b/glass/src/libnt/native/cpp/NetworkTablesProvider.cpp @@ -15,6 +15,7 @@ #include #include "glass/Storage.h" +#include "glass/Window.h" using namespace glass; @@ -23,14 +24,14 @@ NetworkTablesProvider::NetworkTablesProvider(Storage& storage) NetworkTablesProvider::NetworkTablesProvider(Storage& storage, nt::NetworkTableInstance inst) - : Provider{storage.GetChild("windows")}, + : m_windows{storage.GetChild("windows")}, m_inst{inst}, m_poller{inst}, m_typeCache{storage.GetChild("types")} { - storage.SetCustomApply([this] { + m_windows.SetCustomApply([this] { m_listener = m_poller.AddListener( {{""}}, nt::EventFlags::kImmediate | nt::EventFlags::kTopic); - for (auto&& childIt : m_storage.GetChildren()) { + for (auto&& childIt : m_windows.GetChildren()) { auto id = childIt.key(); auto typePtr = m_typeCache.FindValue(id); if (!typePtr || typePtr->type != Storage::Value::kString) { @@ -53,11 +54,7 @@ NetworkTablesProvider::NetworkTablesProvider(Storage& storage, storage.SetCustomClear([this, &storage] { m_poller.RemoveListener(m_listener); m_listener = 0; - for (auto&& modelEntry : m_modelEntries) { - modelEntry->model.reset(); - } - m_viewEntries.clear(); - m_windows.clear(); + m_windows.EraseAll(); m_typeCache.EraseAll(); storage.ClearValues(); }); @@ -66,9 +63,9 @@ NetworkTablesProvider::NetworkTablesProvider(Storage& storage, void NetworkTablesProvider::DisplayMenu() { wpi::SmallVector path; wpi::SmallString<64> name; - for (auto&& entry : m_viewEntries) { + for (auto&& entry : m_windows.GetChildren()) { path.clear(); - wpi::split(entry->name, path, '/', -1, false); + wpi::split(entry.key(), path, '/', -1, false); bool fullDepth = true; int depth = 0; @@ -81,14 +78,16 @@ void NetworkTablesProvider::DisplayMenu() { } if (fullDepth) { - bool visible = entry->window && entry->window->IsVisible(); + auto* data = entry.value().GetData(); + assert(data); + bool visible = data->window && data->window->IsVisible(); bool wasVisible = visible; // FIXME: enabled? // data is the last item, so is guaranteed to be null-terminated ImGui::MenuItem(path.back().data(), nullptr, &visible, true); // Add type label to smartdashboard sendables - if (wpi::starts_with(entry->name, "/SmartDashboard/")) { - auto typeEntry = m_typeCache.FindValue(entry->name); + if (wpi::starts_with(entry.key(), "/SmartDashboard/")) { + auto typeEntry = m_typeCache.FindValue(entry.key()); if (typeEntry) { ImGui::SameLine(); ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(96, 96, 96, 255)); @@ -99,9 +98,10 @@ void NetworkTablesProvider::DisplayMenu() { } } if (!wasVisible && visible) { - Show(entry.get(), entry->window); - } else if (wasVisible && !visible && entry->window) { - entry->window->SetVisible(false); + Show(entry.key(), data); + } else if (wasVisible && !visible && data->window) { + data->window.reset(); + data->model.reset(); } } @@ -112,8 +112,6 @@ void NetworkTablesProvider::DisplayMenu() { } void NetworkTablesProvider::Update() { - Provider::Update(); - for (auto&& event : m_poller.ReadQueue()) { if (auto info = event.GetTopicInfo()) { // add/remove entries from NT changes @@ -163,6 +161,8 @@ void NetworkTablesProvider::Update() { auto tableName = wpi::remove_suffix(topicName, "/.type").value_or(topicName); + auto& storage = m_windows.GetChild(tableName); + storage.GetOrNewData<>(); GetOrCreateView(builderIt->second, nt::Topic{valueData->topic}, tableName); // cache the type @@ -173,8 +173,9 @@ void NetworkTablesProvider::Update() { void NetworkTablesProvider::Register(std::string_view typeName, CreateModelFunc createModel, - CreateViewFunc createView) { - m_typeMap[typeName] = Builder{std::move(createModel), std::move(createView)}; + SetupWindowFunc setupWindow, + DisplayFunc display) { + m_typeMap[typeName] = Builder{std::move(createModel), std::move(setupWindow), std::move(display)}; } void NetworkTablesProvider::Show(ViewEntry* entry, Window* window) { diff --git a/glass/src/libnt/native/include/glass/networktables/NetworkTablesProvider.h b/glass/src/libnt/native/include/glass/networktables/NetworkTablesProvider.h index cba34cc6693..3f3a35faad2 100644 --- a/glass/src/libnt/native/include/glass/networktables/NetworkTablesProvider.h +++ b/glass/src/libnt/native/include/glass/networktables/NetworkTablesProvider.h @@ -17,31 +17,21 @@ #include #include "glass/Model.h" -#include "glass/Provider.h" +#include "glass/Storage.h" namespace glass { class Window; -namespace detail { -struct NTProviderFunctions { - using Exists = - std::function; - using CreateModel = std::function( - nt::NetworkTableInstance inst, const char* path)>; - using ViewExists = std::function; - using CreateView = - std::function(Window*, Model*, const char* path)>; -}; -} // namespace detail - /** - * A provider for NetworkTables (SmartDashboard style) models and views. + * NetworkTables (SmartDashboard style) windows. */ -class NetworkTablesProvider : private Provider { +class NetworkTablesProvider { public: - using Provider::CreateModelFunc; - using Provider::CreateViewFunc; + using CreateModelFunc = std::function( + nt::NetworkTableInstance inst, const char* path)>; + using SetupWindowFunc = std::function; + using DisplayFunc = std::function; explicit NetworkTablesProvider(Storage& storage); NetworkTablesProvider(Storage& storage, nt::NetworkTableInstance inst); @@ -54,28 +44,30 @@ class NetworkTablesProvider : private Provider { nt::NetworkTableInstance GetInstance() const { return m_inst; } /** - * Perform global initialization. This should be called prior to - * wpi::gui::Initialize(). + * Displays all windows. */ - void GlobalInit() override { Provider::GlobalInit(); } + void Display(); /** * Displays menu contents as a tree of available NetworkTables views. */ - void DisplayMenu() override; + void DisplayMenu(); /** - * Registers a NetworkTables model and view. + * Registers a NetworkTables model and display. * * @param typeName SmartDashboard .type value to match * @param createModel functor to create model - * @param createView functor to create view + * @param setupWindow functor to set up window + * @param display functor to display window content */ void Register(std::string_view typeName, CreateModelFunc createModel, - CreateViewFunc createView); + SetupWindowFunc setupWindow, DisplayFunc display); + + void Update(); private: - void Update() override; + Storage& m_windows; nt::NetworkTableInstance m_inst; nt::NetworkTableListenerPoller m_poller; @@ -86,10 +78,11 @@ class NetworkTablesProvider : private Provider { struct Builder { CreateModelFunc createModel; - CreateViewFunc createView; + SetupWindowFunc setupWindow; + DisplayFunc display; }; - // mapping from .type string to model/view creators + // mapping from .type string to builders wpi::StringMap m_typeMap; struct SubListener { @@ -100,18 +93,18 @@ class NetworkTablesProvider : private Provider { // mapping from .type topic to subscriber/listener wpi::DenseMap m_topicMap; - struct Entry : public ModelEntry { - Entry(nt::Topic typeTopic, std::string_view name, const Builder& builder) - : ModelEntry{name, [](auto, const char*) { return true; }, - builder.createModel}, - typeTopic{typeTopic} {} - nt::Topic typeTopic; - }; - - void Show(ViewEntry* entry, Window* window) override; + struct Entry { + explicit Entry(Storage& storage) : typeString{storage.GetString("type")} {} + std::string& typeString; + std::unique_ptr model; + std::unique_ptr window; + }; + // active windows +#if 0 ViewEntry* GetOrCreateView(const Builder& builder, nt::Topic typeTopic, std::string_view name); +#endif }; /**