SCRIPT Move cc files

This commit is contained in:
PJ Reiniger
2025-11-07 19:55:39 -05:00
committed by Peter Johnson
parent 10b4a0c971
commit 7ca1be9bae
1197 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,208 @@
// 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 <stdint.h>
#include <functional>
#include <string>
#include <string_view>
#include <imgui.h>
namespace glass {
class Context;
class Storage;
Context* CreateContext();
void DestroyContext(Context* ctx = nullptr);
Context* GetCurrentContext();
void SetCurrentContext(Context* ctx);
/**
* Resets zero time to current time.
*/
void ResetTime();
/**
* Gets the zero time.
*/
uint64_t GetZeroTime();
/**
* Resets the workspace (all storage except window storage).
* Operates effectively like calling LoadStorage() on a path with no existing
* storage files. Note this will result in auto-saving of the reset state to
* storage.
*/
void WorkspaceReset();
/**
* Adds function to be called during workspace (storage) initialization/load.
* This should set up any initial default state, restore stored
* settings/windows, etc. This will be called after the storage is initialized.
* This must be called prior to WorkspaceInit() for proper automatic startup
* loading.
*
* @param init initialization function
*/
void AddWorkspaceInit(std::function<void()> init);
/**
* Adds function to be called during workspace (storage) reset. This should
* bring back the state to startup state (e.g. remove any storage references,
* destroy windows, etc). This will be called prior to the storage being
* destroyed.
*
* @param reset reset function
*/
void AddWorkspaceReset(std::function<void()> reset);
/**
* Sets storage load and auto-save name.
* Call this prior to calling wpi::gui::Initialize() for automatic startup
* loading.
*
* @param name base name, suffix will be generated
*/
void SetStorageName(std::string_view name);
/**
* Sets storage load and auto-save directory. For more customized behavior, set
* Context::storageLoadPath and Context::storageAutoSavePath directly.
* Call this prior to calling wpi::gui::Initialize() for automatic startup
* loading.
*
* @param dir path to directory
*/
void SetStorageDir(std::string_view dir);
/**
* Gets storage auto-save directory.
*
* @return Path to directory
*/
std::string GetStorageDir();
/**
* Explicitly load storage. Set Context::storageLoadDir prior to calling
* wpi::gui::Initialize() for automatic startup loading.
*
* Non-empty root names are not loaded unless GetStorageRoot() is called during
* initialization (or before this function is called).
*
* @param dir path to directory
*/
bool LoadStorage(std::string_view dir);
/**
* Save storage to automatic on-change save location.
*/
bool SaveStorage();
/**
* Explicitly save storage. Set Context::storageAutoSaveDir prior to calling
* wpi::gui::Initialize() for automatic on-change saving.
*
* @param dir path to directory
*/
bool SaveStorage(std::string_view dir);
/**
* Gets the storage root for the current ID stack (e.g. the last call to
* ResetStorageStack).
*
* @return Storage object
*/
Storage& GetCurStorageRoot();
/**
* Gets an arbitrary storage root.
*
* Non-empty root names are saved but not loaded unless GetStorageRoot()
* is called during initialization (or before LoadStorage is called).
*
* @param rootName root name
* @return Storage object
*/
Storage& GetStorageRoot(std::string_view rootName = {});
/**
* Resets storage stack. Should only be called at top level.
*
* @param rootName root name
*/
void ResetStorageStack(std::string_view rootName = {});
/**
* Gets the storage object for the current point in the ID stack.
*
* @return Storage object
*/
Storage& GetStorage();
/**
* Pushes label/ID onto the storage stack, without pushing the imgui ID stack.
*
* @param label_id label or label###id
*/
void PushStorageStack(std::string_view label_id);
/**
* Pushes specific storage onto the storage stack.
*
* @param storage storage
*/
void PushStorageStack(Storage& storage);
/**
* Pops storage stack, without popping the imgui ID stack.
*/
void PopStorageStack();
bool Begin(const char* name, bool* p_open = nullptr,
ImGuiWindowFlags flags = 0);
void End();
bool BeginChild(const char* str_id, const ImVec2& size = ImVec2(0, 0),
bool border = false, ImGuiWindowFlags flags = 0);
void EndChild();
/**
* Saves open status to storage "open" key.
* If returning 'true' the header is open. doesn't indent nor push on ID stack.
* user doesn't have to call TreePop().
*/
bool CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags = 0);
bool TreeNodeEx(const char* label, ImGuiTreeNodeFlags flags = 0);
void TreePop();
// push string into the ID stack (will hash string).
void PushID(const char* str_id);
// push string into the ID stack (will hash string).
void PushID(const char* str_id_begin, const char* str_id_end);
// push string into the ID stack (will hash string).
inline void PushID(std::string_view str) {
PushID(str.data(), str.data() + str.size());
}
// push integer into the ID stack (will hash integer).
void PushID(int int_id);
// pop from the ID stack.
void PopID();
bool PopupEditName(const char* label, std::string* name);
bool ItemEditName(std::string* name);
} // namespace glass

View File

@@ -0,0 +1,46 @@
// 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 <stdint.h>
#include <functional>
#include <string>
#include <vector>
#include <wpi/SmallVector.h>
#include <wpi/StringMap.h>
#include "glass/Context.h"
#include "glass/Storage.h"
namespace glass {
class DataSource;
class Context {
public:
Context();
Context(const Context&) = delete;
Context& operator=(const Context&) = delete;
~Context();
std::vector<std::function<void()>> workspaceInit;
std::vector<std::function<void()>> workspaceReset;
std::string storageLoadDir = ".";
std::string storageAutoSaveDir = ".";
std::string storageName = "imgui";
wpi::SmallVector<Storage*, 32> storageStack;
wpi::StringMap<Storage> storageRoots;
wpi::StringMap<bool> deviceHidden;
wpi::StringMap<DataSource*> sources;
Storage& sourceNameStorage;
uint64_t zeroTime = 0;
bool isPlatformSaveDir = false;
};
extern Context* gContext;
} // namespace glass

View File

