Add 2D sheet animation for nodes

This commit is contained in:
sfan5 2016-12-23 14:43:56 +01:00
parent 7057c196c4
commit a07b032245
8 changed files with 88 additions and 27 deletions

@ -3702,7 +3702,26 @@ Definition tables
* `image` (name)
### Tile animation definition
* `{type="vertical_frames", aspect_w=16, aspect_h=16, length=3.0}`
{
type = "vertical_frames",
aspect_w = 16,
-- ^ specify width of a frame in pixels
aspect_h = 16,
-- ^ specify height of a frame in pixels
length = 3.0,
-- ^ specify full loop length
}
{
type = "sheet_2d",
frames_w = 5,
-- ^ specify width in number of frames
frames_h = 3,
-- ^ specify height in number of frames
frame_length = 0.5,
-- ^ specify length of a single frame
}
### Node definition (`register_node`)

@ -1044,8 +1044,11 @@ minetest.register_node("default:lava_source", {
inventory_image = minetest.inventorycube("default_lava.png"),
drawtype = "liquid",
--tiles ={"default_lava.png"},
tiles ={
{name="default_lava_source_animated.png", animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=3.0}}
tiles = {
{
name = "default_lava_source_animated.png",
animation = {type="sheet_2d", frames_w=3, frames_h=2, frame_length=0.5}
}
},
special_tiles = {
-- New-style lava source material (mostly unused)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

@ -528,7 +528,7 @@ void ContentFeatures::fillTileAttribs(ITextureSource *tsrc, TileSpec *tile,
tile->material_flags = 0;
if (backface_culling)
tile->material_flags |= MATERIAL_FLAG_BACKFACE_CULLING;
if (tiledef->animation.type == TAT_VERTICAL_FRAMES)
if (tiledef->animation.type != TAT_NONE)
tile->material_flags |= MATERIAL_FLAG_ANIMATION;
if (tiledef->tileable_horizontal)
tile->material_flags |= MATERIAL_FLAG_TILEABLE_HORIZONTAL;

@ -570,7 +570,7 @@ void ParticleManager::addNodeParticle(IGameDef* gamedef, scene::ISceneManager* s
video::ITexture *texture;
// Only use first frame of animated texture
if(tiles[texid].material_flags & MATERIAL_FLAG_ANIMATION)
if (tiles[texid].material_flags & MATERIAL_FLAG_ANIMATION)
texture = tiles[texid].frames[0].texture;
else
texture = tiles[texid].texture;

@ -39,6 +39,7 @@ struct EnumString es_TileAnimationType[] =
{
{TAT_NONE, "none"},
{TAT_VERTICAL_FRAMES, "vertical_frames"},
{TAT_SHEET_2D, "sheet_2d"},
{0, NULL},
};
@ -334,16 +335,26 @@ TileDef read_tiledef(lua_State *L, int index, u8 drawtype)
// 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.vertical_frames.aspect_w =
getintfield_default(L, -1, "aspect_w", 16);
tiledef.animation.vertical_frames.aspect_h =
getintfield_default(L, -1, "aspect_h", 16);
tiledef.animation.vertical_frames.length =
getfloatfield_default(L, -1, "length", 1.0);
if (tiledef.animation.type == TAT_VERTICAL_FRAMES) {
// {type="vertical_frames", aspect_w=16, aspect_h=16, length=2.0}
tiledef.animation.vertical_frames.aspect_w =
getintfield_default(L, -1, "aspect_w", 16);
tiledef.animation.vertical_frames.aspect_h =
getintfield_default(L, -1, "aspect_h", 16);
tiledef.animation.vertical_frames.length =
getfloatfield_default(L, -1, "length", 1.0);
} else if (tiledef.animation.type == TAT_SHEET_2D) {
// {type="sheet_2d", frames_w=5, frames_h=3, frame_length=0.5}
getintfield(L, -1, "frames_w",
tiledef.animation.sheet_2d.frames_w);
getintfield(L, -1, "frames_h",
tiledef.animation.sheet_2d.frames_h);
getfloatfield(L, -1, "frame_length",
tiledef.animation.sheet_2d.frame_length);
}
}
lua_pop(L, 1);
}

@ -21,7 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
void TileAnimationParams::serialize(std::ostream &os, u16 protocol_version) const
{
if(protocol_version < 29 /* TODO bump */) {
if (protocol_version < 29) {
if (type == TAT_VERTICAL_FRAMES) {
writeU8(os, type);
writeU16(os, vertical_frames.aspect_w);
@ -41,47 +41,69 @@ void TileAnimationParams::serialize(std::ostream &os, u16 protocol_version) cons
writeU16(os, vertical_frames.aspect_w);
writeU16(os, vertical_frames.aspect_h);
writeF1000(os, vertical_frames.length);
} else if (type == TAT_SHEET_2D) {
writeU8(os, sheet_2d.frames_w);
writeU8(os, sheet_2d.frames_h);
writeF1000(os, sheet_2d.frame_length);
}
}
void TileAnimationParams::deSerialize(std::istream &is, u16 protocol_version)
{
type = (TileAnimationType) readU8(is);
if(protocol_version < 29 /* TODO bump */) {
if (protocol_version < 29) {
vertical_frames.aspect_w = readU16(is);
vertical_frames.aspect_h = readU16(is);
vertical_frames.length = readF1000(is);
return;
}
if(type == TAT_VERTICAL_FRAMES) {
if (type == TAT_VERTICAL_FRAMES) {
vertical_frames.aspect_w = readU16(is);
vertical_frames.aspect_h = readU16(is);
vertical_frames.length = readF1000(is);
} else if (type == TAT_SHEET_2D) {
sheet_2d.frames_w = readU8(is);
sheet_2d.frames_h = readU8(is);
sheet_2d.frame_length = readF1000(is);
}
}
void TileAnimationParams::determineParams(v2u32 texture_size, int *frame_count, int *frame_length_ms) const
{
if (type == TAT_NONE) {
if (type == TAT_VERTICAL_FRAMES) {
int frame_height = (float)texture_size.X /
(float)vertical_frames.aspect_w *
(float)vertical_frames.aspect_h;
int _frame_count = texture_size.Y / frame_height;
if (frame_count)
*frame_count = _frame_count;
if (frame_length_ms)
*frame_length_ms = 1000.0 * vertical_frames.length / _frame_count;
} else if (type == TAT_SHEET_2D) {
if (frame_count)
*frame_count = sheet_2d.frames_w * sheet_2d.frames_h;
if (frame_length_ms)
*frame_length_ms = 1000 * sheet_2d.frame_length;
} else { // TAT_NONE
*frame_count = 1;
*frame_length_ms = 1000;
return;
}
int frame_height = (float)texture_size.X /
(float)vertical_frames.aspect_w *
(float)vertical_frames.aspect_h;
if (frame_count)
*frame_count = texture_size.Y / frame_height;
if (frame_length_ms)
*frame_length_ms = 1000.0 * vertical_frames.length / (texture_size.Y / frame_height);
}
void TileAnimationParams::getTextureModifer(std::ostream &os, v2u32 texture_size, int frame) const
{
if (type == TAT_NONE)
return;
int frame_count;
determineParams(texture_size, &frame_count, NULL);
os << "^[verticalframe:" << frame_count << ":" << frame;
if (type == TAT_VERTICAL_FRAMES) {
int frame_count;
determineParams(texture_size, &frame_count, NULL);
os << "^[verticalframe:" << frame_count << ":" << frame;
} else if (type == TAT_SHEET_2D) {
int q, r;
q = frame / sheet_2d.frames_w;
r = frame % sheet_2d.frames_w;
os << "^[sheet:" << sheet_2d.frames_w << "x" << sheet_2d.frames_h
<< ":" << r << "," << q;
}
}

@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
enum TileAnimationType {
TAT_NONE = 0,
TAT_VERTICAL_FRAMES = 1,
TAT_SHEET_2D = 2,
};
struct TileAnimationParams {
@ -38,6 +39,11 @@ struct TileAnimationParams {
int aspect_h; // height for aspect ratio
float length; // seconds
} vertical_frames;
struct {
int frames_w; // number of frames left-to-right
int frames_h; // number of frames top-to-bottom
float frame_length; // seconds
} sheet_2d;
};
void serialize(std::ostream &os, u16 protocol_version) const;