10#include "nlohmann/json.hpp"
20const std::filesystem::path layouts_json_rel_path = std::filesystem::path{
"data"} /
"layouts" /
"layouts.json";
39 const std::filesystem::path &project_root,
41 std::string &layouts_table_label,
42 std::vector<ProjectLayoutMetadata> &layout_entries,
43 std::map<std::string, std::size_t> &layout_index,
50 const auto layouts_path = project_root / layouts_json_rel_path;
52 std::ifstream file{layouts_path};
53 if (!file.is_open()) {
58 nlohmann::json json_data;
62 catch (
const nlohmann::json::parse_error &e) {
64 "Failed to parse layouts JSON from '{}': {}.",
69 if (!json_data.contains(
"layouts_table_label")) {
71 "Layouts file '{}' missing required field 'layouts_table_label'.",
75 if (!json_data.contains(
"layouts")) {
84 auto table_label = json_data.at(
"layouts_table_label").get<std::string>();
86 const auto &layouts_array = json_data.at(
"layouts");
87 std::vector<ProjectLayoutMetadata> entries;
88 std::map<std::string, std::size_t> index;
89 entries.reserve(layouts_array.size());
91 for (
const auto &entry : layouts_array) {
93 auto id = entry.at(
"id").get<std::string>();
94 auto name = entry.at(
"name").get<std::string>();
95 auto width = entry.at(
"width").get<std::size_t>();
96 auto height = entry.at(
"height").get<std::size_t>();
97 auto primary_tileset = entry.at(
"primary_tileset").get<std::string>();
98 auto secondary_tileset = entry.at(
"secondary_tileset").get<std::string>();
99 auto border_fp = std::filesystem::path{entry.at(
"border_filepath").get<std::string>()};
100 auto blockdata_fp = std::filesystem::path{entry.at(
"blockdata_filepath").get<std::string>()};
102 const auto idx = entries.size();
109 std::move(primary_tileset),
110 std::move(secondary_tileset),
111 std::move(border_fp),
112 std::move(blockdata_fp)});
114 index.emplace(entries.at(idx).id(), idx);
115 index.emplace(entries.at(idx).name(), idx);
117 catch (
const nlohmann::json::exception &e) {
119 "Malformed layout entry in '{}': {}.",
125 layouts_table_label = std::move(table_label);
126 layout_entries = std::move(entries);
127 layout_index = std::move(index);
128 layouts_parsed =
true;
149 const std::string &layout_name_or_id,
150 const std::filesystem::path &project_root,
151 bool &layouts_parsed,
152 std::string &layouts_table_label,
153 std::vector<ProjectLayoutMetadata> &layout_entries,
154 std::map<std::string, std::size_t> &layout_index,
157 if (
const auto ensure_result = ensure_layouts_parsed(
158 project_root, layouts_parsed, layouts_table_label, layout_entries, layout_index, format);
159 !ensure_result.has_value()) {
166 if (!layout_index.contains(layout_name_or_id)) {
171 return &layout_entries.at(layout_index.at(layout_name_or_id));
180 if (
const auto result = ensure_layouts_parsed(
181 project_root_, layouts_parsed_, layouts_table_label_, layout_entries_, layout_index_, format_);
182 !result.has_value()) {
185 return layout_index_.contains(layout_name_or_id);
196 layouts_table_label_,
212 layouts_table_label_,
228 layouts_table_label_,
233 return layout->primary_tileset();
245 layouts_table_label_,
250 return layout->secondary_tileset();
256 ensure_layouts_parsed(
257 project_root_, layouts_parsed_, layouts_table_label_, layout_entries_, layout_index_, format_),
258 std::set<std::string>,
259 "Failed to enumerate layout names.");
261 std::set<std::string> names;
262 for (
const auto &entry : layout_entries_) {
263 names.insert(entry.name());
271 ensure_layouts_parsed(
272 project_root_, layouts_parsed_, layouts_table_label_, layout_entries_, layout_index_, format_),
273 std::set<std::string>,
274 "Failed to enumerate layout IDs.");
276 std::set<std::string> ids;
277 for (
const auto &entry : layout_entries_) {
278 ids.insert(entry.id());
286 ensure_layouts_parsed(
287 project_root_, layouts_parsed_, layouts_table_label_, layout_entries_, layout_index_, format_),
289 "Failed to get layouts table label.");
290 return layouts_table_label_;
302 layouts_table_label_,
306 std::filesystem::path);
307 return project_root_ /
layout->border_filepath();
319 layouts_table_label_,
323 std::filesystem::path);
324 return project_root_ /
layout->blockdata_filepath();
329 layouts_parsed_ =
false;
330 layouts_table_label_.clear();
331 layout_entries_.clear();
332 layout_index_.clear();
#define PT_TRY_ASSIGN_PASS_ERR(var, expr, return_type)
Unwraps a ChainableResult, passing through the error chain with an empty FormattableError when types ...
#define PT_TRY_CALL_CHAIN_ERR(expr, return_type,...)
Unwraps a void ChainableResult, chaining a new error message on failure.
A result type that maintains a chainable sequence of errors for debugging and error reporting.
static const Style bold
Bold text formatting.
Abstract base class for applying text styling with context-aware formatting.
virtual std::string format(const std::string &format_str, const std::vector< FormatParam > ¶ms) const
Formats a string with styled parameters using fmtlib syntax.
@ layout
Configuration scoped to a specific layout.