1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-09-15 18:57:08 +00:00

Add support for statbar “off state” icons (#9462)

This adds support for optional “off state” icons for statbars. “off state icons” can be used to denote the lack of something, like missing hearts or bubbles.

Add "off state" textures to the builtin statbars.

Co-authored-by: SmallJoker <mk939@ymail.com>
This commit is contained in:
Wuzzy 2020-05-11 21:40:45 +02:00 committed by GitHub
parent 88bb8e57e6
commit 6e1372bd89
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 132 additions and 36 deletions

View file

@ -136,6 +136,7 @@ struct ClientEvent
v3f *world_pos;
v2s32 *size;
s16 z_index;
std::string *text2;
} hudadd;
struct
{

View file

@ -2672,6 +2672,7 @@ void Game::handleClientEvent_HudAdd(ClientEvent *event, CameraOrientation *cam)
delete event->hudadd.offset;
delete event->hudadd.world_pos;
delete event->hudadd.size;
delete event->hudadd.text2;
return;
}
@ -2689,6 +2690,7 @@ void Game::handleClientEvent_HudAdd(ClientEvent *event, CameraOrientation *cam)
e->world_pos = *event->hudadd.world_pos;
e->size = *event->hudadd.size;
e->z_index = event->hudadd.z_index;
e->text2 = *event->hudadd.text2;
hud_server_to_client[server_id] = player->addHud(e);
delete event->hudadd.pos;
@ -2699,6 +2701,7 @@ void Game::handleClientEvent_HudAdd(ClientEvent *event, CameraOrientation *cam)
delete event->hudadd.offset;
delete event->hudadd.world_pos;
delete event->hudadd.size;
delete event->hudadd.text2;
}
void Game::handleClientEvent_HudRemove(ClientEvent *event, CameraOrientation *cam)
@ -2771,6 +2774,10 @@ void Game::handleClientEvent_HudChange(ClientEvent *event, CameraOrientation *ca
case HUD_STAT_Z_INDEX:
e->z_index = event->hudchange.data;
break;
case HUD_STAT_TEXT2:
e->text2 = *event->hudchange.sdata;
break;
}
delete event->hudchange.v3fdata;

View file

