[CSM] Add basic HUD manipulation. (#6067)
authorred-001 <red-001@outlook.ie>
Sat, 20 Jan 2018 13:09:58 +0000 (13:09 +0000)
committerLoïc Blot <nerzhul@users.noreply.github.com>
Sat, 20 Jan 2018 13:09:58 +0000 (14:09 +0100)
* [CSM] Add basic HUD manipulation.

Workaround for on_connect not working right now.

21 files changed:
.gitignore
build/android/jni/Android.mk
clientmods/preview/init.lua
doc/client_lua_api.txt
src/CMakeLists.txt
src/client.h
src/client/CMakeLists.txt
src/client/hud.cpp [new file with mode: 0644]
src/client/hud.h [new file with mode: 0644]
src/client/render/sidebyside.cpp
src/client/renderingengine.cpp
src/gui/guiFormSpecMenu.cpp
src/hud.cpp
src/hud.h
src/network/clientpackethandler.cpp
src/script/common/c_content.cpp
src/script/common/c_content.h
src/script/lua_api/l_localplayer.cpp
src/script/lua_api/l_localplayer.h
src/script/lua_api/l_object.cpp
util/travis/clang-format-whitelist.txt

index 7b5ecab675dd3d523c7be2f4a15ba061199dcd2a..80415c8307ce0c28f7876a06ef94e93f32a325dd 100644 (file)
@@ -86,6 +86,8 @@ locale/
 *.gch
 cmake-build-debug/
 cmake-build-release/
+cmake_config.h
+cmake_config_githash.h
 
 ## Android build files
 build/android/src/main/assets
index 375ab5ce47a0516e5b8629d50cde9c003a32d494..72be8fe2c683e9882aa09a4b09b659f04dd89ca4 100644 (file)
@@ -270,6 +270,7 @@ LOCAL_SRC_FILES := \
                jni/src/settings.cpp                      \
                jni/src/wieldmesh.cpp                     \
                jni/src/client/clientlauncher.cpp         \
+               jni/src/client/hud.cpp                    \
                jni/src/client/inputhandler.cpp           \
                jni/src/client/renderingengine.cpp        \
                jni/src/client/tile.cpp                   \
index 288b1b16c1d9ea67e2134fef3372ad5466d05d00..a384fd6bf6a9047daf74f279efb1918ce4a104a3 100644 (file)
@@ -7,7 +7,7 @@ dofile("preview:example.lua")
 core.register_on_shutdown(function()
        print("[PREVIEW] shutdown client")
 end)
-
+local id = 0
 core.register_on_connect(function()
        print("[PREVIEW] Player connection completed")
        local server_info = core.get_server_info()
@@ -15,7 +15,6 @@ core.register_on_connect(function()
        print("Server ip: " .. server_info.ip)
        print("Server address: " .. server_info.address)
        print("Server port: " .. server_info.port)
-
        mod_channel = core.mod_channel_join("experimental_preview")
 
        core.after(4, function()
@@ -25,6 +24,19 @@ core.register_on_connect(function()
        end)
 end)
 
+core.after(1, function()
+       id = core.localplayer:hud_add({
+                       hud_elem_type = "text",
+                       name = "example",
+                       number = 0xff0000,
+                       position = {x=0, y=1},
+                       offset = {x=8, y=-8},
+                       text = "You are using the preview mod",
+                       scale = {x=200, y=60},
+                       alignment = {x=1, y=-1},
+       })
+end)
+
 core.register_on_modchannel_message(function(channel, sender, message)
        print("[PREVIEW][modchannels] Received message `" .. message .. "` on channel `"
                        .. channel .. "` from sender `" .. sender .. "`")
@@ -184,3 +196,9 @@ core.register_chatcommand("privs", {
                return true, core.privs_to_string(minetest.get_privilege_list())
        end,
 })
+
+core.register_chatcommand("text", {
+       func = function(param)
+               return core.localplayer:hud_change(id, "text", param)
+       end,
+})
index d79b644d72b78f28016da396bc6808fa9eda5095..435cc5b2e502588694fb4b8847474aaeb5b07de4 100644 (file)
@@ -1025,6 +1025,17 @@ Methods:
     * returns last look vertical angle
 * `get_key_pressed()`:
     * returns last key typed by the player
+* `hud_add(definition)`
+    * add a HUD element described by HUD def, returns ID number on success and `nil` on failure.
+    * See [`HUD definition`](#hud-definition-hud_add-hud_get)
+* `hud_get(id)`
+    * returns the [`definition`](#hud-definition-hud_add-hud_get) of the HUD with that ID number or `nil`, if non-existent.
+* `hud_remove(id)`
+    * remove the HUD element of the specified id, returns `true` on success
+* `hud_change(id, stat, value)`
+    * change a value of a previously added HUD element
+    * element `stat` values: `position`, `name`, `scale`, `text`, `number`, `item`, `dir`
+    * Returns `true` on success, otherwise returns `nil`
 
 ### Settings
 An interface to read config files in the format of `minetest.conf`.
@@ -1163,6 +1174,30 @@ Can be obtained via `minetest.get_meta(pos)`.
 }
 ```
 
+### HUD Definition (`hud_add`, `hud_get`)
+```lua
+    {
+        hud_elem_type = "image", -- see HUD element types, default "text"
+    --  ^ type of HUD element, can be either of "image", "text", "statbar", or "inventory"
+        position = {x=0.5, y=0.5},
+    --  ^ Left corner position of element, default `{x=0,y=0}`.
+        name = "<name>",    -- default ""
+        scale = {x=2, y=2}, -- default {x=0,y=0}
+        text = "<text>",    -- default ""
+        number = 2,         -- default 0
+        item = 3,           -- default 0
+    --  ^ Selected item in inventory.  0 for no item selected.
+        direction = 0,      -- default 0
+    --  ^ Direction: 0: left-right, 1: right-left, 2: top-bottom, 3: bottom-top
+        alignment = {x=0, y=0},   -- default {x=0, y=0}
+    --  ^ See "HUD Element Types"
+        offset = {x=0, y=0},      -- default {x=0, y=0}
+    --  ^ See "HUD Element Types"
+        size = { x=100, y=100 },  -- default {x=0, y=0}
+    --  ^ Size of element in pixels
+    }
+```
+
 Escape sequences
 ----------------
 Most text can contain escape sequences, that can for example color the text.
@@ -1206,3 +1241,80 @@ value must (always) be two hexadecimal digits.
 `Color`
 -------------
 `{a = alpha, r = red, g = green, b = blue}` defines an ARGB8 color.
+
+HUD element types
+-----------------
+The position field is used for all element types.
+
+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.
+
+`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.
+
+The `alignment` field specifies how the item will be aligned. It ranges from `-1` to `1`,
+with `0` being the center, `-1` is moved to the left/up, and `1` is to the right/down.
+Fractional values can be used.
+
+The `offset` field specifies a pixel offset from the position. Contrary to position,
+the offset is not scaled to screen size. This allows for some precisely-positioned
+items in the HUD.
+
+**Note**: `offset` _will_ adapt to screen DPI as well as user defined scaling factor!
+
+Below are the specific uses for fields in each type; fields not listed for that type are ignored.
+
+**Note**: Future revisions to the HUD API may be incompatible; the HUD API is still
+in the experimental stages.
+
+### `image`
+Displays an image on the HUD.
+
+* `scale`: The scale of the image, with 1 being the original texture size.
+  Only the X coordinate scale is used (positive values).
+  Negative values represent that percentage of the screen it
+  should take; e.g. `x=-100` means 100% (width).
+* `text`: The name of the texture that is displayed.
+* `alignment`: The alignment of the image.
+* `offset`: offset in pixels from position.
+
+### `text`
+Displays text on the HUD.
+
+* `scale`: Defines the bounding rectangle of the text.
+  A value such as `{x=100, y=100}` should work.
+* `text`: The text to be displayed in the HUD element.
+* `number`: An integer containing the RGB value of the color used to draw the text.
+  Specify `0xFFFFFF` for white text, `0xFF0000` for red, and so on.
+* `alignment`: The alignment of the text.
+* `offset`: offset in pixels from position.
+
+### `statbar`
+Displays a horizontal bar made up of half-images.
+
+* `text`: The name of the texture that is used.
+* `number`: The number of half-textures that are displayed.
+  If odd, will end with a vertically center-split texture.
+* `direction`
+* `offset`: offset in pixels from position.
+* `size`: If used, will force full-image size to this value (override texture pack image size)
+
+### `inventory`
+* `text`: The name of the inventory list to be displayed.
+* `number`: Number of items in the inventory to be displayed.
+* `item`: Position of item that is selected.
+* `direction`
+* `offset`: offset in pixels from position.
+
+### `waypoint`
+Displays distance to selected world position.
+
+* `name`: The name of the waypoint.
+* `text`: Distance suffix. Can be blank.
+* `number:` An integer containing the RGB value of the color used to draw the text.
+* `world_pos`: World position of the waypoint.
+
index 9964b828b5b8f178d48c6041d02deb3e55a82dc6..c2b28832a19801093a06faf4483684d1a80ca9a6 100644 (file)
@@ -448,6 +448,7 @@ set(common_SRCS
        version.cpp
        voxel.cpp
        voxelalgorithms.cpp
+       hud.cpp
        ${common_network_SRCS}
        ${JTHREAD_SRCS}
        ${common_SCRIPT_SRCS}
index 11f27e9bdab97d1faee30e029d2704c2822f5c76..caa3a7b73d3b288ab5b904124bb8f7a2b83d9f4f 100644 (file)
@@ -30,7 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "gamedef.h"
 #include "inventorymanager.h"
 #include "localplayer.h"
-#include "hud.h"
+#include "client/hud.h"
 #include "particles.h"
 #include "mapnode.h"
 #include "tileanimation.h"
@@ -554,6 +554,10 @@ private:
        // And relations to objects
        std::unordered_map<int, u16> m_sounds_to_objects;
 
+       // HUD
+       // Mapping from server hud ids to internal hud ids
+       std::unordered_map<u32, u32> m_hud_server_to_client;
+
        // Privileges
        std::unordered_set<std::string> m_privileges;
 
index 3462636f4c24a436cf42ad42665ac0e5997a780f..c69b2c2d4829d1381452988877ecd44efac7ba6e 100644 (file)
@@ -13,5 +13,6 @@ set(client_SRCS
        ${CMAKE_CURRENT_SOURCE_DIR}/inputhandler.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/tile.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/joystick_controller.cpp
+       ${CMAKE_CURRENT_SOURCE_DIR}/hud.cpp
        PARENT_SCOPE
 )
diff --git a/src/client/hud.cpp b/src/client/hud.cpp
new file mode 100644 (file)
index 0000000..5137c2f
--- /dev/null
@@ -0,0 +1,775 @@
+/*
+Minetest
+Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+Copyright (C) 2010-2013 blue42u, Jonathon Anderson <anderjon@umail.iu.edu>
+Copyright (C) 2010-2013 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "client/hud.h"
+#include "settings.h"
+#include "util/numeric.h"
+#include "log.h"
+#include "client.h"
+#include "inventory.h"
+#include "shader.h"
+#include "client/tile.h"
+#include "localplayer.h"
+#include "camera.h"
+#include "porting.h"
+#include "fontengine.h"
+#include "guiscalingfilter.h"
+#include "mesh.h"
+#include "wieldmesh.h"
+#include "client/renderingengine.h"
+
+#ifdef HAVE_TOUCHSCREENGUI
+#include "gui/touchscreengui.h"
+#endif
+
+Hud::Hud(gui::IGUIEnvironment *guienv, Client *client, LocalPlayer *player,
+               Inventory *inventory)
+{
+       driver            = RenderingEngine::get_video_driver();
+       this->guienv      = guienv;
+       this->client      = client;
+       this->player      = player;
+       this->inventory   = inventory;
+
+       m_hud_scaling      = g_settings->getFloat("hud_scaling");
+       m_hotbar_imagesize = floor(HOTBAR_IMAGE_SIZE *
+               RenderingEngine::getDisplayDensity() + 0.5f);
+       m_hotbar_imagesize *= m_hud_scaling;
+       m_padding = m_hotbar_imagesize / 12;
+
+       for (auto &hbar_color : hbar_colors)
+               hbar_color = video::SColor(255, 255, 255, 255);
+
+       tsrc = client->getTextureSource();
+
+       v3f crosshair_color = g_settings->getV3F("crosshair_color");
+       u32 cross_r = rangelim(myround(crosshair_color.X), 0, 255);
+       u32 cross_g = rangelim(myround(crosshair_color.Y), 0, 255);
+       u32 cross_b = rangelim(myround(crosshair_color.Z), 0, 255);
+       u32 cross_a = rangelim(g_settings->getS32("crosshair_alpha"), 0, 255);
+       crosshair_argb = video::SColor(cross_a, cross_r, cross_g, cross_b);
+
+       v3f selectionbox_color = g_settings->getV3F("selectionbox_color");
+       u32 sbox_r = rangelim(myround(selectionbox_color.X), 0, 255);
+       u32 sbox_g = rangelim(myround(selectionbox_color.Y), 0, 255);
+       u32 sbox_b = rangelim(myround(selectionbox_color.Z), 0, 255);
+       selectionbox_argb = video::SColor(255, sbox_r, sbox_g, sbox_b);
+
+       use_crosshair_image = tsrc->isKnownSourceImage("crosshair.png");
+
+       m_selection_boxes.clear();
+       m_halo_boxes.clear();
+
+       std::string mode_setting = g_settings->get("node_highlighting");
+
+       if (mode_setting == "halo") {
+               m_mode = HIGHLIGHT_HALO;
+       } else if (mode_setting == "none") {
+               m_mode = HIGHLIGHT_NONE;
+       } else {
+               m_mode = HIGHLIGHT_BOX;
+       }
+
+       m_selection_material.Lighting = false;
+
+       if (g_settings->getBool("enable_shaders")) {
+               IShaderSource *shdrsrc = client->getShaderSource();
+               u16 shader_id = shdrsrc->getShader(
+                       m_mode == HIGHLIGHT_HALO ? "selection_shader" : "default_shader", 1, 1);
+               m_selection_material.MaterialType = shdrsrc->getShaderInfo(shader_id).material;
+       } else {
+               m_selection_material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
+       }
+
+       if (m_mode == HIGHLIGHT_BOX) {
+               m_selection_material.Thickness =
+                       rangelim(g_settings->getS16("selectionbox_width"), 1, 5);
+       } else if (m_mode == HIGHLIGHT_HALO) {
+               m_selection_material.setTexture(0, tsrc->getTextureForMesh("halo.png"));
+               m_selection_material.setFlag(video::EMF_BACK_FACE_CULLING, true);
+       } else {
+               m_selection_material.MaterialType = video::EMT_SOLID;
+       }
+}
+
+Hud::~Hud()
+{
+       if (m_selection_mesh)
+               m_selection_mesh->drop();
+}
+
+void Hud::drawItem(const ItemStack &item, const core::rect<s32>& rect,
+               bool selected)
+{
+       if (selected) {
+               /* draw hihlighting around selected item */
+               if (use_hotbar_selected_image) {
+                       core::rect<s32> imgrect2 = rect;
+                       imgrect2.UpperLeftCorner.X  -= (m_padding*2);
+                       imgrect2.UpperLeftCorner.Y  -= (m_padding*2);
+                       imgrect2.LowerRightCorner.X += (m_padding*2);
+                       imgrect2.LowerRightCorner.Y += (m_padding*2);
+                               video::ITexture *texture = tsrc->getTexture(hotbar_selected_image);
+                               core::dimension2di imgsize(texture->getOriginalSize());
+                       draw2DImageFilterScaled(driver, texture, imgrect2,
+                                       core::rect<s32>(core::position2d<s32>(0,0), imgsize),
+                                       NULL, hbar_colors, true);
+               } else {
+                       video::SColor c_outside(255,255,0,0);
+                       //video::SColor c_outside(255,0,0,0);
+                       //video::SColor c_inside(255,192,192,192);
+                       s32 x1 = rect.UpperLeftCorner.X;
+                       s32 y1 = rect.UpperLeftCorner.Y;
+                       s32 x2 = rect.LowerRightCorner.X;
+                       s32 y2 = rect.LowerRightCorner.Y;
+                       // Black base borders
+                       driver->draw2DRectangle(c_outside,
+                               core::rect<s32>(
+                               v2s32(x1 - m_padding, y1 - m_padding),
+                               v2s32(x2 + m_padding, y1)
+                               ), NULL);
+                       driver->draw2DRectangle(c_outside,
+                               core::rect<s32>(
+                               v2s32(x1 - m_padding, y2),
+                               v2s32(x2 + m_padding, y2 + m_padding)
+                               ), NULL);
+                       driver->draw2DRectangle(c_outside,
+                               core::rect<s32>(
+                               v2s32(x1 - m_padding, y1),
+                                       v2s32(x1, y2)
+                               ), NULL);
+                       driver->draw2DRectangle(c_outside,
+                               core::rect<s32>(
+                                       v2s32(x2, y1),
+                               v2s32(x2 + m_padding, y2)
+                               ), NULL);
+                       /*// Light inside borders
+                       driver->draw2DRectangle(c_inside,
+                               core::rect<s32>(
+                                       v2s32(x1 - padding/2, y1 - padding/2),
+                                       v2s32(x2 + padding/2, y1)
+                               ), NULL);
+                       driver->draw2DRectangle(c_inside,
+                               core::rect<s32>(
+                                       v2s32(x1 - padding/2, y2),
+                                       v2s32(x2 + padding/2, y2 + padding/2)
+                               ), NULL);
+                       driver->draw2DRectangle(c_inside,
+                               core::rect<s32>(
+                                       v2s32(x1 - padding/2, y1),
+                                       v2s32(x1, y2)
+                               ), NULL);
+                       driver->draw2DRectangle(c_inside,
+                               core::rect<s32>(
+                                       v2s32(x2, y1),
+                                       v2s32(x2 + padding/2, y2)
+                               ), NULL);
+                       */
+               }
+       }
+
+       video::SColor bgcolor2(128, 0, 0, 0);
+       if (!use_hotbar_image)
+               driver->draw2DRectangle(bgcolor2, rect, NULL);
+       drawItemStack(driver, g_fontengine->getFont(), item, rect, NULL,
+               client, selected ? IT_ROT_SELECTED : IT_ROT_NONE);
+}
+
+//NOTE: selectitem = 0 -> no selected; selectitem 1-based
+void Hud::drawItems(v2s32 upperleftpos, v2s32 screen_offset, s32 itemcount,
+               s32 inv_offset, InventoryList *mainlist, u16 selectitem, u16 direction)
+{
+#ifdef HAVE_TOUCHSCREENGUI
+       if (g_touchscreengui && inv_offset == 0)
+               g_touchscreengui->resetHud();
+#endif
+
+       s32 height  = m_hotbar_imagesize + m_padding * 2;
+       s32 width   = (itemcount - inv_offset) * (m_hotbar_imagesize + m_padding * 2);
+
+       if (direction == HUD_DIR_TOP_BOTTOM || direction == HUD_DIR_BOTTOM_TOP) {
+               s32 tmp = height;
+               height = width;
+               width = tmp;
+       }
+
+       // Position of upper left corner of bar
+       v2s32 pos = screen_offset;
+       pos.X *= m_hud_scaling * RenderingEngine::getDisplayDensity();
+       pos.Y *= m_hud_scaling * RenderingEngine::getDisplayDensity();
+       pos += upperleftpos;
+
+       // Store hotbar_image in member variable, used by drawItem()
+       if (hotbar_image != player->hotbar_image) {
+               hotbar_image = player->hotbar_image;
+               if (!hotbar_image.empty())
+                       use_hotbar_image = tsrc->isKnownSourceImage(hotbar_image);
+               else
+                       use_hotbar_image = false;
+       }
+
+       // Store hotbar_selected_image in member variable, used by drawItem()
+       if (hotbar_selected_image != player->hotbar_selected_image) {
+               hotbar_selected_image = player->hotbar_selected_image;
+               if (!hotbar_selected_image.empty())
+                       use_hotbar_selected_image = tsrc->isKnownSourceImage(hotbar_selected_image);
+               else
+                       use_hotbar_selected_image = false;
+       }
+
+       // draw customized item background
+       if (use_hotbar_image) {
+               core::rect<s32> imgrect2(-m_padding/2, -m_padding/2,
+                       width+m_padding/2, height+m_padding/2);
+               core::rect<s32> rect2 = imgrect2 + pos;
+               video::ITexture *texture = tsrc->getTexture(hotbar_image);
+               core::dimension2di imgsize(texture->getOriginalSize());
+               draw2DImageFilterScaled(driver, texture, rect2,
+                       core::rect<s32>(core::position2d<s32>(0,0), imgsize),
+                       NULL, hbar_colors, true);
+       }
+
+       // Draw items
+       core::rect<s32> imgrect(0, 0, m_hotbar_imagesize, m_hotbar_imagesize);
+       for (s32 i = inv_offset; i < itemcount && (size_t)i < mainlist->getSize(); i++) {
+               s32 fullimglen = m_hotbar_imagesize + m_padding * 2;
+
+               v2s32 steppos;
+               switch (direction) {
+               case HUD_DIR_RIGHT_LEFT:
+                       steppos = v2s32(-(m_padding + (i - inv_offset) * fullimglen), m_padding);
+                       break;
+               case HUD_DIR_TOP_BOTTOM:
+                       steppos = v2s32(m_padding, m_padding + (i - inv_offset) * fullimglen);
+                       break;
+               case HUD_DIR_BOTTOM_TOP:
+                       steppos = v2s32(m_padding, -(m_padding + (i - inv_offset) * fullimglen));
+                       break;
+               default:
+                       steppos = v2s32(m_padding + (i - inv_offset) * fullimglen, m_padding);
+                       break;
+               }
+
+               drawItem(mainlist->getItem(i), (imgrect + pos + steppos), (i + 1) == selectitem);
+
+#ifdef HAVE_TOUCHSCREENGUI
+               if (g_touchscreengui)
+                       g_touchscreengui->registerHudItem(i, (imgrect + pos + steppos));
+#endif
+       }
+}
+
+
+void Hud::drawLuaElements(const v3s16 &camera_offset)
+{
+       u32 text_height = g_fontengine->getTextHeight();
+       irr::gui::IGUIFont* font = g_fontengine->getFont();
+       for (size_t i = 0; i != player->maxHudId(); i++) {
+               HudElement *e = player->getHud(i);
+               if (!e)
+                       continue;
+
+               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) {
+                       case HUD_ELEM_IMAGE: {
+                               video::ITexture *texture = tsrc->getTexture(e->text);
+                               if (!texture)
+                                       continue;
+
+                               const video::SColor color(255, 255, 255, 255);
+                               const video::SColor colors[] = {color, color, color, color};
+                               core::dimension2di imgsize(texture->getOriginalSize());
+                               v2s32 dstsize(imgsize.Width * e->scale.X,
+                                             imgsize.Height * e->scale.Y);
+                               if (e->scale.X < 0)
+                                       dstsize.X = m_screensize.X * (e->scale.X * -0.01);
+                               if (e->scale.Y < 0)
+                                       dstsize.Y = m_screensize.Y * (e->scale.Y * -0.01);
+                               v2s32 offset((e->align.X - 1.0) * dstsize.X / 2,
+                                            (e->align.Y - 1.0) * dstsize.Y / 2);
+                               core::rect<s32> rect(0, 0, dstsize.X, dstsize.Y);
+                               rect += pos + offset + v2s32(e->offset.X, e->offset.Y);
+                               draw2DImageFilterScaled(driver, texture, rect,
+                                       core::rect<s32>(core::position2d<s32>(0,0), imgsize),
+                                       NULL, colors, true);
+                               break; }
+                       case HUD_ELEM_TEXT: {
+                               video::SColor color(255, (e->number >> 16) & 0xFF,
+                                                                                (e->number >> 8)  & 0xFF,
+                                                                                (e->number >> 0)  & 0xFF);
+                               core::rect<s32> size(0, 0, e->scale.X, text_height * e->scale.Y);
+                               std::wstring text = unescape_translate(utf8_to_wide(e->text));
+                               core::dimension2d<u32> textsize = font->getDimension(text.c_str());
+                               v2s32 offset((e->align.X - 1.0) * (textsize.Width / 2),
+                                            (e->align.Y - 1.0) * (textsize.Height / 2));
+                               v2s32 offs(e->offset.X, e->offset.Y);
+                               font->draw(text.c_str(), size + pos + offset + offs, color);
+                               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);
+                               break; }
+                       case HUD_ELEM_INVENTORY: {
+                               InventoryList *inv = inventory->getList(e->text);
+                               drawItems(pos, v2s32(e->offset.X, e->offset.Y), e->number, 0,
+                                       inv, e->item, e->dir);
+                               break; }
+                       case HUD_ELEM_WAYPOINT: {
+                               v3f p_pos = player->getPosition() / BS;
+                               v3f w_pos = e->world_pos * BS;
+                               float distance = floor(10 * p_pos.getDistanceFrom(e->world_pos)) / 10;
+                               scene::ICameraSceneNode* camera =
+                                       RenderingEngine::get_scene_manager()->getActiveCamera();
+                               w_pos -= intToFloat(camera_offset, BS);
+                               core::matrix4 trans = camera->getProjectionMatrix();
+                               trans *= camera->getViewMatrix();
+                               f32 transformed_pos[4] = { w_pos.X, w_pos.Y, w_pos.Z, 1.0f };
+                               trans.multiplyWith1x4Matrix(transformed_pos);
+                               if (transformed_pos[3] < 0)
+                                       break;
+                               f32 zDiv = transformed_pos[3] == 0.0f ? 1.0f :
+                                       core::reciprocal(transformed_pos[3]);
+                               pos.X = m_screensize.X * (0.5 * transformed_pos[0] * zDiv + 0.5);
+                               pos.Y = m_screensize.Y * (0.5 - transformed_pos[1] * zDiv * 0.5);
+                               video::SColor color(255, (e->number >> 16) & 0xFF,
+                                                                                (e->number >> 8)  & 0xFF,
+                                                                                (e->number >> 0)  & 0xFF);
+                               core::rect<s32> size(0, 0, 200, 2 * text_height);
+                               std::wstring text = unescape_translate(utf8_to_wide(e->name));
+                               font->draw(text.c_str(), size + pos, color);
+                               std::ostringstream os;
+                               os << distance << e->text;
+                               text = unescape_translate(utf8_to_wide(os.str()));
+                               pos.Y += text_height;
+                               font->draw(text.c_str(), size + pos, color);
+                               break; }
+                       default:
+                               infostream << "Hud::drawLuaElements: ignoring drawform " << e->type <<
+                                       " of hud element ID " << i << " due to unrecognized type" << std::endl;
+               }
+       }
+}
+
+
+void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture,
+               s32 count, v2s32 offset, v2s32 size)
+{
+       const video::SColor color(255, 255, 255, 255);
+       const video::SColor colors[] = {color, color, color, color};
+
+       video::ITexture *stat_texture = tsrc->getTexture(texture);
+       if (!stat_texture)
+               return;
+
+       core::dimension2di srcd(stat_texture->getOriginalSize());
+       core::dimension2di dstd;
+       if (size == v2s32()) {
+               dstd = srcd;
+       } else {
+               float size_factor = m_hud_scaling * RenderingEngine::getDisplayDensity();
+               dstd.Height = size.Y * size_factor;
+               dstd.Width  = size.X * size_factor;
+               offset.X *= size_factor;
+               offset.Y *= size_factor;
+       }
+
+       v2s32 p = pos;
+       if (corner & HUD_CORNER_LOWER)
+               p -= dstd.Height;
+
+       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:
+                       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);
+       }
+       steppos.X *= dstd.Width;
+       steppos.Y *= dstd.Height;
+
+       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);
+
+               dstrect += p;
+               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);
+       }
+}
+
+
+void Hud::drawHotbar(u16 playeritem) {
+
+       v2s32 centerlowerpos(m_displaycenter.X, m_screensize.Y);
+
+       InventoryList *mainlist = inventory->getList("main");
+       if (mainlist == NULL) {
+               //silently ignore this we may not be initialized completely
+               return;
+       }
+
+       s32 hotbar_itemcount = player->hud_hotbar_itemcount;
+       s32 width = hotbar_itemcount * (m_hotbar_imagesize + m_padding * 2);
+       v2s32 pos = centerlowerpos - v2s32(width / 2, m_hotbar_imagesize + m_padding * 3);
+
+       const v2u32 &window_size = RenderingEngine::get_instance()->getWindowSize();
+       if ( (float) width / (float) window_size.X <=
+                       g_settings->getFloat("hud_hotbar_max_width")) {
+               if (player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE) {
+                       drawItems(pos, v2s32(0, 0), hotbar_itemcount, 0, mainlist, playeritem + 1, 0);
+               }
+       } else {
+               pos.X += width/4;
+
+               v2s32 secondpos = pos;
+               pos = pos - v2s32(0, m_hotbar_imagesize + m_padding);
+
+               if (player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE) {
+                       drawItems(pos, v2s32(0, 0), hotbar_itemcount / 2, 0,
+                               mainlist, playeritem + 1, 0);
+                       drawItems(secondpos, v2s32(0, 0), hotbar_itemcount,
+                               hotbar_itemcount / 2, mainlist, playeritem + 1, 0);
+               }
+       }
+
+       //////////////////////////// compatibility code to be removed //////////////
+       // this is ugly as hell but there's no other way to keep compatibility to
+       // old servers
+       if ((player->hud_flags & HUD_FLAG_HEALTHBAR_VISIBLE)) {
+               drawStatbar(v2s32(floor(0.5 * (float)m_screensize.X + 0.5),
+                       floor(1 * (float) m_screensize.Y + 0.5)),
+                       HUD_CORNER_UPPER, 0, "heart.png",
+                       player->hp, v2s32((-10*24)-25,-(48+24+10)), v2s32(24,24));
+       }
+
+       if ((player->hud_flags & HUD_FLAG_BREATHBAR_VISIBLE) &&
+                       (player->getBreath() < 11)) {
+               drawStatbar(v2s32(floor(0.5 * (float)m_screensize.X + 0.5),
+                       floor(1 * (float) m_screensize.Y + 0.5)),
+                       HUD_CORNER_UPPER, 0, "bubble.png",
+                       player->getBreath(), v2s32(25,-(48+24+10)), v2s32(24,24));
+       }
+       ////////////////////////////////////////////////////////////////////////////
+}
+
+
+void Hud::drawCrosshair()
+{
+       if (use_crosshair_image) {
+               video::ITexture *crosshair = tsrc->getTexture("crosshair.png");
+               v2u32 size  = crosshair->getOriginalSize();
+               v2s32 lsize = v2s32(m_displaycenter.X - (size.X / 2),
+                               m_displaycenter.Y - (size.Y / 2));
+               driver->draw2DImage(crosshair, lsize,
+                               core::rect<s32>(0, 0, size.X, size.Y),
+                               0, crosshair_argb, true);
+       } else {
+               driver->draw2DLine(m_displaycenter - v2s32(10, 0),
+                               m_displaycenter + v2s32(10, 0), crosshair_argb);
+               driver->draw2DLine(m_displaycenter - v2s32(0, 10),
+                               m_displaycenter + v2s32(0, 10), crosshair_argb);
+       }
+}
+
+void Hud::setSelectionPos(const v3f &pos, const v3s16 &camera_offset)
+{
+       m_camera_offset = camera_offset;
+       m_selection_pos = pos;
+       m_selection_pos_with_offset = pos - intToFloat(camera_offset, BS);
+}
+
+void Hud::drawSelectionMesh()
+{
+       if (m_mode == HIGHLIGHT_BOX) {
+               // Draw 3D selection boxes
+               video::SMaterial oldmaterial = driver->getMaterial2D();
+               driver->setMaterial(m_selection_material);
+               for (std::vector<aabb3f>::const_iterator
+                               i = m_selection_boxes.begin();
+                               i != m_selection_boxes.end(); ++i) {
+                       aabb3f box = aabb3f(
+                               i->MinEdge + m_selection_pos_with_offset,
+                               i->MaxEdge + m_selection_pos_with_offset);
+
+                       u32 r = (selectionbox_argb.getRed() *
+                                       m_selection_mesh_color.getRed() / 255);
+                       u32 g = (selectionbox_argb.getGreen() *
+                                       m_selection_mesh_color.getGreen() / 255);
+                       u32 b = (selectionbox_argb.getBlue() *
+                                       m_selection_mesh_color.getBlue() / 255);
+                       driver->draw3DBox(box, video::SColor(255, r, g, b));
+               }
+               driver->setMaterial(oldmaterial);
+       } else if (m_mode == HIGHLIGHT_HALO && m_selection_mesh) {
+               // Draw selection mesh
+               video::SMaterial oldmaterial = driver->getMaterial2D();
+               driver->setMaterial(m_selection_material);
+               setMeshColor(m_selection_mesh, m_selection_mesh_color);
+               video::SColor face_color(0,
+                       MYMIN(255, m_selection_mesh_color.getRed() * 1.5),
+                       MYMIN(255, m_selection_mesh_color.getGreen() * 1.5),
+                       MYMIN(255, m_selection_mesh_color.getBlue() * 1.5));
+               setMeshColorByNormal(m_selection_mesh, m_selected_face_normal,
+                       face_color);
+               scene::IMesh* mesh = cloneMesh(m_selection_mesh);
+               translateMesh(mesh, m_selection_pos_with_offset);
+               u32 mc = m_selection_mesh->getMeshBufferCount();
+               for (u32 i = 0; i < mc; i++) {
+                       scene::IMeshBuffer *buf = mesh->getMeshBuffer(i);
+                       driver->drawMeshBuffer(buf);
+               }
+               mesh->drop();
+               driver->setMaterial(oldmaterial);
+       }
+}
+
+void Hud::updateSelectionMesh(const v3s16 &camera_offset)
+{
+       m_camera_offset = camera_offset;
+       if (m_mode != HIGHLIGHT_HALO)
+               return;
+
+       if (m_selection_mesh) {
+               m_selection_mesh->drop();
+               m_selection_mesh = NULL;
+       }
+
+       if (m_selection_boxes.empty()) {
+               // No pointed object
+               return;
+       }
+
+       // New pointed object, create new mesh.
+
+       // Texture UV coordinates for selection boxes
+       static f32 texture_uv[24] = {
+               0,0,1,1,
+               0,0,1,1,
+               0,0,1,1,
+               0,0,1,1,
+               0,0,1,1,
+               0,0,1,1
+       };
+
+       // Use single halo box instead of multiple overlapping boxes.
+       // Temporary solution - problem can be solved with multiple
+       // rendering targets, or some method to remove inner surfaces.
+       // Thats because of halo transparency.
+
+       aabb3f halo_box(100.0, 100.0, 100.0, -100.0, -100.0, -100.0);
+       m_halo_boxes.clear();
+
+       for (const auto &selection_box : m_selection_boxes) {
+               halo_box.addInternalBox(selection_box);
+       }
+
+       m_halo_boxes.push_back(halo_box);
+       m_selection_mesh = convertNodeboxesToMesh(
+               m_halo_boxes, texture_uv, 0.5);
+}
+
+void Hud::resizeHotbar() {
+       const v2u32 &window_size = RenderingEngine::get_instance()->getWindowSize();
+
+       if (m_screensize != window_size) {
+               m_hotbar_imagesize = floor(HOTBAR_IMAGE_SIZE *
+                       RenderingEngine::getDisplayDensity() + 0.5);
+               m_hotbar_imagesize *= m_hud_scaling;
+               m_padding = m_hotbar_imagesize / 12;
+               m_screensize = window_size;
+               m_displaycenter = v2s32(m_screensize.X/2,m_screensize.Y/2);
+       }
+}
+
+struct MeshTimeInfo {
+       u64 time;
+       scene::IMesh *mesh;
+};
+
+void drawItemStack(video::IVideoDriver *driver,
+               gui::IGUIFont *font,
+               const ItemStack &item,
+               const core::rect<s32> &rect,
+               const core::rect<s32> *clip,
+               Client *client,
+               ItemRotationKind rotation_kind)
+{
+       static MeshTimeInfo rotation_time_infos[IT_ROT_NONE];
+       static thread_local bool enable_animations =
+               g_settings->getBool("inventory_items_animations");
+
+       if (item.empty()) {
+               if (rotation_kind < IT_ROT_NONE) {
+                       rotation_time_infos[rotation_kind].mesh = NULL;
+               }
+               return;
+       }
+
+       const ItemDefinition &def = item.getDefinition(client->idef());
+       ItemMesh *imesh = client->idef()->getWieldMesh(def.name, client);
+
+       if (imesh && imesh->mesh) {
+               scene::IMesh *mesh = imesh->mesh;
+               driver->clearZBuffer();
+               s32 delta = 0;
+               if (rotation_kind < IT_ROT_NONE) {
+                       MeshTimeInfo &ti = rotation_time_infos[rotation_kind];
+                       if (mesh != ti.mesh) {
+                               ti.mesh = mesh;
+                               ti.time = porting::getTimeMs();
+                       } else {
+                               delta = porting::getDeltaMs(ti.time, porting::getTimeMs()) % 100000;
+                       }
+               }
+               core::rect<s32> oldViewPort = driver->getViewPort();
+               core::matrix4 oldProjMat = driver->getTransform(video::ETS_PROJECTION);
+               core::matrix4 oldViewMat = driver->getTransform(video::ETS_VIEW);
+               core::matrix4 ProjMatrix;
+               ProjMatrix.buildProjectionMatrixOrthoLH(2, 2, -1, 100);
+               driver->setTransform(video::ETS_PROJECTION, ProjMatrix);
+               driver->setTransform(video::ETS_VIEW, ProjMatrix);
+               core::matrix4 matrix;
+               matrix.makeIdentity();
+
+               if (enable_animations) {
+                       float timer_f = (float) delta / 5000.0;
+                       matrix.setRotationDegrees(core::vector3df(0, 360 * timer_f, 0));
+               }
+
+               driver->setTransform(video::ETS_WORLD, matrix);
+               driver->setViewPort(rect);
+
+               video::SColor basecolor =
+                       client->idef()->getItemstackColor(item, client);
+
+               u32 mc = mesh->getMeshBufferCount();
+               for (u32 j = 0; j < mc; ++j) {
+                       scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
+                       // we can modify vertices relatively fast,
+                       // because these meshes are not buffered.
+                       assert(buf->getHardwareMappingHint_Vertex() == scene::EHM_NEVER);
+                       video::SColor c = basecolor;
+                       if (imesh->buffer_colors.size() > j) {
+                               ItemPartColor *p = &imesh->buffer_colors[j];
+                               if (p->override_base)
+                                       c = p->color;
+                       }
+                       if (imesh->needs_shading)
+                               colorizeMeshBuffer(buf, &c);
+                       else
+                               setMeshBufferColor(buf, c);
+                       video::SMaterial &material = buf->getMaterial();
+                       material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
+                       material.Lighting = false;
+                       driver->setMaterial(material);
+                       driver->drawMeshBuffer(buf);
+               }
+
+               driver->setTransform(video::ETS_VIEW, oldViewMat);
+               driver->setTransform(video::ETS_PROJECTION, oldProjMat);
+               driver->setViewPort(oldViewPort);
+       }
+
+       if(def.type == ITEM_TOOL && item.wear != 0)
+       {
+               // Draw a progressbar
+               float barheight = rect.getHeight()/16;
+               float barpad_x = rect.getWidth()/16;
+               float barpad_y = rect.getHeight()/16;
+               core::rect<s32> progressrect(
+                       rect.UpperLeftCorner.X + barpad_x,
+                       rect.LowerRightCorner.Y - barpad_y - barheight,
+                       rect.LowerRightCorner.X - barpad_x,
+                       rect.LowerRightCorner.Y - barpad_y);
+
+               // Shrink progressrect by amount of tool damage
+               float wear = item.wear / 65535.0;
+               int progressmid =
+                       wear * progressrect.UpperLeftCorner.X +
+                       (1-wear) * progressrect.LowerRightCorner.X;
+
+               // Compute progressbar color
+               //   wear = 0.0: green
+               //   wear = 0.5: yellow
+               //   wear = 1.0: red
+               video::SColor color(255,255,255,255);
+               int wear_i = MYMIN(floor(wear * 600), 511);
+               wear_i = MYMIN(wear_i + 10, 511);
+               if(wear_i <= 255)
+                       color.set(255, wear_i, 255, 0);
+               else
+                       color.set(255, 255, 511-wear_i, 0);
+
+               core::rect<s32> progressrect2 = progressrect;
+               progressrect2.LowerRightCorner.X = progressmid;
+               driver->draw2DRectangle(color, progressrect2, clip);
+
+               color = video::SColor(255,0,0,0);
+               progressrect2 = progressrect;
+               progressrect2.UpperLeftCorner.X = progressmid;
+               driver->draw2DRectangle(color, progressrect2, clip);
+       }
+
+       if(font != NULL && item.count >= 2)
+       {
+               // Get the item count as a string
+               std::string text = itos(item.count);
+               v2u32 dim = font->getDimension(utf8_to_wide(text).c_str());
+               v2s32 sdim(dim.X,dim.Y);
+
+               core::rect<s32> rect2(
+                       /*rect.UpperLeftCorner,
+                       core::dimension2d<u32>(rect.getWidth(), 15)*/
+                       rect.LowerRightCorner - sdim,
+                       sdim
+               );
+
+               video::SColor bgcolor(128,0,0,0);
+               driver->draw2DRectangle(bgcolor, rect2, clip);
+
+               video::SColor color(255,255,255,255);
+               font->draw(text.c_str(), rect2, color, false, false, clip);
+       }
+}
diff --git a/src/client/hud.h b/src/client/hud.h
new file mode 100644 (file)
index 0000000..e9bcdf4
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+Minetest
+Copyright (C) 2010-2013 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
+Copyright (C) 2017 red-001 <red-001@outlook.ie>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef CLIENT_HUD_HEADER
+#define CLIENT_HUD_HEADER
+
+#include <vector>
+#include <IGUIFont.h>
+#include "irr_aabb3d.h"
+#include "../hud.h"
+
+class Client;
+class ITextureSource;
+class Inventory;
+class InventoryList;
+class LocalPlayer;
+struct ItemStack;
+
+class Hud
+{
+public:
+       video::IVideoDriver *driver;
+       scene::ISceneManager *smgr;
+       gui::IGUIEnvironment *guienv;
+       Client *client;
+       LocalPlayer *player;
+       Inventory *inventory;
+       ITextureSource *tsrc;
+
+       video::SColor crosshair_argb;
+       video::SColor selectionbox_argb;
+       bool use_crosshair_image = false;
+       std::string hotbar_image = "";
+       bool use_hotbar_image = false;
+       std::string hotbar_selected_image = "";
+       bool use_hotbar_selected_image = false;
+
+       Hud(gui::IGUIEnvironment *guienv, Client *client, LocalPlayer *player,
+                       Inventory *inventory);
+       ~Hud();
+
+       void drawHotbar(u16 playeritem);
+       void resizeHotbar();
+       void drawCrosshair();
+       void drawSelectionMesh();
+       void updateSelectionMesh(const v3s16 &camera_offset);
+
+       std::vector<aabb3f> *getSelectionBoxes() { return &m_selection_boxes; }
+
+       void setSelectionPos(const v3f &pos, const v3s16 &camera_offset);
+
+       v3f getSelectionPos() const { return m_selection_pos; }
+
+       void setSelectionMeshColor(const video::SColor &color)
+       {
+               m_selection_mesh_color = color;
+       }
+
+       void setSelectedFaceNormal(const v3f &face_normal)
+       {
+               m_selected_face_normal = face_normal;
+       }
+
+       void drawLuaElements(const v3s16 &camera_offset);
+
+private:
+       void drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture,
+                       s32 count, v2s32 offset, v2s32 size = v2s32());
+
+       void drawItems(v2s32 upperleftpos, v2s32 screen_offset, s32 itemcount,
+                       s32 inv_offset, InventoryList *mainlist, u16 selectitem,
+                       u16 direction);
+
+       void drawItem(const ItemStack &item, const core::rect<s32> &rect, bool selected);
+
+       float m_hud_scaling; // cached minetest setting
+       v3s16 m_camera_offset;
+       v2u32 m_screensize;
+       v2s32 m_displaycenter;
+       s32 m_hotbar_imagesize; // Takes hud_scaling into account, updated by resizeHotbar()
+       s32 m_padding; // Takes hud_scaling into account, updated by resizeHotbar()
+       video::SColor hbar_colors[4];
+
+       std::vector<aabb3f> m_selection_boxes;
+       std::vector<aabb3f> m_halo_boxes;
+       v3f m_selection_pos;
+       v3f m_selection_pos_with_offset;
+
+       scene::IMesh *m_selection_mesh = nullptr;
+       video::SColor m_selection_mesh_color;
+       v3f m_selected_face_normal;
+
+       video::SMaterial m_selection_material;
+
+       enum
+       {
+               HIGHLIGHT_BOX,
+               HIGHLIGHT_HALO,
+               HIGHLIGHT_NONE
+       } m_mode;
+};
+
+enum ItemRotationKind
+{
+       IT_ROT_SELECTED,
+       IT_ROT_HOVERED,
+       IT_ROT_DRAGGED,
+       IT_ROT_NONE, // Must be last, also serves as number
+};
+
+void drawItemStack(video::IVideoDriver *driver,
+               gui::IGUIFont *font,
+               const ItemStack &item,
+               const core::rect<s32> &rect,
+               const core::rect<s32> *clip,
+               Client *client,
+               ItemRotationKind rotation_kind);
+
+#endif
index d2c1717947c065ae9d0b913d0d0fd460f42b0a76..b63e49deacc9de9f393378b258f3a32f96e81754 100644 (file)
@@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 #include "sidebyside.h"
 #include <ICameraSceneNode.h>
-#include "hud.h"
+#include "client/hud.h"
 
 RenderingCoreSideBySide::RenderingCoreSideBySide(
        IrrlichtDevice *_device, Client *_client, Hud *_hud, bool _horizontal)
index 3c48c28a8cbe0e5a71ca1f6c298f7e7ab6ac35ee..94c9c5ef27befa97b93bcc8dadfdedce8f831997 100644 (file)
@@ -25,8 +25,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "clouds.h"
 #include "util/numeric.h"
 #include "guiscalingfilter.h"
-#include "hud.h"
 #include "localplayer.h"
+#include "client/hud.h"
 #include "camera.h"
 #include "minimap.h"
 #include "clientmap.h"
index 6ca4a2e16b0cef662dcd0f405270a499bfa18369..a59143f77132c42f83a508eed8c79384712b4449 100644 (file)
@@ -39,7 +39,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "client/renderingengine.h"
 #include "log.h"
 #include "client/tile.h" // ITextureSource
-#include "hud.h" // drawItemStack
+#include "client/hud.h" // drawItemStack
 #include "filesys.h"
 #include "gettime.h"
 #include "gettext.h"
index ecd2a521d9991de0eac5513bde9bd85b0ce68acc..0d2d092a7930f6d94213ce8b926d5ba2f24c0b59 100644 (file)
-/*
-Minetest
-Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
-Copyright (C) 2010-2013 blue42u, Jonathon Anderson <anderjon@umail.iu.edu>
-Copyright (C) 2010-2013 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU Lesser General Public License as published by
-the Free Software Foundation; either version 2.1 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public License along
-with this program; if not, write to the Free Software Foundation, Inc.,
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-
 #include "hud.h"
-#include "settings.h"
-#include "util/numeric.h"
-#include "log.h"
-#include "client.h"
-#include "inventory.h"
-#include "shader.h"
-#include "client/tile.h"
-#include "localplayer.h"
-#include "camera.h"
-#include "porting.h"
-#include "fontengine.h"
-#include "guiscalingfilter.h"
-#include "mesh.h"
-#include "wieldmesh.h"
-#include "client/renderingengine.h"
-
-#ifdef HAVE_TOUCHSCREENGUI
-#include "gui/touchscreengui.h"
-#endif
-
-Hud::Hud(gui::IGUIEnvironment *guienv, Client *client, LocalPlayer *player,
-               Inventory *inventory)
-{
-       driver            = RenderingEngine::get_video_driver();
-       this->guienv      = guienv;
-       this->client      = client;
-       this->player      = player;
-       this->inventory   = inventory;
-
-       m_hud_scaling      = g_settings->getFloat("hud_scaling");
-       m_hotbar_imagesize = floor(HOTBAR_IMAGE_SIZE *
-               RenderingEngine::getDisplayDensity() + 0.5f);
-       m_hotbar_imagesize *= m_hud_scaling;
-       m_padding = m_hotbar_imagesize / 12;
-
-       for (auto &hbar_color : hbar_colors)
-               hbar_color = video::SColor(255, 255, 255, 255);
-
-       tsrc = client->getTextureSource();
-
-       v3f crosshair_color = g_settings->getV3F("crosshair_color");
-       u32 cross_r = rangelim(myround(crosshair_color.X), 0, 255);
-       u32 cross_g = rangelim(myround(crosshair_color.Y), 0, 255);
-       u32 cross_b = rangelim(myround(crosshair_color.Z), 0, 255);
-       u32 cross_a = rangelim(g_settings->getS32("crosshair_alpha"), 0, 255);
-       crosshair_argb = video::SColor(cross_a, cross_r, cross_g, cross_b);
-
-       v3f selectionbox_color = g_settings->getV3F("selectionbox_color");
-       u32 sbox_r = rangelim(myround(selectionbox_color.X), 0, 255);
-       u32 sbox_g = rangelim(myround(selectionbox_color.Y), 0, 255);
-       u32 sbox_b = rangelim(myround(selectionbox_color.Z), 0, 255);
-       selectionbox_argb = video::SColor(255, sbox_r, sbox_g, sbox_b);
-
-       use_crosshair_image = tsrc->isKnownSourceImage("crosshair.png");
-
-       m_selection_boxes.clear();
-       m_halo_boxes.clear();
-
-       std::string mode_setting = g_settings->get("node_highlighting");
-
-       if (mode_setting == "halo") {
-               m_mode = HIGHLIGHT_HALO;
-       } else if (mode_setting == "none") {
-               m_mode = HIGHLIGHT_NONE;
-       } else {
-               m_mode = HIGHLIGHT_BOX;
-       }
-
-       m_selection_material.Lighting = false;
-
-       if (g_settings->getBool("enable_shaders")) {
-               IShaderSource *shdrsrc = client->getShaderSource();
-               u16 shader_id = shdrsrc->getShader(
-                       m_mode == HIGHLIGHT_HALO ? "selection_shader" : "default_shader", 1, 1);
-               m_selection_material.MaterialType = shdrsrc->getShaderInfo(shader_id).material;
-       } else {
-               m_selection_material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
-       }
-
-       if (m_mode == HIGHLIGHT_BOX) {
-               m_selection_material.Thickness =
-                       rangelim(g_settings->getS16("selectionbox_width"), 1, 5);
-       } else if (m_mode == HIGHLIGHT_HALO) {
-               m_selection_material.setTexture(0, tsrc->getTextureForMesh("halo.png"));
-               m_selection_material.setFlag(video::EMF_BACK_FACE_CULLING, true);
-       } else {
-               m_selection_material.MaterialType = video::EMT_SOLID;
-       }
-}
-
-Hud::~Hud()
-{
-       if (m_selection_mesh)
-               m_selection_mesh->drop();
-}
-
-void Hud::drawItem(const ItemStack &item, const core::rect<s32>& rect,
-               bool selected)
-{
-       if (selected) {
-               /* draw hihlighting around selected item */
-               if (use_hotbar_selected_image) {
-                       core::rect<s32> imgrect2 = rect;
-                       imgrect2.UpperLeftCorner.X  -= (m_padding*2);
-                       imgrect2.UpperLeftCorner.Y  -= (m_padding*2);
-                       imgrect2.LowerRightCorner.X += (m_padding*2);
-                       imgrect2.LowerRightCorner.Y += (m_padding*2);
-                               video::ITexture *texture = tsrc->getTexture(hotbar_selected_image);
-                               core::dimension2di imgsize(texture->getOriginalSize());
-                       draw2DImageFilterScaled(driver, texture, imgrect2,
-                                       core::rect<s32>(core::position2d<s32>(0,0), imgsize),
-                                       NULL, hbar_colors, true);
-               } else {
-                       video::SColor c_outside(255,255,0,0);
-                       //video::SColor c_outside(255,0,0,0);
-                       //video::SColor c_inside(255,192,192,192);
-                       s32 x1 = rect.UpperLeftCorner.X;
-                       s32 y1 = rect.UpperLeftCorner.Y;
-                       s32 x2 = rect.LowerRightCorner.X;
-                       s32 y2 = rect.LowerRightCorner.Y;
-                       // Black base borders
-                       driver->draw2DRectangle(c_outside,
-                               core::rect<s32>(
-                               v2s32(x1 - m_padding, y1 - m_padding),
-                               v2s32(x2 + m_padding, y1)
-                               ), NULL);
-                       driver->draw2DRectangle(c_outside,
-                               core::rect<s32>(
-                               v2s32(x1 - m_padding, y2),
-                               v2s32(x2 + m_padding, y2 + m_padding)
-                               ), NULL);
-                       driver->draw2DRectangle(c_outside,
-                               core::rect<s32>(
-                               v2s32(x1 - m_padding, y1),
-                                       v2s32(x1, y2)
-                               ), NULL);
-                       driver->draw2DRectangle(c_outside,
-                               core::rect<s32>(
-                                       v2s32(x2, y1),
-                               v2s32(x2 + m_padding, y2)
-                               ), NULL);
-                       /*// Light inside borders
-                       driver->draw2DRectangle(c_inside,
-                               core::rect<s32>(
-                                       v2s32(x1 - padding/2, y1 - padding/2),
-                                       v2s32(x2 + padding/2, y1)
-                               ), NULL);
-                       driver->draw2DRectangle(c_inside,
-                               core::rect<s32>(
-                                       v2s32(x1 - padding/2, y2),
-                                       v2s32(x2 + padding/2, y2 + padding/2)
-                               ), NULL);
-                       driver->draw2DRectangle(c_inside,
-                               core::rect<s32>(
-                                       v2s32(x1 - padding/2, y1),
-                                       v2s32(x1, y2)
-                               ), NULL);
-                       driver->draw2DRectangle(c_inside,
-                               core::rect<s32>(
-                                       v2s32(x2, y1),
-                                       v2s32(x2 + padding/2, y2)
-                               ), NULL);
-                       */
-               }
-       }
-
-       video::SColor bgcolor2(128, 0, 0, 0);
-       if (!use_hotbar_image)
-               driver->draw2DRectangle(bgcolor2, rect, NULL);
-       drawItemStack(driver, g_fontengine->getFont(), item, rect, NULL,
-               client, selected ? IT_ROT_SELECTED : IT_ROT_NONE);
-}
-
-//NOTE: selectitem = 0 -> no selected; selectitem 1-based
-void Hud::drawItems(v2s32 upperleftpos, v2s32 screen_offset, s32 itemcount,
-               s32 inv_offset, InventoryList *mainlist, u16 selectitem, u16 direction)
-{
-#ifdef HAVE_TOUCHSCREENGUI
-       if (g_touchscreengui && inv_offset == 0)
-               g_touchscreengui->resetHud();
-#endif
-
-       s32 height  = m_hotbar_imagesize + m_padding * 2;
-       s32 width   = (itemcount - inv_offset) * (m_hotbar_imagesize + m_padding * 2);
-
-       if (direction == HUD_DIR_TOP_BOTTOM || direction == HUD_DIR_BOTTOM_TOP) {
-               s32 tmp = height;
-               height = width;
-               width = tmp;
-       }
-
-       // Position of upper left corner of bar
-       v2s32 pos = screen_offset;
-       pos.X *= m_hud_scaling * RenderingEngine::getDisplayDensity();
-       pos.Y *= m_hud_scaling * RenderingEngine::getDisplayDensity();
-       pos += upperleftpos;
-
-       // Store hotbar_image in member variable, used by drawItem()
-       if (hotbar_image != player->hotbar_image) {
-               hotbar_image = player->hotbar_image;
-               if (!hotbar_image.empty())
-                       use_hotbar_image = tsrc->isKnownSourceImage(hotbar_image);
-               else
-                       use_hotbar_image = false;
-       }
-
-       // Store hotbar_selected_image in member variable, used by drawItem()
-       if (hotbar_selected_image != player->hotbar_selected_image) {
-               hotbar_selected_image = player->hotbar_selected_image;
-               if (!hotbar_selected_image.empty())
-                       use_hotbar_selected_image = tsrc->isKnownSourceImage(hotbar_selected_image);
-               else
-                       use_hotbar_selected_image = false;
-       }
-
-       // draw customized item background
-       if (use_hotbar_image) {
-               core::rect<s32> imgrect2(-m_padding/2, -m_padding/2,
-                       width+m_padding/2, height+m_padding/2);
-               core::rect<s32> rect2 = imgrect2 + pos;
-               video::ITexture *texture = tsrc->getTexture(hotbar_image);
-               core::dimension2di imgsize(texture->getOriginalSize());
-               draw2DImageFilterScaled(driver, texture, rect2,
-                       core::rect<s32>(core::position2d<s32>(0,0), imgsize),
-                       NULL, hbar_colors, true);
-       }
-
-       // Draw items
-       core::rect<s32> imgrect(0, 0, m_hotbar_imagesize, m_hotbar_imagesize);
-       for (s32 i = inv_offset; i < itemcount && (size_t)i < mainlist->getSize(); i++) {
-               s32 fullimglen = m_hotbar_imagesize + m_padding * 2;
-
-               v2s32 steppos;
-               switch (direction) {
-               case HUD_DIR_RIGHT_LEFT:
-                       steppos = v2s32(-(m_padding + (i - inv_offset) * fullimglen), m_padding);
-                       break;
-               case HUD_DIR_TOP_BOTTOM:
-                       steppos = v2s32(m_padding, m_padding + (i - inv_offset) * fullimglen);
-                       break;
-               case HUD_DIR_BOTTOM_TOP:
-                       steppos = v2s32(m_padding, -(m_padding + (i - inv_offset) * fullimglen));
-                       break;
-               default:
-                       steppos = v2s32(m_padding + (i - inv_offset) * fullimglen, m_padding);
-                       break;
-               }
-
-               drawItem(mainlist->getItem(i), (imgrect + pos + steppos), (i + 1) == selectitem);
-
-#ifdef HAVE_TOUCHSCREENGUI
-               if (g_touchscreengui)
-                       g_touchscreengui->registerHudItem(i, (imgrect + pos + steppos));
-#endif
-       }
-}
-
-
-void Hud::drawLuaElements(const v3s16 &camera_offset)
-{
-       u32 text_height = g_fontengine->getTextHeight();
-       irr::gui::IGUIFont* font = g_fontengine->getFont();
-       for (size_t i = 0; i != player->maxHudId(); i++) {
-               HudElement *e = player->getHud(i);
-               if (!e)
-                       continue;
-
-               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) {
-                       case HUD_ELEM_IMAGE: {
-                               video::ITexture *texture = tsrc->getTexture(e->text);
-                               if (!texture)
-                                       continue;
-
-                               const video::SColor color(255, 255, 255, 255);
-                               const video::SColor colors[] = {color, color, color, color};
-                               core::dimension2di imgsize(texture->getOriginalSize());
-                               v2s32 dstsize(imgsize.Width * e->scale.X,
-                                             imgsize.Height * e->scale.Y);
-                               if (e->scale.X < 0)
-                                       dstsize.X = m_screensize.X * (e->scale.X * -0.01);
-                               if (e->scale.Y < 0)
-                                       dstsize.Y = m_screensize.Y * (e->scale.Y * -0.01);
-                               v2s32 offset((e->align.X - 1.0) * dstsize.X / 2,
-                                            (e->align.Y - 1.0) * dstsize.Y / 2);
-                               core::rect<s32> rect(0, 0, dstsize.X, dstsize.Y);
-                               rect += pos + offset + v2s32(e->offset.X, e->offset.Y);
-                               draw2DImageFilterScaled(driver, texture, rect,
-                                       core::rect<s32>(core::position2d<s32>(0,0), imgsize),
-                                       NULL, colors, true);
-                               break; }
-                       case HUD_ELEM_TEXT: {
-                               video::SColor color(255, (e->number >> 16) & 0xFF,
-                                                                                (e->number >> 8)  & 0xFF,
-                                                                                (e->number >> 0)  & 0xFF);
-                               core::rect<s32> size(0, 0, e->scale.X, text_height * e->scale.Y);
-                               std::wstring text = unescape_translate(utf8_to_wide(e->text));
-                               core::dimension2d<u32> textsize = font->getDimension(text.c_str());
-                               v2s32 offset((e->align.X - 1.0) * (textsize.Width / 2),
-                                            (e->align.Y - 1.0) * (textsize.Height / 2));
-                               v2s32 offs(e->offset.X, e->offset.Y);
-                               font->draw(text.c_str(), size + pos + offset + offs, color);
-                               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);
-                               break; }
-                       case HUD_ELEM_INVENTORY: {
-                               InventoryList *inv = inventory->getList(e->text);
-                               drawItems(pos, v2s32(e->offset.X, e->offset.Y), e->number, 0,
-                                       inv, e->item, e->dir);
-                               break; }
-                       case HUD_ELEM_WAYPOINT: {
-                               v3f p_pos = player->getPosition() / BS;
-                               v3f w_pos = e->world_pos * BS;
-                               float distance = floor(10 * p_pos.getDistanceFrom(e->world_pos)) / 10;
-                               scene::ICameraSceneNode* camera =
-                                       RenderingEngine::get_scene_manager()->getActiveCamera();
-                               w_pos -= intToFloat(camera_offset, BS);
-                               core::matrix4 trans = camera->getProjectionMatrix();
-                               trans *= camera->getViewMatrix();
-                               f32 transformed_pos[4] = { w_pos.X, w_pos.Y, w_pos.Z, 1.0f };
-                               trans.multiplyWith1x4Matrix(transformed_pos);
-                               if (transformed_pos[3] < 0)
-                                       break;
-                               f32 zDiv = transformed_pos[3] == 0.0f ? 1.0f :
-                                       core::reciprocal(transformed_pos[3]);
-                               pos.X = m_screensize.X * (0.5 * transformed_pos[0] * zDiv + 0.5);
-                               pos.Y = m_screensize.Y * (0.5 - transformed_pos[1] * zDiv * 0.5);
-                               video::SColor color(255, (e->number >> 16) & 0xFF,
-                                                                                (e->number >> 8)  & 0xFF,
-                                                                                (e->number >> 0)  & 0xFF);
-                               core::rect<s32> size(0, 0, 200, 2 * text_height);
-                               std::wstring text = unescape_translate(utf8_to_wide(e->name));
-                               font->draw(text.c_str(), size + pos, color);
-                               std::ostringstream os;
-                               os << distance << e->text;
-                               text = unescape_translate(utf8_to_wide(os.str()));
-                               pos.Y += text_height;
-                               font->draw(text.c_str(), size + pos, color);
-                               break; }
-                       default:
-                               infostream << "Hud::drawLuaElements: ignoring drawform " << e->type <<
-                                       " of hud element ID " << i << " due to unrecognized type" << std::endl;
-               }
-       }
-}
-
-
-void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture,
-               s32 count, v2s32 offset, v2s32 size)
-{
-       const video::SColor color(255, 255, 255, 255);
-       const video::SColor colors[] = {color, color, color, color};
-
-       video::ITexture *stat_texture = tsrc->getTexture(texture);
-       if (!stat_texture)
-               return;
-
-       core::dimension2di srcd(stat_texture->getOriginalSize());
-       core::dimension2di dstd;
-       if (size == v2s32()) {
-               dstd = srcd;
-       } else {
-               float size_factor = m_hud_scaling * RenderingEngine::getDisplayDensity();
-               dstd.Height = size.Y * size_factor;
-               dstd.Width  = size.X * size_factor;
-               offset.X *= size_factor;
-               offset.Y *= size_factor;
-       }
-
-       v2s32 p = pos;
-       if (corner & HUD_CORNER_LOWER)
-               p -= dstd.Height;
-
-       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:
-                       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);
-       }
-       steppos.X *= dstd.Width;
-       steppos.Y *= dstd.Height;
 
