This commit is contained in:
cx384 2024-04-20 05:16:34 +02:00 committed by GitHub
commit a3a4419d63
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 332 additions and 78 deletions

View File

@ -40,6 +40,7 @@ core.features = {
lsystem_decoration_type = true,
item_meta_range = true,
node_interaction_actor = true,
crosshair_hud_element = true,
}
function core.has_feature(arg)

View File

@ -259,3 +259,16 @@ register_builtin_hud_element("minimap", {
core.get_player_information(player:get_player_name()).protocol_version >= 44
end,
})
--- Crosshair
register_builtin_hud_element("crosshair", {
elem_def = {
type = "crosshair",
position = {x = 0.5, y = 0.5},
scale = {x = 1, y = 1},
},
show_elem = function(player, flags)
return flags.crosshair
end,
})

View File

@ -1812,6 +1812,26 @@ Displays a minimap on the HUD.
* `alignment`: The alignment of the minimap.
* `offset`: offset in pixels from position.
### `crosshair`
Displays a crosshair on the HUD.
* `scale`: The scale of the crosshair.
For image crosshairs it works the same as the scale of `image` HUD elements.
For line crosshairs the length is multiplied by the
* `alignment`: The alignment of the crosshair.
* `offset`: offset in pixels from position.
* `style`: The style of the crosshair:
* 0 - The default crosshair which when pointing at a node or nothing shows two
perpendicular lines of size 20, and when pointing at an object shows two
diagonal lines of size 16. The lines get replaced by images when textures
named `"crosshair.png"` and for objects `"object_crosshair.png"` exist.
* 1 - A crosshair that shows an image.
When pointing at nodes or nothing it uses as texture name `text`.
When pointing at objects it uses as texture name `text2`.
* `text`: Only relevent for `style` = 1.
* `text2`: Only relevent for `style` = 1.
Representations of simple things
================================
@ -5435,6 +5455,9 @@ Utilities
-- Allow passing an optional "actor" ObjectRef to the following functions:
-- minetest.place_node, minetest.dig_node, minetest.punch_node (5.9.0)
node_interaction_actor = true,
-- HUD elements of type crosshair exist and
-- the predefined crosshair is a Lua HUD elements.
crosshair_hud_element = true,
}
```
@ -7045,7 +7068,7 @@ Misc.
(regardless of online status)
* `minetest.hud_replace_builtin(name, hud_definition)`
* Replaces definition of a builtin hud element
* `name`: `"breath"`, `"health"` or `"minimap"`
* `name`: `"breath"`, `"health"`, `"minimap"` or `"crosshair"`
* `hud_definition`: definition to replace builtin definition
* `minetest.parse_relative_number(arg, relative_to)`: returns number or nil
* Helper function for chat commands.
@ -10532,7 +10555,7 @@ Used by `ObjectRef:hud_add`. Returned by `ObjectRef:hud_get`.
{
type = "image",
-- Type of element, can be "image", "text", "statbar", "inventory",
-- "waypoint", "image_waypoint", "compass" or "minimap"
-- "waypoint", "image_waypoint", "compass", "minimap" or "crosshair"
-- If undefined "text" will be used.
hud_elem_type = "image",

View File

@ -206,9 +206,172 @@ minetest.register_chatcommand("zoomfov", {
end,
})
-- Images
local hud_image_defs = {
{
type = "image",
position = {x=0.3, y=0.3},
scale = {x = 10, y = 10},
text = "default_cobble.png",
alignment = {x=0, y=-1},
offset = {x=0, y=0},
},
{
type = "image",
position = {x=0.7, y=0.3},
scale = {x = 10, y = 10},
text = "default_lava.png",
alignment = {x=0, y=1},
offset = {x=0, y=0},
},
{
type = "image",
position = {x=0.3, y=0.7},
scale = {x = 10, y = 20},
text = "default_gravel.png",
alignment = {x=0, y=0},
offset = {x=0, y=0},
},
{
type = "image",
position = {x=0.7, y=0.7},
scale = {x = 10, y = 10},
text = "default_tree_top.png",
alignment = {x=0, y=0},
offset = {x=160, y=0},
},
}
local player_hud_images= {}
minetest.register_chatcommand("hudimages", {
description = "Shows some test Lua HUD elements of type image. (add: Adds elements (default). remove: Removes elements)",
params = "[ add | remove ]",
func = function(name, params)
local player = minetest.get_player_by_name(name)
if not player then
return false, "No player."
end
local id_table = player_hud_images[name]
if not id_table then
id_table = {}
player_hud_images[name] = id_table
end
if params == "remove" then
for _, id in ipairs(id_table) do
player:hud_remove(id)
end
return true, "Images removed."
end
-- params == "add" or default
for _, def in ipairs(hud_image_defs) do
table.insert(id_table, player:hud_add(def))
end
return true, #hud_image_defs .." images added."
end
})
-- Crosshairs
local hud_crosshair_defs = {
{
type = "crosshair",
position = {x=0.45, y=0.5},
scale = {x = 1, y = 1},
alignment = {x=0, y=-1},
offset = {x=0, y=0},
},
{
type = "crosshair",
position = {x=0.45, y=0.5},
scale = {x = 1, y = 1},
alignment = {x=0, y=1},
offset = {x=0, y=0},
},
{
type = "crosshair",
position = {x=0.5, y=0.4},
scale = {x = 1, y = 2},
alignment = {x=0, y=1},
offset = {x=100, y=0},
},
{
type = "crosshair",
position = {x=0.5, y=0.7},
scale = {x = 5, y = 2},
alignment = {x=0, y=-1},
offset = {x=0, y=100},
},
{
type = "crosshair",
position = {x=0.5, y=0.65},
scale = {x = 2, y = 2},
alignment = {x=0, y=-1},
offset = {x=0, y=0},
},
{
type = "crosshair",
position = {x=0.3, y=0.5},
scale = {x = 1, y = 1},
alignment = {x=0, y=0},
offset = {x=0, y=0},
style = 1,
text = "testhud_crosshair.png",
text2 = "testhud_object_crosshair.png",
},
{
type = "crosshair",
position = {x=0.3, y=0.5},
scale = {x = 2, y = 1},
alignment = {x=0, y=2},
offset = {x=0, y=0},
style = 1,
text = "testhud_crosshair.png",
text2 = "testhud_object_crosshair.png",
},
}
local player_hud_crosshairs= {}
minetest.register_chatcommand("hudcrosshairs", {
description = "Shows some test Lua HUD elements of type crosshair. (add: Adds elements (default). remove: Removes elements)",
params = "[ add | remove ]",
func = function(name, params)
local player = minetest.get_player_by_name(name)
if not player then
return false, "No player."
end
local id_table = player_hud_crosshairs[name]
if not id_table then
id_table = {}
player_hud_crosshairs[name] = id_table
end
if params == "remove" then
for _, id in ipairs(id_table) do
player:hud_remove(id)
end
return true, "Crosshairs removed."
end
-- params == "add" or default
for _, def in ipairs(hud_crosshair_defs) do
table.insert(id_table, player:hud_add(def))
end
return true, #hud_crosshair_defs .." Crosshairs added."
end
})
minetest.register_on_leaveplayer(function(player)
player_font_huds[player:get_player_name()] = nil
player_waypoints[player:get_player_name()] = nil
local playername = player:get_player_name()
player_font_huds[playername] = nil
player_waypoints[playername] = nil
player_hud_images[playername] = nil
player_hud_crosshairs[playername] = nil
end)
minetest.register_chatcommand("hudprint", {
@ -230,3 +393,26 @@ minetest.register_chatcommand("hudprint", {
return true, s
end
})
local hud_flags = {"hotbar", "healthbar", "crosshair", "wielditem", "breathbar",
"minimap", "minimap_radar", "basic_debug", "chat"}
minetest.register_chatcommand("hudtoggleflag", {
description = "Toggles a hud flag.",
params = "[ ".. table.concat(hud_flags, " | ") .." ]",
func = function(name, params)
local player = minetest.get_player_by_name(name)
if not player then
return false, "No player."
end
local flags = player:hud_get_flags()
if flags[params] == nil then
return false, "Unknown hud flag."
end
flags[params] = not flags[params]
player:hud_set_flags(flags)
return true, "Flag \"".. params .."\" set to ".. tostring(flags[params]) .. "."
end
})

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 B

View File

@ -1423,7 +1423,7 @@ void Game::copyServerClientCache()
{
// It would be possible to let the client directly read the media files
// from where the server knows they are. But aside from being more complicated
// it would also *not* fill the media cache and cause slower joining of
// it would also *not* fill the media cache and cause slower joining of
// remote servers.
// (Imagine that you launch a game once locally and then connect to a server.)
@ -4302,15 +4302,13 @@ void Game::drawScene(ProfilerGraph *graph, RunStats *stats)
bool draw_wield_tool = (this->m_game_ui->m_flags.show_hud &&
(player->hud_flags & HUD_FLAG_WIELDITEM_VISIBLE) &&
(this->camera->getCameraMode() == CAMERA_MODE_FIRST));
bool draw_crosshair = (
(player->hud_flags & HUD_FLAG_CROSSHAIR_VISIBLE) &&
(this->camera->getCameraMode() != CAMERA_MODE_THIRD_FRONT));
bool draw_crosshairs = (this->camera->getCameraMode() != CAMERA_MODE_THIRD_FRONT);
if (g_touchscreengui && isTouchCrosshairDisabled())
draw_crosshair = false;
draw_crosshairs = false;
this->m_rendering_engine->draw_scene(sky_color, this->m_game_ui->m_flags.show_hud,
draw_wield_tool, draw_crosshair);
draw_wield_tool, draw_crosshairs);
/*
Profiler graph

View File

@ -340,7 +340,7 @@ bool Hud::calculateScreenPos(const v3s16 &camera_offset, HudElement *e, v2s32 *p
return true;
}
void Hud::drawLuaElements(const v3s16 &camera_offset)
void Hud::drawLuaElements(const v3s16 &camera_offset, bool draw_crosshairs)
{
const u32 text_height = g_fontengine->getTextHeight();
gui::IGUIFont *const font = g_fontengine->getFont();
@ -349,12 +349,21 @@ void Hud::drawLuaElements(const v3s16 &camera_offset)
std::vector<HudElement*> elems;
elems.reserve(player->maxHudId());
// Add builtin minimap if the server doesn't send it.
// Add builtin elements if the server doesn't send them.
// Declared here such that they have the same lifetime as the elems vector
HudElement minimap;
if (client->getProtoVersion() < 44 && (player->hud_flags & HUD_FLAG_MINIMAP_VISIBLE)) {
minimap = {HUD_ELEM_MINIMAP, v2f(1, 0), "", v2f(), "", 0 , 0, 0, v2f(-1, 1),
v2f(-10, 10), v3f(), v2s32(256, 256), 0, "", 0};
elems.push_back(&minimap);
HudElement crosshair;
if (client->getProtoVersion() < 44) {
if (player->hud_flags & HUD_FLAG_MINIMAP_VISIBLE) {
minimap = {HUD_ELEM_MINIMAP, v2f(1, 0), "", v2f(), "", 0 , 0, 0, v2f(-1, 1),
v2f(-10, 10), v3f(), v2s32(256, 256), 0, "", 0};
elems.push_back(&minimap);
}
if (player->hud_flags & HUD_FLAG_CROSSHAIR_VISIBLE) {
crosshair = {HUD_ELEM_CROSSHAIR, v2f(0.5, 0.5), "", v2f(1, 1), "", 0 , 0, 0, v2f(),
v2f(), v3f(), v2s32(), 0, "", 0};
elems.push_back(&crosshair);
}
}
for (size_t i = 0; i != player->maxHudId(); i++) {
@ -465,22 +474,7 @@ void Hud::drawLuaElements(const v3s16 &camera_offset)
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 * m_scale_factor,
imgsize.Height * e->scale.Y * m_scale_factor);
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 * m_scale_factor,
e->offset.Y * m_scale_factor);
draw2DImageFilterScaled(driver, texture, rect,
core::rect<s32>(core::position2d<s32>(0,0), imgsize),
NULL, colors, true);
drawImage(pos, e->scale, e->align, e->offset, texture, color);
break; }
case HUD_ELEM_COMPASS: {
video::ITexture *texture = tsrc->getTexture(e->text);
@ -545,6 +539,28 @@ void Hud::drawLuaElements(const v3s16 &camera_offset)
e->offset.Y * m_scale_factor);
client->getMinimap()->drawMinimap(rect);
break; }
case HUD_ELEM_CROSSHAIR: {
// CAMERA_MODE_THIRD_FRONT and HAVE_TOUCHSCREENGUI may disallow crosshairs.
// In the future it may be good to add a feature for Lua HudElements to
// specify CAMERA_MODE and TOUCHSCREEN behavior.
if (!draw_crosshairs)
continue;
if (e->style == 0) {
// Default Crosshair
drawCrosshair(pos, e->align, e->offset, e->scale);
} else if (e->style == 1) {
// Image Crosshair
const video::SColor color(255, 255, 255, 255);
if (pointing_at_object) {
drawImage(pos, e->scale, e->align, e->offset,
tsrc->getTexture(e->text2), color);
} else {
drawImage(pos, e->scale, e->align, e->offset,
tsrc->getTexture(e->text), color);
}
}
break; }
default:
infostream << "Hud::drawLuaElements: ignoring drawform " << e->type
<< " due to unrecognized type" << std::endl;
@ -794,55 +810,71 @@ void Hud::drawHotbar(u16 playeritem)
}
}
void Hud::drawCrosshair()
void Hud::drawImage(const v2s32 &pos, const v2f &scale, const v2f &align, const v2f &offset,
video::ITexture *texture, const video::SColor &color)
{
auto draw_image_crosshair = [this] (video::ITexture *tex) {
core::dimension2di orig_size(tex->getOriginalSize());
// Integer scaling to avoid artifacts, floor instead of round since too
// small looks better than too large in this case.
core::dimension2di scaled_size = orig_size * std::max(std::floor(m_scale_factor), 1.0f);
const video::SColor colors[] = {color, color, color, color};
core::dimension2di imgsize(texture->getOriginalSize());
v2s32 dstsize(imgsize.Width * scale.X * m_scale_factor,
imgsize.Height * scale.Y * m_scale_factor);
if (scale.X < 0)
dstsize.X = m_screensize.X * (scale.X * -0.01);
if (scale.Y < 0)
dstsize.Y = m_screensize.Y * (scale.Y * -0.01);
v2s32 align_offset((align.X - 1.0) * dstsize.X / 2, (align.Y - 1.0) * dstsize.Y / 2);
core::rect<s32> src_rect(orig_size);
core::position2d pos(m_displaycenter.X - scaled_size.Width / 2,
m_displaycenter.Y - scaled_size.Height / 2);
core::rect<s32> dest_rect(pos, scaled_size);
core::rect<s32> rect(0, 0, dstsize.X, dstsize.Y);
rect += pos + align_offset + v2s32(offset.X * m_scale_factor, offset.Y * m_scale_factor);
video::SColor colors[] = { crosshair_argb, crosshair_argb,
crosshair_argb, crosshair_argb };
draw2DImageFilterScaled(driver, tex, dest_rect, src_rect,
nullptr, colors, true);
};
draw2DImageFilterScaled(driver, texture, rect,
core::rect<s32>(core::position2d<s32>(0,0),imgsize),
NULL, colors, true);
}
void Hud::drawCrosshair(const v2s32 &pos, const v2f &align, const v2f &offset, const v2f &scale)
{
if (pointing_at_object) {
if (use_object_crosshair_image) {
draw_image_crosshair(tsrc->getTexture("object_crosshair.png"));
drawImage(pos, scale, align, offset,
tsrc->getTexture("object_crosshair.png"), crosshair_argb);
} else {
s32 line_size = core::round32(OBJECT_CROSSHAIR_LINE_SIZE * m_scale_factor);
s32 line_size_x = core::round32(m_scale_factor * OBJECT_CROSSHAIR_LINE_SIZE * scale.X);
s32 line_size_y = core::round32(m_scale_factor * OBJECT_CROSSHAIR_LINE_SIZE * scale.Y);
v2s32 center_pos(
pos.X + offset.X*m_scale_factor + align.X * line_size_x,
pos.Y + offset.Y*m_scale_factor + align.Y * line_size_y);
driver->draw2DLine(
m_displaycenter - v2s32(line_size, line_size),
m_displaycenter + v2s32(line_size, line_size),
center_pos - v2s32(line_size_x, line_size_y),
center_pos + v2s32(line_size_x, line_size_y),
crosshair_argb);
driver->draw2DLine(
m_displaycenter + v2s32(line_size, -line_size),
m_displaycenter + v2s32(-line_size, line_size),
center_pos + v2s32(line_size_x, -line_size_y),
center_pos + v2s32(-line_size_x, line_size_y),
crosshair_argb);
}
return;
}
if (use_crosshair_image) {
draw_image_crosshair(tsrc->getTexture("crosshair.png"));
drawImage(pos, scale, align, offset,
tsrc->getTexture("crosshair.png"), crosshair_argb);
} else {
s32 line_size = core::round32(CROSSHAIR_LINE_SIZE * m_scale_factor);
s32 line_size_x = core::round32(m_scale_factor * CROSSHAIR_LINE_SIZE * scale.X);
s32 line_size_y = core::round32(m_scale_factor * CROSSHAIR_LINE_SIZE * scale.Y);
driver->draw2DLine(m_displaycenter - v2s32(line_size, 0),
m_displaycenter + v2s32(line_size, 0), crosshair_argb);
driver->draw2DLine(m_displaycenter - v2s32(0, line_size),
m_displaycenter + v2s32(0, line_size), crosshair_argb);
v2s32 center_pos(
pos.X + offset.X*m_scale_factor + align.X * line_size_x,
pos.Y + offset.Y*m_scale_factor + align.Y * line_size_y);
driver->draw2DLine(
center_pos - v2s32(line_size_x, 0),
center_pos + v2s32(line_size_x, 0),
crosshair_argb);
driver->draw2DLine(
center_pos - v2s32(0, line_size_y),
center_pos + v2s32(0, line_size_y),
crosshair_argb);
}
}

View File

@ -64,9 +64,11 @@ public:
void disableBlockBounds();
void drawBlockBounds();
void drawImage(const v2s32 &pos, const v2f &scale, const v2f &align, const v2f &offset,
video::ITexture *texture, const video::SColor &color);
void drawHotbar(u16 playeritem);
void resizeHotbar();
void drawCrosshair();
void drawCrosshair(const v2s32 &pos, const v2f &align, const v2f &offset, const v2f &scale);
void drawSelectionMesh();
void updateSelectionMesh(const v3s16 &camera_offset);
@ -92,7 +94,7 @@ public:
bool hasElementOfType(HudElementType type);
void drawLuaElements(const v3s16 &camera_offset);
void drawLuaElements(const v3s16 &camera_offset, bool draw_crosshairs);
private:
bool calculateScreenPos(const v3s16 &camera_offset, HudElement *e, v2s32 *pos);

View File

@ -37,13 +37,13 @@ RenderingCore::~RenderingCore()
}
void RenderingCore::draw(video::SColor _skycolor, bool _show_hud,
bool _draw_wield_tool, bool _draw_crosshair)
bool _draw_wield_tool, bool _draw_crosshairs)
{
v2u32 screensize = device->getVideoDriver()->getScreenSize();
virtual_size = v2u32(screensize.X * virtual_size_scale.X, screensize.Y * virtual_size_scale.Y);
PipelineContext context(device, client, hud, shadow_renderer, _skycolor, screensize);
context.draw_crosshair = _draw_crosshair;
context.draw_crosshairs = _draw_crosshairs;
context.draw_wield_tool = _draw_wield_tool;
context.show_hud = _show_hud;

View File

@ -54,7 +54,7 @@ public:
RenderingCore &operator=(RenderingCore &&) = delete;
void draw(video::SColor _skycolor, bool _show_hud,
bool _draw_wield_tool, bool _draw_crosshair);
bool _draw_wield_tool, bool _draw_crosshairs);
v2u32 getVirtualSize() const;

View File

@ -47,7 +47,7 @@ struct PipelineContext
bool show_hud {true};
bool draw_wield_tool {true};
bool draw_crosshair {true};
bool draw_crosshairs {true};
};
/**

View File

@ -57,12 +57,9 @@ void DrawHUD::run(PipelineContext &context)
context.shadow_renderer->drawDebug();
context.hud->resizeHotbar();
if (context.draw_crosshair)
context.hud->drawCrosshair();
context.hud->drawHotbar(context.client->getEnv().getLocalPlayer()->getWieldIndex());
context.hud->drawLuaElements(context.client->getCamera()->getOffset());
context.hud->drawLuaElements(context.client->getCamera()->getOffset(),
context.draw_crosshairs);
context.client->getCamera()->drawNametags();
}
context.device->getGUIEnvironment()->drawAll();

View File

@ -412,9 +412,9 @@ void RenderingEngine::finalize()
}
void RenderingEngine::draw_scene(video::SColor skycolor, bool show_hud,
bool draw_wield_tool, bool draw_crosshair)
bool draw_wield_tool, bool draw_crosshairs)
{
core->draw(skycolor, show_hud, draw_wield_tool, draw_crosshair);
core->draw(skycolor, show_hud, draw_wield_tool, draw_crosshairs);
}
const VideoDriverInfo &RenderingEngine::getVideoDriverInfo(irr::video::E_DRIVER_TYPE type)

View File

@ -142,7 +142,7 @@ public:
float dtime = 0, int percent = 0, bool sky = true);
void draw_scene(video::SColor skycolor, bool show_hud,
bool draw_wield_tool, bool draw_crosshair);
bool draw_wield_tool, bool draw_crosshairs);
void initialize(Client *client, Hud *hud);
void finalize();

View File

@ -30,6 +30,7 @@ const struct EnumString es_HudElementType[] =
{HUD_ELEM_IMAGE_WAYPOINT, "image_waypoint"},
{HUD_ELEM_COMPASS, "compass"},
{HUD_ELEM_MINIMAP, "minimap"},
{HUD_ELEM_CROSSHAIR, "crosshair"},
{0, NULL},
};

View File

@ -67,7 +67,8 @@ enum HudElementType {
HUD_ELEM_WAYPOINT = 4,
HUD_ELEM_IMAGE_WAYPOINT = 5,
HUD_ELEM_COMPASS = 6,
HUD_ELEM_MINIMAP = 7
HUD_ELEM_MINIMAP = 7,
HUD_ELEM_CROSSHAIR = 8,
};
enum HudElementStat : u8 {

View File

@ -222,7 +222,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
PROTOCOL VERSION 44:
AO_CMD_SET_BONE_POSITION extended
Add TOCLIENT_MOVE_PLAYER_REL
Move default minimap from client-side C++ to server-side builtin Lua
Move default minimap and crosshair from client-side C++ to server-side builtin Lua
[scheduled bump for 5.9.0]
*/