@@ -0,0 +1,216 @@
// 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 <stdint.h>
#include <concepts>
#include <cstdio>
#include <string>
#include <string_view>
#include <utility>
#include <imgui.h>
#include <wpi/Signal.h>
#include <wpi/SmallVector.h>
#include <wpi/spinlock.h>
namespace glass {
/**
* A data source for numeric/boolean data.
*/
class DataSource {
public:
virtual ~DataSource();
DataSource(const DataSource&) = delete;
DataSource& operator=(const DataSource&) = delete;
DataSource(DataSource&&) = delete;
DataSource& operator=(DataSource&&) = delete;
const char* GetId() const { return m_id.c_str(); }
virtual const char* GetType() const = 0;
void SetName(std::string_view name) { m_name = name; }
std::string& GetName() { return m_name; }
const std::string& GetName() const { return m_name; }
int64_t GetValueTime() const {
std::scoped_lock lock{m_valueMutex};
return m_valueTime;
}
// drag source helpers
void LabelText(const char* label, const char* fmt, ...) const IM_FMTARGS(3);
void LabelTextV(const char* label, const char* fmt, va_list args) const
IM_FMTLIST(3);
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;
static DataSource* Find(std::string_view id);
static wpi::sig::Signal<const char*, DataSource*> sourceCreated;
private:
std::string m_id;
std::string& m_name;
static std::string& GetNameStorage(std::string_view id);
protected:
explicit DataSource(std::string id)
: m_id{std::move(id)}, m_name{GetNameStorage(m_id)} {}
void Register();
virtual void DragDropTooltip() const;
mutable wpi::spinlock m_valueMutex;
int64_t m_valueTime = 0;
};
template <typename T>
requires std::derived_from<T, DataSource> && requires {
{ T::kType } -> std::convertible_to<const char*>;
}
static T* AcceptDragDropPayload(ImGuiDragDropFlags flags = 0) {
char buf[32];
std::snprintf(buf, sizeof(buf), "DataSource:%s", T::kType);
if (auto payload = ImGui::AcceptDragDropPayload(buf, flags)) {
return static_cast<T*>(*static_cast<DataSource**>(payload->Data));
}
return nullptr;
}
std::string MakeSourceId(std::string_view id, int index);
std::string MakeSourceId(std::string_view id, int index, int index2);
template <typename T>
class ValueSource : public DataSource {
public:
void SetValue(T value, int64_t time = 0) {
std::scoped_lock lock{m_valueMutex};
m_value = value;
m_valueTime = time;
valueChanged(value, time);
}
T GetValue() const {
std::scoped_lock lock{m_valueMutex};
return m_value;
}
wpi::sig::SignalBase<wpi::spinlock, T, int64_t> valueChanged;
private:
T m_value = 0;
protected:
explicit ValueSource(std::string id) : DataSource{std::move(id)} {}
};
class BooleanSource : public ValueSource<bool> {
public:
static constexpr const char* kType = "boolean";
explicit BooleanSource(std::string id) : ValueSource{std::move(id)} {
Register();
}
const char* GetType() const override;
};
class DoubleSource : public ValueSource<double> {
public:
static constexpr const char* kType = "boolean";
explicit DoubleSource(std::string id) : ValueSource{std::move(id)} {
Register();
}
const char* GetType() const override;
};
class FloatSource : public ValueSource<float> {
public:
static constexpr const char* kType = "float";
explicit FloatSource(std::string id) : ValueSource{std::move(id)} {
Register();
}
const char* GetType() const override;
};
class IntegerSource : public ValueSource<int64_t> {
public:
static constexpr const char* kType = "integer";
explicit IntegerSource(std::string id) : ValueSource{std::move(id)} {
Register();
}
const char* GetType() const override;
};
class StringSource : public DataSource {
public:
static constexpr const char* kType = "string";
explicit StringSource(std::string id) : DataSource{std::move(id)} {
Register();
}
const char* GetType() const override;
void SetValue(std::string_view value, int64_t time = 0) {
std::scoped_lock lock{m_valueMutex};
m_value = value;
m_valueTime = time;
valueChanged(m_value, time);
}
void SetValue(std::string&& value, int64_t time = 0) {
std::scoped_lock lock{m_valueMutex};
m_value = std::move(value);
m_valueTime = time;
valueChanged(m_value, time);
}
void SetValue(const char* value, int64_t time = 0) {
std::scoped_lock lock{m_valueMutex};
m_value = value;
m_valueTime = time;
valueChanged(m_value, time);
}
std::string GetValue() const {
std::scoped_lock lock{m_valueMutex};
return m_value;
}
std::string_view GetValue(wpi::SmallVectorImpl<char>& buf) const {
std::scoped_lock lock{m_valueMutex};
buf.assign(m_value.begin(), m_value.end());
return {buf.begin(), buf.end()};
}
wpi::sig::SignalBase<wpi::spinlock, std::string_view, int64_t> valueChanged;
private:
std::string m_value;
};
} // namespace glass

View File

@@ -0,0 +1,56 @@
// 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 <functional>
#include <memory>
#include <vector>
#include <portable-file-dialogs.h>
namespace glass {
/**
* GUI main menu bar.
*/
class MainMenuBar {
public:
/**
* Displays the main menu bar. Should be added to GUI LateExecute.
*/
void Display();
/**
* Displays workspace menu. Called by Display().
*/
void WorkspaceMenu();
/**
* 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.
*
* @param menu menu display function
*/
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.
*
* @param menu menu display function
*/
void AddOptionMenu(std::function<void()> menu);
private:
std::vector<std::function<void()>> m_optionMenus;
std::vector<std::function<void()>> m_menus;
std::unique_ptr<pfd::select_folder> m_openFolder;
std::unique_ptr<pfd::select_folder> m_saveFolder;
};
} // namespace glass

View File

@@ -0,0 +1,22 @@
// 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 glass {
class Model {
public:
Model() = default;
virtual ~Model() = default;
Model(const Model&) = delete;
Model& operator=(const Model&) = delete;
virtual void Update() = 0;
virtual bool Exists() = 0;
virtual bool IsReadOnly();
};
} // namespace glass

View File

@@ -0,0 +1,225 @@
// 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 <algorithm>
#include <functional>
#include <memory>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
#include <wpigui.h>
#include "glass/Model.h"
#include "glass/WindowManager.h"
namespace glass {
class Storage;
namespace detail {
struct ProviderFunctions {
using Exists = std::function<bool()>;
using CreateModel = std::function<std::unique_ptr<Model>()>;
using ViewExists = std::function<bool(Model*)>;
using CreateView = std::function<std::unique_ptr<View>(Window*, Model*)>;
};
} // namespace detail
/**
* Providers are registries of models and views. They have ownership over
* their created Models, Windows, and Views.
*
* GlobalInit() configures Update() to be called during EarlyExecute.
* Calling Update() calls Update() on all created models (Provider
* implementations must ensure this occurs).
*
* @tparam Functions defines functor interface types
*/
template <typename Functions = detail::ProviderFunctions>
class Provider : public WindowManager {
public:
using ExistsFunc = typename Functions::Exists;
using CreateModelFunc = typename Functions::CreateModel;
using ViewExistsFunc = typename Functions::ViewExists;
using CreateViewFunc = typename Functions::CreateView;
/**
* Constructor.
*
* @param storage Storage
*/
explicit Provider(Storage& storage) : WindowManager{storage} {}
Provider(const Provider&) = delete;
Provider& operator=(const Provider&) = delete;
/**
* Perform global initialization. This should be called prior to
* wpi::gui::Initialize().
*/
void GlobalInit() override {
WindowManager::GlobalInit();
wpi::gui::AddEarlyExecute([this] { Update(); });
}
/**
* Show the specified view by default on first load. Has no effect if
* the user previously hid the window (e.g. in a saved prior execution).
*
* @param name View name
*/
void ShowDefault(std::string_view name) {
auto win = GetWindow(name);
if (win) {
return;
}
auto it = FindViewEntry(name);
if (it == m_viewEntries.end() || (*it)->name != name) {
return;
}
(*it)->showDefault = true;
}
/**
* Register a model and view combination. Equivalent to calling both
* RegisterModel() and RegisterView() with no ViewExistsFunc.
*
* @param name View/model name
* @param exists Functor, returns true if model can be created
* @param createModel Functor for creating model
* @param createView Functor for creating view
*/
void Register(std::string_view name, ExistsFunc exists,
CreateModelFunc createModel, CreateViewFunc createView) {
RegisterModel(name, std::move(exists), std::move(createModel));
RegisterView(name, name, nullptr, std::move(createView));
}
/**
* Register a model.
*
* @param name Model name
* @param exists Functor, returns true if model can be created
* @param createModel Functor for creating model
*/
void RegisterModel(std::string_view name, ExistsFunc exists,
CreateModelFunc createModel) {
auto it = FindModelEntry(name);
// ignore if exists
if (it != m_modelEntries.end() && (*it)->name == name) {
return;
}
// insert in sorted location
m_modelEntries.emplace(
it, MakeModelEntry(name, std::move(exists), std::move(createModel)));
}
/**
* Register a view.
*
* @param name View name
* @param modelName Model name
* @param exists Functor, returns true if view can be created
* @param createView Functor for creating view
*/
void RegisterView(std::string_view name, std::string_view modelName,
ViewExistsFunc exists, CreateViewFunc createView) {
// find model; if model doesn't exist, ignore
auto modelIt = FindModelEntry(modelName);
if (modelIt == m_modelEntries.end() || (*modelIt)->name != modelName) {
return;
}
auto viewIt = FindViewEntry(name);
// ignore if exists
if (viewIt != m_viewEntries.end() && (*viewIt)->name == name) {
return;
}
// insert in sorted location
m_viewEntries.emplace(viewIt,
MakeViewEntry(name, modelIt->get(), std::move(exists),
std::move(createView)));
}
protected:
virtual void Update() {
// update entries
for (auto&& entry : m_modelEntries) {
if (entry->model) {
entry->model->Update();
}
}
}
struct ModelEntry {
ModelEntry(std::string_view name, ExistsFunc exists,
CreateModelFunc createModel)
: name{name},
exists{std::move(exists)},
createModel{std::move(createModel)} {}
virtual ~ModelEntry() = default;
std::string name;
ExistsFunc exists;
CreateModelFunc createModel;
std::unique_ptr<Model> model;
};
struct ViewEntry {
ViewEntry(std::string_view name, ModelEntry* modelEntry,
ViewExistsFunc exists, CreateViewFunc createView)
: name{name},
modelEntry{modelEntry},
exists{std::move(exists)},
createView{std::move(createView)} {}
virtual ~ViewEntry() = default;
std::string name;
ModelEntry* modelEntry;
ViewExistsFunc exists;
CreateViewFunc createView;
bool showDefault = false;
Window* window = nullptr;
};
// sorted by name
using ModelEntries = std::vector<std::unique_ptr<ModelEntry>>;
ModelEntries m_modelEntries;
using ViewEntries = std::vector<std::unique_ptr<ViewEntry>>;
ViewEntries m_viewEntries;
typename ModelEntries::iterator FindModelEntry(std::string_view name) {
return std::lower_bound(
m_modelEntries.begin(), m_modelEntries.end(), name,
[](const auto& elem, std::string_view s) { return elem->name < s; });
}
typename ViewEntries::iterator FindViewEntry(std::string_view name) {
return std::lower_bound(
m_viewEntries.begin(), m_viewEntries.end(), name,
[](const auto& elem, std::string_view s) { return elem->name < s; });
}
virtual std::unique_ptr<ModelEntry> MakeModelEntry(
std::string_view name, ExistsFunc exists, CreateModelFunc createModel) {
return std::make_unique<ModelEntry>(name, std::move(exists),
std::move(createModel));
}
virtual std::unique_ptr<ViewEntry> MakeViewEntry(std::string_view name,
ModelEntry* modelEntry,
ViewExistsFunc exists,
CreateViewFunc createView) {
return std::make_unique<ViewEntry>(name, modelEntry, std::move(exists),
std::move(createView));
}
virtual void Show(ViewEntry* entry, Window* window) = 0;
};
} // namespace glass

