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) * `image` (name)
### Tile animation definition ### 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`) ### Node definition (`register_node`)

@ -1044,8 +1044,11 @@ minetest.register_node("default:lava_source", {
inventory_image = minetest.inventorycube("default_lava.png"), inventory_image = minetest.inventorycube("default_lava.png"),
drawtype = "liquid", drawtype = "liquid",
--tiles ={"default_lava.png"}, --tiles ={"default_lava.png"},
tiles ={ tiles = {
{name="default_lava_source_animated.png", animation={type="vertical_frames", aspect_w=16, aspect_h=16, length=3.0}} {
name = "default_lava_source_animated.png",
animation = {type="sheet_2d", frames_w=3, frames_h=2, frame_length=0.5}
}
}, },
special_tiles = { special_tiles = {
-- New-style lava source material (mostly unused) -- 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; tile->material_flags = 0;
if (backface_culling) if (backface_culling)
tile->material_flags |= MATERIAL_FLAG_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; tile->material_flags |= MATERIAL_FLAG_ANIMATION;
if (tiledef->tileable_horizontal) if (tiledef->tileable_horizontal)
tile->material_flags |= MATERIAL_FLAG_TILEABLE_HORIZONTAL; tile->material_flags |= MATERIAL_FLAG_TILEABLE_HORIZONTAL;

@ -570,7 +570,7 @@ void ParticleManager::addNodeParticle(IGameDef* gamedef, scene::ISceneManager* s
video::ITexture *texture; video::ITexture *texture;
// Only use first frame of animated 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; texture = tiles[texid].frames[0].texture;
else else
texture = tiles[texid].texture; texture = tiles[texid].texture;

@ -39,6 +39,7 @@ struct EnumString es_TileAnimationType[] =
{ {
{TAT_NONE, "none"}, {TAT_NONE, "none"},
{TAT_VERTICAL_FRAMES, "vertical_frames"}, {TAT_VERTICAL_FRAMES, "vertical_frames"},
{TAT_SHEET_2D, "sheet_2d"},
{0, NULL}, {0, NULL},
}; };
@ -334,16 +335,26 @@ TileDef read_tiledef(lua_State *L, int index, u8 drawtype)
// animation = {} // animation = {}
lua_getfield(L, index, "animation"); lua_getfield(L, index, "animation");
if(lua_istable(L, -1)){ if(lua_istable(L, -1)){
// {type="vertical_frames", aspect_w=16, aspect_h=16, length=2.0}
tiledef.animation.type = (TileAnimationType) tiledef.animation.type = (TileAnimationType)
getenumfield(L, -1, "type", es_TileAnimationType, getenumfield(L, -1, "type", es_TileAnimationType,
TAT_NONE); TAT_NONE);
tiledef.animation.vertical_frames.aspect_w = if (tiledef.animation.type == TAT_VERTICAL_FRAMES) {
getintfield_default(L, -1, "aspect_w", 16); // {type="vertical_frames", aspect_w=16, aspect_h=16, length=2.0}
tiledef.animation.vertical_frames.aspect_h = tiledef.animation.vertical_frames.aspect_w =
getintfield_default(L, -1, "aspect_h", 16); getintfield_default(L, -1, "aspect_w", 16);
tiledef.animation.vertical_frames.length = tiledef.animation.vertical_frames.aspect_h =
getfloatfield_default(L, -1, "length", 1.0); 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); 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 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) { if (type == TAT_VERTICAL_FRAMES) {
writeU8(os, type); writeU8(os, type);
writeU16(os, vertical_frames.aspect_w); 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_w);
writeU16(os, vertical_frames.aspect_h); writeU16(os, vertical_frames.aspect_h);
writeF1000(os, vertical_frames.length); 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) void TileAnimationParams::deSerialize(std::istream &is, u16 protocol_version)
{ {
type = (TileAnimationType) readU8(is); type = (TileAnimationType) readU8(is);
if(protocol_version < 29 /* TODO bump */) { if (protocol_version < 29) {
vertical_frames.aspect_w = readU16(is); vertical_frames.aspect_w = readU16(is);
vertical_frames.aspect_h = readU16(is); vertical_frames.aspect_h = readU16(is);
vertical_frames.length = readF1000(is); vertical_frames.length = readF1000(is);
return; return;
} }
if(type == TAT_VERTICAL_FRAMES) { if (type == TAT_VERTICAL_FRAMES) {
vertical_frames.aspect_w = readU16(is); vertical_frames.aspect_w = readU16(is);
vertical_frames.aspect_h = readU16(is); vertical_frames.aspect_h = readU16(is);
vertical_frames.length = readF1000(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 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_count = 1;
*frame_length_ms = 1000; *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 void TileAnimationParams::getTextureModifer(std::ostream &os, v2u32 texture_size, int frame) const
{ {
if (type == TAT_NONE) if (type == TAT_NONE)
return; return;
int frame_count; if (type == TAT_VERTICAL_FRAMES) {
determineParams(texture_size, &frame_count, NULL); int frame_count;
os << "^[verticalframe:" << frame_count << ":" << frame; 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 { enum TileAnimationType {
TAT_NONE = 0, TAT_NONE = 0,
TAT_VERTICAL_FRAMES = 1, TAT_VERTICAL_FRAMES = 1,
TAT_SHEET_2D = 2,
}; };
struct TileAnimationParams { struct TileAnimationParams {
@ -38,6 +39,11 @@ struct TileAnimationParams {
int aspect_h; // height for aspect ratio int aspect_h; // height for aspect ratio
float length; // seconds float length; // seconds
} vertical_frames; } 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; void serialize(std::ostream &os, u16 protocol_version) const;