mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-24 01:31:46 +00:00
[glass] Add glass: an application for display of robot data
This reuses many pieces of the current simulation GUI. The common pieces have been refactored into the libglass library. The libglass library is designed to be usable for other standalone data visualization applications (e.g. viewing data logs). The name "glass" comes from "glass cockpit", as the application features several multi-function displays that can be adjusted to display robot information as needed.
This commit is contained in:
@@ -1,89 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2017-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. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
namespace halsimgui {
|
||||
|
||||
class GuiDataSource;
|
||||
|
||||
/**
|
||||
* DrawLEDs() configuration for 2D arrays.
|
||||
*/
|
||||
struct LEDConfig {
|
||||
/**
|
||||
* Whether the major order is serpentined (e.g. the first row goes left to
|
||||
* right, the second row right to left, the third row left to right, and so
|
||||
* on).
|
||||
*/
|
||||
bool serpentine = false;
|
||||
|
||||
/**
|
||||
* The input array order (row-major or column-major).
|
||||
*/
|
||||
enum Order { RowMajor = 0, ColumnMajor } order = RowMajor;
|
||||
|
||||
/**
|
||||
* The starting location of the array (0 location).
|
||||
*/
|
||||
enum Start {
|
||||
UpperLeft = 0,
|
||||
LowerLeft,
|
||||
UpperRight,
|
||||
LowerRight
|
||||
} start = UpperLeft;
|
||||
};
|
||||
|
||||
/**
|
||||
* Draw a 2D array of LEDs.
|
||||
*
|
||||
* Values are indices into colors array. Positive values are filled (lit),
|
||||
* negative values are unfilled (dark / border only). The actual color index
|
||||
* is the absolute value of the value - 1. 0 values are not drawn at all
|
||||
* (an empty space is left).
|
||||
*
|
||||
* @param values values array
|
||||
* @param numValues size of values array
|
||||
* @param cols number of columns
|
||||
* @param colors colors array
|
||||
* @param size size of each LED (both horizontal and vertical);
|
||||
* if 0, defaults to 1/2 of font size
|
||||
* @param spacing spacing between each LED (both horizontal and vertical);
|
||||
* if 0, defaults to 1/3 of font size
|
||||
* @param config 2D array configuration
|
||||
*/
|
||||
void DrawLEDs(const int* values, int numValues, int cols, const ImU32* colors,
|
||||
float size = 0.0f, float spacing = 0.0f,
|
||||
const LEDConfig& config = LEDConfig{});
|
||||
|
||||
/**
|
||||
* Draw a 2D array of LEDs.
|
||||
*
|
||||
* Values are indices into colors array. Positive values are filled (lit),
|
||||
* negative values are unfilled (dark / border only). The actual color index
|
||||
* is the absolute value of the value - 1. 0 values are not drawn at all
|
||||
* (an empty space is left).
|
||||
*
|
||||
* @param values values array
|
||||
* @param sources sources array
|
||||
* @param numValues size of values and sources arrays
|
||||
* @param cols number of columns
|
||||
* @param colors colors array
|
||||
* @param size size of each LED (both horizontal and vertical);
|
||||
* if 0, defaults to 1/2 of font size
|
||||
* @param spacing spacing between each LED (both horizontal and vertical);
|
||||
* if 0, defaults to 1/3 of font size
|
||||
* @param config 2D array configuration
|
||||
*/
|
||||
void DrawLEDSources(const int* values, GuiDataSource** sources, int numValues,
|
||||
int cols, const ImU32* colors, float size = 0.0f,
|
||||
float spacing = 0.0f,
|
||||
const LEDConfig& config = LEDConfig{});
|
||||
|
||||
} // namespace halsimgui
|
||||
@@ -7,78 +7,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <string>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <wpi/Signal.h>
|
||||
#include <wpi/StringRef.h>
|
||||
#include <wpi/Twine.h>
|
||||
#include <wpi/spinlock.h>
|
||||
|
||||
namespace halsimgui {
|
||||
|
||||
/**
|
||||
* A data source.
|
||||
*/
|
||||
class GuiDataSource {
|
||||
public:
|
||||
explicit GuiDataSource(const wpi::Twine& id);
|
||||
GuiDataSource(const wpi::Twine& id, int index);
|
||||
GuiDataSource(const wpi::Twine& id, int index, int index2);
|
||||
~GuiDataSource();
|
||||
|
||||
GuiDataSource(const GuiDataSource&) = delete;
|
||||
GuiDataSource& operator=(const GuiDataSource&) = delete;
|
||||
|
||||
const char* GetId() const { return m_id.c_str(); }
|
||||
|
||||
void SetName(const wpi::Twine& name) { m_name = name.str(); }
|
||||
const char* GetName() const { return m_name.c_str(); }
|
||||
|
||||
void SetDigital(bool digital) { m_digital = digital; }
|
||||
bool IsDigital() const { return m_digital; }
|
||||
|
||||
void SetValue(double value) {
|
||||
m_value = value;
|
||||
valueChanged(value);
|
||||
}
|
||||
double GetValue() const { return m_value; }
|
||||
|
||||
// drag source helpers
|
||||
void LabelText(const char* label, const char* fmt, ...) const;
|
||||
void LabelTextV(const char* label, const char* fmt, va_list args) const;
|
||||
bool Combo(const char* label, int* current_item, const char* const items[],
|
||||
int items_count, int popup_max_height_in_items = -1) const;
|
||||
bool SliderFloat(const char* label, float* v, float v_min, float v_max,
|
||||
const char* format = "%.3f", float power = 1.0f) const;
|
||||
bool InputDouble(const char* label, double* v, double step = 0.0,
|
||||
double step_fast = 0.0, const char* format = "%.6f",
|
||||
ImGuiInputTextFlags flags = 0) const;
|
||||
bool InputInt(const char* label, int* v, int step = 1, int step_fast = 100,
|
||||
ImGuiInputTextFlags flags = 0) const;
|
||||
void EmitDrag(ImGuiDragDropFlags flags = 0) const;
|
||||
|
||||
wpi::sig::SignalBase<wpi::spinlock, double> valueChanged;
|
||||
|
||||
static GuiDataSource* Find(wpi::StringRef id);
|
||||
|
||||
static wpi::sig::Signal<const char*, GuiDataSource*> sourceCreated;
|
||||
|
||||
private:
|
||||
std::string m_id;
|
||||
std::string m_name;
|
||||
bool m_digital = false;
|
||||
std::atomic<double> m_value = 0;
|
||||
};
|
||||
|
||||
} // namespace halsimgui
|
||||
#include <glass/DataSource.h>
|
||||
|
||||
#define HALSIMGUI_DATASOURCE(cbname, id, TYPE, vtype) \
|
||||
class cbname##Source : public ::halsimgui::GuiDataSource { \
|
||||
class cbname##Source : public ::glass::DataSource { \
|
||||
public: \
|
||||
cbname##Source() \
|
||||
: GuiDataSource(id), \
|
||||
: DataSource(id), \
|
||||
m_callback{ \
|
||||
HALSIM_Register##cbname##Callback(CallbackFunc, this, true)} { \
|
||||
SetDigital(HAL_##TYPE == HAL_BOOLEAN); \
|
||||
@@ -108,10 +43,10 @@ class GuiDataSource {
|
||||
HALSIMGUI_DATASOURCE(cbname, id, INT, int)
|
||||
|
||||
#define HALSIMGUI_DATASOURCE_INDEXED(cbname, id, TYPE, vtype) \
|
||||
class cbname##Source : public ::halsimgui::GuiDataSource { \
|
||||
class cbname##Source : public ::glass::DataSource { \
|
||||
public: \
|
||||
explicit cbname##Source(int32_t index, int channel = -1) \
|
||||
: GuiDataSource(id, channel < 0 ? index : channel), \
|
||||
: DataSource(id, channel < 0 ? index : channel), \
|
||||
m_index{index}, \
|
||||
m_channel{channel < 0 ? index : channel}, \
|
||||
m_callback{HALSIM_Register##cbname##Callback(index, CallbackFunc, \
|
||||
@@ -147,10 +82,10 @@ class GuiDataSource {
|
||||
HALSIMGUI_DATASOURCE_INDEXED(cbname, id, DOUBLE, double)
|
||||
|
||||
#define HALSIMGUI_DATASOURCE_INDEXED2(cbname, id, TYPE, vtype) \
|
||||
class cbname##Source : public ::halsimgui::GuiDataSource { \
|
||||
class cbname##Source : public ::glass::DataSource { \
|
||||
public: \
|
||||
explicit cbname##Source(int32_t index, int32_t channel) \
|
||||
: GuiDataSource(id, index, channel), \
|
||||
: DataSource(id, index, channel), \
|
||||
m_index{index}, \
|
||||
m_channel{channel}, \
|
||||
m_callback{HALSIM_Register##cbname##Callback( \
|
||||
50
simulation/halsim_gui/src/main/native/include/HALProvider.h
Normal file
50
simulation/halsim_gui/src/main/native/include/HALProvider.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 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. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <glass/Model.h>
|
||||
#include <glass/Provider.h>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <wpi/StringRef.h>
|
||||
|
||||
namespace halsimgui {
|
||||
|
||||
class HALProvider : public glass::Provider<> {
|
||||
public:
|
||||
explicit HALProvider(const wpi::Twine& iniName) : Provider{iniName} {}
|
||||
|
||||
void DisplayMenu() override;
|
||||
|
||||
glass::Model* GetModel(wpi::StringRef 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 Update() override;
|
||||
|
||||
void Show(ViewEntry* entry, glass::Window* window) override;
|
||||
};
|
||||
|
||||
} // namespace halsimgui
|
||||
@@ -7,144 +7,23 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <functional>
|
||||
#endif
|
||||
#include <glass/MainMenuBar.h>
|
||||
#include <glass/WindowManager.h>
|
||||
#include <glass/networktables/NetworkTablesProvider.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
void HALSIMGUI_Add(void* param, void (*initialize)(void*));
|
||||
void HALSIMGUI_AddExecute(void* param, void (*execute)(void*));
|
||||
void HALSIMGUI_AddWindow(const char* name, void* param, void (*display)(void*),
|
||||
int32_t flags);
|
||||
void HALSIMGUI_AddMainMenu(void* param, void (*menu)(void*));
|
||||
void HALSIMGUI_AddOptionMenu(void* param, void (*menu)(void*));
|
||||
void HALSIMGUI_SetWindowVisibility(const char* name, int32_t visibility);
|
||||
void HALSIMGUI_SetDefaultWindowPos(const char* name, float x, float y);
|
||||
void HALSIMGUI_SetDefaultWindowSize(const char* name, float width,
|
||||
float height);
|
||||
void HALSIMGUI_SetWindowPadding(const char* name, float x, float y);
|
||||
int HALSIMGUI_AreOutputsDisabled(void);
|
||||
|
||||
} // extern "C"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include "HALProvider.h"
|
||||
|
||||
namespace halsimgui {
|
||||
|
||||
class HALSimGui {
|
||||
public:
|
||||
static void GlobalInit();
|
||||
static bool Initialize();
|
||||
static void Main(void*);
|
||||
static void Exit(void*);
|
||||
|
||||
/**
|
||||
* Adds feature to GUI. The initialize function is called once, immediately
|
||||
* after the GUI (both GLFW and Dear ImGui) are initialized.
|
||||
*
|
||||
* @param initialize initialization function
|
||||
* @param execute frame execution function
|
||||
*/
|
||||
static void Add(std::function<void()> initialize);
|
||||
static glass::MainMenuBar mainMenu;
|
||||
static glass::WindowManager manager;
|
||||
|
||||
/**
|
||||
* Adds per-frame executor to GUI. The passed function is called on each
|
||||
* Dear ImGui frame prior to window and menu functions.
|
||||
*
|
||||
* @param execute frame execution function
|
||||
*/
|
||||
static void AddExecute(std::function<void()> execute);
|
||||
|
||||
/**
|
||||
* Adds window to GUI. The display function is called from within a
|
||||
* ImGui::Begin()/End() block. While windows can be created within the
|
||||
* execute function passed to AddExecute(), using this function ensures the
|
||||
* windows are consistently integrated with the rest of the GUI.
|
||||
*
|
||||
* On each Dear ImGui frame, AddExecute() functions are always called prior
|
||||
* to AddWindow display functions. Note that windows may be shaded or
|
||||
* completely hidden, in which case this function will not be called.
|
||||
* It's important to perform any processing steps that must be performed
|
||||
* every frame in the AddExecute() function.
|
||||
*
|
||||
* @param name name of the window (title bar)
|
||||
* @param display window contents display function
|
||||
* @param flags Dear ImGui window flags
|
||||
*/
|
||||
static void AddWindow(const char* name, std::function<void()> display,
|
||||
int flags = 0);
|
||||
|
||||
/**
|
||||
* Adds to GUI's main menu bar. The menu function is called from within a
|
||||
* ImGui::BeginMainMenuBar()/EndMainMenuBar() block. Usually it's only
|
||||
* appropriate to create a menu with ImGui::BeginMenu()/EndMenu() inside of
|
||||
* this function.
|
||||
*
|
||||
* On each Dear ImGui frame, AddExecute() functions are always called prior
|
||||
* to AddMainMenu menu functions.
|
||||
*
|
||||
* @param menu menu display function
|
||||
*/
|
||||
static void AddMainMenu(std::function<void()> menu);
|
||||
|
||||
/**
|
||||
* Adds to GUI's option menu. The menu function is called from within a
|
||||
* ImGui::BeginMenu()/EndMenu() block. Usually it's only appropriate to
|
||||
* create menu items inside of this function.
|
||||
*
|
||||
* On each Dear ImGui frame, AddExecute() functions are always called prior
|
||||
* to AddMainMenu menu functions.
|
||||
*
|
||||
* @param menu menu display function
|
||||
*/
|
||||
static void AddOptionMenu(std::function<void()> menu);
|
||||
|
||||
enum WindowVisibility { kHide = 0, kShow, kDisabled };
|
||||
|
||||
/**
|
||||
* Sets visibility of window added with AddWindow().
|
||||
*
|
||||
* @param name window name (same as name passed to AddWindow())
|
||||
* @param visibility 0=hide, 1=show, 2=disabled (force-hide)
|
||||
*/
|
||||
static void SetWindowVisibility(const char* name,
|
||||
WindowVisibility visibility);
|
||||
|
||||
/**
|
||||
* Sets default position of window added with AddWindow().
|
||||
*
|
||||
* @param name window name (same as name passed to AddWindow())
|
||||
* @param x x location of upper left corner
|
||||
* @param y y location of upper left corner
|
||||
*/
|
||||
static void SetDefaultWindowPos(const char* name, float x, float y);
|
||||
|
||||
/**
|
||||
* Sets default size of window added with AddWindow().
|
||||
*
|
||||
* @param name window name (same as name passed to AddWindow())
|
||||
* @param width width
|
||||
* @param height height
|
||||
*/
|
||||
static void SetDefaultWindowSize(const char* name, float width, float height);
|
||||
|
||||
/**
|
||||
* Sets internal padding of window added with AddWindow().
|
||||
* @param name window name (same as name passed to AddWindow())
|
||||
* @param x horizontal padding
|
||||
* @param y vertical padding
|
||||
*/
|
||||
static void SetWindowPadding(const char* name, float x, float y);
|
||||
|
||||
/**
|
||||
* Returns true if outputs are disabled.
|
||||
*
|
||||
* @return true if outputs are disabled, false otherwise.
|
||||
*/
|
||||
static bool AreOutputsDisabled();
|
||||
static HALProvider halProvider;
|
||||
static glass::NetworkTablesProvider ntProvider;
|
||||
};
|
||||
|
||||
} // namespace halsimgui
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 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. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
#include <wpi/DenseMap.h>
|
||||
|
||||
namespace halsimgui {
|
||||
|
||||
template <typename Info>
|
||||
class IniSaver {
|
||||
public:
|
||||
explicit IniSaver(const char* typeName) : m_typeName(typeName) {}
|
||||
void Initialize();
|
||||
|
||||
// pass through useful functions to map
|
||||
Info& operator[](int index) { return m_map[index]; }
|
||||
|
||||
auto begin() { return m_map.begin(); }
|
||||
auto end() { return m_map.end(); }
|
||||
auto find(int index) { return m_map.find(index); }
|
||||
|
||||
auto begin() const { return m_map.begin(); }
|
||||
auto end() const { return m_map.end(); }
|
||||
auto find(int index) const { return m_map.find(index); }
|
||||
|
||||
private:
|
||||
static void* ReadOpen(ImGuiContext* ctx, ImGuiSettingsHandler* handler,
|
||||
const char* name);
|
||||
static void ReadLine(ImGuiContext* ctx, ImGuiSettingsHandler* handler,
|
||||
void* entry, const char* lineStr);
|
||||
static void WriteAll(ImGuiContext* ctx, ImGuiSettingsHandler* handler,
|
||||
ImGuiTextBuffer* out_buf);
|
||||
|
||||
const char* m_typeName;
|
||||
wpi::DenseMap<int, Info> m_map;
|
||||
};
|
||||
|
||||
} // namespace halsimgui
|
||||
|
||||
#include "IniSaver.inl"
|
||||
@@ -1,56 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 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. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace halsimgui {
|
||||
|
||||
template <typename Info>
|
||||
void IniSaver<Info>::Initialize() {
|
||||
// hook ini handler to save settings
|
||||
ImGuiSettingsHandler iniHandler;
|
||||
iniHandler.TypeName = m_typeName;
|
||||
iniHandler.TypeHash = ImHashStr(m_typeName);
|
||||
iniHandler.ReadOpenFn = ReadOpen;
|
||||
iniHandler.ReadLineFn = ReadLine;
|
||||
iniHandler.WriteAllFn = WriteAll;
|
||||
iniHandler.UserData = this;
|
||||
ImGui::GetCurrentContext()->SettingsHandlers.push_back(iniHandler);
|
||||
}
|
||||
|
||||
template <typename Info>
|
||||
void* IniSaver<Info>::ReadOpen(ImGuiContext* ctx, ImGuiSettingsHandler* handler,
|
||||
const char* name) {
|
||||
auto self = static_cast<IniSaver*>(handler->UserData);
|
||||
int num;
|
||||
if (wpi::StringRef{name}.getAsInteger(10, num)) return nullptr;
|
||||
return &self->m_map[num];
|
||||
}
|
||||
|
||||
template <typename Info>
|
||||
void IniSaver<Info>::ReadLine(ImGuiContext* ctx, ImGuiSettingsHandler* handler,
|
||||
void* entry, const char* lineStr) {
|
||||
auto element = static_cast<Info*>(entry);
|
||||
wpi::StringRef line{lineStr};
|
||||
auto [name, value] = line.split('=');
|
||||
name = name.trim();
|
||||
value = value.trim();
|
||||
element->ReadIni(name, value);
|
||||
}
|
||||
|
||||
template <typename Info>
|
||||
void IniSaver<Info>::WriteAll(ImGuiContext* ctx, ImGuiSettingsHandler* handler,
|
||||
ImGuiTextBuffer* out_buf) {
|
||||
auto self = static_cast<IniSaver*>(handler->UserData);
|
||||
for (auto&& it : self->m_map) {
|
||||
out_buf->appendf("[%s][%d]\n", self->m_typeName, it.first);
|
||||
it.second.WriteIni(out_buf);
|
||||
out_buf->append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace halsimgui
|
||||
@@ -1,58 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 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. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <imgui.h>
|
||||
#include <wpi/StringRef.h>
|
||||
|
||||
namespace halsimgui {
|
||||
|
||||
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) const;
|
||||
void GetName(char* buf, size_t size, const char* defaultName,
|
||||
int index) const;
|
||||
void GetName(char* buf, size_t size, const char* defaultName, int index,
|
||||
int index2) const;
|
||||
void GetLabel(char* buf, size_t size, const char* defaultName) const;
|
||||
void GetLabel(char* buf, size_t size, const char* defaultName,
|
||||
int index) const;
|
||||
void GetLabel(char* buf, size_t size, const char* defaultName, int index,
|
||||
int index2) const;
|
||||
|
||||
bool ReadIni(wpi::StringRef name, wpi::StringRef value);
|
||||
void WriteIni(ImGuiTextBuffer* out);
|
||||
void PushEditNameId(int index);
|
||||
void PushEditNameId(const char* name);
|
||||
bool PopupEditName(int index);
|
||||
bool PopupEditName(const char* name);
|
||||
bool InputTextName(const char* label_id, ImGuiInputTextFlags flags = 0);
|
||||
|
||||
private:
|
||||
char m_name[64];
|
||||
};
|
||||
|
||||
class OpenInfo {
|
||||
public:
|
||||
OpenInfo() = default;
|
||||
explicit OpenInfo(bool open) : m_open(open) {}
|
||||
|
||||
bool IsOpen() const { return m_open; }
|
||||
void SetOpen(bool open) { m_open = open; }
|
||||
bool ReadIni(wpi::StringRef name, wpi::StringRef value);
|
||||
void WriteIni(ImGuiTextBuffer* out);
|
||||
|
||||
private:
|
||||
bool m_open = false;
|
||||
};
|
||||
|
||||
} // namespace halsimgui
|
||||
@@ -1,48 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 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. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
#include <wpi/StringMap.h>
|
||||
#include <wpi/StringRef.h>
|
||||
|
||||
namespace halsimgui {
|
||||
|
||||
template <typename Info>
|
||||
class IniSaverString {
|
||||
public:
|
||||
explicit IniSaverString(const char* typeName) : m_typeName(typeName) {}
|
||||
void Initialize();
|
||||
|
||||
// pass through useful functions to map
|
||||
Info& operator[](wpi::StringRef key) { return m_map[key]; }
|
||||
|
||||
auto begin() { return m_map.begin(); }
|
||||
auto end() { return m_map.end(); }
|
||||
auto find(wpi::StringRef key) { return m_map.find(key); }
|
||||
|
||||
auto begin() const { return m_map.begin(); }
|
||||
auto end() const { return m_map.end(); }
|
||||
auto find(wpi::StringRef key) const { return m_map.find(key); }
|
||||
|
||||
private:
|
||||
static void* ReadOpen(ImGuiContext* ctx, ImGuiSettingsHandler* handler,
|
||||
const char* name);
|
||||
static void ReadLine(ImGuiContext* ctx, ImGuiSettingsHandler* handler,
|
||||
void* entry, const char* lineStr);
|
||||
static void WriteAll(ImGuiContext* ctx, ImGuiSettingsHandler* handler,
|
||||
ImGuiTextBuffer* out_buf);
|
||||
|
||||
const char* m_typeName;
|
||||
wpi::StringMap<Info> m_map;
|
||||
};
|
||||
|
||||
} // namespace halsimgui
|
||||
|
||||
#include "IniSaverString.inl"
|
||||
@@ -1,57 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 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. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace halsimgui {
|
||||
|
||||
template <typename Info>
|
||||
void IniSaverString<Info>::Initialize() {
|
||||
// hook ini handler to save settings
|
||||
ImGuiSettingsHandler iniHandler;
|
||||
iniHandler.TypeName = m_typeName;
|
||||
iniHandler.TypeHash = ImHashStr(m_typeName);
|
||||
iniHandler.ReadOpenFn = ReadOpen;
|
||||
iniHandler.ReadLineFn = ReadLine;
|
||||
iniHandler.WriteAllFn = WriteAll;
|
||||
iniHandler.UserData = this;
|
||||
ImGui::GetCurrentContext()->SettingsHandlers.push_back(iniHandler);
|
||||
}
|
||||
|
||||
template <typename Info>
|
||||
void* IniSaverString<Info>::ReadOpen(ImGuiContext* ctx,
|
||||
ImGuiSettingsHandler* handler,
|
||||
const char* name) {
|
||||
auto self = static_cast<IniSaverString*>(handler->UserData);
|
||||
return &self->m_map[name];
|
||||
}
|
||||
|
||||
template <typename Info>
|
||||
void IniSaverString<Info>::ReadLine(ImGuiContext* ctx,
|
||||
ImGuiSettingsHandler* handler, void* entry,
|
||||
const char* lineStr) {
|
||||
auto element = static_cast<Info*>(entry);
|
||||
wpi::StringRef line{lineStr};
|
||||
auto [name, value] = line.split('=');
|
||||
name = name.trim();
|
||||
value = value.trim();
|
||||
element->ReadIni(name, value);
|
||||
}
|
||||
|
||||
template <typename Info>
|
||||
void IniSaverString<Info>::WriteAll(ImGuiContext* ctx,
|
||||
ImGuiSettingsHandler* handler,
|
||||
ImGuiTextBuffer* out_buf) {
|
||||
auto self = static_cast<IniSaverString*>(handler->UserData);
|
||||
for (auto&& it : self->m_map) {
|
||||
out_buf->appendf("[%s][%s]\n", self->m_typeName, it.getKey().data());
|
||||
it.second.WriteIni(out_buf);
|
||||
out_buf->append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace halsimgui
|
||||
@@ -1,36 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 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. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
|
||||
namespace halsimgui {
|
||||
|
||||
template <typename Info>
|
||||
class IniSaverVector : public std::vector<Info> {
|
||||
public:
|
||||
explicit IniSaverVector(const char* typeName) : m_typeName(typeName) {}
|
||||
void Initialize();
|
||||
|
||||
private:
|
||||
static void* ReadOpen(ImGuiContext* ctx, ImGuiSettingsHandler* handler,
|
||||
const char* name);
|
||||
static void ReadLine(ImGuiContext* ctx, ImGuiSettingsHandler* handler,
|
||||
void* entry, const char* lineStr);
|
||||
static void WriteAll(ImGuiContext* ctx, ImGuiSettingsHandler* handler,
|
||||
ImGuiTextBuffer* out_buf);
|
||||
|
||||
const char* m_typeName;
|
||||
};
|
||||
|
||||
} // namespace halsimgui
|
||||
|
||||
#include "IniSaverVector.inl"
|
||||
@@ -1,60 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 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. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace halsimgui {
|
||||
|
||||
template <typename Info>
|
||||
void IniSaverVector<Info>::Initialize() {
|
||||
// hook ini handler to save settings
|
||||
ImGuiSettingsHandler iniHandler;
|
||||
iniHandler.TypeName = m_typeName;
|
||||
iniHandler.TypeHash = ImHashStr(m_typeName);
|
||||
iniHandler.ReadOpenFn = ReadOpen;
|
||||
iniHandler.ReadLineFn = ReadLine;
|
||||
iniHandler.WriteAllFn = WriteAll;
|
||||
iniHandler.UserData = this;
|
||||
ImGui::GetCurrentContext()->SettingsHandlers.push_back(iniHandler);
|
||||
}
|
||||
|
||||
template <typename Info>
|
||||
void* IniSaverVector<Info>::ReadOpen(ImGuiContext* ctx,
|
||||
ImGuiSettingsHandler* handler,
|
||||
const char* name) {
|
||||
auto self = static_cast<IniSaverVector*>(handler->UserData);
|
||||
unsigned int num;
|
||||
if (wpi::StringRef{name}.getAsInteger(10, num)) return nullptr;
|
||||
if (num >= self->size()) self->resize(num + 1);
|
||||
return &(*self)[num];
|
||||
}
|
||||
|
||||
template <typename Info>
|
||||
void IniSaverVector<Info>::ReadLine(ImGuiContext* ctx,
|
||||
ImGuiSettingsHandler* handler, void* entry,
|
||||
const char* lineStr) {
|
||||
auto element = static_cast<Info*>(entry);
|
||||
wpi::StringRef line{lineStr};
|
||||
auto [name, value] = line.split('=');
|
||||
name = name.trim();
|
||||
value = value.trim();
|
||||
element->ReadIni(name, value);
|
||||
}
|
||||
|
||||
template <typename Info>
|
||||
void IniSaverVector<Info>::WriteAll(ImGuiContext* ctx,
|
||||
ImGuiSettingsHandler* handler,
|
||||
ImGuiTextBuffer* out_buf) {
|
||||
auto self = static_cast<IniSaverVector*>(handler->UserData);
|
||||
for (size_t i = 0; i < self->size(); ++i) {
|
||||
out_buf->appendf("[%s][%d]\n", self->m_typeName, static_cast<int>(i));
|
||||
(*self)[i].WriteIni(out_buf);
|
||||
out_buf->append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace halsimgui
|
||||
@@ -7,103 +7,20 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <hal/SimDevice.h>
|
||||
|
||||
#include <hal/Types.h>
|
||||
#include <hal/Value.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <functional>
|
||||
|
||||
#include <imgui.h>
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
|
||||
void HALSIMGUI_DeviceTreeHide(const char* name);
|
||||
void HALSIMGUI_DeviceTreeAdd(void* param, void (*execute)(void*));
|
||||
HAL_Bool HALSIMGUI_DeviceTreeDisplayValue(const char* name, HAL_Bool readonly,
|
||||
struct HAL_Value* value,
|
||||
const char** options,
|
||||
int32_t numOptions);
|
||||
HAL_Bool HALSIMGUI_DeviceTreeStartDevice(const char* label, int32_t flags);
|
||||
void HALSIMGUI_DeviceTreeFinishDevice(void);
|
||||
|
||||
} // extern "C"
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace glass {
|
||||
class DataSource;
|
||||
class DeviceTreeModel;
|
||||
} // namespace glass
|
||||
|
||||
namespace halsimgui {
|
||||
|
||||
class GuiDataSource;
|
||||
|
||||
class SimDeviceGui {
|
||||
public:
|
||||
static void Initialize();
|
||||
|
||||
/**
|
||||
* Hides device on tree.
|
||||
*
|
||||
* @param name device name
|
||||
*/
|
||||
static void Hide(const char* name);
|
||||
|
||||
/**
|
||||
* Adds device to tree. The execute function is called from within the
|
||||
* device tree window context on every frame, so it should implement an
|
||||
* TreeNodeEx() block for each device to display.
|
||||
*
|
||||
* @param execute execute function
|
||||
*/
|
||||
static void Add(std::function<void()> execute);
|
||||
|
||||
/**
|
||||
* Displays device value formatted the same way as SimDevice device values.
|
||||
*
|
||||
* @param name value name
|
||||
* @param readonly prevent value from being modified by the user
|
||||
* @param value value contents (modified in place)
|
||||
* @param options options array for enum values
|
||||
* @param numOptions size of options array for enum values
|
||||
* @return True if value was modified by the user
|
||||
*/
|
||||
static bool DisplayValue(const char* name, bool readonly, HAL_Value* value,
|
||||
const char** options = nullptr,
|
||||
int32_t numOptions = 0);
|
||||
|
||||
/**
|
||||
* Displays device value formatted the same way as SimDevice device values.
|
||||
*
|
||||
* @param name value name
|
||||
* @param readonly prevent value from being modified by the user
|
||||
* @param value value contents (modified in place)
|
||||
* @param source data source (may be nullptr)
|
||||
* @param options options array for enum values
|
||||
* @param numOptions size of options array for enum values
|
||||
* @return True if value was modified by the user
|
||||
*/
|
||||
static bool DisplayValueSource(const char* name, bool readonly,
|
||||
HAL_Value* value, const GuiDataSource* source,
|
||||
const char** options = nullptr,
|
||||
int32_t numOptions = 0);
|
||||
|
||||
/**
|
||||
* Wraps ImGui::CollapsingHeader() to provide consistency and open
|
||||
* persistence. As with the ImGui function, returns true if the tree node
|
||||
* is expanded. If returns true, call StopDevice() to finish the block.
|
||||
*
|
||||
* @param label label
|
||||
* @param flags ImGuiTreeNodeFlags flags
|
||||
* @return True if expanded
|
||||
*/
|
||||
static bool StartDevice(const char* label, ImGuiTreeNodeFlags flags = 0);
|
||||
|
||||
/**
|
||||
* Finish a device block started with StartDevice().
|
||||
*/
|
||||
static void FinishDevice();
|
||||
static glass::DataSource* GetValueSource(HAL_SimValueHandle handle);
|
||||
static glass::DeviceTreeModel& GetDeviceTree();
|
||||
};
|
||||
|
||||
} // namespace halsimgui
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
Reference in New Issue
Block a user