mirror of
				https://github.com/luanti-org/luanti.git
				synced 2025-11-04 01:05:48 +01:00 
			
		
		
		
	Draw node animation for items (#15930)
This commit is contained in:
		@@ -134,7 +134,8 @@ void Camera::step(f32 dtime)
 | 
			
		||||
 | 
			
		||||
	if (m_wield_change_timer >= 0 && was_under_zero) {
 | 
			
		||||
		m_wieldnode->setItem(m_wield_item_next, m_client);
 | 
			
		||||
		m_wieldnode->setNodeLightColor(m_player_light_color);
 | 
			
		||||
		m_wieldnode->setLightColorAndAnimation(m_player_light_color,
 | 
			
		||||
				m_client->getAnimationTime());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (m_view_bobbing_state != 0)
 | 
			
		||||
@@ -537,7 +538,8 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 tool_reload_ratio)
 | 
			
		||||
	m_wieldnode->setRotation(wield_rotation);
 | 
			
		||||
 | 
			
		||||
	m_player_light_color = player->light_color;
 | 
			
		||||
	m_wieldnode->setNodeLightColor(m_player_light_color);
 | 
			
		||||
	m_wieldnode->setLightColorAndAnimation(m_player_light_color,
 | 
			
		||||
			m_client->getAnimationTime());
 | 
			
		||||
 | 
			
		||||
	// Set render distance
 | 
			
		||||
	updateViewingRange();
 | 
			
		||||
 
 | 
			
		||||
@@ -809,7 +809,8 @@ void GenericCAO::setNodeLight(const video::SColor &light_color)
 | 
			
		||||
{
 | 
			
		||||
	if (m_prop.visual == OBJECTVISUAL_WIELDITEM || m_prop.visual == OBJECTVISUAL_ITEM) {
 | 
			
		||||
		if (m_wield_meshnode)
 | 
			
		||||
			m_wield_meshnode->setNodeLightColor(light_color);
 | 
			
		||||
			m_wield_meshnode->setLightColorAndAnimation(light_color,
 | 
			
		||||
					m_client->getAnimationTime());
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -678,9 +678,7 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data):
 | 
			
		||||
			// - Texture animation
 | 
			
		||||
			if (p.layer.material_flags & MATERIAL_FLAG_ANIMATION) {
 | 
			
		||||
				// Add to MapBlockMesh in order to animate these tiles
 | 
			
		||||
				auto &info = m_animation_info[{layer, i}];
 | 
			
		||||
				info.tile = p.layer;
 | 
			
		||||
				info.frame = 0;
 | 
			
		||||
				m_animation_info.emplace(std::make_pair(layer, i), AnimationInfo(p.layer));
 | 
			
		||||
				// Replace tile texture with the first animation frame
 | 
			
		||||
				p.layer.texture = (*p.layer.frames)[0].texture;
 | 
			
		||||
			}
 | 
			
		||||
@@ -763,6 +761,12 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack,
 | 
			
		||||
	// Cracks
 | 
			
		||||
	if (crack != m_last_crack) {
 | 
			
		||||
		for (auto &crack_material : m_crack_materials) {
 | 
			
		||||
 | 
			
		||||
			// TODO crack on animated tiles does not work
 | 
			
		||||
			auto anim_it = m_animation_info.find(crack_material.first);
 | 
			
		||||
			if (anim_it != m_animation_info.end())
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			scene::IMeshBuffer *buf = m_mesh[crack_material.first.first]->
 | 
			
		||||
				getMeshBuffer(crack_material.first.second);
 | 
			
		||||
 | 
			
		||||
@@ -772,16 +776,6 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack,
 | 
			
		||||
			video::ITexture *new_texture =
 | 
			
		||||
					m_tsrc->getTextureForMesh(s, &new_texture_id);
 | 
			
		||||
			buf->getMaterial().setTexture(0, new_texture);
 | 
			
		||||
 | 
			
		||||
			// If the current material is also animated, update animation info
 | 
			
		||||
			auto anim_it = m_animation_info.find(crack_material.first);
 | 
			
		||||
			if (anim_it != m_animation_info.end()) {
 | 
			
		||||
				TileLayer &tile = anim_it->second.tile;
 | 
			
		||||
				tile.texture = new_texture;
 | 
			
		||||
				tile.texture_id = new_texture_id;
 | 
			
		||||
				// force animation update
 | 
			
		||||
				anim_it->second.frame = -1;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		m_last_crack = crack;
 | 
			
		||||
@@ -789,20 +783,9 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack,
 | 
			
		||||
 | 
			
		||||
	// Texture animation
 | 
			
		||||
	for (auto &it : m_animation_info) {
 | 
			
		||||
		const TileLayer &tile = it.second.tile;
 | 
			
		||||
		// Figure out current frame
 | 
			
		||||
		int frameno = (int)(time * 1000 / tile.animation_frame_length_ms) %
 | 
			
		||||
			tile.animation_frame_count;
 | 
			
		||||
		// If frame doesn't change, skip
 | 
			
		||||
		if (frameno == it.second.frame)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		it.second.frame = frameno;
 | 
			
		||||
 | 
			
		||||
		scene::IMeshBuffer *buf = m_mesh[it.first.first]->getMeshBuffer(it.first.second);
 | 
			
		||||
 | 
			
		||||
		const FrameSpec &frame = (*tile.frames)[frameno];
 | 
			
		||||
		buf->getMaterial().setTexture(0, frame.texture);
 | 
			
		||||
		video::SMaterial &material = buf->getMaterial();
 | 
			
		||||
		it.second.updateTexture(material, time);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return true;
 | 
			
		||||
 
 | 
			
		||||
@@ -246,10 +246,6 @@ public:
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	struct AnimationInfo {
 | 
			
		||||
		int frame; // last animation frame
 | 
			
		||||
		TileLayer tile;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	irr_ptr<scene::IMesh> m_mesh[MAX_TILE_LAYERS];
 | 
			
		||||
	std::vector<MinimapMapblock*> m_minimap_mapblocks;
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,19 @@
 | 
			
		||||
// Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
 | 
			
		||||
 | 
			
		||||
#include "tile.h"
 | 
			
		||||
#include <cassert>
 | 
			
		||||
 | 
			
		||||
void AnimationInfo::updateTexture(video::SMaterial &material, float animation_time)
 | 
			
		||||
{
 | 
			
		||||
	// Figure out current frame
 | 
			
		||||
	u16 frame = (u16)(animation_time * 1000 / m_frame_length_ms) % m_frame_count;
 | 
			
		||||
	// Only adjust if frame changed
 | 
			
		||||
	if (frame != m_frame) {
 | 
			
		||||
		m_frame = frame;
 | 
			
		||||
		assert(m_frame < m_frames->size());
 | 
			
		||||
		material.setTexture(0, (*m_frames)[m_frame].texture);
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void TileLayer::applyMaterialOptions(video::SMaterial &material, int layer) const
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -151,6 +151,28 @@ struct TileLayer
 | 
			
		||||
	bool has_color = false;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Stores information for drawing an animated tile
 | 
			
		||||
struct AnimationInfo {
 | 
			
		||||
 | 
			
		||||
	AnimationInfo() = default;
 | 
			
		||||
 | 
			
		||||
	AnimationInfo(const TileLayer &tile) :
 | 
			
		||||
			m_frame_length_ms(tile.animation_frame_length_ms),
 | 
			
		||||
			m_frame_count(tile.animation_frame_count),
 | 
			
		||||
			m_frames(tile.frames)
 | 
			
		||||
	{};
 | 
			
		||||
 | 
			
		||||
	void updateTexture(video::SMaterial &material, float animation_time);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	u16 m_frame = 0; // last animation frame
 | 
			
		||||
	u16 m_frame_length_ms = 0;
 | 
			
		||||
	u16 m_frame_count = 1;
 | 
			
		||||
 | 
			
		||||
	/// @note not owned by this struct
 | 
			
		||||
	std::vector<FrameSpec> *m_frames = nullptr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum class TileRotation: u8 {
 | 
			
		||||
	None,
 | 
			
		||||
	R90,
 | 
			
		||||
 
 | 
			
		||||
@@ -30,6 +30,14 @@
 | 
			
		||||
#define MIN_EXTRUSION_MESH_RESOLUTION 16
 | 
			
		||||
#define MAX_EXTRUSION_MESH_RESOLUTION 512
 | 
			
		||||
 | 
			
		||||
ItemMeshBufferInfo::ItemMeshBufferInfo(const TileLayer &layer) :
 | 
			
		||||
		override_color(layer.color),
 | 
			
		||||
		override_color_set(layer.has_color),
 | 
			
		||||
		animation_info((layer.material_flags & MATERIAL_FLAG_ANIMATION) ?
 | 
			
		||||
			std::make_unique<AnimationInfo>(layer) :
 | 
			
		||||
			nullptr)
 | 
			
		||||
{}
 | 
			
		||||
 | 
			
		||||
static scene::IMesh *createExtrusionMesh(int resolution_x, int resolution_y)
 | 
			
		||||
{
 | 
			
		||||
	const f32 r = 0.5;
 | 
			
		||||
@@ -285,7 +293,7 @@ void WieldMeshSceneNode::setExtruded(const std::string &imagename,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static scene::SMesh *createGenericNodeMesh(Client *client, MapNode n,
 | 
			
		||||
	std::vector<ItemPartColor> *colors, const ContentFeatures &f)
 | 
			
		||||
	std::vector<ItemMeshBufferInfo> *buffer_info, const ContentFeatures &f)
 | 
			
		||||
{
 | 
			
		||||
	n.setParam1(0xff);
 | 
			
		||||
	if (n.getParam2()) {
 | 
			
		||||
@@ -309,7 +317,7 @@ static scene::SMesh *createGenericNodeMesh(Client *client, MapNode n,
 | 
			
		||||
		MapblockMeshGenerator(&mmd, &collector).generate();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	colors->clear();
 | 
			
		||||
	buffer_info->clear();
 | 
			
		||||
	scene::SMesh *mesh = new scene::SMesh();
 | 
			
		||||
	for (int layer = 0; layer < MAX_TILE_LAYERS; layer++) {
 | 
			
		||||
		auto &prebuffers = collector.prebuffers[layer];
 | 
			
		||||
@@ -329,7 +337,7 @@ static scene::SMesh *createGenericNodeMesh(Client *client, MapNode n,
 | 
			
		||||
			p.layer.applyMaterialOptions(buf->Material, layer);
 | 
			
		||||
 | 
			
		||||
			mesh->addMeshBuffer(buf.get());
 | 
			
		||||
			colors->emplace_back(p.layer.has_color, p.layer.color);
 | 
			
		||||
			buffer_info->emplace_back(p.layer);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	mesh->recalculateBoundingBox();
 | 
			
		||||
@@ -352,7 +360,7 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che
 | 
			
		||||
	m_material_type = shdrsrc->getShaderInfo(shader_id).material;
 | 
			
		||||
 | 
			
		||||
	// Color-related
 | 
			
		||||
	m_colors.clear();
 | 
			
		||||
	m_buffer_info.clear();
 | 
			
		||||
	m_base_color = idef->getItemstackColor(item, client);
 | 
			
		||||
 | 
			
		||||
	const std::string wield_image = item.getWieldImage(idef);
 | 
			
		||||
@@ -361,11 +369,10 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che
 | 
			
		||||
 | 
			
		||||
	// If wield_image needs to be checked and is defined, it overrides everything else
 | 
			
		||||
	if (!wield_image.empty() && check_wield_image) {
 | 
			
		||||
		setExtruded(wield_image, wield_overlay, wield_scale, tsrc,
 | 
			
		||||
			1);
 | 
			
		||||
		m_colors.emplace_back();
 | 
			
		||||
		setExtruded(wield_image, wield_overlay, wield_scale, tsrc, 1);
 | 
			
		||||
		m_buffer_info.emplace_back();
 | 
			
		||||
		// overlay is white, if present
 | 
			
		||||
		m_colors.emplace_back(true, video::SColor(0xFFFFFFFF));
 | 
			
		||||
		m_buffer_info.emplace_back(true, video::SColor(0xFFFFFFFF));
 | 
			
		||||
		// initialize the color
 | 
			
		||||
		setColor(video::SColor(0xFFFFFFFF));
 | 
			
		||||
		return;
 | 
			
		||||
@@ -394,8 +401,8 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che
 | 
			
		||||
				wscale, tsrc,
 | 
			
		||||
				l0.animation_frame_count);
 | 
			
		||||
			// Add color
 | 
			
		||||
			m_colors.emplace_back(l0.has_color, l0.color);
 | 
			
		||||
			m_colors.emplace_back(l1.has_color, l1.color);
 | 
			
		||||
			m_buffer_info.emplace_back(l0.has_color, l0.color);
 | 
			
		||||
			m_buffer_info.emplace_back(l1.has_color, l1.color);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		case NDT_PLANTLIKE_ROOTED: {
 | 
			
		||||
@@ -404,7 +411,7 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che
 | 
			
		||||
			setExtruded(tsrc->getTextureName(l0.texture_id),
 | 
			
		||||
				"", wield_scale, tsrc,
 | 
			
		||||
				l0.animation_frame_count);
 | 
			
		||||
			m_colors.emplace_back(l0.has_color, l0.color);
 | 
			
		||||
			m_buffer_info.emplace_back(l0.has_color, l0.color);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		default: {
 | 
			
		||||
@@ -413,7 +420,7 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che
 | 
			
		||||
			if (def.place_param2)
 | 
			
		||||
				n.setParam2(*def.place_param2);
 | 
			
		||||
 | 
			
		||||
			mesh = createGenericNodeMesh(client, n, &m_colors, f);
 | 
			
		||||
			mesh = createGenericNodeMesh(client, n, &m_buffer_info, f);
 | 
			
		||||
			changeToMesh(mesh);
 | 
			
		||||
			mesh->drop();
 | 
			
		||||
			m_meshnode->setScale(
 | 
			
		||||
@@ -447,9 +454,9 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che
 | 
			
		||||
			setExtruded("no_texture.png", "", def.wield_scale, tsrc, 1);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		m_colors.emplace_back();
 | 
			
		||||
		m_buffer_info.emplace_back();
 | 
			
		||||
		// overlay is white, if present
 | 
			
		||||
		m_colors.emplace_back(true, video::SColor(0xFFFFFFFF));
 | 
			
		||||
		m_buffer_info.emplace_back(true, video::SColor(0xFFFFFFFF));
 | 
			
		||||
 | 
			
		||||
		// initialize the color
 | 
			
		||||
		setColor(video::SColor(0xFFFFFFFF));
 | 
			
		||||
@@ -471,33 +478,38 @@ void WieldMeshSceneNode::setColor(video::SColor c)
 | 
			
		||||
	u8 blue = c.getBlue();
 | 
			
		||||
 | 
			
		||||
	const u32 mc = mesh->getMeshBufferCount();
 | 
			
		||||
	if (mc > m_colors.size())
 | 
			
		||||
		m_colors.resize(mc);
 | 
			
		||||
	if (mc > m_buffer_info.size())
 | 
			
		||||
		m_buffer_info.resize(mc);
 | 
			
		||||
	for (u32 j = 0; j < mc; j++) {
 | 
			
		||||
		video::SColor bc(m_base_color);
 | 
			
		||||
		m_colors[j].applyOverride(bc);
 | 
			
		||||
		m_buffer_info[j].applyOverride(bc);
 | 
			
		||||
		video::SColor buffercolor(255,
 | 
			
		||||
			bc.getRed() * red / 255,
 | 
			
		||||
			bc.getGreen() * green / 255,
 | 
			
		||||
			bc.getBlue() * blue / 255);
 | 
			
		||||
		scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
 | 
			
		||||
 | 
			
		||||
		if (m_colors[j].needColorize(buffercolor)) {
 | 
			
		||||
		if (m_buffer_info[j].needColorize(buffercolor)) {
 | 
			
		||||
			buf->setDirty(scene::EBT_VERTEX);
 | 
			
		||||
			setMeshBufferColor(buf, buffercolor);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WieldMeshSceneNode::setNodeLightColor(video::SColor color)
 | 
			
		||||
void WieldMeshSceneNode::setLightColorAndAnimation(video::SColor color, float animation_time)
 | 
			
		||||
{
 | 
			
		||||
	if (!m_meshnode)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	{
 | 
			
		||||
		for (u32 i = 0; i < m_meshnode->getMaterialCount(); ++i) {
 | 
			
		||||
			video::SMaterial &material = m_meshnode->getMaterial(i);
 | 
			
		||||
			material.ColorParam = color;
 | 
			
		||||
	for (u32 i = 0; i < m_meshnode->getMaterialCount(); ++i) {
 | 
			
		||||
		// Color
 | 
			
		||||
		video::SMaterial &material = m_meshnode->getMaterial(i);
 | 
			
		||||
		material.ColorParam = color;
 | 
			
		||||
 | 
			
		||||
		// Animation
 | 
			
		||||
		const ItemMeshBufferInfo &buf_info = m_buffer_info[i];
 | 
			
		||||
		if (buf_info.animation_info) {
 | 
			
		||||
			buf_info.animation_info->updateTexture(material, animation_time);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -544,9 +556,9 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result)
 | 
			
		||||
	const std::string inventory_overlay = item.getInventoryOverlay(idef);
 | 
			
		||||
	if (!inventory_image.empty()) {
 | 
			
		||||
		mesh = getExtrudedMesh(tsrc, inventory_image, inventory_overlay);
 | 
			
		||||
		result->buffer_colors.emplace_back();
 | 
			
		||||
		result->buffer_info.emplace_back();
 | 
			
		||||
		// overlay is white, if present
 | 
			
		||||
		result->buffer_colors.emplace_back(true, video::SColor(0xFFFFFFFF));
 | 
			
		||||
		result->buffer_info.emplace_back(true, video::SColor(0xFFFFFFFF));
 | 
			
		||||
		// Items with inventory images do not need shading
 | 
			
		||||
		result->needs_shading = false;
 | 
			
		||||
	} else if (def.type == ITEM_NODE && f.drawtype == NDT_AIRLIKE) {
 | 
			
		||||
@@ -562,8 +574,8 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result)
 | 
			
		||||
				tsrc->getTextureName(l0.texture_id),
 | 
			
		||||
				tsrc->getTextureName(l1.texture_id));
 | 
			
		||||
			// Add color
 | 
			
		||||
			result->buffer_colors.emplace_back(l0.has_color, l0.color);
 | 
			
		||||
			result->buffer_colors.emplace_back(l1.has_color, l1.color);
 | 
			
		||||
			result->buffer_info.emplace_back(l0.has_color, l0.color);
 | 
			
		||||
			result->buffer_info.emplace_back(l1.has_color, l1.color);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		case NDT_PLANTLIKE_ROOTED: {
 | 
			
		||||
@@ -571,7 +583,7 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result)
 | 
			
		||||
			const TileLayer &l0 = f.special_tiles[0].layers[0];
 | 
			
		||||
			mesh = getExtrudedMesh(tsrc,
 | 
			
		||||
				tsrc->getTextureName(l0.texture_id), "");
 | 
			
		||||
			result->buffer_colors.emplace_back(l0.has_color, l0.color);
 | 
			
		||||
			result->buffer_info.emplace_back(l0.has_color, l0.color);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		default: {
 | 
			
		||||
@@ -580,7 +592,7 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result)
 | 
			
		||||
			if (def.place_param2)
 | 
			
		||||
				n.setParam2(*def.place_param2);
 | 
			
		||||
 | 
			
		||||
			mesh = createGenericNodeMesh(client, n, &result->buffer_colors, f);
 | 
			
		||||
			mesh = createGenericNodeMesh(client, n, &result->buffer_info, f);
 | 
			
		||||
			scaleMesh(mesh, v3f(0.12, 0.12, 0.12));
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,8 @@
 | 
			
		||||
#include <EMaterialTypes.h>
 | 
			
		||||
#include <IMeshSceneNode.h>
 | 
			
		||||
#include <SColor.h>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include "tile.h"
 | 
			
		||||
 | 
			
		||||
namespace irr::scene
 | 
			
		||||
{
 | 
			
		||||
@@ -28,9 +30,10 @@ struct ContentFeatures;
 | 
			
		||||
class ShadowRenderer;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Holds color information of an item mesh's buffer.
 | 
			
		||||
 * Holds information of an item mesh's buffer.
 | 
			
		||||
 * Used for coloring and animation.
 | 
			
		||||
 */
 | 
			
		||||
class ItemPartColor
 | 
			
		||||
class ItemMeshBufferInfo
 | 
			
		||||
{
 | 
			
		||||
	/*
 | 
			
		||||
	 * Optional color that overrides the global base color.
 | 
			
		||||
@@ -47,12 +50,14 @@ class ItemPartColor
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
	ItemPartColor() = default;
 | 
			
		||||
	ItemMeshBufferInfo() = default;
 | 
			
		||||
 | 
			
		||||
	ItemPartColor(bool override, video::SColor color) :
 | 
			
		||||
	ItemMeshBufferInfo(bool override, video::SColor color) :
 | 
			
		||||
		override_color(color), override_color_set(override)
 | 
			
		||||
	{}
 | 
			
		||||
 | 
			
		||||
	ItemMeshBufferInfo(const TileLayer &layer);
 | 
			
		||||
 | 
			
		||||
	void applyOverride(video::SColor &dest) const {
 | 
			
		||||
		if (override_color_set)
 | 
			
		||||
			dest = override_color;
 | 
			
		||||
@@ -65,15 +70,18 @@ public:
 | 
			
		||||
		last_colorized = target;
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Null for no animated parts
 | 
			
		||||
	std::unique_ptr<AnimationInfo> animation_info;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ItemMesh
 | 
			
		||||
{
 | 
			
		||||
	scene::IMesh *mesh = nullptr;
 | 
			
		||||
	/*
 | 
			
		||||
	 * Stores the color of each mesh buffer.
 | 
			
		||||
	 * Stores draw information of each mesh buffer.
 | 
			
		||||
	 */
 | 
			
		||||
	std::vector<ItemPartColor> buffer_colors;
 | 
			
		||||
	std::vector<ItemMeshBufferInfo> buffer_info;
 | 
			
		||||
	/*
 | 
			
		||||
	 * If false, all faces of the item should have the same brightness.
 | 
			
		||||
	 * Disables shading based on normal vectors.
 | 
			
		||||
@@ -101,7 +109,7 @@ public:
 | 
			
		||||
	// Must only be used if the constructor was called with lighting = false
 | 
			
		||||
	void setColor(video::SColor color);
 | 
			
		||||
 | 
			
		||||
	void setNodeLightColor(video::SColor color);
 | 
			
		||||
	void setLightColorAndAnimation(video::SColor color, float animation_time);
 | 
			
		||||
 | 
			
		||||
	scene::IMesh *getMesh() { return m_meshnode->getMesh(); }
 | 
			
		||||
 | 
			
		||||
@@ -120,10 +128,10 @@ private:
 | 
			
		||||
	bool m_bilinear_filter;
 | 
			
		||||
	bool m_trilinear_filter;
 | 
			
		||||
	/*!
 | 
			
		||||
	 * Stores the colors of the mesh's mesh buffers.
 | 
			
		||||
	 * Stores the colors and animation data of the mesh's mesh buffers.
 | 
			
		||||
	 * This does not include lighting.
 | 
			
		||||
	 */
 | 
			
		||||
	std::vector<ItemPartColor> m_colors;
 | 
			
		||||
	std::vector<ItemMeshBufferInfo> m_buffer_info;
 | 
			
		||||
	/*!
 | 
			
		||||
	 * The base color of this mesh. This is the default
 | 
			
		||||
	 * for all mesh buffers.
 | 
			
		||||
 
 | 
			
		||||
@@ -118,13 +118,13 @@ void drawItemStack(
 | 
			
		||||
			client->idef()->getItemstackColor(item, client);
 | 
			
		||||
 | 
			
		||||
		const u32 mc = mesh->getMeshBufferCount();
 | 
			
		||||
		if (mc > imesh->buffer_colors.size())
 | 
			
		||||
			imesh->buffer_colors.resize(mc);
 | 
			
		||||
		if (mc > imesh->buffer_info.size())
 | 
			
		||||
			imesh->buffer_info.resize(mc);
 | 
			
		||||
		for (u32 j = 0; j < mc; ++j) {
 | 
			
		||||
			scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
 | 
			
		||||
			video::SColor c = basecolor;
 | 
			
		||||
 | 
			
		||||
			auto &p = imesh->buffer_colors[j];
 | 
			
		||||
			auto &p = imesh->buffer_info[j];
 | 
			
		||||
			p.applyOverride(c);
 | 
			
		||||
 | 
			
		||||
			// TODO: could be moved to a shader
 | 
			
		||||
@@ -137,6 +137,12 @@ void drawItemStack(
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			video::SMaterial &material = buf->getMaterial();
 | 
			
		||||
 | 
			
		||||
			// Texture animation
 | 
			
		||||
			if (p.animation_info) {
 | 
			
		||||
				p.animation_info->updateTexture(material, client->getAnimationTime());
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
 | 
			
		||||
			driver->setMaterial(material);
 | 
			
		||||
			driver->drawMeshBuffer(buf);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user