8#include "TinyGPU/Surface/Surface.h"
9#include "TinyGPU/ThreeD/Vector.h"
11#include "TinyGPU/Util/TinyGPULogger.h"
12#include "TinyGPU/Input/TouchDriver.h"
13#include "TinyGPU/Surface/SpriteInfo.h"
18
19
20
21
22
23template <
typename RGB_T =
RGB565,
typename SurfaceT =
Surface<RGB_T>>
40 RGB_T invisibleColor = RGB_T(0)) {
41 TinyGPULogger.log(TinyGPULoggerClass::INFO,
"Adding sprite at (%zu, %zu)",
43 auto info = std::make_unique<SpriteInfo<RGB_T, SurfaceT>>(x, y, sprite, invisibleColor,
46 info->saveOriginalPixels(surface_);
47 surface_.drawSprite(x, y, info->currentSprite(), invisibleColor);
49 sprites_.push_back(std::move(info));
50 return *sprites_.back();
55 const ISurface<RGB_T>& sprite,
56 RGB_T invisibleColor = RGB_T(0)) {
57 TinyGPULogger.log(TinyGPULoggerClass::INFO,
58 "Adding sprite at (%zu, %zu) with max size (%zu, %zu)", x,
60 auto info = std::make_unique<SpriteInfo<RGB_T, SurfaceT>>(x, y, sprite, invisibleColor,
62 info->setMaxSize(maxX, maxY);
63 info->saveOriginalPixels(surface_);
64 surface_.drawSprite(x, y, info->currentSprite(), invisibleColor);
65 sprites_.push_back(std::move(info));
66 return *sprites_.back();
72 spriteInfo.x
, spriteInfo.y
);
74 auto it = tinygpu::findSprite(sprites_, spriteInfo);
75 if (it != sprites_.end()) {
82 for (
auto& sprite : sprites_) {
83 if (x >= sprite->x && x < sprite->x + sprite->currentSprite().width() &&
84 y >= sprite->y && y < sprite->y + sprite->currentSprite().height()) {
97 if (idx < 0 || idx >=
static_cast<
int>(sprites_.size())) {
100 return sprites_[idx].get();
104 if (idx < 0 || idx >=
static_cast<
int>(sprites_.size())) {
107 return sprites_[idx].get();;
112 TinyGPULogger.log(TinyGPULoggerClass::INFO,
113 "Moving sprite from (%zu, %zu) to (%zu, %zu)",
114 spriteInfo.x, spriteInfo.y, newX, newY);
115 if (spriteInfo.x == newX && spriteInfo.y == newY) {
119 const Rect oldBounds{spriteInfo.x, spriteInfo.y,
120 spriteInfo.currentSprite().width(),
121 spriteInfo.currentSprite().height()};
128 Surface<RGB_T> movedBackground(oldBounds.width, oldBounds.height,
130 movedBackground.begin();
131 captureFramebufferRegion(movedBackground, 0, 0, newX, newY,
132 oldBounds.width, oldBounds.height);
136 spriteInfo.originalPixels = std::move(movedBackground);
137 surface_.drawSprite(spriteInfo.x, spriteInfo.y, spriteInfo.currentSprite(),
138 spriteInfo.invisibleColor);
146 "Scaling sprite at (%zu, %zu) by %.2f", spriteInfo.x
,
147 spriteInfo.y
, scale
);
148 spriteInfo.currentScale = scale;
158 "Rotating sprite at (%zu, %zu) by %.2f degrees",
159 spriteInfo.x
, spriteInfo.y
, angleDegrees
);
160 spriteInfo.currentAngleDegrees = angleDegrees;
166 void setPixel(size_t x, size_t y, RGB_T color)
override {
167 surface_.setPixel(x, y, color);
170 RGB_T
getPixel(size_t x, size_t y)
const override {
171 return surface_.getPixel(x, y);
174 bool resize(size_t w, size_t h)
override {
return surface_.resize(w, h); }
188 void drawLine(size_t x0, size_t y0, size_t x1, size_t y1, RGB_T color) {
189 surface_.drawLine(x0, y0, x1, y1, color);
192 void drawRect(size_t x, size_t y, size_t w, size_t h, RGB_T color) {
193 surface_.drawRect(x, y, w, h, color);
196 void fillRect(size_t x, size_t y, size_t w, size_t h, RGB_T color) {
197 surface_.fillRect(x, y, w, h, color);
201 surface_.drawCircle(x, y, r, color);
205 surface_.fillCircle(x, y, r, color);
208 void drawSprite(size_t x, size_t y,
const ISurface<RGB_T>& sprite,
209 RGB_T invisibleColor = RGB_T()) {
210 surface_.drawSprite(x, y, sprite, invisibleColor);
214 RGB_T clearColor = RGB_T()) {
215 surface_.clearSprite(x, y, sprite, clearColor);
218 void copySprite(size_t x, size_t y,
const ISurface<RGB_T>& sprite) {
219 surface_.copySprite(x, y, sprite);
222 void drawText(int16_t x, int16_t y,
const char* text, RGB_T foreground,
223 RGB_T background = RGB_T(),
bool opaque =
false,
224 uint8_t scale = 1, uint8_t spacing = 1,
225 uint8_t lineSpacing = 1) {
226 surface_.drawText(x, y, text, foreground, background, opaque, scale,
227 spacing, lineSpacing);
233 return surface_.isInBounds(x, y);
237 surface_.setPixelClipped(x, y, color);
241 surface_.drawHorizontalLineClipped(x0, x1, y, color);
250 bool setData(uint8_t* data, size_t dataSize) {
252 if (dataSize > surface_.size()) {
255 std::memcpy(
const_cast<uint8_t*>(surface_.data()), data, dataSize);
259 bool contains(size_t x, size_t y)
override {
return surface_.contains(x, y); }
267 "Touch detected at (%d, %d) with pressure %d",
272 "Touch is within sprite at (%zu, %zu)", sprite->x
,
275 sprite->onTouch(point);
293 Surface<RGB_T>&& transformedSprite) {
294 const Rect oldBounds{spriteInfo.x, spriteInfo.y,
295 spriteInfo.currentSprite().width(),
296 spriteInfo.currentSprite().height()};
304 const Rect clamped = spriteInfo.clampedSize(transformedSprite.width(),
305 transformedSprite.height());
306 const size_t anchoredX =
307 centeredCoordinate(spriteInfo.x, oldBounds.width, clamped.width);
308 const size_t anchoredY =
309 centeredCoordinate(spriteInfo.y, oldBounds.height, clamped.height);
310 const Rect newBounds{anchoredX, anchoredY, clamped.width, clamped.height};
323 Surface<RGB_T> updatedBackground(newBounds.width, newBounds.height,
325 updatedBackground.begin();
326 captureFramebufferRegion(updatedBackground, 0, 0, newBounds.x,
327 newBounds.y, newBounds.width, newBounds.height);
329 spriteInfo.x = anchoredX;
330 spriteInfo.y = anchoredY;
331 spriteInfo.setTransformedSprite(std::move(transformedSprite));
332 spriteInfo.originalPixels = std::move(updatedBackground);
333 this->drawSprite(spriteInfo.x, spriteInfo.y, spriteInfo.currentSprite(),
334 spriteInfo.invisibleColor);
342 const float centeredPosition =
343 static_cast<
float>(oldPosition) +
344 (
static_cast<
float>(oldSize) -
static_cast<
float>(newSize)) / 2.0;
345 return centeredPosition <= 0.0
347 :
static_cast<size_t>(std::lround(centeredPosition));
368 const Rect& oldBounds) {
369 drawSpriteRegion(spriteInfo.originalPixels, 0, 0, oldBounds.x,
370 oldBounds.y, oldBounds.width, oldBounds.height);
375 size_t sourceY, size_t destX, size_t destY,
376 size_t width, size_t height) {
377 for (size_t currentY = 0; currentY < height; ++currentY) {
378 for (size_t currentX = 0; currentX < width; ++currentX) {
379 const size_t framebufferX = destX + currentX;
380 const size_t framebufferY = destY + currentY;
381 if (framebufferX < surface_.width() &&
382 framebufferY < surface_.height()) {
384 framebufferX, framebufferY,
385 source.getPixel(sourceX + currentX, sourceY + currentY));
394 size_t destY, size_t sourceX, size_t sourceY,
395 size_t width, size_t height) {
396 for (size_t currentY = 0; currentY < height; ++currentY) {
397 for (size_t currentX = 0; currentX < width; ++currentX) {
398 const size_t framebufferX = sourceX + currentX;
399 const size_t framebufferY = sourceY + currentY;
401 framebufferX < surface_.width() && framebufferY < surface_.height()
402 ? surface_.getPixel(framebufferX, framebufferY)
404 destination.setPixel(destX + currentX, destY + currentY, color);
411 surface_.drawSprite(spriteInfo.x, spriteInfo.y, spriteInfo.originalPixels);
Framebuffer with sprite placement and background restoration support.
Definition: FrameBuffer.h:24
void moveSprite(SpriteInfo< RGB_T, SurfaceT > &spriteInfo, size_t newX, size_t newY)
Moves a sprite to a new position and redraws it.
Definition: FrameBuffer.h:111
SpriteInfo< RGB_T, SurfaceT > & addSprite(size_t x, size_t y, size_t maxX, size_t maxY, const ISurface< RGB_T > &sprite, RGB_T invisibleColor=RGB_T(0))
Adds a sprite with a preallocated max buffer size for transformations.
Definition: FrameBuffer.h:54
IFont< RGB_T > & font()
Returns the currently set font for text rendering.
Definition: FrameBuffer.h:182
void applyTransformedSprite(SpriteInfo< RGB_T, SurfaceT > &spriteInfo, Surface< RGB_T > &&transformedSprite)
Definition: FrameBuffer.h:292
void captureFramebufferRegion(Surface< RGB_T > &destination, size_t destX, size_t destY, size_t sourceX, size_t sourceY, size_t width, size_t height)
Definition: FrameBuffer.h:393
SurfaceT surface_
Definition: FrameBuffer.h:283
void fillRect(size_t x, size_t y, size_t w, size_t h, RGB_T color)
Fills a rectangle.
Definition: FrameBuffer.h:196
void drawText(int16_t x, int16_t y, const char *text, RGB_T foreground, RGB_T background=RGB_T(), bool opaque=false, uint8_t scale=1, uint8_t spacing=1, uint8_t lineSpacing=1)
Draws UTF-8 text.
Definition: FrameBuffer.h:222
void drawLine(size_t x0, size_t y0, size_t x1, size_t y1, RGB_T color)
Draws a line between two points.
Definition: FrameBuffer.h:188
void scaleSprite(SpriteInfo< RGB_T, SurfaceT > &spriteInfo, float scale)
Definition: FrameBuffer.h:144
void drawSpriteRegion(const ISurface< RGB_T > &source, size_t sourceX, size_t sourceY, size_t destX, size_t destY, size_t width, size_t height)
Draws a rectangular region from a source surface onto the framebuffer.
Definition: FrameBuffer.h:374
bool contains(size_t x, size_t y) override
checks if the given coordinates are within the surface bounds.
Definition: FrameBuffer.h:259
LinePrinter< RGB_T > & linePrinter()
Returns the line printer for text rendering.
Definition: FrameBuffer.h:230
void restoreFullBounds(const SpriteInfo< RGB_T, SurfaceT > &spriteInfo, const Rect &oldBounds)
Definition: FrameBuffer.h:367
size_t getSpriteCount() const
Returns the number of sprites currently managed by the framebuffer.
Definition: FrameBuffer.h:93
void copySprite(size_t x, size_t y, const ISurface< RGB_T > &sprite)
Copies a sprite.
Definition: FrameBuffer.h:218
void setTouchDriver(TouchDriver &touch)
Definition: FrameBuffer.h:36
void setFont(IFont< RGB_T > &font)
Sets the font for text rendering.
Definition: FrameBuffer.h:180
static size_t centeredCoordinate(size_t oldPosition, size_t oldSize, size_t newSize)
Definition: FrameBuffer.h:340
Vector< std::unique_ptr< SpriteInfo< RGB_T, SurfaceT > > > sprites_
Definition: FrameBuffer.h:288
void end() override
Closes the framebuffer and releases resources.
Definition: FrameBuffer.h:34
void clear(RGB_T color=RGB_T())
Clears the framebuffer with a single color.
Definition: FrameBuffer.h:184
size_t height() const override
Returns the framebuffer height in pixels.
Definition: FrameBuffer.h:178
IFont< RGB_T > & activeFont()
Returns the currently active font used by the framebuffer.
Definition: FrameBuffer.h:287
bool setData(uint8_t *data, size_t dataSize)
Sets the framebuffer pixel data directly, replacing the current content.
Definition: FrameBuffer.h:250
void restoreOriginalPixels(const SpriteInfo< RGB_T, SurfaceT > &spriteInfo)
Restores the original background pixels behind a sprite.
Definition: FrameBuffer.h:410
void fillCircle(size_t x, size_t y, size_t r, RGB_T color)
Fills a circle.
Definition: FrameBuffer.h:204
bool resize(size_t w, size_t h) override
Resizes the framebuffer surface.
Definition: FrameBuffer.h:174
void rotateSprite(SpriteInfo< RGB_T, SurfaceT > &spriteInfo, float angleDegrees)
Definition: FrameBuffer.h:156
const uint8_t * data() const override
Returns the raw pixel buffer as bytes.
Definition: FrameBuffer.h:245
SpriteInfo< RGB_T, SurfaceT > & addSprite(size_t x, size_t y, const ISurface< RGB_T > &sprite, RGB_T invisibleColor=RGB_T(0))
Adds a sprite to the framebuffer and draws it at the given position.
Definition: FrameBuffer.h:39
TouchDriver * p_touchDriver
Definition: FrameBuffer.h:284
void clearSprite(size_t x, size_t y, ISurface< RGB_T > &sprite, RGB_T clearColor=RGB_T())
Clears a sprite.
Definition: FrameBuffer.h:213
FrameBuffer()=default
Creates an empty framebuffer.
SpriteInfo< RGB_T, SurfaceT > * getSpritePtr(int idx)
Definition: FrameBuffer.h:103
FrameBuffer(size_t width, size_t height, IFont< RGB_T > &font)
Creates a framebuffer with the specified size and font.
Definition: FrameBuffer.h:30
void drawCircle(size_t x, size_t y, size_t r, RGB_T color)
Draws a circle outline.
Definition: FrameBuffer.h:200
void drawSprite(size_t x, size_t y, const ISurface< RGB_T > &sprite, RGB_T invisibleColor=RGB_T())
Draws a sprite.
Definition: FrameBuffer.h:208
SpriteInfo< RGB_T, SurfaceT > * getSprite(size_t x, size_t y)
Returns a pointer to the sprite at the given position, if any.
Definition: FrameBuffer.h:81
SpriteInfo< RGB_T, SurfaceT > * getSprite(int idx)
Returns a pointer to the sprite at the given index, if valid.
Definition: FrameBuffer.h:96
void processTouch()
Processes touch input and dispatches events to sprites if touched.
Definition: FrameBuffer.h:262
size_t width() const override
Returns the framebuffer width in pixels.
Definition: FrameBuffer.h:176
void scroll(int dx, int dy) override
Scrolls the framebuffer content by the specified offsets.
Definition: FrameBuffer.h:186
bool begin() override
Initializes the framebuffer surface.
Definition: FrameBuffer.h:33
void removeSprite(SpriteInfo< RGB_T, SurfaceT > &spriteInfo)
Removes a sprite and restores the pixels behind it.
Definition: FrameBuffer.h:70
void setPixelClipped(size_t x, size_t y, RGB_T color)
Sets a pixel with clipping.
Definition: FrameBuffer.h:236
void setPixel(size_t x, size_t y, RGB_T color) override
ISurface<RGB_T> interface delegation.
Definition: FrameBuffer.h:166
size_t size() const override
Returns the size of the buffer in bytes.
Definition: FrameBuffer.h:247
void drawRect(size_t x, size_t y, size_t w, size_t h, RGB_T color)
Draws a rectangle outline.
Definition: FrameBuffer.h:192
RGB_T getPixel(size_t x, size_t y) const override
Returns the pixel at the given position.
Definition: FrameBuffer.h:170
void drawHorizontalLineClipped(int x0, int x1, int y, RGB_T color)
Draws a horizontal line with clipping.
Definition: FrameBuffer.h:240
bool isInBounds(size_t x, size_t y) const
Checks if the given coordinates are within the surface bounds.
Definition: FrameBuffer.h:232
Font rendering interface for TinyGPU-compatible framebuffers.
Definition: IFont.h:19
Helper for printing wrapped lines of text onto a TinyGPU target.
Definition: LinePrinter.h:17
RGB color stored in 16-bit RGB565 format, byte-swapped from the conventional bit layout.
Definition: RGB565.h:24
In-memory bitmap surface with basic 2D drawing and text rendering.
Definition: Surface.h:38
Simple header-only logger for TinyGPU with log levels and vararg support.
Definition: TinyGPULogger.h:24
@ INFO
General information.
Definition: TinyGPULogger.h:32
void log(Level level, const char *fmt,...)
Log a message with printf-style formatting.
Definition: TinyGPULogger.h:56
Base class for touch controllers.
Definition: TouchDriverCommon.h:72
virtual bool isTouched()=0
Return whether the panel currently appears touched.
virtual bool getPoint(Point &outPoint)=0
Read the current touch point.
Definition: DSIBusESP32.h:19
Touch point.
Definition: TouchDriverCommon.h:32
uint16_t pressure
Definition: TouchDriverCommon.h:35
int16_t x
Definition: TouchDriverCommon.h:33
int16_t y
Definition: TouchDriverCommon.h:34
Represents a rectangular area on the screen or surface.
Definition: SpriteInfo.h:19
Definition: SpriteInfo.h:52