mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-19 00:41:43 +00:00
[wpiutil] Move Color and Color8Bit from wpilib to wpiutil (#8437)
Removes one of the org.wpilib.util package conflicts for modularization. Only a few minor tweaks were required to remove the wpimath dependency.
This commit is contained in:
20
wpilibc/robotpy_pybind_build_info.bzl
generated
20
wpilibc/robotpy_pybind_build_info.bzl
generated
@@ -984,26 +984,6 @@ def wpilib_extension(srcs = [], header_to_dat_deps = [], extra_hdrs = [], includ
|
||||
("wpi::Alert", "wpi__Alert.hpp"),
|
||||
],
|
||||
),
|
||||
struct(
|
||||
class_name = "Color",
|
||||
yml_file = "semiwrap/Color.yml",
|
||||
header_root = "$(execpath :robotpy-native-wpilib.copy_headers)",
|
||||
header_file = "$(execpath :robotpy-native-wpilib.copy_headers)/wpi/util/Color.hpp",
|
||||
tmpl_class_names = [],
|
||||
trampolines = [
|
||||
("wpi::Color", "wpi__Color.hpp"),
|
||||
],
|
||||
),
|
||||
struct(
|
||||
class_name = "Color8Bit",
|
||||
yml_file = "semiwrap/Color8Bit.yml",
|
||||
header_root = "$(execpath :robotpy-native-wpilib.copy_headers)",
|
||||
header_file = "$(execpath :robotpy-native-wpilib.copy_headers)/wpi/util/Color8Bit.hpp",
|
||||
tmpl_class_names = [],
|
||||
trampolines = [
|
||||
("wpi::Color8Bit", "wpi__Color8Bit.hpp"),
|
||||
],
|
||||
),
|
||||
struct(
|
||||
class_name = "Preferences",
|
||||
yml_file = "semiwrap/Preferences.yml",
|
||||
|
||||
@@ -75,5 +75,5 @@ void AddressableLED::SetGlobalData(int start, ColorOrder colorOrder,
|
||||
}
|
||||
|
||||
void AddressableLED::LEDData::SetHSV(int h, int s, int v) {
|
||||
SetLED(Color::FromHSV(h, s, v));
|
||||
SetLED(wpi::util::Color::FromHSV(h, s, v));
|
||||
}
|
||||
|
||||
@@ -17,24 +17,29 @@
|
||||
|
||||
using namespace wpi;
|
||||
|
||||
LEDPattern::LEDPattern(std::function<void(wpi::LEDPattern::LEDReader,
|
||||
std::function<void(int, wpi::Color)>)>
|
||||
impl)
|
||||
LEDPattern::LEDPattern(
|
||||
std::function<void(wpi::LEDPattern::LEDReader,
|
||||
std::function<void(int, wpi::util::Color)>)>
|
||||
impl)
|
||||
: m_impl(std::move(impl)) {}
|
||||
|
||||
void LEDPattern::ApplyTo(LEDPattern::LEDReader reader,
|
||||
std::function<void(int, wpi::Color)> writer) const {
|
||||
void LEDPattern::ApplyTo(
|
||||
LEDPattern::LEDReader reader,
|
||||
std::function<void(int, wpi::util::Color)> writer) const {
|
||||
m_impl(reader, writer);
|
||||
}
|
||||
|
||||
void LEDPattern::ApplyTo(std::span<AddressableLED::LEDData> data,
|
||||
std::function<void(int, wpi::Color)> writer) const {
|
||||
void LEDPattern::ApplyTo(
|
||||
std::span<AddressableLED::LEDData> data,
|
||||
std::function<void(int, wpi::util::Color)> writer) const {
|
||||
ApplyTo(LEDPattern::LEDReader{[=](size_t i) { return data[i]; }, data.size()},
|
||||
writer);
|
||||
}
|
||||
|
||||
void LEDPattern::ApplyTo(std::span<AddressableLED::LEDData> data) const {
|
||||
ApplyTo(data, [&](int index, Color color) { data[index].SetLED(color); });
|
||||
ApplyTo(data, [&](int index, wpi::util::Color color) {
|
||||
data[index].SetLED(color);
|
||||
});
|
||||
}
|
||||
|
||||
LEDPattern LEDPattern::MapIndex(
|
||||
@@ -44,7 +49,9 @@ LEDPattern LEDPattern::MapIndex(
|
||||
self.ApplyTo(
|
||||
LEDPattern::LEDReader{
|
||||
[=](auto i) { return data[indexMapper(bufLen, i)]; }, bufLen},
|
||||
[&](int i, Color color) { writer(indexMapper(bufLen, i), color); });
|
||||
[&](int i, wpi::util::Color color) {
|
||||
writer(indexMapper(bufLen, i), color);
|
||||
});
|
||||
}};
|
||||
}
|
||||
|
||||
@@ -131,7 +138,7 @@ LEDPattern LEDPattern::Breathe(wpi::units::second_t period) {
|
||||
auto periodMicros = wpi::units::microsecond_t{period};
|
||||
|
||||
return LEDPattern{[periodMicros, self = *this](auto data, auto writer) {
|
||||
self.ApplyTo(data, [&writer, periodMicros](int i, Color color) {
|
||||
self.ApplyTo(data, [&writer, periodMicros](int i, wpi::util::Color color) {
|
||||
double t = (wpi::util::Now() % periodMicros.to<uint64_t>()) /
|
||||
periodMicros.to<double>();
|
||||
double phase = t * 2 * std::numbers::pi;
|
||||
@@ -140,7 +147,8 @@ LEDPattern LEDPattern::Breathe(wpi::units::second_t period) {
|
||||
// Use cosine so the period starts at 100% brightness
|
||||
double dim = (std::cos(phase) + 1) / 2.0;
|
||||
|
||||
writer(i, Color{color.red * dim, color.green * dim, color.blue * dim});
|
||||
writer(i, wpi::util::Color{color.red * dim, color.green * dim,
|
||||
color.blue * dim});
|
||||
});
|
||||
}};
|
||||
}
|
||||
@@ -151,7 +159,7 @@ LEDPattern LEDPattern::OverlayOn(const LEDPattern& base) {
|
||||
base.ApplyTo(data, writer);
|
||||
|
||||
// ... then, overwrite with illuminated LEDs from the overlay
|
||||
self.ApplyTo(data, [&](int i, Color color) {
|
||||
self.ApplyTo(data, [&](int i, wpi::util::Color color) {
|
||||
if (color.red > 0 || color.green > 0 || color.blue > 0) {
|
||||
writer(i, color);
|
||||
}
|
||||
@@ -164,12 +172,12 @@ LEDPattern LEDPattern::Blend(const LEDPattern& other) {
|
||||
// Apply the current pattern down as normal...
|
||||
self.ApplyTo(data, writer);
|
||||
|
||||
other.ApplyTo(data, [&](int i, Color color) {
|
||||
other.ApplyTo(data, [&](int i, wpi::util::Color color) {
|
||||
// ... then read the result and average it with the output from the other
|
||||
// pattern
|
||||
writer(i, Color{(data[i].r / 255.0 + color.red) / 2,
|
||||
(data[i].g / 255.0 + color.green) / 2,
|
||||
(data[i].b / 255.0 + color.blue) / 2});
|
||||
writer(i, wpi::util::Color{(data[i].r / 255.0 + color.red) / 2,
|
||||
(data[i].g / 255.0 + color.green) / 2,
|
||||
(data[i].b / 255.0 + color.blue) / 2});
|
||||
});
|
||||
}};
|
||||
}
|
||||
@@ -179,23 +187,24 @@ LEDPattern LEDPattern::Mask(const LEDPattern& mask) {
|
||||
// Apply the current pattern down as normal...
|
||||
self.ApplyTo(data, writer);
|
||||
|
||||
mask.ApplyTo(data, [&](int i, Color color) {
|
||||
mask.ApplyTo(data, [&](int i, wpi::util::Color color) {
|
||||
auto currentColor = data[i];
|
||||
// ... then perform a bitwise AND operation on each channel to apply the
|
||||
// mask
|
||||
writer(i, Color{currentColor.r & static_cast<uint8_t>(255 * color.red),
|
||||
currentColor.g & static_cast<uint8_t>(255 * color.green),
|
||||
currentColor.b & static_cast<uint8_t>(255 * color.blue)});
|
||||
writer(i, wpi::util::Color{
|
||||
currentColor.r & static_cast<uint8_t>(255 * color.red),
|
||||
currentColor.g & static_cast<uint8_t>(255 * color.green),
|
||||
currentColor.b & static_cast<uint8_t>(255 * color.blue)});
|
||||
});
|
||||
}};
|
||||
}
|
||||
|
||||
LEDPattern LEDPattern::AtBrightness(double relativeBrightness) {
|
||||
return LEDPattern{[relativeBrightness, self = *this](auto data, auto writer) {
|
||||
self.ApplyTo(data, [&](int i, Color color) {
|
||||
writer(i, Color{color.red * relativeBrightness,
|
||||
color.green * relativeBrightness,
|
||||
color.blue * relativeBrightness});
|
||||
self.ApplyTo(data, [&](int i, wpi::util::Color color) {
|
||||
writer(i, wpi::util::Color{color.red * relativeBrightness,
|
||||
color.green * relativeBrightness,
|
||||
color.blue * relativeBrightness});
|
||||
});
|
||||
}};
|
||||
}
|
||||
@@ -203,10 +212,10 @@ LEDPattern LEDPattern::AtBrightness(double relativeBrightness) {
|
||||
// Static constants and functions
|
||||
|
||||
LEDPattern LEDPattern::Off() {
|
||||
return LEDPattern::Solid(Color::kBlack);
|
||||
return LEDPattern::Solid(wpi::util::Color::kBlack);
|
||||
}
|
||||
|
||||
LEDPattern LEDPattern::Solid(const Color color) {
|
||||
LEDPattern LEDPattern::Solid(const wpi::util::Color color) {
|
||||
return LEDPattern{[=](auto data, auto writer) {
|
||||
auto bufLen = data.size();
|
||||
for (size_t i = 0; i < bufLen; i++) {
|
||||
@@ -223,15 +232,16 @@ LEDPattern LEDPattern::ProgressMaskLayer(
|
||||
size_t max = bufLen * progress;
|
||||
|
||||
for (size_t led = 0; led < max; led++) {
|
||||
writer(led, Color::kWhite);
|
||||
writer(led, wpi::util::Color::kWhite);
|
||||
}
|
||||
for (size_t led = max; led < bufLen; led++) {
|
||||
writer(led, Color::kBlack);
|
||||
writer(led, wpi::util::Color::kBlack);
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
LEDPattern LEDPattern::Steps(std::span<const std::pair<double, Color>> steps) {
|
||||
LEDPattern LEDPattern::Steps(
|
||||
std::span<const std::pair<double, wpi::util::Color>> steps) {
|
||||
if (steps.size() == 0) {
|
||||
// no colors specified
|
||||
return LEDPattern::Off();
|
||||
@@ -247,12 +257,12 @@ LEDPattern LEDPattern::Steps(std::span<const std::pair<double, Color>> steps) {
|
||||
|
||||
// precompute relevant positions for this buffer so we don't need to do a
|
||||
// check on every single LED index
|
||||
std::unordered_map<int, Color> stopPositions;
|
||||
std::unordered_map<int, wpi::util::Color> stopPositions;
|
||||
|
||||
for (auto step : steps) {
|
||||
stopPositions[std::floor(step.first * bufLen)] = step.second;
|
||||
}
|
||||
auto currentColor = Color::kBlack;
|
||||
auto currentColor = wpi::util::Color::kBlack;
|
||||
for (size_t led = 0; led < bufLen; led++) {
|
||||
if (stopPositions.contains(led)) {
|
||||
currentColor = stopPositions[led];
|
||||
@@ -263,12 +273,12 @@ LEDPattern LEDPattern::Steps(std::span<const std::pair<double, Color>> steps) {
|
||||
}
|
||||
|
||||
LEDPattern LEDPattern::Steps(
|
||||
std::initializer_list<std::pair<double, Color>> steps) {
|
||||
std::initializer_list<std::pair<double, wpi::util::Color>> steps) {
|
||||
return Steps(std::span{steps.begin(), steps.end()});
|
||||
}
|
||||
|
||||
LEDPattern LEDPattern::Gradient(GradientType type,
|
||||
std::span<const Color> colors) {
|
||||
std::span<const wpi::util::Color> colors) {
|
||||
if (colors.size() == 0) {
|
||||
// no colors specified
|
||||
return LEDPattern::Off();
|
||||
@@ -300,16 +310,17 @@ LEDPattern LEDPattern::Gradient(GradientType type,
|
||||
auto color = colors[colorIndex];
|
||||
auto nextColor = colors[nextColorIndex];
|
||||
|
||||
Color gradientColor{wpi::util::Lerp(color.red, nextColor.red, t),
|
||||
wpi::util::Lerp(color.green, nextColor.green, t),
|
||||
wpi::util::Lerp(color.blue, nextColor.blue, t)};
|
||||
wpi::util::Color gradientColor{
|
||||
wpi::util::Lerp(color.red, nextColor.red, t),
|
||||
wpi::util::Lerp(color.green, nextColor.green, t),
|
||||
wpi::util::Lerp(color.blue, nextColor.blue, t)};
|
||||
writer(led, gradientColor);
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
LEDPattern LEDPattern::Gradient(GradientType type,
|
||||
std::initializer_list<Color> colors) {
|
||||
LEDPattern LEDPattern::Gradient(
|
||||
GradientType type, std::initializer_list<wpi::util::Color> colors) {
|
||||
return Gradient(type, std::span{colors.begin(), colors.end()});
|
||||
}
|
||||
|
||||
@@ -318,7 +329,7 @@ LEDPattern LEDPattern::Rainbow(int saturation, int value) {
|
||||
auto bufLen = data.size();
|
||||
for (size_t led = 0; led < bufLen; led++) {
|
||||
int hue = ((led * 180) / bufLen) % 180;
|
||||
writer(led, Color::FromHSV(hue, saturation, value));
|
||||
writer(led, wpi::util::Color::FromHSV(hue, saturation, value));
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ static constexpr std::string_view kBackgroundColor = "backgroundColor";
|
||||
static constexpr std::string_view kDims = "dims";
|
||||
|
||||
Mechanism2d::Mechanism2d(double width, double height,
|
||||
const Color8Bit& backgroundColor)
|
||||
const wpi::util::Color8Bit& backgroundColor)
|
||||
: m_width{width}, m_height{height} {
|
||||
SetBackgroundColor(backgroundColor);
|
||||
}
|
||||
@@ -30,7 +30,7 @@ MechanismRoot2d* Mechanism2d::GetRoot(std::string_view name, double x,
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
void Mechanism2d::SetBackgroundColor(const Color8Bit& color) {
|
||||
void Mechanism2d::SetBackgroundColor(const wpi::util::Color8Bit& color) {
|
||||
m_color = color.HexString();
|
||||
if (m_colorPub) {
|
||||
m_colorPub.Set(m_color);
|
||||
|
||||
@@ -17,7 +17,7 @@ static constexpr std::string_view kSmartDashboardType = "line";
|
||||
MechanismLigament2d::MechanismLigament2d(std::string_view name, double length,
|
||||
wpi::units::degree_t angle,
|
||||
double lineWeight,
|
||||
const wpi::Color8Bit& color)
|
||||
const wpi::util::Color8Bit& color)
|
||||
: MechanismObject2d{name},
|
||||
m_length{length},
|
||||
m_angle{angle.value()},
|
||||
@@ -42,7 +42,7 @@ void MechanismLigament2d::UpdateEntries(
|
||||
m_lengthEntry.Set(m_length);
|
||||
}
|
||||
|
||||
void MechanismLigament2d::SetColor(const Color8Bit& color) {
|
||||
void MechanismLigament2d::SetColor(const wpi::util::Color8Bit& color) {
|
||||
std::scoped_lock lock(m_mutex);
|
||||
|
||||
wpi::util::format_to_n_c_str(m_color, sizeof(m_color), "#{:02X}{:02X}{:02X}",
|
||||
@@ -69,7 +69,7 @@ void MechanismLigament2d::SetLineWeight(double lineWidth) {
|
||||
}
|
||||
}
|
||||
|
||||
Color8Bit MechanismLigament2d::GetColor() {
|
||||
wpi::util::Color8Bit MechanismLigament2d::GetColor() {
|
||||
std::scoped_lock lock(m_mutex);
|
||||
if (m_colorEntry) {
|
||||
auto color = m_colorEntry.Get();
|
||||
|
||||
@@ -79,7 +79,7 @@ class AddressableLED {
|
||||
*
|
||||
* @param color The color of the LED
|
||||
*/
|
||||
void SetLED(const Color& color) {
|
||||
void SetLED(const wpi::util::Color& color) {
|
||||
this->r = color.red * 255;
|
||||
this->g = color.green * 255;
|
||||
this->b = color.blue * 255;
|
||||
@@ -90,7 +90,7 @@ class AddressableLED {
|
||||
*
|
||||
* @param color The color of the LED
|
||||
*/
|
||||
void SetLED(const Color8Bit& color) {
|
||||
void SetLED(const wpi::util::Color8Bit& color) {
|
||||
this->r = color.red;
|
||||
this->g = color.green;
|
||||
this->b = color.blue;
|
||||
|
||||
@@ -41,12 +41,13 @@ class LEDPattern {
|
||||
size_t m_size;
|
||||
};
|
||||
|
||||
explicit LEDPattern(std::function<void(wpi::LEDPattern::LEDReader,
|
||||
std::function<void(int, wpi::Color)>)>
|
||||
impl);
|
||||
explicit LEDPattern(
|
||||
std::function<void(wpi::LEDPattern::LEDReader,
|
||||
std::function<void(int, wpi::util::Color)>)>
|
||||
impl);
|
||||
|
||||
void ApplyTo(LEDReader reader,
|
||||
std::function<void(int, wpi::Color)> writer) const;
|
||||
std::function<void(int, wpi::util::Color)> writer) const;
|
||||
|
||||
/**
|
||||
* Writes the pattern to an LED buffer. Dynamic animations should be called
|
||||
@@ -62,7 +63,7 @@ class LEDPattern {
|
||||
* @param writer data writer for setting new LED colors on the LED strip
|
||||
*/
|
||||
void ApplyTo(std::span<wpi::AddressableLED::LEDData> data,
|
||||
std::function<void(int, wpi::Color)> writer) const;
|
||||
std::function<void(int, wpi::util::Color)> writer) const;
|
||||
|
||||
/**
|
||||
* Writes the pattern to an LED buffer. Dynamic animations should be called
|
||||
@@ -199,8 +200,8 @@ class LEDPattern {
|
||||
|
||||
/**
|
||||
* Creates a pattern that plays this pattern overlaid on another. Anywhere
|
||||
* this pattern sets an LED to off (or {@link wpi::Color::kBlack}), the base
|
||||
* pattern will be displayed instead.
|
||||
* this pattern sets an LED to off (or {@link wpi::util::Color::kBlack}), the
|
||||
* base pattern will be displayed instead.
|
||||
*
|
||||
* @param base the base pattern to overlay on top of
|
||||
* @return the combined overlay pattern
|
||||
@@ -256,10 +257,10 @@ class LEDPattern {
|
||||
*
|
||||
* <pre>
|
||||
* // Solid red, but at 50% brightness
|
||||
* wpi::LEDPattern::Solid(wpi::Color::kRed).AtBrightness(0.5);
|
||||
* wpi::LEDPattern::Solid(wpi::util::Color::kRed).AtBrightness(0.5);
|
||||
*
|
||||
* // Solid white, but at only 10% (i.e. ~0.5V)
|
||||
* wpi::LEDPattern::Solid(frc:Color::kWhite).AtBrightness(0.1);
|
||||
* wpi::LEDPattern::Solid(wpi::util::Color::kWhite).AtBrightness(0.1);
|
||||
* </pre>
|
||||
*
|
||||
* @param relativeBrightness the multiplier to apply to all channels to modify
|
||||
@@ -279,7 +280,7 @@ class LEDPattern {
|
||||
* @param color the color to display
|
||||
* @return the pattern
|
||||
*/
|
||||
static LEDPattern Solid(const Color color);
|
||||
static LEDPattern Solid(const wpi::util::Color color);
|
||||
|
||||
/**
|
||||
* Creates a pattern that works as a mask layer for {@link
|
||||
@@ -296,8 +297,8 @@ class LEDPattern {
|
||||
*
|
||||
* <pre>
|
||||
* wpi::LEDPattern basePattern =
|
||||
* wpi::LEDPattern::Gradient(wpi::Color::kRed, wpi::Color::kBlue);
|
||||
* wpi::LEDPattern progressPattern =
|
||||
* wpi::LEDPattern::Gradient(wpi::util::Color::kRed,
|
||||
* wpi::util::Color::kBlue); wpi::LEDPattern progressPattern =
|
||||
* basePattern.Mask(wpi::LEDPattern::ProgressMaskLayer([&]() {
|
||||
* return elevator.GetHeight() / elevator.MaxHeight();
|
||||
* });
|
||||
@@ -322,7 +323,8 @@ class LEDPattern {
|
||||
* position along the LED strip
|
||||
* @return a motionless step pattern
|
||||
*/
|
||||
static LEDPattern Steps(std::span<const std::pair<double, Color>> steps);
|
||||
static LEDPattern Steps(
|
||||
std::span<const std::pair<double, wpi::util::Color>> steps);
|
||||
|
||||
/**
|
||||
* Display a set of colors in steps across the length of the LED strip. No
|
||||
@@ -337,7 +339,7 @@ class LEDPattern {
|
||||
* @return a motionless step pattern
|
||||
*/
|
||||
static LEDPattern Steps(
|
||||
std::initializer_list<std::pair<double, Color>> steps);
|
||||
std::initializer_list<std::pair<double, wpi::util::Color>> steps);
|
||||
|
||||
/** Types of gradients. */
|
||||
enum GradientType {
|
||||
@@ -368,7 +370,8 @@ class LEDPattern {
|
||||
* @param colors the colors to display in the gradient
|
||||
* @return a motionless gradient pattern
|
||||
*/
|
||||
static LEDPattern Gradient(GradientType type, std::span<const Color> colors);
|
||||
static LEDPattern Gradient(GradientType type,
|
||||
std::span<const wpi::util::Color> colors);
|
||||
|
||||
/**
|
||||
* Creates a pattern that displays a non-animated gradient of colors across
|
||||
@@ -384,7 +387,7 @@ class LEDPattern {
|
||||
* @return a motionless gradient pattern
|
||||
*/
|
||||
static LEDPattern Gradient(GradientType type,
|
||||
std::initializer_list<Color> colors);
|
||||
std::initializer_list<wpi::util::Color> colors);
|
||||
|
||||
/**
|
||||
* Creates an LED pattern that displays a rainbow across the color wheel. The
|
||||
@@ -398,7 +401,7 @@ class LEDPattern {
|
||||
|
||||
private:
|
||||
std::function<void(wpi::LEDPattern::LEDReader,
|
||||
std::function<void(int, wpi::Color)>)>
|
||||
std::function<void(int, wpi::util::Color)>)>
|
||||
m_impl;
|
||||
};
|
||||
} // namespace wpi
|
||||
|
||||
@@ -52,7 +52,7 @@ class Mechanism2d : public wpi::nt::NTSendable,
|
||||
* @param backgroundColor the background color
|
||||
*/
|
||||
Mechanism2d(double width, double height,
|
||||
const Color8Bit& backgroundColor = {0, 0, 32});
|
||||
const wpi::util::Color8Bit& backgroundColor = {0, 0, 32});
|
||||
|
||||
/**
|
||||
* Get or create a root in this Mechanism2d with the given name and
|
||||
@@ -73,7 +73,7 @@ class Mechanism2d : public wpi::nt::NTSendable,
|
||||
*
|
||||
* @param color the new background color
|
||||
*/
|
||||
void SetBackgroundColor(const Color8Bit& color);
|
||||
void SetBackgroundColor(const wpi::util::Color8Bit& color);
|
||||
|
||||
void InitSendable(wpi::nt::NTSendableBuilder& builder) override;
|
||||
|
||||
|
||||
@@ -27,21 +27,21 @@ class MechanismLigament2d : public MechanismObject2d {
|
||||
public:
|
||||
MechanismLigament2d(std::string_view name, double length,
|
||||
wpi::units::degree_t angle, double lineWidth = 6,
|
||||
const wpi::Color8Bit& color = {235, 137, 52});
|
||||
const wpi::util::Color8Bit& color = {235, 137, 52});
|
||||
|
||||
/**
|
||||
* Set the ligament color.
|
||||
*
|
||||
* @param color the color of the line
|
||||
*/
|
||||
void SetColor(const Color8Bit& color);
|
||||
void SetColor(const wpi::util::Color8Bit& color);
|
||||
|
||||
/**
|
||||
* Get the ligament color.
|
||||
*
|
||||
* @return the color of the line
|
||||
*/
|
||||
Color8Bit GetColor();
|
||||
wpi::util::Color8Bit GetColor();
|
||||
|
||||
/**
|
||||
* Set the ligament's length.
|
||||
|
||||
@@ -210,8 +210,6 @@ Watchdog = "wpi/system/Watchdog.hpp"
|
||||
|
||||
# wpi/util
|
||||
Alert = "wpi/util/Alert.hpp"
|
||||
Color = "wpi/util/Color.hpp"
|
||||
Color8Bit = "wpi/util/Color8Bit.hpp"
|
||||
Preferences = "wpi/util/Preferences.hpp"
|
||||
SensorUtil = "wpi/util/SensorUtil.hpp"
|
||||
|
||||
|
||||
@@ -39,6 +39,6 @@ classes:
|
||||
SetHSV:
|
||||
SetLED:
|
||||
overloads:
|
||||
const Color&:
|
||||
const Color8Bit&:
|
||||
const wpi::util::Color&:
|
||||
const wpi::util::Color8Bit&:
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@ classes:
|
||||
ApplyTo:
|
||||
overloads:
|
||||
std::span<wpi::AddressableLED::LEDData> [const]:
|
||||
LEDReader, std::function<void (int, wpi::Color)> [const]:
|
||||
std::span<wpi::AddressableLED::LEDData>, std::function<void (int, wpi::Color)> [const]:
|
||||
LEDReader, std::function<void (int, wpi::util::Color)> [const]:
|
||||
std::span<wpi::AddressableLED::LEDData>, std::function<void (int, wpi::util::Color)> [const]:
|
||||
Reversed:
|
||||
OffsetBy:
|
||||
ScrollAtRelativeSpeed:
|
||||
@@ -28,13 +28,13 @@ classes:
|
||||
ProgressMaskLayer:
|
||||
Steps:
|
||||
overloads:
|
||||
std::span<const std::pair<double, Color>>:
|
||||
std::initializer_list<std::pair<double, Color>>:
|
||||
std::span<const std::pair<double, wpi::util::Color>>:
|
||||
std::initializer_list<std::pair<double, wpi::util::Color>>:
|
||||
ignore: true
|
||||
Gradient:
|
||||
overloads:
|
||||
GradientType, std::span<const Color>:
|
||||
GradientType, std::initializer_list<Color>:
|
||||
GradientType, std::span<const wpi::util::Color>:
|
||||
GradientType, std::initializer_list<wpi::util::Color>:
|
||||
ignore: true
|
||||
Rainbow:
|
||||
MapIndex:
|
||||
|
||||
@@ -21,11 +21,11 @@ inline_code: |-
|
||||
cls_MechanismObject2d
|
||||
.def("appendLigament", [](MechanismObject2d *self,
|
||||
std::string_view name, double length, wpi::units::degree_t angle,
|
||||
double lineWidth, const wpi::Color8Bit& color) {
|
||||
double lineWidth, const wpi::util::Color8Bit& color) {
|
||||
return self->Append<MechanismLigament2d>(name, length, angle, lineWidth, color);
|
||||
},
|
||||
py::arg("name"), py::arg("length"), py::arg("angle"),
|
||||
py::arg("lineWidth") = 6, py::arg("color") = wpi::Color8Bit{235, 137, 52},
|
||||
py::arg("lineWidth") = 6, py::arg("color") = wpi::util::Color8Bit{235, 137, 52},
|
||||
"Append a ligament node",
|
||||
py::return_value_policy::reference_internal)
|
||||
;
|
||||
|
||||
@@ -20,11 +20,11 @@ inline_code: |-
|
||||
.def("getName", [](MechanismRoot2d *self) { return self->GetName(); }, release_gil())
|
||||
.def("appendLigament", [](MechanismRoot2d *self,
|
||||
std::string_view name, double length, wpi::units::degree_t angle,
|
||||
double lineWidth, const wpi::Color8Bit& color) {
|
||||
double lineWidth, const wpi::util::Color8Bit& color) {
|
||||
return self->Append<MechanismLigament2d>(name, length, angle, lineWidth, color);
|
||||
},
|
||||
py::arg("name"), py::arg("length"), py::arg("angle"),
|
||||
py::arg("lineWidth") = 6, py::arg("color") = wpi::Color8Bit{235, 137, 52},
|
||||
py::arg("lineWidth") = 6, py::arg("color") = wpi::util::Color8Bit{235, 137, 52},
|
||||
release_gil(), "Append a ligament node",
|
||||
py::return_value_policy::reference_internal)
|
||||
;
|
||||
|
||||
@@ -14,8 +14,6 @@ from ._wpilib import (
|
||||
AnalogPotentiometer,
|
||||
CAN,
|
||||
CANStatus,
|
||||
Color,
|
||||
Color8Bit,
|
||||
Compressor,
|
||||
CompressorConfigType,
|
||||
DSControlWord,
|
||||
@@ -106,8 +104,6 @@ __all__ = [
|
||||
"AnalogPotentiometer",
|
||||
"CAN",
|
||||
"CANStatus",
|
||||
"Color",
|
||||
"Color8Bit",
|
||||
"Compressor",
|
||||
"CompressorConfigType",
|
||||
"DSControlWord",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -60,7 +60,7 @@ TEST(Mechanism2dTest, Ligament) {
|
||||
wpi::MechanismRoot2d* root = mechanism.GetRoot("root", 1, 2);
|
||||
wpi::MechanismLigament2d* ligament = root->Append<wpi::MechanismLigament2d>(
|
||||
"ligament", 3, wpi::units::degree_t{90}, 1,
|
||||
wpi::Color8Bit{255, 255, 255});
|
||||
wpi::util::Color8Bit{255, 255, 255});
|
||||
wpi::SmartDashboard::PutData("mechanism", &mechanism);
|
||||
EXPECT_EQ(ligament->GetAngle(), angleEntry.GetDouble(0.0));
|
||||
EXPECT_EQ(ligament->GetColor().HexString(), colorEntry.GetString(""));
|
||||
|
||||
@@ -61,7 +61,9 @@ class Arm {
|
||||
wpi::MechanismRoot2d* m_armBase = m_mech2d.GetRoot("ArmBase", 30, 30);
|
||||
wpi::MechanismLigament2d* m_armTower =
|
||||
m_armBase->Append<wpi::MechanismLigament2d>(
|
||||
"Arm Tower", 30, -90_deg, 6, wpi::Color8Bit{wpi::Color::kBlue});
|
||||
"Arm Tower", 30, -90_deg, 6,
|
||||
wpi::util::Color8Bit{wpi::util::Color::kBlue});
|
||||
wpi::MechanismLigament2d* m_arm = m_armBase->Append<wpi::MechanismLigament2d>(
|
||||
"Arm", 30, m_armSim.GetAngle(), 6, wpi::Color8Bit{wpi::Color::kYellow});
|
||||
"Arm", 30, m_armSim.GetAngle(), 6,
|
||||
wpi::util::Color8Bit{wpi::util::Color::kYellow});
|
||||
};
|
||||
|
||||
@@ -66,7 +66,8 @@ class Robot : public wpi::TimedRobot {
|
||||
m_root->Append<wpi::MechanismLigament2d>("elevator", 1, 90_deg);
|
||||
wpi::MechanismLigament2d* m_wrist =
|
||||
m_elevator->Append<wpi::MechanismLigament2d>(
|
||||
"wrist", 0.5, 90_deg, 6, wpi::Color8Bit{wpi::Color::kPurple});
|
||||
"wrist", 0.5, 90_deg, 6,
|
||||
wpi::util::Color8Bit{wpi::util::Color::kPurple});
|
||||
};
|
||||
|
||||
#ifndef RUNNING_WPILIB_TESTS
|
||||
|
||||
20
wpiutil/robotpy_pybind_build_info.bzl
generated
20
wpiutil/robotpy_pybind_build_info.bzl
generated
@@ -8,6 +8,26 @@ load("//shared/bazel/rules/robotpy:semiwrap_tool_helpers.bzl", "scan_headers", "
|
||||
|
||||
def wpiutil_extension(srcs = [], header_to_dat_deps = [], extra_hdrs = [], includes = [], extra_pyi_deps = []):
|
||||
WPIUTIL_HEADER_GEN = [
|
||||
struct(
|
||||
class_name = "Color",
|
||||
yml_file = "semiwrap/Color.yml",
|
||||
header_root = "$(execpath :robotpy-native-wpiutil.copy_headers)",
|
||||
header_file = "$(execpath :robotpy-native-wpiutil.copy_headers)/wpi/util/Color.hpp",
|
||||
tmpl_class_names = [],
|
||||
trampolines = [
|
||||
("wpi::util::Color", "wpi__util__Color.hpp"),
|
||||
],
|
||||
),
|
||||
struct(
|
||||
class_name = "Color8Bit",
|
||||
yml_file = "semiwrap/Color8Bit.yml",
|
||||
header_root = "$(execpath :robotpy-native-wpiutil.copy_headers)",
|
||||
header_file = "$(execpath :robotpy-native-wpiutil.copy_headers)/wpi/util/Color8Bit.hpp",
|
||||
tmpl_class_names = [],
|
||||
trampolines = [
|
||||
("wpi::util::Color8Bit", "wpi__util__Color8Bit.hpp"),
|
||||
],
|
||||
),
|
||||
struct(
|
||||
class_name = "StackTrace",
|
||||
yml_file = "semiwrap/StackTrace.yml",
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
package org.wpilib.util;
|
||||
|
||||
import java.util.Objects;
|
||||
import org.wpilib.math.util.MathUtil;
|
||||
|
||||
/**
|
||||
* Represents colors.
|
||||
@@ -197,6 +196,10 @@ public class Color {
|
||||
return Math.clamp(Math.ceil(value * (1 << 12)) / (1 << 12), 0.0, 1.0);
|
||||
}
|
||||
|
||||
private static int lerp(int a, int b, double t) {
|
||||
return (int) (a + (b - a) * t);
|
||||
}
|
||||
|
||||
// Helper methods
|
||||
|
||||
/**
|
||||
@@ -369,10 +372,7 @@ public class Color {
|
||||
* @return the interpolated color, packed in a 32-bit integer
|
||||
*/
|
||||
public static int lerpRGB(int r1, int g1, int b1, int r2, int g2, int b2, double t) {
|
||||
return packRGB(
|
||||
(int) MathUtil.lerp(r1, r2, t),
|
||||
(int) MathUtil.lerp(g1, g2, t),
|
||||
(int) MathUtil.lerp(b1, b2, t));
|
||||
return packRGB(lerp(r1, r2, t), lerp(g1, g2, t), lerp(b1, b2, t));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -11,12 +11,28 @@
|
||||
#include <string_view>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <gcem.hpp>
|
||||
|
||||
#include "wpi/util/StringExtras.hpp"
|
||||
#include "wpi/util/ct_string.hpp"
|
||||
|
||||
namespace wpi {
|
||||
namespace wpi::util {
|
||||
|
||||
// replicate ceil from gcem to avoid gcem dependency here
|
||||
namespace detail {
|
||||
constexpr double ceil_int(double x, double x_whole) noexcept {
|
||||
return (x_whole + ((x > 0) && (x > x_whole)));
|
||||
}
|
||||
|
||||
constexpr double ceil(double x) noexcept {
|
||||
if (std::is_constant_evaluated()) {
|
||||
return ((x < 0.0 ? -x : x) >= 4503599627370496.
|
||||
? x
|
||||
: ceil_int(x, static_cast<double>(static_cast<int64_t>(x))));
|
||||
} else {
|
||||
return std::ceil(x);
|
||||
}
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* Represents colors that can be used with Addressable LEDs.
|
||||
@@ -906,7 +922,7 @@ class Color {
|
||||
|
||||
private:
|
||||
static constexpr double roundAndClamp(double value) {
|
||||
return std::clamp(gcem::ceil(value * (1 << 12)) / (1 << 12), 0.0, 1.0);
|
||||
return std::clamp(detail::ceil(value * (1 << 12)) / (1 << 12), 0.0, 1.0);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1083,4 +1099,4 @@ inline constexpr Color Color::kWhiteSmoke{0.9607843f, 0.9607843f, 0.9607843f};
|
||||
inline constexpr Color Color::kYellow{1.0f, 1.0f, 0.0f};
|
||||
inline constexpr Color Color::kYellowGreen{0.6039216f, 0.8039216f, 0.19607843f};
|
||||
|
||||
} // namespace wpi
|
||||
} // namespace wpi::util
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "wpi/util/StringExtras.hpp"
|
||||
#include "wpi/util/ct_string.hpp"
|
||||
|
||||
namespace wpi {
|
||||
namespace wpi::util {
|
||||
|
||||
/**
|
||||
* Represents colors that can be used with Addressable LEDs.
|
||||
@@ -131,4 +131,4 @@ class Color8Bit {
|
||||
int blue = 0;
|
||||
};
|
||||
|
||||
} // namespace wpi
|
||||
} // namespace wpi::util
|
||||
@@ -67,6 +67,8 @@ depends = ["wpiutil-casters"]
|
||||
|
||||
[tool.semiwrap.extension_modules."wpiutil._wpiutil".headers]
|
||||
# wpi
|
||||
Color = "wpi/util/Color.hpp"
|
||||
Color8Bit = "wpi/util/Color8Bit.hpp"
|
||||
StackTrace = "wpi/util/StackTrace.hpp"
|
||||
Synchronization = "wpi/util/Synchronization.h"
|
||||
RawFrame = "wpi/util/RawFrame.h"
|
||||
|
||||
@@ -2,7 +2,7 @@ extra_includes:
|
||||
- pybind11/operators.h
|
||||
|
||||
classes:
|
||||
wpi::Color:
|
||||
wpi::util::Color:
|
||||
force_type_casters:
|
||||
- wpi::util::ct_string
|
||||
attributes:
|
||||
@@ -173,6 +173,12 @@ classes:
|
||||
HexString:
|
||||
operator==:
|
||||
|
||||
functions:
|
||||
ceil_int:
|
||||
ignore: true
|
||||
ceil:
|
||||
ignore: true
|
||||
|
||||
inline_code: |
|
||||
cls_Color
|
||||
.def("__hash__", [](Color *self) -> size_t {
|
||||
@@ -2,7 +2,7 @@ extra_includes:
|
||||
- pybind11/operators.h
|
||||
|
||||
classes:
|
||||
wpi::Color8Bit:
|
||||
wpi::util::Color8Bit:
|
||||
force_type_casters:
|
||||
- wpi::util::ct_string
|
||||
attributes:
|
||||
@@ -32,7 +32,7 @@ classes:
|
||||
|
||||
inline_code: |
|
||||
cls_Color8Bit
|
||||
.def("toColor", [](const Color8Bit &self) -> wpi::Color {
|
||||
.def("toColor", [](const Color8Bit &self) -> wpi::util::Color {
|
||||
return self;
|
||||
})
|
||||
.def("__hash__", [](Color8Bit *self) -> size_t {
|
||||
@@ -2,6 +2,8 @@ from . import _init__wpiutil
|
||||
|
||||
# autogenerated by 'semiwrap create-imports wpiutil wpiutil._wpiutil'
|
||||
from ._wpiutil import (
|
||||
Color,
|
||||
Color8Bit,
|
||||
Sendable,
|
||||
SendableBuilder,
|
||||
SendableRegistry,
|
||||
@@ -11,6 +13,8 @@ from ._wpiutil import (
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"Color",
|
||||
"Color8Bit",
|
||||
"Sendable",
|
||||
"SendableBuilder",
|
||||
"SendableRegistry",
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
TEST(Color8BitTest, ConstructDefault) {
|
||||
constexpr wpi::Color8Bit color;
|
||||
constexpr wpi::util::Color8Bit color;
|
||||
|
||||
EXPECT_EQ(0, color.red);
|
||||
EXPECT_EQ(0, color.green);
|
||||
@@ -17,7 +17,7 @@ TEST(Color8BitTest, ConstructDefault) {
|
||||
}
|
||||
|
||||
TEST(Color8BitTest, ConstructFromInts) {
|
||||
constexpr wpi::Color8Bit color{255, 128, 64};
|
||||
constexpr wpi::util::Color8Bit color{255, 128, 64};
|
||||
|
||||
EXPECT_EQ(255, color.red);
|
||||
EXPECT_EQ(128, color.green);
|
||||
@@ -25,7 +25,7 @@ TEST(Color8BitTest, ConstructFromInts) {
|
||||
}
|
||||
|
||||
TEST(Color8BitTest, ConstructFromColor) {
|
||||
constexpr wpi::Color8Bit color{wpi::Color{255, 128, 64}};
|
||||
constexpr wpi::util::Color8Bit color{wpi::util::Color{255, 128, 64}};
|
||||
|
||||
EXPECT_EQ(255, color.red);
|
||||
EXPECT_EQ(128, color.green);
|
||||
@@ -33,24 +33,24 @@ TEST(Color8BitTest, ConstructFromColor) {
|
||||
}
|
||||
|
||||
TEST(Color8BitTest, ConstructFromHexString) {
|
||||
constexpr wpi::Color8Bit color{"#FF8040"};
|
||||
constexpr wpi::util::Color8Bit color{"#FF8040"};
|
||||
|
||||
EXPECT_EQ(255, color.red);
|
||||
EXPECT_EQ(128, color.green);
|
||||
EXPECT_EQ(64, color.blue);
|
||||
|
||||
// No leading #
|
||||
EXPECT_THROW(wpi::Color8Bit{"112233"}, std::invalid_argument);
|
||||
EXPECT_THROW(wpi::util::Color8Bit{"112233"}, std::invalid_argument);
|
||||
|
||||
// Too long
|
||||
EXPECT_THROW(wpi::Color8Bit{"#11223344"}, std::invalid_argument);
|
||||
EXPECT_THROW(wpi::util::Color8Bit{"#11223344"}, std::invalid_argument);
|
||||
|
||||
// Invalid hex characters
|
||||
EXPECT_THROW(wpi::Color8Bit{"#$$$$$$"}, std::invalid_argument);
|
||||
EXPECT_THROW(wpi::util::Color8Bit{"#$$$$$$"}, std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST(Color8BitTest, ImplicitConversionToColor) {
|
||||
wpi::Color color = wpi::Color8Bit{255, 128, 64};
|
||||
wpi::util::Color color = wpi::util::Color8Bit{255, 128, 64};
|
||||
|
||||
EXPECT_NEAR(1.0, color.red, 1e-2);
|
||||
EXPECT_NEAR(0.5, color.green, 1e-2);
|
||||
@@ -58,13 +58,13 @@ TEST(Color8BitTest, ImplicitConversionToColor) {
|
||||
}
|
||||
|
||||
TEST(Color8BitTest, ToHexString) {
|
||||
constexpr wpi::Color8Bit color1{255, 128, 64};
|
||||
constexpr wpi::util::Color8Bit color1{255, 128, 64};
|
||||
EXPECT_EQ("#FF8040", color1.HexString());
|
||||
|
||||
// Ensure conversion to std::string works
|
||||
[[maybe_unused]]
|
||||
std::string str = color1.HexString();
|
||||
|
||||
wpi::Color8Bit color2{255, 128, 64};
|
||||
wpi::util::Color8Bit color2{255, 128, 64};
|
||||
EXPECT_EQ("#FF8040", color2.HexString());
|
||||
}
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
TEST(ColorTest, ConstructDefault) {
|
||||
constexpr wpi::Color color;
|
||||
constexpr wpi::util::Color color;
|
||||
|
||||
EXPECT_DOUBLE_EQ(0.0, color.red);
|
||||
EXPECT_DOUBLE_EQ(0.0, color.green);
|
||||
@@ -18,7 +18,7 @@ TEST(ColorTest, ConstructDefault) {
|
||||
|
||||
TEST(ColorTest, ConstructFromDoubles) {
|
||||
{
|
||||
constexpr wpi::Color color{1.0, 0.5, 0.25};
|
||||
constexpr wpi::util::Color color{1.0, 0.5, 0.25};
|
||||
|
||||
EXPECT_NEAR(1.0, color.red, 1e-2);
|
||||
EXPECT_NEAR(0.5, color.green, 1e-2);
|
||||
@@ -26,7 +26,7 @@ TEST(ColorTest, ConstructFromDoubles) {
|
||||
}
|
||||
|
||||
{
|
||||
constexpr wpi::Color color{1.0, 0.0, 0.0};
|
||||
constexpr wpi::util::Color color{1.0, 0.0, 0.0};
|
||||
|
||||
// Check for exact match to ensure round-and-clamp is correct
|
||||
EXPECT_EQ(1.0, color.red);
|
||||
@@ -36,7 +36,7 @@ TEST(ColorTest, ConstructFromDoubles) {
|
||||
}
|
||||
|
||||
TEST(ColorTest, ConstructFromInts) {
|
||||
constexpr wpi::Color color{255, 128, 64};
|
||||
constexpr wpi::util::Color color{255, 128, 64};
|
||||
|
||||
EXPECT_NEAR(1.0, color.red, 1e-2);
|
||||
EXPECT_NEAR(0.5, color.green, 1e-2);
|
||||
@@ -44,46 +44,50 @@ TEST(ColorTest, ConstructFromInts) {
|
||||
}
|
||||
|
||||
TEST(ColorTest, FromHexString) {
|
||||
constexpr wpi::Color color = wpi::Color::FromString("#FF8040");
|
||||
constexpr wpi::util::Color color = wpi::util::Color::FromString("#FF8040");
|
||||
|
||||
EXPECT_NEAR(1.0, color.red, 1e-2);
|
||||
EXPECT_NEAR(0.5, color.green, 1e-2);
|
||||
EXPECT_NEAR(0.25, color.blue, 1e-2);
|
||||
|
||||
// No leading #
|
||||
EXPECT_THROW(wpi::Color::FromString("112233"), std::invalid_argument);
|
||||
EXPECT_THROW(wpi::util::Color::FromString("112233"), std::invalid_argument);
|
||||
|
||||
// Too long
|
||||
EXPECT_THROW(wpi::Color::FromString("#11223344"), std::invalid_argument);
|
||||
EXPECT_THROW(wpi::util::Color::FromString("#11223344"),
|
||||
std::invalid_argument);
|
||||
|
||||
// Invalid hex characters
|
||||
EXPECT_THROW(wpi::Color::FromString("#$$$$$$"), std::invalid_argument);
|
||||
EXPECT_THROW(wpi::util::Color::FromString("#$$$$$$"), std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST(ColorTest, FromRGBString) {
|
||||
constexpr wpi::Color color = wpi::Color::FromString("rgb(255, 128, 64)");
|
||||
constexpr wpi::util::Color color =
|
||||
wpi::util::Color::FromString("rgb(255, 128, 64)");
|
||||
|
||||
EXPECT_NEAR(1.0, color.red, 1e-2);
|
||||
EXPECT_NEAR(0.5, color.green, 1e-2);
|
||||
EXPECT_NEAR(0.25, color.blue, 1e-2);
|
||||
|
||||
// Missing rgb()
|
||||
EXPECT_THROW(wpi::Color::FromString("255, 128, 64"), std::invalid_argument);
|
||||
EXPECT_THROW(wpi::util::Color::FromString("255, 128, 64"),
|
||||
std::invalid_argument);
|
||||
|
||||
// Too few components
|
||||
EXPECT_THROW(wpi::Color::FromString("rgb(255, 128)"), std::invalid_argument);
|
||||
EXPECT_THROW(wpi::util::Color::FromString("rgb(255, 128)"),
|
||||
std::invalid_argument);
|
||||
|
||||
// Too many components
|
||||
EXPECT_THROW(wpi::Color::FromString("rgb(255, 128, 64, 32)"),
|
||||
EXPECT_THROW(wpi::util::Color::FromString("rgb(255, 128, 64, 32)"),
|
||||
std::invalid_argument);
|
||||
|
||||
// Non-integer component
|
||||
EXPECT_THROW(wpi::Color::FromString("rgb(255, abc, 64)"),
|
||||
EXPECT_THROW(wpi::util::Color::FromString("rgb(255, abc, 64)"),
|
||||
std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST(ColorTest, FromHSV) {
|
||||
constexpr wpi::Color color = wpi::Color::FromHSV(90, 128, 64);
|
||||
constexpr wpi::util::Color color = wpi::util::Color::FromHSV(90, 128, 64);
|
||||
|
||||
EXPECT_DOUBLE_EQ(0.125732421875, color.red);
|
||||
EXPECT_DOUBLE_EQ(0.251220703125, color.green);
|
||||
@@ -91,13 +95,13 @@ TEST(ColorTest, FromHSV) {
|
||||
}
|
||||
|
||||
TEST(ColorTest, ToHexString) {
|
||||
constexpr wpi::Color color1{255, 128, 64};
|
||||
constexpr wpi::util::Color color1{255, 128, 64};
|
||||
EXPECT_EQ("#FF8040", color1.HexString());
|
||||
|
||||
// Ensure conversion to std::string works
|
||||
[[maybe_unused]]
|
||||
std::string str = color1.HexString();
|
||||
|
||||
wpi::Color color2{255, 128, 64};
|
||||
wpi::util::Color color2{255, 128, 64};
|
||||
EXPECT_EQ("#FF8040", color2.HexString());
|
||||
}
|
||||
Reference in New Issue
Block a user