box crop and fits; Pixel class support for reading screen pixels

This commit is contained in:
Frank DeMarco 2020-09-12 20:29:26 -04:00
parent 013f8279d4
commit 72a36a1d57
6 changed files with 138 additions and 19 deletions

View File

@ -10,6 +10,8 @@ Box::Box(const glm::vec2& nw, const glm::vec2& size)
h = size.y;
}
Box::Box(const SDL_Rect& rect) : Box({rect.x, rect.y}, {rect.w, rect.h}) {}
float Box::get_x() const
{
return x;
@ -101,11 +103,25 @@ float Box::get_center_y() const
return get_top() + get_h() / 2;
}
void Box::set_top(float top)
void Box::set_top(float top, bool drag)
{
set_y(top);
if (!drag)
{
set_y(top);
}
else
{
drag_top(top - get_top());
}
}
void Box::drag_top(float delta)
{
float previous_top = get_top();
set_top(get_top() + delta);
set_h(get_h() + previous_top - get_top());
}
void Box::set_right(float right, bool drag)
{
float delta = right - get_right();
@ -127,9 +143,25 @@ void Box::drag_right(float delta)
set_right(new_right);
}
void Box::set_bottom(float bottom)
void Box::set_bottom(float bottom, bool drag)
{
move({0, bottom - get_bottom()});
float delta = bottom - get_bottom();
if (!drag)
{
move({0, delta});
}
else
{
drag_bottom(delta);
}
}
void Box::drag_bottom(float delta)
{
float previous_bottom = get_bottom();
float new_bottom = get_bottom() + delta;
set_h(get_h() + new_bottom - previous_bottom);
set_bottom(new_bottom);
}
void Box::set_left(float left, bool drag)
@ -236,6 +268,11 @@ void Box::set_south(const glm::vec2& s)
move(s - get_south());
}
void Box::set_sw(const glm::vec2& sw)
{
move(sw - get_sw());
}
void Box::set_west(const glm::vec2& w)
{
move(w - get_west());
@ -300,6 +337,32 @@ Box Box::stamp(const glm::vec2& delta) const
return clone;
}
bool Box::fits(const Box& container) const
{
return !(get_top() < container.get_top() || get_right() > container.get_right() ||
get_bottom() > container.get_bottom() || get_left() < container.get_left());
}
void Box::crop(const Box& area)
{
if (get_top() < area.get_top())
{
set_top(area.get_top(), true);
}
if (get_right() > area.get_right())
{
set_right(area.get_right(), true);
}
if (get_bottom() > area.get_bottom())
{
set_bottom(area.get_bottom(), true);
}
if (get_left() < area.get_left())
{
set_left(area.get_left(), true);
}
}
bool Box::collide(const glm::vec2& point) const
{
return point.x >= get_left() && point.x <= get_right() && point.y >= get_top() && point.y <= get_bottom();

View File

@ -16,6 +16,7 @@ struct Box : SDL_FRect
{
Box(const glm::vec2& = {0, 0}, const glm::vec2& = {0, 0});
Box(const SDL_Rect&);
float get_x() const;
float get_y() const;
float get_w() const;
@ -33,10 +34,12 @@ struct Box : SDL_FRect
float get_left() const;
float get_center_x() const;
float get_center_y() const;
void set_top(float);
void set_top(float, bool=false);
void drag_top(float);
void set_right(float, bool=false);
void drag_right(float);
void set_bottom(float);
void set_bottom(float, bool=false);
void drag_bottom(float);
void set_left(float, bool=false);
void drag_left(float);
void set_center_x(float);
@ -56,6 +59,7 @@ struct Box : SDL_FRect
void set_east(const glm::vec2&);
void set_se(const glm::vec2&);
void set_south(const glm::vec2&);
void set_sw(const glm::vec2&);
void set_west(const glm::vec2&);
void set_center(const glm::vec2&);
operator SDL_Rect() const;
@ -66,6 +70,8 @@ struct Box : SDL_FRect
void expand(float, bool = false);
void move(const glm::vec2&);
Box stamp(const glm::vec2&) const;
bool fits(const Box&) const;
void crop(const Box&);
bool collide(const glm::vec2&) const;
bool collide(const Segment&, glm::vec2* = nullptr) const;
bool collide(const Segment&, glm::vec2&) const;

View File

@ -92,6 +92,9 @@ Game::Game()
}
else
{
int w, h;
SDL_GetRendererOutputSize(renderer, &w, &h);
SDL_Log("renderer output size is (%i, %i)", w, h);
SDL_SetRenderTarget(renderer, nullptr);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);

View File

@ -1,18 +1,49 @@
#include "Pixels.hpp"
Pixels::Pixels(SDL_Renderer* renderer, SDL_Texture* texture) : Pixels(renderer, texture, sfw::get_texture_box(texture)) {}
Pixels::Pixels(SDL_Renderer* renderer, SDL_Texture* texture, const SDL_Rect& rect) : texture(texture), rect(rect)
Pixels::Pixels(SDL_Renderer* renderer, SDL_Texture* texture, const Box& box) :
texture(texture), renderer(renderer)
{
Uint32 format_enum;
int w, h;
SDL_QueryTexture(texture, &format_enum, &texture_access, &w, &h);
format = SDL_AllocFormat(format_enum);
if (texture_access == SDL_TEXTUREACCESS_STATIC || texture_access == SDL_TEXTUREACCESS_TARGET)
if (texture == nullptr)
{
bool is_duplicate;
SDL_SetRenderTarget(renderer, nullptr);
SDL_DisplayMode display_mode;
if (SDL_GetCurrentDisplayMode(0, &display_mode) < 0)
{
sfw::print_sdl_error("could not get current display mode");
}
if (SDL_GetRendererOutputSize(renderer, &w, &h) < 0)
{
sfw::print_sdl_error("could not get renderer output size");
}
format_enum = display_mode.format;
texture_access = TEXTURE_ACCESS_SCREEN;
}
else
{
SDL_QueryTexture(texture, &format_enum, &texture_access, &w, &h);
}
format = SDL_AllocFormat(format_enum);
if (box.fits({{0, 0}, {w, h}}))
{
rect = box;
}
else
{
Box cropped = box;
cropped.crop({{0, 0}, {w, h}});
rect = cropped;
}
if (texture == nullptr || texture_access == SDL_TEXTUREACCESS_STATIC || texture_access == SDL_TEXTUREACCESS_TARGET)
{
bool is_duplicate = false;
SDL_Texture* base;
if (texture_access == SDL_TEXTUREACCESS_STATIC)
if (texture == nullptr)
{
base = nullptr;
}
else if (texture_access == SDL_TEXTUREACCESS_STATIC)
{
base = sfw::duplicate_texture(renderer, texture);
is_duplicate = true;
@ -20,7 +51,6 @@ Pixels::Pixels(SDL_Renderer* renderer, SDL_Texture* texture, const SDL_Rect& rec
else
{
base = texture;
is_duplicate = false;
}
SDL_SetRenderTarget(renderer, base);
int bytes_total = get_bytes_per_row() * rect.h;
@ -53,6 +83,8 @@ Pixels::Pixels(SDL_Renderer* renderer, SDL_Texture* texture, const SDL_Rect& rec
}
}
Pixels::Pixels(SDL_Renderer* renderer, SDL_Texture* texture) : Pixels(renderer, texture, sfw::get_texture_box(texture)) {}
int Pixels::get_bytes_per_row() const
{
return format->BytesPerPixel * rect.w;
@ -85,7 +117,19 @@ void Pixels::set(const SDL_Color& color, int x, int y)
void Pixels::apply()
{
if (texture_access == SDL_TEXTUREACCESS_STATIC || texture_access == SDL_TEXTUREACCESS_TARGET)
if (texture_access == TEXTURE_ACCESS_SCREEN)
{
SDL_SetRenderTarget(renderer, nullptr);
for (int x = rect.x; x < rect.x + rect.w; x++)
{
for (int y = rect.y; y < rect.y + rect.h; y++)
{
SDL_SetRenderDrawColor(renderer, get(x, y));
SDL_RenderDrawPoint(renderer, x, y);
}
}
}
else if (texture_access == SDL_TEXTUREACCESS_STATIC || texture_access == SDL_TEXTUREACCESS_TARGET)
{
SDL_UpdateTexture(texture, &rect, source, get_bytes_per_row());
}

View File

@ -11,17 +11,20 @@ struct Sprite;
struct Pixels
{
const int TEXTURE_ACCESS_SCREEN = 128;
void* source = nullptr;
SDL_PixelFormat* format = nullptr;
SDL_Texture* texture;
SDL_Renderer* renderer;
int texture_access = 0;
SDL_Rect rect;
bool allocated = false;
Pixels(SDL_Renderer*, SDL_Texture* texture, const Box&);
Pixels(SDL_Renderer*, SDL_Texture* texture);
Pixels(SDL_Renderer*, SDL_Texture* texture, const SDL_Rect&);
Pixels(SDL_Renderer*);
Pixels(Sprite&);
Pixels(Sprite&, const SDL_Rect&);
Pixels(Sprite&, const Box&);
int get_bytes_per_row() const;
Color get(int x, int y);
void set(const SDL_Color&, int x, int y);

View File

@ -1060,6 +1060,6 @@ void Frameset::reverse()
}
Pixels::Pixels(Sprite& sprite) : Pixels(sprite.get_renderer(), sprite.get_current_frame()) {}
Pixels::Pixels(Sprite& sprite, const SDL_Rect& rect) : Pixels(sprite.get_renderer(), sprite.get_current_frame(), rect) {}
Pixels::Pixels(Sprite& sprite, const Box& box) : Pixels(sprite.get_renderer(), sprite.get_current_frame(), box) {}
Segment::Segment(const Sprite& start, const Sprite& end) : Segment(start.get_center(), end.get_center()) {}