1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-06-27 16:36:03 +00:00

Hardware coloring for itemstacks

Adds the possibility to colorize item stacks based on their metadata.

In the item/node definition you can specify palette (an image file)
and color (fallback color if the item has no palette or metadata).
Then you can add palette_index to the metadata.

Dropped itemstacks with different colors do not merge.
This commit is contained in:
Dániel Juhász 2017-03-10 18:25:58 +01:00 committed by Auke Kok
parent d4e9dd4643
commit 58d83a7bb2
23 changed files with 308 additions and 139 deletions

View file

@ -786,6 +786,8 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
tiledef_special[j].backface_culling, material_type);
}
palette = tsrc->getPalette(palette_name);
if ((drawtype == NDT_MESH) && (mesh != "")) {
// Meshnode drawtype
// Read the mesh and apply scale
@ -859,9 +861,6 @@ public:
virtual void removeNode(const std::string &name);
virtual void updateAliases(IItemDefManager *idef);
virtual void applyTextureOverrides(const std::string &override_filepath);
//! Returns a palette or NULL if not found. Only on client.
std::vector<video::SColor> *getPalette(const ContentFeatures &f,
const IGameDef *gamedef);
virtual void updateTextures(IGameDef *gamedef,
void (*progress_cbk)(void *progress_args, u32 progress, u32 max_progress),
void *progress_cbk_args);
@ -910,9 +909,6 @@ private:
// Next possibly free id
content_t m_next_id;
// Maps image file names to loaded palettes.
UNORDERED_MAP<std::string, std::vector<video::SColor> > m_palettes;
// NodeResolvers to callback once node registration has ended
std::vector<NodeResolver *> m_pending_resolve_callbacks;
@ -1401,78 +1397,6 @@ void CNodeDefManager::applyTextureOverrides(const std::string &override_filepath
}
}
std::vector<video::SColor> *CNodeDefManager::getPalette(
const ContentFeatures &f, const IGameDef *gamedef)
{
#ifndef SERVER
// This works because colors always use the most significant bits
// of param2. If you add a new colored type which uses param2
// in a more advanced way, you should change this code, too.
u32 palette_pixels = 0;
switch (f.param_type_2) {
case CPT2_COLOR:
palette_pixels = 256;
break;
case CPT2_COLORED_FACEDIR:
palette_pixels = 8;
break;
case CPT2_COLORED_WALLMOUNTED:
palette_pixels = 32;
break;
default:
return NULL;
}
// This many param2 values will have the same color
u32 step = 256 / palette_pixels;
const std::string &name = f.palette_name;
if (name == "")
return NULL;
Client *client = (Client *) gamedef;
ITextureSource *tsrc = client->tsrc();
UNORDERED_MAP<std::string, std::vector<video::SColor> >::iterator it =
m_palettes.find(name);
if (it == m_palettes.end()) {
// Create palette
if (!tsrc->isKnownSourceImage(name)) {
warningstream << "CNodeDefManager::getPalette(): palette \"" << name
<< "\" could not be loaded." << std::endl;
return NULL;
}
video::IImage *img = tsrc->generateImage(name);
std::vector<video::SColor> new_palette;
u32 w = img->getDimension().Width;
u32 h = img->getDimension().Height;
// Real area of the image
u32 area = h * w;
if (area != palette_pixels)
warningstream << "CNodeDefManager::getPalette(): the "
<< "specified palette image \"" << name << "\" does not "
<< "contain exactly " << palette_pixels
<< " pixels." << std::endl;
if (area > palette_pixels)
area = palette_pixels;
// For each pixel in the image
for (u32 i = 0; i < area; i++) {
video::SColor c = img->getPixel(i % w, i / w);
// Fill in palette with 'step' colors
for (u32 j = 0; j < step; j++)
new_palette.push_back(c);
}
img->drop();
// Fill in remaining elements
while (new_palette.size() < 256)
new_palette.push_back(video::SColor(0xFFFFFFFF));
m_palettes[name] = new_palette;
it = m_palettes.find(name);
}
if (it != m_palettes.end())
return &((*it).second);
#endif
return NULL;
}
void CNodeDefManager::updateTextures(IGameDef *gamedef,
void (*progress_callback)(void *progress_args, u32 progress, u32 max_progress),
void *progress_callback_args)
@ -1489,12 +1413,10 @@ void CNodeDefManager::updateTextures(IGameDef *gamedef,
TextureSettings tsettings;
tsettings.readSettings();
m_palettes.clear();
u32 size = m_content_features.size();
for (u32 i = 0; i < size; i++) {
ContentFeatures *f = &(m_content_features[i]);
f->palette = getPalette(*f, gamedef);
f->updateTextures(tsrc, shdsrc, meshmanip, client, tsettings);
progress_callback(progress_callback_args, i, size);
}