]> git.lizzy.rs Git - minetest.git/commitdiff
Add compass HUD element (#9312)
authorEvidenceB <49488517+EvidenceBKidscode@users.noreply.github.com>
Sat, 29 Aug 2020 18:13:30 +0000 (20:13 +0200)
committerGitHub <noreply@github.com>
Sat, 29 Aug 2020 18:13:30 +0000 (20:13 +0200)
Co-authored-by: Jean-Patrick Guerrero <jeanpatrick.guerrero@gmail.com>
Co-authored-by: Pierre-Yves Rollo <dev@pyrollo.com>
Co-authored-by: SmallJoker <SmallJoker@users.noreply.github.com>
doc/lua_api.txt
src/client/hud.cpp
src/client/hud.h
src/hud.cpp
src/hud.h

index 08bdba03ed2295cbad0724c1be9bbc0c466616c4..c818241635ae0ce3b9b336dc946c04b56b30eaae 100644 (file)
@@ -1451,7 +1451,23 @@ Same as `image`, but does not accept a `position`; the position is instead deter
 * `world_pos`: World position of the waypoint.
 * `offset`: offset in pixels from position.
 
+### `compass`
 
+Displays an image oriented or translated according to current heading direction.
+
+* `size`: The size of this element. Negative values represent percentage
+  of the screen; e.g. `x=-100` means 100% (width).
+* `scale`: Scale of the translated image (used only for dir = 2 or dir = 3).
+* `text`: The name of the texture to use.
+* `alignment`: The alignment of the image.
+* `offset`: Offset in pixels from position.
+* `dir`: How the image is rotated/translated:
+  * 0 - Rotate as heading direction
+  * 1 - Rotate in reverse direction
+  * 2 - Translate as landscape direction
+  * 3 - Translate in reverse direction
+
+If translation is chosen, texture is repeated horizontally to fill the whole element.
 
 Representations of simple things
 ================================
@@ -7968,7 +7984,7 @@ Used by `Player:hud_add`. Returned by `Player:hud_get`.
 
     {
         hud_elem_type = "image",  -- See HUD element types
-        -- Type of element, can be "image", "text", "statbar", or "inventory"
+        -- Type of element, can be "image", "text", "statbar", "inventory" or "compass"
 
         position = {x=0.5, y=0.5},
         -- Left corner position of element
index 2b347c1e0b8f0cfdc1d435f5dcf0827583fb3ace..d3038230c8b731207e917f9cb42e3b6187a3b7ee 100644 (file)
@@ -114,6 +114,28 @@ Hud::Hud(gui::IGUIEnvironment *guienv, Client *client, LocalPlayer *player,
        } else {
                m_selection_material.MaterialType = video::EMT_SOLID;
        }
+
+       // Prepare mesh for compass drawing
+       m_rotation_mesh_buffer.Vertices.set_used(4);
+       m_rotation_mesh_buffer.Indices.set_used(6);
+
+       video::SColor white(255, 255, 255, 255);
+       v3f normal(0.f, 0.f, 1.f);
+
+       m_rotation_mesh_buffer.Vertices[0] = video::S3DVertex(v3f(-1.f, -1.f, 0.f), normal, white, v2f(0.f, 1.f));
+       m_rotation_mesh_buffer.Vertices[1] = video::S3DVertex(v3f(-1.f,  1.f, 0.f), normal, white, v2f(0.f, 0.f));
+       m_rotation_mesh_buffer.Vertices[2] = video::S3DVertex(v3f( 1.f,  1.f, 0.f), normal, white, v2f(1.f, 0.f));
+       m_rotation_mesh_buffer.Vertices[3] = video::S3DVertex(v3f( 1.f, -1.f, 0.f), normal, white, v2f(1.f, 1.f));
+
+       m_rotation_mesh_buffer.Indices[0] = 0;
+       m_rotation_mesh_buffer.Indices[1] = 1;
+       m_rotation_mesh_buffer.Indices[2] = 2;
+       m_rotation_mesh_buffer.Indices[3] = 2;
+       m_rotation_mesh_buffer.Indices[4] = 3;
+       m_rotation_mesh_buffer.Indices[5] = 0;
+
+       m_rotation_mesh_buffer.getMaterial().Lighting = false;
+       m_rotation_mesh_buffer.getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
 }
 
 Hud::~Hud()
@@ -423,6 +445,54 @@ void Hud::drawLuaElements(const v3s16 &camera_offset)
                                        core::rect<s32>(core::position2d<s32>(0,0), imgsize),
                                        NULL, colors, true);
                                break; }
