yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
tile_brush_preview.h
Go to the documentation of this file.
1#ifndef YAZE_APP_EDITOR_OVERWORLD_PAINTING_TILE_BRUSH_PREVIEW_H_
2#define YAZE_APP_EDITOR_OVERWORLD_PAINTING_TILE_BRUSH_PREVIEW_H_
3
4#include <algorithm>
5#include <cstdint>
6#include <span>
7#include <vector>
8
10#include "app/gfx/core/bitmap.h"
11
12namespace yaze::editor {
13
14// A compact piece of a brush, clipped to one 32x32-tile destination map.
16 int tile_x = 0;
17 int tile_y = 0;
18 int width = 0;
19 int height = 0;
20 std::vector<uint8_t> pixels;
21};
22
24 int anchor_x, int anchor_y,
25 int map_x, int map_y,
26 std::span<const uint8_t> atlas,
27 int atlas_width = 128) {
28 MapBrushPreview result;
29 if (!brush.valid() || atlas_width < 16 || atlas_width % 16 != 0)
30 return result;
31 const int left = std::max(anchor_x, map_x * 32);
32 const int top = std::max(anchor_y, map_y * 32);
33 const int right = std::min(anchor_x + brush.width, (map_x + 1) * 32);
34 const int bottom = std::min(anchor_y + brush.height, (map_y + 1) * 32);
35 if (right <= left || bottom <= top)
36 return result;
37 result.tile_x = left;
38 result.tile_y = top;
39 result.width = (right - left) * 16;
40 result.height = (bottom - top) * 16;
41 result.pixels.resize(result.width * result.height);
42 const int columns = atlas_width / 16;
43 for (int y = top; y < bottom; ++y) {
44 for (int x = left; x < right; ++x) {
45 const int id = brush.at(x - anchor_x, y - anchor_y);
46 const size_t source =
47 (id / columns * 16) * atlas_width + (id % columns * 16);
48 if (source + 15 * atlas_width + 16 > atlas.size())
49 continue;
50 for (int row = 0; row < 16; ++row) {
51 std::copy_n(atlas.begin() + source + row * atlas_width, 16,
52 result.pixels.begin() +
53 ((y - top) * 16 + row) * result.width +
54 (x - left) * 16);
55 }
56 }
57 }
58 return result;
59}
60
61// A GPU texture cannot be resized with UpdateTexture. Keep one quadrant-sized
62// allocation per destination map while the clipped piece grows/shrinks at its
63// edges. This is a storage-quadrant extent, not the parent area's dimensions.
64inline void SyncMapBrushPreview(const MapBrushPreview& piece,
65 const gfx::SnesPalette& palette,
66 gfx::Bitmap& preview) {
67 constexpr int kTextureExtent = 32 * 16;
68 if (piece.width <= 0 || piece.height <= 0 || piece.width > kTextureExtent ||
69 piece.height > kTextureExtent ||
70 piece.pixels.size() != static_cast<size_t>(piece.width) * piece.height) {
71 return;
72 }
73 std::vector<uint8_t> pixels(kTextureExtent * kTextureExtent, 0);
74 for (int y = 0; y < piece.height; ++y) {
75 std::copy_n(piece.pixels.begin() + y * piece.width, piece.width,
76 pixels.begin() + y * kTextureExtent);
77 }
78 const bool pixels_changed =
79 !preview.is_active() || preview.vector() != pixels;
80 const bool palette_changed = !(preview.palette() == palette);
81 if (pixels_changed) {
82 preview.Create(kTextureExtent, kTextureExtent, 8, pixels);
83 }
84 if (pixels_changed || palette_changed)
85 preview.SetPalette(palette);
86 if (!preview.texture())
87 preview.CreateTexture();
88 else if (pixels_changed || palette_changed)
89 preview.UpdateTexture();
90}
91
92// The 16x16 pixels (palette indices) of `tile_id` in a tile16 blockset atlas
93// `atlas_width` pixels wide; empty when the tile lies outside the atlas.
94inline std::vector<uint8_t> Tile16PixelsFromBlockset(
95 std::span<const uint8_t> atlas, int tile_id, int atlas_width = 128) {
96 if (tile_id < 0 || atlas_width < 16 || atlas_width % 16 != 0)
97 return {};
98 const int columns = atlas_width / 16;
99 const size_t source =
100 static_cast<size_t>(tile_id / columns * 16) * atlas_width +
101 (tile_id % columns * 16);
102 if (source + 15 * static_cast<size_t>(atlas_width) + 16 > atlas.size())
103 return {};
104 std::vector<uint8_t> pixels(16 * 16);
105 for (int row = 0; row < 16; ++row) {
106 std::copy_n(atlas.begin() + source + row * atlas_width, 16,
107 pixels.begin() + row * 16);
108 }
109 return pixels;
110}
111
112} // namespace yaze::editor
113
114#endif // YAZE_APP_EDITOR_OVERWORLD_PAINTING_TILE_BRUSH_PREVIEW_H_
Represents a bitmap image optimized for SNES ROM hacking.
Definition bitmap.h:70
const SnesPalette & palette() const
Definition bitmap.h:393
void Create(int width, int height, int depth, std::span< uint8_t > data)
Create a bitmap with the given dimensions and data.
Definition bitmap.cc:198
TextureHandle texture() const
Definition bitmap.h:410
const std::vector< uint8_t > & vector() const
Definition bitmap.h:411
void CreateTexture()
Creates the underlying SDL_Texture to be displayed.
Definition bitmap.cc:297
bool is_active() const
Definition bitmap.h:414
void SetPalette(const SnesPalette &palette)
Set the palette for the bitmap using SNES palette format.
Definition bitmap.cc:452
void UpdateTexture()
Updates the underlying SDL_Texture when it already exists.
Definition bitmap.cc:301
Represents a palette of colors for the Super Nintendo Entertainment System (SNES).
Editors are the view controllers for the application.
MapBrushPreview BuildMapBrushPreview(const TileBrush &brush, int anchor_x, int anchor_y, int map_x, int map_y, std::span< const uint8_t > atlas, int atlas_width=128)
void SyncMapBrushPreview(const MapBrushPreview &piece, const gfx::SnesPalette &palette, gfx::Bitmap &preview)
std::vector< uint8_t > Tile16PixelsFromBlockset(std::span< const uint8_t > atlas, int tile_id, int atlas_width=128)
std::vector< uint8_t > pixels
int at(int x, int y) const
Definition tile_brush.h:24