mirror of
https://github.com/luanti-org/luanti.git
synced 2025-06-27 16:36:03 +00:00
Merge 3a607c545c
into 81d62d01d1
This commit is contained in:
commit
1d1972e39c
4 changed files with 75 additions and 22 deletions
|
@ -647,6 +647,9 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data):
|
|||
|
||||
m_bounding_radius = std::sqrt(collector.m_bounding_radius_sq);
|
||||
|
||||
// Using the current time avoids flickering before animate() gets called
|
||||
auto animation_time = client->getAnimationTime();
|
||||
|
||||
for (int layer = 0; layer < MAX_TILE_LAYERS; layer++) {
|
||||
scene::SMesh *mesh = static_cast<scene::SMesh *>(m_mesh[layer].get());
|
||||
|
||||
|
@ -657,9 +660,39 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data):
|
|||
p.applyTileColor();
|
||||
|
||||
// Generate animation data
|
||||
// - Cracks
|
||||
if (p.layer.material_flags & MATERIAL_FLAG_CRACK) {
|
||||
// Find the texture name plus ^[crack:N:
|
||||
if (p.layer.material_flags & MATERIAL_FLAG_ANIMATION) {
|
||||
if (p.layer.material_flags & MATERIAL_FLAG_CRACK) {
|
||||
// - Texture animation with crack
|
||||
std::vector<std::string> crack_frames{p.layer.frames->size()};
|
||||
for (std::size_t j = 0; j < p.layer.frames->size(); j++) {
|
||||
std::ostringstream os(std::ios::binary);
|
||||
os << m_tsrc->getTextureName((*p.layer.frames)[j].texture_id) << "^[crack";
|
||||
if (p.layer.material_flags & MATERIAL_FLAG_CRACK_OVERLAY)
|
||||
os << "o"; // use ^[cracko
|
||||
os << ":" << 1 << ":";
|
||||
|
||||
crack_frames[j] = os.str();
|
||||
}
|
||||
AnimationInfo animation_info = AnimationInfo(p.layer);
|
||||
animation_info.needUpdate(animation_time); // Update current frame
|
||||
// Replace tile texture with the cracked animated one
|
||||
p.layer.texture = m_tsrc->getTextureForMesh(
|
||||
crack_frames[animation_info.getCurrentFrame()] + "0",
|
||||
&p.layer.texture_id);
|
||||
|
||||
m_animation_info_crack.emplace(std::make_pair(layer, i),
|
||||
std::make_pair(std::move(animation_info), std::move(crack_frames)));
|
||||
} else {
|
||||
// - Texture animation
|
||||
AnimationInfo animation_info = AnimationInfo(p.layer);
|
||||
animation_info.needUpdate(animation_time); // Update current frame
|
||||
// Replace tile texture with the current animation frame
|
||||
p.layer.texture = (*p.layer.frames)[animation_info.getCurrentFrame()].texture;
|
||||
// Add to MapBlockMesh in order to animate these tiles
|
||||
m_animation_info.emplace(std::make_pair(layer, i), std::move(animation_info));
|
||||
}
|
||||
} else if (p.layer.material_flags & MATERIAL_FLAG_CRACK) {
|
||||
// - Cracks
|
||||
std::ostringstream os(std::ios::binary);
|
||||
os << m_tsrc->getTextureName(p.layer.texture_id) << "^[crack";
|
||||
if (p.layer.material_flags & MATERIAL_FLAG_CRACK_OVERLAY)
|
||||
|
@ -675,13 +708,6 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data):
|
|||
os.str() + "0",
|
||||
&p.layer.texture_id);
|
||||
}
|
||||
// - Texture animation
|
||||
if (p.layer.material_flags & MATERIAL_FLAG_ANIMATION) {
|
||||
// Add to MapBlockMesh in order to animate these tiles
|
||||
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;
|
||||
}
|
||||
|
||||
// Create material
|
||||
video::SMaterial material;
|
||||
|
@ -731,7 +757,8 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data):
|
|||
// Check if animation is required for this mesh
|
||||
m_has_animation =
|
||||
!m_crack_materials.empty() ||
|
||||
!m_animation_info.empty();
|
||||
!m_animation_info.empty() ||
|
||||
!m_animation_info_crack.empty();
|
||||
}
|
||||
|
||||
MapBlockMesh::~MapBlockMesh()
|
||||
|
@ -761,12 +788,6 @@ 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);
|
||||
|
||||
|
@ -777,8 +798,6 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack,
|
|||
m_tsrc->getTextureForMesh(s, &new_texture_id);
|
||||
buf->getMaterial().setTexture(0, new_texture);
|
||||
}
|
||||
|
||||
m_last_crack = crack;
|
||||
}
|
||||
|
||||
// Texture animation
|
||||
|
@ -788,6 +807,20 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack,
|
|||
it.second.updateTexture(material, time);
|
||||
}
|
||||
|
||||
// Texture animation with crack
|
||||
for (auto &it : m_animation_info_crack) {
|
||||
if (crack != m_last_crack || it.second.first.needUpdate(time)) {
|
||||
scene::IMeshBuffer *buf = m_mesh[it.first.first]->getMeshBuffer(it.first.second);
|
||||
|
||||
u16 frame = it.second.first.getCurrentFrame();
|
||||
std::string s = it.second.second[frame] + itos(crack);
|
||||
u32 new_texture_id = 0;
|
||||
video::ITexture *new_texture = m_tsrc->getTextureForMesh(s, &new_texture_id);
|
||||
buf->getMaterial().setTexture(0, new_texture);
|
||||
}
|
||||
}
|
||||
|
||||
m_last_crack = crack;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -266,10 +266,15 @@ private:
|
|||
std::map<std::pair<u8, u32>, std::string> m_crack_materials;
|
||||
|
||||
// Animation info: texture animation
|
||||
// Maps mesh and mesh buffer indices to TileSpecs
|
||||
// Maps mesh and mesh buffer indices to AnimationInfo
|
||||
// Keys are pairs of (mesh index, buffer index in the mesh)
|
||||
std::map<std::pair<u8, u32>, AnimationInfo> m_animation_info;
|
||||
|
||||
// Same as above, but in the case both are needed, animation and crack
|
||||
// The vector contains base crack textures for each animation frame
|
||||
std::map<std::pair<u8, u32>, std::pair<AnimationInfo, std::vector<std::string>>>
|
||||
m_animation_info_crack;
|
||||
|
||||
// list of all semitransparent triangles in the mapblock
|
||||
std::vector<MeshTriangle> m_transparent_triangles;
|
||||
// Binary Space Partitioning tree for the block
|
||||
|
|
|
@ -6,15 +6,23 @@
|
|||
#include <cassert>
|
||||
|
||||
void AnimationInfo::updateTexture(video::SMaterial &material, float animation_time)
|
||||
{
|
||||
if (needUpdate(animation_time)) {
|
||||
assert(m_frame < m_frames->size());
|
||||
material.setTexture(0, (*m_frames)[m_frame].texture);
|
||||
}
|
||||
};
|
||||
|
||||
bool AnimationInfo::needUpdate(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);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
void TileLayer::applyMaterialOptions(video::SMaterial &material, int layer) const
|
||||
|
|
|
@ -164,6 +164,13 @@ struct AnimationInfo {
|
|||
|
||||
void updateTexture(video::SMaterial &material, float animation_time);
|
||||
|
||||
// Returns true if texture needs to be updated
|
||||
// Also proceeds to next frame if update is needed
|
||||
bool needUpdate(float animation_time);
|
||||
|
||||
// Returns last used frame
|
||||
u16 getCurrentFrame() const { return m_frame; };
|
||||
|
||||
private:
|
||||
u16 m_frame = 0; // last animation frame
|
||||
u16 m_frame_length_ms = 0;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue