yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
sprite_editor_internal.h
Go to the documentation of this file.
1#ifndef YAZE_APP_EDITOR_SPRITE_SPRITE_EDITOR_INTERNAL_H_
2#define YAZE_APP_EDITOR_SPRITE_SPRITE_EDITOR_INTERNAL_H_
3
4#include <algorithm>
5#include <array>
6#include <cstdint>
7#include <vector>
8
10#include "app/gfx/core/bitmap.h"
12
13namespace yaze {
14namespace editor {
15namespace internal {
16
17// 8x8 OAM tile ids a ZSM frame draws, sorted and unique. A 16x16 entry covers
18// id, id+1, id+16 and id+17, as SpriteDrawer draws it.
19inline std::vector<int> FrameTiles8x8(const zsprite::Frame& frame) {
20 std::vector<int> tiles;
21 for (const auto& tile : frame.Tiles) {
22 tiles.push_back(tile.id);
23 if (tile.size) {
24 tiles.push_back(tile.id + 1);
25 tiles.push_back(tile.id + 16);
26 tiles.push_back(tile.id + 17);
27 }
28 }
29 std::sort(tiles.begin(), tiles.end());
30 tiles.erase(std::unique(tiles.begin(), tiles.end()), tiles.end());
31 return tiles;
32}
33
34// The preview palettes SpriteEditor uses without a binding: the global
35// sprite palettes, then aux1/aux2/aux3 palettes until there are 8 rows.
37 const gfx::PaletteGroup& global, const gfx::PaletteGroup& aux1,
38 const gfx::PaletteGroup& aux2, const gfx::PaletteGroup& aux3) {
39 gfx::PaletteGroup palettes;
40 for (size_t i = 0; i < global.size() && i < 8; i++) {
41 palettes.AddPalette(global.palette(i));
42 }
43 while (palettes.size() < 8) {
44 if (palettes.size() < 4 && aux1.size() > 0) {
45 palettes.AddPalette(aux1.palette(palettes.size() % aux1.size()));
46 } else if (palettes.size() < 6 && aux2.size() > 0) {
47 palettes.AddPalette(aux2.palette((palettes.size() - 4) % aux2.size()));
48 } else if (aux3.size() > 0) {
49 palettes.AddPalette(aux3.palette((palettes.size() - 6) % aux3.size()));
50 } else {
51 palettes.AddPalette(gfx::SnesPalette());
52 }
53 }
54 return palettes;
55}
56
57// Eight 16-color sprite palettes (OAM palettes 0-7) from CGRAM rows 8-15.
59 const std::array<SDL_Color, 256>& cgram) {
60 gfx::PaletteGroup palettes;
61 for (int row = 8; row < 16; ++row) {
62 gfx::SnesPalette palette;
63 for (int i = 0; i < 16; ++i) {
64 const SDL_Color& c = cgram[row * 16 + i];
65 palette.AddColor(gfx::SnesColor(c.r, c.g, c.b));
66 }
67 palettes.AddPalette(palette);
68 }
69 return palettes;
70}
71
72// Initialize a sprite-preview bitmap once and queue its texture for creation.
73// Idempotent: returns immediately if the bitmap is already active.
74//
75// SpriteEditor used to call Create()+Reformat() inline, never queueing a
76// CREATE texture command, so canvas_rendering's `if (!texture()) return;`
77// guard skipped the draw silently and the preview was always blank. This
78// helper closes that gap and stamps the bitmap as a composite output (the
79// pixels come from SpriteDrawer rendering OAM tiles into the surface, not
80// from direct user paint).
81//
82// Safe to call every render frame; the `is_active()` short-circuit ensures
83// only the first call does any work.
85 gfx::Bitmap& bmp, int width, int height, int depth,
86 const std::vector<uint8_t>& gfx_buffer) {
87 if (bmp.is_active()) {
88 return;
89 }
90 // Graphics sheets are input to the drawer, not initial composite pixels.
91 const std::vector<uint8_t> blank(
92 gfx_buffer.empty() ? 0 : static_cast<size_t>(width) * height, 0);
93 bmp.Create(width, height, depth, blank);
94 if (!bmp.is_active()) {
95 // Create bailed (empty buffer, surface allocation failed). Don't call
96 // Reformat. It would unconditionally allocate a fresh surface and set
97 // active=true with no pixel data, masking the load failure and queuing
98 // a CREATE for an effectively-blank bitmap. Leave the bitmap inactive
99 // so the next frame's call retries Create with a real buffer.
100 return;
101 }
102 bmp.Reformat(depth);
103 if (bmp.surface() != nullptr) {
104 bmp.CreateTexture();
105 }
107}
108
109// SpriteDrawer writes Bitmap::mutable_data(); the renderer reads the SDL surface.
112 bmp.UpdateTexture();
113}
114
115} // namespace internal
116} // namespace editor
117} // namespace yaze
118
119#endif // YAZE_APP_EDITOR_SPRITE_SPRITE_EDITOR_INTERNAL_H_
Represents a bitmap image optimized for SNES ROM hacking.
Definition bitmap.h:70
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
void UpdateSurfacePixels()
Update SDL surface with current pixel data from data_ vector Call this after modifying pixel data via...
Definition bitmap.cc:373
void Reformat(int format)
Reformat the bitmap to use a different pixel format.
Definition bitmap.cc:280
BitmapMetadata & metadata()
Definition bitmap.h:395
void CreateTexture()
Creates the underlying SDL_Texture to be displayed.
Definition bitmap.cc:297
bool is_active() const
Definition bitmap.h:414
SDL_Surface * surface() const
Definition bitmap.h:409
void UpdateTexture()
Updates the underlying SDL_Texture when it already exists.
Definition bitmap.cc:301
SNES Color container.
Definition snes_color.h:110
Represents a palette of colors for the Super Nintendo Entertainment System (SNES).
void AddColor(const SnesColor &color)
void EnsureSpritePreviewBitmapReady(gfx::Bitmap &bmp, int width, int height, int depth, const std::vector< uint8_t > &gfx_buffer)
void PublishSpritePreviewPixels(gfx::Bitmap &bmp)
std::vector< int > FrameTiles8x8(const zsprite::Frame &frame)
gfx::PaletteGroup SpritePalettesFromCgram(const std::array< SDL_Color, 256 > &cgram)
gfx::PaletteGroup DefaultSpritePreviewPalettes(const gfx::PaletteGroup &global, const gfx::PaletteGroup &aux1, const gfx::PaletteGroup &aux2, const gfx::PaletteGroup &aux3)
std::vector< OamTile > Tiles
Definition zsprite.h:112
Represents a group of palettes.
auto palette(int i) const
void AddPalette(SnesPalette pal)