30 #include <boost/algorithm/string/trim.hpp>
33 #define DBG_FT LOG_STREAM(debug, log_font)
34 #define LOG_FT LOG_STREAM(info, log_font)
35 #define WRN_FT LOG_STREAM(warn, log_font)
36 #define ERR_FT LOG_STREAM(err, log_font)
39 #define ERR_DP LOG_STREAM(err, log_display)
43 typedef std::map<int, font::floating_label> label_map;
47 std::stack<std::set<int>> label_contexts;
51 using namespace std::chrono_literals;
55 floating_label::floating_label(
const std::string& text)
61 , text_(
boost::trim_copy(text))
64 , bgcolor_(0, 0, 0, SDL_ALPHA_TRANSPARENT)
115 if(
tex_ !=
nullptr) {
125 DBG_FT <<
"creating floating label texture, text: " <<
text_.substr(0,15);
144 ERR_FT <<
"could not create floating label's text";
165 ERR_FT <<
"failed to create texture for floating label";
204 ERR_DP <<
"trying to draw floating label with no texture!";
236 return current_time - time_start_;
242 double new_y =
ypos_;
245 auto time_alive = std::chrono::duration_cast<std::chrono::milliseconds>(
get_time_alive(time));
246 new_x += time_alive.count() *
xmove_;
247 new_y += time_alive.count() *
ymove_;
251 return {
static_cast<int>(new_x),
static_cast<int>(new_y)};
268 if(label_contexts.empty()) {
273 labels.emplace(label_id, flabel);
274 label_contexts.top().insert(label_id);
281 if(
i != labels.end()) {
282 i->second.move(xmove, ymove);
288 for(
auto& [
id,
label] : labels) {
290 label.move(xmove, ymove);
298 if(
i != labels.end()) {
300 i->second.set_lifetime(0ms, fadeout);
302 }
else if(fadeout < 0ms) {
303 i->second.set_lifetime(0ms,
i->second.get_fade_time());
311 if(!label_contexts.empty()) {
312 label_contexts.top().erase(
handle);
319 if(
i != labels.end()) {
320 i->second.show(value);
327 if(
i != labels.end()) {
328 if (
i->second.create_texture()) {
339 for(
auto& [
id,
label] : labels) {
340 if(label_contexts.top().count(
id) > 0) {
346 label_contexts.emplace();
352 const std::set<int>& context = label_contexts.top();
354 while(!context.empty()) {
360 label_contexts.pop();
365 if(label_contexts.empty()) {
369 const std::set<int>& context = label_contexts.top();
373 for(
auto& [
id,
label] : labels) {
374 if(context.count(
id) > 0) {
382 if(label_contexts.empty()) {
386 auto time = std::chrono::steady_clock::now();
387 std::set<int>& context = label_contexts.top();
389 for(
auto iter = labels.begin(); iter!= labels.end();) {
392 if(context.count(
id) > 0) {
395 if(
label.expired(time)) {
397 iter = labels.erase(iter);
std::chrono::milliseconds lifetime_
uint8_t get_alpha(const clock::time_point &time) const
rect get_bg_rect(const rect &text_rect) const
point get_pos(const clock::time_point &time) const
clock::time_point time_start_
bool create_texture()
Ensure a texture for this floating label exists, creating one if needed.
int xpos(std::size_t width) const
void update(const clock::time_point &time)
Finalize draw position and alpha, and queue redrawing if changed.
void set_lifetime(const std::chrono::milliseconds &lifetime, const std::chrono::milliseconds &fadeout=std::chrono::milliseconds{100})
std::chrono::milliseconds fadeout_
void move(double xmove, double ymove)
Change the floating label's position.
clock::duration get_time_alive(const clock::time_point ¤t_time) const
void draw()
Draw the label to the screen.
void undraw()
Mark the last drawn location as requiring redraw.
pango_text & set_font_style(const FONT_STYLE font_style)
pango_text & set_characters_per_line(const unsigned characters_per_line)
pango_text & set_foreground_color(const color_t &color)
pango_text & set_family_class(font::family_class fclass)
pango_text & set_add_outline(bool do_add)
pango_text & set_ellipse_mode(const PangoEllipsizeMode ellipse_mode)
pango_text & set_alignment(const PangoAlignment alignment)
pango_text & set_font_size(unsigned font_size)
pango_text & set_link_aware(bool b)
bool set_text(const std::string &text, const bool markedup)
Sets the text to render.
pango_text & set_maximum_height(int height, bool multiline)
pango_text & set_maximum_width(int width)
texture render_and_get_texture()
Returns the cached texture, or creates a new one otherwise.
int w() const
The draw-space width of the texture, in pixels.
void reset()
Releases ownership of the managed texture and resets the ptr to null.
point draw_size() const
The size of the texture in draw-space.
void set_alpha_mod(uint8_t alpha)
Alpha modifier.
constexpr uint8_t ALPHA_OPAQUE
constexpr uint8_t float_to_color(double n)
Convert a double in the range [0.0,1.0] to an 8-bit colour value.
Drawing functions, for drawing things on the screen.
static lg::log_domain log_font("font")
static lg::log_domain log_display("display")
std::string label
What to show in the filter's drop-down list.
std::string id
Text to match against addon_info.tags()
Standard logging facilities (interface).
constexpr double normalize_progress(const std::chrono::duration< RepE, PeriodE > &elapsed, const std::chrono::duration< RepD, PeriodD > &duration)
void invalidate_region(const rect ®ion)
Mark a region of the screen as requiring redraw.
clip_setter reduce_clip(const ::rect &clip)
Set the clipping area to the intersection of the current clipping area and the given rectangle.
void fill(const ::rect &rect, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
Fill an area with the given colour.
::rect get_clip()
Get the current clipping area, in draw coordinates.
void blit(const texture &tex, const ::rect &dst)
Draws a texture, or part of a texture, at the given location.
pango_text & get_text_renderer()
Returns a reference to a static pango_text object.
int add_floating_label(const floating_label &flabel)
add a label floating on the screen above everything else.
rect get_floating_label_rect(int handle)
void show_floating_label(int handle, bool value)
hides or shows a floating label
void scroll_floating_labels(double xmove, double ymove)
moves all floating labels that have 'scroll_mode' set to ANCHOR_LABEL_MAP
void remove_floating_label(int handle, const std::chrono::milliseconds &fadeout)
removes the floating label given by 'handle' from the screen
void update_floating_labels()
void move_floating_label(int handle, double xmove, double ymove)
moves the floating label given by 'handle' by (xmove,ymove)
void draw_floating_labels()
const color_t NORMAL_COLOR
std::shared_ptr< halo_record > handle
std::size_t size(std::string_view str)
Length in characters of a UTF-8 string.
bool headless()
The game is running headless.
rect game_canvas()
The game canvas area, in drawing coordinates.
std::string::const_iterator iterator
~floating_label_context()
An abstract description of a rectangle with integer coordinates.
bool empty() const
False if both w and h are > 0, true otherwise.
constexpr rect padded_by(int dx, int dy) const
Returns a new rectangle with dx horizontal padding and dy vertical padding.
rect intersect(const rect &r) const
Calculates the intersection of this rectangle and another; that is, the maximal rectangle that is con...
bool overlaps(const rect &r) const
Whether the given rectangle and this rectangle overlap.