working demo driver view
This commit is contained in:
parent
938978f5d4
commit
1e378d1093
@ -1,4 +1,4 @@
|
|||||||
cmake_minimum_required(VERSION 3.18)
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
project("FT22 Steering Wheel Display")
|
project("FT22 Steering Wheel Display")
|
||||||
|
|
||||||
@ -60,6 +60,9 @@ add_executable(
|
|||||||
src/AMI.cpp
|
src/AMI.cpp
|
||||||
src/widgets.cpp
|
src/widgets.cpp
|
||||||
src/util.cpp
|
src/util.cpp
|
||||||
|
src/DriverView.cpp
|
||||||
|
src/BaseDataSource.cpp
|
||||||
|
src/DemoDataSource.cpp
|
||||||
)
|
)
|
||||||
target_include_directories(
|
target_include_directories(
|
||||||
stw-display PUBLIC
|
stw-display PUBLIC
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "AMI.h"
|
#include "AMI.h"
|
||||||
#include "AppState.h"
|
#include "AppState.h"
|
||||||
|
#include "DriverView.h"
|
||||||
#include "MissionSelect.h"
|
#include "MissionSelect.h"
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
|
|
||||||
@ -44,6 +45,7 @@ private:
|
|||||||
std::unique_ptr<AppState> state;
|
std::unique_ptr<AppState> state;
|
||||||
std::unique_ptr<MissionSelect> mission_select;
|
std::unique_ptr<MissionSelect> mission_select;
|
||||||
std::unique_ptr<AMI> ami;
|
std::unique_ptr<AMI> ami;
|
||||||
|
std::unique_ptr<DriverView> driver_view;
|
||||||
|
|
||||||
bool running;
|
bool running;
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "DemoDataSource.h"
|
||||||
|
|
||||||
#include <fmt/ostream.h>
|
#include <fmt/ostream.h>
|
||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
@ -32,6 +34,7 @@ public:
|
|||||||
|
|
||||||
AppView get_view() const;
|
AppView get_view() const;
|
||||||
Mission get_mission() const;
|
Mission get_mission() const;
|
||||||
|
DemoDataSource get_data_source() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void unmarshal_mission_select(uint8_t* data);
|
void unmarshal_mission_select(uint8_t* data);
|
||||||
@ -42,6 +45,7 @@ private:
|
|||||||
|
|
||||||
AppView view;
|
AppView view;
|
||||||
Mission mission;
|
Mission mission;
|
||||||
|
DemoDataSource data_source;
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
friend class KeyboardHandler;
|
friend class KeyboardHandler;
|
||||||
|
34
include/BaseDataSource.h
Normal file
34
include/BaseDataSource.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
class BaseDataSource {
|
||||||
|
public:
|
||||||
|
double get_speed(); // in km/h
|
||||||
|
double get_brake_balance(); // 0.0 - 1.0
|
||||||
|
double get_hv_voltage(); // in V
|
||||||
|
double get_hv_voltage_ratio(); // 0.0 - 1.0
|
||||||
|
double get_lv_voltage(); // in V
|
||||||
|
double get_battery_temperature(); // in °C
|
||||||
|
double get_throttle_ratio(); // 0.0 - 1.0
|
||||||
|
double get_brake_pressure_front_bar(); // in bar
|
||||||
|
double get_brake_pressure_rear_bar(); // in bar
|
||||||
|
|
||||||
|
bool brake_balance_change_is_recent(); // true if the last change was less
|
||||||
|
// than 1 second ago
|
||||||
|
|
||||||
|
virtual void poll() = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void set_brake_balance(double value);
|
||||||
|
|
||||||
|
double speed;
|
||||||
|
double brake_balance;
|
||||||
|
double hv_voltage;
|
||||||
|
double hv_voltage_ratio;
|
||||||
|
double lv_voltage;
|
||||||
|
double battery_temperature;
|
||||||
|
double throttle_ratio;
|
||||||
|
double brake_pressure_front_bar;
|
||||||
|
double brake_pressure_rear_bar;
|
||||||
|
|
||||||
|
int time_of_last_brake_balance_change;
|
||||||
|
};
|
13
include/DemoDataSource.h
Normal file
13
include/DemoDataSource.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "BaseDataSource.h"
|
||||||
|
|
||||||
|
class DemoDataSource final : public BaseDataSource {
|
||||||
|
public:
|
||||||
|
DemoDataSource();
|
||||||
|
~DemoDataSource();
|
||||||
|
|
||||||
|
void poll() override;
|
||||||
|
void bump_brake_balance_up();
|
||||||
|
void bump_brake_balance_down();
|
||||||
|
};
|
30
include/DriverView.h
Normal file
30
include/DriverView.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "View.h"
|
||||||
|
#include "defines.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "widgets.h"
|
||||||
|
|
||||||
|
class DriverView final : public View {
|
||||||
|
public:
|
||||||
|
DriverView(SDL_Renderer* renderer);
|
||||||
|
~DriverView();
|
||||||
|
|
||||||
|
void draw(const AppState& state) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
TTF_Font* font_large;
|
||||||
|
TTF_Font* font_detail;
|
||||||
|
TTF_Font* font_tiny;
|
||||||
|
TTF_Font* font_giant;
|
||||||
|
TTF_Font* font_medium;
|
||||||
|
std::unique_ptr<TextWidget> speed_widget;
|
||||||
|
std::unique_ptr<TextWidget> speed_hint_widget;
|
||||||
|
|
||||||
|
std::unique_ptr<TextWidget> brake_balance_widget;
|
||||||
|
std::unique_ptr<TextWidget> brake_balance_hint_widget;
|
||||||
|
|
||||||
|
std::unique_ptr<TextWidget> general_info_widget;
|
||||||
|
|
||||||
|
std::unique_ptr<TextWidget> focus_widget;
|
||||||
|
std::unique_ptr<TextWidget> focus_hint_widget;
|
||||||
|
};
|
@ -79,12 +79,13 @@ public:
|
|||||||
~TextWidget();
|
~TextWidget();
|
||||||
|
|
||||||
void update_text(const std::string& new_text);
|
void update_text(const std::string& new_text);
|
||||||
|
void set_wrap_width(int width);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
TTF_Font* font;
|
TTF_Font* font;
|
||||||
|
|
||||||
std::string text;
|
std::string text;
|
||||||
|
int wrap_width = -1; // -1 means no wrapping (default behavior)
|
||||||
SDL_Texture* generate_text(const std::string& text);
|
SDL_Texture* generate_text(const std::string& text);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
78
src/App.cpp
78
src/App.cpp
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include "AMI.h"
|
#include "AMI.h"
|
||||||
#include "AppState.h"
|
#include "AppState.h"
|
||||||
|
#include "DemoDataSource.h"
|
||||||
|
#include "DriverView.h"
|
||||||
#include "MissionSelect.h"
|
#include "MissionSelect.h"
|
||||||
#include "events.h"
|
#include "events.h"
|
||||||
|
|
||||||
@ -15,6 +17,7 @@
|
|||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
@ -60,6 +63,11 @@ void App::init_state() {
|
|||||||
int App::run() {
|
int App::run() {
|
||||||
mission_select = std::make_unique<MissionSelect>(renderer);
|
mission_select = std::make_unique<MissionSelect>(renderer);
|
||||||
ami = std::make_unique<AMI>(renderer);
|
ami = std::make_unique<AMI>(renderer);
|
||||||
|
driver_view = std::make_unique<DriverView>(renderer);
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
std::cout << "Change brake balance with W (+) and S (-)" << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
running = true;
|
running = true;
|
||||||
|
|
||||||
@ -110,6 +118,9 @@ void App::render() {
|
|||||||
case AppView::AMI:
|
case AppView::AMI:
|
||||||
ami->draw(*state);
|
ami->draw(*state);
|
||||||
break;
|
break;
|
||||||
|
case AppView::DRIVER:
|
||||||
|
driver_view->draw(*state);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error(fmt::format("Unknown view: {}", view));
|
throw std::runtime_error(fmt::format("Unknown view: {}", view));
|
||||||
}
|
}
|
||||||
@ -138,39 +149,44 @@ SDLManager::~SDLManager() {
|
|||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Handle key presses
|
||||||
|
*/
|
||||||
void KeyboardHandler::handle_keyup(const SDL_Event& ev, AppState& state) {
|
void KeyboardHandler::handle_keyup(const SDL_Event& ev, AppState& state) {
|
||||||
switch (ev.key.keysym.sym) {
|
auto pressed_key = ev.key.keysym.sym;
|
||||||
case SDLK_DOWN:
|
if (state.view == AppView::MISSION_SELECT) {
|
||||||
case SDLK_RIGHT:
|
if (pressed_key == SDLK_DOWN || pressed_key == SDLK_RIGHT) {
|
||||||
if (state.mission == Mission::MANUAL) {
|
auto new_mission = static_cast<int>(state.mission) + 1;
|
||||||
state.mission = Mission::ACCELERATION;
|
if (new_mission > 7) {
|
||||||
} else {
|
new_mission = 1;
|
||||||
state.mission = static_cast<Mission>(static_cast<int>(state.mission) + 1);
|
}
|
||||||
|
std::cout << "New mission: " << new_mission << std::endl;
|
||||||
|
state.mission = static_cast<Mission>(new_mission);
|
||||||
|
} else if (pressed_key == SDLK_UP || pressed_key == SDLK_LEFT) {
|
||||||
|
auto new_mission = static_cast<int>(state.mission) - 1;
|
||||||
|
if (new_mission < 1) {
|
||||||
|
new_mission = 7;
|
||||||
|
}
|
||||||
|
state.mission = static_cast<Mission>(new_mission);
|
||||||
|
} else if (pressed_key == SDLK_RETURN) {
|
||||||
|
|
||||||
|
if (state.mission == Mission::MANUAL) {
|
||||||
|
state.view = AppView::DRIVER;
|
||||||
|
} else {
|
||||||
|
state.view = AppView::AMI;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
case SDLK_UP:
|
|
||||||
case SDLK_LEFT:
|
if (state.view == AppView::AMI || state.view == AppView::DRIVER) {
|
||||||
if (state.mission == Mission::NONE ||
|
if (pressed_key == SDLK_ESCAPE) {
|
||||||
state.mission == Mission::ACCELERATION) {
|
state.view = AppView::MISSION_SELECT;
|
||||||
state.mission = Mission::MANUAL;
|
|
||||||
} else {
|
|
||||||
state.mission = static_cast<Mission>(static_cast<int>(state.mission) - 1);
|
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
case SDLK_RETURN:
|
|
||||||
case SDLK_KP_ENTER:
|
if (pressed_key == SDLK_w) {
|
||||||
switch (state.view) {
|
state.data_source.bump_brake_balance_up();
|
||||||
case AppView::MISSION_SELECT:
|
} else if (pressed_key == SDLK_s) {
|
||||||
state.view = AppView::AMI;
|
state.data_source.bump_brake_balance_down();
|
||||||
break;
|
|
||||||
case AppView::AMI:
|
|
||||||
case AppView::DRIVER:
|
|
||||||
case AppView::TESTING:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw std::runtime_error(fmt::format("Unknown view: {}", state.view));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
// We can just ignore other keypresses, so no need for a default clause
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -76,6 +76,7 @@ AppState::~AppState() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AppState::poll() {
|
void AppState::poll() {
|
||||||
|
data_source.poll();
|
||||||
if (!i2c_dev_file) {
|
if (!i2c_dev_file) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -113,3 +114,5 @@ void AppState::unmarshal_ami(uint8_t* data) {
|
|||||||
mission = static_cast<Mission>(data[1]);
|
mission = static_cast<Mission>(data[1]);
|
||||||
spdlog::info("Mission after poll: {}", mission);
|
spdlog::info("Mission after poll: {}", mission);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DemoDataSource AppState::get_data_source() const { return data_source; }
|
35
src/BaseDataSource.cpp
Normal file
35
src/BaseDataSource.cpp
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#include "BaseDataSource.h"
|
||||||
|
|
||||||
|
#include <SDL2/SDL.h>
|
||||||
|
double BaseDataSource::get_speed() { return speed; }
|
||||||
|
|
||||||
|
double BaseDataSource::get_brake_balance() { return brake_balance; }
|
||||||
|
|
||||||
|
double BaseDataSource::get_hv_voltage() { return hv_voltage; }
|
||||||
|
|
||||||
|
double BaseDataSource::get_hv_voltage_ratio() { return hv_voltage_ratio; }
|
||||||
|
|
||||||
|
double BaseDataSource::get_lv_voltage() { return lv_voltage; }
|
||||||
|
|
||||||
|
double BaseDataSource::get_battery_temperature() { return battery_temperature; }
|
||||||
|
|
||||||
|
double BaseDataSource::get_throttle_ratio() { return throttle_ratio; }
|
||||||
|
|
||||||
|
double BaseDataSource::get_brake_pressure_front_bar() {
|
||||||
|
return brake_pressure_front_bar;
|
||||||
|
}
|
||||||
|
|
||||||
|
double BaseDataSource::get_brake_pressure_rear_bar() {
|
||||||
|
return brake_pressure_rear_bar;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseDataSource::set_brake_balance(double value) {
|
||||||
|
brake_balance = value;
|
||||||
|
time_of_last_brake_balance_change = SDL_GetTicks();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BaseDataSource::brake_balance_change_is_recent() {
|
||||||
|
|
||||||
|
return time_of_last_brake_balance_change != 0 &&
|
||||||
|
SDL_GetTicks() - time_of_last_brake_balance_change < 500;
|
||||||
|
}
|
33
src/DemoDataSource.cpp
Normal file
33
src/DemoDataSource.cpp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#include "DemoDataSource.h"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <iostream>
|
||||||
|
DemoDataSource::DemoDataSource() {
|
||||||
|
brake_balance = 0.5;
|
||||||
|
|
||||||
|
lv_voltage = 13.1;
|
||||||
|
battery_temperature = 20.1;
|
||||||
|
throttle_ratio = 0.01;
|
||||||
|
brake_pressure_front_bar = 1;
|
||||||
|
brake_pressure_rear_bar = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
DemoDataSource::~DemoDataSource() {}
|
||||||
|
|
||||||
|
void DemoDataSource::poll() {
|
||||||
|
int min_voltage = 150;
|
||||||
|
int max_voltage = 480;
|
||||||
|
static int count = 0;
|
||||||
|
count++;
|
||||||
|
hv_voltage = 220.1 + std::cos(count / 1000.0 + 2) * 50;
|
||||||
|
hv_voltage_ratio = (hv_voltage - min_voltage) / (max_voltage - min_voltage);
|
||||||
|
speed = 10 + std::sin(count / 100.0) * 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DemoDataSource::bump_brake_balance_up() {
|
||||||
|
set_brake_balance(brake_balance + 0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DemoDataSource::bump_brake_balance_down() {
|
||||||
|
set_brake_balance(brake_balance - 0.01);
|
||||||
|
}
|
124
src/DriverView.cpp
Normal file
124
src/DriverView.cpp
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
#include "DriverView.h"
|
||||||
|
|
||||||
|
#include "DemoDataSource.h"
|
||||||
|
#include "defines.h"
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#define LARGE_FONT_SIZE_POINTS 170
|
||||||
|
#define GIANT_FONT_SIZE_POINTS 200
|
||||||
|
#define MEDIUM_FONT_SIZE_POINTS 50
|
||||||
|
#define SOC_BAR_HEIGHT 80
|
||||||
|
#define SPEED_TEXT_X 22
|
||||||
|
#define SPEED_TEXT_Y 50
|
||||||
|
|
||||||
|
DriverView::DriverView(SDL_Renderer* renderer)
|
||||||
|
: View{renderer}, font_large{util::load_font("resources/Avenir-Book.ttf",
|
||||||
|
LARGE_FONT_SIZE_POINTS)},
|
||||||
|
font_detail{util::load_font("resources/Avenir-Book.ttf", 20)},
|
||||||
|
font_tiny{util::load_font("resources/Avenir-Book.ttf", 15)},
|
||||||
|
font_giant{
|
||||||
|
util::load_font("resources/Avenir-Book.ttf", GIANT_FONT_SIZE_POINTS)},
|
||||||
|
font_medium{util::load_font("resources/Avenir-Book.ttf",
|
||||||
|
MEDIUM_FONT_SIZE_POINTS)} {
|
||||||
|
speed_widget = std::make_unique<TextWidget>(renderer, font_large, "");
|
||||||
|
speed_widget->set_position(SPEED_TEXT_X, SPEED_TEXT_Y);
|
||||||
|
speed_widget->set_alignment(Alignment::CENTER, Alignment::TOP);
|
||||||
|
|
||||||
|
speed_hint_widget = std::make_unique<TextWidget>(renderer, font_tiny, "SPD");
|
||||||
|
speed_hint_widget->set_position(20, 210);
|
||||||
|
speed_hint_widget->set_alignment(Alignment::CENTER, Alignment::TOP);
|
||||||
|
|
||||||
|
brake_balance_widget = std::make_unique<TextWidget>(renderer, font_large, "");
|
||||||
|
brake_balance_widget->set_position(SPEED_TEXT_X + SCREEN_WIDTH / 2,
|
||||||
|
SPEED_TEXT_Y);
|
||||||
|
brake_balance_widget->set_alignment(Alignment::CENTER, Alignment::TOP);
|
||||||
|
brake_balance_hint_widget =
|
||||||
|
std::make_unique<TextWidget>(renderer, font_tiny, "BB");
|
||||||
|
brake_balance_hint_widget->set_position(20 + SCREEN_WIDTH / 2, 210);
|
||||||
|
brake_balance_hint_widget->set_alignment(Alignment::CENTER, Alignment::TOP);
|
||||||
|
|
||||||
|
general_info_widget = std::make_unique<TextWidget>(renderer, font_detail, "");
|
||||||
|
general_info_widget->set_position(SPEED_TEXT_X, SPEED_TEXT_Y + 200);
|
||||||
|
general_info_widget->set_alignment(Alignment::LEFT, Alignment::TOP);
|
||||||
|
general_info_widget->set_wrap_width(SCREEN_WIDTH - 50);
|
||||||
|
|
||||||
|
focus_widget = std::make_unique<TextWidget>(renderer, font_giant, "");
|
||||||
|
focus_widget->set_position(120, 70);
|
||||||
|
focus_widget->set_alignment(Alignment::LEFT, Alignment::TOP);
|
||||||
|
focus_hint_widget = std::make_unique<TextWidget>(renderer, font_medium, "");
|
||||||
|
focus_hint_widget->set_position(120, 40);
|
||||||
|
// focus_hint_widget->set_alignment(Alignment::CENTER, Alignment::CENTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
DriverView::~DriverView() {}
|
||||||
|
|
||||||
|
void DriverView::draw(const AppState& state) {
|
||||||
|
auto ds = state.get_data_source();
|
||||||
|
auto hv_ratio = ds.get_hv_voltage_ratio();
|
||||||
|
SDL_Rect rect;
|
||||||
|
rect.x = 0;
|
||||||
|
rect.y = 0;
|
||||||
|
rect.w = SCREEN_WIDTH;
|
||||||
|
rect.h = SCREEN_HEIGHT;
|
||||||
|
|
||||||
|
static auto hv_low = false;
|
||||||
|
// hysteresis for the hv voltage low
|
||||||
|
if (hv_ratio < 0.15) {
|
||||||
|
hv_low = true;
|
||||||
|
} else if (hv_ratio > 0.2) {
|
||||||
|
hv_low = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int red = hv_low ? 0xa0 : 0x30;
|
||||||
|
SDL_SetRenderDrawColor(renderer, red, 0x30, 0x30, 255);
|
||||||
|
SDL_RenderFillRect(renderer, &rect);
|
||||||
|
|
||||||
|
auto brake_balance_text = fmt::format("{:.0f}", ds.get_brake_balance() * 100);
|
||||||
|
|
||||||
|
if (ds.brake_balance_change_is_recent()) {
|
||||||
|
SDL_SetRenderDrawColor(renderer, 255, 69, 100, 255);
|
||||||
|
SDL_RenderFillRect(renderer, &rect);
|
||||||
|
focus_widget->update_text(brake_balance_text);
|
||||||
|
focus_widget->draw();
|
||||||
|
focus_hint_widget->update_text("BBAL");
|
||||||
|
focus_hint_widget->draw();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rect.w = SCREEN_WIDTH * hv_ratio;
|
||||||
|
rect.h = SOC_BAR_HEIGHT;
|
||||||
|
SDL_SetRenderDrawColor(renderer, 76, 255, 0, 255);
|
||||||
|
SDL_RenderFillRect(renderer, &rect);
|
||||||
|
|
||||||
|
speed_widget->update_text(fmt::format("{:02.0f}", ds.get_speed()));
|
||||||
|
speed_widget->draw();
|
||||||
|
speed_hint_widget->draw();
|
||||||
|
|
||||||
|
brake_balance_widget->update_text(brake_balance_text);
|
||||||
|
|
||||||
|
brake_balance_widget->draw();
|
||||||
|
brake_balance_hint_widget->draw();
|
||||||
|
|
||||||
|
// draw rectangles around the speed and brake balance widgets
|
||||||
|
SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 255);
|
||||||
|
rect.x = 0;
|
||||||
|
rect.y = SOC_BAR_HEIGHT;
|
||||||
|
rect.w = SCREEN_WIDTH / 2;
|
||||||
|
rect.h = 150;
|
||||||
|
SDL_RenderDrawRect(renderer, &rect);
|
||||||
|
rect.x = SCREEN_WIDTH / 2;
|
||||||
|
SDL_RenderDrawRect(renderer, &rect);
|
||||||
|
|
||||||
|
auto general_string = fmt::format(
|
||||||
|
"HV: {:.0f}V | LV: {:.1f}V | B_TEMP: {:.1f}C\nAPPS: {:.0f}% | BPF: "
|
||||||
|
"{:.0f} bar | BPR: {:.0f} bar",
|
||||||
|
ds.get_hv_voltage(), ds.get_lv_voltage(), ds.get_battery_temperature(),
|
||||||
|
ds.get_throttle_ratio() * 100, ds.get_brake_pressure_front_bar(),
|
||||||
|
ds.get_brake_pressure_rear_bar());
|
||||||
|
|
||||||
|
general_info_widget->update_text(general_string);
|
||||||
|
general_info_widget->draw();
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
#include "MissionSelect.h"
|
#include "MissionSelect.h"
|
||||||
|
|
||||||
#include "AppState.h"
|
#include "AppState.h"
|
||||||
|
#include "DriverView.h"
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
#include "events.h"
|
#include "events.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
@ -167,8 +167,13 @@ void TextWidget::update_text(const std::string& new_text) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SDL_Texture* TextWidget::generate_text(const std::string& text) {
|
SDL_Texture* TextWidget::generate_text(const std::string& text) {
|
||||||
SDL_Surface* surf =
|
SDL_Surface* surf;
|
||||||
TTF_RenderText_Solid(font, text.c_str(), {0xFF, 0xFF, 0XFF, 0xFF});
|
if (wrap_width == -1) {
|
||||||
|
surf = TTF_RenderText_Blended(font, text.c_str(), {0xFF, 0xFF, 0XFF, 0xFF});
|
||||||
|
} else {
|
||||||
|
surf = TTF_RenderText_Blended_Wrapped(font, text.c_str(),
|
||||||
|
{0xFF, 0xFF, 0XFF, 0xFF}, wrap_width);
|
||||||
|
}
|
||||||
if (surf == nullptr) {
|
if (surf == nullptr) {
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
fmt::format("Unable to render text surface: {}", TTF_GetError()));
|
fmt::format("Unable to render text surface: {}", TTF_GetError()));
|
||||||
@ -181,6 +186,8 @@ SDL_Texture* TextWidget::generate_text(const std::string& text) {
|
|||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextWidget::set_wrap_width(int width) { wrap_width = width; }
|
||||||
|
|
||||||
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},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user