/
yaseeeeechka
/
CenterControl
Обзор
Документация
Войти
/
yaseeeeechka
/
CenterControl
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
CenterControl_TCP/include/client/RoomScreenList.h
789 строк
30 KB
Yaroslava
New structure of Repo. TCP impl
11 дек 2025, 21:12
11 дек 2025, 21:12
6fdf9d7
Код
Авторство
О чём код?
#ifndef ROOMSCREENLIST_H #define ROOMSCREENLIST_H #include <SFML/Graphics.hpp> #include <memory> #include <vector> #include <algorithm> #include <cctype> #include <iostream> #include <cmath> #include <cstdint> #include "IScreen.h" #include "TextBox.h" #include "InputForm.h" #ifdef __linux__ constexpr const char* star_path = "/home/user/dir/programming/C++/Yaroslava/CenterControl/images/star.png"; #elif defined(_WIN32) constexpr const char* star_path = "D:\\CenterControl\\CenterControl_TCP\\images\\star.png"; #endif // ==================== RoomsListScreen ====================================== class RoomsListScreen : public IScreen { public: RoomsListScreen(IScreenApp *app, const sf::Font &font) : app_(app), title_(font, "Rooms", 26), username_txt_(font, "", 18), btn_settings_(sf::Vector2f(160.f, 40.f)), btn_settings_txt_(font, "Top Scores", 18), create_label_(font, "New room:", 18), create_btn_(sf::Vector2f(120.f, 36.f)), create_btn_txt_(font, "Create", 18), list_viewport_(sf::Vector2f(860.f, 200.f)), chat_send_txt_(font, "Send", 18), chat_label_(font, "Chat:", 18), quick_btn_hello_(sf::Vector2f(90.f, 36.f)), quick_btn_bye_(sf::Vector2f(90.f, 36.f)), quick_btn_go_(sf::Vector2f(90.f, 36.f)), quick_txt_hello_(font, "Hello!", 16), quick_txt_bye_(font, "Bye!", 16), quick_txt_go_(font, "Let's go!", 16), bgGradient_(sf::PrimitiveType::TriangleStrip, 4) { // --- Палитра --- btn_primary_color_ = sf::Color(90, 140, 255); btn_primary_hover_color_ = sf::Color(110, 170, 255); btn_secondary_color_ = sf::Color(70, 80, 120); btn_secondary_hover_color_ = sf::Color(95, 105, 150); btn_quick_color_ = sf::Color(100, 150, 255); btn_quick_hover_color_ = sf::Color(120, 175, 255); room_row_color_ = sf::Color(33, 41, 70); room_row_hover_color_ = sf::Color(50, 60, 95); room_row_full_color_ = sf::Color(75, 40, 60); // --- Общий фон --- auto winSize = app_->GetWindow().getSize(); background_.setSize(sf::Vector2f(static_cast<float>(winSize.x), static_cast<float>(winSize.y))); background_.setFillColor(sf::Color(15, 20, 35, 230)); // --- Градиентный фон --- { sf::Color top(10, 14, 30); sf::Color bottom(10, 18, 50); bgGradient_[0].position = {0.f, 0.f}; bgGradient_[0].color = top; bgGradient_[1].position = {static_cast<float>(winSize.x), 0.f}; bgGradient_[1].color = top; bgGradient_[2].position = {0.f, static_cast<float>(winSize.y)}; bgGradient_[2].color = bottom; bgGradient_[3].position = {static_cast<float>(winSize.x), static_cast<float>(winSize.y)}; bgGradient_[3].color = bottom; } // --- Заголовок и имя пользователя --- title_.setFillColor(sf::Color(235, 240, 255)); title_.setPosition({20.f, 16.f}); username_txt_.setFillColor(sf::Color(170, 180, 210)); username_txt_.setPosition({20.f, 52.f}); // Загрузка текстуры звезды (ачивки) if (star_texture_.loadFromFile(star_path)) { star_texture_.setSmooth(true); star_texture_loaded_ = true; } else { std::cerr << "[RoomsListScreen] Failed to load star texture\n"; star_texture_loaded_ = false; } // --- Кнопка Top Scores --- btn_settings_.setPosition({720.f, 20.f}); btn_settings_.setFillColor(btn_secondary_color_); btn_settings_.setOutlineThickness(0.f); btn_settings_txt_.setFillColor(sf::Color::White); CenterTextInRect(btn_settings_txt_, btn_settings_); // --- Область списка комнат --- list_viewport_.setPosition({20.f, 110.f}); list_viewport_.setFillColor(sf::Color(22, 28, 50, 220)); list_viewport_.setOutlineColor(sf::Color(80, 100, 165)); list_viewport_.setOutlineThickness(1.5f); // --- Скролл-бар --- scrollbarTrack_.setFillColor(sf::Color(30, 35, 60)); scrollbarTrack_.setOutlineThickness(0.f); scrollbarThumb_.setFillColor(sf::Color(110, 130, 200)); scrollbarThumb_.setOutlineThickness(0.f); // --- Чат: подпись --- chat_label_.setFillColor(sf::Color(220, 225, 245)); chat_label_.setPosition({ 20.f, list_viewport_.getPosition().y + list_viewport_.getSize().y + 24.f }); // --- Чат: область вывода --- chat_bg_.setPosition({20.f, chat_label_.getPosition().y + 26.f}); chat_bg_.setSize({860.f, 160.f}); chat_bg_.setFillColor(sf::Color(22, 28, 50, 220)); chat_bg_.setOutlineColor(sf::Color(80, 100, 165)); chat_bg_.setOutlineThickness(1.5f); // --- Чат: поле ввода + быстрые кнопки + Send --- const float inputY = chat_bg_.getPosition().y + chat_bg_.getSize().y + 18.f; const float inputX = 20.f; const float inputWidth = 380.f; chat_input_ = std::make_unique<TextBox>(inputX, inputY, inputWidth, 36.f, font); // Быстрые кнопки float quickY = inputY; quick_btn_hello_.setPosition({inputX + inputWidth + 10.f, quickY}); quick_btn_hello_.setFillColor(btn_quick_color_); quick_txt_hello_.setFillColor(sf::Color::White); CenterTextInRect(quick_txt_hello_, quick_btn_hello_); quick_btn_bye_.setPosition( {quick_btn_hello_.getPosition().x + quick_btn_hello_.getSize().x + 8.f, quickY} ); quick_btn_bye_.setFillColor(btn_quick_color_); quick_txt_bye_.setFillColor(sf::Color::White); CenterTextInRect(quick_txt_bye_, quick_btn_bye_); quick_btn_go_.setPosition( {quick_btn_bye_.getPosition().x + quick_btn_bye_.getSize().x + 8.f, quickY} ); quick_btn_go_.setFillColor(btn_quick_color_); quick_txt_go_.setFillColor(sf::Color::White); CenterTextInRect(quick_txt_go_, quick_btn_go_); // Кнопка Send chat_send_btn_.setSize({120.f, 36.f}); chat_send_btn_.setPosition({760.f, inputY}); chat_send_btn_.setFillColor(btn_primary_color_); chat_send_btn_.setOutlineThickness(0.f); chat_send_txt_.setFillColor(sf::Color::White); CenterTextInRect(chat_send_txt_, chat_send_btn_); // --- Блок создания комнаты --- create_label_.setFillColor(sf::Color(220, 225, 245)); create_label_.setPosition({20.f, chat_send_btn_.getPosition().y + 50.f}); room_name_box_ = std::make_unique<TextBox>( 20.f, create_label_.getPosition().y + 28.f, 700.f, 36.f, font ); create_btn_.setPosition({760.f, create_label_.getPosition().y + 28.f}); create_btn_.setFillColor(btn_primary_color_); create_btn_.setOutlineThickness(0.f); create_btn_txt_.setFillColor(sf::Color::White); CenterTextInRect(create_btn_txt_, create_btn_); // --- Коллбэки от Session --- if (auto sess = app_->GetSession()) { sess->SetRoomsCallback([this](const std::vector<RoomInfo> &rooms) { rooms_ = rooms; ClampScrollBar(); UpdateScrollbarGeometry(); }); sess->SetRoomCreateCallback([this](bool ok, const std::string &msg) { toast_ = msg; toast_clock_.restart(); }); sess->SetChatCallback([this](const std::vector<ChatMessageDTO> &msgs) { chat_messages_ = msgs; }); } } void HandleEvent(const sf::Event &e) override { // ввод текста чата chat_input_->HandleEvent(e, app_->GetWindow()); // ввод в поле названия комнаты room_name_box_->HandleEvent(e, app_->GetWindow()); // колесо — только над viewport if (auto mw = e.getIf<sf::Event::MouseWheelScrolled>()) { auto mpos = sf::Mouse::getPosition(app_->GetWindow()); sf::Vector2f p = {(float)mpos.x, (float)mpos.y}; if (list_viewport_.getGlobalBounds().contains(p)) { scrollOffsetRows_ -= mw->delta; // шаг — одна строка ClampScrollBar(); UpdateScrollbarGeometry(); } } if (e.is<sf::Event::MouseButtonPressed>()) { auto m = sf::Mouse::getPosition(app_->GetWindow()); sf::Vector2f mp{(float)m.x, (float)m.y}; if (btn_settings_.getGlobalBounds().contains(mp)) { app_->SwitchScreen("topscores"); return; } // клик по ползунку — начинаем перетаскивание if (scrollbarVisible_ && scrollbarThumb_.getGlobalBounds().contains(mp)) { draggingScrollbar_ = true; dragStartMouseY_ = mp.y; dragStartThumbY_ = scrollbarThumb_.getPosition().y; } // клик по треку — прыжок страницей else if (scrollbarVisible_ && scrollbarTrack_.getGlobalBounds().contains(mp)) { float thumbTop = scrollbarThumb_.getPosition().y; if (mp.y < thumbTop) { scrollOffsetRows_ -= std::max(1.f, visibleRows() - 1.f); } else { scrollOffsetRows_ += std::max(1.f, visibleRows() - 1.f); } ClampScrollBar(); UpdateScrollbarGeometry(); } if (create_btn_.getGlobalBounds().contains(mp)) { auto name = room_name_box_->GetText(); Trim(name); if (!name.empty()) { app_->GetSession()->CreateRoom(name); room_name_box_->Clear(); } } if (list_viewport_.getGlobalBounds().contains(mp)) { int idx = (int)((mp.y - list_viewport_.getPosition().y) / itemHeight_) + (int)std::floor(scrollOffsetRows_); if (idx >= 0 && idx < (int)rooms_.size()) { const auto &r = rooms_[idx]; auto mb = e.getIf<sf::Event::MouseButtonPressed>()->button; if (mb == sf::Mouse::Button::Left) { if (auto sess = app_->GetSession()) { STATUS st = sess->JoinRoom(r.name); if (st == STATUS::RET_SUCCESS) { sess->SetSuppressAutoGame(false); sess->SetCurrentRoom(r.name); app_->SwitchScreen("room"); } else if (st == STATUS::RET_ROOM_FULL) { toast_ = "Room is full"; toast_clock_.restart(); } else { toast_ = "Failed to join room"; toast_clock_.restart(); } } } else if (mb == sf::Mouse::Button::Right) { if (r.players == 0) { if (auto sess = app_->GetSession()) { sess->DeleteRoom(r.name); } } else { toast_ = "Cannot delete: room is not empty"; toast_clock_.restart(); } } } return; } // Обработка кнопок чата (Send + быстрые) auto m2 = sf::Mouse::getPosition(app_->GetWindow()); sf::Vector2f mp2{(float)m2.x, (float)m2.y}; if (chat_send_btn_.getGlobalBounds().contains(mp2)) { auto txt = chat_input_->GetText(); Trim(txt); if (!txt.empty()) { if (auto sess = app_->GetSession()) { sess->SendChatMessage(txt); } chat_input_->Clear(); } } else if (quick_btn_hello_.getGlobalBounds().contains(mp2)) { if (auto sess = app_->GetSession()) { sess->SendChatMessage("Hello!"); } } else if (quick_btn_bye_.getGlobalBounds().contains(mp2)) { if (auto sess = app_->GetSession()) { sess->SendChatMessage("Bye!"); } } else if (quick_btn_go_.getGlobalBounds().contains(mp2)) { if (auto sess = app_->GetSession()) { sess->SendChatMessage("Let's go!"); } } } if (auto mv = e.getIf<sf::Event::MouseMoved>()) { sf::Vector2f mp{(float)mv->position.x, (float)mv->position.y}; // перетаскивание скроллбара if (draggingScrollbar_ && scrollbarVisible_) { float viewH = list_viewport_.getSize().y; float thumbH = scrollbarThumb_.getSize().y; float trackY = scrollbarTrack_.getPosition().y; float dy = mp.y - dragStartMouseY_; float newThumbY = std::clamp(dragStartThumbY_ + dy, trackY, trackY + viewH - thumbH); float usable = viewH - thumbH; float t = usable > 0.f ? (newThumbY - trackY) / usable : 0.f; float maxRows = std::max(0.f, totalRows() - visibleRows()); scrollOffsetRows_ = t * maxRows; UpdateScrollbarGeometry(); } // hover по строкам списка hoveredRoomIndex_ = -1; if (list_viewport_.getGlobalBounds().contains(mp) && !rooms_.empty()) { float topY = list_viewport_.getPosition().y; if (mp.y >= topY) { int localIndex = static_cast<int>((mp.y - topY) / itemHeight_); int globalIndex = (int)std::floor(scrollOffsetRows_) + localIndex; if (globalIndex >= 0 && globalIndex < (int)rooms_.size()) { hoveredRoomIndex_ = globalIndex; } } } // hover по кнопкам UpdateButtonsHover(mp); } if (e.is<sf::Event::MouseButtonReleased>()) { draggingScrollbar_ = false; } } void OnShow() override { if (auto sess = app_->GetSession()) { username_txt_.setString("User: " + sess->GetCurrentUser()); // Запрашиваем количество звёзд у сервера user_stars_ = sess->RequestMyStars(); UpdateUsernameWithStars(); sess->SetChatCallback( [this](const std::vector<ChatMessageDTO> &msgs) { chat_messages_ = msgs; } ); sess->RequestRooms(); sess->RequestChatHistory(); // глобальный чат } else { username_txt_.setString(""); user_stars_ = 0; star_sprites_.clear(); } pollClock_.restart(); pollAccum_ = 0.f; UpdateScrollbarGeometry(); } void Update(float dt) override { // периодические запросы pollAccum_ += dt; if (pollAccum_ >= pollIntervalSec_) { pollAccum_ = 0.f; if (auto sess = app_->GetSession()) { sess->RequestRooms(); sess->RequestChatHistory(); } } } void Render(sf::RenderWindow &w) override { // --- фон как в TopScores: градиент + тёмный overlay --- w.draw(bgGradient_); w.draw(background_); // заголовки/общие элементы w.draw(title_); w.draw(username_txt_); // звёзды-ачивки у пользователя for (auto &sp : star_sprites_) { w.draw(sp); } // кнопка Top Scores + область списка w.draw(btn_settings_); w.draw(btn_settings_txt_); w.draw(list_viewport_); // --- список комнат --- int first = static_cast<int>(std::floor(scrollOffsetRows_)); int max_visible = static_cast<int>(list_viewport_.getSize().y / itemHeight_); int last = std::min(static_cast<int>(rooms_.size()), first + max_visible); float x = list_viewport_.getPosition().x + 6.f; float y = list_viewport_.getPosition().y + 6.f; // helper для статуса комнаты auto getStatus = [](const RoomInfo &r) -> std::pair<std::string, sf::Color> { if (r.inGame) { return {"In game", sf::Color(90, 150, 255)}; // синий } if (r.players == 0) { return {"Empty", sf::Color(150, 150, 150)}; // серый } else if (r.players < 4) { return {"Waiting", sf::Color(240, 200, 0)}; // жёлтый } else { return {"Full", sf::Color(210, 80, 80)}; // красный } }; for (int i = first; i < last; ++i) { const auto &r = rooms_[i]; sf::RectangleShape rowRect(sf::Vector2f( list_viewport_.getSize().x - 12.f - (scrollbarVisible_ ? (scrollbarWidth_ + 6.f) : 0.f), itemHeight_ - 8.f )); rowRect.setPosition({x, y + (i - first) * itemHeight_}); // --- базовый цвет строки: тёмный, как в TopScores --- sf::Color fillColor = room_row_color_; // если комната заполнена — отдельный цвет if (r.players >= 4 && !r.inGame) { fillColor = room_row_full_color_; } // hover if (i == hoveredRoomIndex_) { fillColor = room_row_hover_color_; } rowRect.setFillColor(fillColor); rowRect.setOutlineColor(sf::Color(90, 110, 185)); rowRect.setOutlineThickness(i == hoveredRoomIndex_ ? 2.f : 1.f); w.draw(rowRect); // --- слева: название комнаты --- sf::Text nameText(title_.getFont(), r.name, 18); nameText.setFillColor(sf::Color(235, 240, 255)); // светлый текст на тёмном фоне nameText.setPosition({ rowRect.getPosition().x + 10.f, rowRect.getPosition().y + 6.f }); w.draw(nameText); // --- справа: "N/4" --- std::string playersStr = std::to_string(r.players) + "/4"; sf::Text playersText(title_.getFont(), playersStr, 18); playersText.setFillColor(sf::Color(235, 240, 255)); sf::FloatRect pb = playersText.getLocalBounds(); float playersX = rowRect.getPosition().x + rowRect.getSize().x - 10.f - pb.size.x - pb.position.x; float playersY = rowRect.getPosition().y + 6.f; playersText.setPosition({playersX, playersY}); w.draw(playersText); // --- между именем и "N/4": статус + кружочек --- auto [statusStr, statusColor] = getStatus(r); sf::Text statusText(title_.getFont(), statusStr, 16); statusText.setFillColor(sf::Color(210, 215, 235)); sf::FloatRect sb = statusText.getLocalBounds(); float circleRadius = 5.f; sf::CircleShape statusDot(circleRadius); statusDot.setFillColor(statusColor); float statusRightX = playersX - 10.f; float statusTextX = statusRightX - 2.f * circleRadius - 6.f - sb.size.x - sb.position.x; float rowCenterY = rowRect.getPosition().y + rowRect.getSize().y * 0.5f; statusText.setPosition({ statusTextX, rowCenterY - sb.size.y * 0.5f - sb.position.y }); float dotX = statusText.getPosition().x + sb.size.x + sb.position.x + 6.f; float dotY = rowCenterY - circleRadius; statusDot.setPosition({dotX, dotY}); w.draw(statusText); w.draw(statusDot); } if (scrollbarVisible_) { w.draw(scrollbarTrack_); w.draw(scrollbarThumb_); } // --- блок создания комнаты --- w.draw(create_label_); room_name_box_->Draw(w); w.draw(create_btn_); w.draw(create_btn_txt_); // --- тост --- if (!toast_.empty() && toast_clock_.getElapsedTime().asSeconds() < 2.f) { sf::RectangleShape r(sf::Vector2f(300.f, 36.f)); r.setFillColor(sf::Color(0, 0, 0, 170)); r.setPosition({(900.f - 300.f) / 2.f, 720.f - 36.f - 10.f}); w.draw(r); sf::Text tt(title_.getFont(), toast_, 16); tt.setFillColor(sf::Color::White); tt.setPosition({r.getPosition().x + 10.f, r.getPosition().y + 8.f}); w.draw(tt); } // --- Чат --- w.draw(chat_label_); w.draw(chat_bg_); int maxLines = 10; int total = static_cast<int>(chat_messages_.size()); int start = std::max(0, total - maxLines); float cx = chat_bg_.getPosition().x + 6.f; float cy = chat_bg_.getPosition().y + 6.f; for (int i = start; i < total; ++i) { const auto &m = chat_messages_[i]; std::string line = m.user + ": " + m.text; sf::Text t(title_.getFont(), line, 16); // на тёмном фоне лучше светлый текст t.setFillColor(sf::Color(220, 225, 245)); t.setPosition({cx, cy}); w.draw(t); cy += 14.f; } chat_input_->Draw(w); w.draw(quick_btn_hello_); w.draw(quick_txt_hello_); w.draw(quick_btn_bye_); w.draw(quick_txt_bye_); w.draw(quick_btn_go_); w.draw(quick_txt_go_); w.draw(chat_send_btn_); w.draw(chat_send_txt_); } private: // --- Вспомогательные методы --- static void Trim(std::string &s) { s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { return !std::isspace(ch); })); s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { return !std::isspace(ch); }).base(), s.end()); } float totalRows() const { return static_cast<float>(rooms_.size()); } float visibleRows() const { return list_viewport_.getSize().y / itemHeight_; } void ClampScrollBar() { float maxOff = std::max(0.f, totalRows() - visibleRows()); if (scrollOffsetRows_ < 0.f) scrollOffsetRows_ = 0.f; if (scrollOffsetRows_ > maxOff) scrollOffsetRows_ = maxOff; } void UpdateScrollbarGeometry() { const float viewH = list_viewport_.getSize().y; const float viewW = list_viewport_.getSize().x; const sf::Vector2f vpPos = list_viewport_.getPosition(); const float contentH = totalRows() * itemHeight_; scrollbarVisible_ = contentH > viewH + 0.5f; if (!scrollbarVisible_) return; scrollbarTrack_.setPosition({vpPos.x + viewW - scrollbarWidth_, vpPos.y}); scrollbarTrack_.setSize({scrollbarWidth_, viewH}); float thumbH = std::max(scrollbarMinThumb_, (viewH * viewH) / contentH); float maxRows = std::max(0.f, totalRows() - visibleRows()); float t = (maxRows > 0.f) ? (scrollOffsetRows_ / maxRows) : 0.f; t = std::clamp(t, 0.f, 1.f); float trackY = scrollbarTrack_.getPosition().y; float usable = viewH - thumbH; float thumbY = trackY + t * usable; scrollbarThumb_.setPosition({scrollbarTrack_.getPosition().x, thumbY}); scrollbarThumb_.setSize({scrollbarWidth_, thumbH}); } void UpdateUsernameWithStars() { star_sprites_.clear(); if (username_txt_.getString().isEmpty() || !star_texture_loaded_ || user_stars_ == 0) { return; } sf::String userStr = username_txt_.getString(); std::size_t len = userStr.getSize(); sf::Vector2f endPos = username_txt_.findCharacterPos(len); float charSize = static_cast<float>(username_txt_.getCharacterSize()); sf::Vector2u texSize = star_texture_.getSize(); float targetHeight = charSize; float scale = targetHeight / static_cast<float>(texSize.y); float offsetX = 10.f; float spacing = 4.f; for (std::uint8_t i = 0; i < user_stars_; ++i) { sf::Sprite sp{star_texture_}; sp.setScale({scale, scale}); float starWidth = texSize.x * scale; float starHeight = texSize.y * scale; float x = endPos.x + offsetX + i * (starWidth + spacing); float y = username_txt_.getPosition().y + (charSize - starHeight) * 0.5f; sp.setPosition({x, y}); star_sprites_.push_back(sp); } } void CenterTextInRect(sf::Text &txt, const sf::RectangleShape &rect) { sf::FloatRect bounds = txt.getLocalBounds(); sf::Vector2f rectPos = rect.getPosition(); sf::Vector2f rectSize = rect.getSize(); sf::Vector2f textPos; // SFML 3: bounds.position / bounds.size вместо left/top/width/height textPos.x = rectPos.x + (rectSize.x - bounds.size.x) / 2.f - bounds.position.x; textPos.y = rectPos.y + (rectSize.y - bounds.size.y) / 2.f - bounds.position.y; txt.setPosition(textPos); } void UpdateButtonsHover(const sf::Vector2f &mp) { // Top Scores bool overSettings = btn_settings_.getGlobalBounds().contains(mp); btn_settings_.setFillColor(overSettings ? btn_secondary_hover_color_ : btn_secondary_color_); // Create bool overCreate = create_btn_.getGlobalBounds().contains(mp); create_btn_.setFillColor(overCreate ? btn_primary_hover_color_ : btn_primary_color_); // Send bool overSend = chat_send_btn_.getGlobalBounds().contains(mp); chat_send_btn_.setFillColor(overSend ? btn_primary_hover_color_ : btn_primary_color_); // Quick buttons bool overHello = quick_btn_hello_.getGlobalBounds().contains(mp); quick_btn_hello_.setFillColor(overHello ? btn_quick_hover_color_ : btn_quick_color_); bool overBye = quick_btn_bye_.getGlobalBounds().contains(mp); quick_btn_bye_.setFillColor(overBye ? btn_quick_hover_color_ : btn_quick_color_); bool overGo = quick_btn_go_.getGlobalBounds().contains(mp); quick_btn_go_.setFillColor(overGo ? btn_quick_hover_color_ : btn_quick_color_); } private: IScreenApp *app_; // фон sf::RectangleShape background_; sf::VertexArray bgGradient_; // заголовок, пользователь sf::Text title_; sf::Text username_txt_; // кнопка Top Scores sf::RectangleShape btn_settings_; sf::Text btn_settings_txt_; // область списка комнат sf::RectangleShape list_viewport_; const float itemHeight_ = 44.f; std::vector<RoomInfo> rooms_; // чат sf::RectangleShape chat_bg_; std::unique_ptr<TextBox> chat_input_; sf::RectangleShape chat_send_btn_; sf::Text chat_send_txt_; std::vector<ChatMessageDTO> chat_messages_; sf::Text chat_label_; // быстрые сообщения sf::RectangleShape quick_btn_hello_; sf::RectangleShape quick_btn_bye_; sf::RectangleShape quick_btn_go_; sf::Text quick_txt_hello_; sf::Text quick_txt_bye_; sf::Text quick_txt_go_; // создание комнаты sf::Text create_label_; std::unique_ptr<TextBox> room_name_box_; sf::RectangleShape create_btn_; sf::Text create_btn_txt_; // тост std::string toast_; sf::Clock toast_clock_; // периодический запрос sf::Clock pollClock_; float pollAccum_ = 0.f; const float pollIntervalSec_ = 1.0f; // скроллбар sf::RectangleShape scrollbarTrack_; sf::RectangleShape scrollbarThumb_; bool scrollbarVisible_ = false; bool draggingScrollbar_ = false; float dragStartMouseY_ = 0.f; float dragStartThumbY_ = 0.f; float scrollOffsetRows_ = 0.f; const float scrollbarWidth_ = 10.f; const float scrollbarMinThumb_ = 24.f; int hoveredRoomIndex_ = -1; // ачивки пользователя std::uint8_t user_stars_ = 0; sf::Texture star_texture_; std::vector<sf::Sprite> star_sprites_; bool star_texture_loaded_ = false; // цвета sf::Color btn_primary_color_; sf::Color btn_primary_hover_color_; sf::Color btn_secondary_color_; sf::Color btn_secondary_hover_color_; sf::Color btn_quick_color_; sf::Color btn_quick_hover_color_; sf::Color room_row_color_; sf::Color room_row_hover_color_; sf::Color room_row_full_color_; }; #endif // ROOMSCREENLIST_H