Show available missions
This commit is contained in:
		@ -8,9 +8,6 @@
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
constexpr const char* FT_LOGO_PATH = "resources/Fasttube_Logo-white.bmp";
 | 
			
		||||
constexpr const char* AVENIR_FONT_PATH = "resources/Avenir-Book.ttf";
 | 
			
		||||
 | 
			
		||||
class AMI final : public View {
 | 
			
		||||
public:
 | 
			
		||||
  AMI(SDL_Renderer* renderer);
 | 
			
		||||
@ -24,4 +21,6 @@ private:
 | 
			
		||||
 | 
			
		||||
  ImageWidget ft_logo;
 | 
			
		||||
  TextWidget choose;
 | 
			
		||||
  ListWidget missions_widget;
 | 
			
		||||
  std::vector<std::unique_ptr<Widget>> missions;
 | 
			
		||||
};
 | 
			
		||||
@ -5,6 +5,7 @@
 | 
			
		||||
 | 
			
		||||
#include <optional>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
enum class Alignment { LEFT, RIGHT, CENTER };
 | 
			
		||||
struct PositionInfo {
 | 
			
		||||
@ -25,6 +26,10 @@ public:
 | 
			
		||||
  virtual void set_position(int x, int y);
 | 
			
		||||
  virtual void set_alignment(Alignment align);
 | 
			
		||||
 | 
			
		||||
  int get_width();
 | 
			
		||||
  int get_height();
 | 
			
		||||
  const PositionInfo& get_position();
 | 
			
		||||
 | 
			
		||||
  virtual void draw() = 0;
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
@ -69,3 +74,22 @@ protected:
 | 
			
		||||
 | 
			
