Add z-index management to HUD
authorPierre-Yves Rollo <dev@pyrollo.com>
Mon, 4 Nov 2019 08:30:02 +0000 (09:30 +0100)
committerrubenwardy <rw@rubenwardy.com>
Fri, 6 Dec 2019 20:31:26 +0000 (20:31 +0000)
doc/lua_api.txt
src/client/clientevent.h
src/client/game.cpp
src/client/hud.cpp
src/hud.cpp
src/hud.h
src/network/clientpackethandler.cpp
src/network/networkprotocol.h
src/script/common/c_content.cpp
src/server.cpp

index 9ca44747fc6bffeff9190eaa6658a23300cadd02..697efcdbc1624093b01ec4f66a92dea2bd0845ad 100644 (file)
@@ -1260,6 +1260,11 @@ precisely positioned items in the HUD.
 **Note**: `offset` _will_ adapt to screen DPI as well as user defined scaling
 factor!
 
+The `z_index` field specifies the order of HUD elements from back to front.
+Lower z-index elements are displayed behind higher z-index elements. Elements
+with same z-index are displayed in an arbitrary order. Default 0.
+Supports negative values.
+
 Below are the specific uses for fields in each type; fields not listed for that
 type are ignored.
 
@@ -7322,6 +7327,9 @@ Used by `Player:hud_add`. Returned by `Player:hud_get`.
 
         size = { x=100, y=100 },
         -- Size of element in pixels
+
+        z_index = 0,
+        -- Z index : lower z-index HUDs are displayed behind higher z-index HUDs
     }
 
 Particle definition
index 2a44717ce4195e82c15820f4a204177cb0874780..69e8838b469dc5b17553dbe88be09a7ed01ed80f 100644 (file)
@@ -131,6 +131,7 @@ struct ClientEvent
                        v2f *offset;
                        v3f *world_pos;
                        v2s32 *size;
