[glass] Split DataSource into type-specific variants (#7588)

This commit is contained in:
Peter Johnson
2025-01-03 13:36:40 -08:00
committed by GitHub
parent 148fcdca85
commit 0f6693594c
62 changed files with 667 additions and 390 deletions

View File

@@ -4,7 +4,11 @@
#include "glass/DataSource.h"
#include <cstdio>
#include <string>
#include <fmt/format.h>
#include <imgui.h>
#include "glass/ContextInternal.h"
@@ -12,17 +16,13 @@ using namespace glass;
wpi::sig::Signal<const char*, DataSource*> DataSource::sourceCreated;
DataSource::DataSource(std::string_view id)
: m_id{id}, m_name{gContext->sourceNameStorage.GetString(m_id)} {
gContext->sources.try_emplace(m_id, this);
sourceCreated(m_id.c_str(), this);
std::string glass::MakeSourceId(std::string_view id, int index) {
return fmt::format("{}[{}]", id, index);
}
DataSource::DataSource(std::string_view id, int index)
: DataSource{fmt::format("{}[{}]", id, index)} {}
DataSource::DataSource(std::string_view id, int index, int index2)
: DataSource{fmt::format("{}[{},{}]", id, index, index2)} {}
std::string glass::MakeSourceId(std::string_view id, int index, int index2) {
return fmt::format("{}[{},{}]", id, index, index2);
}
DataSource::~DataSource() {
if (!gContext) {
@@ -99,10 +99,11 @@ bool DataSource::InputInt(const char* label, int* v, int step, int step_fast,
void DataSource::EmitDrag(ImGuiDragDropFlags flags) const {
if (ImGui::BeginDragDropSource(flags)) {
char buf[32];
std::snprintf(buf, sizeof(buf), "DataSource:%s", GetType());
auto self = this;
ImGui::SetDragDropPayload("DataSource", &self, sizeof(self)); // NOLINT
const char* name = GetName().c_str();
ImGui::TextUnformatted(name[0] == '\0' ? m_id.c_str() : name);
ImGui::SetDragDropPayload(buf, &self, sizeof(self)); // NOLINT
DragDropTooltip();
ImGui::EndDragDropSource();
}
}
@@ -114,3 +115,38 @@ DataSource* DataSource::Find(std::string_view id) {
}
return it->second;
}
std::string& DataSource::GetNameStorage(std::string_view id) {
return gContext->sourceNameStorage.GetString(id);
}
void DataSource::Register() {
gContext->sources.insert_or_assign(m_id, this);
sourceCreated(m_id.c_str(), this);
}
void DataSource::DragDropTooltip() const {
const char* name = GetName().c_str();
ImGui::TextUnformatted(name[0] == '\0' ? m_id.c_str() : name);
ImGui::Text("(%s)", GetType());
}
const char* BooleanSource::GetType() const {
return kType;
}
const char* DoubleSource::GetType() const {
return kType;
}
const char* FloatSource::GetType() const {
return kType;
}
const char* IntegerSource::GetType() const {
return kType;
}
const char* StringSource::GetType() const {
return kType;
}

View File

@@ -75,14 +75,14 @@ void DisplayDIOImpl(DIOModel* model, int index, bool outputsEnabled) {
dioData->LabelText(label, "unknown");
ImGui::PopStyleColor();
} else if (model->IsReadOnly()) {
dioData->LabelText(
label, "%s",
outputsEnabled ? (dioData->GetValue() != 0 ? "1 (high)" : "0 (low)")
: "1 (disabled)");
dioData->LabelText(label, "%s",
outputsEnabled
? (dioData->GetValue() ? "1 (high)" : "0 (low)")
: "1 (disabled)");
} else {
static const char* options[] = {"0 (low)", "1 (high)"};
int val = dioData->GetValue() != 0 ? 1 : 0;
int val = dioData->GetValue() ? 1 : 0;
if (dioData->Combo(label, &val, options, 2)) {
model->SetValue(val);
}

View File

@@ -7,7 +7,6 @@
#include <imgui.h>
#include <imgui_internal.h>
#include "glass/Context.h"
#include "glass/DataSource.h"
using namespace glass;

View File

@@ -58,7 +58,7 @@ void glass::DisplayRelay(RelayModel* model, int index, bool outputsEnabled) {
IM_COL32(128, 128, 128, 255)};
int values[2] = {reverseData ? (reverse ? 2 : -2) : -3,
forwardData ? (forward ? 1 : -1) : -3};
DataSource* sources[2] = {reverseData, forwardData};
BooleanSource* sources[2] = {reverseData, forwardData};
DrawLEDSources(values, sources, 2, 2, colors);
}

View File

@@ -6,7 +6,6 @@
#include <imgui.h>
#include "glass/Context.h"
#include "glass/DataSource.h"
using namespace glass;

View File

@@ -13,7 +13,6 @@
#include <imgui_internal.h>
#include <numbers>
#include "glass/Context.h"
#include "glass/DataSource.h"
using namespace glass;

View File

@@ -80,12 +80,12 @@ void glass::DisplayFMS(FMSModel* model, bool editableDsAttached) {
}
// Game Specific Message
wpi::SmallString<64> gameSpecificMessageBuf;
std::string gameSpecificMessage{
model->GetGameSpecificMessage(gameSpecificMessageBuf)};
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
if (ImGui::InputText("Game Specific", &gameSpecificMessage)) {
model->SetGameSpecificMessage(gameSpecificMessage);
if (auto data = model->GetGameSpecificMessageData()) {
std::string gameSpecificMessage = data->GetValue();
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
if (ImGui::InputText("Game Specific", &gameSpecificMessage)) {
model->SetGameSpecificMessage(gameSpecificMessage);
}
}
}
@@ -148,11 +148,11 @@ void glass::DisplayFMSReadOnly(FMSModel* model) {
ImGui::TextUnformatted("?");
}
}
wpi::SmallString<64> gameSpecificMessageBuf;
std::string_view gameSpecificMessage =
model->GetGameSpecificMessage(gameSpecificMessageBuf);
ImGui::Text("Game Specific: %s", exists ? gameSpecificMessage.data() : "?");
if (auto data = model->GetGameSpecificMessageData()) {
wpi::SmallString<64> gsmBuf;
ImGui::Text("Game Specific: %s",
exists ? data->GetValue(gsmBuf).data() : "?");
}
if (!exists) {
ImGui::PopStyleColor();

View File

@@ -4,11 +4,8 @@
#include "glass/other/PIDController.h"
#include <string>
#include <imgui.h>
#include "glass/Context.h"
#include "glass/DataSource.h"
using namespace glass;

View File

@@ -82,12 +82,13 @@ class PlotSeries {
private:
bool IsDigital() const {
return m_digital.GetValue() == kDigital ||
(m_digital.GetValue() == kAuto && m_source && m_source->IsDigital());
(m_digital.GetValue() == kAuto && m_source && m_digitalSource);
}
void AppendValue(double value, int64_t time);
// source linkage
DataSource* m_source = nullptr;
bool m_digitalSource = false;
wpi::sig::ScopedConnection m_sourceCreatedConn;
wpi::sig::ScopedConnection m_newValueConn;
std::string& m_id;
@@ -255,11 +256,39 @@ void PlotSeries::CheckSource() {
void PlotSeries::SetSource(DataSource* source) {
m_source = source;
// add initial value
AppendValue(source->GetValue(), 0);
if (auto s = dynamic_cast<BooleanSource*>(source)) {
m_digitalSource = true;
m_newValueConn = source->valueChanged.connect_connection(
[this](double value, int64_t time) { AppendValue(value, time); });
// add initial value
AppendValue(s->GetValue(), 0);
m_newValueConn = s->valueChanged.connect_connection(
[this](bool value, int64_t time) { AppendValue(value, time); });
} else if (auto s = dynamic_cast<DoubleSource*>(source)) {
m_digitalSource = false;
// add initial value
AppendValue(s->GetValue(), 0);
m_newValueConn = s->valueChanged.connect_connection(
[this](double value, int64_t time) { AppendValue(value, time); });
} else if (auto s = dynamic_cast<FloatSource*>(source)) {
m_digitalSource = false;
// add initial value
AppendValue(s->GetValue(), 0);
m_newValueConn = s->valueChanged.connect_connection(
[this](double value, int64_t time) { AppendValue(value, time); });
} else if (auto s = dynamic_cast<IntegerSource*>(source)) {
m_digitalSource = false;
// add initial value
AppendValue(s->GetValue(), 0);
m_newValueConn = s->valueChanged.connect_connection(
[this](int64_t value, int64_t time) { AppendValue(value, time); });
}
}
void PlotSeries::AppendValue(double value, int64_t timeUs) {
@@ -522,9 +551,18 @@ Plot::Plot(Storage& storage)
}
void Plot::DragDropAccept(PlotView& view, size_t i, int yAxis) {
if (const ImGuiPayload* payload =
ImGui::AcceptDragDropPayload("DataSource")) {
auto source = *static_cast<DataSource**>(payload->Data);
// accept any of double/float/boolean/integer sources
DataSource* source = AcceptDragDropPayload<DoubleSource>();
if (!source) {
source = AcceptDragDropPayload<FloatSource>();
}
if (!source) {
source = AcceptDragDropPayload<BooleanSource>();
}
if (!source) {
source = AcceptDragDropPayload<IntegerSource>();
}
if (source) {
// don't add duplicates unless it's onto a different Y axis
auto it =
std::find_if(m_series.begin(), m_series.end(), [=](const auto& elem) {

View File

@@ -4,11 +4,8 @@
#include "glass/other/ProfiledPIDController.h"
#include <string>
#include <imgui.h>
#include "glass/Context.h"
#include "glass/DataSource.h"
using namespace glass;

View File

@@ -19,7 +19,7 @@
namespace glass {
void DrawLEDSources(const int* values, DataSource** sources, int numValues,
void DrawLEDSources(const int* values, BooleanSource** sources, int numValues,
int cols, const ImU32* colors, float size, float spacing,
const LEDConfig& config) {
if (numValues == 0 || cols < 1) {

View File

@@ -6,11 +6,15 @@
#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 {
@@ -20,35 +24,21 @@ namespace glass {
*/
class DataSource {
public:
explicit DataSource(std::string_view id);
DataSource(std::string_view id, int index);
DataSource(std::string_view id, int index, int index2);
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; }
void SetDigital(bool digital) { m_digital = digital; }
bool IsDigital() const { return m_digital; }
void SetValue(double value, int64_t time = 0) {
std::scoped_lock lock{m_valueMutex};
m_value = value;
m_valueTime = time;
valueChanged(value, time);
}
double GetValue() const {
std::scoped_lock lock{m_valueMutex};
return m_value;
}
int64_t GetValueTime() const {
std::scoped_lock lock{m_valueMutex};
return m_valueTime;
@@ -69,8 +59,6 @@ class DataSource {
ImGuiInputTextFlags flags = 0) const;
void EmitDrag(ImGuiDragDropFlags flags = 0) const;
wpi::sig::SignalBase<wpi::spinlock, double, int64_t> valueChanged;
static DataSource* Find(std::string_view id);
static wpi::sig::Signal<const char*, DataSource*> sourceCreated;
@@ -78,10 +66,151 @@ class DataSource {
private:
std::string m_id;
std::string& m_name;
bool m_digital = false;
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;
double m_value = 0;
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

@@ -8,13 +8,13 @@
namespace glass {
class DataSource;
class DoubleSource;
class AccelerometerModel : public Model {
public:
virtual DataSource* GetXData() = 0;
virtual DataSource* GetYData() = 0;
virtual DataSource* GetZData() = 0;
virtual DoubleSource* GetXData() = 0;
virtual DoubleSource* GetYData() = 0;
virtual DoubleSource* GetZData() = 0;
virtual int GetRange() = 0;

View File

@@ -10,12 +10,12 @@
namespace glass {
class DataSource;
class DoubleSource;
class AnalogGyroModel : public Model {
public:
virtual DataSource* GetAngleData() = 0;
virtual DataSource* GetRateData() = 0;
virtual DoubleSource* GetAngleData() = 0;
virtual DoubleSource* GetRateData() = 0;
virtual void SetAngle(double val) = 0;
virtual void SetRate(double val) = 0;

View File

@@ -12,14 +12,14 @@
namespace glass {
class DataSource;
class DoubleSource;
class AnalogInputModel : public Model {
public:
virtual bool IsGyro() const = 0;
virtual const char* GetSimDevice() const = 0;
virtual DataSource* GetVoltageData() = 0;
virtual DoubleSource* GetVoltageData() = 0;
virtual void SetVoltage(double val) = 0;
};

View File

@@ -10,11 +10,11 @@
namespace glass {
class DataSource;
class DoubleSource;
class AnalogOutputModel : public Model {
public:
virtual DataSource* GetVoltageData() = 0;
virtual DoubleSource* GetVoltageData() = 0;
virtual void SetVoltage(double val) = 0;
};

View File

@@ -13,13 +13,14 @@
namespace glass {
class EncoderModel;
class DataSource;
class BooleanSource;
class DoubleSource;
class DPWMModel : public Model {
public:
virtual const char* GetSimDevice() const = 0;
virtual DataSource* GetValueData() = 0;
virtual DoubleSource* GetValueData() = 0;
virtual void SetValue(double val) = 0;
};
@@ -28,7 +29,7 @@ class DutyCycleModel : public Model {
public:
virtual const char* GetSimDevice() const = 0;
virtual DataSource* GetValueData() = 0;
virtual DoubleSource* GetValueData() = 0;
virtual void SetValue(double val) = 0;
};
@@ -45,7 +46,7 @@ class DIOModel : public Model {
virtual bool IsInput() const = 0;
virtual DataSource* GetValueData() = 0;
virtual BooleanSource* GetValueData() = 0;
virtual void SetValue(bool val) = 0;
};

View File

@@ -12,7 +12,9 @@
namespace glass {
class DataSource;
class BooleanSource;
class DoubleSource;
class IntegerSource;
class EncoderModel : public Model {
public:
@@ -23,12 +25,12 @@ class EncoderModel : public Model {
virtual int GetChannelA() const = 0;
virtual int GetChannelB() const = 0;
virtual DataSource* GetDistancePerPulseData() = 0;
virtual DataSource* GetCountData() = 0;
virtual DataSource* GetPeriodData() = 0;
virtual DataSource* GetDirectionData() = 0;
virtual DataSource* GetDistanceData() = 0;
virtual DataSource* GetRateData() = 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;

View File

@@ -7,13 +7,13 @@
#include "glass/Model.h"
namespace glass {
class DataSource;
class DoubleSource;
class GyroModel : public Model {
public:
virtual const char* GetName() const = 0;
virtual const char* GetSimDevice() const = 0;
virtual DataSource* GetAngleData() = 0;
virtual DoubleSource* GetAngleData() = 0;
virtual void SetAngle(double angle) = 0;
};
void DisplayGyro(GyroModel* m);

View File

@@ -7,12 +7,12 @@
#include "glass/Model.h"
namespace glass {
class DataSource;
class DoubleSource;
class MotorControllerModel : public Model {
public:
virtual const char* GetName() const = 0;
virtual const char* GetSimDevice() const = 0;
virtual DataSource* GetPercentData() = 0;
virtual DoubleSource* GetPercentData() = 0;
virtual void SetPercent(double value) = 0;
};
void DisplayMotorController(MotorControllerModel* m);

View File

@@ -12,14 +12,14 @@
namespace glass {
class DataSource;
class DoubleSource;
class PWMModel : public Model {
public:
// returns -1 if not an addressable LED
virtual int GetAddressableLED() const = 0;
virtual DataSource* GetSpeedData() = 0;
virtual DoubleSource* GetSpeedData() = 0;
virtual void SetSpeed(double val) = 0;
};

View File

@@ -14,14 +14,15 @@
namespace glass {
class DataSource;
class BooleanSource;
class DoubleSource;
class CompressorModel : public Model {
public:
virtual DataSource* GetRunningData() = 0;
virtual DataSource* GetEnabledData() = 0;
virtual DataSource* GetPressureSwitchData() = 0;
virtual DataSource* GetCurrentData() = 0;
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;
@@ -31,7 +32,7 @@ class CompressorModel : public Model {
class SolenoidModel : public Model {
public:
virtual DataSource* GetOutputData() = 0;
virtual BooleanSource* GetOutputData() = 0;
virtual void SetOutput(bool val) = 0;
};

View File

@@ -12,15 +12,15 @@
namespace glass {
class DataSource;
class DoubleSource;
class PowerDistributionModel : public Model {
public:
virtual int GetNumChannels() const = 0;
virtual DataSource* GetTemperatureData() = 0;
virtual DataSource* GetVoltageData() = 0;
virtual DataSource* GetCurrentData(int channel) = 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;

View File

@@ -12,12 +12,12 @@
namespace glass {
class DataSource;
class BooleanSource;
class RelayModel : public Model {
public:
virtual DataSource* GetForwardData() = 0;
virtual DataSource* GetReverseData() = 0;
virtual BooleanSource* GetForwardData() = 0;
virtual BooleanSource* GetReverseData() = 0;
virtual void SetForward(bool val) = 0;
virtual void SetReverse(bool val) = 0;

View File

@@ -8,14 +8,16 @@
namespace glass {
class DataSource;
class BooleanSource;
class DoubleSource;
class IntegerSource;
class RoboRioRailModel : public Model {
public:
virtual DataSource* GetVoltageData() = 0;
virtual DataSource* GetCurrentData() = 0;
virtual DataSource* GetActiveData() = 0;
virtual DataSource* GetFaultsData() = 0;
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;
@@ -29,10 +31,10 @@ class RoboRioModel : public Model {
virtual RoboRioRailModel* GetUser5VRail() = 0;
virtual RoboRioRailModel* GetUser3V3Rail() = 0;
virtual DataSource* GetUserButton() = 0;
virtual DataSource* GetVInVoltageData() = 0;
virtual DataSource* GetVInCurrentData() = 0;
virtual DataSource* GetBrownoutVoltage() = 0;
virtual BooleanSource* GetUserButton() = 0;
virtual DoubleSource* GetVInVoltageData() = 0;
virtual DoubleSource* GetVInCurrentData() = 0;
virtual DoubleSource* GetBrownoutVoltage() = 0;
virtual void SetUserButton(bool val) = 0;
virtual void SetVInVoltage(double val) = 0;

View File

@@ -7,11 +7,11 @@
#include "glass/Model.h"
namespace glass {
class DataSource;
class BooleanSource;
class CommandSelectorModel : public Model {
public:
virtual const char* GetName() const = 0;
virtual DataSource* GetRunningData() = 0;
virtual BooleanSource* GetRunningData() = 0;
virtual void SetRunning(bool run) = 0;
};
void DisplayCommandSelector(CommandSelectorModel* m);

View File

@@ -15,15 +15,15 @@
struct ImVec2;
namespace glass {
class DataSource;
class DoubleSource;
class DriveModel : public Model {
public:
struct WheelInfo {
std::string name;
DataSource* percent;
DoubleSource* percent;
std::function<void(double)> setter;
WheelInfo(std::string_view name, DataSource* percent,
WheelInfo(std::string_view name, DoubleSource* percent,
std::function<void(double)> setter)
: name(name), percent(percent), setter(std::move(setter)) {}
};

View File

@@ -15,20 +15,22 @@ class SmallVectorImpl;
namespace glass {
class DataSource;
class BooleanSource;
class DoubleSource;
class IntegerSource;
class StringSource;
class FMSModel : public Model {
public:
virtual DataSource* GetFmsAttachedData() = 0;
virtual DataSource* GetDsAttachedData() = 0;
virtual DataSource* GetAllianceStationIdData() = 0;
virtual DataSource* GetMatchTimeData() = 0;
virtual DataSource* GetEStopData() = 0;
virtual DataSource* GetEnabledData() = 0;
virtual DataSource* GetTestData() = 0;
virtual DataSource* GetAutonomousData() = 0;
virtual std::string_view GetGameSpecificMessage(
wpi::SmallVectorImpl<char>& buf) = 0;
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;

View File

@@ -7,16 +7,16 @@
#include "glass/Model.h"
namespace glass {
class DataSource;
class DoubleSource;
class PIDControllerModel : public Model {
public:
virtual const char* GetName() const = 0;
virtual DataSource* GetPData() = 0;
virtual DataSource* GetIData() = 0;
virtual DataSource* GetDData() = 0;
virtual DataSource* GetSetpointData() = 0;
virtual DataSource* GetIZoneData() = 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;

View File

@@ -7,18 +7,18 @@
#include "glass/Model.h"
namespace glass {
class DataSource;
class DoubleSource;
class ProfiledPIDControllerModel : public Model {
public:
virtual const char* GetName() const = 0;
virtual DataSource* GetPData() = 0;
virtual DataSource* GetIData() = 0;
virtual DataSource* GetDData() = 0;
virtual DataSource* GetIZoneData() = 0;
virtual DataSource* GetMaxVelocityData() = 0;
virtual DataSource* GetMaxAccelerationData() = 0;
virtual DataSource* GetGoalData() = 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;

View File

@@ -11,7 +11,7 @@
namespace glass {
class DataSource;
class BooleanSource;
/**
* DrawLEDs() configuration for 2D arrays.
@@ -81,7 +81,7 @@ void DrawLEDs(const int* values, int numValues, int cols, const ImU32* colors,
* if 0, defaults to 1/3 of font size
* @param config 2D array configuration
*/
void DrawLEDSources(const int* values, DataSource** sources, int numValues,
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{});

View File

@@ -21,9 +21,7 @@ NTCommandSelectorModel::NTCommandSelectorModel(nt::NetworkTableInstance inst,
.GetEntry(false)},
m_name{inst.GetStringTopic(fmt::format("{}/.name", path)).Subscribe("")},
m_runningData{fmt::format("NTCmd:{}", path)},
m_nameValue{wpi::rsplit(path, '/').second} {
m_runningData.SetDigital(true);
}
m_nameValue{wpi::rsplit(path, '/').second} {}
void NTCommandSelectorModel::SetRunning(bool run) {
m_running.Set(run);

View File

@@ -21,9 +21,7 @@ NTDigitalInputModel::NTDigitalInputModel(nt::NetworkTableInstance inst,
inst.GetBooleanTopic(fmt::format("{}/Value", path)).Subscribe(false)},
m_name{inst.GetStringTopic(fmt::format("{}/.name", path)).Subscribe("")},
m_valueData{fmt::format("NT_DIn:{}", path)},
m_nameValue{wpi::rsplit(path, '/').second} {
m_valueData.SetDigital(true);
}
m_nameValue{wpi::rsplit(path, '/').second} {}
void NTDigitalInputModel::Update() {
for (auto&& v : m_value.ReadQueue()) {

View File

@@ -21,9 +21,7 @@ NTDigitalOutputModel::NTDigitalOutputModel(nt::NetworkTableInstance inst,
m_name{inst.GetStringTopic(fmt::format("{}/.name", path)).Subscribe("")},
m_controllable{inst.GetBooleanTopic(fmt::format("{}/.controllable", path))
.Subscribe(false)},
m_valueData{fmt::format("NT_DOut:{}", path)} {
m_valueData.SetDigital(true);
}
m_valueData{fmt::format("NT_DOut:{}", path)} {}
void NTDigitalOutputModel::SetValue(bool val) {
m_value.Set(val);

View File

@@ -6,6 +6,8 @@
#include <stdint.h>
#include <utility>
#include <fmt/format.h>
#include <wpi/SmallVector.h>
#include <wpi/timestamp.h>
@@ -32,19 +34,9 @@ NTFMSModel::NTFMSModel(nt::NetworkTableInstance inst, std::string_view path)
m_estop{fmt::format("NT_FMS:EStop:{}", path)},
m_enabled{fmt::format("NT_FMS:RobotEnabled:{}", path)},
m_test{fmt::format("NT_FMS:TestMode:{}", path)},
m_autonomous{fmt::format("NT_FMS:AutonomousMode:{}", path)} {
m_fmsAttached.SetDigital(true);
m_dsAttached.SetDigital(true);
m_estop.SetDigital(true);
m_enabled.SetDigital(true);
m_test.SetDigital(true);
m_autonomous.SetDigital(true);
}
std::string_view NTFMSModel::GetGameSpecificMessage(
wpi::SmallVectorImpl<char>& buf) {
return m_gameSpecificMessage.Get(buf, "");
}
m_autonomous{fmt::format("NT_FMS:AutonomousMode:{}", path)},
m_gameSpecificMessageData{
fmt::format("NT_FMS:GameSpecificMessage:{}", path)} {}
void NTFMSModel::Update() {
for (auto&& v : m_alliance.ReadQueue()) {
@@ -70,6 +62,9 @@ void NTFMSModel::Update() {
m_fmsAttached.SetValue(((controlWord & 0x10) != 0) ? 1 : 0, v.time);
m_dsAttached.SetValue(((controlWord & 0x20) != 0) ? 1 : 0, v.time);
}
for (auto&& v : m_gameSpecificMessage.ReadQueue()) {
m_gameSpecificMessageData.SetValue(std::move(v.value), v.time);
}
}
bool NTFMSModel::Exists() {

View File

@@ -6,7 +6,6 @@
#include <algorithm>
#include <cinttypes>
#include <concepts>
#include <cstring>
#include <functional>
#include <initializer_list>
@@ -632,19 +631,53 @@ static void UpdateJsonValueSource(NetworkTablesModel& model,
}
void NetworkTablesModel::ValueSource::UpdateDiscreteSource(
std::string_view name, double value, int64_t time, bool digital) {
std::string_view name, bool value, int64_t time) {
valueChildren.clear();
if (!source) {
source = std::make_unique<DataSource>(fmt::format("NT:{}", name));
auto s = dynamic_cast<BooleanSource*>(source.get());
if (!s) {
source = std::make_unique<BooleanSource>(fmt::format("NT:{}", name));
s = static_cast<BooleanSource*>(source.get());
}
source->SetValue(value, time);
source->SetDigital(digital);
s->SetValue(value, time);
}
template <typename T, typename MakeValue>
void NetworkTablesModel::ValueSource::UpdateDiscreteSource(
std::string_view name, float value, int64_t time) {
valueChildren.clear();
auto s = dynamic_cast<FloatSource*>(source.get());
if (!s) {
source = std::make_unique<FloatSource>(fmt::format("NT:{}", name));
s = static_cast<FloatSource*>(source.get());
}
s->SetValue(value, time);
}
void NetworkTablesModel::ValueSource::UpdateDiscreteSource(
std::string_view name, double value, int64_t time) {
valueChildren.clear();
auto s = dynamic_cast<DoubleSource*>(source.get());
if (!s) {
source = std::make_unique<DoubleSource>(fmt::format("NT:{}", name));
s = static_cast<DoubleSource*>(source.get());
}
s->SetValue(value, time);
}
void NetworkTablesModel::ValueSource::UpdateDiscreteSource(
std::string_view name, int64_t value, int64_t time) {
valueChildren.clear();
auto s = dynamic_cast<IntegerSource*>(source.get());
if (!s) {
source = std::make_unique<IntegerSource>(fmt::format("NT:{}", name));
s = static_cast<IntegerSource*>(source.get());
}
s->SetValue(value, time);
}
template <bool IsBoolean, typename T, typename MakeValue>
void NetworkTablesModel::ValueSource::UpdateDiscreteArray(
std::string_view name, std::span<const T> arr, int64_t time,
MakeValue makeValue, bool digital) {
MakeValue makeValue) {
if (valueChildrenMap) {
valueChildren.clear();
valueChildrenMap = false;
@@ -657,7 +690,11 @@ void NetworkTablesModel::ValueSource::UpdateDiscreteArray(
child.path = fmt::format("{}{}", name, child.name);
}
child.value = makeValue(arr[i], time);
child.UpdateDiscreteSource(child.path, arr[i], time, digital);
if constexpr (IsBoolean) {
child.UpdateDiscreteSource(child.path, static_cast<bool>(arr[i]), time);
} else {
child.UpdateDiscreteSource(child.path, arr[i], time);
}
++i;
}
}
@@ -667,8 +704,7 @@ void NetworkTablesModel::ValueSource::UpdateFromValue(
std::string_view typeStr) {
switch (value.type()) {
case NT_BOOLEAN:
UpdateDiscreteSource(name, value.GetBoolean() ? 1 : 0, value.time(),
true);
UpdateDiscreteSource(name, value.GetBoolean(), value.time());
break;
case NT_INTEGER:
UpdateDiscreteSource(name, value.GetInteger(), value.time());
@@ -680,20 +716,20 @@ void NetworkTablesModel::ValueSource::UpdateFromValue(
UpdateDiscreteSource(name, value.GetDouble(), value.time());
break;
case NT_BOOLEAN_ARRAY:
UpdateDiscreteArray(name, value.GetBooleanArray(), value.time(),
nt::Value::MakeBoolean, true);
UpdateDiscreteArray<true>(name, value.GetBooleanArray(), value.time(),
nt::Value::MakeBoolean);
break;
case NT_INTEGER_ARRAY:
UpdateDiscreteArray(name, value.GetIntegerArray(), value.time(),
nt::Value::MakeInteger);
UpdateDiscreteArray<false>(name, value.GetIntegerArray(), value.time(),
nt::Value::MakeInteger);
break;
case NT_FLOAT_ARRAY:
UpdateDiscreteArray(name, value.GetFloatArray(), value.time(),
nt::Value::MakeFloat);
UpdateDiscreteArray<false>(name, value.GetFloatArray(), value.time(),
nt::Value::MakeFloat);
break;
case NT_DOUBLE_ARRAY:
UpdateDiscreteArray(name, value.GetDoubleArray(), value.time(),
nt::Value::MakeDouble);
UpdateDiscreteArray<false>(name, value.GetDoubleArray(), value.time(),
nt::Value::MakeDouble);
break;
case NT_STRING_ARRAY: {
auto arr = value.GetStringArray();
@@ -729,6 +765,13 @@ void NetworkTablesModel::ValueSource::UpdateFromValue(
os << '"';
os.write_escaped(value.GetString());
os << '"';
auto s = dynamic_cast<StringSource*>(source.get());
if (!s) {
source = std::make_unique<StringSource>(fmt::format("NT:{}", name));
s = static_cast<StringSource*>(source.get());
}
s->SetValue(value.GetString(), value.time());
}
break;
case NT_RAW:

View File

@@ -23,7 +23,7 @@ class NTCommandSelectorModel : public CommandSelectorModel {
NTCommandSelectorModel(nt::NetworkTableInstance inst, std::string_view path);
const char* GetName() const override { return m_nameValue.c_str(); }
DataSource* GetRunningData() override { return &m_runningData; }
BooleanSource* GetRunningData() override { return &m_runningData; }
void SetRunning(bool run) override;
void Update() override;
@@ -35,7 +35,7 @@ class NTCommandSelectorModel : public CommandSelectorModel {
nt::BooleanEntry m_running;
nt::StringSubscriber m_name;
DataSource m_runningData;
BooleanSource m_runningData;
std::string m_nameValue;
};
} // namespace glass

View File

@@ -46,8 +46,8 @@ class NTDifferentialDriveModel : public DriveModel {
std::string m_nameValue;
bool m_controllableValue = false;
DataSource m_lPercentData;
DataSource m_rPercentData;
DoubleSource m_lPercentData;
DoubleSource m_rPercentData;
std::vector<DriveModel::WheelInfo> m_wheels;
ImVec2 m_speedVector;

View File

@@ -34,7 +34,7 @@ class NTDigitalInputModel : public DIOModel {
bool IsInput() const override { return true; }
DataSource* GetValueData() override { return &m_valueData; }
BooleanSource* GetValueData() override { return &m_valueData; }
void SetValue(bool val) override {}
@@ -47,7 +47,7 @@ class NTDigitalInputModel : public DIOModel {
nt::BooleanSubscriber m_value;
nt::StringSubscriber m_name;
DataSource m_valueData;
BooleanSource m_valueData;
std::string m_nameValue;
};

View File

@@ -34,7 +34,7 @@ class NTDigitalOutputModel : public DIOModel {
bool IsInput() const override { return true; }
DataSource* GetValueData() override { return &m_valueData; }
BooleanSource* GetValueData() override { return &m_valueData; }
void SetValue(bool val) override;
@@ -48,7 +48,7 @@ class NTDigitalOutputModel : public DIOModel {
nt::StringSubscriber m_name;
nt::BooleanSubscriber m_controllable;
DataSource m_valueData;
BooleanSource m_valueData;
std::string m_nameValue;
bool m_controllableValue = false;
};

View File

@@ -24,19 +24,20 @@ class NTFMSModel : public FMSModel {
explicit NTFMSModel(std::string_view path);
NTFMSModel(nt::NetworkTableInstance inst, std::string_view path);
DataSource* GetFmsAttachedData() override { return &m_fmsAttached; }
DataSource* GetDsAttachedData() override { return &m_dsAttached; }
DataSource* GetAllianceStationIdData() override {
BooleanSource* GetFmsAttachedData() override { return &m_fmsAttached; }
BooleanSource* GetDsAttachedData() override { return &m_dsAttached; }
IntegerSource* GetAllianceStationIdData() override {
return &m_allianceStationId;
}
// NT does not provide match time
DataSource* GetMatchTimeData() override { return nullptr; }
DataSource* GetEStopData() override { return &m_estop; }
DataSource* GetEnabledData() override { return &m_enabled; }
DataSource* GetTestData() override { return &m_test; }
DataSource* GetAutonomousData() override { return &m_autonomous; }
std::string_view GetGameSpecificMessage(
wpi::SmallVectorImpl<char>& buf) override;
DoubleSource* GetMatchTimeData() override { return nullptr; }
BooleanSource* GetEStopData() override { return &m_estop; }
BooleanSource* GetEnabledData() override { return &m_enabled; }
BooleanSource* GetTestData() override { return &m_test; }
BooleanSource* GetAutonomousData() override { return &m_autonomous; }
StringSource* GetGameSpecificMessageData() override {
return &m_gameSpecificMessageData;
}
// NT is read-only (it's continually set by robot code)
void SetFmsAttached(bool val) override {}
@@ -60,13 +61,14 @@ class NTFMSModel : public FMSModel {
nt::IntegerSubscriber m_station;
nt::IntegerSubscriber m_controlWord;
DataSource m_fmsAttached;
DataSource m_dsAttached;
DataSource m_allianceStationId;
DataSource m_estop;
DataSource m_enabled;
DataSource m_test;
DataSource m_autonomous;
BooleanSource m_fmsAttached;
BooleanSource m_dsAttached;
IntegerSource m_allianceStationId;
BooleanSource m_estop;
BooleanSource m_enabled;
BooleanSource m_test;
BooleanSource m_autonomous;
StringSource m_gameSpecificMessageData;
};
} // namespace glass

View File

@@ -25,7 +25,7 @@ class NTGyroModel : public GyroModel {
const char* GetName() const override { return m_nameValue.c_str(); }
const char* GetSimDevice() const override { return nullptr; }
DataSource* GetAngleData() override { return &m_angleData; }
DoubleSource* GetAngleData() override { return &m_angleData; }
void SetAngle(double value) override {}
void Update() override;
@@ -37,7 +37,7 @@ class NTGyroModel : public GyroModel {
nt::DoubleSubscriber m_angle;
nt::StringSubscriber m_name;
DataSource m_angleData;
DoubleSource m_angleData;
std::string m_nameValue;
};
} // namespace glass

View File

@@ -47,10 +47,10 @@ class NTMecanumDriveModel : public DriveModel {
std::string m_nameValue;
bool m_controllableValue = false;
DataSource m_flPercentData;
DataSource m_frPercentData;
DataSource m_rlPercentData;
DataSource m_rrPercentData;
DoubleSource m_flPercentData;
DoubleSource m_frPercentData;
DoubleSource m_rlPercentData;
DoubleSource m_rrPercentData;
std::vector<DriveModel::WheelInfo> m_wheels;
ImVec2 m_speedVector;

View File

@@ -26,7 +26,7 @@ class NTMotorControllerModel : public MotorControllerModel {
const char* GetName() const override { return m_nameValue.c_str(); }
const char* GetSimDevice() const override { return nullptr; }
DataSource* GetPercentData() override { return &m_valueData; }
DoubleSource* GetPercentData() override { return &m_valueData; }
void SetPercent(double value) override;
void Update() override;
@@ -39,7 +39,7 @@ class NTMotorControllerModel : public MotorControllerModel {
nt::StringSubscriber m_name;
nt::BooleanSubscriber m_controllable;
DataSource m_valueData;
DoubleSource m_valueData;
std::string m_nameValue;
bool m_controllableValue = false;
};

View File

@@ -25,11 +25,11 @@ class NTPIDControllerModel : public PIDControllerModel {
const char* GetName() const override { return m_nameValue.c_str(); }
DataSource* GetPData() override { return &m_pData; }
DataSource* GetIData() override { return &m_iData; }
DataSource* GetDData() override { return &m_dData; }
DataSource* GetSetpointData() override { return &m_setpointData; }
DataSource* GetIZoneData() override { return &m_iZoneData; }
DoubleSource* GetPData() override { return &m_pData; }
DoubleSource* GetIData() override { return &m_iData; }
DoubleSource* GetDData() override { return &m_dData; }
DoubleSource* GetSetpointData() override { return &m_setpointData; }
DoubleSource* GetIZoneData() override { return &m_iZoneData; }
void SetP(double value) override;
void SetI(double value) override;
@@ -51,11 +51,11 @@ class NTPIDControllerModel : public PIDControllerModel {
nt::DoubleEntry m_setpoint;
nt::DoubleEntry m_iZone;
DataSource m_pData;
DataSource m_iData;
DataSource m_dData;
DataSource m_setpointData;
DataSource m_iZoneData;
DoubleSource m_pData;
DoubleSource m_iData;
DoubleSource m_dData;
DoubleSource m_setpointData;
DoubleSource m_iZoneData;
std::string m_nameValue;
bool m_controllableValue = false;

View File

@@ -26,15 +26,15 @@ class NTProfiledPIDControllerModel : public ProfiledPIDControllerModel {
const char* GetName() const override { return m_nameValue.c_str(); }
DataSource* GetPData() override { return &m_pData; }
DataSource* GetIData() override { return &m_iData; }
DataSource* GetDData() override { return &m_dData; }
DataSource* GetIZoneData() override { return &m_iZoneData; }
DataSource* GetMaxVelocityData() override { return &m_maxVelocityData; }
DataSource* GetMaxAccelerationData() override {
DoubleSource* GetPData() override { return &m_pData; }
DoubleSource* GetIData() override { return &m_iData; }
DoubleSource* GetDData() override { return &m_dData; }
DoubleSource* GetIZoneData() override { return &m_iZoneData; }
DoubleSource* GetMaxVelocityData() override { return &m_maxVelocityData; }
DoubleSource* GetMaxAccelerationData() override {
return &m_maxAccelerationData;
}
DataSource* GetGoalData() override { return &m_goalData; }
DoubleSource* GetGoalData() override { return &m_goalData; }
void SetP(double value) override;
void SetI(double value) override;
@@ -60,13 +60,13 @@ class NTProfiledPIDControllerModel : public ProfiledPIDControllerModel {
nt::DoubleEntry m_maxAcceleration;
nt::DoubleEntry m_goal;
DataSource m_pData;
DataSource m_iData;
DataSource m_dData;
DataSource m_iZoneData;
DataSource m_maxVelocityData;
DataSource m_maxAccelerationData;
DataSource m_goalData;
DoubleSource m_pData;
DoubleSource m_iData;
DoubleSource m_dData;
DoubleSource m_iZoneData;
DoubleSource m_maxVelocityData;
DoubleSource m_maxAccelerationData;
DoubleSource m_goalData;
std::string m_nameValue;
bool m_controllableValue = false;

View File

@@ -58,13 +58,16 @@ class NetworkTablesModel : public Model {
bool valueChildrenMap = false;
private:
void UpdateDiscreteSource(std::string_view name, double value, int64_t time,
bool digital = false);
void UpdateDiscreteSource(std::string_view name, bool value, int64_t time);
void UpdateDiscreteSource(std::string_view name, float value, int64_t time);
void UpdateDiscreteSource(std::string_view name, double value,
int64_t time);
void UpdateDiscreteSource(std::string_view name, int64_t value,
int64_t time);
template <typename T, typename MakeValue>
template <bool IsBoolean, typename T, typename MakeValue>
void UpdateDiscreteArray(std::string_view name, std::span<const T> arr,
int64_t time, MakeValue makeValue,
bool digital = false);
int64_t time, MakeValue makeValue);
};
struct EntryValueTreeNode : public ValueSource {

View File

@@ -32,9 +32,9 @@ class AccelerometerSimModel : public glass::AccelerometerModel {
bool Exists() override { return HALSIM_GetAccelerometerActive(m_index); }
glass::DataSource* GetXData() override { return &m_xData; }
glass::DataSource* GetYData() override { return &m_yData; }
glass::DataSource* GetZData() override { return &m_zData; }
glass::DoubleSource* GetXData() override { return &m_xData; }
glass::DoubleSource* GetYData() override { return &m_yData; }
glass::DoubleSource* GetZData() override { return &m_zData; }
int GetRange() override { return HALSIM_GetAccelerometerRange(m_index); }

View File

@@ -32,8 +32,8 @@ class AnalogGyroSimModel : public glass::AnalogGyroModel {
bool Exists() override { return HALSIM_GetAnalogGyroInitialized(m_index); }
glass::DataSource* GetAngleData() override { return &m_angle; }
glass::DataSource* GetRateData() override { return &m_rate; }
glass::DoubleSource* GetAngleData() override { return &m_angle; }
glass::DoubleSource* GetRateData() override { return &m_rate; }
void SetAngle(double val) override {
HALSIM_SetAnalogGyroAngle(m_index, val);

View File

@@ -44,7 +44,7 @@ class AnalogInputSimModel : public glass::AnalogInputModel {
}
}
glass::DataSource* GetVoltageData() override { return &m_voltageData; }
glass::DoubleSource* GetVoltageData() override { return &m_voltageData; }
void SetVoltage(double val) override {
HALSIM_SetAnalogInVoltage(m_index, val);

View File

@@ -30,7 +30,7 @@ class AnalogOutputSimModel : public glass::AnalogOutputModel {
bool Exists() override { return HALSIM_GetAnalogOutInitialized(m_index); }
glass::DataSource* GetVoltageData() override { return &m_voltageData; }
glass::DoubleSource* GetVoltageData() override { return &m_voltageData; }
void SetVoltage(double val) override {
HALSIM_SetAnalogOutVoltage(m_index, val);

View File

@@ -44,7 +44,7 @@ class DPWMSimModel : public glass::DPWMModel {
}
}
glass::DataSource* GetValueData() override { return &m_valueData; }
glass::DoubleSource* GetValueData() override { return &m_valueData; }
void SetValue(double val) override {
HALSIM_SetDigitalPWMDutyCycle(m_index, val);
@@ -73,7 +73,7 @@ class DutyCycleSimModel : public glass::DutyCycleModel {
}
}
glass::DataSource* GetValueData() override { return &m_valueData; }
glass::DoubleSource* GetValueData() override { return &m_valueData; }
void SetValue(double val) override {
HALSIM_SetDutyCycleOutput(m_index, val);
@@ -115,7 +115,7 @@ class DIOSimModel : public glass::DIOModel {
bool IsInput() const override { return HALSIM_GetDIOIsInput(m_channel); }
glass::DataSource* GetValueData() override { return &m_valueData; }
glass::BooleanSource* GetValueData() override { return &m_valueData; }
void SetValue(bool val) override { HALSIM_SetDIOValue(m_channel, val); }

View File

@@ -197,11 +197,11 @@ class JoystickModel {
int axisCount;
int buttonCount;
int povCount;
std::unique_ptr<glass::DataSource> axes[HAL_kMaxJoystickAxes];
std::unique_ptr<glass::DoubleSource> axes[HAL_kMaxJoystickAxes];
// use pointer instead of unique_ptr to allow it to be passed directly
// to DrawLEDSources()
glass::DataSource* buttons[32];
std::unique_ptr<glass::DataSource> povs[HAL_kMaxJoystickPOVs];
glass::BooleanSource* buttons[32];
std::unique_ptr<glass::IntegerSource> povs[HAL_kMaxJoystickPOVs];
private:
static void CallbackFunc(const char*, void* param, const HAL_Value*);
@@ -214,19 +214,18 @@ class FMSSimModel : public glass::FMSModel {
public:
FMSSimModel();
glass::DataSource* GetFmsAttachedData() override { return &m_fmsAttached; }
glass::DataSource* GetDsAttachedData() override { return &m_dsAttached; }
glass::DataSource* GetAllianceStationIdData() override {
glass::BooleanSource* GetFmsAttachedData() override { return &m_fmsAttached; }
glass::BooleanSource* GetDsAttachedData() override { return &m_dsAttached; }
glass::IntegerSource* GetAllianceStationIdData() override {
return &m_allianceStationId;
}
glass::DataSource* GetMatchTimeData() override { return &m_matchTime; }
glass::DataSource* GetEStopData() override { return &m_estop; }
glass::DataSource* GetEnabledData() override { return &m_enabled; }
glass::DataSource* GetTestData() override { return &m_test; }
glass::DataSource* GetAutonomousData() override { return &m_autonomous; }
std::string_view GetGameSpecificMessage(
wpi::SmallVectorImpl<char>& buf) override {
return m_gameMessage;
glass::DoubleSource* GetMatchTimeData() override { return &m_matchTime; }
glass::BooleanSource* GetEStopData() override { return &m_estop; }
glass::BooleanSource* GetEnabledData() override { return &m_enabled; }
glass::BooleanSource* GetTestData() override { return &m_test; }
glass::BooleanSource* GetAutonomousData() override { return &m_autonomous; }
glass::StringSource* GetGameSpecificMessageData() override {
return &m_gameMessage;
}
void SetFmsAttached(bool val) override { m_fmsAttached.SetValue(val); }
@@ -240,7 +239,7 @@ class FMSSimModel : public glass::FMSModel {
void SetTest(bool val) override { m_test.SetValue(val); }
void SetAutonomous(bool val) override { m_autonomous.SetValue(val); }
void SetGameSpecificMessage(std::string_view val) override {
m_gameMessage = val;
m_gameMessage.SetValue(val);
}
void UpdateHAL();
@@ -252,16 +251,16 @@ class FMSSimModel : public glass::FMSModel {
bool IsReadOnly() override;
private:
glass::DataSource m_fmsAttached{"FMS:FMSAttached"};
glass::DataSource m_dsAttached{"FMS:DSAttached"};
glass::DataSource m_allianceStationId{"FMS:AllianceStationID"};
glass::DataSource m_matchTime{"FMS:MatchTime"};
glass::DataSource m_estop{"FMS:EStop"};
glass::DataSource m_enabled{"FMS:RobotEnabled"};
glass::DataSource m_test{"FMS:TestMode"};
glass::DataSource m_autonomous{"FMS:AutonomousMode"};
glass::BooleanSource m_fmsAttached{"FMS:FMSAttached"};
glass::BooleanSource m_dsAttached{"FMS:DSAttached"};
glass::IntegerSource m_allianceStationId{"FMS:AllianceStationID"};
glass::DoubleSource m_matchTime{"FMS:MatchTime"};
glass::BooleanSource m_estop{"FMS:EStop"};
glass::BooleanSource m_enabled{"FMS:RobotEnabled"};
glass::BooleanSource m_test{"FMS:TestMode"};
glass::BooleanSource m_autonomous{"FMS:AutonomousMode"};
double m_startMatchTime = -1.0;
std::string m_gameMessage;
glass::StringSource m_gameMessage{"FMS:GameSpecificMessage"};
};
} // namespace
@@ -297,7 +296,7 @@ JoystickModel::JoystickModel(int index) : m_index{index} {
HALSIM_GetJoystickAxes(index, &halAxes);
axisCount = halAxes.count;
for (int i = 0; i < axisCount; ++i) {
axes[i] = std::make_unique<glass::DataSource>(
axes[i] = std::make_unique<glass::DoubleSource>(
fmt::format("Joystick[{}] Axis[{}]", index, i));
}
@@ -305,9 +304,8 @@ JoystickModel::JoystickModel(int index) : m_index{index} {
HALSIM_GetJoystickButtons(index, &halButtons);
buttonCount = halButtons.count;
for (int i = 0; i < buttonCount; ++i) {
buttons[i] = new glass::DataSource(
buttons[i] = new glass::BooleanSource(
fmt::format("Joystick[{}] Button[{}]", index, i + 1));
buttons[i]->SetDigital(true);
}
for (int i = buttonCount; i < 32; ++i) {
buttons[i] = nullptr;
@@ -317,7 +315,7 @@ JoystickModel::JoystickModel(int index) : m_index{index} {
HALSIM_GetJoystickPOVs(index, &halPOVs);
povCount = halPOVs.count;
for (int i = 0; i < povCount; ++i) {
povs[i] = std::make_unique<glass::DataSource>(
povs[i] = std::make_unique<glass::IntegerSource>(
fmt::format("Joystick[{}] POV [{}]", index, i));
}
@@ -1149,12 +1147,6 @@ static void DriverStationExecute() {
}
FMSSimModel::FMSSimModel() {
m_fmsAttached.SetDigital(true);
m_dsAttached.SetDigital(true);
m_estop.SetDigital(true);
m_enabled.SetDigital(true);
m_test.SetDigital(true);
m_autonomous.SetDigital(true);
m_matchTime.SetValue(-1.0);
m_allianceStationId.SetValue(HAL_AllianceStationID_kRed1);
}
@@ -1168,7 +1160,7 @@ void FMSSimModel::UpdateHAL() {
HALSIM_SetDriverStationTest(m_test.GetValue());
HALSIM_SetDriverStationAutonomous(m_autonomous.GetValue());
HALSIM_SetDriverStationMatchTime(m_matchTime.GetValue());
auto str = wpi::make_string(m_gameMessage);
auto str = wpi::make_string(m_gameMessage.GetValue());
HALSIM_SetGameSpecificMessage(&str);
HALSIM_SetDriverStationDsAttached(m_dsAttached.GetValue());
}
@@ -1206,8 +1198,10 @@ void FMSSimModel::Update() {
HAL_MatchInfo info;
HALSIM_GetMatchInfo(&info);
m_gameMessage.assign(info.gameSpecificMessage,
info.gameSpecificMessage + info.gameSpecificMessageSize);
m_gameMessage.SetValue(
std::string_view{reinterpret_cast<const char*>(info.gameSpecificMessage),
reinterpret_cast<const char*>(info.gameSpecificMessage) +
info.gameSpecificMessageSize});
}
bool FMSSimModel::IsReadOnly() {

View File

@@ -12,12 +12,12 @@
#include <vector>
#include <fmt/format.h>
#include <glass/DataSource.h>
#include <glass/hardware/Encoder.h>
#include <hal/Ports.h>
#include <hal/simulation/EncoderData.h>
#include <hal/simulation/SimDeviceData.h>
#include "HALDataSource.h"
#include "HALSimGui.h"
using namespace halsimgui;
@@ -45,9 +45,7 @@ class EncoderSimModel : public glass::EncoderModel {
m_periodCallback{HALSIM_RegisterEncoderPeriodCallback(
index, PeriodCallbackFunc, this, true)},
m_directionCallback{HALSIM_RegisterEncoderDirectionCallback(
index, DirectionCallbackFunc, this, true)} {
m_direction.SetDigital(true);
}
index, DirectionCallbackFunc, this, true)} {}
EncoderSimModel(int32_t index, int channelA, int channelB)
: EncoderSimModel(fmt::format("Encoder[{},{}]", channelA, channelB),
@@ -90,14 +88,14 @@ class EncoderSimModel : public glass::EncoderModel {
int GetChannelA() const override { return m_channelA; }
int GetChannelB() const override { return m_channelB; }
glass::DataSource* GetDistancePerPulseData() override {
glass::DoubleSource* GetDistancePerPulseData() override {
return &m_distancePerPulse;
}
glass::DataSource* GetCountData() override { return &m_count; }
glass::DataSource* GetPeriodData() override { return &m_period; }
glass::DataSource* GetDirectionData() override { return &m_direction; }
glass::DataSource* GetDistanceData() override { return &m_distance; }
glass::DataSource* GetRateData() override { return &m_rate; }
glass::IntegerSource* GetCountData() override { return &m_count; }
glass::DoubleSource* GetPeriodData() override { return &m_period; }
glass::BooleanSource* GetDirectionData() override { return &m_direction; }
glass::DoubleSource* GetDistanceData() override { return &m_distance; }
glass::DoubleSource* GetRateData() override { return &m_rate; }
double GetMaxPeriod() override { return HALSIM_GetEncoderMaxPeriod(m_index); }
bool GetReverseDirection() override {
@@ -178,12 +176,12 @@ class EncoderSimModel : public glass::EncoderModel {
}
}
glass::DataSource m_distancePerPulse;
glass::DataSource m_count;
glass::DataSource m_period;
glass::DataSource m_direction;
glass::DataSource m_distance;
glass::DataSource m_rate;
glass::DoubleSource m_distancePerPulse;
glass::IntegerSource m_count;
glass::DoubleSource m_period;
glass::BooleanSource m_direction;
glass::DoubleSource m_distance;
glass::DoubleSource m_rate;
int32_t m_index;
int m_channelA;

View File

@@ -41,12 +41,12 @@ class CompressorSimModel : public glass::CompressorModel {
bool Exists() override { return HALSIM_GetCTREPCMInitialized(m_index); }
glass::DataSource* GetRunningData() override { return &m_running; }
glass::DataSource* GetEnabledData() override { return &m_enabled; }
glass::DataSource* GetPressureSwitchData() override {
glass::BooleanSource* GetRunningData() override { return &m_running; }
glass::BooleanSource* GetEnabledData() override { return &m_enabled; }
glass::BooleanSource* GetPressureSwitchData() override {
return &m_pressureSwitch;
}
glass::DataSource* GetCurrentData() override { return &m_current; }
glass::DoubleSource* GetCurrentData() override { return &m_current; }
void SetRunning(bool val) override {
HALSIM_SetCTREPCMCompressorOn(m_index, val);
@@ -78,7 +78,7 @@ class SolenoidSimModel : public glass::SolenoidModel {
bool Exists() override { return HALSIM_GetCTREPCMInitialized(m_index); }
glass::DataSource* GetOutputData() override { return &m_output; }
glass::BooleanSource* GetOutputData() override { return &m_output; }
void SetOutput(bool val) override {
HALSIM_SetCTREPCMSolenoidOutput(m_index, m_channel, val);

View File

@@ -39,12 +39,12 @@ class CompressorSimModel : public glass::CompressorModel {
bool Exists() override { return HALSIM_GetREVPHInitialized(m_index); }
glass::DataSource* GetRunningData() override { return &m_running; }
glass::DataSource* GetEnabledData() override { return nullptr; }
glass::DataSource* GetPressureSwitchData() override {
glass::BooleanSource* GetRunningData() override { return &m_running; }
glass::BooleanSource* GetEnabledData() override { return nullptr; }
glass::BooleanSource* GetPressureSwitchData() override {
return &m_pressureSwitch;
}
glass::DataSource* GetCurrentData() override { return &m_current; }
glass::DoubleSource* GetCurrentData() override { return &m_current; }
void SetRunning(bool val) override {
HALSIM_SetREVPHCompressorOn(m_index, val);
@@ -73,7 +73,7 @@ class SolenoidSimModel : public glass::SolenoidModel {
bool Exists() override { return HALSIM_GetREVPHInitialized(m_index); }
glass::DataSource* GetOutputData() override { return &m_output; }
glass::BooleanSource* GetOutputData() override { return &m_output; }
void SetOutput(bool val) override {
HALSIM_SetREVPHSolenoidOutput(m_index, m_channel, val);

View File

@@ -31,7 +31,7 @@ class PWMSimModel : public glass::PWMModel {
void SetAddressableLED(int led) { m_led = led; }
int GetAddressableLED() const override { return m_led; }
glass::DataSource* GetSpeedData() override { return &m_speed; }
glass::DoubleSource* GetSpeedData() override { return &m_speed; }
void SetSpeed(double val) override { HALSIM_SetPWMSpeed(m_index, val); }

View File

@@ -47,9 +47,9 @@ class PowerDistributionSimModel : public glass::PowerDistributionModel {
int GetNumChannels() const override { return m_currents.size(); }
glass::DataSource* GetTemperatureData() override { return &m_temp; }
glass::DataSource* GetVoltageData() override { return &m_voltage; }
glass::DataSource* GetCurrentData(int channel) override {
glass::DoubleSource* GetTemperatureData() override { return &m_temp; }
glass::DoubleSource* GetVoltageData() override { return &m_voltage; }
glass::DoubleSource* GetCurrentData(int channel) override {
return m_currents[channel].get();
}

View File

@@ -33,10 +33,10 @@ class RelaySimModel : public glass::RelayModel {
HALSIM_GetRelayInitializedReverse(m_index);
}
glass::DataSource* GetForwardData() override {
glass::BooleanSource* GetForwardData() override {
return HALSIM_GetRelayInitializedForward(m_index) ? &m_forward : nullptr;
}
glass::DataSource* GetReverseData() override {
glass::BooleanSource* GetReverseData() override {
return HALSIM_GetRelayInitializedReverse(m_index) ? &m_reverse : nullptr;
}

View File

@@ -36,10 +36,10 @@ class RoboRioUser6VRailSimModel : public glass::RoboRioRailModel {
public:
void Update() override {}
bool Exists() override { return true; }
glass::DataSource* GetVoltageData() override { return &m_voltage; }
glass::DataSource* GetCurrentData() override { return &m_current; }
glass::DataSource* GetActiveData() override { return &m_active; }
glass::DataSource* GetFaultsData() override { return &m_faults; }
glass::DoubleSource* GetVoltageData() override { return &m_voltage; }
glass::DoubleSource* GetCurrentData() override { return &m_current; }
glass::BooleanSource* GetActiveData() override { return &m_active; }
glass::IntegerSource* GetFaultsData() override { return &m_faults; }
void SetVoltage(double val) override { HALSIM_SetRoboRioUserVoltage6V(val); }
void SetCurrent(double val) override { HALSIM_SetRoboRioUserCurrent6V(val); }
@@ -57,10 +57,10 @@ class RoboRioUser5VRailSimModel : public glass::RoboRioRailModel {
public:
void Update() override {}
bool Exists() override { return true; }
glass::DataSource* GetVoltageData() override { return &m_voltage; }
glass::DataSource* GetCurrentData() override { return &m_current; }
glass::DataSource* GetActiveData() override { return &m_active; }
glass::DataSource* GetFaultsData() override { return &m_faults; }
glass::DoubleSource* GetVoltageData() override { return &m_voltage; }
glass::DoubleSource* GetCurrentData() override { return &m_current; }
glass::BooleanSource* GetActiveData() override { return &m_active; }
glass::IntegerSource* GetFaultsData() override { return &m_faults; }
void SetVoltage(double val) override { HALSIM_SetRoboRioUserVoltage5V(val); }
void SetCurrent(double val) override { HALSIM_SetRoboRioUserCurrent5V(val); }
@@ -78,10 +78,10 @@ class RoboRioUser3V3RailSimModel : public glass::RoboRioRailModel {
public:
void Update() override {}
bool Exists() override { return true; }
glass::DataSource* GetVoltageData() override { return &m_voltage; }
glass::DataSource* GetCurrentData() override { return &m_current; }
glass::DataSource* GetActiveData() override { return &m_active; }
glass::DataSource* GetFaultsData() override { return &m_faults; }
glass::DoubleSource* GetVoltageData() override { return &m_voltage; }
glass::DoubleSource* GetCurrentData() override { return &m_current; }
glass::BooleanSource* GetActiveData() override { return &m_active; }
glass::IntegerSource* GetFaultsData() override { return &m_faults; }
void SetVoltage(double val) override { HALSIM_SetRoboRioUserVoltage3V3(val); }
void SetCurrent(double val) override { HALSIM_SetRoboRioUserCurrent3V3(val); }
@@ -105,10 +105,10 @@ class RoboRioSimModel : public glass::RoboRioModel {
glass::RoboRioRailModel* GetUser5VRail() override { return &m_user5VRail; }
glass::RoboRioRailModel* GetUser3V3Rail() override { return &m_user3V3Rail; }
glass::DataSource* GetUserButton() override { return &m_userButton; }
glass::DataSource* GetVInVoltageData() override { return &m_vInVoltage; }
glass::DataSource* GetVInCurrentData() override { return &m_vInCurrent; }
glass::DataSource* GetBrownoutVoltage() override {
glass::BooleanSource* GetUserButton() override { return &m_userButton; }
glass::DoubleSource* GetVInVoltageData() override { return &m_vInVoltage; }
glass::DoubleSource* GetVInCurrentData() override { return &m_vInCurrent; }
glass::DoubleSource* GetBrownoutVoltage() override {
return &m_brownoutVoltage;
}

View File

@@ -22,14 +22,43 @@
using namespace halsimgui;
namespace {
class SimValueSource : public glass::DataSource {
#define DEFINE_SIMVALUESOURCE(Type, TYPE, v_type) \
class Sim##Type##ValueSource : public glass::Type##Source { \
public: \
explicit Sim##Type##ValueSource(HAL_SimValueHandle handle, \
const char* device, const char* name) \
: Type##Source(fmt::format("{}-{}", device, name)), \
m_callback{HALSIM_RegisterSimValueChangedCallback( \
handle, this, CallbackFunc, true)} {} \
~Sim##Type##ValueSource() override { \
if (m_callback != 0) { \
HALSIM_CancelSimValueChangedCallback(m_callback); \
} \
} \
\
private: \
static void CallbackFunc(const char*, void* param, HAL_SimValueHandle, \
int32_t, const HAL_Value* value) { \
auto source = static_cast<Sim##Type##ValueSource*>(param); \
if (value->type == HAL_##TYPE) { \
source->SetValue(value->data.v_##v_type); \
} \
} \
\
int32_t m_callback; \
};
DEFINE_SIMVALUESOURCE(Boolean, BOOLEAN, boolean)
DEFINE_SIMVALUESOURCE(Double, DOUBLE, double)
class SimIntegerValueSource : public glass::IntegerSource {
public:
explicit SimValueSource(HAL_SimValueHandle handle, const char* device,
const char* name)
: DataSource(fmt::format("{}-{}", device, name)),
explicit SimIntegerValueSource(HAL_SimValueHandle handle, const char* device,
const char* name)
: IntegerSource(fmt::format("{}-{}", device, name)),
m_callback{HALSIM_RegisterSimValueChangedCallback(
handle, this, CallbackFunc, true)} {}
~SimValueSource() override {
~SimIntegerValueSource() override {
if (m_callback != 0) {
HALSIM_CancelSimValueChangedCallback(m_callback);
}
@@ -38,13 +67,13 @@ class SimValueSource : public glass::DataSource {
private:
static void CallbackFunc(const char*, void* param, HAL_SimValueHandle,
int32_t, const HAL_Value* value) {
auto source = static_cast<SimValueSource*>(param);
if (value->type == HAL_BOOLEAN) {
source->SetValue(value->data.v_boolean);
source->SetDigital(true);
} else if (value->type == HAL_DOUBLE) {
source->SetValue(value->data.v_double);
source->SetDigital(false);
auto source = static_cast<SimIntegerValueSource*>(param);
if (value->type == HAL_ENUM) {
source->SetValue(value->data.v_enum);
} else if (value->type == HAL_INT) {
source->SetValue(value->data.v_int);
} else if (value->type == HAL_LONG) {
source->SetValue(value->data.v_long);
}
}
@@ -61,7 +90,8 @@ class SimDevicesModel : public glass::Model {
}
private:
wpi::DenseMap<HAL_SimValueHandle, std::unique_ptr<SimValueSource>> m_sources;
wpi::DenseMap<HAL_SimValueHandle, std::unique_ptr<glass::DataSource>>
m_sources;
};
} // namespace
@@ -81,9 +111,30 @@ void SimDevicesModel::Update() {
int32_t direction, const HAL_Value* value) {
auto data = static_cast<Data*>(dataV);
auto& source = data->self->m_sources[handle];
if (!source) {
source = std::make_unique<SimValueSource>(handle, data->device,
name);
switch (value->type) {
case HAL_BOOLEAN:
if (!dynamic_cast<SimBooleanValueSource*>(source.get())) {
source = std::make_unique<SimBooleanValueSource>(
handle, data->device, name);
}
break;
case HAL_DOUBLE:
if (!dynamic_cast<SimDoubleValueSource*>(source.get())) {
source = std::make_unique<SimDoubleValueSource>(
handle, data->device, name);
}
break;
case HAL_ENUM:
case HAL_INT:
case HAL_LONG:
if (!dynamic_cast<SimIntegerValueSource*>(source.get())) {
source = std::make_unique<SimIntegerValueSource>(
handle, data->device, name);
}
break;
default:
source.reset();
break;
}
});
});

View File

@@ -6,15 +6,13 @@
#include <glass/DataSource.h>
#define HALSIMGUI_DATASOURCE(cbname, id, TYPE, vtype) \
class cbname##Source : public ::glass::DataSource { \
#define HALSIMGUI_DATASOURCE(cbname, id, TYPE, Type, vtype) \
class cbname##Source : public ::glass::Type##Source { \
public: \
cbname##Source() \
: DataSource(id), \
: Type##Source{id}, \
m_callback{ \
HALSIM_Register##cbname##Callback(CallbackFunc, this, true)} { \
SetDigital(HAL_##TYPE == HAL_BOOLEAN); \
} \
HALSIM_Register##cbname##Callback(CallbackFunc, this, true)} {} \
\
~cbname##Source() { \
if (m_callback != 0) \
@@ -32,25 +30,24 @@
}
#define HALSIMGUI_DATASOURCE_BOOLEAN(cbname, id) \
HALSIMGUI_DATASOURCE(cbname, id, BOOLEAN, boolean)
HALSIMGUI_DATASOURCE(cbname, id, BOOLEAN, Boolean, boolean)
#define HALSIMGUI_DATASOURCE_DOUBLE(cbname, id) \
HALSIMGUI_DATASOURCE(cbname, id, DOUBLE, double)
HALSIMGUI_DATASOURCE(cbname, id, DOUBLE, Double, double)
#define HALSIMGUI_DATASOURCE_INT(cbname, id) \
HALSIMGUI_DATASOURCE(cbname, id, INT, int)
HALSIMGUI_DATASOURCE(cbname, id, INT, Integer, int)
#define HALSIMGUI_DATASOURCE_INDEXED(cbname, id, TYPE, vtype) \
class cbname##Source : public ::glass::DataSource { \
#define HALSIMGUI_DATASOURCE_INDEXED(cbname, id, TYPE, Type, vtype) \
class cbname##Source : public ::glass::Type##Source { \
public: \
explicit cbname##Source(int32_t index, int channel = -1) \
: DataSource(id, channel < 0 ? index : channel), \
: Type##Source{::glass::MakeSourceId(id, \
channel < 0 ? index : channel)}, \
m_index{index}, \
m_channel{channel < 0 ? index : channel}, \
m_callback{HALSIM_Register##cbname##Callback(index, CallbackFunc, \
this, true)} { \
SetDigital(HAL_##TYPE == HAL_BOOLEAN); \
} \
this, true)} {} \
\
~cbname##Source() { \
if (m_callback != 0) \
@@ -78,22 +75,20 @@
}
#define HALSIMGUI_DATASOURCE_BOOLEAN_INDEXED(cbname, id) \
HALSIMGUI_DATASOURCE_INDEXED(cbname, id, BOOLEAN, boolean)
HALSIMGUI_DATASOURCE_INDEXED(cbname, id, BOOLEAN, Boolean, boolean)
#define HALSIMGUI_DATASOURCE_DOUBLE_INDEXED(cbname, id) \
HALSIMGUI_DATASOURCE_INDEXED(cbname, id, DOUBLE, double)
HALSIMGUI_DATASOURCE_INDEXED(cbname, id, DOUBLE, Double, double)
#define HALSIMGUI_DATASOURCE_INDEXED2(cbname, id, TYPE, vtype) \
class cbname##Source : public ::glass::DataSource { \
#define HALSIMGUI_DATASOURCE_INDEXED2(cbname, id, TYPE, Type, vtype) \
class cbname##Source : public ::glass::Type##Source { \
public: \
explicit cbname##Source(int32_t index, int32_t channel) \
: DataSource(id, index, channel), \
: Type##Source{::glass::MakeSourceId(id, index, channel)}, \
m_index{index}, \
m_channel{channel}, \
m_callback{HALSIM_Register##cbname##Callback( \
index, channel, CallbackFunc, this, true)} { \
SetDigital(HAL_##TYPE == HAL_BOOLEAN); \
} \
index, channel, CallbackFunc, this, true)} {} \
\
~cbname##Source() { \
if (m_callback != 0) \
@@ -121,7 +116,7 @@
}
#define HALSIMGUI_DATASOURCE_BOOLEAN_INDEXED2(cbname, id) \
HALSIMGUI_DATASOURCE_INDEXED2(cbname, id, BOOLEAN, boolean)
HALSIMGUI_DATASOURCE_INDEXED2(cbname, id, BOOLEAN, Boolean, boolean)
#define HALSIMGUI_DATASOURCE_DOUBLE_INDEXED2(cbname, id) \
HALSIMGUI_DATASOURCE_INDEXED2(cbname, id, DOUBLE, double)
HALSIMGUI_DATASOURCE_INDEXED2(cbname, id, DOUBLE, Double, double)