mirror of
https://github.com/minetest/minetest.git
synced 2024-08-19 04:54:18 +02: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:
parent
88bb8e57e6
commit
6e1372bd89
@ -5,7 +5,9 @@ local health_bar_definition = {
|
||||
hud_elem_type = "statbar",
|
||||
position = {x = 0.5, y = 1},
|
||||
text = "heart.png",
|
||||
text2 = "heart_gone.png",
|
||||
number = core.PLAYER_MAX_HP_DEFAULT,
|
||||
item = core.PLAYER_MAX_HP_DEFAULT,
|
||||
direction = 0,
|
||||
size = {x = 24, y = 24},
|
||||
offset = {x = (-10 * 24) - 25, y = -(48 + 24 + 16)},
|
||||
@ -15,7 +17,9 @@ local breath_bar_definition = {
|
||||
hud_elem_type = "statbar",
|
||||
position = {x = 0.5, y = 1},
|
||||
text = "bubble.png",
|
||||
text2 = "bubble_gone.png",
|
||||
number = core.PLAYER_MAX_BREATH_DEFAULT,
|
||||
item = core.PLAYER_MAX_BREATH_DEFAULT * 2,
|
||||
direction = 0,
|
||||
size = {x = 24, y = 24},
|
||||
offset = {x = 25, y= -(48 + 24 + 16)},
|
||||
|
@ -1289,9 +1289,9 @@ To account for differing resolutions, the position coordinates are the
|
||||
percentage of the screen, ranging in value from `0` to `1`.
|
||||
|
||||
The name field is not yet used, but should contain a description of what the
|
||||
HUD element represents. The direction field is the direction in which something
|
||||
is drawn.
|
||||
HUD element represents.
|
||||
|
||||
The `direction` field is the direction in which something is drawn.
|
||||
`0` draws from left to right, `1` draws from right to left, `2` draws from
|
||||
top to bottom, and `3` draws from bottom to top.
|
||||
|
||||
@ -1355,12 +1355,16 @@ Displays text on the HUD.
|
||||
|
||||
### `statbar`
|
||||
|
||||
Displays a horizontal bar made up of half-images.
|
||||
Displays a horizontal bar made up of half-images with an optional background.
|
||||
|
||||
* `text`: The name of the texture that is used.
|
||||
* `text`: The name of the texture to use.
|
||||
* `text2`: Optional texture name to enable a background / "off state"
|
||||
texture (useful to visualize the maximal value). Both textures
|
||||
must have the same size.
|
||||
* `number`: The number of half-textures that are displayed.
|
||||
If odd, will end with a vertically center-split texture.
|
||||
* `direction`
|
||||
* `item`: Same as `number` but for the "off state" texture
|
||||
* `direction`: To which direction the images will extend to
|
||||
* `offset`: offset in pixels from position.
|
||||
* `size`: If used, will force full-image size to this value (override texture
|
||||
pack image size)
|
||||
@ -7772,6 +7776,8 @@ Used by `Player:hud_add`. Returned by `Player:hud_get`.
|
||||
|
||||
text = "<text>",
|
||||
|
||||
text2 = "<text>",
|
||||
|
||||
number = 2,
|
||||
|
||||
item = 3,
|
||||
|
@ -64,6 +64,8 @@ by texture packs. All existing fallback textures can be found in the directory
|
||||
|
||||
* `bubble.png`: the bubble texture when the player is drowning
|
||||
(default size: 12×12)
|
||||
* `bubble_gone.png`: like `bubble.png`, but denotes lack of breath
|
||||
(transparent by default, same size as bubble.png)
|
||||
|
||||
* `crack_anylength.png`: node overlay texture when digging
|
||||
|
||||
@ -76,6 +78,8 @@ by texture packs. All existing fallback textures can be found in the directory
|
||||
|
||||
* `heart.png`: used to display the health points of the player
|
||||
(default size: 12×12)
|
||||
* `heart_gone.png`: like `heart.png`, but denotes lack of health points
|
||||
(transparent by default, same size as heart.png)
|
||||
|
||||
* `minimap_mask_round.png`: round minimap mask, white gets replaced by the map
|
||||
* `minimap_mask_square.png`: mask used for the square minimap
|
||||
|
@ -136,6 +136,7 @@ struct ClientEvent
|
||||
v3f *world_pos;
|
||||
v2s32 *size;
|
||||
s16 z_index;
|
||||
std::string *text2;
|
||||
} hudadd;
|
||||
struct
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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},
|
||||
};
|
||||
|
||||
|
@ -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[];
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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:
|
||||
|
BIN
textures/base/pack/bubble_gone.png
Normal file
BIN
textures/base/pack/bubble_gone.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 68 B |
BIN
textures/base/pack/heart_gone.png
Normal file
BIN
textures/base/pack/heart_gone.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 68 B |
Loading…
Reference in New Issue
Block a user