Porytiles
Loading...
Searching...
No Matches
layer_mode_converter.cpp
Go to the documentation of this file.
2
11
12namespace porytiles {
13
15{
17 layer_mode, component.detect_layer_mode(), std::vector<TilemapEntry>, "Layer mode detection failed.");
18 if (layer_mode == LayerMode::triple) {
19 // No-op case
20 return component.metatiles_bin();
21 }
22
23 const auto &metatiles_bin = component.metatiles_bin();
24 const auto &metatile_attributes = component.metatile_attributes_bin();
25
26 const std::size_t num_metatiles = metatiles_bin.size() / metatile::entries_per_metatile_dual;
27
28 std::vector<TilemapEntry> result;
29 result.reserve(num_metatiles * metatile::entries_per_metatile_triple);
30
31 // Create a transparent entry (tile_index = 0, pal_index = 0, no flips)
32 const TilemapEntry transparent{0, 0, false, false};
33
34 for (std::size_t i = 0; i < num_metatiles; ++i) {
35 // Number of transparent entries to insert
36 constexpr std::size_t transparent_entries = 4;
37 const auto &attribute = metatile_attributes[i];
38 const std::size_t input_offset = i * metatile::entries_per_metatile_dual;
39
40 switch (attribute.layer_type()) {
42 // Insert 4 transparent entries at the start
43 for (std::size_t j = 0; j < transparent_entries; ++j) {
44 result.push_back(transparent);
45 }
46 // Copy the 8 original entries
47 for (std::size_t j = 0; j < metatile::entries_per_metatile_dual; ++j) {
48 result.push_back(metatiles_bin[input_offset + j]);
49 }
50 break;
51
53 // Copy the 8 original entries
54 for (std::size_t j = 0; j < metatile::entries_per_metatile_dual; ++j) {
55 result.push_back(metatiles_bin[input_offset + j]);
56 }
57 // Insert 4 transparent entries at the end
58 for (std::size_t j = 0; j < transparent_entries; ++j) {
59 result.push_back(transparent);
60 }
61 break;
62
64 // Copy the first 4 entries
65 for (std::size_t j = 0; j < transparent_entries; ++j) {
66 result.push_back(metatiles_bin[input_offset + j]);
67 }
68 // Insert 4 transparent entries in the middle
69 for (std::size_t j = 0; j < transparent_entries; ++j) {
70 result.push_back(transparent);
71 }
72 // Copy the last 4 entries
73 for (std::size_t j = transparent_entries; j < metatile::entries_per_metatile_dual; ++j) {
74 result.push_back(metatiles_bin[input_offset + j]);
75 }
76 break;
77 }
78 }
79
80 return result;
81}
82
83[[nodiscard]] std::vector<TilemapEntry> LayerModeConverter::dual_layerize(
84 const std::vector<TilemapEntry> &entries, const std::vector<Metatile<Rgba32>> &source_metatiles)
85{
86 const std::size_t expected_entries_size = source_metatiles.size() * metatile::entries_per_metatile_triple;
87 if (entries.size() != expected_entries_size) {
88 panic(
89 "entries vector size " + std::to_string(entries.size()) + " did not match expected size " +
90 std::to_string(expected_entries_size));
91 }
92
93 std::vector<TilemapEntry> result;
94 result.reserve(source_metatiles.size() * metatile::entries_per_metatile_dual);
95
96 for (std::size_t i = 0; i < source_metatiles.size(); ++i) {
97 const auto &metatile = source_metatiles[i];
98 const std::size_t input_offset = i * metatile::entries_per_metatile_triple;
99
100 // Check precondition: no metatile should have implied LayerMode::triple
101 const LayerMode layer_mode = metatile.infer_layer_mode(extrinsic_transparency_);
102 if (layer_mode == LayerMode::triple) {
103 panic("metatile " + std::to_string(i) + " has implied LayerMode::triple, cannot dual_layerize");
104 }
105
106 // Infer the layer type for this metatile using extrinsic transparency
107 const LayerType layer_type = metatile.infer_layer_type(extrinsic_transparency_);
108
109 switch (layer_type) {
111 // Skip first 4 transparent entries, copy next 8
112 for (std::size_t j = 4; j < metatile::entries_per_metatile_triple; ++j) {
113 result.push_back(entries[input_offset + j]);
114 }
115 break;
116
118 // Copy first 8 entries, skip last 4 transparent
119 for (std::size_t j = 0; j < metatile::entries_per_metatile_dual; ++j) {
120 result.push_back(entries[input_offset + j]);
121 }
122 break;
123
124 case LayerType::split:
125 // Copy first 4, skip middle 4 transparent, copy last 4
126 for (std::size_t j = 0; j < 4; ++j) {
127 result.push_back(entries[input_offset + j]);
128 }
129 for (std::size_t j = 8; j < metatile::entries_per_metatile_triple; ++j) {
130 result.push_back(entries[input_offset + j]);
131 }
132 break;
133 }
134 }
135
136 return result;
137}
138
139} // namespace porytiles
#define PT_TRY_ASSIGN_CHAIN_ERR(var, expr, return_type,...)
Unwraps a ChainableResult, chaining a new error message on failure.
A result type that maintains a chainable sequence of errors for debugging and error reporting.
std::vector< TilemapEntry > dual_layerize(const std::vector< TilemapEntry > &entries, const std::vector< Metatile< Rgba32 > > &source_metatiles)
Converts a tileset from triple-layer format to dual-layer format.
ChainableResult< std::vector< TilemapEntry > > triple_layerize(const PorymapTilesetComponent &component)
Converts a tileset component to triple-layer format.
The core tileset entity - a 2x2 grid of PixelTile objects arranged into three layers.
Definition metatile.hpp:186
const std::vector< TilemapEntry > & metatiles_bin() const
ChainableResult< LayerMode > detect_layer_mode() const
const std::vector< MetatileAttribute > & metatile_attributes_bin() const
Represents a tilemap entry referencing a tile with palette and flip attributes.
constexpr std::size_t entries_per_metatile_dual
Definition metatile.hpp:20
constexpr std::size_t entries_per_metatile_triple
Definition metatile.hpp:21
LayerMode
Specifies whether a metatile uses dual-layer or triple-layer mode.
Definition layer.hpp:21
void panic(const StringViewSourceLoc &s)
Unconditionally terminates the program with a panic message.
Definition panic.cpp:43
LayerType
Specifies which layers of a metatile are used for rendering.
Definition layer.hpp:97