View File

@@ -0,0 +1,288 @@
// 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 <stdint.h>
#include <functional>
#include <memory>
#include <span>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
#include <wpi/StringMap.h>
#include <wpi/iterator_range.h>
#include <wpi/json_fwd.h>
namespace glass {
namespace detail {
template <typename IteratorType>
class ChildIterator;
} // namespace detail
/**
* Storage provides both persistent and non-persistent nested key/value storage
* for widgets.
*
* Keys are always strings. The storage also provides non-persistent arbitrary
* data storage (via std::shared_ptr<void>).
*
* Storage is automatically indexed internally by the ID stack. Note it is
* necessary to use the glass wrappers for PushID et al to preserve naming in
* the save file (unnamed values are still stored, but this is non-ideal for
* users trying to hand-edit the save file).
*/
class Storage {
public:
struct Value {
enum Type {
kNone,
kInt,
kInt64,
kBool,
kFloat,
kDouble,
kString,
kChild,
kIntArray,
kInt64Array,
kBoolArray,
kFloatArray,
kDoubleArray,
kStringArray,
kChildArray
};
Value() = default;
explicit Value(Type type) : type{type} {}
Value(const Value&) = delete;
Value& operator=(const Value&) = delete;
~Value() { Reset(kNone); }
Type type = kNone;
union {
int intVal;
int64_t int64Val;
bool boolVal;
float floatVal;
double doubleVal;
Storage* child;
std::vector<int>* intArray;
std::vector<int64_t>* int64Array;
std::vector<int>* boolArray;
std::vector<float>* floatArray;
std::vector<double>* doubleArray;
std::vector<std::string>* stringArray;
std::vector<std::unique_ptr<Storage>>* childArray;
};
std::string stringVal;
union {
int intDefault;
int64_t int64Default;
bool boolDefault;
float floatDefault;
double doubleDefault;
// pointers may be nullptr to indicate empty
std::vector<int>* intArrayDefault;
std::vector<int64_t>* int64ArrayDefault;
std::vector<int>* boolArrayDefault;
std::vector<float>* floatArrayDefault;
std::vector<double>* doubleArrayDefault;
std::vector<std::string>* stringArrayDefault;
};
std::string stringDefault;
bool hasDefault = false;
void Reset(Type newType);
};
using ValueMap = wpi::StringMap<std::unique_ptr<Value>>;
template <typename Iterator>
using ChildIterator = detail::ChildIterator<Iterator>;
// The "Read" functions don't create or overwrite the value
int ReadInt(std::string_view key, int defaultVal = 0) const;
int64_t ReadInt64(std::string_view key, int64_t defaultVal = 0) const;
bool ReadBool(std::string_view key, bool defaultVal = false) const;
float ReadFloat(std::string_view key, float defaultVal = 0.0f) const;
double ReadDouble(std::string_view key, double defaultVal = 0.0) const;
std::string ReadString(std::string_view key,
std::string_view defaultVal = {}) const;
void SetInt(std::string_view key, int val);
void SetInt64(std::string_view key, int64_t val);
void SetBool(std::string_view key, bool val);
void SetFloat(std::string_view key, float val);
void SetDouble(std::string_view key, double val);
void SetString(std::string_view key, std::string_view val);
// The "Get" functions create or override the current value type.
// If the value is not set, it is set to the provided default.
int& GetInt(std::string_view key, int defaultVal = 0);
int64_t& GetInt64(std::string_view key, int64_t defaultVal = 0);
bool& GetBool(std::string_view key, bool defaultVal = false);
float& GetFloat(std::string_view key, float defaultVal = 0.0f);
double& GetDouble(std::string_view key, double defaultVal = 0.0);
std::string& GetString(std::string_view key,
std::string_view defaultVal = {});
std::vector<int>& GetIntArray(std::string_view key,
std::span<const int> defaultVal = {});
std::vector<int64_t>& GetInt64Array(std::string_view key,
std::span<const int64_t> defaultVal = {});
std::vector<int>& GetBoolArray(std::string_view key,
std::span<const int> defaultVal = {});
std::vector<float>& GetFloatArray(std::string_view key,
std::span<const float> defaultVal = {});
std::vector<double>& GetDoubleArray(std::string_view key,
std::span<const double> defaultVal = {});
std::vector<std::string>& GetStringArray(
std::string_view key, std::span<const std::string> defaultVal = {});
std::vector<std::unique_ptr<Storage>>& GetChildArray(std::string_view key);
Value* FindValue(std::string_view key);
Value& GetValue(std::string_view key);
Storage& GetChild(std::string_view label_id);
void SetData(std::shared_ptr<void>&& data) { m_data = std::move(data); }
template <typename T>
T* GetData() const {
return static_cast<T*>(m_data.get());
}
Storage() = default;
Storage(const Storage&) = delete;
Storage& operator=(const Storage&) = delete;
void Insert(std::string_view key, std::unique_ptr<Value> value) {
m_values[key] = std::move(value);
}
std::unique_ptr<Value> Erase(std::string_view key);
void EraseAll() { m_values.clear(); }
ValueMap& GetValues() { return m_values; }
const ValueMap& GetValues() const { return m_values; }
wpi::iterator_range<ChildIterator<ValueMap::iterator>> GetChildren();
/**
* Erases all children (at top level).
*/
void EraseChildren();
bool FromJson(const wpi::json& json, const char* filename);
wpi::json ToJson() const;
/**
* Clear settings (set to default). Calls custom clear function (if set),
* otherwise calls ClearValues().
*/
void Clear();
/**
* Clear values (and values of children) only (set to default). Does not
* call custom clear function.
*/
void ClearValues();
/**
* Apply settings (called after all settings have been loaded). Calls
* custom apply function (if set), otherwise calls ApplyChildren().
*/
void Apply();
/**
* Apply settings to children. Does not call custom apply function.
*/
void ApplyChildren();
/**
* Sets custom JSON handlers (replaces FromJson and ToJson).
*
* @param fromJson replacement for FromJson()
* @param toJson replacement for ToJson()
*/
void SetCustomJson(
std::function<bool(const wpi::json& json, const char* filename)> fromJson,
std::function<wpi::json()> toJson) {
m_fromJson = std::move(fromJson);
m_toJson = std::move(toJson);
}
void SetCustomClear(std::function<void()> clear) {
m_clear = std::move(clear);
}
void SetCustomApply(std::function<void()> apply) {
m_apply = std::move(apply);
}
private:
mutable ValueMap m_values;
std::shared_ptr<void> m_data;
std::function<bool(const wpi::json& json, const char* filename)> m_fromJson;
std::function<wpi::json()> m_toJson;
std::function<void()> m_clear;
std::function<void()> m_apply;
};
namespace detail {
/// proxy class for the GetChildren() function
template <typename IteratorType>
class ChildIterator {
private:
/// the iterator
IteratorType anchor;
IteratorType end;
public:
ChildIterator(IteratorType it, IteratorType end) noexcept
: anchor(it), end(end) {
while (anchor != end && anchor->second->type != Storage::Value::kChild) {
++anchor;
}
}
/// dereference operator (needed for range-based for)
ChildIterator& operator*() { return *this; }
/// increment operator (needed for range-based for)
ChildIterator& operator++() {
++anchor;
while (anchor != end && anchor->second->type != Storage::Value::kChild) {
++anchor;
}
return *this;
}
/// inequality operator (needed for range-based for)
bool operator!=(const ChildIterator& o) const noexcept {
return anchor != o.anchor;
}
/// return key of the iterator
std::string_view key() const { return anchor->first; }
/// return value of the iterator
Storage& value() const { return *anchor->second->child; }
};
} // namespace detail
inline auto Storage::GetChildren()
-> wpi::iterator_range<ChildIterator<ValueMap::iterator>> {
return {{m_values.begin(), m_values.end()}, {m_values.end(), m_values.end()}};
}
} // namespace glass

View File

@@ -0,0 +1,59 @@
// 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 <memory>
#include <wpi/FunctionExtras.h>
namespace glass {
/**
* A view is the contents of a window (1:1 mapping).
* It may reference multiple models.
*
* Typically a view is constructed by a Provider and the View's constructor
* is given the corresponding Model(s).
*
* A view may retain a reference to its parent window for dynamic
* window configuration.
*/
class View {
public:
virtual ~View() = default;
/**
* Displays the window contents. Called by Window::Display() from within an
* ImGui::Begin() / ImGui::End() block.
*/
virtual void Display() = 0;
/**
* Called instead of Display() when the window is hidden (e.g. when
* ImGui::Begin() returns false).
*/
virtual void Hidden();
/**
* Called from within ImGui::BeginContextPopupItem() and ImGui::EndPopup().
* Used to display the settings for the view
*/
virtual void Settings();
/**
* If the view has settings and if the result of Settings should be displayed.
*/
virtual bool HasSettings();
};
/**
* Make a View for a display functor.
*
* @param display Display function
* @return unique_ptr to View
*/
std::unique_ptr<View> MakeFunctionView(wpi::unique_function<void()> display);
} // namespace glass

View File

@@ -0,0 +1,140 @@
// 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 <memory>
#include <string>
#include <string_view>
#include <utility>
#include <imgui.h>
#include "glass/View.h"
namespace glass {
class Storage;
/**
* Managed window information.
* A Window owns the View that displays the window's contents.
*/
class Window {
public:
enum Visibility { kHide = 0, kShow, kDisabled };
Window(Storage& storage, std::string_view id,
Visibility defaultVisibility = kShow);
std::string_view GetId() const { return m_id; }
bool HasView() { return static_cast<bool>(m_view); }
void SetView(std::unique_ptr<View> view) { m_view = std::move(view); }
View* GetView() { return m_view.get(); }
const View* GetView() const { return m_view.get(); }
bool IsVisible() const { return m_visible; }
void SetVisible(bool visible) { m_visible = visible; }
bool IsEnabled() const { return m_enabled; }
void SetEnabled(bool enabled) { m_enabled = enabled; }
void SetFlags(ImGuiWindowFlags flags) { m_flags = flags; }
void SetName(std::string_view name) { m_name = name; }
void SetDefaultName(std::string_view name) { m_defaultName = name; }
/**
* Normally windows provide a right-click popup menu on the title bar to
* rename the window. Calling this disables that functionality so the
* view can provide its own popup.
*/
void DisableRenamePopup() { m_renamePopupEnabled = false; }
/**
* Sets visibility of window.
*
* @param visibility 0=hide, 1=show, 2=disabled (force-hide)
*/
void SetVisibility(Visibility visibility);
/**
* Sets default visibility of window.
*
* @param visibility 0=hide, 1=show, 2=disabled (force-hide)
*/
void SetDefaultVisibility(Visibility visibility);
/**
* Sets default position of window.
*
* @param x x location of upper left corner
* @param y y location of upper left corner
*/
void SetDefaultPos(float x, float y) {
m_posCond = ImGuiCond_FirstUseEver;
m_pos = ImVec2{x, y};
}
/**
* Sets default size of window.
*
* @param width width
* @param height height
*/
void SetDefaultSize(float width, float height) {
m_sizeCond = ImGuiCond_FirstUseEver;
m_size = ImVec2{width, height};
}
/**
* Sets internal padding of window.
* @param x horizontal padding
* @param y vertical padding
*/
void SetPadding(float x, float y) {
m_setPadding = true;
m_padding = ImVec2{x, y};
}
/**
* Displays window.
*/
void Display();
/**
* Displays menu item for the window.
* @param label what to display as the menu item label; defaults to
* window ID if nullptr
* @return True if window went from invisible to visible.
*/
bool DisplayMenuItem(const char* label = nullptr);
/**
* Scale default window position and size.
*/
void ScaleDefault(float scale);
private:
std::string m_id;
std::string& m_name;
std::string m_defaultName;
std::unique_ptr<View> m_view;
ImGuiWindowFlags m_flags = 0;
bool& m_visible;
bool& m_enabled;
bool& m_defaultVisible;
bool& m_defaultEnabled;
bool m_renamePopupEnabled = true;
ImGuiCond m_posCond = 0;
ImGuiCond m_sizeCond = 0;
ImVec2 m_pos;
ImVec2 m_size;
bool m_setPadding = false;
ImVec2 m_padding;
};
} // namespace glass

View File

@@ -0,0 +1,146 @@
// 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 <memory>
#include <string_view>
#include <vector>
#include <wpi/FunctionExtras.h>
#include "glass/Window.h"
namespace glass {
class Storage;
/**
* Window manager.
*
* To properly integrate into an application:
* - Call GlobalInit() from the application main, after calling
* wpi::gui::CreateContext(), but before calling wpi::gui::Initialize().
* - Add DisplayMenu() to the application's MainMenuBar.
*/
class WindowManager {
public:
/**
* Constructor.
*
* @param storage Storage for window information
*/
explicit WindowManager(Storage& storage);
virtual ~WindowManager() = default;
WindowManager(const WindowManager&) = delete;
WindowManager& operator=(const WindowManager&) = delete;
/**
* Perform global initialization. This should be called prior to
* wpi::gui::Initialize().
*/
virtual void GlobalInit();
/**
* Displays menu contents, one item for each window.
* See Window::DisplayMenuItem().
*/
virtual void DisplayMenu();
/**
* 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 gui::AddExecute(), using this function ensures
* the windows are consistently integrated with the rest of the GUI.
*
* On each Dear ImGui frame, gui::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 gui::AddExecute() function.
*
* @param id unique identifier of the window (title bar)
* @param display window contents display function
* @param defaultVisibility default window visibility
*/
Window* AddWindow(std::string_view id, wpi::unique_function<void()> display,
Window::Visibility defaultVisibility = Window::kShow);
/**
* Adds window to GUI. The view's display function is called from within a
* ImGui::Begin()/End() block. While windows can be created within the
* execute function passed to gui::AddExecute(), using this function ensures
* the windows are consistently integrated with the rest of the GUI.
*
* On each Dear ImGui frame, gui::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 gui::AddExecute() function.
*
* @param id unique identifier of the window (title bar)
* @param view view object
* @param defaultVisibility default window visibility
* @return Window, or nullptr on duplicate window
*/
Window* AddWindow(std::string_view id, std::unique_ptr<View> view,
Window::Visibility defaultVisibility = Window::kShow);
/**
* Adds window to GUI. A View must be assigned to the returned Window
* to display the window contents. While windows can be created within the
* execute function passed to gui::AddExecute(), using this function ensures
* the windows are consistently integrated with the rest of the GUI.
*
* On each Dear ImGui frame, gui::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 gui::AddExecute() function.
*
* @param id unique identifier of the window (default title bar)
* @param duplicateOk if false, warn on duplicates
* @param defaultVisibility default window visibility
* @return Window, or nullptr on duplicate window
*/
Window* GetOrAddWindow(std::string_view id, bool duplicateOk = false,
Window::Visibility defaultVisibility = Window::kShow);
/**
* Gets existing window. If none exists, returns nullptr.
*
* @param id unique identifier of the window (default title bar)
* @return Window, or nullptr if window does not exist
*/
Window* GetWindow(std::string_view id);
/**
* Erases all windows.
*/
void EraseWindows() { m_windows.clear(); }
/**
* Get window count.
*/
size_t GetNumWindows() const { return m_windows.size(); }
protected:
/**
* Removes existing window (by index)
*
* @param index index of window in m_windows
*/
void RemoveWindow(size_t index);
// kept sorted by id
std::vector<std::unique_ptr<Window>> m_windows;
Storage& m_storage;
private:
void DisplayWindows();
};
} // namespace glass

View File

@@ -0,0 +1,36 @@
// 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 <string_view>
#include <wpi/function_ref.h>
#include "glass/Model.h"
namespace glass {
class DoubleSource;
class AnalogInputModel : public Model {
public:
virtual const char* GetSimDevice() const = 0;
virtual DoubleSource* GetVoltageData() = 0;
virtual void SetVoltage(double val) = 0;
};
class AnalogInputsModel : public Model {
public:
virtual void ForEachAnalogInput(
wpi::function_ref<void(AnalogInputModel& model, int index)> func) = 0;
};
void DisplayAnalogInput(AnalogInputModel* model, int index);
void DisplayAnalogInputs(AnalogInputsModel* model,
std::string_view noneMsg = "No analog inputs");
} // namespace glass

View File

@@ -0,0 +1,64 @@
// 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 <string_view>
#include <wpi/function_ref.h>
#include "glass/Model.h"
namespace glass {
class EncoderModel;
class BooleanSource;
class DoubleSource;
class DPWMModel : public Model {
public:
virtual const char* GetSimDevice() const = 0;
virtual DoubleSource* GetValueData() = 0;
virtual void SetValue(double val) = 0;
};
class DutyCycleModel : public Model {
public:
virtual const char* GetSimDevice() const = 0;
virtual DoubleSource* GetValueData() = 0;
virtual void SetValue(double val) = 0;
};
class DIOModel : public Model {
public:
virtual const char* GetName() const = 0;
virtual const char* GetSimDevice() const = 0;
virtual DPWMModel* GetDPWM() = 0;
virtual DutyCycleModel* GetDutyCycle() = 0;
virtual EncoderModel* GetEncoder() = 0;
virtual bool IsInput() const = 0;
virtual BooleanSource* GetValueData() = 0;
virtual void SetValue(bool val) = 0;
};
class DIOsModel : public Model {
public:
virtual void ForEachDIO(
wpi::function_ref<void(DIOModel& model, int index)> func) = 0;
};
void DisplayDIO(DIOModel* model, int index, bool outputsEnabled);
void DisplayDIOs(DIOsModel* model, bool outputsEnabled,
std::string_view noneMsg = "No Digital I/O");
} // namespace glass

View File

@@ -0,0 +1,59 @@
// 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 <string_view>
#include <wpi/function_ref.h>
#include "glass/Model.h"
namespace glass {
class BooleanSource;
class DoubleSource;
class IntegerSource;
class EncoderModel : public Model {
public:
virtual void SetName(std::string_view name);
virtual const char* GetSimDevice() const = 0;
virtual int GetChannelA() const = 0;
virtual int GetChannelB() const = 0;
virtual DoubleSource* GetDistancePerPulseData() = 0;
virtual IntegerSource* GetCountData() = 0;
virtual DoubleSource* GetPeriodData() = 0;
virtual BooleanSource* GetDirectionData() = 0;
virtual DoubleSource* GetDistanceData() = 0;
virtual DoubleSource* GetRateData() = 0;
virtual double GetMaxPeriod() = 0;
virtual bool GetReverseDirection() = 0;
virtual void SetDistancePerPulse(double val) = 0;
virtual void SetCount(int val) = 0;
virtual void SetPeriod(double val) = 0;
virtual void SetDirection(bool val) = 0;
virtual void SetDistance(double val) = 0;
virtual void SetRate(double val) = 0;
virtual void SetMaxPeriod(double val) = 0;
virtual void SetReverseDirection(bool val) = 0;
};
class EncodersModel : public Model {
public:
virtual void ForEachEncoder(
wpi::function_ref<void(EncoderModel& model, int index)> func) = 0;
};
void DisplayEncoder(EncoderModel* model);
void DisplayEncoders(EncodersModel* model,
std::string_view noneMsg = "No encoders");
} // namespace glass

View File

@@ -0,0 +1,20 @@
// 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 "glass/Model.h"
namespace glass {
class DoubleSource;
class GyroModel : public Model {
public:
virtual const char* GetName() const = 0;
virtual const char* GetSimDevice() const = 0;
virtual DoubleSource* GetAngleData() = 0;
virtual void SetAngle(double angle) = 0;
};
void DisplayGyro(GyroModel* m);
} // namespace glass

View File

@@ -0,0 +1,42 @@
// 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 <span>
#include <wpi/function_ref.h>
#include "glass/Model.h"
namespace wpi {
template <typename T>
class SmallVectorImpl;
} // namespace wpi
namespace glass {
class LEDDisplayModel : public glass::Model {
public:
struct Data {
uint8_t r;
uint8_t g;
uint8_t b;
};
virtual std::span<const Data> GetData(wpi::SmallVectorImpl<Data>& buf) = 0;
};
class LEDDisplaysModel : public glass::Model {
public:
virtual size_t GetNumLEDDisplays() = 0;
virtual void ForEachLEDDisplay(
wpi::function_ref<void(LEDDisplayModel& model, int index)> func) = 0;
};
void DisplayLEDDisplay(LEDDisplayModel* model, int index);
void DisplayLEDDisplays(LEDDisplaysModel* model);
} // namespace glass

View File

@@ -0,0 +1,19 @@
// 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 "glass/Model.h"
namespace glass {
class DoubleSource;
class MotorControllerModel : public Model {
public:
virtual const char* GetName() const = 0;
virtual const char* GetSimDevice() const = 0;
virtual DoubleSource* GetPercentData() = 0;
virtual void SetPercent(double value) = 0;
};
void DisplayMotorController(MotorControllerModel* m);
} // namespace glass

View File

@@ -0,0 +1,34 @@
// 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 <string_view>
#include <wpi/function_ref.h>
#include "glass/Model.h"
namespace glass {
class DoubleSource;
class PWMModel : public Model {
public:
virtual DoubleSource* GetSpeedData() = 0;
virtual void SetSpeed(double val) = 0;
};
class PWMsModel : public Model {
public:
virtual void ForEachPWM(
wpi::function_ref<void(PWMModel& model, int index)> func) = 0;
};
void DisplayPWM(PWMModel* model, int index, bool outputsEnabled);
void DisplayPWMs(PWMsModel* model, bool outputsEnabled,
std::string_view noneMsg = "No PWM outputs");
} // namespace glass

View File

@@ -0,0 +1,81 @@
// 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 <memory>
#include <string_view>
#include <utility>
#include <wpi/function_ref.h>
#include "glass/Model.h"
namespace glass {
class BooleanSource;
class DoubleSource;
class CompressorModel : public Model {
public:
virtual BooleanSource* GetRunningData() = 0;
virtual BooleanSource* GetEnabledData() = 0;
virtual BooleanSource* GetPressureSwitchData() = 0;
virtual DoubleSource* GetCurrentData() = 0;
virtual void SetRunning(bool val) = 0;
virtual void SetEnabled(bool val) = 0;
virtual void SetPressureSwitch(bool val) = 0;
virtual void SetCurrent(double val) = 0;
};
class SolenoidModel : public Model {
public:
virtual BooleanSource* GetOutputData() = 0;
virtual void SetOutput(bool val) = 0;
};
class PneumaticControlModel : public Model {
public:
virtual CompressorModel* GetCompressor() = 0;
virtual void ForEachSolenoid(
wpi::function_ref<void(SolenoidModel& model, int index)> func) = 0;
virtual std::string_view GetName() = 0;
};
class PneumaticControlsModel : public Model {
public:
virtual void ForEachPneumaticControl(
wpi::function_ref<void(PneumaticControlModel& model, int index)>
func) = 0;
};
struct AllPneumaticControlsModel : public Model {
AllPneumaticControlsModel(std::unique_ptr<PneumaticControlsModel> pcms,
std::unique_ptr<PneumaticControlsModel> phs)
: pcms{std::move(pcms)}, phs{std::move(phs)} {};
std::unique_ptr<PneumaticControlsModel> pcms;
std::unique_ptr<PneumaticControlsModel> phs;
void Update() override {
pcms->Update();
phs->Update();
};
bool Exists() override { return true; }
};
bool DisplayPneumaticControlSolenoids(PneumaticControlModel* model, int index,
bool outputsEnabled);
void DisplayPneumaticControlsSolenoids(
PneumaticControlsModel* model, bool outputsEnabled,
std::string_view noneMsg = "No solenoids");
void DisplayCompressorDevice(CompressorModel* model, int index,
bool outputsEnabled);
void DisplayCompressorsDevice(PneumaticControlsModel* model,
bool outputsEnabled);
} // namespace glass

View File

@@ -0,0 +1,42 @@
// 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 <string_view>
#include <wpi/function_ref.h>
#include "glass/Model.h"
namespace glass {
class DoubleSource;
class PowerDistributionModel : public Model {
public:
virtual int GetNumChannels() const = 0;
virtual DoubleSource* GetTemperatureData() = 0;
virtual DoubleSource* GetVoltageData() = 0;
virtual DoubleSource* GetCurrentData(int channel) = 0;
virtual void SetTemperature(double val) = 0;
virtual void SetVoltage(double val) = 0;
virtual void SetCurrent(int channel, double val) = 0;
};
class PowerDistributionsModel : public Model {
public:
virtual void ForEachPowerDistribution(
wpi::function_ref<void(PowerDistributionModel& model, int index)>
func) = 0;
};
void DisplayPowerDistribution(PowerDistributionModel* model, int index);
void DisplayPowerDistributions(
PowerDistributionsModel* model,
std::string_view noneMsg = "No Power Distributions");
} // namespace glass

View File

@@ -0,0 +1,41 @@
// 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 "glass/Model.h"
namespace glass {
class BooleanSource;
class DoubleSource;
class IntegerSource;
class RoboRioRailModel : public Model {
public:
virtual DoubleSource* GetVoltageData() = 0;
virtual DoubleSource* GetCurrentData() = 0;
virtual BooleanSource* GetActiveData() = 0;
virtual IntegerSource* GetFaultsData() = 0;
virtual void SetVoltage(double val) = 0;
virtual void SetCurrent(double val) = 0;
virtual void SetActive(bool val) = 0;
virtual void SetFaults(int val) = 0;
};
class RoboRioModel : public Model {
public:
virtual RoboRioRailModel* GetUser3V3Rail() = 0;
virtual DoubleSource* GetVInVoltageData() = 0;
virtual DoubleSource* GetBrownoutVoltage() = 0;
virtual void SetVInVoltage(double val) = 0;
virtual void SetBrownoutVoltage(double val) = 0;
};
void DisplayRoboRio(RoboRioModel* model);
} // namespace glass

View File

@@ -0,0 +1,23 @@
// 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 <string>
#include <vector>
#include "glass/Model.h"
namespace glass {
class AlertsModel : public Model {
public:
virtual const std::vector<std::string>& GetInfos() = 0;
virtual const std::vector<std::string>& GetWarnings() = 0;
virtual const std::vector<std::string>& GetErrors() = 0;
};
void DisplayAlerts(AlertsModel* model);
} // namespace glass

View File

@@ -0,0 +1,21 @@
// 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 <string>
#include <vector>
#include "glass/Model.h"
namespace glass {
class DataSource;
class CommandSchedulerModel : public Model {
public:
virtual const char* GetName() const = 0;
virtual const std::vector<std::string>& GetCurrentCommands() = 0;
virtual void CancelCommand(size_t index) = 0;
};
void DisplayCommandScheduler(CommandSchedulerModel* m);
} // namespace glass

View File

@@ -0,0 +1,18 @@
// 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 "glass/Model.h"
namespace glass {
class BooleanSource;
class CommandSelectorModel : public Model {
public:
virtual const char* GetName() const = 0;
virtual BooleanSource* GetRunningData() = 0;
virtual void SetRunning(bool run) = 0;
};
void DisplayCommandSelector(CommandSelectorModel* m);
} // namespace glass

View File

