diff --git a/board_widget.cpp b/board_widget.cpp index 3476be1..735d8c6 100644 --- a/board_widget.cpp +++ b/board_widget.cpp @@ -1,10 +1,14 @@ -#include -#include +#include +#include + +#include +#include +#include #include "board_widget.hpp" #include "game.hpp" -using namespace bwidgets::utils; +using namespace bwidgets; using namespace game; using namespace game::data; @@ -16,7 +20,7 @@ ui::BoardWidget::BoardWidget(Widget* p) [this] (const SDL_MouseButtonEvent& p) -> void { - if (_board != nullptr) + if (board != nullptr) { auto coord = new SDL_Point(this->board_coord_from_input({p.x, p.y})); SDL_Event play_ev; @@ -30,44 +34,36 @@ ui::BoardWidget::BoardWidget(Widget* p) }; } -void ui::BoardWidget::board(Board* b) +ui::BoardWidget::~BoardWidget() { - _board = b; + delete _circle_blue; + delete _circle_red; } SDL_Point ui::BoardWidget::board_coord_from_input(const SDL_Point& p) const { - if (_board == nullptr) + if (board == nullptr) return {-1, -1}; return { - (p.x - _viewport.x - _widget_area.x) / (_widget_area.w / _board->width), - (p.y - _viewport.y - _widget_area.y) / (_widget_area.h / _board->height) + (p.x - _viewport.x - _widget_area.x) / (_widget_area.w / board->width), + (p.y - _viewport.y - _widget_area.y) / (_widget_area.h / board->height) }; } -void ui::BoardWidget::render(SDL_Renderer* r) +void ui::BoardWidget::_handle_rendering() { - Widget::render(r); - - if (_renderer == nullptr || _renderer != r) - { - _renderer = r; - _update_textures(); - } - - SDL_RenderSetViewport(r, &_viewport); - - SDL_SetRenderDrawColor(r, color_bg.r, color_bg.g, color_bg.b, color_bg.a); - SDL_RenderFillRect(r, &_widget_area); + if (!_circle_blue || !_circle_red) + _handle_texture_update(); + _renderer->draw_color(color_bg)->fill_rect(_widget_area); _render_empty_board(); _render_square_content(); } -void ui::BoardWidget::viewport(const SDL_Rect& vp) +void ui::BoardWidget::_handle_geometry_change(const SDL_Rect& vp) noexcept { - Widget::viewport(vp); + _widget_area = {0, 0, vp.w, vp.h}; auto smallest_size { _widget_area.w < _widget_area.h ? _widget_area.w @@ -85,10 +81,9 @@ void ui::BoardWidget::viewport(const SDL_Rect& vp) _widget_area.w - 2 * (_border_area.w), _widget_area.h - 2 * (_border_area.w) }; - _update_textures(); } -void ui::BoardWidget::_draw_atoms(const SDL_Rect& area, int atoms, SDL_Texture* texture) +void ui::BoardWidget::_draw_atoms(const SDL_Rect& area, int atoms, core::Texture* texture) { const auto radius = area.w < area.h ? area.w / 8 : area.h / 8; const auto diameter = radius * 2; @@ -145,86 +140,81 @@ void ui::BoardWidget::_draw_atoms(const SDL_Rect& area, int atoms, SDL_Texture* { const int size {o.x == disabled ? 0 : diameter}; - render::render_copy(_renderer, texture, {area.x + o.x, area.y + o.y, size, size}); + _renderer->copy(texture, NULL, {area.x + o.x, area.y + o.y, size, size}); } } +void ui::BoardWidget::_handle_renderer_change(core::Renderer*) +{ + core::OpaqueStruct::discard(_circle_blue); + core::OpaqueStruct::discard(_circle_red); +} + void ui::BoardWidget::_render_empty_board() { - SDL_SetRenderDrawColor(_renderer, - color_outline.r, - color_outline.g, - color_outline.b, - color_outline.a); + _renderer->draw_color(color_outline); - if (_board != nullptr) + if (board) { - for (int col = 0; col <= _board->width; col++) + for (int col = 0; col <= board->width; col++) { - int x = col * _widget_area.w / _board->width; - SDL_RenderDrawLine(_renderer, - _widget_area.x + x, _widget_area.y, - _widget_area.x + x, _widget_area.y + _widget_area.h); + int x = col * _widget_area.w / board->width; + _renderer->draw_line({_widget_area.x + x, _widget_area.y}, + {_widget_area.x + x, _widget_area.y + _widget_area.h}); } - for (int row = 0; row <= _board->height; row++) + for (int row = 0; row <= board->height; row++) { - int y = row * _widget_area.h / _board->height; - SDL_RenderDrawLine(_renderer, - _widget_area.x, _widget_area.y + y, - _widget_area.x + _widget_area.w, _widget_area.y + y); + int y = row * _widget_area.h / board->height; + _renderer->draw_line({_widget_area.x, _widget_area.y + y}, + {_widget_area.x + _widget_area.w, _widget_area.y + y}); } } for (int xy = 0; xy < _border_area.w; xy++) { const float color_factor = 1 - (float)xy / _border_area.w / 3; - SDL_SetRenderDrawColor(_renderer, - color_outline.r * color_factor, - color_outline.g * color_factor, - color_outline.b * color_factor, - color_outline.a); - - SDL_Rect border { - _border_area.x + xy, - _border_area.y + xy, - _widget_area.w + 2 * (_widget_area.x - _border_area.x - xy) + 1, - _widget_area.h + 2 * (_widget_area.y - _border_area.y - xy) + 1 - }; - SDL_RenderDrawRect(_renderer, &border); + _renderer->draw_color({ + (uint8_t)(color_outline.r * color_factor), + (uint8_t)(color_outline.g * color_factor), + (uint8_t)(color_outline.b * color_factor), + color_outline.a})->draw_rect({ + _border_area.x + xy, + _border_area.y + xy, + _widget_area.w + 2 * (_widget_area.x - _border_area.x - xy) + 1, + _widget_area.h + 2 * (_widget_area.y - _border_area.y - xy) + 1 + }); } } void ui::BoardWidget::_render_square_content() { - if (_board == nullptr) + if (!board) return; - for (int y = 0; y < _board->height; y++) + for (int y = 0; y < board->height; y++) { - for (int x = 0; x < _board->width; x++) + for (int x = 0; x < board->width; x++) { SDL_Rect sqr_area { _widget_area.x - + x * _widget_area.w / _board->width + 1, + + x * _widget_area.w / board->width + 1, _widget_area.y - + y * _widget_area.h / _board->height + 1, - _widget_area.w / _board->width - 2, - _widget_area.h / _board->height - 2 + + y * _widget_area.h / board->height + 1, + _widget_area.w / board->width - 2, + _widget_area.h / board->height - 2 }; - const auto& sqr = Board::square(*_board, {x, y}); - auto capacity = logic::square_capacity(*_board, {x, y}); + const auto& sqr = Board::square(*board, {x, y}); + auto capacity = logic::square_capacity(*board, {x, y}); if (sqr.value > capacity) { - SDL_SetRenderDrawColor(_renderer, 255, 0, 0, 255/16); - SDL_RenderFillRect(_renderer, &sqr_area); + _renderer->draw_color(color_hl1)->fill_rect(sqr_area); } else if (sqr.value == capacity) { - SDL_SetRenderDrawColor(_renderer, 255, 255, 0, 255/16); - SDL_RenderFillRect(_renderer, &sqr_area); + _renderer->draw_color(color_hl2)->fill_rect(sqr_area); } _draw_atoms(sqr_area, sqr.value, sqr.owner == game::data::Player::P1 @@ -234,20 +224,18 @@ void ui::BoardWidget::_render_square_content() } } -void ui::BoardWidget::_update_textures() +void ui::BoardWidget::_handle_texture_update() { - if (_board == nullptr || _renderer == nullptr) + SDL_assert_release(!_circle_blue && !_circle_red); + + if (!board) return; - int circle_size = _widget_area.w > _widget_area.h - ? _widget_area.h / _board->height / 4 - : _widget_area.w / _board->width / 4; + auto circle_size = _widget_area.w > _widget_area.h + ? _widget_area.h / board->height / 4 + : _widget_area.w / board->width / 4; - for (SDL_Texture** t : {&_circle_blue, &_circle_red}) - { - SDL_DestroyTexture(*t); - *t = nullptr; - } - _circle_blue = render::filled_circle({0, 0, 255, 255}, circle_size, _renderer); - _circle_red = render::filled_circle({255, 0, 0, 255}, circle_size, _renderer); + auto aa = circle_size > 16 ? 3 : 0; + _circle_blue = core::filled_circle({0, 0, 255, 255}, circle_size, _renderer, aa); + _circle_red = core::filled_circle({255, 0, 0, 255}, circle_size, _renderer, aa); } diff --git a/board_widget.hpp b/board_widget.hpp index 0f44674..124f152 100644 --- a/board_widget.hpp +++ b/board_widget.hpp @@ -4,12 +4,11 @@ #include #include -#include -#include +#include +#include +#include -extern Uint32 SDL_RegisterEvents(int); -struct SDL_Renderer; -struct SDL_Texture; +extern "C" { Uint32 SDL_RegisterEvents(int); } namespace game::data { @@ -18,24 +17,27 @@ namespace game::data namespace game::ui { - class BoardWidget : public bwidgets::abstract::Widget, - public bwidgets::abstract::MouseHandler + class BoardWidget : public bwidgets::widget::Widget, + public bwidgets::widget::MouseHandler, + public bwidgets::widget::TextureHandler { protected: static const - int _border_ratio {30}; + int _border_ratio {30}; - const data::Board* _board {nullptr}; - SDL_Rect _border_area; - SDL_Texture* _circle_blue {nullptr}; - SDL_Texture* _circle_red {nullptr}; - SDL_Renderer* _renderer {nullptr}; + SDL_Rect _border_area; + bwidgets::core::Texture* _circle_blue {nullptr}; + bwidgets::core::Texture* _circle_red {nullptr}; - virtual void _draw_atoms(const SDL_Rect&, int, SDL_Texture*); + virtual void _draw_atoms(const SDL_Rect&, int, bwidgets::core::Texture*); + virtual void _handle_focus_change(bool) override {} + virtual void _handle_geometry_change(const SDL_Rect&) noexcept override; + virtual void _handle_renderer_change(bwidgets::core::Renderer*) override; + virtual void _handle_rendering() override; + virtual void _handle_texture_update() override; virtual void _render_empty_board(); virtual void _render_square_content(); - virtual void _update_textures(); public: enum struct event_code : Sint32 { @@ -43,17 +45,18 @@ namespace game::ui }; const Uint32 event_type {SDL_RegisterEvents(1)}; - SDL_Color color_bg {50, 50, 50, SDL_ALPHA_OPAQUE}; - SDL_Color color_outline {175, 175, 175, SDL_ALPHA_OPAQUE}; - SDL_Color color_p1 {255, 0, 0, SDL_ALPHA_OPAQUE}; - SDL_Color color_p2 {0, 0, 255, SDL_ALPHA_OPAQUE}; + const data::Board* board {nullptr}; + SDL_Color color_bg {50, 50, 50, SDL_ALPHA_OPAQUE}; + SDL_Color color_hl1 {255, 0, 0, SDL_ALPHA_OPAQUE/16}; + SDL_Color color_hl2 {255, 255, 0, SDL_ALPHA_OPAQUE/16}; + SDL_Color color_outline {175, 175, 175, SDL_ALPHA_OPAQUE}; + SDL_Color color_p1 {255, 0, 0, SDL_ALPHA_OPAQUE}; + SDL_Color color_p2 {0, 0, 255, SDL_ALPHA_OPAQUE}; BoardWidget(Widget* parent=nullptr); + virtual ~BoardWidget(); - void board(data::Board*); SDL_Point board_coord_from_input(const SDL_Point&) const; - void render(SDL_Renderer*); - void viewport(const SDL_Rect&); }; } #endif diff --git a/game_screen.cpp b/game_screen.cpp index 3a19c3d..c469f1d 100644 --- a/game_screen.cpp +++ b/game_screen.cpp @@ -23,8 +23,8 @@ static inline auto& cur_caption(ui::GameScreen* scr) ui::GameScreen::GameScreen() : board(this), caption_none(this), caption_p1(this), caption_p2(this) { - caption_p1.text("Player 1"); - caption_p2.text("Player 2"); + caption_p1.text("Player 1")->color_bg(board.color_outline); + caption_p2.text("Player 2")->color_bg(board.color_outline); } ui::GameScreen::~GameScreen() @@ -33,34 +33,30 @@ ui::GameScreen::~GameScreen() free(l.second); } -void ui::GameScreen::handle_event(const SDL_Event& e) +ui::GameScreen* ui::GameScreen::handle_event(const SDL_Event& e) { if (_cur_layer == nullptr) board.handle_event(e); else Layer::handle_event(e); + + return this; } -void ui::GameScreen::render(SDL_Renderer* r) +void ui::GameScreen::_handle_rendering() { - SDL_RenderSetViewport(r, &_viewport); + _renderer->draw_color(board.color_outline) + ->fill_rect(_widget_area); - SDL_SetRenderDrawColor(r, - board.color_outline.r, - board.color_outline.g, - board.color_outline.b, - board.color_outline.a - ); - SDL_RenderFillRect(r, NULL); + cur_caption(this).render(); + board.render(); - cur_caption(this).render(r); - board.render(r); - - Layer::render(r); + Layer::_handle_rendering(); } -void ui::GameScreen::viewport(const SDL_Rect& vp) +void ui::GameScreen::_handle_geometry_change(const SDL_Rect& vp) noexcept { + _widget_area = {0, 0, vp.w, vp.h}; int heighest_caption = 0; for (auto step = 0; step < 2; step++) @@ -94,15 +90,29 @@ void ui::GameScreen::viewport(const SDL_Rect& vp) _viewport = vp; } -void ui::GameScreen::_for_widgets(std::function f) +void ui::GameScreen::_for_widgets(std::function f) { - if (_cur_layer != nullptr) + if (_cur_layer) f(*_cur_layer); } -void ui::GameScreen::_handle_font_change() +void ui::GameScreen::_handle_font_change(core::Font* f) { - Layer::_handle_font_change(); + for (auto l : _layers) + l.second->font(f); + for (auto* c : {&caption_none, &caption_p1, &caption_p2}) - c->font(_font); + c->font(f); +} + +void ui::GameScreen::_handle_renderer_change(core::Renderer* r) +{ + for (auto l : _layers) + l.second->renderer(r); + + for (auto* c : {(Widget*)&board, + (Widget*)&caption_none, + (Widget*)&caption_p1, + (Widget*)&caption_p2}) + c->renderer(r); } diff --git a/game_screen.hpp b/game_screen.hpp index 91888fc..155d4ab 100644 --- a/game_screen.hpp +++ b/game_screen.hpp @@ -3,7 +3,7 @@ #include -#include +#include #include "board_widget.hpp" #include "data.hpp" @@ -13,7 +13,7 @@ struct SDL_Renderer; namespace game::ui { - class GameScreen : public Layer + class GameScreen final : public Layer { enum LayerId { MENU @@ -24,8 +24,12 @@ namespace game::ui Layers _layers; SDL_Rect _viewport {}; - void _for_widgets(std::function) override; - void _handle_font_change() override; + void _for_widgets(std::function) override; + void _handle_font_change(bwidgets::core::Font*) override; + void _handle_font_color_change(const SDL_Color&, const SDL_Color&) override {} + void _handle_geometry_change(const SDL_Rect&) noexcept override; + void _handle_renderer_change(bwidgets::core::Renderer*) override; + void _handle_rendering() override; public: BoardWidget board; @@ -37,9 +41,7 @@ namespace game::ui GameScreen(); ~GameScreen(); - void handle_event(const SDL_Event&) override; - void render(SDL_Renderer*) override; - void viewport(const SDL_Rect&) override; + virtual GameScreen* handle_event(const SDL_Event&) override; }; } diff --git a/layer.cpp b/layer.cpp index 520156c..c90ff8e 100644 --- a/layer.cpp +++ b/layer.cpp @@ -5,16 +5,15 @@ using namespace game; using namespace std; -using namespace bwidgets::abstract; +using namespace bwidgets; -ui::Layer::Layer(Widget* parent) +ui::Layer::Layer(widget::Widget* parent) : Widget(parent) { } -void ui::Layer::_handle_font_change() +void ui::Layer::_handle_font_change(core::Font* f) { - auto f = _font; _for_widgets([f](Widget& w) { try { auto& handler = dynamic_cast(w); @@ -23,23 +22,24 @@ void ui::Layer::_handle_font_change() }); } -void ui::Layer::handle_event(const SDL_Event& e) +ui::Layer* ui::Layer::handle_event(const SDL_Event& e) { _for_widgets([e](Widget& w) { w.handle_event(e); }); + return this; } -void ui::Layer::render(SDL_Renderer* r) +void ui::Layer::_handle_renderer_change(core::Renderer* r) { _for_widgets([r](Widget& w) { - w.render(r); + w.renderer(r); }); } -void ui::Layer::viewport(const SDL_Rect& vp) +void ui::Layer::_handle_rendering() { - _for_widgets([vp](Widget& w) { - w.viewport(vp); + _for_widgets([](Widget& w) { + w.render(); }); } diff --git a/layer.hpp b/layer.hpp index 9705d4a..6094619 100644 --- a/layer.hpp +++ b/layer.hpp @@ -3,32 +3,28 @@ #include -#include -#include +#include +#include union SDL_Event; struct SDL_Rect; struct SDL_Renderer; -namespace bwidgets::abstract { - class Widget; -} - namespace game::ui { - class Layer : public bwidgets::abstract::Widget, - public bwidgets::abstract::FontHandler + class Layer : public bwidgets::widget::Widget, + public bwidgets::widget::FontHandler { - protected: - virtual void _for_widgets(std::function) = 0; - virtual void _handle_font_change() override; + protected: + virtual void _for_widgets(std::function) = 0; + virtual void _handle_font_change(bwidgets::core::Font*) override; + virtual void _handle_renderer_change(bwidgets::core::Renderer*) override; + virtual void _handle_rendering() override; - public: - Layer(Widget* parent=nullptr); + public: + Layer(Widget* parent=nullptr); - void handle_event(const SDL_Event&) override; - void render(SDL_Renderer*) override; - void viewport(const SDL_Rect&) override; + virtual Layer* handle_event(const SDL_Event&) override; }; } diff --git a/main.cpp b/main.cpp index 9cc4c12..7a2be0e 100644 --- a/main.cpp +++ b/main.cpp @@ -2,11 +2,12 @@ #include -#include +#include #include "game_screen.hpp" #include "game.hpp" +using namespace bwidgets; using namespace game; int main() @@ -23,21 +24,21 @@ int main() height, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE ); - SDL_Renderer* rend = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED); - SDL_SetRenderDrawBlendMode(rend, SDL_BLENDMODE_BLEND); + auto* rend = new core::Renderer(win, -1, SDL_RENDERER_ACCELERATED); + rend->blend_mode(SDL_BLENDMODE_BLEND); SDL_Rect viewport {2, 2, width - 4, height - 4}; TTF_Init(); - std::string font_file = bwidgets::utils::font::find("Monospace"); - TTF_Font* font = TTF_OpenFont(font_file.c_str(), 20); + auto* font = new core::Font(core::Font::find("Monospace"), 20); data::Board board(4, 3); data::Board transition_board(board); ui::GameScreen game_screen; - game_screen.board.board(&board); + game_screen.board.board = &board; game_screen.font(font); + game_screen.renderer(rend); game_screen.viewport(viewport); bool quit = false; @@ -63,9 +64,9 @@ int main() if (ev.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) { - SDL_GetRendererOutputSize(rend, &width, &height); - viewport.w = width - 4; - viewport.h = height - 4; + auto s = rend->output_size(); + viewport.w = s.w - 4; + viewport.h = s.h - 4; game_screen.viewport(viewport); } @@ -104,33 +105,32 @@ int main() } - SDL_SetRenderDrawColor(rend, 0, 0, 0, SDL_ALPHA_OPAQUE); - SDL_RenderClear(rend); + rend->draw_color({0, 0, 0, SDL_ALPHA_OPAQUE})->clear(); if (transitions_iterator < transitions.size()) { if (auto t = SDL_GetTicks(); t - transitions_timer > 750) { - game_screen.board.board(&transitions[transitions_iterator]); + game_screen.board.board = &transitions[transitions_iterator]; transitions_iterator++; transitions_timer = t; } } else if (transitions_iterator > 0 && transitions_iterator == transitions.size()) { - game_screen.board.board(&board); + game_screen.board.board = &board; transitions_iterator = 0; transitions.clear(); } - game_screen.render(rend); + game_screen.render(); - SDL_RenderPresent(rend); + rend->present(); } - TTF_CloseFont(font); + delete font; + delete rend; TTF_Quit(); - SDL_DestroyRenderer(rend); SDL_DestroyWindow(win); SDL_Quit(); return 0;