-       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);
 
-               dstrect += p;
-               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);
-       }
-}
-
-
-void Hud::drawHotbar(u16 playeritem) {
-
-       v2s32 centerlowerpos(m_displaycenter.X, m_screensize.Y);
-
-       InventoryList *mainlist = inventory->getList("main");
-       if (mainlist == NULL) {
-               //silently ignore this we may not be initialized completely
-               return;
-       }
-
-       s32 hotbar_itemcount = player->hud_hotbar_itemcount;
-       s32 width = hotbar_itemcount * (m_hotbar_imagesize + m_padding * 2);
-       v2s32 pos = centerlowerpos - v2s32(width / 2, m_hotbar_imagesize + m_padding * 3);
-
-       const v2u32 &window_size = RenderingEngine::get_instance()->getWindowSize();
-       if ( (float) width / (float) window_size.X <=
-                       g_settings->getFloat("hud_hotbar_max_width")) {
-               if (player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE) {
-                       drawItems(pos, v2s32(0, 0), hotbar_itemcount, 0, mainlist, playeritem + 1, 0);
-               }
-       } else {
-               pos.X += width/4;
-
-               v2s32 secondpos = pos;
-               pos = pos - v2s32(0, m_hotbar_imagesize + m_padding);
-
-               if (player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE) {
-                       drawItems(pos, v2s32(0, 0), hotbar_itemcount / 2, 0,
-                               mainlist, playeritem + 1, 0);
-                       drawItems(secondpos, v2s32(0, 0), hotbar_itemcount,
-                               hotbar_itemcount / 2, mainlist, playeritem + 1, 0);
-               }
-       }
-
-       //////////////////////////// compatibility code to be removed //////////////
-       // this is ugly as hell but there's no other way to keep compatibility to
-       // old servers
-       if ((player->hud_flags & HUD_FLAG_HEALTHBAR_VISIBLE)) {
-               drawStatbar(v2s32(floor(0.5 * (float)m_screensize.X + 0.5),
-                       floor(1 * (float) m_screensize.Y + 0.5)),
-                       HUD_CORNER_UPPER, 0, "heart.png",
-                       player->hp, v2s32((-10*24)-25,-(48+24+10)), v2s32(24,24));
-       }
-
-       if ((player->hud_flags & HUD_FLAG_BREATHBAR_VISIBLE) &&
-                       (player->getBreath() < 11)) {
-               drawStatbar(v2s32(floor(0.5 * (float)m_screensize.X + 0.5),
-                       floor(1 * (float) m_screensize.Y + 0.5)),
-                       HUD_CORNER_UPPER, 0, "bubble.png",
-                       player->getBreath(), v2s32(25,-(48+24+10)), v2s32(24,24));
-       }
-       ////////////////////////////////////////////////////////////////////////////
-}
-
-
-void Hud::drawCrosshair()
+const struct EnumString es_HudElementType[] =
 {
-       if (use_crosshair_image) {
-               video::ITexture *crosshair = tsrc->getTexture("crosshair.png");
-               v2u32 size  = crosshair->getOriginalSize();
-               v2s32 lsize = v2s32(m_displaycenter.X - (size.X / 2),
-                               m_displaycenter.Y - (size.Y / 2));
-               driver->draw2DImage(crosshair, lsize,
-                               core::rect<s32>(0, 0, size.X, size.Y),
-                               0, crosshair_argb, true);
-       } else {
-               driver->draw2DLine(m_displaycenter - v2s32(10, 0),
-                               m_displaycenter + v2s32(10, 0), crosshair_argb);
-               driver->draw2DLine(m_displaycenter - v2s32(0, 10),
-                               m_displaycenter + v2s32(0, 10), crosshair_argb);
-       }
-}
-
-void Hud::setSelectionPos(const v3f &pos, const v3s16 &camera_offset)
-{
-       m_camera_offset = camera_offset;
-       m_selection_pos = pos;
-       m_selection_pos_with_offset = pos - intToFloat(camera_offset, BS);
-}
-
-void Hud::drawSelectionMesh()
-{
-       if (m_mode == HIGHLIGHT_BOX) {
-               // Draw 3D selection boxes
-               video::SMaterial oldmaterial = driver->getMaterial2D();
-               driver->setMaterial(m_selection_material);
-               for (std::vector<aabb3f>::const_iterator
-                               i = m_selection_boxes.begin();
-                               i != m_selection_boxes.end(); ++i) {
-                       aabb3f box = aabb3f(
-                               i->MinEdge + m_selection_pos_with_offset,
-                               i->MaxEdge + m_selection_pos_with_offset);
-
-                       u32 r = (selectionbox_argb.getRed() *
-                                       m_selection_mesh_color.getRed() / 255);
-                       u32 g = (selectionbox_argb.getGreen() *
-                                       m_selection_mesh_color.getGreen() / 255);
-                       u32 b = (selectionbox_argb.getBlue() *
-                                       m_selection_mesh_color.getBlue() / 255);
-                       driver->draw3DBox(box, video::SColor(255, r, g, b));
-               }
-               driver->setMaterial(oldmaterial);
-       } else if (m_mode == HIGHLIGHT_HALO && m_selection_mesh) {
-               // Draw selection mesh
-               video::SMaterial oldmaterial = driver->getMaterial2D();
-               driver->setMaterial(m_selection_material);
-               setMeshColor(m_selection_mesh, m_selection_mesh_color);
-               video::SColor face_color(0,
-                       MYMIN(255, m_selection_mesh_color.getRed() * 1.5),
-                       MYMIN(255, m_selection_mesh_color.getGreen() * 1.5),
-                       MYMIN(255, m_selection_mesh_color.getBlue() * 1.5));
-               setMeshColorByNormal(m_selection_mesh, m_selected_face_normal,
-                       face_color);
-               scene::IMesh* mesh = cloneMesh(m_selection_mesh);
-               translateMesh(mesh, m_selection_pos_with_offset);
-               u32 mc = m_selection_mesh->getMeshBufferCount();
-               for (u32 i = 0; i < mc; i++) {
-                       scene::IMeshBuffer *buf = mesh->getMeshBuffer(i);
-                       driver->drawMeshBuffer(buf);
-               }
-               mesh->drop();
-               driver->setMaterial(oldmaterial);
-       }
-}
-
-void Hud::updateSelectionMesh(const v3s16 &camera_offset)
-{
-       m_camera_offset = camera_offset;
-       if (m_mode != HIGHLIGHT_HALO)
-               return;
-
-       if (m_selection_mesh) {
-               m_selection_mesh->drop();
-               m_selection_mesh = NULL;
-       }
-
-       if (m_selection_boxes.empty()) {
-               // No pointed object
-               return;
-       }
-
-       // New pointed object, create new mesh.
-
-       // Texture UV coordinates for selection boxes
-       static f32 texture_uv[24] = {
-               0,0,1,1,
-               0,0,1,1,
-               0,0,1,1,
-               0,0,1,1,
-               0,0,1,1,
-               0,0,1,1
-       };
-
-       // Use single halo box instead of multiple overlapping boxes.
-       // Temporary solution - problem can be solved with multiple
-       // rendering targets, or some method to remove inner surfaces.
-       // Thats because of halo transparency.
-
-       aabb3f halo_box(100.0, 100.0, 100.0, -100.0, -100.0, -100.0);
-       m_halo_boxes.clear();
-
-       for (const auto &selection_box : m_selection_boxes) {
-               halo_box.addInternalBox(selection_box);
-       }
-
-       m_halo_boxes.push_back(halo_box);
-       m_selection_mesh = convertNodeboxesToMesh(
-               m_halo_boxes, texture_uv, 0.5);
-}
-
-void Hud::resizeHotbar() {
-       const v2u32 &window_size = RenderingEngine::get_instance()->getWindowSize();
-
-       if (m_screensize != window_size) {
-               m_hotbar_imagesize = floor(HOTBAR_IMAGE_SIZE *
-                       RenderingEngine::getDisplayDensity() + 0.5);
-               m_hotbar_imagesize *= m_hud_scaling;
-               m_padding = m_hotbar_imagesize / 12;
-               m_screensize = window_size;
-               m_displaycenter = v2s32(m_screensize.X/2,m_screensize.Y/2);
-       }
-}
+       {HUD_ELEM_IMAGE,     "image"},
+       {HUD_ELEM_TEXT,      "text"},
+       {HUD_ELEM_STATBAR,   "statbar"},
+       {HUD_ELEM_INVENTORY, "inventory"},
+       {HUD_ELEM_WAYPOINT,  "waypoint"},
+       {0, NULL},
+};
 
