18const std::filesystem::path src_dir{
"src"};
19const std::filesystem::path porytiles_generated_include{
"include/porytiles_generated/tilesets"};
20const std::filesystem::path porytiles_src{
"porytiles_src"};
21const std::filesystem::path porytiles_bin{
"porytiles_bin"};
22const std::filesystem::path anim_dir{
"anim"};
23const std::filesystem::path generated_anim_code_header{
"generated_anim_code.h"};
24const std::filesystem::path bottom_png{
"bottom.png"};
25const std::filesystem::path middle_png{
"middle.png"};
26const std::filesystem::path top_png{
"top.png"};
27const std::filesystem::path attributes_csv{
"attributes.csv"};
28const std::filesystem::path porytiles_pals{
"palettes"};
29const std::filesystem::path porymap_pals{
"palettes"};
30const std::filesystem::path anim_json{
"anim.json"};
31const std::filesystem::path metatiles_bin{
"metatiles.bin"};
32const std::filesystem::path attrs_bin{
"metatile_attributes.bin"};
33const std::filesystem::path tiles_png{
"tiles.png"};
49 const std::filesystem::path &dir_path,
const std::string &artifact_type,
const TextFormatter *format)
51 if (!std::filesystem::exists(dir_path) || !std::filesystem::is_directory(dir_path)) {
52 return std::set<std::string>{};
55 std::set<std::string> result;
56 for (
const auto &entry : std::filesystem::directory_iterator{dir_path}) {
57 if (!entry.is_directory()) {
60 const std::string dir_name = entry.path().filename().string();
62 if (expected_snake != dir_name) {
64 "{} directory name '{}' must be snake_case (expected '{}')",
69 result.insert(dir_name);
88scan_png_files(
const std::filesystem::path &dir_path,
const std::string &artifact_type,
const TextFormatter *format)
90 if (!std::filesystem::exists(dir_path) || !std::filesystem::is_directory(dir_path)) {
91 return std::set<std::string>{};
94 std::set<std::string> result;
95 for (
const auto &entry : std::filesystem::directory_iterator{dir_path}) {
96 if (!entry.is_regular_file()) {
99 const auto &path = entry.path();
100 if (path.extension() !=
".png") {
103 const std::string stem = path.stem().string();
105 if (expected_snake != stem) {
107 "{} file name '{}' must be snake_case (expected '{}.png')",
132 "Failed to determine primary/secondary status.");
137 auto base_path = is_secondary ? tileset_paths_secondary_bin : tileset_paths_primary_bin;
139 std::filesystem::path path =
140 std::filesystem::path{base_path.value()} / snake_tileset_dir / porytiles_bin / metatiles_bin;
153 "Failed to determine primary/secondary status.");
158 auto base_path = is_secondary ? tileset_paths_secondary_bin : tileset_paths_primary_bin;
160 std::filesystem::path path =
161 std::filesystem::path{base_path.value()} / snake_tileset_dir / porytiles_bin / attrs_bin;
173 "Failed to determine primary/secondary status.");
178 auto base_path = is_secondary ? tileset_paths_secondary_bin : tileset_paths_primary_bin;
180 std::filesystem::path path =
181 std::filesystem::path{base_path.value()} / snake_tileset_dir / porytiles_bin / tiles_png;
194 "Failed to determine primary/secondary status.");
199 auto base_path = is_secondary ? tileset_paths_secondary_bin : tileset_paths_primary_bin;
201 std::filesystem::path path = std::filesystem::path{base_path.value()} / snake_tileset_dir / porytiles_bin /
208 const std::string &tileset_name,
const std::string &anim_name,
const std::string &frame_name)
const
215 "Failed to determine primary/secondary status.");
220 auto base_path = is_secondary ? tileset_paths_secondary_bin : tileset_paths_primary_bin;
222 std::filesystem::path path = std::filesystem::path{base_path.value()} / snake_tileset_dir / porytiles_bin /
223 anim_dir / anim_name / (frame_name + std::string{
".png"});
232 std::filesystem::path path = porytiles_generated_include / snake_tileset_dir / generated_anim_code_header;
247 "Failed to determine primary/secondary status.");
252 auto base_path = is_secondary ? tileset_paths_secondary_bin : tileset_paths_primary_bin;
254 std::filesystem::path path =
255 std::filesystem::path{base_path.value()} / snake_tileset_dir / porytiles_src / bottom_png;
268 "Failed to determine primary/secondary status.");
273 auto base_path = is_secondary ? tileset_paths_secondary_bin : tileset_paths_primary_bin;
275 std::filesystem::path path =
276 std::filesystem::path{base_path.value()} / snake_tileset_dir / porytiles_src / middle_png;
288 "Failed to determine primary/secondary status.");
293 auto base_path = is_secondary ? tileset_paths_secondary_bin : tileset_paths_primary_bin;
295 std::filesystem::path path = std::filesystem::path{base_path.value()} / snake_tileset_dir / porytiles_src / top_png;
308 "Failed to determine primary/secondary status.");
313 auto base_path = is_secondary ? tileset_paths_secondary_bin : tileset_paths_primary_bin;
315 std::filesystem::path path =
316 std::filesystem::path{base_path.value()} / snake_tileset_dir / porytiles_src / attributes_csv;
329 "Failed to determine primary/secondary status.");
334 auto base_path = is_secondary ? tileset_paths_secondary_bin : tileset_paths_primary_bin;
336 std::filesystem::path path = std::filesystem::path{base_path.value()} / snake_tileset_dir / porytiles_src /
343 const std::string &tileset_name,
const std::string &anim_name,
const std::string &frame_name)
const
350 "Failed to determine primary/secondary status.");
355 auto base_path = is_secondary ? tileset_paths_secondary_bin : tileset_paths_primary_bin;
357 std::filesystem::path path = std::filesystem::path{base_path.value()} / snake_tileset_dir / porytiles_src /
358 anim_dir / anim_name / (frame_name + std::string{
".png"});
371 "Failed to determine primary/secondary status.");
376 auto base_path = is_secondary ? tileset_paths_secondary_bin : tileset_paths_primary_bin;
378 std::filesystem::path path =
379 std::filesystem::path{base_path.value()} / snake_tileset_dir / porytiles_src / anim_dir / anim_json;
387 const std::filesystem::path artifact = project_root_ / key.
key();
388 return std::filesystem::exists(artifact);
397 std::set<std::string>,
398 "Failed to determine primary/secondary status.");
401 auto base_path = is_secondary ? tileset_paths_secondary_bin : tileset_paths_primary_bin;
404 const std::filesystem::path anim_path =
405 project_root_ / std::filesystem::path{base_path.value()} / snake_tileset_dir / porytiles_bin / anim_dir;
407 return scan_subdirectories(anim_path,
"Porymap animation", format_);
411 const std::string &tileset_name,
const std::string &anim_name)
const
416 std::set<std::string>,
417 "Failed to determine primary/secondary status.");
420 auto base_path = is_secondary ? tileset_paths_secondary_bin : tileset_paths_primary_bin;
423 const std::filesystem::path frame_dir = project_root_ / std::filesystem::path{base_path.value()} /
424 snake_tileset_dir / porytiles_bin / anim_dir / anim_name;
426 return scan_png_files(frame_dir,
"Porymap animation frame", format_);
435 std::set<std::string>,
436 "Failed to determine primary/secondary status.");
439 auto base_path = is_secondary ? tileset_paths_secondary_src : tileset_paths_primary_src;
442 const std::filesystem::path anim_path =
443 project_root_ / std::filesystem::path{base_path.value()} / snake_tileset_dir / porytiles_src / anim_dir;
445 return scan_subdirectories(anim_path,
"Porytiles animation", format_);
449 const std::string &tileset_name,
const std::string &anim_name)
const
454 std::set<std::string>,
455 "Failed to determine primary/secondary status.");
458 auto base_path = is_secondary ? tileset_paths_secondary_src : tileset_paths_primary_src;
461 const std::filesystem::path frame_dir = project_root_ / std::filesystem::path{base_path.value()} /
462 snake_tileset_dir / porytiles_src / anim_dir / anim_name;
464 return scan_png_files(frame_dir,
"Porytiles animation frame", format_);
#define PT_TRY_ASSIGN_CHAIN_ERR(var, expr, return_type,...)
Unwraps a ChainableResult, chaining a new error message on failure.
A type-safe wrapper for artifact keys.
const std::string & key() const
A result type that maintains a chainable sequence of errors for debugging and error reporting.
A smart string wrapper that preserves word structure for lossless case format conversion.
std::string to_snake_case() const
Outputs all words flattened and joined with underscores.
bool artifact_exists(const ArtifactKey &key) const override
Checks whether an artifact exists in the backing store for the given key.
ChainableResult< ArtifactKey > key_for_porymap_anim_params(const std::string &tileset_name) const override
Returns the key for Porymap animation parameters.
ChainableResult< std::set< std::string > > discover_porymap_anim_frames(const std::string &tileset_name, const std::string &anim_name) const override
Discovers the frame indices for a specific Porymap animation.
ChainableResult< ArtifactKey > key_for_middle_png(const std::string &tileset_name) const override
ChainableResult< ArtifactKey > key_for_metatile_attributes_bin(const std::string &tileset_name) const override
ChainableResult< ArtifactKey > key_for_top_png(const std::string &tileset_name) const override
ChainableResult< std::set< std::string > > discover_porytiles_anims(const std::string &tileset_name) const override
Discovers the names of all Porytiles animations available for a tileset.
ChainableResult< ArtifactKey > key_for_porymap_pal_n(const std::string &tileset_name, std::size_t index) const override
ChainableResult< ArtifactKey > key_for_porytiles_anim_params(const std::string &tileset_name) const override
Returns the key for the anim.json file (Porytiles animation configuration).
ChainableResult< std::set< std::string > > discover_porytiles_anim_frames(const std::string &tileset_name, const std::string &anim_name) const override
Discovers the frame indices for a specific Porytiles animation.
ChainableResult< ArtifactKey > key_for_bottom_png(const std::string &tileset_name) const override
ChainableResult< ArtifactKey > key_for_porytiles_anim_frame(const std::string &tileset_name, const std::string &anim_name, const std::string &frame_name) const override
ChainableResult< ArtifactKey > key_for_tiles_png(const std::string &tileset_name) const override
ChainableResult< ArtifactKey > key_for_attributes_csv(const std::string &tileset_name) const override
ChainableResult< std::set< std::string > > discover_porymap_anims(const std::string &tileset_name) const override
Discovers the names of all Porymap animations available for a tileset.
ChainableResult< ArtifactKey > key_for_metatiles_bin(const std::string &tileset_name) const override
ChainableResult< ArtifactKey > key_for_porymap_anim_frame(const std::string &tileset_name, const std::string &anim_name, const std::string &frame_name) const override
ChainableResult< ArtifactKey > key_for_porytiles_pal_n(const std::string &tileset_name, std::size_t index) const override
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.
std::string pal_filename(std::size_t pal_index)
Constructs a palette filename from a palette index.
DynamicCasedName extract_tileset_cased_name(const std::string &tileset_name)
Extracts the tileset short name and wraps it in a DynamicCasedName.
Utility functions for string manipulation and formatting.
#define PT_UNWRAP_TILESET_CONFIG_PTR(ptr, config, tileset_name, return_type)
Unwraps a tileset-scoped config value via pointer access, returning early if the value is not availab...