@@ -0,0 +1,140 @@
// 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 <memory>
#include <utility>
#include <vector>
#include <imgui.h>
#include <wpi/FunctionExtras.h>
#include "glass/Model.h"
namespace glass {
class DataSource;
/**
* Model for device tree.
*/
class DeviceTreeModel : public Model {
public:
using DisplayFunc = wpi::unique_function<void(Model*)>;
/**
* Add a display to the device tree.
*
* @param model Model to keep updated (may be nullptr)
* @param display Display function
*/
void Add(std::unique_ptr<Model> model, DisplayFunc display) {
m_displays.emplace_back(model.get(), std::move(display));
m_ownedModels.emplace_back(std::move(model));
}
void Add(Model* model, DisplayFunc display) {
m_displays.emplace_back(model, std::move(display));
}
void Update() override;
bool Exists() override;
void Display();
private:
std::vector<std::pair<Model*, DisplayFunc>> m_displays;
std::vector<std::unique_ptr<Model>> m_ownedModels;
};
/**
* Hides device on tree.
*
* @param id device name
*/
void HideDevice(const char* id);
/**
* Wraps CollapsingHeader() to provide both hiding functionality and open
* persistence. As with the ImGui function, returns true if the tree node
* is visible and expanded. If returns true, call EndDevice() to finish
* the block.
*
* @param id label
* @param flags ImGuiTreeNodeFlags flags
* @return True if expanded
*/
bool BeginDevice(const char* id, ImGuiTreeNodeFlags flags = 0);
/**
* Finish a device block started with BeginDevice().
*/
void EndDevice();
/**
* Displays device value.
*
* @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 for drag source (may be nullptr)
* @return True if value was modified by the user
*/
bool DeviceBoolean(const char* name, bool readonly, bool* value,
const DataSource* source = nullptr);
/**
* Displays device value.
*
* @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 for drag source (may be nullptr)
* @return True if value was modified by the user
*/
bool DeviceDouble(const char* name, bool readonly, double* value,
const DataSource* source = nullptr);
/**
* Displays device value.
*
* @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
* @param numOptions size of options array
* @param source data source for drag source (may be nullptr)
* @return True if value was modified by the user
*/
bool DeviceEnum(const char* name, bool readonly, int* value,
const char** options, int32_t numOptions,
const DataSource* source = nullptr);
/**
* Displays device value.
*
* @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 for drag source (may be nullptr)
* @return True if value was modified by the user
*/
bool DeviceInt(const char* name, bool readonly, int32_t* value,
const DataSource* source = nullptr);
/**
* Displays device value.
*
* @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 for drag source (may be nullptr)
* @return True if value was modified by the user
*/
bool DeviceLong(const char* name, bool readonly, int64_t* value,
const DataSource* source = nullptr);
} // namespace glass

View File

@@ -0,0 +1,40 @@
// 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 <functional>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
#include "glass/Model.h"
struct ImVec2;
namespace glass {
class DoubleSource;
class DriveModel : public Model {
public:
struct WheelInfo {
std::string name;
DoubleSource* percent;
std::function<void(double)> setter;
WheelInfo(std::string_view name, DoubleSource* percent,
std::function<void(double)> setter)
: name(name), percent(percent), setter(std::move(setter)) {}
};
virtual const char* GetName() const = 0;
virtual const std::vector<WheelInfo>& GetWheels() const = 0;
virtual ImVec2 GetSpeedVector() const = 0;
// Clamped between -1 and 1 with -1 being full CCW.
virtual double GetRotation() const = 0;
};
void DisplayDrive(DriveModel* m);
} // namespace glass

View File

@@ -0,0 +1,56 @@
// 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 <string_view>
#include "glass/Model.h"
namespace wpi {
template <typename T>
class SmallVectorImpl;
} // namespace wpi
namespace glass {
class BooleanSource;
class DoubleSource;
class IntegerSource;
class StringSource;
class FMSModel : public Model {
public:
virtual BooleanSource* GetFmsAttachedData() = 0;
virtual BooleanSource* GetDsAttachedData() = 0;
virtual IntegerSource* GetAllianceStationIdData() = 0;
virtual DoubleSource* GetMatchTimeData() = 0;
virtual BooleanSource* GetEStopData() = 0;
virtual BooleanSource* GetEnabledData() = 0;
virtual BooleanSource* GetTestData() = 0;
virtual BooleanSource* GetAutonomousData() = 0;
virtual StringSource* GetGameSpecificMessageData() = 0;
virtual void SetFmsAttached(bool val) = 0;
virtual void SetDsAttached(bool val) = 0;
virtual void SetAllianceStationId(int val) = 0;
virtual void SetMatchTime(double val) = 0;
virtual void SetEStop(bool val) = 0;
virtual void SetEnabled(bool val) = 0;
virtual void SetTest(bool val) = 0;
virtual void SetAutonomous(bool val) = 0;
virtual void SetGameSpecificMessage(std::string_view val) = 0;
};
/**
* Displays FMS view.
*
* @param matchTimeEnabled If not null, a checkbox is displayed for
* "enable match time" linked to this value
* @param editableDsAttached If true, DS attached should be editable
*/
void DisplayFMS(FMSModel* model, bool editableDsAttached);
void DisplayFMSReadOnly(FMSModel* model);
} // namespace glass

View File

@@ -0,0 +1,56 @@
// 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 <span>
#include <string_view>
#include <frc/geometry/Pose2d.h>
#include <frc/geometry/Rotation2d.h>
#include <frc/geometry/Translation2d.h>
#include <imgui.h>
#include <wpi/function_ref.h>
#include "glass/Model.h"
#include "glass/View.h"
namespace glass {
class FieldObjectModel : public Model {
public:
virtual const char* GetName() const = 0;
virtual std::span<const frc::Pose2d> GetPoses() = 0;
virtual void SetPoses(std::span<const frc::Pose2d> poses) = 0;
virtual void SetPose(size_t i, frc::Pose2d pose) = 0;
virtual void SetPosition(size_t i, frc::Translation2d pos) = 0;
virtual void SetRotation(size_t i, frc::Rotation2d rot) = 0;
};
class Field2DModel : public Model {
public:
virtual FieldObjectModel* AddFieldObject(std::string_view name) = 0;
virtual void RemoveFieldObject(std::string_view name) = 0;
virtual void ForEachFieldObject(
wpi::function_ref<void(FieldObjectModel& model, std::string_view name)>
func) = 0;
};
void DisplayField2D(Field2DModel* model, const ImVec2& contentSize);
void DisplayField2DSettings(Field2DModel* model);
class Field2DView : public View {
public:
explicit Field2DView(Field2DModel* model) : m_model{model} {}
void Display() override;
void Settings() override;
bool HasSettings() override;
private:
Field2DModel* m_model;
};
} // namespace glass

View File

@@ -0,0 +1,46 @@
// 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 <string>
#include <string_view>
#include <vector>
#include "glass/View.h"
namespace glass {
class LogData {
friend void DisplayLog(LogData*, bool);
public:
explicit LogData(size_t maxLines = 10000);
void Clear();
void Append(std::string_view msg);
const std::string& GetBuffer();
private:
size_t m_maxLines;
std::string m_buf;
std::vector<size_t> m_lineOffsets{0};
};
void DisplayLog(LogData* data, bool autoScroll);
class LogView : public View {
public:
explicit LogView(LogData* data) : m_data{data} {}
void Display() override;
void Settings() override;
bool HasSettings() override;
private:
LogData* m_data;
bool m_autoScroll{true};
};
} // namespace glass

View File

@@ -0,0 +1,65 @@
// 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 <frc/geometry/Rotation2d.h>
#include <frc/geometry/Translation2d.h>
#include <imgui.h>
#include <wpi/function_ref.h>
#include "glass/Model.h"
#include "glass/View.h"
namespace glass {
class MechanismObjectModel;
class MechanismObjectGroup {
public:
virtual const char* GetName() const = 0;
virtual void ForEachObject(
wpi::function_ref<void(MechanismObjectModel& model)> func) = 0;
};
class MechanismObjectModel : public MechanismObjectGroup {
public:
virtual const char* GetType() const = 0;
virtual ImU32 GetColor() const = 0;
// line accessors
virtual double GetWeight() const = 0;
virtual frc::Rotation2d GetAngle() const = 0;
virtual units::meter_t GetLength() const = 0;
};
class MechanismRootModel : public MechanismObjectGroup {
public:
virtual frc::Translation2d GetPosition() const = 0;
};
class Mechanism2DModel : public Model {
public:
virtual frc::Translation2d GetDimensions() const = 0;
virtual ImU32 GetBackgroundColor() const = 0;
virtual void ForEachRoot(
wpi::function_ref<void(MechanismRootModel& model)> func) = 0;
};
void DisplayMechanism2D(Mechanism2DModel* model, const ImVec2& contentSize);
void DisplayMechanism2DSettings(Mechanism2DModel* model);
class Mechanism2DView : public View {
public:
explicit Mechanism2DView(Mechanism2DModel* model) : m_model{model} {}
void Display() override;
void Settings() override;
bool HasSettings() override;
private:
Mechanism2DModel* m_model;
};
} // namespace glass

