Add bold, italic and monospace font styling for HUD text elements (#11478)

Co-authored-by: Elias Fleckenstein <eliasfleckenstein@web.de>
This commit is contained in:
sfan5 2021-07-27 19:11:46 +02:00 committed by GitHub
parent cf136914cf
commit 6e8aebf432
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 127 additions and 24 deletions

@ -1314,6 +1314,8 @@ It can be created via `Raycast(pos1, pos2, objects, liquids)` or
-- ^ See "HUD Element Types" -- ^ See "HUD Element Types"
size = { x=100, y=100 }, -- default {x=0, y=0} size = { x=100, y=100 }, -- default {x=0, y=0}
-- ^ Size of element in pixels -- ^ Size of element in pixels
style = 0,
-- ^ For "text" elements sets font style: bitfield with 1 = bold, 2 = italic, 4 = monospace
} }
``` ```

@ -8447,6 +8447,9 @@ Used by `Player:hud_add`. Returned by `Player:hud_get`.
z_index = 0, z_index = 0,
-- Z index : lower z-index HUDs are displayed behind higher z-index HUDs -- Z index : lower z-index HUDs are displayed behind higher z-index HUDs
style = 0,
-- For "text" elements sets font style: bitfield with 1 = bold, 2 = italic, 4 = monospace
} }
Particle definition Particle definition

@ -0,0 +1,81 @@
local player_huds = {}
local states = {
{0, "Normal font"},
{1, "Bold font"},
{2, "Italic font"},
{3, "Bold and italic font"},
{4, "Monospace font"},
{5, "Bold and monospace font"},
{7, "ZOMG all the font styles"},
}
local default_def = {
hud_elem_type = "text",
position = {x = 0.5, y = 0.5},
scale = {x = 2, y = 2},
alignment = { x = 0, y = 0 },
}
local function add_hud(player, state)
local def = table.copy(default_def)
local statetbl = states[state]
def.offset = {x = 0, y = 32 * state}
def.style = statetbl[1]
def.text = statetbl[2]
return player:hud_add(def)
end
minetest.register_on_leaveplayer(function(player)
player_huds[player:get_player_name()] = nil
end)
local etime = 0
local state = 0
minetest.register_globalstep(function(dtime)
etime = etime + dtime
if etime < 1 then
return
end
etime = 0
for _, player in ipairs(minetest.get_connected_players()) do
local huds = player_huds[player:get_player_name()]
if huds then
for i, hud_id in ipairs(huds) do
local statetbl = states[(state + i) % #states + 1]
player:hud_change(hud_id, "style", statetbl[1])
player:hud_change(hud_id, "text", statetbl[2])
end
end
end
state = state + 1
end)
minetest.register_chatcommand("hudfonts", {
params = "",
description = "Show/Hide some text on the HUD with various font options",
func = function(name, param)
local player = minetest.get_player_by_name(name)
local param = tonumber(param) or 0
param = math.min(math.max(param, 1), #states)
if player_huds[name] == nil then
player_huds[name] = {}
for i = 1, param do
table.insert(player_huds[name], add_hud(player, i))
end
minetest.chat_send_player(name, ("%d HUD element(s) added."):format(param))
else
local huds = player_huds[name]
if huds then
for _, hud_id in ipairs(huds) do
player:hud_remove(hud_id)
end
minetest.chat_send_player(name, "All HUD elements removed.")
end
player_huds[name] = nil
end
return true
end,
})

@ -0,0 +1,2 @@
name = testhud
description = For testing HUD functionality

@ -59,7 +59,7 @@ struct ClientEventHudAdd
v2f pos, scale; v2f pos, scale;
std::string name; std::string name;
std::string text, text2; std::string text, text2;
u32 number, item, dir; u32 number, item, dir, style;
v2f align, offset; v2f align, offset;
v3f world_pos; v3f world_pos;
v2s32 size; v2s32 size;

@ -2730,6 +2730,7 @@ void Game::handleClientEvent_HudAdd(ClientEvent *event, CameraOrientation *cam)
e->size = event->hudadd->size; e->size = event->hudadd->size;
e->z_index = event->hudadd->z_index; e->z_index = event->hudadd->z_index;
e->text2 = event->hudadd->text2; e->text2 = event->hudadd->text2;
e->style = event->hudadd->style;
m_hud_server_to_client[server_id] = player->addHud(e); m_hud_server_to_client[server_id] = player->addHud(e);
delete event->hudadd; delete event->hudadd;
@ -2795,6 +2796,8 @@ void Game::handleClientEvent_HudChange(ClientEvent *event, CameraOrientation *ca
CASE_SET(HUD_STAT_Z_INDEX, z_index, data); CASE_SET(HUD_STAT_Z_INDEX, z_index, data);
CASE_SET(HUD_STAT_TEXT2, text2, sdata); CASE_SET(HUD_STAT_TEXT2, text2, sdata);
CASE_SET(HUD_STAT_STYLE, style, data);
} }
#undef CASE_SET #undef CASE_SET

@ -331,8 +331,8 @@ bool Hud::calculateScreenPos(const v3s16 &camera_offset, HudElement *e, v2s32 *p
void Hud::drawLuaElements(const v3s16 &camera_offset) void Hud::drawLuaElements(const v3s16 &camera_offset)
{ {
u32 text_height = g_fontengine->getTextHeight(); const u32 text_height = g_fontengine->getTextHeight();
irr::gui::IGUIFont* font = g_fontengine->getFont(); gui::IGUIFont *const font = g_fontengine->getFont();
// Reorder elements by z_index // Reorder elements by z_index
std::vector<HudElement*> elems; std::vector<HudElement*> elems;
@ -356,38 +356,34 @@ void Hud::drawLuaElements(const v3s16 &camera_offset)
floor(e->pos.Y * (float) m_screensize.Y + 0.5)); floor(e->pos.Y * (float) m_screensize.Y + 0.5));
switch (e->type) { switch (e->type) {
case HUD_ELEM_TEXT: { case HUD_ELEM_TEXT: {
irr::gui::IGUIFont *textfont = font;
unsigned int font_size = g_fontengine->getDefaultFontSize(); unsigned int font_size = g_fontengine->getDefaultFontSize();
if (e->size.X > 0) if (e->size.X > 0)
font_size *= e->size.X; font_size *= e->size.X;
if (font_size != g_fontengine->getDefaultFontSize()) #ifdef __ANDROID__
textfont = g_fontengine->getFont(font_size); // The text size on Android is not proportional with the actual scaling
// FIXME: why do we have such a weird unportable hack??
if (font_size > 3 && e->offset.X < -20)
font_size -= 3;
#endif
auto textfont = g_fontengine->getFont(FontSpec(font_size,
(e->style & HUD_STYLE_MONO) ? FM_Mono : FM_Unspecified,
e->style & HUD_STYLE_BOLD, e->style & HUD_STYLE_ITALIC));
video::SColor color(255, (e->number >> 16) & 0xFF, video::SColor color(255, (e->number >> 16) & 0xFF,
(e->number >> 8) & 0xFF, (e->number >> 8) & 0xFF,
(e->number >> 0) & 0xFF); (e->number >> 0) & 0xFF);
std::wstring text = unescape_translate(utf8_to_wide(e->text)); std::wstring text = unescape_translate(utf8_to_wide(e->text));
core::dimension2d<u32> textsize = textfont->getDimension(text.c_str()); core::dimension2d<u32> textsize = textfont->getDimension(text.c_str());
#ifdef __ANDROID__
// The text size on Android is not proportional with the actual scaling
irr::gui::IGUIFont *font_scaled = font_size <= 3 ?
textfont : g_fontengine->getFont(font_size - 3);
if (e->offset.X < -20)
textsize = font_scaled->getDimension(text.c_str());
#endif
v2s32 offset((e->align.X - 1.0) * (textsize.Width / 2), v2s32 offset((e->align.X - 1.0) * (textsize.Width / 2),
(e->align.Y - 1.0) * (textsize.Height / 2)); (e->align.Y - 1.0) * (textsize.Height / 2));
core::rect<s32> size(0, 0, e->scale.X * m_scale_factor, core::rect<s32> size(0, 0, e->scale.X * m_scale_factor,
text_height * e->scale.Y * m_scale_factor); text_height * e->scale.Y * m_scale_factor);
v2s32 offs(e->offset.X * m_scale_factor, v2s32 offs(e->offset.X * m_scale_factor,
e->offset.Y * m_scale_factor); e->offset.Y * m_scale_factor);
#ifdef __ANDROID__
if (e->offset.X < -20)
font_scaled->draw(text.c_str(), size + pos + offset + offs, color);
else
#endif
{ {
textfont->draw(text.c_str(), size + pos + offset + offs, color); textfont->draw(text.c_str(), size + pos + offset + offs, color);
} }

@ -50,6 +50,7 @@ const struct EnumString es_HudElementStat[] =
{HUD_STAT_SIZE, "size"}, {HUD_STAT_SIZE, "size"},
{HUD_STAT_Z_INDEX, "z_index"}, {HUD_STAT_Z_INDEX, "z_index"},
{HUD_STAT_TEXT2, "text2"}, {HUD_STAT_TEXT2, "text2"},
{HUD_STAT_STYLE, "style"},
{0, NULL}, {0, NULL},
}; };

@ -33,6 +33,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define HUD_CORNER_LOWER 1 #define HUD_CORNER_LOWER 1
#define HUD_CORNER_CENTER 2 #define HUD_CORNER_CENTER 2
#define HUD_STYLE_BOLD 1
#define HUD_STYLE_ITALIC 2
#define HUD_STYLE_MONO 4
// Note that these visibility flags do not determine if the hud items are // Note that these visibility flags do not determine if the hud items are
// actually drawn, but rather, whether to draw the item should the rest // actually drawn, but rather, whether to draw the item should the rest
// of the game state permit it. // of the game state permit it.
@ -78,6 +82,7 @@ enum HudElementStat {
HUD_STAT_SIZE, HUD_STAT_SIZE,
HUD_STAT_Z_INDEX, HUD_STAT_Z_INDEX,
HUD_STAT_TEXT2, HUD_STAT_TEXT2,
HUD_STAT_STYLE,
}; };
enum HudCompassDir { enum HudCompassDir {
@ -102,6 +107,7 @@ struct HudElement {
v2s32 size; v2s32 size;
s16 z_index = 0; s16 z_index = 0;
std::string text2; std::string text2;
u32 style;
}; };
extern const EnumString es_HudElementType[]; extern const EnumString es_HudElementType[];

@ -1061,6 +1061,7 @@ void Client::handleCommand_HudAdd(NetworkPacket* pkt)
v2s32 size; v2s32 size;
s16 z_index = 0; s16 z_index = 0;
std::string text2; std::string text2;
u32 style = 0;
*pkt >> server_id >> type >> pos >> name >> scale >> text >> number >> item *pkt >> server_id >> type >> pos >> name >> scale >> text >> number >> item
>> dir >> align >> offset; >> dir >> align >> offset;
@ -1069,6 +1070,7 @@ void Client::handleCommand_HudAdd(NetworkPacket* pkt)
*pkt >> size; *pkt >> size;
*pkt >> z_index; *pkt >> z_index;
*pkt >> text2; *pkt >> text2;
*pkt >> style;
} catch(PacketError &e) {}; } catch(PacketError &e) {};
ClientEvent *event = new ClientEvent(); ClientEvent *event = new ClientEvent();
@ -1089,6 +1091,7 @@ void Client::handleCommand_HudAdd(NetworkPacket* pkt)
event->hudadd->size = size; event->hudadd->size = size;
event->hudadd->z_index = z_index; event->hudadd->z_index = z_index;
event->hudadd->text2 = text2; event->hudadd->text2 = text2;
event->hudadd->style = style;
m_client_event_queue.push(event); m_client_event_queue.push(event);
} }
@ -1123,7 +1126,7 @@ void Client::handleCommand_HudChange(NetworkPacket* pkt)
*pkt >> sdata; *pkt >> sdata;
else if (stat == HUD_STAT_WORLD_POS) else if (stat == HUD_STAT_WORLD_POS)
*pkt >> v3fdata; *pkt >> v3fdata;
else if (stat == HUD_STAT_SIZE ) else if (stat == HUD_STAT_SIZE)
*pkt >> v2s32data; *pkt >> v2s32data;
else else
*pkt >> intdata; *pkt >> intdata;

@ -1928,6 +1928,8 @@ void read_hud_element(lua_State *L, HudElement *elem)
elem->world_pos = lua_istable(L, -1) ? read_v3f(L, -1) : v3f(); elem->world_pos = lua_istable(L, -1) ? read_v3f(L, -1) : v3f();
lua_pop(L, 1); lua_pop(L, 1);
elem->style = getintfield_default(L, 2, "style", 0);
/* check for known deprecated element usage */ /* check for known deprecated element usage */
if ((elem->type == HUD_ELEM_STATBAR) && (elem->size == v2s32())) if ((elem->type == HUD_ELEM_STATBAR) && (elem->size == v2s32()))
log_deprecated(L,"Deprecated usage of statbar without size!"); log_deprecated(L,"Deprecated usage of statbar without size!");
@ -1982,6 +1984,9 @@ void push_hud_element(lua_State *L, HudElement *elem)
lua_pushstring(L, elem->text2.c_str()); lua_pushstring(L, elem->text2.c_str());
lua_setfield(L, -2, "text2"); lua_setfield(L, -2, "text2");
lua_pushinteger(L, elem->style);
lua_setfield(L, -2, "style");
} }
HudElementStat read_hud_change(lua_State *L, HudElement *elem, void **value) HudElementStat read_hud_change(lua_State *L, HudElement *elem, void **value)
@ -2050,6 +2055,10 @@ HudElementStat read_hud_change(lua_State *L, HudElement *elem, void **value)
elem->text2 = luaL_checkstring(L, 4); elem->text2 = luaL_checkstring(L, 4);
*value = &elem->text2; *value = &elem->text2;
break; break;
case HUD_STAT_STYLE:
elem->style = luaL_checknumber(L, 4);
*value = &elem->style;
break;
} }
return stat; return stat;
} }

@ -1638,7 +1638,7 @@ void Server::SendHUDAdd(session_t peer_id, u32 id, HudElement *form)
pkt << id << (u8) form->type << form->pos << form->name << form->scale pkt << id << (u8) form->type << form->pos << form->name << form->scale
<< form->text << form->number << form->item << form->dir << form->text << form->number << form->item << form->dir
<< form->align << form->offset << form->world_pos << form->size << form->align << form->offset << form->world_pos << form->size
<< form->z_index << form->text2; << form->z_index << form->text2 << form->style;
Send(&pkt); Send(&pkt);
} }
@ -1673,10 +1673,7 @@ void Server::SendHUDChange(session_t peer_id, u32 id, HudElementStat stat, void
case HUD_STAT_SIZE: case HUD_STAT_SIZE:
pkt << *(v2s32 *) value; pkt << *(v2s32 *) value;
break; break;
case HUD_STAT_NUMBER: default: // all other types
case HUD_STAT_ITEM:
case HUD_STAT_DIR:
default:
pkt << *(u32 *) value; pkt << *(u32 *) value;
break; break;
} }