15 void addGame(
const std::function<
void(
Game&)>& initializer = {}) {
16 std::lock_guard lock(m_mutex);
17 m_games.emplace_back();
18 auto& new_game = m_games.back();
21 initializer(new_game);
24 m_selected_index = m_games.size() - 1;
27 void selectGame(std::size_t index) {
28 std::lock_guard lock(m_mutex);
29 if (index < m_games.size()) {
30 m_selected_index = index;
34 void closeGame(
size_t index) {
35 std::lock_guard lock(m_mutex);
36 if (index >= m_games.size())
return;
38 m_games.erase(m_games.begin() +
static_cast<int>(index));
40 if (!m_selected_index)
return;
42 if (index < *m_selected_index) {
43 --(*m_selected_index);
44 }
else if (index == *m_selected_index) {
45 if (m_games.empty()) {
46 m_selected_index.reset();
47 }
else if (index >= m_games.size()) {
48 m_selected_index = m_games.size() - 1;
53 void applyToAllGames(
const std::function<
void(
Game&)>& action) {
54 std::lock_guard lock(m_mutex);
55 for (
auto& game : m_games) {
60 void applyToCurrentGame(
const std::function<
void(
Game&)>& action) {
61 std::lock_guard lock(m_mutex);
62 if (
auto index = currentIndex()) {
63 action(m_games[*index]);
68 std::vector<std::string> game_titles;
69 std::optional<std::size_t> selected_index;
70 const Game* current_game =
nullptr;
74 std::lock_guard lock(m_mutex);
76 snap.game_titles.reserve(m_games.size());
78 for (
const auto& game : m_games) {
79 snap.game_titles.push_back(game.title());
82 snap.selected_index = m_selected_index;
84 if (
auto index = currentIndex()) {
85 snap.current_game = &m_games[*index];
90 [[nodiscard]]
bool shouldQuit()
const {
return m_quit_flag.load(); }
91 void signalQuit() { m_quit_flag =
true; }
94 std::optional<std::size_t> currentIndex()
const {
95 if (m_selected_index.has_value() && m_selected_index.value() < m_games.size()) {
96 return m_selected_index;
101 std::vector<Game> m_games;
102 std::optional<std::size_t> m_selected_index;
103 mutable std::mutex m_mutex;
104 std::atomic<bool> m_quit_flag{
false};