Simulation GUI: Add support for custom names (#2292)

This allows users to right click on just about any name in the GUI (e.g. "PWM[0]") and rename it (e.g. "Left Motor [0]"). The index portion is not editable. The name is saved into imgui.ini so it's persistent.
This commit is contained in:
Peter Johnson
2020-01-20 22:47:36 -08:00
committed by GitHub
parent bb184ed481
commit 9d7b087972
11 changed files with 232 additions and 97 deletions

View File

@@ -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 <cstdio>
#include <hal/Ports.h>
#include <imgui.h>
#include <mockdata/AnalogGyroData.h>
@@ -16,9 +14,13 @@
#include <mockdata/SimDeviceData.h>
#include "HALSimGui.h"
#include "IniSaver.h"
#include "IniSaverInfo.h"
using namespace halsimgui;
static IniSaver<NameInfo> 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);

View File

@@ -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 <cstdio>
#include <cstring>
#include <memory>
#include <hal/Ports.h>
#include <imgui.h>
#include <mockdata/AnalogOutData.h>
#include "IniSaver.h"
#include "IniSaverInfo.h"
#include "SimDeviceGui.h"
using namespace halsimgui;
static IniSaver<NameInfo> gAnalogOuts{"AnalogOut"}; // indexed by channel
static void DisplayAnalogOutputs() {
static const int numAnalog = HAL_GetNumAnalogOutputs();
static auto init = std::make_unique<bool[]>(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);
}

View File

@@ -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 <cstdio>
#include <cstring>
#include <memory>
#include <hal/Ports.h>
#include <imgui.h>
#include <mockdata/DIOData.h>
@@ -20,9 +16,13 @@
#include <mockdata/SimDeviceData.h>
#include "HALSimGui.h"
#include "IniSaver.h"
#include "IniSaverInfo.h"
using namespace halsimgui;
static IniSaver<NameInfo> 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);
}

View File

@@ -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();

View File

@@ -7,8 +7,6 @@
#include "EncoderGui.h"
#include <cstdio>
#include <hal/Ports.h>
#include <imgui.h>
#include <mockdata/EncoderData.h>
@@ -20,7 +18,21 @@
using namespace halsimgui;
static IniSaver<OpenInfo> 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<EncoderInfo> 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();
}
}
}
}

View File

@@ -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);

View File

@@ -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 <algorithm>
#include <cstdio>
#include <cstring>
#include <memory>
#include <hal/Ports.h>
@@ -15,64 +17,82 @@
#include <mockdata/PDPData.h>
#include "HALSimGui.h"
#include "IniSaver.h"
#include "IniSaverInfo.h"
using namespace halsimgui;
static IniSaver<NameInfo> gChannels{"PDP"};
static void DisplayPDP() {
bool hasAny = false;
static int numPDP = HAL_GetNumPDPModules();
static int numChannels = HAL_GetNumPDPChannels();
static auto channelCurrents = std::make_unique<double[]>(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);

View File

@@ -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 <mockdata/PWMData.h>
#include "HALSimGui.h"
#include "IniSaver.h"
#include "IniSaverInfo.h"
using namespace halsimgui;
static IniSaver<NameInfo> gPWM{"PWM"};
static void DisplayPWMs() {
bool hasOutputs = false;
static const int numPWM = HAL_GetNumPWMChannels();
@@ -45,6 +49,7 @@ static void DisplayPWMs() {
//};
// static std::vector<std::unique_ptr<History>> 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<unsigned int>(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);

View File

@@ -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<NameInfo> 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);

View File

@@ -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<OpenInfo> gPCMs{"PCM"};
static IniSaver<NameInfo> 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);