View File

@@ -0,0 +1,28 @@
// 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 "glass/Model.h"
namespace glass {
class DoubleSource;
class PIDControllerModel : public Model {
public:
virtual const char* GetName() const = 0;
virtual DoubleSource* GetPData() = 0;
virtual DoubleSource* GetIData() = 0;
virtual DoubleSource* GetDData() = 0;
virtual DoubleSource* GetSetpointData() = 0;
virtual DoubleSource* GetIZoneData() = 0;
virtual void SetP(double value) = 0;
virtual void SetI(double value) = 0;
virtual void SetD(double value) = 0;
virtual void SetSetpoint(double value) = 0;
virtual void SetIZone(double value) = 0;
};
void DisplayPIDController(PIDControllerModel* m);
} // namespace glass

View File

@@ -0,0 +1,36 @@
// 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 "glass/WindowManager.h"
namespace glass {
class PlotProvider : private WindowManager {
public:
explicit PlotProvider(Storage& storage);
~PlotProvider() override;
using WindowManager::GlobalInit;
/**
* Pauses or unpauses all plots.
*
* @param paused true to pause, false to unpause
*/
void SetPaused(bool paused) { m_paused = paused; }
/**
* Returns true if all plots are paused.
*/
bool IsPaused() { return m_paused; }
void DisplayMenu() override;
private:
bool m_paused = false;
};
} // namespace glass

View File

@@ -0,0 +1,32 @@
// 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 "glass/Model.h"
namespace glass {
class DoubleSource;
class ProfiledPIDControllerModel : public Model {
public:
virtual const char* GetName() const = 0;
virtual DoubleSource* GetPData() = 0;
virtual DoubleSource* GetIData() = 0;
virtual DoubleSource* GetDData() = 0;
virtual DoubleSource* GetIZoneData() = 0;
virtual DoubleSource* GetMaxVelocityData() = 0;
virtual DoubleSource* GetMaxAccelerationData() = 0;
virtual DoubleSource* GetGoalData() = 0;
virtual void SetP(double value) = 0;
virtual void SetI(double value) = 0;
virtual void SetD(double value) = 0;
virtual void SetIZone(double value) = 0;
virtual void SetMaxVelocity(double value) = 0;
virtual void SetMaxAcceleration(double value) = 0;
virtual void SetGoal(double value) = 0;
};
void DisplayProfiledPIDController(ProfiledPIDControllerModel* m);
} // namespace glass

View File

@@ -0,0 +1,27 @@
// 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 <string>
#include <string_view>
#include <vector>
#include "glass/Model.h"
namespace glass {
class StringChooserModel : public Model {
public:
virtual const std::string& GetDefault() = 0;
virtual const std::string& GetSelected() = 0;
virtual const std::string& GetActive() = 0;
virtual const std::vector<std::string>& GetOptions() = 0;
virtual void SetSelected(std::string_view val) = 0;
};
void DisplayStringChooser(StringChooserModel* model);
} // namespace glass

View File

@@ -0,0 +1,18 @@
// 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 "glass/Model.h"
namespace glass {
class DataSource;
class SubsystemModel : public Model {
public:
virtual const char* GetName() const = 0;
virtual const char* GetDefaultCommand() const = 0;
virtual const char* GetCurrentCommand() const = 0;
};
void DisplaySubsystem(SubsystemModel* m);
} // namespace glass

View File

@@ -0,0 +1,53 @@
// 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 <vector>
#include <imgui.h>
namespace glass {
class ColorSetting {
public:
explicit ColorSetting(std::vector<float>& color);
ImVec4 GetColor() const {
return {m_color[0], m_color[1], m_color[2], m_color[3]};
}
float* GetColorFloat() { return m_color.data(); }
const float* GetColorFloat() const { return m_color.data(); }
void SetColor(const ImVec4& color) {
m_color[0] = color.x;
m_color[1] = color.y;
m_color[2] = color.z;
m_color[3] = color.w;
}
// updates internal value, returns true on change
bool ColorEdit3(const char* label, ImGuiColorEditFlags flags = 0) {
return ImGui::ColorEdit3(label, m_color.data(), flags);
}
bool ColorEdit4(const char* label, ImGuiColorEditFlags flags = 0) {
return ImGui::ColorEdit4(label, m_color.data(), flags);
}
bool ColorPicker3(const char* label, ImGuiColorEditFlags flags = 0) {
return ImGui::ColorPicker3(label, m_color.data(), flags);
}
bool ColorPicker4(const char* label, ImGuiColorEditFlags flags = 0,
const float* ref_col = nullptr) {
return ImGui::ColorPicker4(label, m_color.data(), flags, ref_col);
}
private:
std::vector<float>& m_color;
};
} // namespace glass

View File

@@ -0,0 +1,34 @@
// 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 <string>
#include <wpi/SmallVector.h>
namespace glass {
class EnumSetting {
public:
EnumSetting(std::string& str, int defaultValue,
std::initializer_list<const char*> choices);
int GetValue() const;
void SetValue(int value);
// updates internal value, returns true on change
bool Combo(const char* label, int numOptions = -1,
int popup_max_height_in_items = -1);
private:
void UpdateValue() const;
std::string& m_str;
wpi::SmallVector<const char*, 8> m_choices;
int m_defaultValue;
mutable int m_value = -1;
};
} // namespace glass

View File

@@ -0,0 +1,22 @@
// 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 <stdint.h>
#include <string>
#include <wpi/expected>
namespace glass::expression {
template <typename V>
wpi::expected<V, std::string> TryParseExpr(const char* expr);
extern template wpi::expected<double, std::string> TryParseExpr(const char*);
extern template wpi::expected<float, std::string> TryParseExpr(const char*);
extern template wpi::expected<int64_t, std::string> TryParseExpr(const char*);
} // namespace glass::expression

View File

@@ -0,0 +1,116 @@
// 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 <stdint.h>
#include <imgui.h>
namespace glass {
class BooleanSource;
/**
* 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, BooleanSource** sources, int numValues,
int cols, const ImU32* colors, float size = 0.0f,
float spacing = 0.0f,
const LEDConfig& config = LEDConfig{});
/**
* Delete button (X in circle), based on ImGui::CloseButton().
*/
bool DeleteButton(ImGuiID id, const ImVec2& pos);
/**
* Create a small overlapping delete button for collapsing headers.
*/
bool HeaderDeleteButton(const char* label);
/**
* Settings button similar to ImGui::CloseButton.
*/
bool HamburgerButton(const ImGuiID id, const ImVec2 position);
/**
* Edit a value with expression input. Similar to ImGui::InputScalar()
*/
template <typename V>
bool InputExpr(const char* label, V* v, const char* format,
ImGuiInputTextFlags flags = 0);
extern template bool InputExpr(const char*, int64_t*, const char*,
ImGuiInputTextFlags);
extern template bool InputExpr(const char*, float*, const char*,
ImGuiInputTextFlags);
extern template bool InputExpr(const char*, double*, const char*,
ImGuiInputTextFlags);
} // namespace glass

View File

@@ -0,0 +1,43 @@
// 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 <string>
#include <string_view>
#include <imgui.h>
namespace glass {
class NameSetting {
public:
explicit NameSetting(std::string& str) : m_name{str} {}
bool HasName() const { return !m_name.empty(); }
void SetName(std::string_view name) { m_name = name; }
std::string& GetName() { return m_name; }
const std::string& 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;
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:
std::string& m_name;
};
} // namespace glass