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_palettes{
"palettes"};
29const std::filesystem::path porymap_palettes{
"palettes"};
30const std::filesystem::path anim_json{
"anim.json"};
31const std::filesystem::path metatiles_bin{
"metatiles.bin"};
32const std::filesystem::path attributes_bin{
"metatile_attributes.bin"};
33const std::filesystem::path tiles_png{
"tiles.png"};
47 const std::filesystem::path &dir_path,
const std::string &artifact_type,
const TextFormatter *format)
49 if (!std::filesystem::exists(dir_path) || !std::filesystem::is_directory(dir_path)) {
50 return std::set<std::string>{};
53 std::set<std::string> result;
54 for (
const auto &entry : std::filesystem::directory_iterator{dir_path}) {
55 if (!entry.is_directory()) {
58 const std::string dir_name = entry.path().filename().string();
60 if (expected_snake != dir_name) {
62 "{} directory name '{}' must be snake_case (expected '{}')",
67 result.insert(dir_name);
84scan_png_files(
const std::filesystem::path &dir_path,
const std::string &artifact_type,
const TextFormatter *format)
86 if (!std::filesystem::exists(dir_path) || !std::filesystem::is_directory(dir_path)) {
87 return std::set<std::string>{};
90 std::set<std::string> result;
91 for (
const auto &entry : std::filesystem::directory_iterator{dir_path}) {
92 if (!entry.is_regular_file()) {
95 const auto &path = entry.path();
96 if (path.extension() !=
".png") {
99 const std::string stem = path.stem().string();
101 if (expected_snake != stem) {
103 "{} file name '{}' must be snake_case (expected '{}.png')",
126 "Failed to determine primary/secondary status.");
131 auto base_path = is_secondary ? tileset_paths_secondary_bin : tileset_paths_primary_bin;
133 std::filesystem::path path =
134 std::filesystem::path{base_path.value()} / snake_tileset_dir / porytiles_bin / metatiles_bin;
147 "Failed to determine primary/secondary status.");
152 auto base_path = is_secondary ? tileset_paths_secondary_bin : tileset_paths_primary_bin;
154 std::filesystem::path path =
155 std::filesystem::path{base_path.value()} / snake_tileset_dir / porytiles_bin / attributes_bin;
167 "Failed to determine primary/secondary status.");
172 auto base_path = is_secondary ? tileset_paths_secondary_bin : tileset_paths_primary_bin;
174 std::filesystem::path path =
175 std::filesystem::path{base_path.value()} / snake_tileset_dir / porytiles_bin / tiles_png;
188 "Failed to determine primary/secondary status.");
193 auto base_path = is_secondary ? tileset_paths_secondary_bin : tileset_paths_primary_bin;
195 std::filesystem::path path = std::filesystem::path{base_path.value()} / snake_tileset_dir / porytiles_bin /
202 const std::string &tileset_name,
const std::string &anim_name,
const std::string &frame_name)
const
209 "Failed to determine primary/secondary status.");
214 auto base_path = is_secondary ? tileset_paths_secondary_bin : tileset_paths_primary_bin;
216 std::filesystem::path path = std::filesystem::path{base_path.value()} / snake_tileset_dir / porytiles_bin /
217 anim_dir / anim_name / (frame_name + std::string{
".png"});
226 std::filesystem::path path = porytiles_generated_include / snake_tileset_dir / generated_anim_code_header;
239 "Failed to determine primary/secondary status.");
244 auto base_path = is_secondary ? tileset_paths_secondary_bin : tileset_paths_primary_bin;
246 std::filesystem::path path =
247 std::filesystem::path{base_path.value()} / snake_tileset_dir / porytiles_src / bottom_png;
260 "Failed to determine primary/secondary status.");
265 auto base_path = is_secondary ? tileset_paths_secondary_bin : tileset_paths_primary_bin;
267 std::filesystem::path path =
268 std::filesystem::path{base_path.value()} / snake_tileset_dir / porytiles_src / middle_png;
280 "Failed to determine primary/secondary status.");
285 auto base_path = is_secondary ? tileset_paths_secondary_bin : tileset_paths_primary_bin;
287 std::filesystem::path path = std::filesystem::path{base_path.value()} / snake_tileset_dir / porytiles_src / top_png;
300 "Failed to determine primary/secondary status.");
305 auto base_path = is_secondary ? tileset_paths_secondary_bin : tileset_paths_primary_bin;
307 std::filesystem::path path =
308 std::filesystem::path{base_path.value()} / snake_tileset_dir / porytiles_src / attributes_csv;
321 "Failed to determine primary/secondary status.");
326 auto base_path = is_secondary ? tileset_paths_secondary_bin : tileset_paths_primary_bin;
328 std::filesystem::path path = std::filesystem::path{base_path.value()} / snake_tileset_dir / porytiles_src /
335 const std::string &tileset_name,
const std::string &anim_name,
const std::string &frame_name)
const
342 "Failed to determine primary/secondary status.");
347 auto base_path = is_secondary ? tileset_paths_secondary_bin : tileset_paths_primary_bin;
349 std::filesystem::path path = std::filesystem::path{base_path.value()} / snake_tileset_dir / porytiles_src /
350 anim_dir / anim_name / (frame_name + std::string{
".png"});
363 "Failed to determine primary/secondary status.");
368 auto base_path = is_secondary ? tileset_paths_secondary_bin : tileset_paths_primary_bin;
370 std::filesystem::path path =
371 std::filesystem::path{base_path.value()} / snake_tileset_dir / porytiles_src / anim_dir / anim_json;
379 const std::filesystem::path artifact = project_root_ / key.
key();
380 return std::filesystem::exists(artifact);
389 std::set<std::string>,
390 "Failed to determine primary/secondary status.");
393 auto base_path = is_secondary ? tileset_paths_secondary_bin : tileset_paths_primary_bin;
396 const std::filesystem::path anim_path =
397 project_root_ / std::filesystem::path{base_path.value()} / snake_tileset_dir / porytiles_bin / anim_dir;
399 return scan_subdirectories(anim_path,
"Porymap animation", format_);
403 const std::string &tileset_name,
const std::string &anim_name)
const
408 std::set<std::string>,
409 "Failed to determine primary/secondary status.");
412 auto base_path = is_secondary ? tileset_paths_secondary_bin : tileset_paths_primary_bin;
415 const std::filesystem::path frame_dir = project_root_ / std::filesystem::path{base_path.value()} /
416 snake_tileset_dir / porytiles_bin / anim_dir / anim_name;
418 return scan_png_files(frame_dir,
"Porymap animation frame", format_);
427 std::set<std::string>,
428 "Failed to determine primary/secondary status.");
431 auto base_path = is_secondary ? tileset_paths_secondary_src : tileset_paths_primary_src;
434 const std::filesystem::path anim_path =
435 project_root_ / std::filesystem::path{base_path.value()} / snake_tileset_dir / porytiles_src / anim_dir;
437 return scan_subdirectories(anim_path,
"Porytiles animation", format_);
441 const std::string &tileset_name,
const std::string &anim_name)
const
446 std::set<std::string>,
447 "Failed to determine primary/secondary status.");
450 auto base_path = is_secondary ? tileset_paths_secondary_src : tileset_paths_primary_src;
453 const std::filesystem::path frame_dir = project_root_ / std::filesystem::path{base_path.value()} /
454 snake_tileset_dir / porytiles_src / anim_dir / anim_name;
456 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.
ChainableResult< ArtifactKey > key_for_porytiles_palette_n(const std::string &tileset_name, std::size_t index) const override
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_porymap_palette_n(const std::string &tileset_name, std::size_t index) 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_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
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.
DynamicCasedName extract_tileset_cased_name(const std::string &tileset_name)
Extracts the tileset short name and wraps it in a DynamicCasedName.
std::string palette_filename(std::size_t palette_index)
Constructs a palette filename from a palette index.
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...