summaryrefslogtreecommitdiffstats
path: root/game/client/scoreboard.cc
blob: c000ae46b9a94a3ee90b462d322a8a78af0fa493 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#include "client/pch.hh"
#include "client/scoreboard.hh"

#include "core/config.hh"

#include "shared/protocol.hh"

#include "client/globals.hh"
#include "client/gui_screen.hh"
#include "client/keybind.hh"
#include "client/session.hh"
#include "client/settings.hh"

constexpr static ImGuiWindowFlags WINDOW_FLAGS = ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoNav;

static ConfigKeyBind list_key(GLFW_KEY_TAB);

static std::vector<std::string> usernames;
static float max_username_size;

static void on_scoreboard_update_packet(const protocol::ScoreboardUpdate &packet)
{
    usernames = packet.names;
    max_username_size = 0.0f;
}

void scoreboard::init(void)
{
    globals::client_config.add_value("scoreboard.key", list_key);

    settings::add_keybind(3, list_key, settings_location::KEYBOARD_MISC, "key.scoreboard");

    globals::dispatcher.sink<protocol::ScoreboardUpdate>().connect<&on_scoreboard_update_packet>();
}

void scoreboard::layout(void)
{
    if(globals::gui_screen != GUI_SCREEN_NONE)
        return;
    if(!session::is_ingame())
        return;
    if(glfwGetKey(globals::window, list_key.get_key()) != GLFW_PRESS)
        return;
    
    const auto viewport = ImGui::GetMainViewport();
    const auto window_start = ImVec2(0.0f, 0.0f);
    const auto window_size = ImVec2(viewport->Size.x, viewport->Size.y);

    ImGui::SetNextWindowPos(window_start);
    ImGui::SetNextWindowSize(window_size);

    if(!ImGui::Begin("###chat", nullptr, WINDOW_FLAGS)) {
        ImGui::End();
        return;
    }

    ImGui::PushFont(globals::font_chat);

    const auto &padding = ImGui::GetStyle().FramePadding;
    const auto &spacing = ImGui::GetStyle().ItemSpacing;
    auto font = globals::font_chat;

    // Figure out the maximum username size
    for(const auto &username : usernames) {
        const ImVec2 size = ImGui::CalcTextSize(username.c_str(), username.c_str() + username.size());
        
        if(size.x <= max_username_size)
            continue;
        max_username_size = size.x;
    }

    // Having a minimum size allows for
    // generally better in-game visibility
    const float true_size = cxpr::max<float>(0.25f * window_size.x, max_username_size);

    // Figure out username rect dimensions
    const float rect_start_x = 0.5f * window_size.x - 0.5f * true_size;
    const float rect_start_y = 0.15f * window_size.y;
    const float rect_size_x = 2.0f * padding.x + true_size;
    const float rect_size_y = 2.0f * padding.y + font->FontSize;

    //const ImU32 border_col = ImGui::GetColorU32(ImGuiCol_Border, 1.00f);
    const ImU32 rect_col = ImGui::GetColorU32(ImGuiCol_FrameBg, 0.80f);
    const ImU32 text_col = ImGui::GetColorU32(ImGuiCol_Text, 1.00f);
    
    ImDrawList *draw_list = ImGui::GetWindowDrawList();

    // Slightly space apart individual rows
    const float row_step_y = rect_size_y + 0.5f * spacing.y;

    for(std::size_t i = 0; i < usernames.size(); ++i) {
        const ImVec2 rect_a = ImVec2(rect_start_x, rect_start_y + i * row_step_y);
        const ImVec2 rect_b = ImVec2(rect_a.x + rect_size_x, rect_a.y + rect_size_y);
        const ImVec2 text_pos = ImVec2(rect_a.x + padding.x, rect_a.y + padding.y);

        //draw_list->AddRect(rect_a, rect_b, border_col, 0.0f, ImDrawFlags_None, globals::gui_scale);
        draw_list->AddRectFilled(rect_a, rect_b, rect_col, 0.0f, ImDrawFlags_None);
        draw_list->AddText(font, font->FontSize, text_pos, text_col, usernames[i].c_str(), usernames[i].c_str() + usernames[i].size());
    }

    ImGui::PopFont();
    ImGui::End();
}