8#include "fruit/fruit.h"
62 cmd.add_option(
"<tileset-name>", tileset_name_,
"Name of the tileset to create (e.g., gTileset_MyTileset)")
64 cmd.add_flag(
"--secondary", secondary_,
"Create a secondary tileset instead of a primary.");
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);
153 project_root / behaviors_header_root_relative, text_formatter, diag.get()};
167 &tileset_anims_modifier};
170 BaseGameDetector base_game_detector{project_root, text_formatter, diag.get()};
171 auto base_game_result = base_game_detector.
detect();
172 if (!base_game_result.has_value()) {
173 diag->fatal(base_game_result);
174 throw CLI::RuntimeError{1};
176 const BaseGame base_game = base_game_result.value();
179 std::unique_ptr<HeaderTerrainTypeMapProvider> terrain_provider;
180 std::unique_ptr<HeaderEncounterTypeMapProvider> encounter_provider;
181 if (base_game == BaseGame::pokefirered) {
182 terrain_provider = std::make_unique<HeaderTerrainTypeMapProvider>(
183 project_root / global_fieldmap_header_root_relative, text_formatter, diag.get());
184 encounter_provider = std::make_unique<HeaderEncounterTypeMapProvider>(
185 project_root / global_fieldmap_header_root_relative, text_formatter, diag.get());
190 text_formatter, &behavior_map_provider, base_game, terrain_provider.get(), encounter_provider.get()};
194 project_root, &config, &metadata_provider, text_formatter, diag.get()};
201 &attributes_csv_loader,
217 &anim_code_generator,
218 &behavior_map_provider,
219 terrain_provider.get(),
220 encounter_provider.get()};
223 &checksum_provider, &metadata_provider, &key_provider, &artifact_reader, &artifact_writer, diag.get()};
227 TilesetCompiler compiler{&config, text_formatter, diag.get(), tile_printer.get(), pal_printer.get()};
240 &layout_metadata_provider,
245 create_result = create_use_case.create(tileset_name_);
249 &creator, &compiler, &repo, &metadata_provider, &tileset_manager, &config, &config, diag.get()};
250 create_result = create_use_case.create(tileset_name_);
256 diag->fatal(fail_result);
257 throw CLI::RuntimeError{1};
262 static constexpr auto kCommandName =
"create-tileset";
263 static constexpr auto kCommandDesc =
"Create a new Porytiles-managed tileset from scratch.";
264 static constexpr auto kCommandGroup =
"COMMANDS";
265 std::string tileset_name_;
266 bool secondary_ =
false;
Command is an abstract class that provides basic command functionality for the Porytiles CLI driver.
CLI::App & get_app() const
CreateTilesetCommand(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 creating a new primary Tileset from scratch.
Use case for creating a new secondary Tileset from scratch.
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).
Domain service for creating new tilesets from scratch.
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.