@ -332,7 +332,8 @@ void Hud::drawLuaElements(const v3s16 &camera_offset)
break; }
case HUD_ELEM_STATBAR: {
v2s32 offs(e->offset.X, e->offset.Y);
drawStatbar(pos, HUD_CORNER_UPPER, e->dir, e->text, e->number, offs, e->size);
drawStatbar(pos, HUD_CORNER_UPPER, e->dir, e->text, e->text2,
e->number, e->item, offs, e->size);
break; }
case HUD_ELEM_INVENTORY: {
InventoryList *inv = inventory->getList(e->text);
@ -401,8 +402,9 @@ void Hud::drawLuaElements(const v3s16 &camera_offset)
}
void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, const std::string &texture,
s32 count, v2s32 offset, v2s32 size)
void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir,
const std::string &texture, const std::string &bgtexture,
s32 count, s32 maxcount, v2s32 offset, v2s32 size)
{
const video::SColor color(255, 255, 255, 255);
const video::SColor colors[] = {color, color, color, color};
@ -411,6 +413,11 @@ void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, const std::string &tex
if (!stat_texture)
return;
video::ITexture *stat_texture_bg = nullptr;
if (!bgtexture.empty()) {
stat_texture_bg = tsrc->getTexture(bgtexture);
}
core::dimension2di srcd(stat_texture->getOriginalSize());
core::dimension2di dstd;
if (size == v2s32()) {
@ -430,43 +437,100 @@ void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, const std::string &tex
p += offset;
v2s32 steppos;
core::rect<s32> srchalfrect, dsthalfrect;
switch (drawdir) {
case HUD_DIR_RIGHT_LEFT:
steppos = v2s32(-1, 0);
srchalfrect = core::rect<s32>(srcd.Width / 2, 0, srcd.Width, srcd.Height);
dsthalfrect = core::rect<s32>(dstd.Width / 2, 0, dstd.Width, dstd.Height);
break;
case HUD_DIR_TOP_BOTTOM:
steppos = v2s32(0, 1);
srchalfrect = core::rect<s32>(0, 0, srcd.Width, srcd.Height / 2);
dsthalfrect = core::rect<s32>(0, 0, dstd.Width, dstd.Height / 2);
break;
case HUD_DIR_BOTTOM_TOP:
steppos = v2s32(0, -1);
srchalfrect = core::rect<s32>(0, srcd.Height / 2, srcd.Width, srcd.Height);
dsthalfrect = core::rect<s32>(0, dstd.Height / 2, dstd.Width, dstd.Height);
break;
default:
// From left to right
steppos = v2s32(1, 0);
srchalfrect = core::rect<s32>(0, 0, srcd.Width / 2, srcd.Height);
dsthalfrect = core::rect<s32>(0, 0, dstd.Width / 2, dstd.Height);
break;
}
auto calculate_clipping_rect = [] (core::dimension2di src,
v2s32 steppos) -> core::rect<s32> {
// Create basic rectangle
core::rect<s32> rect(0, 0,
src.Width - std::abs(steppos.X) * src.Width / 2,
src.Height - std::abs(steppos.Y) * src.Height / 2
);
// Move rectangle left or down
if (steppos.X == -1)
rect += v2s32(src.Width / 2, 0);
if (steppos.Y == -1)
rect += v2s32(0, src.Height / 2);
return rect;
};
// Rectangles for 1/2 the actual value to display
core::rect<s32> srchalfrect, dsthalfrect;
// Rectangles for 1/2 the "off state" texture
core::rect<s32> srchalfrect2, dsthalfrect2;
if (count % 2 == 1) {
// Need to draw halves: Calculate rectangles
srchalfrect = calculate_clipping_rect(srcd, steppos);
dsthalfrect = calculate_clipping_rect(dstd, steppos);
srchalfrect2 = calculate_clipping_rect(srcd, steppos * -1);
dsthalfrect2 = calculate_clipping_rect(dstd, steppos * -1);
}
steppos.X *= dstd.Width;
steppos.Y *= dstd.Height;
// Draw full textures
for (s32 i = 0; i < count / 2; i++) {
core::rect<s32> srcrect(0, 0, srcd.Width, srcd.Height);
core::rect<s32> dstrect(0,0, dstd.Width, dstd.Height);
core::rect<s32> dstrect(0, 0, dstd.Width, dstd.Height);
dstrect += p;
draw2DImageFilterScaled(driver, stat_texture, dstrect, srcrect, NULL, colors, true);
draw2DImageFilterScaled(driver, stat_texture,
dstrect, srcrect, NULL, colors, true);
p += steppos;
}
if (count % 2 == 1) {
dsthalfrect += p;
draw2DImageFilterScaled(driver, stat_texture, dsthalfrect, srchalfrect, NULL, colors, true);
// Draw half a texture
draw2DImageFilterScaled(driver, stat_texture,
dsthalfrect + p, srchalfrect, NULL, colors, true);
if (stat_texture_bg && maxcount > count) {
draw2DImageFilterScaled(driver, stat_texture_bg,
dsthalfrect2 + p, srchalfrect2,
NULL, colors, true);
p += steppos;
}
}
if (stat_texture_bg && maxcount > count / 2) {
// Draw "off state" textures
s32 start_offset;
if (count % 2 == 1)
start_offset = count / 2 + 1;
else
start_offset = count / 2;
for (s32 i = start_offset; i < maxcount / 2; i++) {
core::rect<s32> srcrect(0, 0, srcd.Width, srcd.Height);
core::rect<s32> dstrect(0, 0, dstd.Width, dstd.Height);
dstrect += p;
draw2DImageFilterScaled(driver, stat_texture_bg,
dstrect, srcrect,
NULL, colors, true);
p += steppos;
}
if (maxcount % 2 == 1) {
draw2DImageFilterScaled(driver, stat_texture_bg,
dsthalfrect + p, srchalfrect,
NULL, colors, true);
}
}
}

View file

@ -82,8 +82,9 @@ public:
private:
bool calculateScreenPos(const v3s16 &camera_offset, HudElement *e, v2s32 *pos);
void drawStatbar(v2s32 pos, u16 corner, u16 drawdir, const std::string &texture,
s32 count, v2s32 offset, v2s32 size = v2s32());
void drawStatbar(v2s32 pos, u16 corner, u16 drawdir,
const std::string &texture, const std::string& bgtexture,
s32 count, s32 maxcount, v2s32 offset, v2s32 size = v2s32());
void drawItems(v2s32 upperleftpos, v2s32 screen_offset, s32 itemcount,
s32 inv_offset, InventoryList *mainlist, u16 selectitem,

View file

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

View file

@ -77,6 +77,7 @@ enum HudElementStat {
HUD_STAT_WORLD_POS,
HUD_STAT_SIZE,
HUD_STAT_Z_INDEX,
HUD_STAT_TEXT2,
};
struct HudElement {
@ -93,6 +94,7 @@ struct HudElement {
v3f world_pos;
v2s32 size;
s16 z_index = 0;
std::string text2;
};
extern const EnumString es_HudElementType[];

View file

@ -1102,22 +1102,16 @@ void Client::handleCommand_HudAdd(NetworkPacket* pkt)
v3f world_pos;
v2s32 size;
s16 z_index = 0;
std::string text2;
*pkt >> server_id >> type >> pos >> name >> scale >> text >> number >> item
>> dir >> align >> offset;
try {
*pkt >> world_pos;
}
catch(SerializationError &e) {};
try {
*pkt >> size;
} catch(SerializationError &e) {};
try {
*pkt >> z_index;
}
catch(PacketError &e) {}
*pkt >> text2;
} catch(PacketError &e) {};
ClientEvent *event = new ClientEvent();
event->type = CE_HUDADD;
@ -1135,6 +1129,7 @@ void Client::handleCommand_HudAdd(NetworkPacket* pkt)
event->hudadd.world_pos = new v3f(world_pos);
event->hudadd.size = new v2s32(size);
event->hudadd.z_index = z_index;
event->hudadd.text2 = new std::string(text2);
m_client_event_queue.push(event);
}
@ -1171,7 +1166,7 @@ void Client::handleCommand_HudChange(NetworkPacket* pkt)
if (stat == HUD_STAT_POS || stat == HUD_STAT_SCALE ||
stat == HUD_STAT_ALIGN || stat == HUD_STAT_OFFSET)
*pkt >> v2fdata;
else if (stat == HUD_STAT_NAME || stat == HUD_STAT_TEXT)
else if (stat == HUD_STAT_NAME || stat == HUD_STAT_TEXT || stat == HUD_STAT_TEXT2)
*pkt >> sdata;
else if (stat == HUD_STAT_WORLD_POS)
*pkt >> v3fdata;

View file

@ -560,10 +560,10 @@ enum ToClientCommand
u32 id
u8 type
v2f1000 pos
u32 len
u16 len
u8[len] name
v2f1000 scale
u32 len2
u16 len2
u8[len2] text
u32 number
u32 item
@ -573,6 +573,8 @@ enum ToClientCommand
v3f1000 world_pos
v2s32 size
s16 z_index
u16 len3
u8[len3] text2
*/
TOCLIENT_HUDRM = 0x4a,

View file

@ -1871,6 +1871,7 @@ void read_hud_element(lua_State *L, HudElement *elem)
elem->dir = getintfield_default(L, 2, "direction", 0);
elem->z_index = MYMAX(S16_MIN, MYMIN(S16_MAX,
getintfield_default(L, 2, "z_index", 0)));
elem->text2 = getstringfield_default(L, 2, "text2", "");
// Deprecated, only for compatibility's sake
if (elem->dir == 0)
@ -1939,6 +1940,9 @@ void push_hud_element(lua_State *L, HudElement *elem)
lua_pushnumber(L, elem->z_index);
lua_setfield(L, -2, "z_index");
lua_pushstring(L, elem->text2.c_str());
lua_setfield(L, -2, "text2");
}
HudElementStat read_hud_change(lua_State *L, HudElement *elem, void **value)
@ -2000,6 +2004,10 @@ HudElementStat read_hud_change(lua_State *L, HudElement *elem, void **value)
elem->z_index = MYMAX(S16_MIN, MYMIN(S16_MAX, luaL_checknumber(L, 4)));
*value = &elem->z_index;
break;
case HUD_STAT_TEXT2:
elem->text2 = luaL_checkstring(L, 4);
*value = &elem->text2;
break;
}
return stat;
}

View file

@ -1621,7 +1621,7 @@ void Server::SendHUDAdd(session_t peer_id, u32 id, HudElement *form)
pkt << id << (u8) form->type << form->pos << form->name << form->scale
<< form->text << form->number << form->item << form->dir
<< form->align << form->offset << form->world_pos << form->size
<< form->z_index;
<< form->z_index << form->text2;
Send(&pkt);
}
@ -1647,6 +1647,7 @@ void Server::SendHUDChange(session_t peer_id, u32 id, HudElementStat stat, void
break;
case HUD_STAT_NAME:
case HUD_STAT_TEXT:
case HUD_STAT_TEXT2:
pkt << *(std::string *) value;
break;
case HUD_STAT_WORLD_POS: