10#include "nlohmann/json.hpp"
20const std::filesystem::path layouts_json_rel_path = std::filesystem::path{
"data"} /
"layouts" /
"layouts.json";
37 const std::filesystem::path &project_root,
39 std::string &layouts_table_label,
40 std::vector<ProjectLayoutMetadata> &layout_entries,
41 std::map<std::string, std::size_t> &layout_index,
48 const auto layouts_path = project_root / layouts_json_rel_path;
50 std::ifstream file{layouts_path};
51 if (!file.is_open()) {
56 nlohmann::json json_data;
60 catch (
const nlohmann::json::parse_error &e) {
62 "Failed to parse layouts JSON from '{}': {}.",
67 if (!json_data.contains(
"layouts_table_label")) {
69 "Layouts file '{}' missing required field 'layouts_table_label'.",
76 if (!json_data.at(
"layouts_table_label").is_string()) {
78 "Layouts file '{}' field 'layouts_table_label' must be a string.",
82 if (!json_data.contains(
"layouts")) {
87 if (!json_data.at(
"layouts").is_array()) {
94 auto table_label = json_data.at(
"layouts_table_label").get<std::string>();
96 const auto &layouts_array = json_data.at(
"layouts");
97 std::vector<ProjectLayoutMetadata> entries;
98 std::map<std::string, std::size_t> index;
99 entries.reserve(layouts_array.size());
101 for (
const auto &entry : layouts_array) {
103 auto id = entry.at(
"id").get<std::string>();
104 auto name = entry.at(
"name").get<std::string>();
105 auto width = entry.at(
"width").get<std::size_t>();
106 auto height = entry.at(
"height").get<std::size_t>();
107 auto primary_tileset = entry.at(
"primary_tileset").get<std::string>();
108 auto secondary_tileset = entry.at(
"secondary_tileset").get<std::string>();
109 auto border_fp = std::filesystem::path{entry.at(
"border_filepath").get<std::string>()};
110 auto blockdata_fp = std::filesystem::path{entry.at(
"blockdata_filepath").get<std::string>()};
112 const auto idx = entries.size();
119 std::move(primary_tileset),
120 std::move(secondary_tileset),
121 std::move(border_fp),
122 std::move(blockdata_fp)});
124 index.emplace(entries.at(idx).id(), idx);
125 index.emplace(entries.at(idx).name(), idx);
127 catch (
const nlohmann::json::exception &e) {
129 "Malformed layout entry in '{}': {}.",
135 layouts_table_label = std::move(table_label);
136 layout_entries = std::move(entries);
137 layout_index = std::move(index);
138 layouts_parsed =
true;
157 const std::string &layout_name_or_id,
158 const std::filesystem::path &project_root,
159 bool &layouts_parsed,
160 std::string &layouts_table_label,
161 std::vector<ProjectLayoutMetadata> &layout_entries,
162 std::map<std::string, std::size_t> &layout_index,
165 if (
const auto ensure_result = ensure_layouts_parsed(
166 project_root, layouts_parsed, layouts_table_label, layout_entries, layout_index, format);
167 !ensure_result.has_value()) {
174 if (!layout_index.contains(layout_name_or_id)) {
179 return &layout_entries.at(layout_index.at(layout_name_or_id));
188 if (
const auto result = ensure_layouts_parsed(
189 project_root_, layouts_parsed_, layouts_table_label_, layout_entries_, layout_index_, format_);
190 !result.has_value()) {
193 return layout_index_.contains(layout_name_or_id);
204 layouts_table_label_,
220 layouts_table_label_,
236 layouts_table_label_,
241 return layout->primary_tileset();
253 layouts_table_label_,
258 return layout->secondary_tileset();
264 ensure_layouts_parsed(
265 project_root_, layouts_parsed_, layouts_table_label_, layout_entries_, layout_index_, format_),
266 std::set<std::string>,
267 "Failed to enumerate layout names.");
269 std::set<std::string> names;
270 for (
const auto &entry : layout_entries_) {
271 names.insert(entry.name());
279 ensure_layouts_parsed(
280 project_root_, layouts_parsed_, layouts_table_label_, layout_entries_, layout_index_, format_),
281 std::set<std::string>,
282 "Failed to enumerate layout IDs.");
284 std::set<std::string> ids;
285 for (
const auto &entry : layout_entries_) {
286 ids.insert(entry.id());
294 ensure_layouts_parsed(
295 project_root_, layouts_parsed_, layouts_table_label_, layout_entries_, layout_index_, format_),
297 "Failed to get layouts table label.");
298 return layouts_table_label_;
310 layouts_table_label_,
314 std::filesystem::path);
315 return project_root_ /
layout->border_filepath();
327 layouts_table_label_,
331 std::filesystem::path);
332 return project_root_ /
layout->blockdata_filepath();
337 layouts_parsed_ =
false;
338 layouts_table_label_.clear();
339 layout_entries_.clear();
340 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.