-struct MeshTimeInfo {
-       u64 time;
-       scene::IMesh *mesh;
+const struct EnumString es_HudElementStat[] =
+{
+       {HUD_STAT_POS,    "position"},
+       {HUD_STAT_POS,    "pos"}, /* Deprecated, only for compatibility's sake */
+       {HUD_STAT_NAME,   "name"},
+       {HUD_STAT_SCALE,  "scale"},
+       {HUD_STAT_TEXT,   "text"},
+       {HUD_STAT_NUMBER, "number"},
+       {HUD_STAT_ITEM,   "item"},
+       {HUD_STAT_DIR,    "direction"},
+       {HUD_STAT_ALIGN,  "alignment"},
+       {HUD_STAT_OFFSET, "offset"},
+       {HUD_STAT_WORLD_POS, "world_pos"},
+       {0, NULL},
 };
 
-void drawItemStack(video::IVideoDriver *driver,
-               gui::IGUIFont *font,
-               const ItemStack &item,
-               const core::rect<s32> &rect,
-               const core::rect<s32> *clip,
-               Client *client,
-               ItemRotationKind rotation_kind)
+const struct EnumString es_HudBuiltinElement[] =
 {
-       static MeshTimeInfo rotation_time_infos[IT_ROT_NONE];
-       static thread_local bool enable_animations =
-               g_settings->getBool("inventory_items_animations");
-
-       if (item.empty()) {
-               if (rotation_kind < IT_ROT_NONE) {
-                       rotation_time_infos[rotation_kind].mesh = NULL;
-               }
-               return;
-       }
-
-       const ItemDefinition &def = item.getDefinition(client->idef());
-       ItemMesh *imesh = client->idef()->getWieldMesh(def.name, client);
-
-       if (imesh && imesh->mesh) {
-               scene::IMesh *mesh = imesh->mesh;
-               driver->clearZBuffer();
-               s32 delta = 0;
-               if (rotation_kind < IT_ROT_NONE) {
-                       MeshTimeInfo &ti = rotation_time_infos[rotation_kind];
-                       if (mesh != ti.mesh) {
-                               ti.mesh = mesh;
-                               ti.time = porting::getTimeMs();
-                       } else {
-                               delta = porting::getDeltaMs(ti.time, porting::getTimeMs()) % 100000;
-                       }
-               }
-               core::rect<s32> oldViewPort = driver->getViewPort();
-               core::matrix4 oldProjMat = driver->getTransform(video::ETS_PROJECTION);
-               core::matrix4 oldViewMat = driver->getTransform(video::ETS_VIEW);
-               core::matrix4 ProjMatrix;
-               ProjMatrix.buildProjectionMatrixOrthoLH(2, 2, -1, 100);
-               driver->setTransform(video::ETS_PROJECTION, ProjMatrix);
-               driver->setTransform(video::ETS_VIEW, ProjMatrix);
-               core::matrix4 matrix;
-               matrix.makeIdentity();
-
-               if (enable_animations) {
-                       float timer_f = (float) delta / 5000.0;
-                       matrix.setRotationDegrees(core::vector3df(0, 360 * timer_f, 0));
-               }
-
-               driver->setTransform(video::ETS_WORLD, matrix);
-               driver->setViewPort(rect);
-
-               video::SColor basecolor =
-                       client->idef()->getItemstackColor(item, client);
-
-               u32 mc = mesh->getMeshBufferCount();
-               for (u32 j = 0; j < mc; ++j) {
-                       scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
-                       // we can modify vertices relatively fast,
-                       // because these meshes are not buffered.
-                       assert(buf->getHardwareMappingHint_Vertex() == scene::EHM_NEVER);
-                       video::SColor c = basecolor;
-                       if (imesh->buffer_colors.size() > j) {
-                               ItemPartColor *p = &imesh->buffer_colors[j];
-                               if (p->override_base)
-                                       c = p->color;
-                       }
-                       if (imesh->needs_shading)
-                               colorizeMeshBuffer(buf, &c);
-                       else
-                               setMeshBufferColor(buf, c);
-                       video::SMaterial &material = buf->getMaterial();
-                       material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
-                       material.Lighting = false;
-                       driver->setMaterial(material);
-                       driver->drawMeshBuffer(buf);
-               }
-
-               driver->setTransform(video::ETS_VIEW, oldViewMat);
-               driver->setTransform(video::ETS_PROJECTION, oldProjMat);
-               driver->setViewPort(oldViewPort);
-       }
-
-       if(def.type == ITEM_TOOL && item.wear != 0)
-       {
-               // Draw a progressbar
-               float barheight = rect.getHeight()/16;
-               float barpad_x = rect.getWidth()/16;
-               float barpad_y = rect.getHeight()/16;
-               core::rect<s32> progressrect(
-                       rect.UpperLeftCorner.X + barpad_x,
-                       rect.LowerRightCorner.Y - barpad_y - barheight,
-                       rect.LowerRightCorner.X - barpad_x,
-                       rect.LowerRightCorner.Y - barpad_y);
-
-               // Shrink progressrect by amount of tool damage
-               float wear = item.wear / 65535.0;
-               int progressmid =
-                       wear * progressrect.UpperLeftCorner.X +
-                       (1-wear) * progressrect.LowerRightCorner.X;
-
-               // Compute progressbar color
-               //   wear = 0.0: green
-               //   wear = 0.5: yellow
-               //   wear = 1.0: red
-               video::SColor color(255,255,255,255);
-               int wear_i = MYMIN(floor(wear * 600), 511);
-               wear_i = MYMIN(wear_i + 10, 511);
-               if(wear_i <= 255)
-                       color.set(255, wear_i, 255, 0);
-               else
-                       color.set(255, 255, 511-wear_i, 0);
-
-               core::rect<s32> progressrect2 = progressrect;
-               progressrect2.LowerRightCorner.X = progressmid;
-               driver->draw2DRectangle(color, progressrect2, clip);
-
-               color = video::SColor(255,0,0,0);
-               progressrect2 = progressrect;
-               progressrect2.UpperLeftCorner.X = progressmid;
-               driver->draw2DRectangle(color, progressrect2, clip);
-       }
-
-       if(font != NULL && item.count >= 2)
-       {
-               // Get the item count as a string
-               std::string text = itos(item.count);
-               v2u32 dim = font->getDimension(utf8_to_wide(text).c_str());
-               v2s32 sdim(dim.X,dim.Y);
-
-               core::rect<s32> rect2(
-                       /*rect.UpperLeftCorner,
-                       core::dimension2d<u32>(rect.getWidth(), 15)*/
-                       rect.LowerRightCorner - sdim,
-                       sdim
-               );
-
-               video::SColor bgcolor(128,0,0,0);
-               driver->draw2DRectangle(bgcolor, rect2, clip);
-
-               video::SColor color(255,255,255,255);
-               font->draw(text.c_str(), rect2, color, false, false, clip);
-       }
-}
+       {HUD_FLAG_HOTBAR_VISIBLE,    "hotbar"},
+       {HUD_FLAG_HEALTHBAR_VISIBLE, "healthbar"},
+       {HUD_FLAG_CROSSHAIR_VISIBLE, "crosshair"},
+       {HUD_FLAG_WIELDITEM_VISIBLE, "wielditem"},
+       {HUD_FLAG_BREATHBAR_VISIBLE, "breathbar"},
+       {HUD_FLAG_MINIMAP_VISIBLE,   "minimap"},
+       {0, NULL},
+};
index 3084478b1f8e8b8ef414a902a0444eded78e1b7d..699313980ee8ab337f76689d314717d9b553c55a 100644 (file)
--- a/src/hud.h
+++ b/src/hud.h
@@ -1,6 +1,7 @@
 /*
 Minetest
 Copyright (C) 2010-2013 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
+Copyright (C) 2017 red-001 <red-001@outlook.ie>
 
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU Lesser General Public License as published by
@@ -17,10 +18,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
 
-#pragma once
+#ifndef HUD_HEADER
+#define HUD_HEADER
 
 #include "irrlichttypes_extrabloated.h"
 #include <string>
+#include "common/c_types.h"
 
 #define HUD_DIR_LEFT_RIGHT 0
 #define HUD_DIR_RIGHT_LEFT 1
@@ -89,111 +92,8 @@ struct HudElement {
        v2s32 size;
 };
 
-#ifndef SERVER
-
-#include <vector>
-#include <IGUIFont.h>
-#include "irr_aabb3d.h"
-
-class Client;
-class ITextureSource;
-class Inventory;
-class InventoryList;
-class LocalPlayer;
-struct ItemStack;
-
-class Hud {
-public:
-       video::IVideoDriver *driver;
-       scene::ISceneManager* smgr;
-       gui::IGUIEnvironment *guienv;
-       Client *client;
-       LocalPlayer *player;
-       Inventory *inventory;
-       ITextureSource *tsrc;
-
-       video::SColor crosshair_argb;
-       video::SColor selectionbox_argb;
-       bool use_crosshair_image = false;
-       std::string hotbar_image = "";
-       bool use_hotbar_image = false;
-       std::string hotbar_selected_image = "";
-       bool use_hotbar_selected_image = false;
-
-       Hud(gui::IGUIEnvironment *guienv, Client *client, LocalPlayer *player,
-               Inventory *inventory);
-       ~Hud();
-
-       void drawHotbar(u16 playeritem);
-       void resizeHotbar();
-       void drawCrosshair();
-       void drawSelectionMesh();
-       void updateSelectionMesh(const v3s16 &camera_offset);
-
-       std::vector<aabb3f> *getSelectionBoxes()
-       { return &m_selection_boxes; }
-
-       void setSelectionPos(const v3f &pos, const v3s16 &camera_offset);
-
-       v3f getSelectionPos() const
-       { return m_selection_pos; }
-
-       void setSelectionMeshColor(const video::SColor &color)
-       { m_selection_mesh_color = color; }
-
-       void setSelectedFaceNormal(const v3f &face_normal)
-       { m_selected_face_normal = face_normal; }
-
-       void drawLuaElements(const v3s16 &camera_offset);
-
-private:
-       void drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture,
-                       s32 count, v2s32 offset, v2s32 size=v2s32());
-
-       void drawItems(v2s32 upperleftpos, v2s32 screen_offset, s32 itemcount,
-               s32 inv_offset, InventoryList *mainlist, u16 selectitem, u16 direction);
-
-       void drawItem(const ItemStack &item, const core::rect<s32>& rect,
-               bool selected);
-
-       float m_hud_scaling; // cached minetest setting
-       v3s16 m_camera_offset;
-       v2u32 m_screensize;
-       v2s32 m_displaycenter;
-       s32 m_hotbar_imagesize; // Takes hud_scaling into account, updated by resizeHotbar()
-       s32 m_padding;  // Takes hud_scaling into account, updated by resizeHotbar()
-       video::SColor hbar_colors[4];
-
-       std::vector<aabb3f> m_selection_boxes;
-       std::vector<aabb3f> m_halo_boxes;
-       v3f m_selection_pos;
-       v3f m_selection_pos_with_offset;
-
-       scene::IMesh *m_selection_mesh = nullptr;
-       video::SColor m_selection_mesh_color;
-       v3f m_selected_face_normal;
-
-       video::SMaterial m_selection_material;
-
-       enum {
-               HIGHLIGHT_BOX,
-               HIGHLIGHT_HALO,
-               HIGHLIGHT_NONE } m_mode;
-};
-
-enum ItemRotationKind {
-       IT_ROT_SELECTED,
-       IT_ROT_HOVERED,
-       IT_ROT_DRAGGED,
-       IT_ROT_NONE, // Must be last, also serves as number
-};
-
-void drawItemStack(video::IVideoDriver *driver,
-               gui::IGUIFont *font,
-               const ItemStack &item,
-               const core::rect<s32> &rect,
-               const core::rect<s32> *clip,
-               Client *client,
-               ItemRotationKind rotation_kind);
+extern const EnumString es_HudElementType[];
+extern const EnumString es_HudElementStat[];
+extern const EnumString es_HudBuiltinElement[];
 
 #endif
index 14aa7b6e6418539c7cb78952ef4819cf453d6a50..bd0cd6a082ee56f7ab96b042a0721750bf93c845 100644 (file)
@@ -1028,7 +1028,7 @@ void Client::handleCommand_HudAdd(NetworkPacket* pkt)
        std::string datastring(pkt->getString(0), pkt->getSize());
        std::istringstream is(datastring, std::ios_base::binary);
 
-       u32 id;
+       u32 server_id;
        u8 type;
        v2f pos;
        std::string name;
@@ -1042,7 +1042,7 @@ void Client::handleCommand_HudAdd(NetworkPacket* pkt)
        v3f world_pos;
        v2s32 size;
 
-       *pkt >> id >> type >> pos >> name >> scale >> text >> number >> item
+       *pkt >> server_id >> type >> pos >> name >> scale >> text >> number >> item
                >> dir >> align >> offset;
        try {
                *pkt >> world_pos;
@@ -1052,10 +1052,12 @@ void Client::handleCommand_HudAdd(NetworkPacket* pkt)
        try {
                *pkt >> size;
        } catch(SerializationError &e) {};
+       u32 client_id = getEnv().getLocalPlayer()->getFreeHudID();
+       m_hud_server_to_client[server_id] = client_id;
 
        ClientEvent *event = new ClientEvent();
        event->type             = CE_HUDADD;
-       event->hudadd.id        = id;
+       event->hudadd.id        = client_id;
        event->hudadd.type      = type;
        event->hudadd.pos       = new v2f(pos);
        event->hudadd.name      = new std::string(name);
@@ -1073,14 +1075,20 @@ void Client::handleCommand_HudAdd(NetworkPacket* pkt)
 
 void Client::handleCommand_HudRemove(NetworkPacket* pkt)
 {
-       u32 id;
+       u32 server_id;
 
-       *pkt >> id;
+       *pkt >> server_id;
 
-       ClientEvent *event = new ClientEvent();
-       event->type     = CE_HUDRM;
-       event->hudrm.id = id;
-       m_client_event_queue.push(event);
+       std::unordered_map<u32, u32>::const_iterator i = m_hud_server_to_client.find(server_id);
+       if (i != m_hud_server_to_client.end()) {
+               int client_id = i->second;
+               m_hud_server_to_client.erase(i);
+
+               ClientEvent *event = new ClientEvent();
+               event->type     = CE_HUDRM;
+               event->hudrm.id = client_id;
+               m_client_event_queue.push(event);
+       }
 }
 
 void Client::handleCommand_HudChange(NetworkPacket* pkt)
@@ -1090,10 +1098,10 @@ void Client::handleCommand_HudChange(NetworkPacket* pkt)
        v3f v3fdata;
        u32 intdata = 0;
        v2s32 v2s32data;
-       u32 id;
+       u32 server_id;
        u8 stat;
 
-       *pkt >> id >> stat;
+       *pkt >> server_id >> stat;
 
        if (stat == HUD_STAT_POS || stat == HUD_STAT_SCALE ||
                stat == HUD_STAT_ALIGN || stat == HUD_STAT_OFFSET)
@@ -1107,16 +1115,19 @@ void Client::handleCommand_HudChange(NetworkPacket* pkt)
        else
                *pkt >> intdata;
 
-       ClientEvent *event = new ClientEvent();
-       event->type              = CE_HUDCHANGE;
-       event->hudchange.id      = id;
-       event->hudchange.stat    = (HudElementStat)stat;
-       event->hudchange.v2fdata = new v2f(v2fdata);
-       event->hudchange.v3fdata = new v3f(v3fdata);
-       event->hudchange.sdata   = new std::string(sdata);
-       event->hudchange.data    = intdata;
-       event->hudchange.v2s32data = new v2s32(v2s32data);
-       m_client_event_queue.push(event);
+       std::unordered_map<u32, u32>::const_iterator i = m_hud_server_to_client.find(server_id);
+       if (i != m_hud_server_to_client.end()) {
+               ClientEvent *event = new ClientEvent();
+               event->type              = CE_HUDCHANGE;
+               event->hudchange.id      = i->second;
+               event->hudchange.stat    = (HudElementStat)stat;
+               event->hudchange.v2fdata = new v2f(v2fdata);
+               event->hudchange.v3fdata = new v3f(v3fdata);
+               event->hudchange.sdata   = new std::string(sdata);
+               event->hudchange.data    = intdata;
+               event->hudchange.v2s32data = new v2s32(v2s32data);
+               m_client_event_queue.push(event);
+       }
 }
 
 void Client::handleCommand_HudSetFlags(NetworkPacket* pkt)
index 507fd58b4a27ad40a58bb72ba32e5b7a30df6150..cac48d4882f4b6cab99fd6d99f36be1ca0285c81 100644 (file)
@@ -1792,3 +1792,142 @@ void push_objectRef(lua_State *L, const u16 id)
        lua_remove(L, -2); // object_refs
        lua_remove(L, -2); // core
 }
+
+void read_hud_element(lua_State *L, HudElement *elem)
+{
+       elem->type = (HudElementType)getenumfield(L, 2, "hud_elem_type",
+                                                                       es_HudElementType, HUD_ELEM_TEXT);
+
+       lua_getfield(L, 2, "position");
+       elem->pos = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
+       lua_pop(L, 1);
+
+       lua_getfield(L, 2, "scale");
+       elem->scale = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
+       lua_pop(L, 1);
+
+       lua_getfield(L, 2, "size");
+       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);
+
+       // Deprecated, only for compatibility's sake
+       if (elem->dir == 0)
+               elem->dir = getintfield_default(L, 2, "dir", 0);
+
+       lua_getfield(L, 2, "alignment");
+       elem->align = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
+       lua_pop(L, 1);
+
+       lua_getfield(L, 2, "offset");
+       elem->offset = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
+       lua_pop(L, 1);
+
+       lua_getfield(L, 2, "world_pos");
+       elem->world_pos = lua_istable(L, -1) ? read_v3f(L, -1) : v3f();
+       lua_pop(L, 1);
+
+       /* check for known deprecated element usage */
+       if ((elem->type  == HUD_ELEM_STATBAR) && (elem->size == v2s32()))
+               log_deprecated(L,"Deprecated usage of statbar without size!");
+}
+
+void push_hud_element(lua_State *L, HudElement *elem)
+{
+       lua_newtable(L);
+
+       lua_pushstring(L, es_HudElementType[(u8)elem->type].str);
+       lua_setfield(L, -2, "type");
+
+       push_v2f(L, elem->pos);
+       lua_setfield(L, -2, "position");
+
+       lua_pushstring(L, elem->name.c_str());
+       lua_setfield(L, -2, "name");
+
+       push_v2f(L, elem->scale);
+       lua_setfield(L, -2, "scale");
+
+       lua_pushstring(L, elem->text.c_str());
+       lua_setfield(L, -2, "text");
+
+       lua_pushnumber(L, elem->number);
+       lua_setfield(L, -2, "number");
+
+       lua_pushnumber(L, elem->item);
+       lua_setfield(L, -2, "item");
+
+       lua_pushnumber(L, elem->dir);
+       lua_setfield(L, -2, "direction");
+
+       // Deprecated, only for compatibility's sake
+       lua_pushnumber(L, elem->dir);
+       lua_setfield(L, -2, "dir");
+
+       push_v3f(L, elem->world_pos);
+       lua_setfield(L, -2, "world_pos");
+}
+
+HudElementStat read_hud_change(lua_State *L, HudElement *elem, void **value)
+{
+       HudElementStat stat = HUD_STAT_NUMBER;
+       if (lua_isstring(L, 3)) {
+               int statint;
+               std::string statstr = lua_tostring(L, 3);
+               stat = string_to_enum(es_HudElementStat, statint, statstr) ?
+                               (HudElementStat)statint : stat;
+       }
+
+       switch (stat) {
+               case HUD_STAT_POS:
+                       elem->pos = read_v2f(L, 4);
+                       *value = &elem->pos;
+                       break;
+               case HUD_STAT_NAME:
+                       elem->name = luaL_checkstring(L, 4);
+                       *value = &elem->name;
+                       break;
+               case HUD_STAT_SCALE:
+                       elem->scale = read_v2f(L, 4);
+                       *value = &elem->scale;
+                       break;
+               case HUD_STAT_TEXT:
+                       elem->text = luaL_checkstring(L, 4);
+                       *value = &elem->text;
+                       break;
+               case HUD_STAT_NUMBER:
+                       elem->number = luaL_checknumber(L, 4);
+                       *value = &elem->number;
+                       break;
+               case HUD_STAT_ITEM:
+                       elem->item = luaL_checknumber(L, 4);
+                       *value = &elem->item;
+                       break;
+               case HUD_STAT_DIR:
+                       elem->dir = luaL_checknumber(L, 4);
+                       *value = &elem->dir;
+                       break;
+               case HUD_STAT_ALIGN:
+                       elem->align = read_v2f(L, 4);
+                       *value = &elem->align;
+                       break;
+               case HUD_STAT_OFFSET:
+                       elem->offset = read_v2f(L, 4);
+                       *value = &elem->offset;
+                       break;
+               case HUD_STAT_WORLD_POS:
+                       elem->world_pos = read_v3f(L, 4);
+                       *value = &elem->world_pos;
+                       break;
+               case HUD_STAT_SIZE:
+                       elem->size = read_v2s32(L, 4);
+                       *value = &elem->size;
+                       break;
+       }
+       return stat;
+}
index 80a96e3275ec2e16f4531aaac37c41a1d0a328ed..d5c375a8fe6c97e5b57c025772f48f065b677aff 100644 (file)
@@ -39,6 +39,7 @@ extern "C" {
 #include "itemgroup.h"
 #include "itemdef.h"
 #include "c_types.h"
+#include "hud.h"
 
 namespace Json { class Value; }
 
@@ -181,4 +182,10 @@ void               push_pointed_thing        (lua_State *L, const PointedThing &
 
 void               push_objectRef            (lua_State *L, const u16 id);
 
+void               read_hud_element          (lua_State *L, HudElement *elem);
+
+void               push_hud_element          (lua_State *L, HudElement *elem);
+
+HudElementStat     read_hud_change           (lua_State *L, HudElement *elem, void **value);
+
 extern struct EnumString es_TileAnimationType[];
index da560c3acb630cfdbd6e81508640deeff73695b0..492422d92cd09d5feaf3e00c9366ebb62878bec3 100644 (file)
@@ -21,6 +21,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "l_internal.h"
 #include "script/common/c_converter.h"
 #include "localplayer.h"
+#include "hud.h"
+#include "common/c_content.h"
 
 LuaLocalPlayer::LuaLocalPlayer(LocalPlayer *m) : m_localplayer(m)
 {
@@ -272,6 +274,73 @@ int LuaLocalPlayer::l_get_movement(lua_State *L)
        return 1;
 }
 
+
+// hud_add(self, form)
+int LuaLocalPlayer::l_hud_add(lua_State *L)
+{
+       LocalPlayer *player = getobject(L, 1);
+
+       HudElement *elem = new HudElement;
+       read_hud_element(L, elem);
+
+       u32 id = player->addHud(elem);
+       if (id == U32_MAX) {
+               delete elem;
+               return 0;
+       }
+       lua_pushnumber(L, id);
+       return 1;
+}
+
+// hud_remove(self, id)
+int LuaLocalPlayer::l_hud_remove(lua_State *L)
+{
+       LocalPlayer *player = getobject(L, 1);
+       u32 id = luaL_checkinteger(L, 2);
+       HudElement *element = player->removeHud(id);
+       if (!element)
+               lua_pushboolean(L, false);
+       else
+               lua_pushboolean(L, true);
+       delete element;
+       return 1;
+}
+
+// hud_change(self, id, stat, data)
+int LuaLocalPlayer::l_hud_change(lua_State *L)
+{
+       LocalPlayer *player = getobject(L, 1);
+
+       u32 id = luaL_checkinteger(L, 2);
+
+       HudElement *element = player->getHud(id);
+       if (!element)
+               return 0;
+
+       void *unused;
+       read_hud_change(L, element, &unused);
+
+       lua_pushboolean(L, true);
+       return 1;
+}
+
+// hud_get(self, id)
+int LuaLocalPlayer::l_hud_get(lua_State *L)
+{
+       LocalPlayer *player = getobject(L, 1);
+
+       u32 id = luaL_checkinteger(L, -1);
+
+       HudElement *e = player->getHud(id);
+       if (!e) {
+               lua_pushnil(L);
+               return 1;
+       }
+
+       push_hud_element(L, e);
+       return 1;
+}
+
 LuaLocalPlayer *LuaLocalPlayer::checkobject(lua_State *L, int narg)
 {
        luaL_checktype(L, narg, LUA_TUSERDATA);
@@ -353,6 +422,10 @@ const luaL_Reg LuaLocalPlayer::methods[] = {
                luamethod(LuaLocalPlayer, get_movement_acceleration),
                luamethod(LuaLocalPlayer, get_movement_speed),
                luamethod(LuaLocalPlayer, get_movement),
+               luamethod(LuaLocalPlayer, hud_add),
+               luamethod(LuaLocalPlayer, hud_remove),
+               luamethod(LuaLocalPlayer, hud_change),
+               luamethod(LuaLocalPlayer, hud_get),
 
                {0, 0}
 };
index d30fe1d6431ef313e9ba8c59e8906c99e8d7ce2c..01de2ed4eaf16798d8470289cead5cd81cdbc97a 100644 (file)
@@ -66,6 +66,17 @@ private:
 
        static int l_get_movement(lua_State *L);
 
+       // hud_add(self, id, form)
+       static int l_hud_add(lua_State *L);
+
+       // hud_rm(self, id)
+       static int l_hud_remove(lua_State *L);
+
+       // hud_change(self, id, stat, data)
+       static int l_hud_change(lua_State *L);
+       // hud_get(self, id)
+       static int l_hud_get(lua_State *L);
+
        LocalPlayer *m_localplayer = nullptr;
 
 public:
index bc150d70f4a1c704bfbd8ecbc8caa4be8a4ee188..3afd21ec3b22a910cc3175e8877322c19f8a2fa3 100644 (file)
@@ -32,44 +32,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "hud.h"
 #include "scripting_server.h"
 
-struct EnumString es_HudElementType[] =
-{
-       {HUD_ELEM_IMAGE,     "image"},
-       {HUD_ELEM_TEXT,      "text"},
-       {HUD_ELEM_STATBAR,   "statbar"},
-       {HUD_ELEM_INVENTORY, "inventory"},
-       {HUD_ELEM_WAYPOINT,  "waypoint"},
-{0, NULL},
-};
-
-struct EnumString es_HudElementStat[] =
-{
-       {HUD_STAT_POS,    "position"},
-       {HUD_STAT_POS,    "pos"}, /* Deprecated, only for compatibility's sake */
-       {HUD_STAT_NAME,   "name"},
-       {HUD_STAT_SCALE,  "scale"},
-       {HUD_STAT_TEXT,   "text"},
-       {HUD_STAT_NUMBER, "number"},
-       {HUD_STAT_ITEM,   "item"},
-       {HUD_STAT_DIR,    "direction"},
-       {HUD_STAT_ALIGN,  "alignment"},
-       {HUD_STAT_OFFSET, "offset"},
-       {HUD_STAT_WORLD_POS, "world_pos"},
-       {0, NULL},
-};
-
-struct EnumString es_HudBuiltinElement[] =
-{
-       {HUD_FLAG_HOTBAR_VISIBLE,        "hotbar"},
-       {HUD_FLAG_HEALTHBAR_VISIBLE,     "healthbar"},
-       {HUD_FLAG_CROSSHAIR_VISIBLE,     "crosshair"},
-       {HUD_FLAG_WIELDITEM_VISIBLE,     "wielditem"},
-       {HUD_FLAG_BREATHBAR_VISIBLE,     "breathbar"},
-       {HUD_FLAG_MINIMAP_VISIBLE,       "minimap"},
-       {HUD_FLAG_MINIMAP_RADAR_VISIBLE, "minimap_radar"},
-       {0, NULL},
-};
-
 /*
        ObjectRef
 */
@@ -1345,48 +1307,7 @@ int ObjectRef::l_hud_add(lua_State *L)
                return 0;
 
        HudElement *elem = new HudElement;
-
-       elem->type = (HudElementType)getenumfield(L, 2, "hud_elem_type",
-                                                               es_HudElementType, HUD_ELEM_TEXT);
-
-       lua_getfield(L, 2, "position");
-       elem->pos = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
-       lua_pop(L, 1);
-
-       lua_getfield(L, 2, "scale");
-       elem->scale = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
-       lua_pop(L, 1);
-
-       lua_getfield(L, 2, "size");
-       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);
-
-       // Deprecated, only for compatibility's sake
-       if (elem->dir == 0)
-               elem->dir = getintfield_default(L, 2, "dir", 0);
-
-       lua_getfield(L, 2, "alignment");
-       elem->align = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
-       lua_pop(L, 1);
-
-       lua_getfield(L, 2, "offset");
-       elem->offset = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
-       lua_pop(L, 1);
-
-       lua_getfield(L, 2, "world_pos");
-       elem->world_pos = lua_istable(L, -1) ? read_v3f(L, -1) : v3f();
-       lua_pop(L, 1);
-
-       /* check for known deprecated element usage */
-       if ((elem->type  == HUD_ELEM_STATBAR) && (elem->size == v2s32())) {
-               log_deprecated(L,"Deprecated usage of statbar without size!");
-       }
+       read_hud_element(L, elem);
 
        u32 id = getServer(L)->hudAdd(player, elem);
        if (id == U32_MAX) {
@@ -1433,61 +1354,8 @@ int ObjectRef::l_hud_change(lua_State *L)
        if (!e)
                return 0;
 
-       HudElementStat stat = HUD_STAT_NUMBER;
-       if (lua_isstring(L, 3)) {
-               int statint;
-               std::string statstr = lua_tostring(L, 3);
-               stat = string_to_enum(es_HudElementStat, statint, statstr) ?
-                               (HudElementStat)statint : HUD_STAT_NUMBER;
-       }
-
        void *value = NULL;
-       switch (stat) {
-               case HUD_STAT_POS:
-                       e->pos = read_v2f(L, 4);
-                       value = &e->pos;
-                       break;
-               case HUD_STAT_NAME:
-                       e->name = luaL_checkstring(L, 4);
-                       value = &e->name;
-                       break;
-               case HUD_STAT_SCALE:
-                       e->scale = read_v2f(L, 4);
-                       value = &e->scale;
-                       break;
-               case HUD_STAT_TEXT:
-                       e->text = luaL_checkstring(L, 4);
-                       value = &e->text;
-                       break;
-               case HUD_STAT_NUMBER:
-                       e->number = luaL_checknumber(L, 4);
-                       value = &e->number;
-                       break;
-               case HUD_STAT_ITEM:
-                       e->item = luaL_checknumber(L, 4);
-                       value = &e->item;
-                       break;
-               case HUD_STAT_DIR:
-                       e->dir = luaL_checknumber(L, 4);
-                       value = &e->dir;
-                       break;
-               case HUD_STAT_ALIGN:
-                       e->align = read_v2f(L, 4);
-                       value = &e->align;
-                       break;
-               case HUD_STAT_OFFSET:
-                       e->offset = read_v2f(L, 4);
-                       value = &e->offset;
-                       break;
-               case HUD_STAT_WORLD_POS:
-                       e->world_pos = read_v3f(L, 4);
-                       value = &e->world_pos;
-                       break;
-               case HUD_STAT_SIZE:
-                       e->size = read_v2s32(L, 4);
-                       value = &e->size;
-                       break;
-       }
+       HudElementStat stat = read_hud_change(L, e, &value);
 
        getServer(L)->hudChange(player, id, stat, value);
 
@@ -1509,40 +1377,7 @@ int ObjectRef::l_hud_get(lua_State *L)
        HudElement *e = player->getHud(id);
        if (!e)
                return 0;
-
-       lua_newtable(L);
-
-       lua_pushstring(L, es_HudElementType[(u8)e->type].str);
-       lua_setfield(L, -2, "type");
-
-       push_v2f(L, e->pos);
-       lua_setfield(L, -2, "position");
-
-       lua_pushstring(L, e->name.c_str());
-       lua_setfield(L, -2, "name");
-
-       push_v2f(L, e->scale);
-       lua_setfield(L, -2, "scale");
-
-       lua_pushstring(L, e->text.c_str());
-       lua_setfield(L, -2, "text");
-
-       lua_pushnumber(L, e->number);
-       lua_setfield(L, -2, "number");
-
-       lua_pushnumber(L, e->item);
-       lua_setfield(L, -2, "item");
-
-       lua_pushnumber(L, e->dir);
-       lua_setfield(L, -2, "direction");
-
-       // Deprecated, only for compatibility's sake
-       lua_pushnumber(L, e->dir);
-       lua_setfield(L, -2, "dir");
-
-       push_v3f(L, e->world_pos);
-       lua_setfield(L, -2, "world_pos");
-
+       push_hud_element(L, e);
        return 1;
 }
 
index 95a61fc28a9986d34495a9cac4a1295996dc83be..f124cd7a58b76fba8bce6a3b69010323ff54f78c 100644 (file)
@@ -2,30 +2,30 @@ src/activeobject.h
 src/ban.cpp
 src/camera.cpp
 src/camera.h
-src/mapgen/cavegen.cpp
-src/mapgen/cavegen.h
 src/chat.cpp
 src/chat.h
 src/chat_interface.h
+src/client/clientlauncher.cpp
+src/client/clientlauncher.h
 src/client.cpp
-src/client.h
 src/clientenvironment.cpp
 src/clientenvironment.h
+src/client/gameui.cpp
+src/client.h
+src/client/hud.cpp
+src/client/hud.h
 src/clientiface.cpp
 src/clientiface.h
+src/client/joystick_controller.cpp
+src/client/joystick_controller.h
 src/clientmap.cpp
 src/clientmap.h
 src/clientmedia.cpp
 src/clientmedia.h
 src/clientobject.cpp
 src/clientobject.h
-src/client/clientlauncher.cpp
-src/client/clientlauncher.h
-src/client/gameui.cpp
-src/client/joystick_controller.cpp
-src/client/joystick_controller.h
-src/client/renderingengine.cpp
 src/client/render/core.cpp
+src/client/renderingengine.cpp
 src/client/render/interlaced.cpp
 src/client/render/plain.cpp
 src/client/render/sidebyside.cpp
@@ -65,8 +65,6 @@ src/daynightratio.h
 src/debug.cpp
 src/debug.h
 src/defaultsettings.cpp
-src/mapgen/dungeongen.cpp
-src/mapgen/dungeongen.h
 src/emerge.cpp
 src/emerge.h
 src/environment.cpp
@@ -81,8 +79,8 @@ src/filesys.h
 src/fontengine.cpp
 src/fontengine.h
 src/game.cpp
-src/game.h
 src/gamedef.h
+src/game.h
 src/genericobject.cpp
 src/genericobject.h
 src/gettext.cpp
@@ -93,26 +91,29 @@ src/gui/guiEditBoxWithScrollbar.cpp
 src/gui/guiEditBoxWithScrollbar.h
 src/gui/guiEngine.cpp
 src/gui/guiEngine.h
-src/gui/guiPathSelectMenu.cpp
-src/gui/guiPathSelectMenu.h
 src/gui/guiFormSpecMenu.cpp
 src/gui/guiFormSpecMenu.h
 src/gui/guiKeyChangeMenu.cpp
 src/gui/guiMainMenu.h
 src/gui/guiPasswordChange.cpp
-src/guiscalingfilter.cpp
-src/guiscalingfilter.h
+src/gui/guiPathSelectMenu.cpp
+src/gui/guiPathSelectMenu.h
 src/gui/guiTable.cpp
 src/gui/guiTable.h
 src/gui/guiVolumeChange.cpp
 src/gui/guiVolumeChange.h
+src/gui/intlGUIEditBox.cpp
+src/gui/intlGUIEditBox.h
+src/gui/mainmenumanager.h
+src/gui/modalMenu.h
+src/guiscalingfilter.cpp
+src/guiscalingfilter.h
+src/gui/touchscreengui.cpp
 src/httpfetch.cpp
 src/hud.cpp
 src/hud.h
 src/imagefilters.cpp
 src/imagefilters.h
-src/gui/intlGUIEditBox.cpp
-src/gui/intlGUIEditBox.h
 src/inventory.cpp
 src/inventory.h
 src/inventorymanager.cpp
@@ -132,21 +133,23 @@ src/localplayer.cpp
 src/log.cpp
 src/log.h
 src/main.cpp
-src/gui/mainmenumanager.h
 src/mapblock.cpp
 src/mapblock.h
 src/mapblock_mesh.cpp
 src/mapblock_mesh.h
 src/map.cpp
-src/map.h
-src/mapgen/mapgen.cpp
-src/mapgen/mapgen.h
+src/mapgen/cavegen.cpp
+src/mapgen/cavegen.h
+src/mapgen/dungeongen.cpp
+src/mapgen/dungeongen.h
 src/mapgen/mapgen_carpathian.cpp
 src/mapgen/mapgen_carpathian.h
+src/mapgen/mapgen.cpp
 src/mapgen/mapgen_flat.cpp
 src/mapgen/mapgen_flat.h
 src/mapgen/mapgen_fractal.cpp
 src/mapgen/mapgen_fractal.h
+src/mapgen/mapgen.h
 src/mapgen/mapgen_singlenode.cpp
 src/mapgen/mapgen_singlenode.h
 src/mapgen/mapgen_v5.cpp
@@ -157,6 +160,17 @@ src/mapgen/mapgen_v7.cpp
 src/mapgen/mapgen_v7.h
 src/mapgen/mapgen_valleys.cpp
 src/mapgen/mapgen_valleys.h
+src/mapgen/mg_biome.cpp
+src/mapgen/mg_biome.h
+src/mapgen/mg_decoration.cpp
+src/mapgen/mg_decoration.h
+src/mapgen/mg_ore.cpp
+src/mapgen/mg_ore.h
+src/mapgen/mg_schematic.cpp
+src/mapgen/mg_schematic.h
+src/mapgen/treegen.cpp
+src/mapgen/treegen.h
+src/map.h
 src/mapnode.cpp
 src/mapnode.h
 src/mapsector.cpp
@@ -164,20 +178,11 @@ src/mapsector.h
 src/map_settings_manager.cpp
 src/map_settings_manager.h
 src/mesh.cpp
-src/mesh.h
 src/mesh_generator_thread.cpp
+src/mesh.h
 src/metadata.h
-src/mapgen/mg_biome.cpp
-src/mapgen/mg_biome.h
-src/mapgen/mg_decoration.cpp
-src/mapgen/mg_decoration.h
-src/mapgen/mg_ore.cpp
-src/mapgen/mg_ore.h
-src/mapgen/mg_schematic.cpp
-src/mapgen/mg_schematic.h
 src/minimap.cpp
 src/minimap.h
-src/gui/modalMenu.h
 src/mods.cpp
 src/mods.h
 src/network/clientopcodes.cpp
@@ -305,12 +310,12 @@ src/script/scripting_server.cpp
 src/script/scripting_server.h
 src/serialization.cpp
 src/serialization.h
-src/server.cpp
-src/server.h
 src/serveractiveobjectmap.cpp
 src/serveractiveobjectmap.h
+src/server.cpp
 src/serverenvironment.cpp
 src/serverenvironment.h
+src/server.h
 src/serverlist.cpp
 src/serverlist.h
 src/serverobject.cpp
@@ -342,17 +347,14 @@ src/threads.h
 src/tileanimation.cpp
 src/tool.cpp
 src/tool.h
-src/gui/touchscreengui.cpp
 src/translation.cpp
-src/mapgen/treegen.cpp
-src/mapgen/treegen.h
-src/unittest/test.cpp
-src/unittest/test.h
 src/unittest/test_areastore.cpp
 src/unittest/test_collision.cpp
 src/unittest/test_compression.cpp
 src/unittest/test_connection.cpp
+src/unittest/test.cpp
 src/unittest/test_filepath.cpp
+src/unittest/test.h
 src/unittest/test_inventory.cpp
 src/unittest/test_keycode.cpp
 src/unittest/test_map_settings_manager.cpp