Zappy GUI
C++ graphic client: renderer, camera, network
Loading...
Searching...
No Matches
EntityTooltipWidget.cpp
Go to the documentation of this file.
1
2
4
5#include <algorithm>
6
7#include "ColorPalette.hpp"
8#include "I18n.hpp"
9#include "TextRenderer.hpp"
10
11static constexpr Color BG_COLOR = {20, 25, 35, 220};
12static constexpr Color BORDER_COLOR = {60, 70, 90, 200};
13static constexpr Color TEXT_COLOR = {255, 255, 255, 255};
14static constexpr Color TILE_COLOR = {100, 200, 255, 255};
15static constexpr Color PLAYER_COLOR = {100, 255, 150, 255};
16static constexpr Color EGG_COLOR = {255, 200, 80, 255};
17static constexpr Color FOLLOW_NORMAL = {40, 80, 60, 220};
18static constexpr Color FOLLOW_HOVER = {60, 140, 90, 240};
19static constexpr Color STOP_NORMAL = {80, 40, 40, 220};
20static constexpr Color STOP_HOVER = {140, 60, 60, 240};
21
37
39void EntityTooltipWidget::setWorld(const WorldState* world) { _world = world; }
40void EntityTooltipWidget::setTeamColorFunc(std::function<Color(const std::string&)> func)
41{
42 _colorFunc = std::move(func);
43}
45
47{
48 int id = _pendingFollowId;
50 return id;
51}
52
54
60
62{
64
66
67 // Reserve space for the button at the bottom of the panel (player case only)
68 float extraPad = _isPlayerCase() ? BTN_H + BTN_MARGIN * 2.0f : 0.0f;
70 // Ensure panel is at least as wide as the button + side padding
71 _tooltip.setMinWidth(_isPlayerCase() ? _btnW + 20.0f * 2.0f : 0.0f);
72
73 switch (_selection.type) {
76 if (res.isEmpty()) {
80 } else {
82 for (int i = 0; i < 7; i++) {
83 if (res[i] <= 0) continue;
85 {std::string(" ") + I18n::resourceName(i), ": " + std::to_string(res[i])},
87 }
88 }
89 break;
90 }
91
93 if (!_world->playerExists(_selection.id)) return;
94 const Player& p = _world->players.at(_selection.id);
95 Color teamColor = _colorFunc ? _colorFunc(p.team) : WHITE;
97 {I18n::get(I18n::Key::LABEL_PLAYER), " #" + std::to_string(p.id)},
100 {TEXT_COLOR, teamColor});
102 std::string(I18n::get(I18n::Key::PLAYER_LEVEL)) + std::to_string(p.level),
103 TEXT_COLOR);
104 if (p.inventory.isEmpty()) {
106 } else {
108 for (int i = 0; i < 7; i++) {
109 if (p.inventory[i] <= 0) continue;
110 _tooltip.addColoredLine({std::string(" ") + I18n::resourceName(i),
111 ": " + std::to_string(p.inventory[i])},
113 }
114 }
115 break;
116 }
117
119 if (!_world->eggExists(_selection.id)) return;
120 const Egg& egg = _world->eggs.at(_selection.id);
121 Color teamColor = _colorFunc ? _colorFunc(egg.team) : WHITE;
123 {I18n::get(I18n::Key::LABEL_EGG), " #" + std::to_string(egg.id)},
126 {TEXT_COLOR, teamColor});
127 break;
128 }
129
130 default:
131 break;
132 }
133}
134
136{
137 Rectangle tb = _tooltip.getLastBounds();
138 if (tb.width <= 0.0f) return;
139
140 // Grow width to fit whichever label is longer, with horizontal padding.
141 // Measure both so the button doesn't resize when toggling between the two labels.
144 _btnW = std::max(BTN_W, static_cast<float>(std::max(mFollow, mStop)) + 24.0f);
145
146 float btnX = tb.x + (tb.width - _btnW) / 2.0f;
147 float btnY = tb.y + tb.height - BTN_H - BTN_MARGIN;
149}
150
152{
153 _btnHovered = false;
154 if (!_isPlayerCase()) return false;
155
157
158 bool stopping = _followActive;
161 .setHoverColor(stopping ? STOP_HOVER : FOLLOW_HOVER);
162
164 _btnHovered = CheckCollisionPointRec(GetMousePosition(), _followBtn.getBounds());
165
167
168 return false; // non-blocking: raycasts still fire (caller checks isFollowButtonHovered())
169}
170
171void EntityTooltipWidget::draw(int scaledFontSize) const
172{
174
175 _scaledFontSize = scaledFontSize;
176 _rebuild();
177 _tooltip.draw(scaledFontSize);
178
179 if (_isPlayerCase()) {
181 _followBtn.draw(scaledFontSize);
182 }
183}
static constexpr Color TILE_COLOR
static constexpr Color STOP_NORMAL
static constexpr Color TEXT_COLOR
static constexpr Color FOLLOW_NORMAL
static constexpr Color BORDER_COLOR
static constexpr Color PLAYER_COLOR
static constexpr Color STOP_HOVER
static constexpr Color EGG_COLOR
static constexpr Color BG_COLOR
static constexpr Color FOLLOW_HOVER
Tooltip widget for selected entities (tile, player, egg).
ButtonWidget & setNormalColor(Color color)
bool handleInput() override
void draw(int scaledFontSize) const override
Draws the widget.
bool wasClicked()
Returns true once per click, then resets.
ButtonWidget & setRoundness(float roundness)
ButtonWidget & setSize(float width, float height)
Rectangle getBounds() const
Returns the bounding rectangle (after anchor resolution).
ButtonWidget & setBorderColor(Color color)
ButtonWidget & setPosition(float x, float y)
Sets the button position directly (requires Anchor::None).
ButtonWidget & setBorderThickness(float thickness)
ButtonWidget & setTextColor(Color color)
ButtonWidget & setLabel(const std::string &label)
static Color getResourceColor(int resourceIndex)
Returns the designated UI/3D color for a given resource index.
void setSelection(const SelectionFinder::Selection &sel)
static constexpr float BTN_MARGIN
int popFollowRequest()
Returns and clears the pending follow target player id. Positive id = start follow....
void setTeamColorFunc(std::function< Color(const std::string &)> func)
void setFollowActive(bool active)
Tells the widget whether follow mode is currently active (affects button label/color).
void draw(int scaledFontSize) const override
Draws the widget.
bool handleInput() override
Processes user input.
static constexpr float BTN_H
bool isFollowButtonHovered() const
True when the follow button is hovered — use to block raycasts.
void setWorld(const WorldState *world)
SelectionFinder::Selection _selection
static constexpr float BTN_W
const WorldState * _world
std::function< Color(const std::string &)> _colorFunc
static const char * get(Key key)
Definition I18n.hpp:86
@ PLAYER_INVENTORY
@ PLAYER_INVENTORY_EMPTY
static const char * resourceName(int index)
Resource name by index (0–6), matching Resources[] ordering.
Definition I18n.hpp:92
bool isEmpty() const
static int measure(const std::string &text, int fontSize)
TooltipWidget & addLine(const std::string &text, Color color=WHITE)
Adds a single-color text line.
TooltipWidget & setExtraBottomPadding(float px)
Adds extra blank space at the bottom of the box (e.g. to reserve room for a button).
TooltipWidget & clearLines()
Removes all lines.
TooltipWidget & setBorderColor(Color color)
TooltipWidget & setAnchor(Anchor anchor, float margin=10.0f)
Auto-positioning relative to screen edges.
TooltipWidget & setMinWidth(float minWidth)
Override minimum panel width (0 = fit to content).
TooltipWidget & setBackgroundColor(Color color)
TooltipWidget & setPadding(int padding)
TooltipWidget & setBackgroundAlpha(unsigned char alpha)
void draw(int scaledFontSize) const override
Draws the widget.
TooltipWidget & addColoredLine(const std::vector< std::string > &segments, const std::vector< Color > &colors)
Adds a line with multiple colored segments (inline spans).
TooltipWidget & setBorderThickness(int thickness)
Rectangle getLastBounds() const
Returns the bounding rectangle for the last drawn frame. Useful for positioning sibling widgets (e....
Represents the state of the world in the game, including the map size, tile contents,...
Resources & at(int x, int y)
Accesses the resources at a specific tile coordinate (x, y).
bool playerExists(int id) const
Checks if a player with the given ID exists in the world.
bool eggExists(int id) const
Checks if an egg with the given ID exists in the world.
std::unordered_map< int, Egg > eggs
std::unordered_map< int, Player > players
int id
Resources inventory
int level