diff --git a/simulation/halsim_gui/src/main/native/cpp/AnalogInputGui.cpp b/simulation/halsim_gui/src/main/native/cpp/AnalogInputGui.cpp index 0918a6963a..c2b1ada2b8 100644 --- a/simulation/halsim_gui/src/main/native/cpp/AnalogInputGui.cpp +++ b/simulation/halsim_gui/src/main/native/cpp/AnalogInputGui.cpp @@ -1,5 +1,5 @@ /*----------------------------------------------------------------------------*/ -/* Copyright (c) 2019 FIRST. All Rights Reserved. */ +/* Copyright (c) 2019-2020 FIRST. All Rights Reserved. */ /* Open Source Software - may be modified and shared by FRC teams. The code */ /* must be accompanied by the FIRST BSD license file in the root directory of */ /* the project. */ @@ -7,8 +7,6 @@ #include "AnalogInputGui.h" -#include - #include #include #include @@ -16,9 +14,13 @@ #include #include "HALSimGui.h" +#include "IniSaver.h" +#include "IniSaverInfo.h" using namespace halsimgui; +static IniSaver gAnalogInputs{"AnalogInput"}; // indexed by channel + static void DisplayAnalogInputs() { ImGui::Text("(Use Ctrl+Click to edit value)"); bool hasInputs = false; @@ -36,8 +38,11 @@ static void DisplayAnalogInputs() { first = false; } - char name[32]; - std::snprintf(name, sizeof(name), "In[%d]", i); + auto& info = gAnalogInputs[i]; + // build name + char name[128]; + info.GetName(name, sizeof(name), "In", i); + if (i < numAccum && HALSIM_GetAnalogGyroInitialized(i)) { ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(96, 96, 96, 255)); ImGui::LabelText(name, "AnalogGyro[%d]", i); @@ -51,12 +56,16 @@ static void DisplayAnalogInputs() { if (ImGui::SliderFloat(name, &val, 0.0, 5.0)) HALSIM_SetAnalogInVoltage(i, val); } + + // context menu to change name + info.PopupEditName(i); } } if (!hasInputs) ImGui::Text("No analog inputs"); } void AnalogInputGui::Initialize() { + gAnalogInputs.Initialize(); HALSimGui::AddWindow("Analog Inputs", DisplayAnalogInputs, ImGuiWindowFlags_AlwaysAutoResize); HALSimGui::SetDefaultWindowPos("Analog Inputs", 640, 20); diff --git a/simulation/halsim_gui/src/main/native/cpp/AnalogOutGui.cpp b/simulation/halsim_gui/src/main/native/cpp/AnalogOutGui.cpp index 38b69a9f6d..e347bf5785 100644 --- a/simulation/halsim_gui/src/main/native/cpp/AnalogOutGui.cpp +++ b/simulation/halsim_gui/src/main/native/cpp/AnalogOutGui.cpp @@ -1,5 +1,5 @@ /*----------------------------------------------------------------------------*/ -/* Copyright (c) 2019 FIRST. All Rights Reserved. */ +/* Copyright (c) 2019-2020 FIRST. All Rights Reserved. */ /* Open Source Software - may be modified and shared by FRC teams. The code */ /* must be accompanied by the FIRST BSD license file in the root directory of */ /* the project. */ @@ -7,18 +7,18 @@ #include "AnalogOutGui.h" -#include -#include -#include - #include #include #include +#include "IniSaver.h" +#include "IniSaverInfo.h" #include "SimDeviceGui.h" using namespace halsimgui; +static IniSaver gAnalogOuts{"AnalogOut"}; // indexed by channel + static void DisplayAnalogOutputs() { static const int numAnalog = HAL_GetNumAnalogOutputs(); static auto init = std::make_unique(numAnalog); @@ -34,14 +34,20 @@ static void DisplayAnalogOutputs() { if (SimDeviceGui::StartDevice("Analog Outputs")) { for (int i = 0; i < numAnalog; ++i) { if (!init[i]) continue; - char name[32]; - std::snprintf(name, sizeof(name), "Out[%d]", i); + + auto& info = gAnalogOuts[i]; + char name[128]; + info.GetName(name, sizeof(name), "Out", i); HAL_Value value = HAL_MakeDouble(HALSIM_GetAnalogOutVoltage(i)); SimDeviceGui::DisplayValue(name, true, &value); + info.PopupEditName(i); } SimDeviceGui::FinishDevice(); } } -void AnalogOutGui::Initialize() { SimDeviceGui::Add(DisplayAnalogOutputs); } +void AnalogOutGui::Initialize() { + gAnalogOuts.Initialize(); + SimDeviceGui::Add(DisplayAnalogOutputs); +} diff --git a/simulation/halsim_gui/src/main/native/cpp/DIOGui.cpp b/simulation/halsim_gui/src/main/native/cpp/DIOGui.cpp index 7c9eae5ecc..7647cef85f 100644 --- a/simulation/halsim_gui/src/main/native/cpp/DIOGui.cpp +++ b/simulation/halsim_gui/src/main/native/cpp/DIOGui.cpp @@ -1,5 +1,5 @@ /*----------------------------------------------------------------------------*/ -/* Copyright (c) 2019 FIRST. All Rights Reserved. */ +/* Copyright (c) 2019-2020 FIRST. All Rights Reserved. */ /* Open Source Software - may be modified and shared by FRC teams. The code */ /* must be accompanied by the FIRST BSD license file in the root directory of */ /* the project. */ @@ -7,10 +7,6 @@ #include "DIOGui.h" -#include -#include -#include - #include #include #include @@ -20,9 +16,13 @@ #include #include "HALSimGui.h" +#include "IniSaver.h" +#include "IniSaverInfo.h" using namespace halsimgui; +static IniSaver gDIO{"DIO"}; + static void LabelSimDevice(const char* name, HAL_SimDeviceHandle simDevice) { ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(96, 96, 96, 255)); ImGui::LabelText(name, "%s", HALSIM_GetSimDeviceName(simDevice)); @@ -71,9 +71,10 @@ static void DisplayDIO() { for (int i = 0; i < numDIO; ++i) { if (HALSIM_GetDIOInitialized(i)) { hasAny = true; - char name[32]; + auto& info = gDIO[i]; + char name[128]; if (pwmMap[i] > 0) { - std::snprintf(name, sizeof(name), "PWM[%d]", i); + info.GetName(name, sizeof(name), "PWM", i); if (auto simDevice = HALSIM_GetDIOSimDevice(i)) { LabelSimDevice(name, simDevice); } else { @@ -81,7 +82,7 @@ static void DisplayDIO() { HALSIM_GetDigitalPWMDutyCycle(pwmMap[i] - 1)); } } else if (encoderMap[i] > 0) { - std::snprintf(name, sizeof(name), " In[%d]", i); + info.GetName(name, sizeof(name), " In", i); if (auto simDevice = HALSIM_GetEncoderSimDevice(encoderMap[i] - 1)) { LabelSimDevice(name, simDevice); } else { @@ -92,7 +93,7 @@ static void DisplayDIO() { ImGui::PopStyleColor(); } } else if (dutyCycleMap[i] > 0) { - std::snprintf(name, sizeof(name), "PWM[%d]", i); + info.GetName(name, sizeof(name), "Dty", i); if (auto simDevice = HALSIM_GetDutyCycleSimDevice(dutyCycleMap[i] - 1)) { LabelSimDevice(name, simDevice); @@ -102,7 +103,7 @@ static void DisplayDIO() { HALSIM_SetDutyCycleOutput(dutyCycleMap[i] - 1, val); } } else if (!HALSIM_GetDIOIsInput(i)) { - std::snprintf(name, sizeof(name), "Out[%d]", i); + info.GetName(name, sizeof(name), "Out", i); if (auto simDevice = HALSIM_GetDIOSimDevice(i)) { LabelSimDevice(name, simDevice); } else { @@ -110,7 +111,7 @@ static void DisplayDIO() { HALSIM_GetDIOValue(i) ? "1 (high)" : "0 (low)"); } } else { - std::snprintf(name, sizeof(name), " In[%d]", i); + info.GetName(name, sizeof(name), " In", i); if (auto simDevice = HALSIM_GetDIOSimDevice(i)) { LabelSimDevice(name, simDevice); } else { @@ -119,6 +120,7 @@ static void DisplayDIO() { if (ImGui::Combo(name, &val, options, 2)) HALSIM_SetDIOValue(i, val); } } + info.PopupEditName(i); } } ImGui::PopItemWidth(); @@ -126,6 +128,7 @@ static void DisplayDIO() { } void DIOGui::Initialize() { + gDIO.Initialize(); HALSimGui::AddWindow("DIO", DisplayDIO, ImGuiWindowFlags_AlwaysAutoResize); HALSimGui::SetDefaultWindowPos("DIO", 470, 20); } diff --git a/simulation/halsim_gui/src/main/native/cpp/DriverStationGui.cpp b/simulation/halsim_gui/src/main/native/cpp/DriverStationGui.cpp index 1e2f879a73..38fd90e268 100644 --- a/simulation/halsim_gui/src/main/native/cpp/DriverStationGui.cpp +++ b/simulation/halsim_gui/src/main/native/cpp/DriverStationGui.cpp @@ -1,5 +1,5 @@ /*----------------------------------------------------------------------------*/ -/* Copyright (c) 2019 FIRST. All Rights Reserved. */ +/* Copyright (c) 2019-2020 FIRST. All Rights Reserved. */ /* Open Source Software - may be modified and shared by FRC teams. The code */ /* must be accompanied by the FIRST BSD license file in the root directory of */ /* the project. */ @@ -22,6 +22,7 @@ #include "ExtraGuiWidgets.h" #include "HALSimGui.h" +#include "IniSaverInfo.h" using namespace halsimgui; @@ -45,6 +46,7 @@ struct SystemJoystick { }; struct RobotJoystick { + NameInfo name; std::string guid; const SystemJoystick* sys = nullptr; bool useGamepad = false; @@ -93,6 +95,8 @@ static void JoystickReadLine(ImGuiContext* ctx, ImGuiSettingsHandler* handler, int num; if (value.getAsInteger(10, num)) return; joy->useGamepad = num; + } else { + joy->name.ReadIni(name, value); } } @@ -100,11 +104,15 @@ static void JoystickWriteAll(ImGuiContext* ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* out_buf) { for (int i = 0; i < HAL_kMaxJoysticks; ++i) { auto& joy = gRobotJoysticks[i]; - if (!joy.sys) continue; - const char* guid = glfwGetJoystickGUID(joy.sys - gSystemJoysticks); - if (!guid) continue; - out_buf->appendf("[Joystick][%d]\nguid=%s\nuseGamepad=%d\n\n", i, guid, + if (!joy.name.HasName() && !joy.sys) continue; + out_buf->appendf("[Joystick][%d]\nuseGamepad=%d\n", i, joy.useGamepad ? 1 : 0); + if (joy.name.HasName()) joy.name.WriteIni(out_buf); + if (joy.sys) { + const char* guid = glfwGetJoystickGUID(joy.sys - gSystemJoysticks); + if (guid) out_buf->appendf("guid=%s\n", guid); + } + out_buf->append("\n"); } } @@ -426,8 +434,8 @@ static void DisplayJoysticks() { ImGui::Columns(HAL_kMaxJoysticks, "Joysticks", false); for (int i = 0; i < HAL_kMaxJoysticks; ++i) { auto& joy = gRobotJoysticks[i]; - char label[30]; - std::snprintf(label, sizeof(label), "Joystick %d", i); + char label[128]; + joy.name.GetName(label, sizeof(label), "Joystick", i); if (joy.sys) { ImGui::Selectable(label, false); if (ImGui::BeginDragDropSource()) { @@ -455,6 +463,7 @@ static void DisplayJoysticks() { } ImGui::EndDragDropTarget(); } + joy.name.PopupEditName(i); ImGui::NextColumn(); } ImGui::Separator(); diff --git a/simulation/halsim_gui/src/main/native/cpp/EncoderGui.cpp b/simulation/halsim_gui/src/main/native/cpp/EncoderGui.cpp index bf8c52e5f9..98bc616cfc 100644 --- a/simulation/halsim_gui/src/main/native/cpp/EncoderGui.cpp +++ b/simulation/halsim_gui/src/main/native/cpp/EncoderGui.cpp @@ -7,8 +7,6 @@ #include "EncoderGui.h" -#include - #include #include #include @@ -20,7 +18,21 @@ using namespace halsimgui; -static IniSaver gEncoders{"Encoder"}; // indexed by channel A +namespace { +struct EncoderInfo : public NameInfo, public OpenInfo { + bool ReadIni(wpi::StringRef name, wpi::StringRef value) { + if (NameInfo::ReadIni(name, value)) return true; + if (OpenInfo::ReadIni(name, value)) return true; + return false; + } + void WriteIni(ImGuiTextBuffer* out) { + NameInfo::WriteIni(out); + OpenInfo::WriteIni(out); + } +}; +} // namespace + +static IniSaver gEncoders{"Encoder"}; // indexed by channel A static void DisplayEncoders() { bool hasAny = false; @@ -29,55 +41,61 @@ static void DisplayEncoders() { for (int i = 0; i < numEncoder; ++i) { if (HALSIM_GetEncoderInitialized(i)) { hasAny = true; - char name[32]; - int chA = HALSIM_GetEncoderDigitalChannelA(i); - int chB = HALSIM_GetEncoderDigitalChannelB(i); - std::snprintf(name, sizeof(name), "Encoder[%d,%d]", chA, chB); if (auto simDevice = HALSIM_GetEncoderSimDevice(i)) { ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(96, 96, 96, 255)); ImGui::Text("%s", HALSIM_GetSimDeviceName(simDevice)); ImGui::PopStyleColor(); - } else if (ImGui::CollapsingHeader(name, - gEncoders[chA].IsOpen() - ? ImGuiTreeNodeFlags_DefaultOpen - : 0)) { - gEncoders[chA].SetOpen(true); - - ImGui::PushID(i); - - // distance per pulse - double distancePerPulse = HALSIM_GetEncoderDistancePerPulse(i); - ImGui::LabelText("Dist/Count", "%.6f", distancePerPulse); - - // count - int count = HALSIM_GetEncoderCount(i); - if (ImGui::InputInt("Count", &count)) HALSIM_SetEncoderCount(i, count); - ImGui::SameLine(); - if (ImGui::Button("Reset")) HALSIM_SetEncoderCount(i, 0); - - // max period - double maxPeriod = HALSIM_GetEncoderMaxPeriod(i); - ImGui::LabelText("Max Period", "%.6f", maxPeriod); - - // period - double period = HALSIM_GetEncoderPeriod(i); - if (ImGui::InputDouble("Period", &period, 0, 0, "%.6g")) - HALSIM_SetEncoderPeriod(i, period); - - // reverse direction - ImGui::LabelText( - "Reverse Direction", "%s", - HALSIM_GetEncoderReverseDirection(i) ? "true" : "false"); - - // direction - static const char* options[] = {"reverse", "forward"}; - int direction = HALSIM_GetEncoderDirection(i) ? 1 : 0; - if (ImGui::Combo("Direction", &direction, options, 2)) - HALSIM_SetEncoderDirection(i, direction); - - ImGui::PopID(); } else { - gEncoders[chA].SetOpen(false); + int chA = HALSIM_GetEncoderDigitalChannelA(i); + int chB = HALSIM_GetEncoderDigitalChannelB(i); + + // build header name + auto& info = gEncoders[chA]; + char name[128]; + info.GetName(name, sizeof(name), "Encoder", chA, chB); + + // header + bool open = ImGui::CollapsingHeader( + name, gEncoders[chA].IsOpen() ? ImGuiTreeNodeFlags_DefaultOpen : 0); + info.SetOpen(open); + + // context menu to change name + info.PopupEditName(chA); + + if (open) { + ImGui::PushID(i); + // distance per pulse + double distancePerPulse = HALSIM_GetEncoderDistancePerPulse(i); + ImGui::LabelText("Dist/Count", "%.6f", distancePerPulse); + + // count + int count = HALSIM_GetEncoderCount(i); + if (ImGui::InputInt("Count", &count)) + HALSIM_SetEncoderCount(i, count); + ImGui::SameLine(); + if (ImGui::Button("Reset")) HALSIM_SetEncoderCount(i, 0); + + // max period + double maxPeriod = HALSIM_GetEncoderMaxPeriod(i); + ImGui::LabelText("Max Period", "%.6f", maxPeriod); + + // period + double period = HALSIM_GetEncoderPeriod(i); + if (ImGui::InputDouble("Period", &period, 0, 0, "%.6g")) + HALSIM_SetEncoderPeriod(i, period); + + // reverse direction + ImGui::LabelText( + "Reverse Direction", "%s", + HALSIM_GetEncoderReverseDirection(i) ? "true" : "false"); + + // direction + static const char* options[] = {"reverse", "forward"}; + int direction = HALSIM_GetEncoderDirection(i) ? 1 : 0; + if (ImGui::Combo("Direction", &direction, options, 2)) + HALSIM_SetEncoderDirection(i, direction); + ImGui::PopID(); + } } } } diff --git a/simulation/halsim_gui/src/main/native/cpp/IniSaverInfo.cpp b/simulation/halsim_gui/src/main/native/cpp/IniSaverInfo.cpp index 0393d523d9..15f3a4c09d 100644 --- a/simulation/halsim_gui/src/main/native/cpp/IniSaverInfo.cpp +++ b/simulation/halsim_gui/src/main/native/cpp/IniSaverInfo.cpp @@ -23,6 +23,17 @@ void NameInfo::GetName(char* buf, size_t size, const char* defaultName, } } +void NameInfo::GetName(char* buf, size_t size, const char* defaultName, + int index, int index2) { + if (m_name[0] != '\0') { + std::snprintf(buf, size, "%s [%d,%d]###Name%d", m_name, index, index2, + index); + } else { + std::snprintf(buf, size, "%s[%d,%d]###Name%d", defaultName, index, index2, + index); + } +} + bool NameInfo::ReadIni(wpi::StringRef name, wpi::StringRef value) { if (name != "name") return false; size_t len = (std::min)(value.size(), sizeof(m_name) - 1); @@ -35,6 +46,12 @@ void NameInfo::WriteIni(ImGuiTextBuffer* out) { out->appendf("name=%s\n", m_name); } +void NameInfo::PushEditNameId(int index) { + char id[64]; + std::snprintf(id, sizeof(id), "Name%d", index); + ImGui::PushID(id); +} + void NameInfo::PopupEditName(int index) { char id[64]; std::snprintf(id, sizeof(id), "Name%d", index); diff --git a/simulation/halsim_gui/src/main/native/cpp/PDPGui.cpp b/simulation/halsim_gui/src/main/native/cpp/PDPGui.cpp index da29ac3f7c..5fdebbb58d 100644 --- a/simulation/halsim_gui/src/main/native/cpp/PDPGui.cpp +++ b/simulation/halsim_gui/src/main/native/cpp/PDPGui.cpp @@ -1,5 +1,5 @@ /*----------------------------------------------------------------------------*/ -/* Copyright (c) 2019 FIRST. All Rights Reserved. */ +/* Copyright (c) 2019-2020 FIRST. All Rights Reserved. */ /* Open Source Software - may be modified and shared by FRC teams. The code */ /* must be accompanied by the FIRST BSD license file in the root directory of */ /* the project. */ @@ -7,7 +7,9 @@ #include "PDPGui.h" +#include #include +#include #include #include @@ -15,64 +17,82 @@ #include #include "HALSimGui.h" +#include "IniSaver.h" +#include "IniSaverInfo.h" using namespace halsimgui; +static IniSaver gChannels{"PDP"}; + static void DisplayPDP() { bool hasAny = false; static int numPDP = HAL_GetNumPDPModules(); static int numChannels = HAL_GetNumPDPChannels(); static auto channelCurrents = std::make_unique(numChannels); - ImGui::PushItemWidth(ImGui::GetFontSize() * 13); for (int i = 0; i < numPDP; ++i) { if (HALSIM_GetPDPInitialized(i)) { hasAny = true; - char name[32]; + char name[128]; std::snprintf(name, sizeof(name), "PDP[%d]", i); if (ImGui::CollapsingHeader(name, ImGuiTreeNodeFlags_DefaultOpen)) { ImGui::PushID(i); // temperature double temp = HALSIM_GetPDPTemperature(i); - if (ImGui::InputDouble("Temp", &temp)) + ImGui::SetNextItemWidth(ImGui::GetFontSize() * 4); + if (ImGui::InputDouble("Temp", &temp, 0, 0, "%.3f")) HALSIM_SetPDPTemperature(i, temp); // voltage double volts = HALSIM_GetPDPVoltage(i); - if (ImGui::InputDouble("Voltage", &volts)) + ImGui::SetNextItemWidth(ImGui::GetFontSize() * 4); + if (ImGui::InputDouble("Voltage", &volts, 0, 0, "%.3f")) HALSIM_SetPDPVoltage(i, volts); // channel currents; show as two columns laid out like PDP HALSIM_GetPDPAllCurrents(i, channelCurrents.get()); ImGui::Text("Channel Current (A)"); ImGui::Columns(2, "channels", false); + float maxWidth = ImGui::GetFontSize() * 13; for (int left = 0, right = numChannels - 1; left < right; ++left, --right) { double val; - std::snprintf(name, sizeof(name), "[%d]", left); + auto& leftInfo = gChannels[i * numChannels + left]; + leftInfo.GetName(name, sizeof(name), "", left); val = channelCurrents[left]; - if (ImGui::InputDouble(name, &val)) + ImGui::SetNextItemWidth(ImGui::GetFontSize() * 4); + if (ImGui::InputDouble(name, &val, 0, 0, "%.3f")) HALSIM_SetPDPCurrent(i, left, val); + float leftWidth = ImGui::GetItemRectSize().x; + leftInfo.PopupEditName(left); ImGui::NextColumn(); - std::snprintf(name, sizeof(name), "[%d]", right); + auto& rightInfo = gChannels[i * numChannels + right]; + rightInfo.GetName(name, sizeof(name), "", right); val = channelCurrents[right]; - if (ImGui::InputDouble(name, &val)) + ImGui::SetNextItemWidth(ImGui::GetFontSize() * 4); + if (ImGui::InputDouble(name, &val, 0, 0, "%.3f")) HALSIM_SetPDPCurrent(i, right, val); + float rightWidth = ImGui::GetItemRectSize().x; + rightInfo.PopupEditName(right); ImGui::NextColumn(); + + float width = (std::max)(leftWidth, rightWidth) * 2; + if (width > maxWidth) maxWidth = width; } ImGui::Columns(1); + ImGui::Dummy(ImVec2(maxWidth, 0)); ImGui::PopID(); } } } - ImGui::PopItemWidth(); if (!hasAny) ImGui::Text("No PDPs"); } void PDPGui::Initialize() { + gChannels.Initialize(); HALSimGui::AddWindow("PDP", DisplayPDP, ImGuiWindowFlags_AlwaysAutoResize); // hide it by default HALSimGui::SetWindowVisibility("PDP", HALSimGui::kHide); diff --git a/simulation/halsim_gui/src/main/native/cpp/PWMGui.cpp b/simulation/halsim_gui/src/main/native/cpp/PWMGui.cpp index 430502dbc7..2407e056b0 100644 --- a/simulation/halsim_gui/src/main/native/cpp/PWMGui.cpp +++ b/simulation/halsim_gui/src/main/native/cpp/PWMGui.cpp @@ -1,5 +1,5 @@ /*----------------------------------------------------------------------------*/ -/* Copyright (c) 2019 FIRST. All Rights Reserved. */ +/* Copyright (c) 2019-2020 FIRST. All Rights Reserved. */ /* Open Source Software - may be modified and shared by FRC teams. The code */ /* must be accompanied by the FIRST BSD license file in the root directory of */ /* the project. */ @@ -17,9 +17,13 @@ #include #include "HALSimGui.h" +#include "IniSaver.h" +#include "IniSaverInfo.h" using namespace halsimgui; +static IniSaver gPWM{"PWM"}; + static void DisplayPWMs() { bool hasOutputs = false; static const int numPWM = HAL_GetNumPWMChannels(); @@ -45,6 +49,7 @@ static void DisplayPWMs() { //}; // static std::vector> history; bool first = true; + ImGui::PushItemWidth(ImGui::GetFontSize() * 4); for (int i = 0; i < numPWM; ++i) { if (HALSIM_GetPWMInitialized(i)) { hasOutputs = true; @@ -54,14 +59,16 @@ static void DisplayPWMs() { else first = false; - char name[32]; - std::snprintf(name, sizeof(name), "PWM[%d]", i); + char name[128]; + auto& info = gPWM[i]; + info.GetName(name, sizeof(name), "PWM", i); if (ledMap[i] > 0) { - ImGui::Text("%s: LED[%d]", name, ledMap[i] - 1); + ImGui::LabelText(name, "LED[%d]", ledMap[i] - 1); } else { float val = HALSimGui::AreOutputsDisabled() ? 0 : HALSIM_GetPWMSpeed(i); - ImGui::Value(name, val, "%0.3f"); + ImGui::LabelText(name, "%0.3f", val); } + info.PopupEditName(i); // lazily build history storage // if (static_cast(i) > history.size()) @@ -74,10 +81,12 @@ static void DisplayPWMs() { // ); } } + ImGui::PopItemWidth(); if (!hasOutputs) ImGui::Text("No PWM outputs"); } void PWMGui::Initialize() { + gPWM.Initialize(); HALSimGui::AddWindow("PWM Outputs", DisplayPWMs, ImGuiWindowFlags_AlwaysAutoResize); HALSimGui::SetDefaultWindowPos("PWM Outputs", 910, 20); diff --git a/simulation/halsim_gui/src/main/native/cpp/RelayGui.cpp b/simulation/halsim_gui/src/main/native/cpp/RelayGui.cpp index a833fffefe..df059c8aea 100644 --- a/simulation/halsim_gui/src/main/native/cpp/RelayGui.cpp +++ b/simulation/halsim_gui/src/main/native/cpp/RelayGui.cpp @@ -1,5 +1,5 @@ /*----------------------------------------------------------------------------*/ -/* Copyright (c) 2019 FIRST. All Rights Reserved. */ +/* Copyright (c) 2019-2020 FIRST. All Rights Reserved. */ /* Open Source Software - may be modified and shared by FRC teams. The code */ /* must be accompanied by the FIRST BSD license file in the root directory of */ /* the project. */ @@ -16,9 +16,13 @@ #include "ExtraGuiWidgets.h" #include "HALSimGui.h" +#include "IniSaver.h" +#include "IniSaverInfo.h" using namespace halsimgui; +static IniSaver gRelays{"Relay"}; + static void DisplayRelays() { bool hasOutputs = false; bool first = true; @@ -42,7 +46,14 @@ static void DisplayRelays() { forward = HALSIM_GetRelayForward(i); } - ImGui::Text("Relay[%d]", i); + auto& info = gRelays[i]; + info.PushEditNameId(i); + if (info.HasName()) + ImGui::Text("%s [%d]", info.GetName(), i); + else + ImGui::Text("Relay[%d]", i); + ImGui::PopID(); + info.PopupEditName(i); ImGui::SameLine(); // show forward and reverse as LED indicators @@ -58,6 +69,7 @@ static void DisplayRelays() { } void RelayGui::Initialize() { + gRelays.Initialize(); HALSimGui::AddWindow("Relays", DisplayRelays, ImGuiWindowFlags_AlwaysAutoResize); HALSimGui::SetDefaultWindowPos("Relays", 180, 20); diff --git a/simulation/halsim_gui/src/main/native/cpp/SolenoidGui.cpp b/simulation/halsim_gui/src/main/native/cpp/SolenoidGui.cpp index 75712c6d36..bc523a699a 100644 --- a/simulation/halsim_gui/src/main/native/cpp/SolenoidGui.cpp +++ b/simulation/halsim_gui/src/main/native/cpp/SolenoidGui.cpp @@ -1,5 +1,5 @@ /*----------------------------------------------------------------------------*/ -/* Copyright (c) 2019 FIRST. All Rights Reserved. */ +/* Copyright (c) 2019-2020 FIRST. All Rights Reserved. */ /* Open Source Software - may be modified and shared by FRC teams. The code */ /* must be accompanied by the FIRST BSD license file in the root directory of */ /* the project. */ @@ -17,9 +17,14 @@ #include "ExtraGuiWidgets.h" #include "HALSimGui.h" +#include "IniSaver.h" +#include "IniSaverInfo.h" using namespace halsimgui; +static IniSaver gPCMs{"PCM"}; +static IniSaver gSolenoids{"Solenoid"}; + static void DisplaySolenoids() { bool hasOutputs = false; static const int numPCM = HAL_GetNumPCMModules(); @@ -43,18 +48,40 @@ static void DisplaySolenoids() { if (!anyInit) continue; hasOutputs = true; - ImGui::Text("PCM[%d]", i); + char name[128]; + std::snprintf(name, sizeof(name), "PCM[%d]", i); + auto& pcmInfo = gPCMs[i]; + bool open = ImGui::CollapsingHeader( + name, pcmInfo.IsOpen() ? ImGuiTreeNodeFlags_DefaultOpen : 0); + pcmInfo.SetOpen(open); + ImGui::SetItemAllowOverlap(); ImGui::SameLine(); // show channels as LED indicators static const ImU32 colors[] = {IM_COL32(255, 255, 102, 255), IM_COL32(128, 128, 128, 255)}; DrawLEDs(channels.data(), channels.size(), channels.size(), colors); + + if (open) { + ImGui::PushID(i); + ImGui::PushItemWidth(ImGui::GetFontSize() * 4); + for (int j = 0; j < numChannels; ++j) { + if (channels[j] == -2) continue; + auto& info = gSolenoids[i * numChannels + j]; + info.GetName(name, sizeof(name), "Solenoid", j); + ImGui::LabelText(name, "%s", channels[j] == 1 ? "On" : "Off"); + info.PopupEditName(j); + } + ImGui::PopItemWidth(); + ImGui::PopID(); + } } if (!hasOutputs) ImGui::Text("No solenoids"); } void SolenoidGui::Initialize() { + gPCMs.Initialize(); + gSolenoids.Initialize(); HALSimGui::AddWindow("Solenoids", DisplaySolenoids, ImGuiWindowFlags_AlwaysAutoResize); HALSimGui::SetDefaultWindowPos("Solenoids", 290, 20); diff --git a/simulation/halsim_gui/src/main/native/include/IniSaverInfo.h b/simulation/halsim_gui/src/main/native/include/IniSaverInfo.h index 12dd3defc7..67f668d4f4 100644 --- a/simulation/halsim_gui/src/main/native/include/IniSaverInfo.h +++ b/simulation/halsim_gui/src/main/native/include/IniSaverInfo.h @@ -16,9 +16,14 @@ class NameInfo { public: NameInfo() { m_name[0] = '\0'; } + bool HasName() const { return m_name[0] != '\0'; } + const char* GetName() const { return m_name; } void GetName(char* buf, size_t size, const char* defaultName, int index); + void GetName(char* buf, size_t size, const char* defaultName, int index, + int index2); bool ReadIni(wpi::StringRef name, wpi::StringRef value); void WriteIni(ImGuiTextBuffer* out); + void PushEditNameId(int index); void PopupEditName(int index); private: