Skip to content

Commit f6a33a1

Browse files
juhdanadnerzhul
authored andcommitted
Overlays for wield and inventory images (#6107)
* Overlays for wield and inventory images
1 parent 6761e21 commit f6a33a1

File tree

6 files changed

+135
-51
lines changed

6 files changed

+135
-51
lines changed

doc/lua_api.txt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -588,7 +588,11 @@ other. This allows different hardware coloring, but also means that
588588
tiles with overlays are drawn slower. Using too much overlays might
589589
cause FPS loss.
590590

591-
To define an overlay, simply set the `overlay_tiles` field of the node
591+
For inventory and wield images you can specify overlays which
592+
hardware coloring does not modify. You have to set `inventory_overlay`
593+
and `wield_overlay` fields to an image name.
594+
595+
To define a node overlay, simply set the `overlay_tiles` field of the node
592596
definition. These tiles are defined in the same way as plain tiles:
593597
they can have a texture name, color etc.
594598
To skip one face, set that overlay tile to an empty string.
@@ -4146,7 +4150,9 @@ Definition tables
41464150
{bendy = 2, snappy = 1},
41474151
{hard = 1, metal = 1, spikes = 1}
41484152
inventory_image = "default_tool_steelaxe.png",
4153+
inventory_overlay = "overlay.png", -- an overlay which does not get colorized
41494154
wield_image = "",
4155+
wield_overlay = "",
41504156
palette = "",
41514157
--[[
41524158
^ An image file containing the palette of a node.

src/itemdef.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,9 @@ ItemDefinition& ItemDefinition::operator=(const ItemDefinition &def)
6767
name = def.name;
6868
description = def.description;
6969
inventory_image = def.inventory_image;
70+
inventory_overlay = def.inventory_overlay;
7071
wield_image = def.wield_image;
72+
wield_overlay = def.wield_overlay;
7173
wield_scale = def.wield_scale;
7274
stack_max = def.stack_max;
7375
usable = def.usable;
@@ -105,7 +107,9 @@ void ItemDefinition::reset()
105107
name = "";
106108
description = "";
107109
inventory_image = "";
110+
inventory_overlay = "";
108111
wield_image = "";
112+
wield_overlay = "";
109113
palette_image = "";
110114
color = video::SColor(0xFFFFFFFF);
111115
wield_scale = v3f(1.0, 1.0, 1.0);
@@ -159,6 +163,8 @@ void ItemDefinition::serialize(std::ostream &os, u16 protocol_version) const
159163
if (version >= 4) {
160164
writeF1000(os, sound_place.pitch);
161165
writeF1000(os, sound_place_failed.pitch);
166+
os << serializeString(inventory_overlay);
167+
os << serializeString(wield_overlay);
162168
}
163169
}
164170

@@ -222,6 +228,8 @@ void ItemDefinition::deSerialize(std::istream &is)
222228
if (version >= 4) {
223229
sound_place.pitch = readF1000(is);
224230
sound_place_failed.pitch = readF1000(is);
231+
inventory_overlay = deSerializeString(is);
232+
wield_overlay = deSerializeString(is);
225233
}
226234
} catch(SerializationError &e) {};
227235
}

src/itemdef.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,9 @@ struct ItemDefinition
6060
Visual properties
6161
*/
6262
std::string inventory_image; // Optional for nodes, mandatory for tools/craftitems
63+
std::string inventory_overlay; // Overlay of inventory_image.
6364
std::string wield_image; // If empty, inventory_image or mesh (only nodes) is used
65+
std::string wield_overlay; // Overlay of wield_image.
6466
std::string palette_image; // If specified, the item will be colorized based on this
6567
video::SColor color; // The fallback color of the node.
6668
v3f wield_scale;

src/script/common/c_content.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@ void read_item_definition(lua_State* L, int index,
5656
getstringfield(L, index, "name", def.name);
5757
getstringfield(L, index, "description", def.description);
5858
getstringfield(L, index, "inventory_image", def.inventory_image);
59+
getstringfield(L, index, "inventory_overlay", def.inventory_overlay);
5960
getstringfield(L, index, "wield_image", def.wield_image);
61+
getstringfield(L, index, "wield_overlay", def.wield_overlay);
6062
getstringfield(L, index, "palette", def.palette_image);
6163

6264
// Read item color.
@@ -142,8 +144,12 @@ void push_item_definition_full(lua_State *L, const ItemDefinition &i)
142144
lua_setfield(L, -2, "type");
143145
lua_pushstring(L, i.inventory_image.c_str());
144146
lua_setfield(L, -2, "inventory_image");
147+
lua_pushstring(L, i.inventory_overlay.c_str());
148+
lua_setfield(L, -2, "inventory_overlay");
145149
lua_pushstring(L, i.wield_image.c_str());
146150
lua_setfield(L, -2, "wield_image");
151+
lua_pushstring(L, i.wield_overlay.c_str());
152+
lua_setfield(L, -2, "wield_overlay");
147153
lua_pushstring(L, i.palette_image.c_str());
148154
lua_setfield(L, -2, "palette_image");
149155
push_ARGB8(L, i.color);

src/wieldmesh.cpp

Lines changed: 108 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -240,50 +240,63 @@ void WieldMeshSceneNode::setCube(const ContentFeatures &f,
240240
}
241241

242242
void WieldMeshSceneNode::setExtruded(const std::string &imagename,
243-
v3f wield_scale, ITextureSource *tsrc, u8 num_frames)
243+
const std::string &overlay_name, v3f wield_scale, ITextureSource *tsrc,
244+
u8 num_frames)
244245
{
245246
video::ITexture *texture = tsrc->getTexture(imagename);
246247
if (!texture) {
247248
changeToMesh(nullptr);
248249
return;
249250
}
251+
video::ITexture *overlay_texture =
252+
overlay_name.empty() ? NULL : tsrc->getTexture(overlay_name);
250253

251254
core::dimension2d<u32> dim = texture->getSize();
252255
// Detect animation texture and pull off top frame instead of using entire thing
253256
if (num_frames > 1) {
254257
u32 frame_height = dim.Height / num_frames;
255258
dim = core::dimension2d<u32>(dim.Width, frame_height);
256259
}
257-
scene::IMesh *mesh = g_extrusion_mesh_cache->create(dim);
258-
scene::SMesh *copy = cloneMesh(mesh);
260+
scene::IMesh *original = g_extrusion_mesh_cache->create(dim);
261+
scene::SMesh *mesh = cloneMesh(original);
262+
original->drop();
263+
//set texture
264+
mesh->getMeshBuffer(0)->getMaterial().setTexture(0,
265+
tsrc->getTexture(imagename));
266+
if (overlay_texture) {
267+
scene::IMeshBuffer *copy = cloneMeshBuffer(mesh->getMeshBuffer(0));
268+
copy->getMaterial().setTexture(0, overlay_texture);
269+
mesh->addMeshBuffer(copy);
270+
copy->drop();
271+
}
272+
changeToMesh(mesh);
259273
mesh->drop();
260-
changeToMesh(copy);
261-
copy->drop();
262274

263275
m_meshnode->setScale(wield_scale * WIELD_SCALE_FACTOR_EXTRUDED);
264276

265-
// Customize material
266-
video::SMaterial &material = m_meshnode->getMaterial(0);
267-
material.setTexture(0, tsrc->getTextureForMesh(imagename));
268-
material.TextureLayer[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE;
269-
material.TextureLayer[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE;
270-
material.MaterialType = m_material_type;
271-
material.setFlag(video::EMF_BACK_FACE_CULLING, true);
272-
// Enable bi/trilinear filtering only for high resolution textures
273-
if (dim.Width > 32) {
274-
material.setFlag(video::EMF_BILINEAR_FILTER, m_bilinear_filter);
275-
material.setFlag(video::EMF_TRILINEAR_FILTER, m_trilinear_filter);
276-
} else {
277-
material.setFlag(video::EMF_BILINEAR_FILTER, false);
278-
material.setFlag(video::EMF_TRILINEAR_FILTER, false);
279-
}
280-
material.setFlag(video::EMF_ANISOTROPIC_FILTER, m_anisotropic_filter);
281-
// mipmaps cause "thin black line" artifacts
277+
// Customize materials
278+
for (u32 layer = 0; layer < m_meshnode->getMaterialCount(); layer++) {
279+
video::SMaterial &material = m_meshnode->getMaterial(layer);
280+
material.TextureLayer[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE;
281+
material.TextureLayer[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE;
282+
material.MaterialType = m_material_type;
283+
material.setFlag(video::EMF_BACK_FACE_CULLING, true);
284+
// Enable bi/trilinear filtering only for high resolution textures
285+
if (dim.Width > 32) {
286+
material.setFlag(video::EMF_BILINEAR_FILTER, m_bilinear_filter);
287+
material.setFlag(video::EMF_TRILINEAR_FILTER, m_trilinear_filter);
288+
} else {
289+
material.setFlag(video::EMF_BILINEAR_FILTER, false);
290+
material.setFlag(video::EMF_TRILINEAR_FILTER, false);
291+
}
292+
material.setFlag(video::EMF_ANISOTROPIC_FILTER, m_anisotropic_filter);
293+
// mipmaps cause "thin black line" artifacts
282294
#if (IRRLICHT_VERSION_MAJOR >= 1 && IRRLICHT_VERSION_MINOR >= 8) || IRRLICHT_VERSION_MAJOR >= 2
283-
material.setFlag(video::EMF_USE_MIP_MAPS, false);
295+
material.setFlag(video::EMF_USE_MIP_MAPS, false);
284296
#endif
285-
if (m_enable_shaders) {
286-
material.setTexture(2, tsrc->getShaderFlagsTexture(false));
297+
if (m_enable_shaders) {
298+
material.setTexture(2, tsrc->getShaderFlagsTexture(false));
299+
}
287300
}
288301
}
289302

@@ -308,8 +321,11 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client)
308321

309322
// If wield_image is defined, it overrides everything else
310323
if (!def.wield_image.empty()) {
311-
setExtruded(def.wield_image, def.wield_scale, tsrc, 1);
324+
setExtruded(def.wield_image, def.wield_overlay, def.wield_scale, tsrc,
325+
1);
312326
m_colors.emplace_back();
327+
// overlay is white, if present
328+
m_colors.emplace_back(true, video::SColor(0xFFFFFFFF));
313329
return;
314330
}
315331

@@ -335,14 +351,23 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client)
335351
}
336352
case NDT_PLANTLIKE: {
337353
setExtruded(tsrc->getTextureName(f.tiles[0].layers[0].texture_id),
354+
tsrc->getTextureName(f.tiles[0].layers[1].texture_id),
338355
def.wield_scale, tsrc,
339356
f.tiles[0].layers[0].animation_frame_count);
357+
// Add color
358+
const TileLayer &l0 = f.tiles[0].layers[0];
359+
m_colors.emplace_back(l0.has_color, l0.color);
360+
const TileLayer &l1 = f.tiles[0].layers[1];
361+
m_colors.emplace_back(l1.has_color, l1.color);
340362
break;
341363
}
342364
case NDT_PLANTLIKE_ROOTED: {
343365
setExtruded(tsrc->getTextureName(f.special_tiles[0].layers[0].texture_id),
344-
def.wield_scale, tsrc,
366+
"", def.wield_scale, tsrc,
345367
f.special_tiles[0].layers[0].animation_frame_count);
368+
// Add color
369+
const TileLayer &l0 = f.special_tiles[0].layers[0];
370+
m_colors.emplace_back(l0.has_color, l0.color);
346371
break;
347372
}
348373
case NDT_NORMAL:
@@ -376,10 +401,12 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client)
376401
}
377402
return;
378403
}
379-
380-
if (!def.inventory_image.empty()) {
381-
setExtruded(def.inventory_image, def.wield_scale, tsrc, 1);
404+
else if (!def.inventory_image.empty()) {
405+
setExtruded(def.inventory_image, def.inventory_overlay, def.wield_scale,
406+
tsrc, 1);
382407
m_colors.emplace_back();
408+
// overlay is white, if present
409+
m_colors.emplace_back(true, video::SColor(0xFFFFFFFF));
383410
return;
384411
}
385412

@@ -456,24 +483,38 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result)
456483

