Show available missions
This commit is contained in:
parent
6d8ada3f18
commit
a904f0cdaf
@ -8,9 +8,6 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#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 {
|
class AMI final : public View {
|
||||||
public:
|
public:
|
||||||
AMI(SDL_Renderer* renderer);
|
AMI(SDL_Renderer* renderer);
|
||||||
@ -24,4 +21,6 @@ private:
|
|||||||
|
|
||||||
ImageWidget ft_logo;
|
ImageWidget ft_logo;
|
||||||
TextWidget choose;
|
TextWidget choose;
|
||||||
|
ListWidget missions_widget;
|
||||||
|
std::vector<std::unique_ptr<Widget>> missions;
|
||||||
};
|
};
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
enum class Alignment { LEFT, RIGHT, CENTER };
|
enum class Alignment { LEFT, RIGHT, CENTER };
|
||||||
struct PositionInfo {
|
struct PositionInfo {
|
||||||
@ -25,6 +26,10 @@ public:
|
|||||||
virtual void set_position(int x, int y);
|
virtual void set_position(int x, int y);
|
||||||
virtual void set_alignment(Alignment align);
|
virtual void set_alignment(Alignment align);
|
||||||
|
|
||||||
|
int get_width();
|
||||||
|
int get_height();
|
||||||
|
const PositionInfo& get_position();
|
||||||
|
|
||||||
virtual void draw() = 0;
|
virtual void draw() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -69,3 +74,22 @@ protected:
|
|||||||
|
|
||||||
SDL_Texture* generate_text(const std::string& text);
|
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 "defines.h"
|
||||||
#include "util.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)
|
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,
|
ft_logo{renderer, FT_LOGO_PATH}, choose{renderer, avenir,
|
||||||
"Choose a mission:"} {
|
"Choose a mission:"},
|
||||||
ft_logo.set_height(40);
|
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_position(SCREEN_WIDTH / 2, 0);
|
||||||
ft_logo.set_alignment(Alignment::CENTER);
|
ft_logo.set_alignment(Alignment::CENTER);
|
||||||
widgets.push_back(&ft_logo);
|
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);
|
choose.set_alignment(Alignment::CENTER);
|
||||||
widgets.push_back(&choose);
|
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() {
|
void AMI::draw() {
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "AMI.h"
|
#include "AMI.h"
|
||||||
|
|
||||||
|
#include <SDL2/SDL.h>
|
||||||
#include <SDL2/SDL_image.h>
|
#include <SDL2/SDL_image.h>
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
#include "widgets.h"
|
#include "widgets.h"
|
||||||
|
|
||||||
|
#include "defines.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
#include <SDL2/SDL.h>
|
||||||
#include <SDL2/SDL_image.h>
|
#include <SDL2/SDL_image.h>
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
@ -40,6 +42,12 @@ void Widget::set_alignment(Alignment align) {
|
|||||||
recalculate_rect();
|
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() {
|
void Widget::recalculate_rect() {
|
||||||
int x = pos.x;
|
int x = pos.x;
|
||||||
int y = pos.y;
|
int y = pos.y;
|
||||||
@ -130,3 +138,62 @@ SDL_Texture* TextWidget::generate_text(const std::string& text) {
|
|||||||
}
|
}
|
||||||
return texture;
|
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);
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user