38 #define LOG_DP LOG_STREAM(info, log_display)
46 std::unique_ptr<image::locator> get_orb_image(
orb_status os)
69 std::unique_ptr<image::locator> get_playing_ally_orb_image(
orb_status os)
89 void draw_bar(
int xpos,
int ypos,
int bar_height,
double filled,
const color_t& col)
92 static constexpr
unsigned int bar_width = 4;
94 static constexpr
color_t bar_color_bg{0, 0, 0, 80};
95 static constexpr
color_t bar_color_border{213, 213, 213, 200};
113 bar_rect.w = std::clamp<int>(bar_rect.w, 0,
display::hex_size() * 0.80 - offset.x);
114 bar_rect.h = std::clamp<int>(bar_rect.h, 0,
display::hex_size() * 0.80 - offset.y);
116 filled = std::clamp<double>(filled, 0.0, 1.0);
117 const int unfilled =
static_cast<std::size_t
>(bar_rect.h * (1.0 - filled));
120 const rect fill_rect {
122 bar_rect.y + unfilled,
124 bar_rect.h - unfilled
140 , dc(disp.get_disp_context())
143 , halo_man(thedisp.get_halo_manager())
144 , viewing_team(disp.viewing_team())
145 , playing_team(disp.playing_team())
146 , viewing_team_ref(teams[viewing_team])
147 , playing_team_ref(teams[playing_team])
148 , is_blindfolded(disp.is_blindfolded())
149 , show_everything(disp.show_everything())
150 , sel_hex(disp.selected_hex())
151 , mouse_hex(disp.mouseover_hex())
152 , zoom_factor(disp.get_zoom_factor())
153 , hex_size(disp.hex_size())
154 , hex_size_by_2(disp.hex_size() / 2)
193 const bool is_selected_hex = (loc ==
sel_hex || is_highlighted_enemy);
197 xp_color.a = hp_color.a;
202 ac.
anim_->update_last_draw_time();
209 if (!ac.
anim_)
return;
215 ac.
anim_->update_last_draw_time();
232 if (is_flying && height_adjust < 0) {
235 params.
y -= height_adjust;
236 params.
halo_y -= height_adjust;
239 double blend_ratio = 0;
287 int ellipse_floating = 0;
290 if(adjusted_params.submerge > 0.0) {
294 ellipse_floating =
static_cast<int>(adjusted_params.submerge *
hex_size_by_2);
298 ellipse=
"misc/ellipse";
301 if(ellipse !=
"none") {
303 const std::string nozoc = !emit_zoc ?
"nozoc-" :
"";
304 const std::string leader = can_recruit ?
"leader-" :
"";
305 const std::string
selected = is_selected_hex?
"selected-" :
"";
308 const std::string ellipse_top =
formatter() << ellipse <<
"-" << leader << nozoc <<
selected <<
"top.png~RC(ellipse_red>" << tc <<
")";
309 const std::string ellipse_bot =
formatter() << ellipse <<
"-" << leader << nozoc <<
selected <<
"bottom.png~RC(ellipse_red>" << tc <<
")";
319 const point origin { d.x, d.y + adj_y - ellipse_floating };
322 draw::blit(ellipse_back, display::scaled_to_zoom({origin.x, origin.y, ellipse_back.w(), ellipse_back.h()}));
331 const auto& type_cfg = u.type().get_cfg();
332 const auto& cfg_offset_x = type_cfg[
"bar_offset_x"];
333 const auto& cfg_offset_y = type_cfg[
"bar_offset_y"];
336 if(cfg_offset_x.empty() && cfg_offset_y.empty()) {
340 xoff = !
s.x ? 0 : (hex_size -
s.x)/2;
341 yoff = !
s.y ? 0 : (hex_size -
s.x)/2;
344 xoff = cfg_offset_x.to_int();
345 yoff = cfg_offset_y.to_int();
349 std::unique_ptr<image::locator> orb_img =
nullptr;
351 if(viewing_team_ref.is_enemy(side)) {
352 if(!u.incapacitated())
354 }
else if(
static_cast<std::size_t
>(side) != playing_team + 1) {
359 if(
static_cast<std::size_t
>(side) != viewing_team + 1)
361 orb_img = get_orb_image(os);
362 }
else if(
static_cast<std::size_t
>(side) != viewing_team + 1) {
364 auto os = dc.unit_orb_status(u);
365 orb_img = get_playing_ally_orb_image(os);
368 auto os = dc.unit_orb_status(u);
369 orb_img = get_orb_image(os);
373 std::vector<texture> textures;
375 if(orb_img !=
nullptr) {
381 textures.push_back(std::move(tex));
385 for(
const std::string& ov : u.overlays()) {
387 textures.push_back(std::move(tex));
391 const std::vector<std::string> overlays_abilities = u.overlays_abilities();
392 for(
const std::string& ov : overlays_abilities) {
394 textures.push_back(std::move(tex));
399 textures = std::move(textures),
400 adj_y = adjusted_params.y,
402 bar_hp_height =
static_cast<int>(max_hitpoints * u.hp_bar_scaling()),
403 bar_xp_height =
static_cast<int>(max_experience * u.xp_bar_scaling() / std::max<int>(u.level(), 1))
405 const point origin { d.x + xoff, d.y + yoff + adj_y };
407 for(
const texture& tex : textures) {
408 draw::blit(tex, display::scaled_to_zoom({origin.x, origin.y, tex.w(), tex.h()}));
411 if(max_hitpoints > 0) {
415 double filled =
static_cast<double>(hitpoints) /
static_cast<double>(max_hitpoints);
416 draw_bar(origin.x + hp_offset, origin.y, bar_hp_height, filled, hp_color);
419 if(experience > 0 && can_advance) {
420 double filled =
static_cast<double>(experience) /
static_cast<double>(max_experience);
421 draw_bar(origin.x, origin.y, bar_xp_height, filled, xp_color);
430 const terrain_type& terrain_dst_info = map.get_terrain_info(terrain_dst);
434 int height_adjust_unit =
static_cast<int>(terrain_info.unit_height_adjust() * (1.0 - adjusted_params.offset) +
436 if (is_flying && height_adjust_unit < 0) {
437 height_adjust_unit = 0;
439 params.y -= height_adjust_unit - height_adjust;
440 params.halo_y -= height_adjust_unit - height_adjust;
445 adjusted_params.offset * xdst
446 + (1.0 - adjusted_params.offset) * xsrc
451 adjusted_params.offset * ydst
452 + (1.0 - adjusted_params.offset) * ysrc
454 + hex_size_by_2 - height_adjust_unit * zoom_factor;
456 bool has_halo = ac.unit_halo_ && ac.unit_halo_->valid();
457 if(!has_halo && !u.image_halo().empty()) {
458 ac.unit_halo_ = halo_man.add(
460 u.image_halo() + u.TC_image_mods(),
464 if(has_halo && u.image_halo().empty()) {
465 halo_man.remove(ac.unit_halo_);
466 ac.unit_halo_.reset();
467 }
else if(has_halo) {
468 halo_man.set_location(ac.unit_halo_, halo_x, halo_y);
471 const std::vector<std::string> halos_abilities = u.halo_abilities();
472 bool has_abil_halo = !ac.abil_halos_.empty() && ac.abil_halos_.front()->valid();
473 if(!has_abil_halo && !halos_abilities.empty()) {
474 for(
const std::string& halo_ab : halos_abilities){
477 halo_ab + u.TC_image_mods(),
480 if(abil_halo->valid()){
481 ac.abil_halos_.push_back(abil_halo);
485 if(has_abil_halo && (ac.abil_halos_ref_ != halos_abilities || halos_abilities.empty())){
487 halo_man.remove(abil_halo);
489 ac.abil_halos_.clear();
490 if(!halos_abilities.empty()){
491 for(
const std::string& halo_ab : halos_abilities){
494 halo_ab + u.TC_image_mods(),
497 if(abil_halo->valid()){
498 ac.abil_halos_.push_back(abil_halo);
502 }
else if(has_abil_halo){
504 halo_man.set_location(abil_halo, halo_x, halo_y);
508 ac.abil_halos_ref_ = halos_abilities;
510 ac.anim_->redraw(params, halo_man);
511 ac.refreshing_ =
false;
Sort-of-Singleton that many classes, both GUI and non-GUI, use to access the game data.
@ LAYER_UNIT_FIRST
Reserve layers to be selected for WML.
@ LAYER_UNIT_BAR
Unit bars and overlays are drawn on this layer (for testing here).
static int hex_size()
Function which returns the size of a hex in pixels (from top tip to bottom tip or left edge to right ...
int get_location_x(const map_location &loc) const
Functions to get the on-screen positions of hexes.
static double get_zoom_factor()
Returns the current zoom factor.
void drawing_buffer_add(const drawing_layer layer, const map_location &loc, decltype(draw_helper::do_draw) draw_func)
Add an item to the drawing buffer.
rect map_outside_area() const
Returns the available area for a map, this may differ from the above.
int get_location_y(const map_location &loc) const
static rect scaled_to_zoom(const SDL_Rect &r)
Scale the width and height of a rect by the current zoom factor.
const std::set< map_location > & units_that_can_reach_goal() const
Return the locations of units that can reach goal (.
terrain_code get_terrain(const map_location &loc) const
Looks up terrain at a particular location.
const terrain_type & get_terrain_info(const t_translation::terrain_code &terrain) const
Generic locator abstracting the location of an image.
static std::string get_side_color_id(unsigned side)
int unit_height_adjust() const
double unit_submerge() const
Wrapper class to encapsulate creation and management of an SDL_Texture.
bool draw_bars_
bool indicating whether to draw bars with the unit
std::unique_ptr< unit_animation > anim_
The current animation.
void set_standing(bool with_bars=true)
Sets the animation state to standing.
bool refreshing_
avoid infinite recursion.
void clear_haloes()
Clear the haloes associated to the unit.
const team & viewing_team_ref
void redraw_unit(const unit &u) const
draw a unit.
std::set< map_location > units_that_can_reach_goal
unit_drawer(display &thedisp)
This class represents a single unit of a specific type.
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_display("display")
Frame for unit's animation sequence.
bool invisible(const map_location &loc, bool see_all=true) const
bool is_visible_to_team(const team &team, bool const see_all=true) const
int max_hitpoints() const
The max number of hitpoints this unit can have.
bool incapacitated() const
Check if the unit has been petrified.
int hitpoints() const
The current number of hitpoints this unit has.
bool slowed() const
Check if the unit has been slowed.
bool get_hidden() const
Gets whether this unit is currently hidden on the map.
int experience() const
The current number of experience points this unit has.
bool can_recruit() const
Whether this unit can recruit other units - ie, are they a leader unit.
int side() const
The side this unit belongs to.
bool poisoned() const
Check if the unit has been poisoned.
int max_experience() const
The max number of experience points this unit can have.
bool can_advance() const
Checks whether this unit has any options to advance to.
color_t xp_color() const
Color for this unit's XP.
unit_animation_component & anim_comp() const
color_t hp_color() const
Color for this unit's current hitpoints.
std::string TC_image_mods() const
Constructs a recolor (RC) IPF string for this unit's team color.
std::string image_ellipse() const
Get the unit's ellipse image.
std::string image_mods() const
Gets an IPF string containing all IPF image mods.
std::string default_anim_image() const
The default image to use for animation frames with no defined image.
bool emits_zoc() const
Tests whether the unit has a zone-of-control, considering incapacitated.
const map_location & get_location() const
The current map location this unit is at.
map_location::DIRECTION facing() const
The current direction this unit is facing within its hex.
bool is_flying() const
Check if the unit is a flying unit.
Standard logging facilities (interface).
void fill(const SDL_Rect &rect, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
Fill an area with the given colour.
void blit(const texture &tex, const SDL_Rect &dst)
Draws a texture, or part of a texture, at the given location.
void rect(const SDL_Rect &rect)
Draw a rectangle.
std::string orb_two_color
std::shared_ptr< halo_record > handle
texture get_texture(const image::locator &i_locator, TYPE type, bool skip_cache)
Returns an image texture suitable for hardware-accelerated rendering.
point get_size(const locator &i_locator, bool skip_cache)
Returns the width and height of an image.
std::string get_orb_color(orb_status os)
Wrapper for the various preferences::unmoved_color(), moved_color(), etc methods, using the enum inst...
bool prefs_show_orb(orb_status os)
Wrapper for the various preferences::show_..._orb() methods, using the enum instead of exposing a sep...
std::string moved_color()
std::string partial_color()
bool show_status_on_ally_orb()
std::string allied_color()
orb_status
Corresponds to the colored orbs displayed above units' hp-bar and xp-bar.
@ partial
There are still moves and/or attacks possible, but the unit doesn't fit in the "unmoved" status.
@ moved
All moves and possible attacks have been done.
@ disengaged
The unit can move but can't attack, and wouldn't be able to attack even if it was moved to a hex adja...
@ allied
Belongs to a friendly side.
@ enemy
Belongs to a non-friendly side; normally visualised by not displaying an orb.
The basic class for representing 8-bit RGB or RGBA colour values.
All parameters from a frame at a given instant.
boost::tribool primary_frame
std::optional< color_t > blend_with
Encapsulates the map of the game.
DIRECTION
Valid directions which can be moved in our hexagonal world.
map_location get_direction(DIRECTION dir, unsigned int n=1u) const
An abstract description of a rectangle with integer coordinates.
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...
static map_location::DIRECTION s