Set dimensions, position & alignment separately
This commit is contained in:
		@ -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<std::unique_ptr<Widget>> widgets;
 | 
			
		||||
  std::vector<Widget*> widgets;
 | 
			
		||||
 | 
			
		||||
  ImageWidget ft_logo;
 | 
			
		||||
  TextWidget choose;
 | 
			
		||||
};
 | 
			
		||||
@ -5,6 +5,7 @@
 | 
			
		||||
class View {
 | 
			
		||||
public:
 | 
			
		||||
  View(SDL_Renderer* renderer);
 | 
			
		||||
  virtual ~View();
 | 
			
		||||
 | 
			
		||||
  virtual void draw() = 0;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -6,24 +6,36 @@
 | 
			
		||||
#include <optional>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
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<SDL_Texture*> texture);
 | 
			
		||||
  TextureWidget(SDL_Renderer* renderer, std::optional<SDL_Texture*> 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<SDL_Texture*> 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();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										18
									
								
								src/AMI.cpp
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								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<ImageWidget>(renderer, logo_rect, FT_LOGO_PATH));
 | 
			
		||||
  SDL_Rect choose_rect = {.x = 0, .y = 45, .w = 480, .h = 40};
 | 
			
		||||
  widgets.emplace_back(std::make_unique<TextWidget>(
 | 
			
		||||
      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() {
 | 
			
		||||
 | 
			
		||||
@ -1,3 +1,4 @@
 | 
			
		||||
#include "View.h"
 | 
			
		||||
 | 
			
		||||
View::View(SDL_Renderer* renderer) : renderer{renderer} {}
 | 
			
		||||
View::View(SDL_Renderer* renderer) : renderer{renderer} {}
 | 
			
		||||
View::~View() {}
 | 
			
		||||
@ -7,16 +7,64 @@
 | 
			
		||||
 | 
			
		||||
#include <stdexcept>
 | 
			
		||||
 | 
			
		||||
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<SDL_Texture*> 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));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user