mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-22 01:11:42 +00:00
[glass] Field2D: Embed standard field images (#5159)
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
#include <fields/fields.h>
|
||||
#include <fmt/format.h>
|
||||
#include <frc/geometry/Pose2d.h>
|
||||
#include <frc/geometry/Rotation2d.h>
|
||||
@@ -237,10 +238,12 @@ class FieldInfo {
|
||||
private:
|
||||
void Reset();
|
||||
bool LoadImageImpl(const std::string& fn);
|
||||
void LoadJson(std::string_view jsonfile);
|
||||
bool LoadJson(wpi::raw_istream& is, std::string_view filename);
|
||||
void LoadJsonFile(std::string_view jsonfile);
|
||||
|
||||
std::unique_ptr<pfd::open_file> m_fileOpener;
|
||||
|
||||
std::string& m_builtin;
|
||||
std::string& m_filename;
|
||||
gui::Texture m_texture;
|
||||
|
||||
@@ -340,7 +343,8 @@ static bool InputPose(frc::Pose2d* pose) {
|
||||
}
|
||||
|
||||
FieldInfo::FieldInfo(Storage& storage)
|
||||
: m_filename{storage.GetString("image")},
|
||||
: m_builtin{storage.GetString("builtin")},
|
||||
m_filename{storage.GetString("image")},
|
||||
m_width{storage.GetFloat("width", kDefaultWidth.to<float>())},
|
||||
m_height{storage.GetFloat("height", kDefaultHeight.to<float>())},
|
||||
m_top{storage.GetInt("top", 0)},
|
||||
@@ -349,7 +353,25 @@ FieldInfo::FieldInfo(Storage& storage)
|
||||
m_right{storage.GetInt("right", -1)} {}
|
||||
|
||||
void FieldInfo::DisplaySettings() {
|
||||
if (ImGui::Button("Choose image...")) {
|
||||
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 10);
|
||||
if (ImGui::BeginCombo("Image",
|
||||
m_builtin.empty() ? "Custom" : m_builtin.c_str())) {
|
||||
if (ImGui::Selectable("Custom", m_builtin.empty())) {
|
||||
Reset();
|
||||
}
|
||||
for (auto&& field : fields::GetFields()) {
|
||||
bool selected = field.name == m_builtin;
|
||||
if (ImGui::Selectable(field.name, selected)) {
|
||||
Reset();
|
||||
m_builtin = field.name;
|
||||
}
|
||||
if (selected) {
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
if (m_builtin.empty() && ImGui::Button("Load image...")) {
|
||||
m_fileOpener = std::make_unique<pfd::open_file>(
|
||||
"Choose field image", "",
|
||||
std::vector<std::string>{"Image File",
|
||||
@@ -370,6 +392,7 @@ void FieldInfo::DisplaySettings() {
|
||||
|
||||
void FieldInfo::Reset() {
|
||||
m_texture = gui::Texture{};
|
||||
m_builtin.clear();
|
||||
m_filename.clear();
|
||||
m_imageWidth = 0;
|
||||
m_imageHeight = 0;
|
||||
@@ -384,7 +407,7 @@ void FieldInfo::LoadImage() {
|
||||
auto result = m_fileOpener->result();
|
||||
if (!result.empty()) {
|
||||
if (wpi::ends_with(result[0], ".json")) {
|
||||
LoadJson(result[0]);
|
||||
LoadJsonFile(result[0]);
|
||||
} else {
|
||||
LoadImageImpl(result[0].c_str());
|
||||
m_top = 0;
|
||||
@@ -395,33 +418,47 @@ void FieldInfo::LoadImage() {
|
||||
}
|
||||
m_fileOpener.reset();
|
||||
}
|
||||
if (!m_texture && !m_filename.empty()) {
|
||||
if (!LoadImageImpl(m_filename)) {
|
||||
m_filename.clear();
|
||||
if (!m_texture) {
|
||||
if (!m_builtin.empty()) {
|
||||
for (auto&& field : fields::GetFields()) {
|
||||
if (field.name == m_builtin) {
|
||||
auto jsonstr = field.getJson();
|
||||
wpi::raw_mem_istream is{jsonstr.data(), jsonstr.size()};
|
||||
auto imagedata = field.getImage();
|
||||
auto texture = gui::Texture::CreateFromImage(
|
||||
reinterpret_cast<const unsigned char*>(imagedata.data()),
|
||||
imagedata.size());
|
||||
if (texture && LoadJson(is, {})) {
|
||||
m_texture = std::move(texture);
|
||||
m_imageWidth = m_texture.GetWidth();
|
||||
m_imageHeight = m_texture.GetHeight();
|
||||
} else {
|
||||
m_builtin.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (!m_filename.empty()) {
|
||||
if (!LoadImageImpl(m_filename)) {
|
||||
m_filename.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FieldInfo::LoadJson(std::string_view jsonfile) {
|
||||
std::error_code ec;
|
||||
wpi::raw_fd_istream f(jsonfile, ec);
|
||||
if (ec) {
|
||||
std::fputs("GUI: could not open field JSON file\n", stderr);
|
||||
return;
|
||||
}
|
||||
|
||||
bool FieldInfo::LoadJson(wpi::raw_istream& is, std::string_view filename) {
|
||||
// parse file
|
||||
wpi::json j;
|
||||
try {
|
||||
j = wpi::json::parse(f);
|
||||
j = wpi::json::parse(is);
|
||||
} catch (const wpi::json::parse_error& e) {
|
||||
fmt::print(stderr, "GUI: JSON: could not parse: {}\n", e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
// top level must be an object
|
||||
if (!j.is_object()) {
|
||||
std::fputs("GUI: JSON: does not contain a top object\n", stderr);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// image filename
|
||||
@@ -430,7 +467,7 @@ void FieldInfo::LoadJson(std::string_view jsonfile) {
|
||||
image = j.at("field-image").get<std::string>();
|
||||
} catch (const wpi::json::exception& e) {
|
||||
fmt::print(stderr, "GUI: JSON: could not read field-image: {}\n", e.what());
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// corners
|
||||
@@ -443,7 +480,7 @@ void FieldInfo::LoadJson(std::string_view jsonfile) {
|
||||
} catch (const wpi::json::exception& e) {
|
||||
fmt::print(stderr, "GUI: JSON: could not read field-corners: {}\n",
|
||||
e.what());
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// size
|
||||
@@ -454,7 +491,7 @@ void FieldInfo::LoadJson(std::string_view jsonfile) {
|
||||
height = j.at("field-size").at(1).get<float>();
|
||||
} catch (const wpi::json::exception& e) {
|
||||
fmt::print(stderr, "GUI: JSON: could not read field-size: {}\n", e.what());
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// units for size
|
||||
@@ -463,7 +500,7 @@ void FieldInfo::LoadJson(std::string_view jsonfile) {
|
||||
unit = j.at("field-unit").get<std::string>();
|
||||
} catch (const wpi::json::exception& e) {
|
||||
fmt::print(stderr, "GUI: JSON: could not read field-unit: {}\n", e.what());
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// convert size units to meters
|
||||
@@ -472,22 +509,35 @@ void FieldInfo::LoadJson(std::string_view jsonfile) {
|
||||
height = units::convert<units::feet, units::meters>(height);
|
||||
}
|
||||
|
||||
// the image filename is relative to the json file
|
||||
auto pathname = fs::path{jsonfile}.replace_filename(image).string();
|
||||
if (!filename.empty()) {
|
||||
// the image filename is relative to the json file
|
||||
auto pathname = fs::path{filename}.replace_filename(image).string();
|
||||
|
||||
// load field image
|
||||
if (!LoadImageImpl(pathname.c_str())) {
|
||||
return;
|
||||
// load field image
|
||||
if (!LoadImageImpl(pathname.c_str())) {
|
||||
return false;
|
||||
}
|
||||
m_filename = pathname;
|
||||
}
|
||||
|
||||
// save to field info
|
||||
m_filename = pathname;
|
||||
m_top = top;
|
||||
m_left = left;
|
||||
m_bottom = bottom;
|
||||
m_right = right;
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
return true;
|
||||
}
|
||||
|
||||
void FieldInfo::LoadJsonFile(std::string_view jsonfile) {
|
||||
std::error_code ec;
|
||||
wpi::raw_fd_istream f(jsonfile, ec);
|
||||
if (ec) {
|
||||
std::fputs("GUI: could not open field JSON file\n", stderr);
|
||||
return;
|
||||
}
|
||||
LoadJson(f, jsonfile);
|
||||
}
|
||||
|
||||
bool FieldInfo::LoadImageImpl(const std::string& fn) {
|
||||
|
||||
Reference in New Issue
Block a user