		||||
  SDL_Texture* generate_text(const std::string& text);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class ListWidget : public Widget {
 | 
			
		||||
public:
 | 
			
		||||
  ListWidget(SDL_Renderer* renderer, int element_height,
 | 
			
		||||
             Alignment element_alignment);
 | 
			
		||||
  virtual ~ListWidget();
 | 
			
		||||
 | 
			
		||||
  void add_element(Widget* element);
 | 
			
		||||
 | 
			
		||||
  virtual void draw() override;
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
  int element_height;
 | 
			
		||||
  Alignment element_alignment;
 | 
			
		||||
 | 
			
		||||
  std::vector<Widget*> elements;
 | 
			
		||||
 | 
			
		||||
  void place_element(Widget* element, int index);
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										39
									
								
								src/AMI.cpp
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								src/AMI.cpp
									
									
									
									
									
								
							@ -2,18 +2,49 @@
 | 
			
		||||
 | 
			
		||||
#include "defines.h"
 | 
			
		||||
#include "util.h"
 | 
			
		||||
#include "widgets.h"
 | 
			
		||||
 | 
			
		||||
#include <array>
 | 
			
		||||
 | 
			
		||||
constexpr const char* FT_LOGO_PATH = "resources/Fasttube_Logo-white.bmp";
 | 
			
		||||
constexpr const char* AVENIR_FONT_PATH = "resources/Avenir-Book.ttf";
 | 
			
		||||
constexpr int AVENIR_PTS = 20;
 | 
			
		||||
constexpr int FT_LOGO_HEIGHT = 40;
 | 
			
		||||
constexpr int GAP = 5;
 | 
			
		||||
constexpr int CHOOSE_Y = FT_LOGO_HEIGHT + GAP;
 | 
			
		||||
constexpr int MISSION_HEIGHT = 30;
 | 
			
		||||
 | 
			
		||||
constexpr std::array MISSIONS = {"ACCELERATION",  "SKIDPAD",  "AUTOCROSS",
 | 
			
		||||
                                 "TRACKDRIVE",    "EBS TEST", "INSPECTION",
 | 
			
		||||
                                 "MANUAL DRIVING"};
 | 
			
		||||
 | 
			
		||||
AMI::AMI(SDL_Renderer* renderer)
 | 
			
		||||
    : View{renderer}, avenir{util::load_font(AVENIR_FONT_PATH, 20)},
 | 
			
		||||
    : View{renderer}, avenir{util::load_font(AVENIR_FONT_PATH, AVENIR_PTS)},
 | 
			
		||||
      ft_logo{renderer, FT_LOGO_PATH}, choose{renderer, avenir,
 | 
			
		||||
                                              "Choose a mission:"} {
 | 
			
		||||
  ft_logo.set_height(40);
 | 
			
		||||
                                              "Choose a mission:"},
 | 
			
		||||
      missions_widget{renderer, MISSION_HEIGHT, Alignment::CENTER} {
 | 
			
		||||
  ft_logo.set_height(FT_LOGO_HEIGHT);
 | 
			
		||||
  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_position(SCREEN_WIDTH / 2, CHOOSE_Y);
 | 
			
		||||
  choose.set_alignment(Alignment::CENTER);
 | 
			
		||||
  widgets.push_back(&choose);
 | 
			
		||||
 | 
			
		||||
  int choose_height = choose.get_height();
 | 
			
		||||
  int missions_y = CHOOSE_Y + choose_height + GAP;
 | 
			
		||||
  int missions_height = SCREEN_HEIGHT - CHOOSE_Y - choose_height - 1;
 | 
			
		||||
  missions_widget.set_position(0, missions_y);
 | 
			
		||||
  missions_widget.set_width(SCREEN_WIDTH, false);
 | 
			
		||||
  missions_widget.set_height(missions_height, false);
 | 
			
		||||
  for (const auto mission : MISSIONS) {
 | 
			
		||||
    missions.push_back(std::make_unique<TextWidget>(renderer, avenir, mission));
 | 
			
		||||
  }
 | 
			
		||||
  for (const auto& mission : missions) {
 | 
			
		||||
    missions_widget.add_element(mission.get());
 | 
			
		||||
  }
 | 
			
		||||
  widgets.push_back(&missions_widget);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void AMI::draw() {
 | 
			
		||||
 | 
			
		||||
@ -2,6 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include "AMI.h"
 | 
			
		||||
 | 
			
		||||
#include <SDL2/SDL.h>
 | 
			
		||||
#include <SDL2/SDL_image.h>
 | 
			
		||||
#include <fmt/format.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,9 @@
 | 
			
		||||
#include "widgets.h"
 | 
			
		||||
 | 
			
		||||
#include "defines.h"
 | 
			
		||||
#include "util.h"
 | 
			
		||||
 | 
			
		||||
#include <SDL2/SDL.h>
 | 
			
		||||
#include <SDL2/SDL_image.h>
 | 
			
		||||
#include <fmt/format.h>
 | 
			
		||||
 | 
			
		||||
@ -40,6 +42,12 @@ void Widget::set_alignment(Alignment align) {
 | 
			
		||||
  recalculate_rect();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int Widget::get_width() { return rect.w; }
 | 
			
		||||
 | 
			
		||||
int Widget::get_height() { return rect.h; }
 | 
			
		||||
 | 
			
		||||
const PositionInfo& Widget::get_position() { return pos; }
 | 
			
		||||
 | 
			
		||||
void Widget::recalculate_rect() {
 | 
			
		||||
  int x = pos.x;
 | 
			
		||||
  int y = pos.y;
 | 
			
		||||
@ -130,3 +138,62 @@ SDL_Texture* TextWidget::generate_text(const std::string& text) {
 | 
			
		||||
  }
 | 
			
		||||
  return texture;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ListWidget::ListWidget(SDL_Renderer* renderer, int element_height,
 | 
			
		||||
                       Alignment element_alignment)
 | 
			
		||||
    : Widget{renderer}, element_height{element_height},
 | 
			
		||||
      element_alignment{element_alignment} {}
 | 
			
		||||
 | 
			
		||||
ListWidget::~ListWidget() {}
 | 
			
		||||
 | 
			
		||||
void ListWidget::add_element(Widget* element) {
 | 
			
		||||
  int new_index = elements.size();
 | 
			
		||||
  elements.push_back(element);
 | 
			
		||||
  place_element(element, new_index);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ListWidget::draw() {
 | 
			
		||||
  int max_y = rect.y + rect.h;
 | 
			
		||||
  for (size_t i = 0; i < elements.size(); i++) {
 | 
			
		||||
    const auto& element = elements[i];
 | 
			
		||||
    const PositionInfo& element_pos = element->get_position();
 | 
			
		||||
    if (element_pos.y >= max_y) {
 | 
			
		||||
      // Since the elements are sorted, we can stop the loop now.
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    if (i % 2 == 1) {
 | 
			
		||||
      SDL_SetRenderDrawColor(renderer, 0x11, 0x11, 0x11, 0xFF);
 | 
			
		||||
      SDL_Rect fill_rect = {
 | 
			
		||||
          .x = pos.x, .y = element_pos.y, .w = rect.w, .h = element_height};
 | 
			
		||||
      SDL_RenderFillRect(renderer, &fill_rect);
 | 
			
		||||
    }
 | 
			
		||||
    element->draw();
 | 
			
		||||
    if (i != elements.size() - 1) {
 | 
			
		||||
      int border_y = element_pos.y + element->get_height();
 | 
			
		||||
      SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF);
 | 
			
		||||
      SDL_RenderDrawLine(renderer, rect.x, border_y, rect.x + rect.w, border_y);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ListWidget::place_element(Widget* element, int index) {
 | 
			
		||||
  int x = rect.x;
 | 
			
		||||
  switch (element_alignment) {
 | 
			
		||||
  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));
 | 
			
		||||
  }
 | 
			
		||||
  // Additional pixel for border
 | 
			
		||||
  int y = rect.y + index * (element_height + 1);
 | 
			
		||||
  element->set_position(x, y);
 | 
			
		||||
  element->set_alignment(element_alignment);
 | 
			
		||||
  element->set_height(element_height);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user