+                       case HUD_ELEM_COMPASS: {
+                               video::ITexture *texture = tsrc->getTexture(e->text);
+                               if (!texture)
+                                       continue;
+
+                               // Positionning :
+                               v2s32 dstsize(e->size.X, e->size.Y);
+                               if (e->size.X < 0)
+                                       dstsize.X = m_screensize.X * (e->size.X * -0.01);
+                               if (e->size.Y < 0)
+                                       dstsize.Y = m_screensize.Y * (e->size.Y * -0.01);
+
+                               if (dstsize.X <= 0 || dstsize.Y <= 0)
+                                       return; // Avoid zero divides
+
+                               // Angle according to camera view
+                               v3f fore(0.f, 0.f, 1.f);
+                               scene::ICameraSceneNode *cam = RenderingEngine::get_scene_manager()->getActiveCamera();
+                               cam->getAbsoluteTransformation().rotateVect(fore);
+                               int angle = - fore.getHorizontalAngle().Y;
+
+                               // Limit angle and ajust with given offset
+                               angle = (angle + (int)e->number) % 360;
+
+                               core::rect<s32> dstrect(0, 0, dstsize.X, dstsize.Y);
+                               dstrect += pos + v2s32(
+                                                               (e->align.X - 1.0) * dstsize.X / 2,
+                                                               (e->align.Y - 1.0) * dstsize.Y / 2) +
+                                               v2s32(e->offset.X * m_hud_scaling, e->offset.Y * m_hud_scaling);
+
+                               switch (e->dir) {
+                               case HUD_COMPASS_ROTATE:
+                                       drawCompassRotate(e, texture, dstrect, angle);
+                                       break;
+                               case HUD_COMPASS_ROTATE_REVERSE:
+                                       drawCompassRotate(e, texture, dstrect, -angle);
+                                       break;
+                               case HUD_COMPASS_TRANSLATE:
+                                       drawCompassTranslate(e, texture, dstrect, angle);
+                                       break;
+                               case HUD_COMPASS_TRANSLATE_REVERSE:
+                                       drawCompassTranslate(e, texture, dstrect, -angle);
+                                       break;
+                               default:
+                                       break;
+                               }
+
+                               break; }
                        default:
                                infostream << "Hud::drawLuaElements: ignoring drawform " << e->type <<
                                        " of hud element ID " << i << " due to unrecognized type" << std::endl;
@@ -430,6 +500,76 @@ void Hud::drawLuaElements(const v3s16 &camera_offset)
        }
 }
 
+void Hud::drawCompassTranslate(HudElement *e, video::ITexture *texture,
+               const core::rect<s32> &rect, int angle)
+{
+       const video::SColor color(255, 255, 255, 255);
+       const video::SColor colors[] = {color, color, color, color};
+
+       // Compute source image scaling
+       core::dimension2di imgsize(texture->getOriginalSize());
+       core::rect<s32> srcrect(0, 0, imgsize.Width, imgsize.Height);
+
+       v2s32 dstsize(rect.getHeight() * e->scale.X * imgsize.Width / imgsize.Height,
+                       rect.getHeight() * e->scale.Y);
+
+       // Avoid infinite loop
+       if (dstsize.X <= 0 || dstsize.Y <= 0)
+               return;
+
+       core::rect<s32> tgtrect(0, 0, dstsize.X, dstsize.Y);
+       tgtrect +=  v2s32(
+                               (rect.getWidth() - dstsize.X) / 2,
+                               (rect.getHeight() - dstsize.Y) / 2) +
+                       rect.UpperLeftCorner;
+
+       int offset = angle * dstsize.X / 360;
+
+       tgtrect += v2s32(offset, 0);
+
+       // Repeat image as much as needed
+       while (tgtrect.UpperLeftCorner.X > rect.UpperLeftCorner.X)
+               tgtrect -= v2s32(dstsize.X, 0);
+
+       draw2DImageFilterScaled(driver, texture, tgtrect, srcrect, &rect, colors, true);
+       tgtrect += v2s32(dstsize.X, 0);
+
+       while (tgtrect.UpperLeftCorner.X < rect.LowerRightCorner.X) {
+               draw2DImageFilterScaled(driver, texture, tgtrect, srcrect, &rect, colors, true);
+               tgtrect += v2s32(dstsize.X, 0);
+       }
+}
+
+void Hud::drawCompassRotate(HudElement *e, video::ITexture *texture,
+               const core::rect<s32> &rect, int angle)
+{
+       core::dimension2di imgsize(texture->getOriginalSize());
+
+       core::rect<s32> oldViewPort = driver->getViewPort();
+       core::matrix4 oldProjMat = driver->getTransform(video::ETS_PROJECTION);
+       core::matrix4 oldViewMat = driver->getTransform(video::ETS_VIEW);
+
+       core::matrix4 Matrix;
+       Matrix.makeIdentity();
+       Matrix.setRotationDegrees(v3f(0.f, 0.f, angle));
+
+       driver->setViewPort(rect);
+       driver->setTransform(video::ETS_PROJECTION, core::matrix4());
+       driver->setTransform(video::ETS_VIEW, core::matrix4());
+       driver->setTransform(video::ETS_WORLD, Matrix);
+
+       video::SMaterial &material = m_rotation_mesh_buffer.getMaterial();
+       material.TextureLayer[0].Texture = texture;
+       driver->setMaterial(material);
+       driver->drawMeshBuffer(&m_rotation_mesh_buffer);
+
+       driver->setTransform(video::ETS_WORLD, core::matrix4());
+       driver->setTransform(video::ETS_VIEW, oldViewMat);
+       driver->setTransform(video::ETS_PROJECTION, oldProjMat);
+
+       // restore the view area
+       driver->setViewPort(oldViewPort);
+}
 
 void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir,
                const std::string &texture, const std::string &bgtexture,
index ba34d479d82a7fcfe9bbd13391606abfb03270f6..cf83cb16e178468c0baf9a927fcf6578a009c6bd 100644 (file)
@@ -95,6 +95,12 @@ class Hud
 
        void drawItem(const ItemStack &item, const core::rect<s32> &rect, bool selected);
 
+       void drawCompassTranslate(HudElement *e, video::ITexture *texture,
+                       const core::rect<s32> &rect, int way);
+
+       void drawCompassRotate(HudElement *e, video::ITexture *texture,
+                       const core::rect<s32> &rect, int way);
+
        float m_hud_scaling; // cached minetest setting
        float m_scale_factor;
        v3s16 m_camera_offset;
@@ -115,6 +121,8 @@ class Hud
 
        video::SMaterial m_selection_material;
 
+       scene::SMeshBuffer m_rotation_mesh_buffer;
+
        enum
        {
                HIGHLIGHT_BOX,
index 4830c56a4d074c540f08fdf136c3d24850e7b3ca..1757013427091d449f010cd85750a266b9a1cb69 100644 (file)
@@ -28,6 +28,7 @@ const struct EnumString es_HudElementType[] =
        {HUD_ELEM_INVENTORY, "inventory"},
        {HUD_ELEM_WAYPOINT,  "waypoint"},
        {HUD_ELEM_IMAGE_WAYPOINT, "image_waypoint"},
+       {HUD_ELEM_COMPASS,   "compass"},
        {0, NULL},
 };
 
index e015baec125fbf9dfe6334a52944c89937097aa6..0a6993c1b4ae0ae28a06c3985bf66fd2f4c20677 100644 (file)
--- a/src/hud.h
+++ b/src/hud.h
@@ -60,7 +60,8 @@ enum HudElementType {
        HUD_ELEM_STATBAR   = 2,
        HUD_ELEM_INVENTORY = 3,
        HUD_ELEM_WAYPOINT  = 4,
-       HUD_ELEM_IMAGE_WAYPOINT = 5
+       HUD_ELEM_IMAGE_WAYPOINT = 5,
+       HUD_ELEM_COMPASS   = 6
 };
 
 enum HudElementStat {
@@ -79,6 +80,13 @@ enum HudElementStat {
        HUD_STAT_TEXT2,
 };
 
+enum HudCompassDir {
+       HUD_COMPASS_ROTATE = 0,
+       HUD_COMPASS_ROTATE_REVERSE,
+       HUD_COMPASS_TRANSLATE,
+       HUD_COMPASS_TRANSLATE_REVERSE,
+};
+
 struct HudElement {
        HudElementType type;
        v2f pos;