Compare commits
2 Commits
882a645926
...
2e76523bf4
Author | SHA1 | Date |
---|---|---|
Jasper Blanckenburg | 2e76523bf4 | |
Jasper Blanckenburg | 654c71f3ee |
|
@ -39,7 +39,7 @@ add_executable(
|
||||||
src/main.cpp
|
src/main.cpp
|
||||||
src/App.cpp
|
src/App.cpp
|
||||||
src/View.cpp
|
src/View.cpp
|
||||||
src/AMI.cpp
|
src/MissionSelect.cpp
|
||||||
src/widgets.cpp
|
src/widgets.cpp
|
||||||
src/util.cpp
|
src/util.cpp
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "AMI.h"
|
#include "MissionSelect.h"
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
|
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
enum class AppView { AMI, DRIVER, TESTING };
|
enum class AppView { MISSION_SELECT, AMI, DRIVER, TESTING };
|
||||||
|
|
||||||
class SDLManager {
|
class SDLManager {
|
||||||
public:
|
public:
|
||||||
|
@ -33,7 +33,7 @@ private:
|
||||||
// others and its destructor is called after the others.
|
// others and its destructor is called after the others.
|
||||||
SDLManager sdl_manager;
|
SDLManager sdl_manager;
|
||||||
|
|
||||||
std::unique_ptr<AMI> ami;
|
std::unique_ptr<MissionSelect> mission_select;
|
||||||
|
|
||||||
bool running;
|
bool running;
|
||||||
AppView view;
|
AppView view;
|
||||||
|
|
|
@ -1,19 +1,22 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "View.h"
|
#include "View.h"
|
||||||
|
#include "events.h"
|
||||||
#include "widgets.h"
|
#include "widgets.h"
|
||||||
|
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <queue>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class AMI final : public View {
|
class MissionSelect final : public View {
|
||||||
public:
|
public:
|
||||||
AMI(SDL_Renderer* renderer);
|
MissionSelect(SDL_Renderer* renderer);
|
||||||
~AMI();
|
~MissionSelect();
|
||||||
|
|
||||||
void draw() override;
|
void draw() override;
|
||||||
|
void handle_events(std::queue<Event>& events) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TTF_Font* avenir;
|
TTF_Font* avenir;
|
|
@ -1,13 +1,18 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "events.h"
|
||||||
|
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
class View {
|
class View {
|
||||||
public:
|
public:
|
||||||
View(SDL_Renderer* renderer);
|
View(SDL_Renderer* renderer);
|
||||||
virtual ~View();
|
virtual ~View();
|
||||||
|
|
||||||
virtual void draw() = 0;
|
virtual void draw() = 0;
|
||||||
|
virtual void handle_events(std::queue<Event>& events) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
SDL_Renderer* renderer;
|
SDL_Renderer* renderer;
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
enum class Event { Next, Prev, Confirm };
|
|
@ -85,10 +85,16 @@ public:
|
||||||
|
|
||||||
virtual void draw() override;
|
virtual void draw() override;
|
||||||
|
|
||||||
|
void select_next();
|
||||||
|
void select_prev();
|
||||||
|
size_t get_selection();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int element_height;
|
int element_height;
|
||||||
Alignment element_alignment;
|
Alignment element_alignment;
|
||||||
|
|
||||||
|
size_t selection;
|
||||||
|
|
||||||
std::vector<Widget*> elements;
|
std::vector<Widget*> elements;
|
||||||
|
|
||||||
void place_element(Widget* element, int index);
|
void place_element(Widget* element, int index);
|
||||||
|
|
39
src/App.cpp
39
src/App.cpp
|
@ -1,14 +1,18 @@
|
||||||
#include "App.h"
|
#include "App.h"
|
||||||
|
|
||||||
#include "AMI.h"
|
#include "MissionSelect.h"
|
||||||
|
#include "events.h"
|
||||||
|
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
#include <SDL2/SDL_events.h>
|
||||||
#include <SDL2/SDL_image.h>
|
#include <SDL2/SDL_image.h>
|
||||||
|
#include <SDL2/SDL_keycode.h>
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
#include <queue>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
App::App() : view{AppView::AMI} { init_sdl(); }
|
App::App() : view{AppView::MISSION_SELECT} { init_sdl(); }
|
||||||
|
|
||||||
App::~App() {
|
App::~App() {
|
||||||
// Destroy window
|
// Destroy window
|
||||||
|
@ -34,7 +38,7 @@ void App::init_sdl() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int App::run() {
|
int App::run() {
|
||||||
ami = std::make_unique<AMI>(renderer);
|
mission_select = std::make_unique<MissionSelect>(renderer);
|
||||||
|
|
||||||
running = true;
|
running = true;
|
||||||
|
|
||||||
|
@ -48,18 +52,43 @@ int App::run() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::handle_events() {
|
void App::handle_events() {
|
||||||
|
std::queue<Event> events;
|
||||||
SDL_Event e;
|
SDL_Event e;
|
||||||
while (SDL_PollEvent(&e) != 0) {
|
while (SDL_PollEvent(&e) != 0) {
|
||||||
if (e.type == SDL_QUIT) {
|
if (e.type == SDL_QUIT) {
|
||||||
running = false;
|
running = false;
|
||||||
|
} else if (e.type == SDL_KEYUP) {
|
||||||
|
switch (e.key.keysym.sym) {
|
||||||
|
case SDLK_DOWN:
|
||||||
|
case SDLK_RIGHT:
|
||||||
|
events.push(Event::Next);
|
||||||
|
break;
|
||||||
|
case SDLK_UP:
|
||||||
|
case SDLK_LEFT:
|
||||||
|
events.push(Event::Prev);
|
||||||
|
break;
|
||||||
|
case SDLK_RETURN:
|
||||||
|
case SDLK_KP_ENTER:
|
||||||
|
events.push(Event::Confirm);
|
||||||
|
break;
|
||||||
|
// We can just ignore other keypresses, so no need for a default clause
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (view) {
|
||||||
|
case AppView::MISSION_SELECT:
|
||||||
|
mission_select->handle_events(events);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw std::runtime_error(fmt::format("Unknown view: {}", (int)view));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::render() {
|
void App::render() {
|
||||||
switch (view) {
|
switch (view) {
|
||||||
case AppView::AMI:
|
case AppView::MISSION_SELECT:
|
||||||
ami->draw();
|
mission_select->draw();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error(fmt::format("Unknown view: {}", (int)view));
|
throw std::runtime_error(fmt::format("Unknown view: {}", (int)view));
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
#include "AMI.h"
|
#include "MissionSelect.h"
|
||||||
|
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
|
#include "events.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "widgets.h"
|
#include "widgets.h"
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
constexpr const char* FT_LOGO_PATH = "resources/Fasttube_Logo-white.bmp";
|
constexpr const char* FT_LOGO_PATH = "resources/Fasttube_Logo-white.bmp";
|
||||||
|
@ -20,7 +24,7 @@ constexpr std::array MISSIONS = {"ACCELERATION", "SKIDPAD", "AUTOCROSS",
|
||||||
"TRACKDRIVE", "EBS TEST", "INSPECTION",
|
"TRACKDRIVE", "EBS TEST", "INSPECTION",
|
||||||
"MANUAL DRIVING"};
|
"MANUAL DRIVING"};
|
||||||
|
|
||||||
AMI::AMI(SDL_Renderer* renderer)
|
MissionSelect::MissionSelect(SDL_Renderer* renderer)
|
||||||
: View{renderer}, avenir{util::load_font(AVENIR_FONT_PATH, AVENIR_PTS)},
|
: View{renderer}, avenir{util::load_font(AVENIR_FONT_PATH, AVENIR_PTS)},
|
||||||
chinat{util::load_font(CHINAT_FONT_PATH, CHINAT_PTS)} {
|
chinat{util::load_font(CHINAT_FONT_PATH, CHINAT_PTS)} {
|
||||||
ft_logo = std::make_unique<ImageWidget>(renderer, FT_LOGO_PATH);
|
ft_logo = std::make_unique<ImageWidget>(renderer, FT_LOGO_PATH);
|
||||||
|
@ -51,15 +55,36 @@ AMI::AMI(SDL_Renderer* renderer)
|
||||||
widgets.push_back(missions_widget.get());
|
widgets.push_back(missions_widget.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
AMI::~AMI() {
|
MissionSelect::~MissionSelect() {
|
||||||
TTF_CloseFont(avenir);
|
TTF_CloseFont(avenir);
|
||||||
TTF_CloseFont(chinat);
|
TTF_CloseFont(chinat);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AMI::draw() {
|
void MissionSelect::draw() {
|
||||||
SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0xFF);
|
SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0xFF);
|
||||||
SDL_RenderClear(renderer);
|
SDL_RenderClear(renderer);
|
||||||
for (const auto& widget : widgets) {
|
for (const auto& widget : widgets) {
|
||||||
widget->draw();
|
widget->draw();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MissionSelect::handle_events(std::queue<Event>& events) {
|
||||||
|
while (!events.empty()) {
|
||||||
|
Event e = events.front();
|
||||||
|
events.pop();
|
||||||
|
switch (e) {
|
||||||
|
case Event::Next:
|
||||||
|
missions_widget->select_next();
|
||||||
|
break;
|
||||||
|
case Event::Prev:
|
||||||
|
missions_widget->select_prev();
|
||||||
|
break;
|
||||||
|
case Event::Confirm:
|
||||||
|
std::cout << fmt::format("Selected mission {}\n",
|
||||||
|
missions_widget->get_selection());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw std::runtime_error(fmt::format("Unknown event: {}", (int)e));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -7,8 +7,19 @@
|
||||||
#include <SDL2/SDL_image.h>
|
#include <SDL2/SDL_image.h>
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
constexpr uint8_t LIST_SELECTION_BG_R = 0x77;
|
||||||
|
constexpr uint8_t LIST_SELECTION_BG_G = 0x33;
|
||||||
|
constexpr uint8_t LIST_SELECTION_BG_B = 0x33;
|
||||||
|
constexpr uint8_t LIST_OTHER_BG_R = 0x22;
|
||||||
|
constexpr uint8_t LIST_OTHER_BG_G = 0x22;
|
||||||
|
constexpr uint8_t LIST_OTHER_BG_B = 0x22;
|
||||||
|
constexpr uint8_t LIST_NORMAL_BG_R = 0x00;
|
||||||
|
constexpr uint8_t LIST_NORMAL_BG_G = 0x00;
|
||||||
|
constexpr uint8_t LIST_NORMAL_BG_B = 0x00;
|
||||||
|
|
||||||
PositionInfo::PositionInfo() : x{0}, y{0}, align{Alignment::LEFT} {}
|
PositionInfo::PositionInfo() : x{0}, y{0}, align{Alignment::LEFT} {}
|
||||||
|
|
||||||
Widget::Widget(SDL_Renderer* renderer) : renderer{renderer}, rect{0, 0, 0, 0} {}
|
Widget::Widget(SDL_Renderer* renderer) : renderer{renderer}, rect{0, 0, 0, 0} {}
|
||||||
|
@ -144,7 +155,7 @@ SDL_Texture* TextWidget::generate_text(const std::string& text) {
|
||||||
ListWidget::ListWidget(SDL_Renderer* renderer, int element_height,
|
ListWidget::ListWidget(SDL_Renderer* renderer, int element_height,
|
||||||
Alignment element_alignment)
|
Alignment element_alignment)
|
||||||
: Widget{renderer}, element_height{element_height},
|
: Widget{renderer}, element_height{element_height},
|
||||||
element_alignment{element_alignment} {}
|
element_alignment{element_alignment}, selection{0} {}
|
||||||
|
|
||||||
ListWidget::~ListWidget() {}
|
ListWidget::~ListWidget() {}
|
||||||
|
|
||||||
|
@ -163,12 +174,19 @@ void ListWidget::draw() {
|
||||||
// Since the elements are sorted, we can stop the loop now.
|
// Since the elements are sorted, we can stop the loop now.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (i % 2 == 1) {
|
if (i == selection) {
|
||||||
SDL_SetRenderDrawColor(renderer, 0x11, 0x11, 0x11, 0xFF);
|
SDL_SetRenderDrawColor(renderer, LIST_SELECTION_BG_R, LIST_SELECTION_BG_G,
|
||||||
SDL_Rect fill_rect = {
|
LIST_SELECTION_BG_B, 0xFF);
|
||||||
.x = pos.x, .y = element_pos.y, .w = rect.w, .h = element_height};
|
} else if (i % 2 == 1) {
|
||||||
SDL_RenderFillRect(renderer, &fill_rect);
|
SDL_SetRenderDrawColor(renderer, LIST_OTHER_BG_R, LIST_OTHER_BG_G,
|
||||||
|
LIST_OTHER_BG_B, 0xFF);
|
||||||
|
} else {
|
||||||
|
SDL_SetRenderDrawColor(renderer, LIST_NORMAL_BG_R, LIST_NORMAL_BG_G,
|
||||||
|
LIST_NORMAL_BG_B, 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();
|
element->draw();
|
||||||
if (i != elements.size() - 1) {
|
if (i != elements.size() - 1) {
|
||||||
int border_y = element_pos.y + element->get_height();
|
int border_y = element_pos.y + element->get_height();
|
||||||
|
@ -178,6 +196,28 @@ void ListWidget::draw() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ListWidget::select_next() {
|
||||||
|
size_t n = elements.size();
|
||||||
|
if (n == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
selection = (selection + 1) % n;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListWidget::select_prev() {
|
||||||
|
size_t n = elements.size();
|
||||||
|
if (n == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (selection == 0) {
|
||||||
|
selection = n - 1;
|
||||||
|
} else {
|
||||||
|
selection = selection - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ListWidget::get_selection() { return selection; }
|
||||||
|
|
||||||
void ListWidget::place_element(Widget* element, int index) {
|
void ListWidget::place_element(Widget* element, int index) {
|
||||||
int x = rect.x;
|
int x = rect.x;
|
||||||
switch (element_alignment) {
|
switch (element_alignment) {
|
||||||
|
|
Loading…
Reference in New Issue