Zappy GUI
C++ graphic client: renderer, camera, network
Loading...
Searching...
No Matches
SpeedSlider.cpp
Go to the documentation of this file.
1#include "SpeedSlider.hpp"
2
3#include <raylib.h>
4
5#include <cmath>
6#include <string>
7
8#include "I18n.hpp"
9#include "TextRenderer.hpp"
10
11const std::vector<int> SpeedSlider::STEPS = {1, 2, 3, 4, 5, 10, 15, 20, 25, 30, 35,
12 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90,
13 95, 100, 105, 110, 115, 120, 125, 130, 135, 140, 145,
14 150, 155, 160, 165, 170, 175, 180, 185, 190, 195, 200};
15
16static constexpr float ROUNDNESS = 0.2f;
17static constexpr int SEGMENTS = 8;
18static constexpr float BORDER_THICKNESS = 2.0f;
19static constexpr float TRACK_H = 4.0f;
20static constexpr float HANDLE_RADIUS = 6.0f;
21
22static constexpr Color BG_COLOR = {20, 25, 35, 180};
23static constexpr Color BORDER_COLOR = {60, 70, 90, 200};
24static constexpr Color ACCENT_COLOR = {210, 220, 240, 255};
25static constexpr Color TRACK_BG_COLOR = {60, 70, 90, 220};
26static constexpr Color TRACK_FILL_COLOR = {100, 160, 255, 255};
27static constexpr Color HANDLE_DRAG_COLOR = {255, 220, 80, 255};
28
29float SpeedSlider::_trackX(float panelX) { return panelX + 10.0f; }
30float SpeedSlider::_trackY(float panelY, float panelH) { return panelY + panelH * 0.75f; }
31float SpeedSlider::_trackW(float panelW) { return panelW - 20.0f; }
32
33void SpeedSlider::syncFromServer(int serverTimeUnit)
34{
35 if (_initialized || serverTimeUnit <= 0) return;
36
37 int best = 0;
38 int bestDiff = std::abs(STEPS[0] - serverTimeUnit);
39 for (int i = 1; i < static_cast<int>(STEPS.size()); i++) {
40 int diff = std::abs(STEPS[i] - serverTimeUnit);
41 if (diff < bestDiff) {
42 bestDiff = diff;
43 best = i;
44 }
45 }
46 _index = best;
47 _initialized = true;
48}
49
51{
52 int sh = GetScreenHeight();
53 Rectangle panelRect = {10.0f, static_cast<float>(sh - PANEL_HEIGHT - 10),
54 static_cast<float>(PANEL_WIDTH), static_cast<float>(PANEL_HEIGHT)};
55
56 float tx = _trackX(panelRect.x);
57 float ty = _trackY(panelRect.y, panelRect.height);
58 float tw = _trackW(panelRect.width);
59
60 float t = static_cast<float>(_index) / static_cast<float>(STEPS.size() - 1);
61 float handleX = tx + tw * t;
62
63 Rectangle handleHit = {handleX - HANDLE_RADIUS * 1.5f, ty - HANDLE_RADIUS * 1.5f,
64 HANDLE_RADIUS * 3.0f, HANDLE_RADIUS * 3.0f};
65
66 Vector2 mouse = GetMousePosition();
67
68 if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) &&
69 (CheckCollisionPointRec(mouse, panelRect) || CheckCollisionPointRec(mouse, handleHit)))
70 _dragging = true;
71
72 if (_dragging) {
73 if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT)) {
74 _dragging = false;
76 } else {
77 float frac = (mouse.x - tx) / tw;
78 frac = frac < 0.0f ? 0.0f : (frac > 1.0f ? 1.0f : frac);
79 _index = static_cast<int>(frac * static_cast<float>(STEPS.size() - 1) + 0.5f);
80 }
81 return true;
82 }
83
84 return false;
85}
86
88{
89 auto val = _pendingSpeed;
90 _pendingSpeed = std::nullopt;
91 return val;
92}
93
94void SpeedSlider::draw(int scaledFontSize) const
95{
96 int sh = GetScreenHeight();
97 float panelX = 10.0f;
98 float panelY = static_cast<float>(sh - PANEL_HEIGHT - 10);
99 float panelW = static_cast<float>(PANEL_WIDTH);
100 float panelH = static_cast<float>(PANEL_HEIGHT);
101
102 Rectangle rect = {panelX, panelY, panelW, panelH};
103 DrawRectangleRounded(rect, ROUNDNESS, SEGMENTS, BG_COLOR);
104 DrawRectangleRoundedLines(rect, ROUNDNESS, SEGMENTS, BORDER_THICKNESS, BORDER_COLOR);
105
106 std::string label =
107 std::string(I18n::get(I18n::Key::SPEED_LABEL)) + std::to_string(STEPS[_index]);
108 TextRenderer::draw(label, static_cast<int>(panelX + 10), static_cast<int>(panelY + 8),
109 scaledFontSize, ACCENT_COLOR);
110
111 float tx = _trackX(panelX);
112 float ty = _trackY(panelY, panelH);
113 float tw = _trackW(panelW);
114
115 DrawRectangleRounded({tx, ty - TRACK_H / 2.0f, tw, TRACK_H}, 1.0f, 4, TRACK_BG_COLOR);
116
117 float t = static_cast<float>(_index) / static_cast<float>(STEPS.size() - 1);
118 float fillW = tw * t;
119 if (fillW > 0.5f)
120 DrawRectangleRounded({tx, ty - TRACK_H / 2.0f, fillW, TRACK_H}, 1.0f, 4, TRACK_FILL_COLOR);
121
122 float handleX = tx + fillW;
123 Color handleColor = _dragging ? HANDLE_DRAG_COLOR : ACCENT_COLOR;
124 DrawCircle(static_cast<int>(handleX), static_cast<int>(ty), HANDLE_RADIUS, handleColor);
125 DrawCircleLines(static_cast<int>(handleX), static_cast<int>(ty), HANDLE_RADIUS, BORDER_COLOR);
126}
static constexpr Color BORDER_COLOR
static constexpr Color BG_COLOR
static constexpr Color ACCENT_COLOR
static constexpr float TRACK_H
static constexpr Color HANDLE_DRAG_COLOR
static constexpr float BORDER_THICKNESS
static constexpr Color TRACK_FILL_COLOR
static constexpr float HANDLE_RADIUS
static constexpr float ROUNDNESS
static constexpr Color BORDER_COLOR
static constexpr Color TRACK_BG_COLOR
static constexpr int SEGMENTS
static constexpr Color BG_COLOR
static const char * get(Key key)
Definition I18n.hpp:86
static constexpr int PANEL_HEIGHT
static float _trackY(float panelY, float panelH)
void draw(int scaledFontSize) const override
Draws the slider panel at the bottom-left of the screen.
static float _trackW(float panelW)
std::optional< int > getPendingSpeedChange()
Returns and clears any pending speed change.
void syncFromServer(int serverTimeUnit)
Snaps to the nearest step index matching serverTimeUnit. No-op if already initialized or serverTimeUn...
static const std::vector< int > STEPS
static constexpr int PANEL_WIDTH
std::optional< int > _pendingSpeed
static float _trackX(float panelX)
bool handleInput() override
Processes mouse input.
static void draw(const std::string &text, int x, int y, int fontSize, Color color)