|
Porytiles
|
A workspace for managing canonical IndexPixel tiles destined for tiles.png output. More...
#include <tiles_png_workspace.hpp>
Public Member Functions | |
| TilesPngWorkspace (std::size_t capacity) | |
| Constructs a TilesPngWorkspace with a specified capacity, initializing all slots with transparent tiles. | |
| TilesPngWorkspace (const Image< IndexPixel > &img, std::size_t capacity) | |
| Constructs a TilesPngWorkspace from an existing IndexPixel image and capacity. | |
| std::size_t | insert_tile (const CanonicalPixelTile< IndexPixel > &tile) |
| Attempts to insert a non-transparent tile into the workspace at the current cursor position. | |
| std::optional< std::size_t > | first_occurrence_of (const CanonicalPixelTile< IndexPixel > &tile) const |
| Finds the first occurrence index of a given canonical tile in the workspace. | |
| std::optional< std::size_t > | first_occurrence_of_by_color (const CanonicalPixelTile< IndexPixel > &tile, const Palette< Rgba32, pal::max_size > &palette) const |
| Finds the first occurrence of a tile using color-equivalence comparison. | |
| CanonicalPixelTile< IndexPixel > | tile_at (std::size_t index) const |
| Retrieves the canonical tile at the specified index in the workspace. | |
| Image< IndexPixel > | export_image (ExportFlipMode flip_mode=ExportFlipMode::canonical, ExportTrimMode trim_mode=ExportTrimMode::trim_trailing_transparent) const |
| Exports the workspace tiles to an Image<IndexPixel> in tiles.png format. | |
| Image< IndexPixel > | export_secondary_image (std::size_t primary_tile_count, ExportFlipMode flip_mode=ExportFlipMode::canonical, ExportTrimMode trim_mode=ExportTrimMode::trim_trailing_transparent) const |
Exports only the secondary portion of the workspace (tiles from primary_tile_count onward). | |
| bool | at_capacity () const |
| Checks if the workspace has reached capacity and can no longer accept new tile insertions. | |
| void | reserve_anim_slots (std::size_t anim_tile_count, std::size_t start_offset=1) |
Reserves contiguous slots for animation keyframe tiles starting at start_offset. | |
| void | place_anim_tile (std::size_t reserved_index, const CanonicalPixelTile< IndexPixel > &tile) |
| Places an animation keyframe tile at a specific reserved index. | |
| std::size_t | anim_start_offset () const |
| Returns the starting absolute index for animation tiles. | |
| std::size_t | anim_end_offset () const |
| Returns the ending absolute index for animation tiles (exclusive). | |
| bool | has_anim_slots () const |
| Returns whether animation slots have been reserved. | |
| std::optional< std::size_t > | find_contiguous_transparent_slots (std::size_t count) const |
| Finds the first contiguous run of transparent tiles that can accommodate the requested count. | |
| std::optional< std::size_t > | find_existing_contiguous_tiles_by_color (const std::vector< CanonicalPixelTile< IndexPixel > > &tiles, const std::vector< const Palette< Rgba32, pal::max_size > * > &palettes) const |
| Checks if a sequence of tiles already exists contiguously using color-equivalence comparison. | |
| void | place_tiles_at (std::size_t start_index, const std::vector< CanonicalPixelTile< IndexPixel > > &tiles) |
| Places tiles at specific positions for patch mode animation placement. | |
| std::size_t | capacity () const |
| Returns the maximum number of tiles this workspace can hold. | |
Static Public Member Functions | |
| static TilesPngWorkspace | for_secondary (const Image< IndexPixel > &primary_tiles_png, std::size_t primary_tile_count, std::size_t total_capacity) |
| Creates a workspace pre-loaded with primary tiles for secondary tileset compilation. | |
| static TilesPngWorkspace | for_standalone_secondary (std::size_t primary_tile_count, std::size_t total_capacity) |
| Creates a workspace for standalone secondary compilation with no paired primary. | |
A workspace for managing canonical IndexPixel tiles destined for tiles.png output.
TilesPngWorkspace provides a fixed-capacity container for PixelTiles that will be written to the tiles.png output file in the PorymapTilesetComponent of a Tileset. The workspace manages tile deduplication, transparent tile slots, and efficient insertion through cursor-based tracking.
Storage Model: The workspace uses a pre-allocated vector where all slots are initialized with transparent tiles. Non-transparent tiles are inserted by replacing transparent tiles at the cursor position. The cursor always points to the next available transparent slot, skipping over already-inserted non-transparent tiles.
Canonical Forms: Only non-transparent tiles are tracked in the canonical forms map for deduplication purposes. This map stores the canonical (lexicographically minimal) representation of each unique tile and all indices where that tile appears in the workspace.
Definition at line 90 of file tiles_png_workspace.hpp.
|
explicit |
Constructs a TilesPngWorkspace with a specified capacity, initializing all slots with transparent tiles.
Creates a workspace that can hold up to capacity tiles. All tile slots are pre-initialized with transparent tiles (tiles where every pixel is IndexPixel(0)). The cursor is initialized to position 1, as position 0 is reserved for the mandatory transparent tile per GBA tileset requirements.
After construction:
capacity transparent tiles| capacity | The maximum number of tiles this workspace can hold |
Definition at line 149 of file tiles_png_workspace.cpp.
|
explicit |
Constructs a TilesPngWorkspace from an existing IndexPixel image and capacity.
Extracts 8×8 pixel tiles from the input image in row-major order and populates the workspace. The image dimensions must be multiples of 8 (the tile dimension). If the image contains more tiles than the specified capacity, the constructor panics.
Extraction Process:
Non-transparent tile tracking: Only tiles that contain at least one non-zero IndexPixel are added to canonical_forms_. This enables efficient deduplication via first_occurrence_of() lookups.
Cursor initialization: After loading the image, the cursor is positioned at the first transparent tile index greater than 0. If all tiles from the image are non-transparent, the cursor points to the first padding tile.
| img | The IndexPixel image to extract tiles from; dimensions must be multiples of 8 |
| capacity | The maximum number of tiles this workspace can hold |
Definition at line 159 of file tiles_png_workspace.cpp.
|
inline |
Returns the ending absolute index for animation tiles (exclusive).
Returns the index just past the last reserved animation slot. If no animation slots were reserved, returns 1 (same as animation_start_offset()). Regular tile insertion begins at this index.
Definition at line 410 of file tiles_png_workspace.hpp.
|
inline |
Returns the starting absolute index for animation tiles.
For primary tilesets, animation tiles start at index 1 (after the transparent tile 0). For secondary tilesets, animation tiles start at num_tiles_in_primary + 1 (after the secondary transparent tile). The value is set by reserve_anim_slots() and defaults to 1.
Definition at line 396 of file tiles_png_workspace.hpp.
| bool porytiles::TilesPngWorkspace::at_capacity | ( | ) | const |
Checks if the workspace has reached capacity and can no longer accept new tile insertions.
Returns true when the cursor has reached or exceeded the capacity, indicating that all available transparent tile slots have been filled with non-transparent tiles. At this point, insert_tile() will panic for any further insertion attempts.
Note: This method returns true even if there are still transparent tiles in the workspace behind the cursor position, as the cursor always advances forward and never backtracks. However, this state shouldn't be reachable under normal operation conditions.
Definition at line 413 of file tiles_png_workspace.cpp.
|
inline |
Returns the maximum number of tiles this workspace can hold.
Returns the capacity value specified during construction. This is the fixed size of the tiles_ vector and represents the maximum number of tiles (both transparent and non-transparent) that can be stored.
Definition at line 487 of file tiles_png_workspace.hpp.
| Image< IndexPixel > porytiles::TilesPngWorkspace::export_image | ( | ExportFlipMode | flip_mode = ExportFlipMode::canonical, |
| ExportTrimMode | trim_mode = ExportTrimMode::trim_trailing_transparent |
||
| ) | const |
Exports the workspace tiles to an Image<IndexPixel> in tiles.png format.
Creates an Image<IndexPixel> representation of tiles in the workspace, arranged in row-major order with 16 tiles per row (128 pixels wide). This method provides flexible control over both flip transformation application and trailing transparent tile trimming via enum parameters.
Image Layout:
Flip Mode:
Trim Mode:
| flip_mode | Controls whether tiles are exported in canonical or original (flipped) form |
| trim_mode | Controls whether trailing transparent tiles are included or trimmed |
Definition at line 392 of file tiles_png_workspace.cpp.
| Image< IndexPixel > porytiles::TilesPngWorkspace::export_secondary_image | ( | std::size_t | primary_tile_count, |
| ExportFlipMode | flip_mode = ExportFlipMode::canonical, |
||
| ExportTrimMode | trim_mode = ExportTrimMode::trim_trailing_transparent |
||
| ) | const |
Exports only the secondary portion of the workspace (tiles from primary_tile_count onward).
Creates an Image<IndexPixel> containing only the secondary tiles. The tile at position primary_tile_count becomes the first tile (row 0, col 0) in the output image.
When trimming, if all secondary tiles are transparent, the output will contain at least the secondary transparent tile at position primary_tile_count.
| primary_tile_count | The number of primary tiles to skip (e.g. 512) |
| flip_mode | Controls whether tiles are exported in canonical or original (flipped) form |
| trim_mode | Controls whether trailing transparent tiles are included or trimmed |
Definition at line 401 of file tiles_png_workspace.cpp.
| std::optional< std::size_t > porytiles::TilesPngWorkspace::find_contiguous_transparent_slots | ( | std::size_t | count | ) | const |
Finds the first contiguous run of transparent tiles that can accommodate the requested count.
Scans the workspace starting from index 1 (skipping reserved tile 0) to find a contiguous sequence of transparent tiles with length >= count. This is useful in patch mode to find free space for animation keyframes when they don't already exist in the workspace.
| count | The number of contiguous transparent slots needed |
Definition at line 480 of file tiles_png_workspace.cpp.
| std::optional< std::size_t > porytiles::TilesPngWorkspace::find_existing_contiguous_tiles_by_color | ( | const std::vector< CanonicalPixelTile< IndexPixel > > & | tiles, |
| const std::vector< const Palette< Rgba32, pal::max_size > * > & | palettes | ||
| ) | const |
Checks if a sequence of tiles already exists contiguously using color-equivalence comparison.
Uses color-equivalence comparison to find contiguous tile sequences. This handles the case where palettes contain duplicate colors at different indices. Two pixels are considered equivalent if they reference the same color value in the palette, even if their indices differ.
This is necessary for patch/locked builds where vanilla workspace tiles may use a different palette index than the one computed by index_tile_from_color_tile() (which always picks the first matching index). For example, if palette slot 7 and slot 14 both contain the same color, vanilla tiles might use slot 14 while our computed tiles use slot 7 - they should still be considered matching.
Note: This method performs a linear scan of the workspace (O(capacity × tiles × 64)). This is acceptable because animation sequences are typically small and workspace capacity is bounded.
| tiles | The sequence of canonical tiles to search for |
| palettes | Parallel vector of palette pointers corresponding to each tile (for color lookup) |
Definition at line 512 of file tiles_png_workspace.cpp.
| std::optional< std::size_t > porytiles::TilesPngWorkspace::first_occurrence_of | ( | const CanonicalPixelTile< IndexPixel > & | tile | ) | const |
Finds the first occurrence index of a given canonical tile in the workspace.
Searches the canonical_forms_ map for the given tile and returns the index of its first occurrence in the workspace. This method only finds non-transparent tiles that have been explicitly inserted or loaded from an image during construction.
Deduplication Use Case: This method is used to check if a tile already exists in the workspace before inserting it. If the tile is found, the caller can reuse the existing tile's index rather than inserting a duplicate.
Transparent Tiles: Transparent tiles are never tracked in canonical_forms_, so this method will always return std::nullopt for any transparent tile, even though the workspace may contain many transparent tiles. Since tile 0 is guaranteed to be transparent, callers who need to index into a transparent tile can always just use tile 0 instead of searching for one.
| tile | The canonical pixel tile to search for |
Definition at line 353 of file tiles_png_workspace.cpp.
| std::optional< std::size_t > porytiles::TilesPngWorkspace::first_occurrence_of_by_color | ( | const CanonicalPixelTile< IndexPixel > & | tile, |
| const Palette< Rgba32, pal::max_size > & | palette | ||
| ) | const |
Finds the first occurrence of a tile using color-equivalence comparison.
Similar to first_occurrence_of(), but uses color-equivalence comparison instead of exact index matching. This handles the case where palettes contain duplicate colors at different indices. Two pixels are considered equivalent if they reference the same color value in the palette, even if their indices differ.
This is necessary for patch/locked builds where vanilla workspace tiles may use a different palette index than the one computed by index_tile_from_color_tile() (which always picks the first matching index). For example, if palette slot 7 and slot 14 both contain the same color, vanilla tiles might use slot 14 while our computed tiles use slot 7 - they should still be considered matching.
Note: This method performs a linear scan of the workspace (O(capacity × 64)) instead of the O(1) map lookup used by first_occurrence_of(). This is acceptable because workspace capacity is bounded and this method is only used in patch/locked modes.
| tile | The canonical pixel tile to search for |
| palette | The palette to use for color lookup |
Definition at line 363 of file tiles_png_workspace.cpp.
|
static |
Creates a workspace pre-loaded with primary tiles for secondary tileset compilation.
Constructs a workspace with total_capacity tiles. Positions 0 through primary_tile_count - 1 are populated from primary_tiles_png. Position primary_tile_count is reserved as a transparent tile per vanilla secondary tileset convention. The cursor is set to primary_tile_count + 1, ready for secondary tile insertion.
Primary tiles are registered in the canonical forms map for deduplication, so secondary tiles that match an existing primary tile will reuse its global index rather than inserting a duplicate.
| primary_tiles_png | The compiled primary tileset's tiles.png image |
| primary_tile_count | The number of tile slots reserved for primary tiles (e.g. 512) |
| total_capacity | The total tile capacity for primary + secondary (e.g. 1024) |
primary_tiles_png dimensions must be multiples of 8 primary_tile_count must be less than total_capacity Definition at line 228 of file tiles_png_workspace.cpp.
|
static |
Creates a workspace for standalone secondary compilation with no paired primary.
Creates a workspace with total_capacity tiles, all transparent. Positions 0 through primary_tile_count are reserved (transparent placeholders for primary tile slots). Position primary_tile_count is the secondary transparent tile (vanilla convention). The cursor is set to primary_tile_count + 1, ready for secondary tile insertion. No tiles are registered in canonical_forms_ since there are no primary tiles to deduplicate against.
| primary_tile_count | Number of primary tile slots to reserve. |
| total_capacity | Total workspace capacity (primary + secondary). |
primary_tile_count must be less than total_capacity. Definition at line 304 of file tiles_png_workspace.cpp.
|
inline |
Returns whether animation slots have been reserved.
Definition at line 420 of file tiles_png_workspace.hpp.
| std::size_t porytiles::TilesPngWorkspace::insert_tile | ( | const CanonicalPixelTile< IndexPixel > & | tile | ) |
Attempts to insert a non-transparent tile into the workspace at the current cursor position.
Inserts the given canonical tile at the cursor position, replacing the transparent tile that was there. After insertion, the cursor is advanced to the next available transparent tile slot. The inserted tile is added to the canonical_forms_ map for deduplication support. The function then returns the index of the inserted tile.
Insertion Criteria:
Post-insertion State:
Cursor Fast-Forward: After inserting a tile, the cursor is incremented and then fast-forwarded through any non-transparent tiles until it finds the next transparent slot or reaches capacity. This ensures O(1) insertion for the next insert_tile call in the common case.
| tile | The canonical pixel tile to insert; must be non-transparent for successful insertion |
Definition at line 327 of file tiles_png_workspace.cpp.
| void porytiles::TilesPngWorkspace::place_anim_tile | ( | std::size_t | reserved_index, |
| const CanonicalPixelTile< IndexPixel > & | tile | ||
| ) |
Places an animation keyframe tile at a specific reserved index.
Places a tile in the reserved animation region. The index is an offset within the reserved region, NOT an absolute index. For example, if animation_tile_count tiles were reserved:
| reserved_index | The index within the reserved animation region (0-based) |
| tile | The tile to place at the specified position |
Definition at line 449 of file tiles_png_workspace.cpp.
| void porytiles::TilesPngWorkspace::place_tiles_at | ( | std::size_t | start_index, |
| const std::vector< CanonicalPixelTile< IndexPixel > > & | tiles | ||
| ) |
Places tiles at specific positions for patch mode animation placement.
Places the provided tiles starting at the specified index. All target positions must be transparent (the method panics if any position is non-transparent). After placement, the canonical_forms_ map is updated and the cursor is advanced past any newly-filled positions.
| start_index | The starting index where tiles should be placed |
| tiles | The tiles to place at consecutive positions starting from start_index |
Definition at line 557 of file tiles_png_workspace.cpp.
| void porytiles::TilesPngWorkspace::reserve_anim_slots | ( | std::size_t | anim_tile_count, |
| std::size_t | start_offset = 1 |
||
| ) |
Reserves contiguous slots for animation keyframe tiles starting at start_offset.
Animation tiles are placed in a contiguous block to ensure stable offsets that can be referenced by the generated animation C code. This method reserves a contiguous block of slots for animation tiles and moves the cursor past the reserved region.
For primary tilesets, start_offset is 1 (after the transparent tile 0). For secondary tilesets, start_offset is num_tiles_in_primary + 1 (after the secondary transparent tile at num_tiles_in_primary).
After calling this method:
start_offset through start_offset + anim_tile_count - 1 (inclusive) are reservedstart_offset + anim_tile_count (first slot after reserved region)| anim_tile_count | Total number of tiles to reserve for animation keyframes |
| start_offset | The starting index for the animation region (default: 1 for primary tilesets) |
start_offset (no regular tiles inserted past that point) start_offset + anim_tile_count must be less than capacity Definition at line 418 of file tiles_png_workspace.cpp.
| CanonicalPixelTile< IndexPixel > porytiles::TilesPngWorkspace::tile_at | ( | std::size_t | index | ) | const |
Retrieves the canonical tile at the specified index in the workspace.
Returns a copy of the CanonicalPixelTile at the given index. The index must be within the bounds of the tiles_ vector (0 to capacity - 1). This method provides read-only access to any tile in the workspace, including transparent tiles and non-transparent tiles.
Bounds Checking: If the index is out of bounds, the method panics with an error message indicating the invalid index and the workspace size.
| index | The zero-based index of the tile to retrieve; must be < capacity |
Definition at line 384 of file tiles_png_workspace.cpp.