457484
// If inventory_image is defined, it overrides everything else
458485
if (!def.inventory_image.empty()) {
459-
mesh = getExtrudedMesh(tsrc, def.inventory_image);
486+
mesh = getExtrudedMesh(tsrc, def.inventory_image,
487+
def.inventory_overlay);
460488
result->buffer_colors.emplace_back();
489+
// overlay is white, if present
490+
result->buffer_colors.emplace_back(true, video::SColor(0xFFFFFFFF));
461491
// Items with inventory images do not need shading
462492
result->needs_shading = false;
463493
} else if (def.type == ITEM_NODE) {
464494
if (f.mesh_ptr[0]) {
465495
mesh = cloneMesh(f.mesh_ptr[0]);
466496
scaleMesh(mesh, v3f(0.12, 0.12, 0.12));
497+
postProcessNodeMesh(mesh, f, false, false, nullptr,
498+
&result->buffer_colors);
467499
} else {
468500
switch (f.drawtype) {
469501
case NDT_PLANTLIKE: {
470502
mesh = getExtrudedMesh(tsrc,
471-
tsrc->getTextureName(f.tiles[0].layers[0].texture_id));
503+
tsrc->getTextureName(f.tiles[0].layers[0].texture_id),
504+
tsrc->getTextureName(f.tiles[0].layers[1].texture_id));
505+
// Add color
506+
const TileLayer &l0 = f.tiles[0].layers[0];
507+
result->buffer_colors.emplace_back(l0.has_color, l0.color);
508+
const TileLayer &l1 = f.tiles[0].layers[1];
509+
result->buffer_colors.emplace_back(l1.has_color, l1.color);
472510
break;
473511
}
474512
case NDT_PLANTLIKE_ROOTED: {
475513
mesh = getExtrudedMesh(tsrc,
476-
tsrc->getTextureName(f.special_tiles[0].layers[0].texture_id));
514+
tsrc->getTextureName(f.special_tiles[0].layers[0].texture_id), "");
515+
// Add color
516+
const TileLayer &l0 = f.special_tiles[0].layers[0];
517+
result->buffer_colors.emplace_back(l0.has_color, l0.color);
477518
break;
478519
}
479520
case NDT_NORMAL:
@@ -484,6 +525,9 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result)
484525
mesh = cloneMesh(cube);
485526
cube->drop();
486527
scaleMesh(mesh, v3f(1.2, 1.2, 1.2));
528+
// add overlays
529+
postProcessNodeMesh(mesh, f, false, false, nullptr,
530+
&result->buffer_colors);
487531
break;
488532
}
489533
default: {
@@ -507,6 +551,10 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result)
507551
material1.setTexture(3, material2.getTexture(3));
508552
material1.MaterialType = material2.MaterialType;
509553
}
554+
// add overlays (since getMesh() returns
555+
// the base layer only)
556+
postProcessNodeMesh(mesh, f, false, false, nullptr,
557+
&result->buffer_colors);
510558
}
511559
}
512560
}
@@ -524,36 +572,49 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result)
524572

525573
rotateMeshXZby(mesh, -45);
526574
rotateMeshYZby(mesh, -30);
527-
528-
postProcessNodeMesh(mesh, f, false, false, nullptr, &result->buffer_colors);
529575
}
530576
result->mesh = mesh;
531577
}
532578

533579

534580

535-
scene::SMesh *getExtrudedMesh(ITextureSource *tsrc, const std::string &imagename)
581+
scene::SMesh *getExtrudedMesh(ITextureSource *tsrc,
582+
const std::string &imagename, const std::string &overlay_name)
536583
{
584+
// check textures
537585
video::ITexture *texture = tsrc->getTextureForMesh(imagename);
538586
if (!texture) {
539-
return nullptr;
587+
return NULL;
540588
}
589+
video::ITexture *overlay_texture =
590+
(overlay_name.empty()) ? NULL : tsrc->getTexture(overlay_name);
541591

592+
// get mesh
542593
core::dimension2d<u32> dim = texture->getSize();
543594
scene::IMesh *original = g_extrusion_mesh_cache->create(dim);
544595
scene::SMesh *mesh = cloneMesh(original);
545596
original->drop();
546597

547-
// Customize material
548-
video::SMaterial &material = mesh->getMeshBuffer(0)->getMaterial();
549-
material.setTexture(0, tsrc->getTexture(imagename));
550-
material.TextureLayer[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE;
551-
material.TextureLayer[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE;
552-
material.setFlag(video::EMF_BILINEAR_FILTER, false);
553-
material.setFlag(video::EMF_TRILINEAR_FILTER, false);
554-
material.setFlag(video::EMF_BACK_FACE_CULLING, true);
555-
material.setFlag(video::EMF_LIGHTING, false);
556-
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
598+
//set texture
599+
mesh->getMeshBuffer(0)->getMaterial().setTexture(0,
600+
tsrc->getTexture(imagename));
601+
if (overlay_texture) {
602+
scene::IMeshBuffer *copy = cloneMeshBuffer(mesh->getMeshBuffer(0));
603+
copy->getMaterial().setTexture(0, overlay_texture);
604+
mesh->addMeshBuffer(copy);
605+
copy->drop();
606+
}
607+
// Customize materials
608+
for (u32 layer = 0; layer < mesh->getMeshBufferCount(); layer++) {
609+
video::SMaterial &material = mesh->getMeshBuffer(layer)->getMaterial();
610+
material.TextureLayer[0].TextureWrapU = video::ETC_CLAMP_TO_EDGE;
611+
material.TextureLayer[0].TextureWrapV = video::ETC_CLAMP_TO_EDGE;
612+
material.setFlag(video::EMF_BILINEAR_FILTER, false);
613+
material.setFlag(video::EMF_TRILINEAR_FILTER, false);
614+
material.setFlag(video::EMF_BACK_FACE_CULLING, true);
615+
material.setFlag(video::EMF_LIGHTING, false);
616+
material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
617+
}
557618
scaleMesh(mesh, v3f(2.0, 2.0, 2.0));
558619

559620
return mesh;

src/wieldmesh.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,8 @@ class WieldMeshSceneNode : public scene::ISceneNode
7878
virtual ~WieldMeshSceneNode();
7979

8080
void setCube(const ContentFeatures &f, v3f wield_scale);
81-
void setExtruded(const std::string &imagename, v3f wield_scale,
82-
ITextureSource *tsrc, u8 num_frames);
81+
void setExtruded(const std::string &imagename, const std::string &overlay_image,
82+
v3f wield_scale, ITextureSource *tsrc, u8 num_frames);
8383
void setItem(const ItemStack &item, Client *client);
8484

8585
// Sets the vertex color of the wield mesh.
@@ -125,7 +125,8 @@ class WieldMeshSceneNode : public scene::ISceneNode
125125

126126
void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result);
127127

128-
scene::SMesh *getExtrudedMesh(ITextureSource *tsrc, const std::string &imagename);
128+
scene::SMesh *getExtrudedMesh(ITextureSource *tsrc, const std::string &imagename,
129+
const std::string &overlay_name);
129130

130131
/*!
131132
* Applies overlays, textures and optionally materials to the given mesh and

0 commit comments

Comments
 (0)