Node texture animation
parent
f0678979b1
commit
fd1135c7af
|
@ -1124,17 +1124,29 @@ Item definition (register_node, register_craftitem, register_tool)
|
||||||
^ The default functions handle regular use cases.
|
^ The default functions handle regular use cases.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Tile definition:
|
||||||
|
- "image.png"
|
||||||
|
- {name="image.png", animation={Tile Animation definition}}
|
||||||
|
- {name="image.png", backface_culling=bool}
|
||||||
|
^ backface culling only supported in special tiles
|
||||||
|
- deprecated still supported field names:
|
||||||
|
- image -> name
|
||||||
|
|
||||||
|
Tile animation definition:
|
||||||
|
- {type="vertical_frames", aspect_w=16, aspect_h=16, length=3.0}
|
||||||
|
|
||||||
Node definition (register_node)
|
Node definition (register_node)
|
||||||
{
|
{
|
||||||
<all fields allowed in item definitions>,
|
<all fields allowed in item definitions>,
|
||||||
|
|
||||||
drawtype = "normal",
|
drawtype = "normal",
|
||||||
visual_scale = 1.0,
|
visual_scale = 1.0,
|
||||||
tile_images = {"default_unknown_block.png"},
|
tiles = {tile definition 1, def2, def3, def4, def5, def6},
|
||||||
special_materials = {
|
^ List can be shortened to needed length
|
||||||
{image="", backface_culling=true},
|
^ Old field name: tile_images
|
||||||
{image="", backface_culling=true},
|
special_tiles = {tile definition 1, Tile definition 2},
|
||||||
},
|
^ List can be shortened to needed length
|
||||||
|
^ Old field name: special_materials
|
||||||
alpha = 255,
|
alpha = 255,
|
||||||
post_effect_color = {a=0, r=0, g=0, b=0},
|
post_effect_color = {a=0, r=0, g=0, b=0},
|
||||||
paramtype = "none",
|
paramtype = "none",
|
||||||
|
|
|
@ -1040,8 +1040,16 @@ minetest.register_node("default:lava_flowing", {
|
||||||
damage_per_second = 4*2,
|
damage_per_second = 4*2,
|
||||||
post_effect_color = {a=192, r=255, g=64, b=0},
|
post_effect_color = {a=192, r=255, g=64, b=0},
|
||||||
special_materials = {
|
special_materials = {
|
||||||
{image="default_lava.png", backface_culling=false},
|
{
|
||||||
{image="default_lava.png", backface_culling=true},
|
image="default_lava_flowing_animated.png",
|
||||||
|
backface_culling=false,
|
||||||
|
animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=3.3}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
image="default_lava_flowing_animated.png",
|
||||||
|
backface_culling=true,
|
||||||
|
animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=3.3}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
groups = {lava=3, liquid=2, hot=3},
|
groups = {lava=3, liquid=2, hot=3},
|
||||||
})
|
})
|
||||||
|
@ -1050,7 +1058,10 @@ minetest.register_node("default:lava_source", {
|
||||||
description = "Lava",
|
description = "Lava",
|
||||||
inventory_image = minetest.inventorycube("default_lava.png"),
|
inventory_image = minetest.inventorycube("default_lava.png"),
|
||||||
drawtype = "liquid",
|
drawtype = "liquid",
|
||||||
tile_images = {"default_lava.png"},
|
--tile_images = {"default_lava.png"},
|
||||||
|
tile_images = {
|
||||||
|
{name="default_lava_source_animated.png", animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=3.0}}
|
||||||
|
},
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
light_source = LIGHT_MAX - 1,
|
light_source = LIGHT_MAX - 1,
|
||||||
walkable = false,
|
walkable = false,
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 8.5 KiB |
Binary file not shown.
After Width: | Height: | Size: 3.4 KiB |
|
@ -54,6 +54,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
PROTOCOL_VERSION 10:
|
PROTOCOL_VERSION 10:
|
||||||
TOCLIENT_PRIVILEGES
|
TOCLIENT_PRIVILEGES
|
||||||
Version raised to force 'fly' and 'fast' privileges into effect.
|
Version raised to force 'fly' and 'fast' privileges into effect.
|
||||||
|
Node metadata change (came in later; somewhat incompatible)
|
||||||
|
TileDef in ContentFeatures (non-TileDef deserialization is supported)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PROTOCOL_VERSION 10
|
#define PROTOCOL_VERSION 10
|
||||||
|
|
|
@ -471,7 +471,9 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
pa_liquid.x0(), pa_liquid.y0()),
|
pa_liquid.x0(), pa_liquid.y0()),
|
||||||
};
|
};
|
||||||
|
|
||||||
// This fixes a strange bug
|
// To get backface culling right, the vertices need to go
|
||||||
|
// clockwise around the front of the face. And we happened to
|
||||||
|
// calculate corner levels in exact reverse order.
|
||||||
s32 corner_resolve[4] = {3,2,1,0};
|
s32 corner_resolve[4] = {3,2,1,0};
|
||||||
|
|
||||||
for(s32 i=0; i<4; i++)
|
for(s32 i=0; i<4; i++)
|
||||||
|
@ -483,6 +485,52 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
||||||
vertices[i].Pos += intToFloat(p, BS);
|
vertices[i].Pos += intToFloat(p, BS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Default downwards-flowing texture animation goes from
|
||||||
|
// -Z towards +Z, thus the direction is +Z.
|
||||||
|
// Rotate texture to make animation go in flow direction
|
||||||
|
// Positive if liquid moves towards +Z
|
||||||
|
int dz = (corner_levels[side_corners[2][0]] +
|
||||||
|
corner_levels[side_corners[2][1]] <
|
||||||
|
corner_levels[side_corners[3][0]] +
|
||||||
|
corner_levels[side_corners[3][1]]);
|
||||||
|
// Positive if liquid moves towards +X
|
||||||
|
int dx = (corner_levels[side_corners[0][0]] +
|
||||||
|
corner_levels[side_corners[0][1]] <
|
||||||
|
corner_levels[side_corners[1][0]] +
|
||||||
|
corner_levels[side_corners[1][1]]);
|
||||||
|
// -X
|
||||||
|
if(-dx >= abs(dz))
|
||||||
|
{
|
||||||
|
v2f t = vertices[0].TCoords;
|
||||||
|
vertices[0].TCoords = vertices[1].TCoords;
|
||||||
|
vertices[1].TCoords = vertices[2].TCoords;
|
||||||
|
vertices[2].TCoords = vertices[3].TCoords;
|
||||||
|
vertices[3].TCoords = t;
|
||||||
|
}
|
||||||
|
// +X
|
||||||
|
if(dx >= abs(dz))
|
||||||
|
{
|
||||||
|
v2f t = vertices[0].TCoords;
|
||||||
|
vertices[0].TCoords = vertices[3].TCoords;
|
||||||
|
vertices[3].TCoords = vertices[2].TCoords;
|
||||||
|
vertices[2].TCoords = vertices[1].TCoords;
|
||||||
|
vertices[1].TCoords = t;
|
||||||
|
}
|
||||||
|
// -Z
|
||||||
|
if(-dz >= abs(dx))
|
||||||
|
{
|
||||||
|
v2f t = vertices[0].TCoords;
|
||||||
|
vertices[0].TCoords = vertices[3].TCoords;
|
||||||
|
vertices[3].TCoords = vertices[2].TCoords;
|
||||||
|
vertices[2].TCoords = vertices[1].TCoords;
|
||||||
|
vertices[1].TCoords = t;
|
||||||
|
t = vertices[0].TCoords;
|
||||||
|
vertices[0].TCoords = vertices[3].TCoords;
|
||||||
|
vertices[3].TCoords = vertices[2].TCoords;
|
||||||
|
vertices[2].TCoords = vertices[1].TCoords;
|
||||||
|
vertices[1].TCoords = t;
|
||||||
|
}
|
||||||
|
|
||||||
u16 indices[] = {0,1,2,2,3,0};
|
u16 indices[] = {0,1,2,2,3,0};
|
||||||
// Add to mesh collector
|
// Add to mesh collector
|
||||||
collector.append(tile_liquid, vertices, 4, indices, 6);
|
collector.append(tile_liquid, vertices, 4, indices, 6);
|
||||||
|
|
|
@ -2206,7 +2206,7 @@ void the_game(
|
||||||
infotext = narrow_to_wide(meta->getString("infotext"));
|
infotext = narrow_to_wide(meta->getString("infotext"));
|
||||||
} else {
|
} else {
|
||||||
MapNode n = map.getNode(nodepos);
|
MapNode n = map.getNode(nodepos);
|
||||||
if(nodedef->get(n).tname_tiles[0] == "unknown_block.png"){
|
if(nodedef->get(n).tiledef[0].name == "unknown_block.png"){
|
||||||
infotext = L"Unknown node: ";
|
infotext = L"Unknown node: ";
|
||||||
infotext += narrow_to_wide(nodedef->get(n).name);
|
infotext += narrow_to_wide(nodedef->get(n).name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -451,7 +451,7 @@ public:
|
||||||
if(def->inventory_texture == NULL)
|
if(def->inventory_texture == NULL)
|
||||||
{
|
{
|
||||||
def->inventory_texture =
|
def->inventory_texture =
|
||||||
tsrc->getTextureRaw(f.tname_tiles[0]);
|
tsrc->getTextureRaw(f.tiledef[0].name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "gamedef.h"
|
#include "gamedef.h"
|
||||||
#include "mesh.h"
|
#include "mesh.h"
|
||||||
#include "content_mapblock.h"
|
#include "content_mapblock.h"
|
||||||
|
#include "noise.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
MeshMakeData
|
MeshMakeData
|
||||||
|
@ -559,6 +560,11 @@ TileSpec getNodeTileN(MapNode mn, v3s16 p, u8 tileindex, MeshMakeData *data)
|
||||||
spec.material_flags |= MATERIAL_FLAG_CRACK;
|
spec.material_flags |= MATERIAL_FLAG_CRACK;
|
||||||
spec.texture = data->m_gamedef->tsrc()->getTextureRawAP(spec.texture);
|
spec.texture = data->m_gamedef->tsrc()->getTextureRawAP(spec.texture);
|
||||||
}
|
}
|
||||||
|
// If animated, replace tile texture with one without texture atlas
|
||||||
|
if(spec.material_flags & MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES)
|
||||||
|
{
|
||||||
|
spec.texture = data->m_gamedef->tsrc()->getTextureRawAP(spec.texture);
|
||||||
|
}
|
||||||
return spec;
|
return spec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -983,6 +989,23 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data):
|
||||||
crack_basename += "^[crack";
|
crack_basename += "^[crack";
|
||||||
m_crack_materials.insert(std::make_pair(i, crack_basename));
|
m_crack_materials.insert(std::make_pair(i, crack_basename));
|
||||||
}
|
}
|
||||||
|
// - Texture animation
|
||||||
|
if(p.tile.material_flags & MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES)
|
||||||
|
{
|
||||||
|
ITextureSource *tsrc = data->m_gamedef->tsrc();
|
||||||
|
// Add to MapBlockMesh in order to animate these tiles
|
||||||
|
m_animation_tiles[i] = p.tile;
|
||||||
|
m_animation_frames[i] = 0;
|
||||||
|
// Get starting position from noise
|
||||||
|
m_animation_frame_offsets[i] = 100000 * (2.0 + noise3d(
|
||||||
|
data->m_blockpos.X, data->m_blockpos.Y,
|
||||||
|
data->m_blockpos.Z, 0));
|
||||||
|
// Replace tile texture with the first animation frame
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
os<<tsrc->getTextureName(p.tile.texture.id);
|
||||||
|
os<<"^[verticalframe:"<<(int)p.tile.animation_frame_count<<":0";
|
||||||
|
p.tile.texture = tsrc->getTexture(os.str());
|
||||||
|
}
|
||||||
// - Lighting
|
// - Lighting
|
||||||
for(u32 j = 0; j < p.vertices.size(); j++)
|
for(u32 j = 0; j < p.vertices.size(); j++)
|
||||||
{
|
{
|
||||||
|
@ -1055,7 +1078,8 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data):
|
||||||
// Check if animation is required for this mesh
|
// Check if animation is required for this mesh
|
||||||
m_has_animation =
|
m_has_animation =
|
||||||
!m_crack_materials.empty() ||
|
!m_crack_materials.empty() ||
|
||||||
!m_daynight_diffs.empty();
|
!m_daynight_diffs.empty() ||
|
||||||
|
!m_animation_tiles.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
MapBlockMesh::~MapBlockMesh()
|
MapBlockMesh::~MapBlockMesh()
|
||||||
|
@ -1095,6 +1119,34 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack, u32 daynight_rat
|
||||||
m_last_crack = crack;
|
m_last_crack = crack;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Texture animation
|
||||||
|
for(std::map<u32, TileSpec>::iterator
|
||||||
|
i = m_animation_tiles.begin();
|
||||||
|
i != m_animation_tiles.end(); i++)
|
||||||
|
{
|
||||||
|
const TileSpec &tile = i->second;
|
||||||
|
// Figure out current frame
|
||||||
|
int frameoffset = m_animation_frame_offsets[i->first];
|
||||||
|
int frame = (int)(time * 1000 / tile.animation_frame_length_ms
|
||||||
|
+ frameoffset) % tile.animation_frame_count;
|
||||||
|
// If frame doesn't change, skip
|
||||||
|
if(frame == m_animation_frames[i->first])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
m_animation_frames[i->first] = frame;
|
||||||
|
|
||||||
|
scene::IMeshBuffer *buf = m_mesh->getMeshBuffer(i->first);
|
||||||
|
ITextureSource *tsrc = m_gamedef->getTextureSource();
|
||||||
|
|
||||||
|
// Create new texture name from original
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
os<<tsrc->getTextureName(tile.texture.id);
|
||||||
|
os<<"^[verticalframe:"<<(int)tile.animation_frame_count<<":"<<frame;
|
||||||
|
// Set the texture
|
||||||
|
AtlasPointer ap = tsrc->getTexture(os.str());
|
||||||
|
buf->getMaterial().setTexture(0, ap.atlas);
|
||||||
|
}
|
||||||
|
|
||||||
// Day-night transition
|
// Day-night transition
|
||||||
if(daynight_ratio != m_last_daynight_ratio)
|
if(daynight_ratio != m_last_daynight_ratio)
|
||||||
{
|
{
|
||||||
|
|
|
@ -122,6 +122,12 @@ private:
|
||||||
// Maps mesh buffer (i.e. material) indices to base texture names
|
// Maps mesh buffer (i.e. material) indices to base texture names
|
||||||
std::map<u32, std::string> m_crack_materials;
|
std::map<u32, std::string> m_crack_materials;
|
||||||
|
|
||||||
|
// Animation info: texture animationi
|
||||||
|
// Maps meshbuffers to TileSpecs
|
||||||
|
std::map<u32, TileSpec> m_animation_tiles;
|
||||||
|
std::map<u32, int> m_animation_frames; // last animation frame
|
||||||
|
std::map<u32, int> m_animation_frame_offsets;
|
||||||
|
|
||||||
// Animation info: day/night transitions
|
// Animation info: day/night transitions
|
||||||
// Last daynight_ratio value passed to animate()
|
// Last daynight_ratio value passed to animate()
|
||||||
u32 m_last_daynight_ratio;
|
u32 m_last_daynight_ratio;
|
||||||
|
|
143
src/nodedef.cpp
143
src/nodedef.cpp
|
@ -63,19 +63,29 @@ void NodeBox::deSerialize(std::istream &is)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
MaterialSpec
|
TileDef
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void MaterialSpec::serialize(std::ostream &os) const
|
void TileDef::serialize(std::ostream &os) const
|
||||||
{
|
{
|
||||||
os<<serializeString(tname);
|
writeU8(os, 0); // version
|
||||||
writeU8(os, backface_culling);
|
os<<serializeString(name);
|
||||||
|
writeU8(os, animation.type);
|
||||||
|
writeU16(os, animation.aspect_w);
|
||||||
|
writeU16(os, animation.aspect_h);
|
||||||
|
writeF1000(os, animation.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MaterialSpec::deSerialize(std::istream &is)
|
void TileDef::deSerialize(std::istream &is)
|
||||||
{
|
{
|
||||||
tname = deSerializeString(is);
|
int version = readU8(is);
|
||||||
backface_culling = readU8(is);
|
if(version != 0)
|
||||||
|
throw SerializationError("unsupported TileDef version");
|
||||||
|
name = deSerializeString(is);
|
||||||
|
animation.type = (TileAnimationType)readU8(is);
|
||||||
|
animation.aspect_w = readU16(is);
|
||||||
|
animation.aspect_h = readU16(is);
|
||||||
|
animation.length = readF1000(is);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -133,9 +143,9 @@ void ContentFeatures::reset()
|
||||||
drawtype = NDT_NORMAL;
|
drawtype = NDT_NORMAL;
|
||||||
visual_scale = 1.0;
|
visual_scale = 1.0;
|
||||||
for(u32 i=0; i<6; i++)
|
for(u32 i=0; i<6; i++)
|
||||||
tname_tiles[i] = "";
|
tiledef[i] = TileDef();
|
||||||
for(u16 j=0; j<CF_SPECIAL_COUNT; j++)
|
for(u16 j=0; j<CF_SPECIAL_COUNT; j++)
|
||||||
mspec_special[j] = MaterialSpec();
|
tiledef_special[j] = TileDef();
|
||||||
alpha = 255;
|
alpha = 255;
|
||||||
post_effect_color = video::SColor(0, 0, 0, 0);
|
post_effect_color = video::SColor(0, 0, 0, 0);
|
||||||
param_type = CPT_NONE;
|
param_type = CPT_NONE;
|
||||||
|
@ -164,7 +174,7 @@ void ContentFeatures::reset()
|
||||||
|
|
||||||
void ContentFeatures::serialize(std::ostream &os)
|
void ContentFeatures::serialize(std::ostream &os)
|
||||||
{
|
{
|
||||||
writeU8(os, 3); // version
|
writeU8(os, 4); // version
|
||||||
os<<serializeString(name);
|
os<<serializeString(name);
|
||||||
writeU16(os, groups.size());
|
writeU16(os, groups.size());
|
||||||
for(ItemGroupList::const_iterator
|
for(ItemGroupList::const_iterator
|
||||||
|
@ -176,10 +186,10 @@ void ContentFeatures::serialize(std::ostream &os)
|
||||||
writeF1000(os, visual_scale);
|
writeF1000(os, visual_scale);
|
||||||
writeU8(os, 6);
|
writeU8(os, 6);
|
||||||
for(u32 i=0; i<6; i++)
|
for(u32 i=0; i<6; i++)
|
||||||
os<<serializeString(tname_tiles[i]);
|
tiledef[i].serialize(os);
|
||||||
writeU8(os, CF_SPECIAL_COUNT);
|
writeU8(os, CF_SPECIAL_COUNT);
|
||||||
for(u32 i=0; i<CF_SPECIAL_COUNT; i++){
|
for(u32 i=0; i<CF_SPECIAL_COUNT; i++){
|
||||||
mspec_special[i].serialize(os);
|
tiledef_special[i].serialize(os);
|
||||||
}
|
}
|
||||||
writeU8(os, alpha);
|
writeU8(os, alpha);
|
||||||
writeU8(os, post_effect_color.getAlpha());
|
writeU8(os, post_effect_color.getAlpha());
|
||||||
|
@ -214,7 +224,7 @@ void ContentFeatures::serialize(std::ostream &os)
|
||||||
void ContentFeatures::deSerialize(std::istream &is)
|
void ContentFeatures::deSerialize(std::istream &is)
|
||||||
{
|
{
|
||||||
int version = readU8(is);
|
int version = readU8(is);
|
||||||
if(version != 3)
|
if(version != 4 && version != 3)
|
||||||
throw SerializationError("unsupported ContentFeatures version");
|
throw SerializationError("unsupported ContentFeatures version");
|
||||||
name = deSerializeString(is);
|
name = deSerializeString(is);
|
||||||
groups.clear();
|
groups.clear();
|
||||||
|
@ -228,12 +238,21 @@ void ContentFeatures::deSerialize(std::istream &is)
|
||||||
visual_scale = readF1000(is);
|
visual_scale = readF1000(is);
|
||||||
if(readU8(is) != 6)
|
if(readU8(is) != 6)
|
||||||
throw SerializationError("unsupported tile count");
|
throw SerializationError("unsupported tile count");
|
||||||
for(u32 i=0; i<6; i++)
|
for(u32 i=0; i<6; i++){
|
||||||
tname_tiles[i] = deSerializeString(is);
|
if(version == 4)
|
||||||
|
tiledef[i].deSerialize(is);
|
||||||
|
else if(version == 3) // Allow connecting to older servers
|
||||||
|
tiledef[i].name = deSerializeString(is);
|
||||||
|
}
|
||||||
if(readU8(is) != CF_SPECIAL_COUNT)
|
if(readU8(is) != CF_SPECIAL_COUNT)
|
||||||
throw SerializationError("unsupported CF_SPECIAL_COUNT");
|
throw SerializationError("unsupported CF_SPECIAL_COUNT");
|
||||||
for(u32 i=0; i<CF_SPECIAL_COUNT; i++){
|
for(u32 i=0; i<CF_SPECIAL_COUNT; i++){
|
||||||
mspec_special[i].deSerialize(is);
|
if(version == 4){
|
||||||
|
tiledef_special[i].deSerialize(is);
|
||||||
|
} else if(version == 3){ // Allow connecting to older servers
|
||||||
|
tiledef_special[i].name = deSerializeString(is);
|
||||||
|
tiledef_special[i].backface_culling = readU8(is);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
alpha = readU8(is);
|
alpha = readU8(is);
|
||||||
post_effect_color.setAlpha(readU8(is));
|
post_effect_color.setAlpha(readU8(is));
|
||||||
|
@ -260,12 +279,12 @@ void ContentFeatures::deSerialize(std::istream &is)
|
||||||
selection_box.deSerialize(is);
|
selection_box.deSerialize(is);
|
||||||
legacy_facedir_simple = readU8(is);
|
legacy_facedir_simple = readU8(is);
|
||||||
legacy_wallmounted = readU8(is);
|
legacy_wallmounted = readU8(is);
|
||||||
|
deSerializeSimpleSoundSpec(sound_footstep, is);
|
||||||
|
deSerializeSimpleSoundSpec(sound_dig, is);
|
||||||
|
deSerializeSimpleSoundSpec(sound_dug, is);
|
||||||
// If you add anything here, insert it primarily inside the try-catch
|
// If you add anything here, insert it primarily inside the try-catch
|
||||||
// block to not need to increase the version.
|
// block to not need to increase the version.
|
||||||
try{
|
try{
|
||||||
deSerializeSimpleSoundSpec(sound_footstep, is);
|
|
||||||
deSerializeSimpleSoundSpec(sound_dig, is);
|
|
||||||
deSerializeSimpleSoundSpec(sound_dug, is);
|
|
||||||
}catch(SerializationError &e) {};
|
}catch(SerializationError &e) {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -495,13 +514,14 @@ public:
|
||||||
{
|
{
|
||||||
ContentFeatures *f = &m_content_features[i];
|
ContentFeatures *f = &m_content_features[i];
|
||||||
|
|
||||||
std::string tname_tiles[6];
|
// Figure out the actual tiles to use
|
||||||
|
TileDef tiledef[6];
|
||||||
for(u32 j=0; j<6; j++)
|
for(u32 j=0; j<6; j++)
|
||||||
{
|
{
|
||||||
tname_tiles[j] = f->tname_tiles[j];
|
tiledef[j] = f->tiledef[j];
|
||||||
if(tname_tiles[j] == "")
|
if(tiledef[j].name == "")
|
||||||
tname_tiles[j] = "unknown_block.png";
|
tiledef[j].name = "unknown_block.png";
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(f->drawtype){
|
switch(f->drawtype){
|
||||||
default:
|
default:
|
||||||
|
@ -547,7 +567,7 @@ public:
|
||||||
f->drawtype = NDT_NORMAL;
|
f->drawtype = NDT_NORMAL;
|
||||||
f->solidness = 2;
|
f->solidness = 2;
|
||||||
for(u32 i=0; i<6; i++){
|
for(u32 i=0; i<6; i++){
|
||||||
tname_tiles[i] += std::string("^[noalpha");
|
tiledef[i].name += std::string("^[noalpha");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -560,29 +580,92 @@ public:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tile textures
|
// Tiles (fill in f->tiles[])
|
||||||
for(u16 j=0; j<6; j++){
|
for(u16 j=0; j<6; j++){
|
||||||
f->tiles[j].texture = tsrc->getTexture(tname_tiles[j]);
|
// Texture
|
||||||
|
f->tiles[j].texture = tsrc->getTexture(tiledef[j].name);
|
||||||
|
// Alpha
|
||||||
f->tiles[j].alpha = f->alpha;
|
f->tiles[j].alpha = f->alpha;
|
||||||
if(f->alpha == 255)
|
if(f->alpha == 255)
|
||||||
f->tiles[j].material_type = MATERIAL_ALPHA_SIMPLE;
|
f->tiles[j].material_type = MATERIAL_ALPHA_SIMPLE;
|
||||||
else
|
else
|
||||||
f->tiles[j].material_type = MATERIAL_ALPHA_VERTEX;
|
f->tiles[j].material_type = MATERIAL_ALPHA_VERTEX;
|
||||||
|
// Material flags
|
||||||
f->tiles[j].material_flags = 0;
|
f->tiles[j].material_flags = 0;
|
||||||
if(f->backface_culling)
|
if(f->backface_culling)
|
||||||
f->tiles[j].material_flags |= MATERIAL_FLAG_BACKFACE_CULLING;
|
f->tiles[j].material_flags |= MATERIAL_FLAG_BACKFACE_CULLING;
|
||||||
|
if(tiledef[j].animation.type == TAT_VERTICAL_FRAMES)
|
||||||
|
f->tiles[j].material_flags |= MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES;
|
||||||
|
// Animation parameters
|
||||||
|
if(f->tiles[j].material_flags &
|
||||||
|
MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES)
|
||||||
|
{
|
||||||
|
// Get raw texture size to determine frame count by
|
||||||
|
// aspect ratio
|
||||||
|
video::ITexture *t = tsrc->getTextureRaw(tiledef[j].name);
|
||||||
|
v2u32 size = t->getOriginalSize();
|
||||||
|
int frame_height = (float)size.X /
|
||||||
|
(float)tiledef[j].animation.aspect_w *
|
||||||
|
(float)tiledef[j].animation.aspect_h;
|
||||||
|
int frame_count = size.Y / frame_height;
|
||||||
|
int frame_length_ms = 1000.0 *
|
||||||
|
tiledef[j].animation.length / frame_count;
|
||||||
|
f->tiles[j].animation_frame_count = frame_count;
|
||||||
|
f->tiles[j].animation_frame_length_ms = frame_length_ms;
|
||||||
|
|
||||||
|
// If there are no frames for an animation, switch
|
||||||
|
// animation off (so that having specified an animation
|
||||||
|
// for something but not using it in the texture pack
|
||||||
|
// gives no overhead)
|
||||||
|
if(frame_count == 1){
|
||||||
|
f->tiles[j].material_flags &=
|
||||||
|
~MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Special tiles
|
// Special tiles (fill in f->special_tiles[])
|
||||||
for(u16 j=0; j<CF_SPECIAL_COUNT; j++){
|
for(u16 j=0; j<CF_SPECIAL_COUNT; j++){
|
||||||
f->special_tiles[j].texture = tsrc->getTexture(f->mspec_special[j].tname);
|
// Texture
|
||||||
|
f->special_tiles[j].texture =
|
||||||
|
tsrc->getTexture(f->tiledef_special[j].name);
|
||||||
|
// Alpha
|
||||||
f->special_tiles[j].alpha = f->alpha;
|
f->special_tiles[j].alpha = f->alpha;
|
||||||
if(f->alpha == 255)
|
if(f->alpha == 255)
|
||||||
f->special_tiles[j].material_type = MATERIAL_ALPHA_SIMPLE;
|
f->special_tiles[j].material_type = MATERIAL_ALPHA_SIMPLE;
|
||||||
else
|
else
|
||||||
f->special_tiles[j].material_type = MATERIAL_ALPHA_VERTEX;
|
f->special_tiles[j].material_type = MATERIAL_ALPHA_VERTEX;
|
||||||
|
// Material flags
|
||||||
f->special_tiles[j].material_flags = 0;
|
f->special_tiles[j].material_flags = 0;
|
||||||
if(f->mspec_special[j].backface_culling)
|
if(f->tiledef_special[j].backface_culling)
|
||||||
f->special_tiles[j].material_flags |= MATERIAL_FLAG_BACKFACE_CULLING;
|
f->special_tiles[j].material_flags |= MATERIAL_FLAG_BACKFACE_CULLING;
|
||||||
|
if(f->tiledef_special[j].animation.type == TAT_VERTICAL_FRAMES)
|
||||||
|
f->special_tiles[j].material_flags |= MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES;
|
||||||
|
// Animation parameters
|
||||||
|
if(f->special_tiles[j].material_flags &
|
||||||
|
MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES)
|
||||||
|
{
|
||||||
|
// Get raw texture size to determine frame count by
|
||||||
|
// aspect ratio
|
||||||
|
video::ITexture *t = tsrc->getTextureRaw(f->tiledef_special[j].name);
|
||||||
|
v2u32 size = t->getOriginalSize();
|
||||||
|
int frame_height = (float)size.X /
|
||||||
|
(float)f->tiledef_special[j].animation.aspect_w *
|
||||||
|
(float)f->tiledef_special[j].animation.aspect_h;
|
||||||
|
int frame_count = size.Y / frame_height;
|
||||||
|
int frame_length_ms = 1000.0 *
|
||||||
|
f->tiledef_special[j].animation.length / frame_count;
|
||||||
|
f->special_tiles[j].animation_frame_count = frame_count;
|
||||||
|
f->special_tiles[j].animation_frame_length_ms = frame_length_ms;
|
||||||
|
|
||||||
|
// If there are no frames for an animation, switch
|
||||||
|
// animation off (so that having specified an animation
|
||||||
|
// for something but not using it in the texture pack
|
||||||
|
// gives no overhead)
|
||||||
|
if(frame_count == 1){
|
||||||
|
f->special_tiles[j].material_flags &=
|
||||||
|
~MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -95,15 +95,33 @@ struct NodeBox
|
||||||
struct MapNode;
|
struct MapNode;
|
||||||
class NodeMetadata;
|
class NodeMetadata;
|
||||||
|
|
||||||
struct MaterialSpec
|
/*
|
||||||
|
Stand-alone definition of a TileSpec (basically a server-side TileSpec)
|
||||||
|
*/
|
||||||
|
enum TileAnimationType{
|
||||||
|
TAT_NONE=0,
|
||||||
|
TAT_VERTICAL_FRAMES=1,
|
||||||
|
};
|
||||||
|
struct TileDef
|
||||||
{
|
{
|
||||||
std::string tname;
|
std::string name;
|
||||||
bool backface_culling;
|
bool backface_culling; // Takes effect only in special cases
|
||||||
|
struct{
|
||||||
|
enum TileAnimationType type;
|
||||||
|
int aspect_w; // width for aspect ratio
|
||||||
|
int aspect_h; // height for aspect ratio
|
||||||
|
float length; // seconds
|
||||||
|
} animation;
|
||||||
|
|
||||||
MaterialSpec(const std::string &tname_="", bool backface_culling_=true):
|
TileDef()
|
||||||
tname(tname_),
|
{
|
||||||
backface_culling(backface_culling_)
|
name = "";
|
||||||
{}
|
backface_culling = true;
|
||||||
|
animation.type = TAT_NONE;
|
||||||
|
animation.aspect_w = 1;
|
||||||
|
animation.aspect_h = 1;
|
||||||
|
animation.length = 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
void serialize(std::ostream &os) const;
|
void serialize(std::ostream &os) const;
|
||||||
void deSerialize(std::istream &is);
|
void deSerialize(std::istream &is);
|
||||||
|
@ -159,8 +177,8 @@ struct ContentFeatures
|
||||||
// Visual definition
|
// Visual definition
|
||||||
enum NodeDrawType drawtype;
|
enum NodeDrawType drawtype;
|
||||||
float visual_scale; // Misc. scale parameter
|
float visual_scale; // Misc. scale parameter
|
||||||
std::string tname_tiles[6];
|
TileDef tiledef[6];
|
||||||
MaterialSpec mspec_special[CF_SPECIAL_COUNT]; // Use setter methods
|
TileDef tiledef_special[CF_SPECIAL_COUNT]; // eg. flowing liquid
|
||||||
u8 alpha;
|
u8 alpha;
|
||||||
|
|
||||||
// Post effect color, drawn when the camera is inside the node.
|
// Post effect color, drawn when the camera is inside the node.
|
||||||
|
|
|
@ -426,6 +426,13 @@ struct EnumString es_CraftMethod[] =
|
||||||
{0, NULL},
|
{0, NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct EnumString es_TileAnimationType[] =
|
||||||
|
{
|
||||||
|
{TAT_NONE, "none"},
|
||||||
|
{TAT_VERTICAL_FRAMES, "vertical_frames"},
|
||||||
|
{0, NULL},
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
C struct <-> Lua table converter functions
|
C struct <-> Lua table converter functions
|
||||||
*/
|
*/
|
||||||
|
@ -991,6 +998,50 @@ static ItemDefinition read_item_definition(lua_State *L, int index,
|
||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
TileDef
|
||||||
|
*/
|
||||||
|
|
||||||
|
static TileDef read_tiledef(lua_State *L, int index)
|
||||||
|
{
|
||||||
|
if(index < 0)
|
||||||
|
index = lua_gettop(L) + 1 + index;
|
||||||
|
|
||||||
|
TileDef tiledef;
|
||||||
|
|
||||||
|
// key at index -2 and value at index
|
||||||
|
if(lua_isstring(L, index)){
|
||||||
|
// "default_lava.png"
|
||||||
|
tiledef.name = lua_tostring(L, index);
|
||||||
|
}
|
||||||
|
else if(lua_istable(L, index))
|
||||||
|
{
|
||||||
|
// {name="default_lava.png", animation={}}
|
||||||
|
tiledef.name = "";
|
||||||
|
getstringfield(L, index, "name", tiledef.name);
|
||||||
|
getstringfield(L, index, "image", tiledef.name); // MaterialSpec compat.
|
||||||
|
tiledef.backface_culling = getboolfield_default(
|
||||||
|
L, index, "backface_culling", true);
|
||||||
|
// animation = {}
|
||||||
|
lua_getfield(L, index, "animation");
|
||||||
|
if(lua_istable(L, -1)){
|
||||||
|
// {type="vertical_frames", aspect_w=16, aspect_h=16, length=2.0}
|
||||||
|
tiledef.animation.type = (TileAnimationType)
|
||||||
|
getenumfield(L, -1, "type", es_TileAnimationType,
|
||||||
|
TAT_NONE);
|
||||||
|
tiledef.animation.aspect_w =
|
||||||
|
getintfield_default(L, -1, "aspect_w", 16);
|
||||||
|
tiledef.animation.aspect_h =
|
||||||
|
getintfield_default(L, -1, "aspect_h", 16);
|
||||||
|
tiledef.animation.length =
|
||||||
|
getfloatfield_default(L, -1, "length", 1.0);
|
||||||
|
}
|
||||||
|
lua_pop(L, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tiledef;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
ContentFeatures
|
ContentFeatures
|
||||||
*/
|
*/
|
||||||
|
@ -1027,17 +1078,22 @@ static ContentFeatures read_content_features(lua_State *L, int index)
|
||||||
NDT_NORMAL);
|
NDT_NORMAL);
|
||||||
getfloatfield(L, index, "visual_scale", f.visual_scale);
|
getfloatfield(L, index, "visual_scale", f.visual_scale);
|
||||||
|
|
||||||
lua_getfield(L, index, "tile_images");
|
// tiles = {}
|
||||||
|
lua_getfield(L, index, "tiles");
|
||||||
|
// If nil, try the deprecated name "tile_images" instead
|
||||||
|
if(lua_isnil(L, -1)){
|
||||||
|
lua_pop(L, 1);
|
||||||
|
warn_if_field_exists(L, index, "tile_images",
|
||||||
|
"Deprecated; new name is \"tiles\".");
|
||||||
|
lua_getfield(L, index, "tile_images");
|
||||||
|
}
|
||||||
if(lua_istable(L, -1)){
|
if(lua_istable(L, -1)){
|
||||||
int table = lua_gettop(L);
|
int table = lua_gettop(L);
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while(lua_next(L, table) != 0){
|
while(lua_next(L, table) != 0){
|
||||||
// key at index -2 and value at index -1
|
// Read tiledef from value
|
||||||
if(lua_isstring(L, -1))
|
f.tiledef[i] = read_tiledef(L, -1);
|
||||||
f.tname_tiles[i] = lua_tostring(L, -1);
|
|
||||||
else
|
|
||||||
f.tname_tiles[i] = "";
|
|
||||||
// removes value, keeps key for next iteration
|
// removes value, keeps key for next iteration
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
i++;
|
i++;
|
||||||
|
@ -1048,29 +1104,31 @@ static ContentFeatures read_content_features(lua_State *L, int index)
|
||||||
}
|
}
|
||||||
// Copy last value to all remaining textures
|
// Copy last value to all remaining textures
|
||||||
if(i >= 1){
|
if(i >= 1){
|
||||||
std::string lastname = f.tname_tiles[i-1];
|
TileDef lasttile = f.tiledef[i-1];
|
||||||
while(i < 6){
|
while(i < 6){
|
||||||
f.tname_tiles[i] = lastname;
|
f.tiledef[i] = lasttile;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
||||||
lua_getfield(L, index, "special_materials");
|
// special_tiles = {}
|
||||||
|
lua_getfield(L, index, "special_tiles");
|
||||||
|
// If nil, try the deprecated name "special_materials" instead
|
||||||
|
if(lua_isnil(L, -1)){
|
||||||
|
lua_pop(L, 1);
|
||||||
|
warn_if_field_exists(L, index, "special_materials",
|
||||||
|
"Deprecated; new name is \"special_tiles\".");
|
||||||
|
lua_getfield(L, index, "special_materials");
|
||||||
|
}
|
||||||
if(lua_istable(L, -1)){
|
if(lua_istable(L, -1)){
|
||||||
int table = lua_gettop(L);
|
int table = lua_gettop(L);
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while(lua_next(L, table) != 0){
|
while(lua_next(L, table) != 0){
|
||||||
// key at index -2 and value at index -1
|
// Read tiledef from value
|
||||||
int smtable = lua_gettop(L);
|
f.tiledef_special[i] = read_tiledef(L, -1);
|
||||||
std::string tname = getstringfield_default(
|
|
||||||
L, smtable, "image", "");
|
|
||||||
bool backface_culling = getboolfield_default(
|
|
||||||
L, smtable, "backface_culling", true);
|
|
||||||
MaterialSpec mspec(tname, backface_culling);
|
|
||||||
f.mspec_special[i] = mspec;
|
|
||||||
// removes value, keeps key for next iteration
|
// removes value, keeps key for next iteration
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
i++;
|
i++;
|
||||||
|
|
|
@ -80,7 +80,7 @@ void define_some_nodes(IWritableItemDefManager *idef, IWritableNodeDefManager *n
|
||||||
f = ContentFeatures();
|
f = ContentFeatures();
|
||||||
f.name = itemdef.name;
|
f.name = itemdef.name;
|
||||||
for(int i = 0; i < 6; i++)
|
for(int i = 0; i < 6; i++)
|
||||||
f.tname_tiles[i] = "default_stone.png";
|
f.tiledef[i].name = "default_stone.png";
|
||||||
f.is_ground_content = true;
|
f.is_ground_content = true;
|
||||||
idef->registerItem(itemdef);
|
idef->registerItem(itemdef);
|
||||||
ndef->set(i, f);
|
ndef->set(i, f);
|
||||||
|
@ -100,10 +100,10 @@ void define_some_nodes(IWritableItemDefManager *idef, IWritableNodeDefManager *n
|
||||||
"{default_dirt.png&default_grass_side.png";
|
"{default_dirt.png&default_grass_side.png";
|
||||||
f = ContentFeatures();
|
f = ContentFeatures();
|
||||||
f.name = itemdef.name;
|
f.name = itemdef.name;
|
||||||
f.tname_tiles[0] = "default_grass.png";
|
f.tiledef[0].name = "default_grass.png";
|
||||||
f.tname_tiles[1] = "default_dirt.png";
|
f.tiledef[1].name = "default_dirt.png";
|
||||||
for(int i = 2; i < 6; i++)
|
for(int i = 2; i < 6; i++)
|
||||||
f.tname_tiles[i] = "default_dirt.png^default_grass_side.png";
|
f.tiledef[i].name = "default_dirt.png^default_grass_side.png";
|
||||||
f.is_ground_content = true;
|
f.is_ground_content = true;
|
||||||
idef->registerItem(itemdef);
|
idef->registerItem(itemdef);
|
||||||
ndef->set(i, f);
|
ndef->set(i, f);
|
||||||
|
|
46
src/tile.cpp
46
src/tile.cpp
|
@ -858,7 +858,7 @@ void TextureSource::buildMainAtlas(class IGameDef *gamedef)
|
||||||
const ContentFeatures &f = ndef->get(j);
|
const ContentFeatures &f = ndef->get(j);
|
||||||
for(u32 i=0; i<6; i++)
|
for(u32 i=0; i<6; i++)
|
||||||
{
|
{
|
||||||
std::string name = f.tname_tiles[i];
|
std::string name = f.tiledef[i].name;
|
||||||
sourcelist[name] = true;
|
sourcelist[name] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -988,7 +988,7 @@ void TextureSource::buildMainAtlas(class IGameDef *gamedef)
|
||||||
src_x = pos_in_atlas.X;
|
src_x = pos_in_atlas.X;
|
||||||
}
|
}
|
||||||
s32 y = y0 + pos_in_atlas.Y;
|
s32 y = y0 + pos_in_atlas.Y;
|
||||||
s32 src_y = MYMAX(pos_in_atlas.Y, MYMIN(pos_in_atlas.Y + dim.Height - 1, y));
|
s32 src_y = MYMAX((int)pos_in_atlas.Y, MYMIN((int)pos_in_atlas.Y + (int)dim.Height - 1, y));
|
||||||
s32 dst_y = y;
|
s32 dst_y = y;
|
||||||
video::SColor c = atlas_img->getPixel(src_x, src_y);
|
video::SColor c = atlas_img->getPixel(src_x, src_y);
|
||||||
atlas_img->setPixel(dst_x,dst_y,c);
|
atlas_img->setPixel(dst_x,dst_y,c);
|
||||||
|
@ -1638,6 +1638,48 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
|
||||||
img2->drop();
|
img2->drop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
[verticalframe:N:I
|
||||||
|
Crops a frame of a vertical animation.
|
||||||
|
N = frame count, I = frame index
|
||||||
|
*/
|
||||||
|
else if(part_of_name.substr(0,15) == "[verticalframe:")
|
||||||
|
{
|
||||||
|
Strfnd sf(part_of_name);
|
||||||
|
sf.next(":");
|
||||||
|
u32 frame_count = stoi(sf.next(":"));
|
||||||
|
u32 frame_index = stoi(sf.next(":"));
|
||||||
|
|
||||||
|
if(baseimg == NULL){
|
||||||
|
errorstream<<"generate_image(): baseimg!=NULL "
|
||||||
|
<<"for part_of_name=\""<<part_of_name
|
||||||
|
<<"\", cancelling."<<std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
v2u32 frame_size = baseimg->getDimension();
|
||||||
|
frame_size.Y /= frame_count;
|
||||||
|
|
||||||
|
video::IImage *img = driver->createImage(video::ECF_A8R8G8B8,
|
||||||
|
frame_size);
|
||||||
|
if(!img){
|
||||||
|
errorstream<<"generate_image(): Could not create image "
|
||||||
|
<<"for part_of_name=\""<<part_of_name
|
||||||
|
<<"\", cancelling."<<std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
core::dimension2d<u32> dim = frame_size;
|
||||||
|
core::position2d<s32> pos_dst(0, 0);
|
||||||
|
core::position2d<s32> pos_src(0, frame_index * frame_size.Y);
|
||||||
|
baseimg->copyToWithAlpha(img, pos_dst,
|
||||||
|
core::rect<s32>(pos_src, dim),
|
||||||
|
video::SColor(255,255,255,255),
|
||||||
|
NULL);
|
||||||
|
// Replace baseimg
|
||||||
|
baseimg->drop();
|
||||||
|
baseimg = img;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
errorstream<<"generate_image(): Invalid "
|
errorstream<<"generate_image(): Invalid "
|
||||||
|
|
13
src/tile.h
13
src/tile.h
|
@ -162,6 +162,9 @@ enum MaterialType{
|
||||||
// Should the crack be drawn on transparent pixels (unset) or not (set)?
|
// Should the crack be drawn on transparent pixels (unset) or not (set)?
|
||||||
// Ignored if MATERIAL_FLAG_CRACK is not set.
|
// Ignored if MATERIAL_FLAG_CRACK is not set.
|
||||||
#define MATERIAL_FLAG_CRACK_OVERLAY 0x04
|
#define MATERIAL_FLAG_CRACK_OVERLAY 0x04
|
||||||
|
// Animation made up by splitting the texture to vertical frames, as
|
||||||
|
// defined by extra parameters
|
||||||
|
#define MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES 0x08
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This fully defines the looks of a tile.
|
This fully defines the looks of a tile.
|
||||||
|
@ -178,7 +181,9 @@ struct TileSpec
|
||||||
material_flags(
|
material_flags(
|
||||||
//0 // <- DEBUG, Use the one below
|
//0 // <- DEBUG, Use the one below
|
||||||
MATERIAL_FLAG_BACKFACE_CULLING
|
MATERIAL_FLAG_BACKFACE_CULLING
|
||||||
)
|
),
|
||||||
|
animation_frame_count(1),
|
||||||
|
animation_frame_length_ms(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,10 +232,12 @@ struct TileSpec
|
||||||
AtlasPointer texture;
|
AtlasPointer texture;
|
||||||
// Vertex alpha
|
// Vertex alpha
|
||||||
u8 alpha;
|
u8 alpha;
|
||||||
// Material type
|
// Material parameters
|
||||||
u8 material_type;
|
u8 material_type;
|
||||||
// Material flags
|
|
||||||
u8 material_flags;
|
u8 material_flags;
|
||||||
|
// Animation parameters
|
||||||
|
u8 animation_frame_count;
|
||||||
|
u16 animation_frame_length_ms;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue