Skip to content

Commit

Permalink
Add compass HUD element (#9312)
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
4 people committed Aug 29, 2020
1 parent 386d5f7 commit 5c4b560
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 2 deletions.
18 changes: 17 additions & 1 deletion doc/lua_api.txt
Expand Up @@ -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
================================
Expand Down Expand Up @@ -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
Expand Down
140 changes: 140 additions & 0 deletions src/client/hud.cpp
Expand Up @@ -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()
Expand Down Expand Up @@ -423,13 +445,131 @@ 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;
}
}
}

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,
Expand Down
8 changes: 8 additions & 0 deletions src/client/hud.h
Expand Up @@ -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;
Expand All @@ -115,6 +121,8 @@ class Hud

video::SMaterial m_selection_material;

scene::SMeshBuffer m_rotation_mesh_buffer;

enum
{
HIGHLIGHT_BOX,
Expand Down
1 change: 1 addition & 0 deletions src/hud.cpp
Expand Up @@ -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},
};

Expand Down
10 changes: 9 additions & 1 deletion src/hud.h
Expand Up @@ -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 {
Expand All @@ -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;
Expand Down

0 comments on commit 5c4b560

Please sign in to comment.