From 3934e4777f3f335c34b79c6f32156af7771e5097 Mon Sep 17 00:00:00 2001 From: Jasper Date: Thu, 19 May 2022 23:31:53 +0200 Subject: [PATCH] Set dimensions, position & alignment separately --- include/AMI.h | 7 +++-- include/View.h | 1 + include/widgets.h | 28 ++++++++++++----- src/AMI.cpp | 18 ++++++----- src/View.cpp | 3 +- src/widgets.cpp | 80 +++++++++++++++++++++++++++++++++++++++-------- 6 files changed, 106 insertions(+), 31 deletions(-) diff --git a/include/AMI.h b/include/AMI.h index 0694df2..d4db314 100644 --- a/include/AMI.h +++ b/include/AMI.h @@ -11,7 +11,7 @@ constexpr const char* FT_LOGO_PATH = "resources/Fasttube_Logo-white.bmp"; constexpr const char* AVENIR_FONT_PATH = "resources/Avenir-Book.ttf"; -class AMI : public View { +class AMI final : public View { public: AMI(SDL_Renderer* renderer); @@ -20,5 +20,8 @@ public: private: TTF_Font* avenir; - std::vector> widgets; + std::vector widgets; + + ImageWidget ft_logo; + TextWidget choose; }; \ No newline at end of file diff --git a/include/View.h b/include/View.h index dfb3ab8..e1943c1 100644 --- a/include/View.h +++ b/include/View.h @@ -5,6 +5,7 @@ class View { public: View(SDL_Renderer* renderer); + virtual ~View(); virtual void draw() = 0; diff --git a/include/widgets.h b/include/widgets.h index 2ce6d01..0bcdbc3 100644 --- a/include/widgets.h +++ b/include/widgets.h @@ -6,24 +6,36 @@ #include #include +enum class Alignment { LEFT, RIGHT, CENTER }; +struct PositionInfo { + int x; + int y; + Alignment align; +}; + class Widget { public: - Widget(SDL_Renderer* renderer, SDL_Rect dest_rect); + Widget(SDL_Renderer* renderer); virtual ~Widget(); - virtual void update_rect(SDL_Rect new_rect); + virtual void set_width(int width, bool preserve_aspect_ratio = true); + virtual void set_height(int height, bool preserve_aspect_ratio = true); + virtual void set_position(int x, int y); + virtual void set_alignment(Alignment align); virtual void draw() = 0; protected: + void recalculate_rect(); + SDL_Renderer* renderer; - SDL_Rect dest_rect; + SDL_Rect rect; + PositionInfo pos; }; class TextureWidget : public Widget { public: - TextureWidget(SDL_Renderer* renderer, SDL_Rect dest_rect, - std::optional texture); + TextureWidget(SDL_Renderer* renderer, std::optional texture); ~TextureWidget(); virtual void draw() override; @@ -31,18 +43,18 @@ public: void update_texture(SDL_Texture* new_texture); private: + void update_dimensions_from_texture(SDL_Texture* texture); std::optional texture; }; class ImageWidget : public TextureWidget { public: - ImageWidget(SDL_Renderer* renderer, SDL_Rect dest_rect, - const std::string& path); + ImageWidget(SDL_Renderer* renderer, const std::string& path); }; class TextWidget : public TextureWidget { public: - TextWidget(SDL_Renderer* renderer, SDL_Rect dest_rect, TTF_Font* font, + TextWidget(SDL_Renderer* renderer, TTF_Font* font, const std::string& initial_text = ""); ~TextWidget(); diff --git a/src/AMI.cpp b/src/AMI.cpp index 9d3d822..c4b28c0 100644 --- a/src/AMI.cpp +++ b/src/AMI.cpp @@ -1,15 +1,19 @@ #include "AMI.h" +#include "App.h" #include "util.h" AMI::AMI(SDL_Renderer* renderer) - : View{renderer}, avenir{util::load_font(AVENIR_FONT_PATH, 28)} { - SDL_Rect logo_rect = {.x = 182, .y = 0, .w = 116, .h = 40}; - widgets.emplace_back( - std::make_unique(renderer, logo_rect, FT_LOGO_PATH)); - SDL_Rect choose_rect = {.x = 0, .y = 45, .w = 480, .h = 40}; - widgets.emplace_back(std::make_unique( - renderer, choose_rect, avenir, "Choose a Mission:")); + : View{renderer}, avenir{util::load_font(AVENIR_FONT_PATH, 20)}, + ft_logo{renderer, FT_LOGO_PATH}, choose{renderer, avenir, + "Choose a mission:"} { + ft_logo.set_height(40); + ft_logo.set_position(SCREEN_WIDTH / 2, 0); + ft_logo.set_alignment(Alignment::CENTER); + widgets.push_back(&ft_logo); + choose.set_position(SCREEN_WIDTH / 2, 45); + choose.set_alignment(Alignment::CENTER); + widgets.push_back(&choose); } void AMI::draw() { diff --git a/src/View.cpp b/src/View.cpp index eb92227..c77298d 100644 --- a/src/View.cpp +++ b/src/View.cpp @@ -1,3 +1,4 @@ #include "View.h" -View::View(SDL_Renderer* renderer) : renderer{renderer} {} \ No newline at end of file +View::View(SDL_Renderer* renderer) : renderer{renderer} {} +View::~View() {} \ No newline at end of file diff --git a/src/widgets.cpp b/src/widgets.cpp index e47b4a2..d02628a 100644 --- a/src/widgets.cpp +++ b/src/widgets.cpp @@ -7,16 +7,64 @@ #include -Widget::Widget(SDL_Renderer* renderer, SDL_Rect rect) - : renderer{renderer}, dest_rect{rect} {} +Widget::Widget(SDL_Renderer* renderer) : renderer{renderer}, rect{0, 0, 0, 0} {} Widget::~Widget() {} -void Widget::update_rect(SDL_Rect new_rect) { dest_rect = new_rect; } +void Widget::set_width(int width, bool preserve_aspect_ratio) { + if (preserve_aspect_ratio) { + float scale = width / rect.w; + rect.h = round(rect.h * scale); + } + rect.w = width; +} -TextureWidget::TextureWidget(SDL_Renderer* renderer, SDL_Rect dest_rect, +void Widget::set_height(int height, bool preserve_aspect_ratio) { + if (preserve_aspect_ratio) { + float scale = ((float)height) / rect.h; + rect.w = round(rect.w * scale); + } + rect.h = height; +} + +void Widget::set_position(int x, int y) { + pos.x = x; + pos.y = y; + recalculate_rect(); +} + +void Widget::set_alignment(Alignment align) { + pos.align = align; + recalculate_rect(); +} + +void Widget::recalculate_rect() { + int x = pos.x; + int y = pos.y; + switch (pos.align) { + case Alignment::LEFT: + break; + case Alignment::RIGHT: + x -= rect.w; + break; + case Alignment::CENTER: + x -= rect.w / 2; + break; + default: + throw std::runtime_error( + fmt::format("Unknown alignment: {}", (int)pos.align)); + } + rect.x = x; + rect.y = y; +} + +TextureWidget::TextureWidget(SDL_Renderer* renderer, std::optional texture) - : Widget{renderer, dest_rect}, texture{texture} {} + : Widget{renderer}, texture{texture} { + if (texture) { + update_dimensions_from_texture(*texture); + } +} TextureWidget::~TextureWidget() { if (texture) { @@ -27,7 +75,7 @@ TextureWidget::~TextureWidget() { void TextureWidget::draw() { if (texture) { - SDL_RenderCopy(renderer, *texture, NULL, &dest_rect); + SDL_RenderCopy(renderer, *texture, NULL, &rect); } } @@ -35,17 +83,23 @@ void TextureWidget::update_texture(SDL_Texture* new_texture) { if (texture) { SDL_DestroyTexture(*texture); } + update_dimensions_from_texture(new_texture); texture = new_texture; } -ImageWidget::ImageWidget(SDL_Renderer* renderer, SDL_Rect dest_rect, - const std::string& path) - : TextureWidget{renderer, dest_rect, util::load_img(renderer, path)} {} +void TextureWidget::update_dimensions_from_texture(SDL_Texture* texture) { + if (SDL_QueryTexture(texture, nullptr, nullptr, &rect.w, &rect.h) != 0) { + throw std::runtime_error( + fmt::format("Couldn't query texture: {}", SDL_GetError())); + } +} -TextWidget::TextWidget(SDL_Renderer* renderer, SDL_Rect dest_rect, - TTF_Font* font, const std::string& initial_text) - : TextureWidget{renderer, dest_rect, std::nullopt}, font{font}, - text{initial_text} { +ImageWidget::ImageWidget(SDL_Renderer* renderer, const std::string& path) + : TextureWidget{renderer, util::load_img(renderer, path)} {} + +TextWidget::TextWidget(SDL_Renderer* renderer, TTF_Font* font, + const std::string& initial_text) + : TextureWidget{renderer, std::nullopt}, font{font}, text{initial_text} { if (text != "") { update_texture(generate_text(text)); }