Porytiles
Loading...
Searching...
No Matches
porytiles_tileset_component.cpp
Go to the documentation of this file.
2
3#include <format>
4
11
12namespace porytiles {
13
14void PorytilesTilesetComponent::insert_attribute(std::size_t metatile_id, MetatileAttribute attribute)
15{
16 if (metatile_attributes_.contains(metatile_id)) {
17 panic("id " + std::to_string(metatile_id) + " already exists in attribute map");
18 }
19 metatile_attributes_.insert({metatile_id, std::move(attribute)});
20}
21
22std::optional<MetatileAttribute> PorytilesTilesetComponent::get_attribute(std::size_t metatile_id) const
23{
24 if (metatile_attributes_.contains(metatile_id)) {
25 return metatile_attributes_.at(metatile_id);
26 }
27 return std::nullopt;
28}
29
31{
32 const auto it = prior_pin_column_states_.find(role);
33 return it != prior_pin_column_states_.end() ? it->second : PriorPinColumnState::no_csv;
34}
35
37{
38 prior_pin_column_states_[role] = state;
39}
40
42{
43 if (palette_index >= palette::num_palettes) {
44 panic(std::format("invalid palette index {}: out of range", palette_index));
45 }
46 palettes_[palette_index] = std::move(palette);
47}
48
49const std::optional<Palette<Rgba32, palette::max_size>> &
50PorytilesTilesetComponent::palette_at(std::size_t palette_index) const
51{
52 if (palette_index >= palette::num_palettes) {
53 panic(std::format("invalid palette index {}: out of range", palette_index));
54 }
55 return palettes_[palette_index];
56}
57
59{
60 return bottom_.size() == 0 && middle_.size() == 0 && top_.size() == 0;
61}
62
64{
65 // Pre-check: all three images must have identical dimensions
66 if (bottom_.width() != middle_.width() || bottom_.width() != top_.width() || bottom_.height() != middle_.height() ||
67 bottom_.height() != top_.height()) {
68 panic(
69 std::format(
70 "layer images have mismatched dimensions: bottom={}x{}, middle={}x{}, top={}x{}",
71 bottom_.width(),
72 bottom_.height(),
73 middle_.width(),
74 middle_.height(),
75 top_.width(),
76 top_.height()));
77 }
78
79 const std::size_t width = bottom_.width();
80 const std::size_t height = bottom_.height();
81
82 // Iterate over each 8x8 region
83 for (std::size_t region_row = 0; region_row < height; region_row += tile::side_length_pix) {
84 for (std::size_t region_col = 0; region_col < width; region_col += tile::side_length_pix) {
85 bool bottom_has_opaque = false;
86 bool middle_has_opaque = false;
87 bool top_has_opaque = false;
88
89 // Check each pixel in the current 8x8 region
90 for (std::size_t row = region_row; row < region_row + tile::side_length_pix && row < height; ++row) {
91 for (std::size_t col = region_col; col < region_col + tile::side_length_pix && col < width; ++col) {
92 if (!bottom_.at(row, col).is_transparent(extrinsic)) {
93 bottom_has_opaque = true;
94 }
95 if (!middle_.at(row, col).is_transparent(extrinsic)) {
96 middle_has_opaque = true;
97 }
98 if (!top_.at(row, col).is_transparent(extrinsic)) {
99 top_has_opaque = true;
100 }
101
102 // Early exit if all three layers have opaque pixels in this region
103 if (bottom_has_opaque && middle_has_opaque && top_has_opaque) {
104 return LayerMode::triple;
105 }
106 }
107 }
108 }
109 }
110
111 // If no region had opaque pixels on all three layers, it's dual mode
112 return LayerMode::dual;
113}
114
116{
117 const std::string &name = anim.name();
118 if (anims_.contains(name)) {
119 panic("animation '" + name + "' already exists in PorytilesTilesetComponent");
120 }
121 anims_.insert({name, std::move(anim)});
122}
123
124} // namespace porytiles
A complete tileset animation with name, configuration, and frame data.
Definition animation.hpp:89
const std::string & name() const
Definition animation.hpp:97
A result type that maintains a chainable sequence of errors for debugging and error reporting.
The attributes of a single metatile, modeled as a map of named field values.
A generic palette container for colors that support transparency checking.
Definition palette.hpp:45
const std::optional< Palette< Rgba32, palette::max_size > > & palette_at(std::size_t palette_index) const
void set_palette(std::size_t palette_index, Palette< Rgba32, palette::max_size > palette)
std::optional< MetatileAttribute > get_attribute(std::size_t metatile_id) const
PriorPinColumnState prior_pin_column_state(FieldRole role) const
Returns the recorded prior pin-column state for a role, or no_csv when none was recorded.
ChainableResult< LayerMode > detect_layer_mode(const Rgba32 &extrinsic) const
void insert_attribute(std::size_t metatile_id, MetatileAttribute attribute)
Insert a MetatileAttribute to the end of the attribute vector.
Represents a 32-bit RGBA color.
Definition rgba32.hpp:21
std::string name
constexpr std::size_t num_palettes
Definition palette.hpp:21
constexpr std::size_t side_length_pix
void panic(const StringViewSourceLoc &s)
Unconditionally terminates the program with a panic message.
Definition panic.cpp:43
PriorPinColumnState
What an attributes.csv (if any) said about a role's pin column when this component was loaded.
FieldRole
Semantic roles a schema field can carry beyond holding a plain per-metatile value.