+                       s16 z_index;
                } hudadd;
                struct
                {
index 59654e892ddf084b7e127163d2959d4f593afa32..e3e0e1150ec5bd81fe084746ff923b6265d98f57 100644 (file)
@@ -2650,6 +2650,7 @@ void Game::handleClientEvent_HudAdd(ClientEvent *event, CameraOrientation *cam)
        e->offset = *event->hudadd.offset;
        e->world_pos = *event->hudadd.world_pos;
        e->size = *event->hudadd.size;
+       e->z_index = event->hudadd.z_index;
        hud_server_to_client[server_id] = player->addHud(e);
 
        delete event->hudadd.pos;
@@ -2728,6 +2729,10 @@ void Game::handleClientEvent_HudChange(ClientEvent *event, CameraOrientation *ca
                case HUD_STAT_SIZE:
                        e->size = *event->hudchange.v2s32data;
                        break;
+
+               case HUD_STAT_Z_INDEX:
+                       e->z_index = event->hudchange.data;
+                       break;
        }
 
        delete event->hudchange.v3fdata;
index 304a3ab16194272bd18b6cf2204ee21aae848c40..e78130dd42d0cf8a8712372d8add397761544ddf 100644 (file)
@@ -283,11 +283,25 @@ void Hud::drawLuaElements(const v3s16 &camera_offset)
 {
        u32 text_height = g_fontengine->getTextHeight();
        irr::gui::IGUIFont* font = g_fontengine->getFont();
+
+       // Reorder elements by z_index
+       std::vector<size_t> ids;
+
        for (size_t i = 0; i != player->maxHudId(); i++) {
                HudElement *e = player->getHud(i);
                if (!e)
                        continue;
 
+               auto it = ids.begin();
+               while (it != ids.end() && player->getHud(*it)->z_index <= e->z_index)
+                       ++it;
+
+               ids.insert(it, i);
+       }
+
+       for (size_t i : ids) {
+               HudElement *e = player->getHud(i);
+
                v2s32 pos(floor(e->pos.X * (float) m_screensize.X + 0.5),
                                floor(e->pos.Y * (float) m_screensize.Y + 0.5));
                switch (e->type) {
index 8ada65274730805a4ee49319077c4ffcb341cd42..7711e3a4a143368bf1fbf4a25ab5af10507f65ab 100644 (file)
@@ -43,6 +43,8 @@ const struct EnumString es_HudElementStat[] =
        {HUD_STAT_ALIGN,  "alignment"},
        {HUD_STAT_OFFSET, "offset"},
        {HUD_STAT_WORLD_POS, "world_pos"},
+       {HUD_STAT_SIZE,    "size"},
+       {HUD_STAT_Z_INDEX, "z_index"},
        {0, NULL},
 };
 
index bfb6443035975ebe01e0c8c304405b1757457a99..23f189dff5cd9c9001081509d360f598cf731d0a 100644 (file)
--- a/src/hud.h
+++ b/src/hud.h
@@ -74,7 +74,8 @@ enum HudElementStat {
        HUD_STAT_ALIGN,
        HUD_STAT_OFFSET,
        HUD_STAT_WORLD_POS,
-       HUD_STAT_SIZE
+       HUD_STAT_SIZE,
+       HUD_STAT_Z_INDEX,
 };
 
 struct HudElement {
@@ -90,6 +91,7 @@ struct HudElement {
        v2f offset;
        v3f world_pos;
        v2s32 size;
+       s16 z_index = 0;
 };
 
 extern const EnumString es_HudElementType[];
index b6e9defb00444c98e2b4fd1fe916640e37b39b55..79f2b95babfc913688a117063254c8f056f847ab 100644 (file)
@@ -1081,6 +1081,7 @@ void Client::handleCommand_HudAdd(NetworkPacket* pkt)
        v2f offset;
        v3f world_pos;
        v2s32 size;
+       s16 z_index = 0;
 
        *pkt >> server_id >> type >> pos >> name >> scale >> text >> number >> item
                >> dir >> align >> offset;
@@ -1093,6 +1094,11 @@ void Client::handleCommand_HudAdd(NetworkPacket* pkt)
                *pkt >> size;
        } catch(SerializationError &e) {};
 
+       try {
+               *pkt >> z_index;
+       }
+       catch(PacketError &e) {}
+
        ClientEvent *event = new ClientEvent();
        event->type             = CE_HUDADD;
        event->hudadd.server_id = server_id;
@@ -1108,6 +1114,7 @@ void Client::handleCommand_HudAdd(NetworkPacket* pkt)
        event->hudadd.offset    = new v2f(offset);
        event->hudadd.world_pos = new v3f(world_pos);
        event->hudadd.size      = new v2s32(size);
+       event->hudadd.z_index   = z_index;
        m_client_event_queue.push(event);
 }
 
index 236c7892e01ccaace927cc7f48395e23d6a1d673..f740278284d65e8f9a03ef5cd8571a231fabb8d1 100644 (file)
@@ -563,6 +563,7 @@ enum ToClientCommand
                v2f1000 offset
                v3f1000 world_pos
                v2s32 size
+               s16 z_index
        */
 
        TOCLIENT_HUDRM = 0x4a,
index 72142798eb2042061c439a316431425412831aa6..fc1d82bcc1368d4b9b20c30c7f7abcbe9f05fb3a 100644 (file)
@@ -1851,11 +1851,13 @@ void read_hud_element(lua_State *L, HudElement *elem)
        elem->size = lua_istable(L, -1) ? read_v2s32(L, -1) : v2s32();
        lua_pop(L, 1);
 
-       elem->name   = getstringfield_default(L, 2, "name", "");
-       elem->text   = getstringfield_default(L, 2, "text", "");
-       elem->number = getintfield_default(L, 2, "number", 0);
-       elem->item   = getintfield_default(L, 2, "item", 0);
-       elem->dir    = getintfield_default(L, 2, "direction", 0);
+       elem->name    = getstringfield_default(L, 2, "name", "");
+       elem->text    = getstringfield_default(L, 2, "text", "");
+       elem->number  = getintfield_default(L, 2, "number", 0);
+       elem->item    = getintfield_default(L, 2, "item", 0);
+       elem->dir     = getintfield_default(L, 2, "direction", 0);
+       elem->z_index = MYMAX(S16_MIN, MYMIN(S16_MAX,
+                       getintfield_default(L, 2, "z_index", 0)));
 
        // Deprecated, only for compatibility's sake
        if (elem->dir == 0)
@@ -1921,6 +1923,9 @@ void push_hud_element(lua_State *L, HudElement *elem)
 
        push_v3f(L, elem->world_pos);
        lua_setfield(L, -2, "world_pos");
+
+       lua_pushnumber(L, elem->z_index);
+       lua_setfield(L, -2, "z_index");
 }
 
 HudElementStat read_hud_change(lua_State *L, HudElement *elem, void **value)
@@ -1978,6 +1983,10 @@ HudElementStat read_hud_change(lua_State *L, HudElement *elem, void **value)
                        elem->size = read_v2s32(L, 4);
                        *value = &elem->size;
                        break;
+               case HUD_STAT_Z_INDEX:
+                       elem->z_index = MYMAX(S16_MIN, MYMIN(S16_MAX, luaL_checknumber(L, 4)));
+                       *value = &elem->z_index;
+                       break;
        }
        return stat;
 }
index d914beead35c44d086ac1aad92240c4387ff0db9..4090dd773e065312db345890aed6377549e444e6 100644 (file)
@@ -1654,7 +1654,8 @@ 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->align << form->offset << form->world_pos << form->size
+                       << form->z_index;
 
        Send(&pkt);
 }