21const std::filesystem::path headers_rel_path = std::filesystem::path{
"src"} /
"data" /
"tilesets" /
"headers.h";
24const std::filesystem::path graphics_rel_path = std::filesystem::path{
"src"} /
"data" /
"tilesets" /
"graphics.h";
25const std::filesystem::path metatiles_rel_path = std::filesystem::path{
"src"} /
"data" /
"tilesets" /
"metatiles.h";
26const std::filesystem::path src_graphics_rel_path = std::filesystem::path{
"src"} /
"graphics.c";
43 const std::filesystem::path &project_root,
44 bool &metadata_parsed,
45 std::map<std::string, ProjectTilesetMetadata> &tileset_metadata,
48 if (metadata_parsed) {
52 const auto headers_path = project_root / headers_rel_path;
57 parser.parse_struct_initializers(
"gTileset_"),
59 format->
format(
"Failed to parse tileset headers from '{}'.",
FormatParam{headers_path.string(), Style::bold}));
61 for (
auto &struct_decl : struct_decls) {
62 const auto &tileset_name = struct_decl.variable_name();
64 auto is_secondary_opt = struct_decl.field_value(
"isSecondary");
65 bool is_secondary = is_secondary_opt.has_value() && is_secondary_opt.value() ==
"TRUE";
67 auto tiles_var = struct_decl.field_value(
"tiles");
68 auto palettes_var = struct_decl.field_value(
"palettes");
69 auto metatiles_var = struct_decl.field_value(
"metatiles");
70 auto metatile_attributes_var = struct_decl.field_value(
"metatileAttributes");
71 auto callback_var = struct_decl.field_value(
"callback");
73 if (!tiles_var.has_value() || !palettes_var.has_value() || !metatiles_var.has_value() ||
74 !metatile_attributes_var.has_value()) {
78 std::optional<std::string> callback_func = std::nullopt;
79 if (callback_var.has_value() && callback_var.value() !=
"NULL") {
80 callback_func = callback_var.value();
83 tileset_metadata.emplace(
90 metatiles_var.value(),
91 metatile_attributes_var.value(),
95 metadata_parsed =
true;
116 const std::filesystem::path &project_root,
117 bool &metadata_parsed,
118 std::map<std::string, ProjectTilesetMetadata> &tileset_metadata,
119 bool &artifact_paths_parsed,
120 std::map<std::string, ProjectTilesetArtifactPaths> &tileset_artifact_paths,
123 if (artifact_paths_parsed) {
128 ensure_metadata_parsed(project_root, metadata_parsed, tileset_metadata, format),
130 "Failed to resolve artifact paths.");
133 std::map<std::string, IncbinDeclaration> incbin_vars;
135 const auto graphics_path = project_root / graphics_rel_path;
139 graphics_parser.parse_incbin_arrays(),
142 "Failed to parse graphics INCBINs from '{}'.",
FormatParam{graphics_path.string(), Style::bold}));
143 for (
auto &incbin : graphics_incbins) {
144 incbin_vars.emplace(incbin.variable_name(), std::move(incbin));
147 const auto metatiles_path = project_root / metatiles_rel_path;
151 metatiles_parser.parse_incbin_arrays(),
154 "Failed to parse metatiles INCBINs from '{}'.",
FormatParam{metatiles_path.string(), Style::bold}));
155 for (
auto &incbin : metatiles_incbins) {
156 incbin_vars.emplace(incbin.variable_name(), std::move(incbin));
159 const auto src_graphics_path = project_root / src_graphics_rel_path;
160 CParserFacade src_graphics_parser{src_graphics_path, format};
162 src_graphics_incbins,
163 src_graphics_parser.parse_incbin_arrays(),
166 "Failed to parse graphics INCBINs from '{}'.",
FormatParam{src_graphics_path.string(), Style::bold}));
167 for (
auto &incbin : src_graphics_incbins) {
168 incbin_vars.emplace(incbin.variable_name(), std::move(incbin));
172 for (
const auto &[tileset_name, metadata] : tileset_metadata) {
173 auto tiles_it = incbin_vars.find(metadata.tiles_var());
174 auto palettes_it = incbin_vars.find(metadata.palettes_var());
175 auto metatiles_it = incbin_vars.find(metadata.metatiles_var());
176 auto attrs_it = incbin_vars.find(metadata.metatile_attributes_var());
178 if (tiles_it == incbin_vars.end() || palettes_it == incbin_vars.end() || metatiles_it == incbin_vars.end() ||
179 attrs_it == incbin_vars.end()) {
183 if (tiles_it->second.paths().empty() || palettes_it->second.paths().empty() ||
184 metatiles_it->second.paths().empty() || attrs_it->second.paths().empty()) {
188 std::vector<std::filesystem::path> palette_paths;
189 palette_paths.reserve(palettes_it->second.paths().size());
190 for (
const auto &path_str : palettes_it->second.paths()) {
191 palette_paths.emplace_back(path_str);
194 tileset_artifact_paths.emplace(
197 std::filesystem::path{tiles_it->second.paths().front()},
198 std::move(palette_paths),
199 std::filesystem::path{metatiles_it->second.paths().front()},
200 std::filesystem::path{attrs_it->second.paths().front()}});
203 artifact_paths_parsed =
true;
213 const auto metadata_result =
metadata_for(tileset_name);
214 return metadata_result.has_value();
220 return metadata.is_secondary();
226 return metadata.has_animations();
232 ensure_metadata_parsed(project_root_, metadata_parsed_, tileset_metadata_, format_),
233 std::set<std::string>,
234 "Failed to enumerate tilesets.");
236 std::set<std::string> names;
237 for (
const auto &[tileset_name, metadata] : tileset_metadata_) {
238 names.insert(tileset_name);
247 ensure_metadata_parsed(project_root_, metadata_parsed_, tileset_metadata_, format_),
249 format_->
format(
"Failed to get metadata for tileset '{}'.",
FormatParam{tileset_name, Style::bold}));
251 if (!tileset_metadata_.contains(tileset_name)) {
256 return tileset_metadata_.at(tileset_name);
263 ensure_artifact_paths_parsed(
267 artifact_paths_parsed_,
268 tileset_artifact_paths_,
271 format_->
format(
"Failed to get artifact paths for tileset '{}'.",
FormatParam{tileset_name, Style::bold}));
273 if (!tileset_artifact_paths_.contains(tileset_name)) {
278 return tileset_artifact_paths_.at(tileset_name);
283 metadata_parsed_ =
false;
284 tileset_metadata_.clear();
285 artifact_paths_parsed_ =
false;
286 tileset_artifact_paths_.clear();
#define PT_TRY_ASSIGN_CHAIN_ERR(var, expr, return_type,...)
Unwraps a ChainableResult, chaining a new error message on failure.
#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.
High-level facade for parsing C/C++ source files.
A result type that maintains a chainable sequence of errors for debugging and error reporting.
Represents resolved filesystem paths for tileset artifacts from INCBIN declarations.
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.