9#include "fruit/fruit.h"
61 :
Command{parent_app, kCommandName, kCommandDesc, kCommandGroup}
64 cmd.add_option(
"<tileset-name>", tileset_name_,
"Name of the tileset to compile")->required();
74 const bool no_color = !isatty(STDERR_FILENO);
75 fruit::Injector injector{di::get_formatter_component, no_color};
79 auto stderr_diag = std::make_unique<StderrStyledUserDiagnostics>(text_formatter);
81 std::filesystem::path project_root = project_root_opt_.
project_root();
82 std::filesystem::path fieldmap_header_root_relative{
"include/fieldmap.h"};
83 std::filesystem::path behaviors_header_root_relative{
"include/constants/metatile_behaviors.h"};
84 std::filesystem::path global_fieldmap_header_root_relative{
"include/global.fieldmap.h"};
87 std::vector<std::unique_ptr<ConfigProvider>> providers{};
88 providers.push_back(std::make_unique<CliOptionProvider>(cli_storage_));
89 auto yaml_provider = std::make_unique<YamlFileProvider>(text_formatter, stderr_diag.get(), project_root);
90 auto *yaml_provider_ptr = yaml_provider.get();
91 providers.push_back(std::move(yaml_provider));
93 std::make_unique<HeaderDefineProvider>(project_root, fieldmap_header_root_relative, text_formatter));
94 providers.push_back(std::make_unique<MetatilesHeaderProvider>(project_root, text_formatter));
95 providers.push_back(std::make_unique<DefaultProvider>());
99 if (yaml_provider_ptr->preload_and_validate(ConfigScopeType::tileset, tileset_name_)) {
101 "Configuration validation failed for tileset '{}'.",
FormatParam{tileset_name_, Style::bold}}};
102 stderr_diag->fatal(validation_err);
103 throw CLI::RuntimeError{1};
107 auto attr_size_check = config.metatile_attr_size(ConfigScopeType::tileset, tileset_name_);
108 if (!attr_size_check.has_value()) {
109 stderr_diag->fatal(attr_size_check);
110 throw CLI::RuntimeError{1};
112 const std::size_t metatile_attr_size = attr_size_check.value().value();
115 auto get_filter_patterns =
117 if (result.has_value()) {
118 return std::move(result).value().value();
120 stderr_diag->fatal(result);
126 get_filter_patterns(config.diagnostic_warnings_exclude(ConfigScopeType::tileset, tileset_name_)),
127 get_filter_patterns(config.diagnostic_warnings_include(ConfigScopeType::tileset, tileset_name_))};
130 get_filter_patterns(config.diagnostic_remarks_exclude(ConfigScopeType::tileset, tileset_name_)),
131 get_filter_patterns(config.diagnostic_remarks_include(ConfigScopeType::tileset, tileset_name_))};
134 auto diag = std::make_unique<FilteredUserDiagnostics>(
135 text_formatter, stderr_diag.get(), std::move(warning_filter), std::move(remark_filter));
137 std::unique_ptr<TilePrinter> tile_printer = std::make_unique<AsciiTilePrinter>(text_formatter);
138 std::unique_ptr<PalettePrinter> pal_printer = std::make_unique<ColorPalettePrinter>(text_formatter);
152 TilesetCompiler compiler{&config, text_formatter, diag.get(), tile_printer.get(), pal_printer.get()};
156 project_root / behaviors_header_root_relative, text_formatter, diag.get()};
173 &tileset_anims_modifier};
176 BaseGameDetector base_game_detector{project_root, text_formatter, diag.get()};
177 auto base_game_result = base_game_detector.
detect();
178 if (!base_game_result.has_value()) {
179 diag->fatal(base_game_result);
180 throw CLI::RuntimeError{1};
182 const BaseGame base_game = base_game_result.value();
185 std::unique_ptr<HeaderTerrainTypeMapProvider> terrain_provider;
186 std::unique_ptr<HeaderEncounterTypeMapProvider> encounter_provider;
187 if (base_game == BaseGame::pokefirered) {
188 terrain_provider = std::make_unique<HeaderTerrainTypeMapProvider>(
189 project_root / global_fieldmap_header_root_relative, text_formatter, diag.get());
190 encounter_provider = std::make_unique<HeaderEncounterTypeMapProvider>(
191 project_root / global_fieldmap_header_root_relative, text_formatter, diag.get());
196 text_formatter, &behavior_map_provider, base_game, terrain_provider.get(), encounter_provider.get()};
200 project_root, &config, &metadata_provider, text_formatter, diag.get()};
207 &attributes_csv_loader,
223 &anim_code_generator,
224 &behavior_map_provider,
225 terrain_provider.get(),
226 encounter_provider.get()};
229 &checksum_provider, &metadata_provider, &key_provider, &artifact_reader, &artifact_writer, diag.get()};
232 if (!metadata_provider.exists(tileset_name_)) {
234 "Tileset '{}' does not exist. Create or import it first.",
FormatParam{tileset_name_, Style::bold}}};
235 diag->fatal(not_found_err);
236 throw CLI::RuntimeError{1};
240 auto is_secondary_result = metadata_provider.is_secondary(tileset_name_);
241 if (!is_secondary_result.has_value()) {
242 diag->fatal(is_secondary_result);
243 throw CLI::RuntimeError{1};
247 if (is_secondary_result.value()) {
252 &layout_metadata_provider,
257 compile_result = compile_use_case.compile(tileset_name_);
261 &repo, &compiler, &metadata_provider, &tileset_manager, &config, &config, diag.get()};
262 compile_result = compile_use_case.compile(tileset_name_);
268 diag->fatal(fail_result);
269 throw CLI::RuntimeError{1};
274 static constexpr auto kCommandName =
"compile-tileset";
275 static constexpr auto kCommandDesc =
276 "Compile a tileset -- update the Porymap assets to match the Porytiles assets.";
277 static constexpr auto kCommandGroup =
"COMMANDS";
278 std::string tileset_name_;
Command is an abstract class that provides basic command functionality for the Porytiles CLI driver.
CLI::App & get_app() const
CompileTilesetCommand(CLI::App &parent_app)
std::filesystem::path project_root() const
void RegisterOpt(CLI::App &app) override
Generates C header code for tileset animations.
Parses C code to extract tileset animation parameters using callback chain discovery.
Parses and writes animation configuration JSON files (anim.json).
A service that loads metatile attributes from a CSV file.
Detects the base game of a decompilation project.
ChainableResult< BaseGame > detect() const
Detects the base game for the project.
A result type that maintains a chainable sequence of errors for debugging and error reporting.
bool has_value() const
Checks whether the result contains a success value.
Use case for compiling a primary Tileset.
Use case for compiling a secondary Tileset.
Regex-based include/exclude filter for diagnostic tags.
Appends INCBIN declarations for Porytiles-managed tileset assets.
An implementation of FilePalLoader that loads palettes from JASC-PAL (Paintshop Pro) pal files.
An implementation of FilePalSaver that saves palettes to JASC-PAL (Paintshop Pro) pal files.
A Config implementation that lazily pulls a config value by consulting multiple priority-ordered back...
An image loader that reads PNG files to create an Image with an index pixel type.
An image saver that saves PNG files from an Image with an index pixel type.
An image loader that reads PNG files to create an Image with an Rgba32 pixel type.
An image saver that saves PNG files from an Image with an Rgba32 pixel type.
Pokeemerald project filesystem-based implementation of ArtifactChecksumProvider.
Manages Porytiles-owned tilesets via TilesetManifest JSON files.
Modifies tileset_anims.c to include Porytiles-managed animation code headers.
Provides a pokeemerald project filesystem-based implementation for TilesetArtifactKeyProvider.
Provides a filesystem-based implementation for TilesetArtifactReader.
Provides a filesystem-based implementation for TilesetArtifactWriter.
Abstract base class for applying text styling with context-aware formatting.
Service that compiles a Tileset (primary or secondary).
Repository interface for the Tileset aggregate root.
BaseGame
Identifies the target base game for a decompilation project.
void register_config_options(CLI::App &app, CliOptionStorage &storage)
Registers all config options with a CLI11 App.
Storage struct for CLI option values.