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