14const std::filesystem::path primary_tileset_rel_path = std::filesystem::path{
"data"} /
"tilesets" /
"primary";
15const std::filesystem::path secondary_tileset_rel_path = std::filesystem::path{
"data"} /
"tilesets" /
"secondary";
17std::filesystem::path get_tileset_path(
const std::string &tileset_name,
const std::filesystem::path &project_root)
19 if (std::filesystem::exists(project_root / primary_tileset_rel_path / tileset_name)) {
20 return project_root / primary_tileset_rel_path / tileset_name;
22 if (std::filesystem::exists(project_root / secondary_tileset_rel_path / tileset_name)) {
23 return project_root / secondary_tileset_rel_path / tileset_name;
25 panic(fmt::format(
"tileset '{}' does not exist", tileset_name));
28const std::filesystem::path porytiles_directory{
"porytiles"};
29const std::filesystem::path bottom_png{
"bottom.png"};
30const std::filesystem::path middle_png{
"middle.png"};
31const std::filesystem::path top_png{
"top.png"};
32const std::filesystem::path attributes_csv{
"attributes.csv"};
33const std::filesystem::path anim{
"anim"};
34const std::filesystem::path pal_overrides{
"palette-overrides"};
35const std::filesystem::path metatiles_bin{
"metatiles.bin"};
36const std::filesystem::path metatile_attributes_bin{
"metatile_attributes.bin"};
37const std::filesystem::path tiles_png{
"tiles.png"};
38const std::filesystem::path palettes{
"palettes"};
39const std::filesystem::path config{
"porytiles.yaml"};
40const std::filesystem::path local_config{
"porytiles.local.yaml"};
49 const auto tileset_path = get_tileset_path(tileset_name, project_root_);
51 switch (artifact.
type()) {
54 return ArtifactKey{tileset_path / porytiles_directory / bottom_png};
56 return ArtifactKey{tileset_path / porytiles_directory / middle_png};
58 return ArtifactKey{tileset_path / porytiles_directory / top_png};
60 return ArtifactKey{tileset_path / porytiles_directory / attributes_csv};
62 if (!artifact.
name().has_value()) {
63 panic(
"missing porytiles anim frame name");
65 if (!artifact.
index().has_value()) {
66 panic(
"missing porytiles anim frame index");
68 const auto anim_name = artifact.
name().value();
69 const auto frame_num = artifact.
index().value();
70 return ArtifactKey{tileset_path / porytiles_directory / anim / anim_name / fmt::format(
"{:02}.png", frame_num)};
73 if (!artifact.
index().has_value()) {
74 panic(
"missing pal override index");
76 const auto override_index = artifact.
index().value();
78 tileset_path / porytiles_directory / pal_overrides / fmt::format(
"{:02}.pal", override_index)};
85 return ArtifactKey{tileset_path / metatile_attributes_bin};
89 if (!artifact.
name().has_value()) {
90 panic(
"missing porymap anim frame name");
92 if (!artifact.
index().has_value()) {
93 panic(
"missing porymap anim frame index");
95 const auto anim_name = artifact.
name().value();
96 const auto frame_num = artifact.
index().value();
97 return ArtifactKey{tileset_path / anim / anim_name / fmt::format(
"{:02}.png", frame_num)};
100 if (!artifact.
index().has_value()) {
101 panic(
"missing pal index");
103 const auto pal_index = artifact.
index().value();
104 return ArtifactKey{tileset_path / palettes / fmt::format(
"{:02}.pal", pal_index)};
115 panic(
"unhandled TilesetArtifact::Type");
121 const std::filesystem::path artifact{key.
key()};
122 return std::filesystem::exists(artifact);
127 if (std::filesystem::exists(project_root_ / primary_tileset_rel_path / tileset_name)) {
130 if (std::filesystem::exists(project_root_ / secondary_tileset_rel_path / tileset_name)) {
138 const auto tileset_path = get_tileset_path(tileset_name, project_root_);
139 const auto anims_dir = tileset_path / porytiles_directory / anim;
141 std::set<std::string> anim_names;
143 if (!std::filesystem::exists(anims_dir) || !std::filesystem::is_directory(anims_dir)) {
147 for (
const auto &entry : std::filesystem::directory_iterator(anims_dir)) {
148 if (!entry.is_directory()) {
154 const auto frame_00_path = entry.path() /
"00.png";
155 if (!std::filesystem::exists(frame_00_path)) {
160 const auto anim_name = entry.path().filename().string();
161 anim_names.insert(anim_name);
168 const std::string &tileset_name,
const std::string &anim_name)
const
170 const auto tileset_path = get_tileset_path(tileset_name, project_root_);
171 const auto anim_dir = tileset_path / porytiles_directory / anim / anim_name;
173 std::set<int> frame_indices;
175 if (!std::filesystem::exists(anim_dir) || !std::filesystem::is_directory(anim_dir)) {
176 return frame_indices;
179 for (
const auto &entry : std::filesystem::directory_iterator(anim_dir)) {
180 if (!entry.is_regular_file()) {
185 const auto filename = entry.path().filename().string();
187 if (filename.length() != 6 || !filename.ends_with(
".png")) {
193 if (filename ==
"00.png") {
198 const auto frame_str = filename.substr(0, 2);
199 if (!std::isdigit(frame_str[0]) || !std::isdigit(frame_str[1])) {
203 const int frame_index = std::stoi(frame_str);
204 frame_indices.insert(frame_index);
207 return frame_indices;
212 const auto tileset_path = get_tileset_path(tileset_name, project_root_);
213 const auto anims_dir = tileset_path / anim;
215 std::set<std::string> anim_names;
217 if (!std::filesystem::exists(anims_dir) || !std::filesystem::is_directory(anims_dir)) {
221 for (
const auto &entry : std::filesystem::directory_iterator(anims_dir)) {
222 if (!entry.is_directory()) {
228 const auto frame_00_path = entry.path() /
"00.png";
229 if (!std::filesystem::exists(frame_00_path)) {
234 const auto anim_name = entry.path().filename().string();
235 anim_names.insert(anim_name);
242 const std::string &tileset_name,
const std::string &anim_name)
const
244 const auto tileset_path = get_tileset_path(tileset_name, project_root_);
245 const auto anim_dir = tileset_path / anim / anim_name;
247 std::set<int> frame_indices;
249 if (!std::filesystem::exists(anim_dir) || !std::filesystem::is_directory(anim_dir)) {
250 return frame_indices;
253 for (
const auto &entry : std::filesystem::directory_iterator(anim_dir)) {
254 if (!entry.is_regular_file()) {
259 const auto filename = entry.path().filename().string();
261 if (filename.length() != 6 || !filename.ends_with(
".png")) {
267 if (filename ==
"00.png") {
272 const auto frame_str = filename.substr(0, 2);
273 if (!std::isdigit(frame_str[0]) || !std::isdigit(frame_str[1])) {
277 const int frame_index = std::stoi(frame_str);
278 frame_indices.insert(frame_index);
281 return frame_indices;
284[[nodiscard]] std::filesystem::path
287 return get_tileset_path(tileset_name, project_root_);
A type-safe wrapper for artifact keys.
const std::string & key() const
Gets the underlying string value.
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.
std::filesystem::path tileset_root(const std::string &tileset_name) const
Returns the filesystem path to the root directory of a tileset.
ArtifactKey key_for(const std::string &tileset_name, const TilesetArtifact &artifact) const override
Constructs a key for a given tileset artifact.
std::set< int > 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.
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.
bool artifact_exists(const ArtifactKey &key) const override
Checks whether an artifact exists in the backing store for the given key.
std::set< int > 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.
bool tileset_exists(const std::string &tileset_name) const override
Checks whether a tileset exists in the backing store for the given tileset name.
Represents a Pokémon Generation III decomp tileset artifact with type and optional metadata.
Type type() const
Gets the artifact type.
std::optional< std::string > name() const
Gets the artifact name if present.
@ porytiles_anim_frame
Animation frame PNG for Porytiles-format animation.
@ attributes_csv
CSV file containing metatile attribute overrides.
@ middle_png
Middle layer PNG input image.
@ metatile_attributes_bin
Metatile attributes output for Porymap.
@ bottom_png
Bottom layer PNG input image.
@ top_png
Top layer PNG input image.
@ pal_n
JASC palette data file.
@ metatiles_bin
Metatile data output for Porymap.
@ pal_override_n
JASC palette override file.
@ tiles_png
Combined tile sheet PNG output for Porymap.
@ local_config
Tileset configuration YAML file.
@ porymap_anim_frame
Animation frame PNG for Porymap-format animation.
std::optional< unsigned int > index() const
Gets the artifact index if present.
void panic(const StringViewSourceLoc &s)
Unconditionally terminates the program with a panic message.