aboutsummaryrefslogtreecommitdiff
path: root/src/client
diff options
context:
space:
mode:
Diffstat (limited to 'src/client')
-rw-r--r--src/client/tile.cpp119
-rw-r--r--src/client/tile.h8
2 files changed, 74 insertions, 53 deletions
diff --git a/src/client/tile.cpp b/src/client/tile.cpp
index a2284eed3..9321a4586 100644
--- a/src/client/tile.cpp
+++ b/src/client/tile.cpp
@@ -545,7 +545,7 @@ static void apply_mask(video::IImage *mask, video::IImage *dst,
// Draw or overlay a crack
static void draw_crack(video::IImage *crack, video::IImage *dst,
bool use_overlay, s32 frame_count, s32 progression,
- video::IVideoDriver *driver);
+ video::IVideoDriver *driver, u8 tiles = 1);
// Brighten image
void brighten(video::IImage *image);
@@ -1280,11 +1280,22 @@ bool TextureSource::generateImagePart(std::string part_of_name,
}
// Crack image number and overlay option
+ // Format: crack[o][:<tiles>]:<frame_count>:<frame>
bool use_overlay = (part_of_name[6] == 'o');
Strfnd sf(part_of_name);
sf.next(":");
s32 frame_count = stoi(sf.next(":"));
s32 progression = stoi(sf.next(":"));
+ s32 tiles = 1;
+ // Check whether there is the <tiles> argument, that is,
+ // whether there are 3 arguments. If so, shift values
+ // as the first and not the last argument is optional.
+ auto s = sf.next(":");
+ if (!s.empty()) {
+ tiles = frame_count;
+ frame_count = progression;
+ progression = stoi(s);
+ }
if (progression >= 0) {
/*
@@ -1299,7 +1310,7 @@ bool TextureSource::generateImagePart(std::string part_of_name,
if (img_crack) {
draw_crack(img_crack, baseimg,
use_overlay, frame_count,
- progression, driver);
+ progression, driver, tiles);
img_crack->drop();
}
}
@@ -2102,74 +2113,78 @@ static void apply_mask(video::IImage *mask, video::IImage *dst,
}
}
+video::IImage *create_crack_image(video::IImage *crack, s32 frame_index,
+ core::dimension2d<u32> size, u8 tiles, video::IVideoDriver *driver)
+{
+ core::dimension2d<u32> strip_size = crack->getDimension();
+ core::dimension2d<u32> frame_size(strip_size.Width, strip_size.Width);
+ core::dimension2d<u32> tile_size(size / tiles);
+ s32 frame_count = strip_size.Height / strip_size.Width;
+ if (frame_index >= frame_count)
+ frame_index = frame_count - 1;
+ core::rect<s32> frame(v2s32(0, frame_index * frame_size.Height), frame_size);
+ video::IImage *result = nullptr;
+
+// extract crack frame
+ video::IImage *crack_tile = driver->createImage(video::ECF_A8R8G8B8, tile_size);
+ if (!crack_tile)
+ return nullptr;
+ if (tile_size == frame_size) {
+ crack->copyTo(crack_tile, v2s32(0, 0), frame);
+ } else {
+ video::IImage *crack_frame = driver->createImage(video::ECF_A8R8G8B8, frame_size);
+ if (!crack_frame)
+ goto exit__has_tile;
+ crack->copyTo(crack_frame, v2s32(0, 0), frame);
+ crack_frame->copyToScaling(crack_tile);
+ crack_frame->drop();
+ }
+ if (tiles == 1)
+ return crack_tile;
+
+// tile it
+ result = driver->createImage(video::ECF_A8R8G8B8, size);
+ if (!result)
+ goto exit__has_tile;
+ result->fill({});
+ for (u8 i = 0; i < tiles; i++)
+ for (u8 j = 0; j < tiles; j++)
+ crack_tile->copyTo(result, v2s32(i * tile_size.Width, j * tile_size.Height));
+
+exit__has_tile:
+ crack_tile->drop();
+ return result;
+}
+
static void draw_crack(video::IImage *crack, video::IImage *dst,
bool use_overlay, s32 frame_count, s32 progression,
- video::IVideoDriver *driver)
+ video::IVideoDriver *driver, u8 tiles)
{
// Dimension of destination image
core::dimension2d<u32> dim_dst = dst->getDimension();
- // Dimension of original image
- core::dimension2d<u32> dim_crack = crack->getDimension();
- // Count of crack stages
- s32 crack_count = dim_crack.Height / dim_crack.Width;
// Limit frame_count
if (frame_count > (s32) dim_dst.Height)
frame_count = dim_dst.Height;
if (frame_count < 1)
frame_count = 1;
- // Limit progression
- if (progression > crack_count-1)
- progression = crack_count-1;
- // Dimension of a single crack stage
- core::dimension2d<u32> dim_crack_cropped(
- dim_crack.Width,
- dim_crack.Width
- );
// Dimension of the scaled crack stage,
// which is the same as the dimension of a single destination frame
- core::dimension2d<u32> dim_crack_scaled(
+ core::dimension2d<u32> frame_size(
dim_dst.Width,
dim_dst.Height / frame_count
);
- // Create cropped and scaled crack images
- video::IImage *crack_cropped = driver->createImage(
- video::ECF_A8R8G8B8, dim_crack_cropped);
- video::IImage *crack_scaled = driver->createImage(
- video::ECF_A8R8G8B8, dim_crack_scaled);
+ video::IImage *crack_scaled = create_crack_image(crack, progression,
+ frame_size, tiles, driver);
+ if (!crack_scaled)
+ return;
- if (crack_cropped && crack_scaled)
- {
- // Crop crack image
- v2s32 pos_crack(0, progression*dim_crack.Width);
- crack->copyTo(crack_cropped,
- v2s32(0,0),
- core::rect<s32>(pos_crack, dim_crack_cropped));
- // Scale crack image by copying
- crack_cropped->copyToScaling(crack_scaled);
- // Copy or overlay crack image onto each frame
- for (s32 i = 0; i < frame_count; ++i)
- {
- v2s32 dst_pos(0, dim_crack_scaled.Height * i);
- if (use_overlay)
- {
- blit_with_alpha_overlay(crack_scaled, dst,
- v2s32(0,0), dst_pos,
- dim_crack_scaled);
- }
- else
- {
- blit_with_alpha(crack_scaled, dst,
- v2s32(0,0), dst_pos,
- dim_crack_scaled);
- }
- }
+ auto blit = use_overlay ? blit_with_alpha_overlay : blit_with_alpha;
+ for (s32 i = 0; i < frame_count; ++i) {
+ v2s32 dst_pos(0, frame_size.Height * i);
+ blit(crack_scaled, dst, v2s32(0,0), dst_pos, frame_size);
}
- if (crack_scaled)
- crack_scaled->drop();
-
- if (crack_cropped)
- crack_cropped->drop();
+ crack_scaled->drop();
}
void brighten(video::IImage *image)
diff --git a/src/client/tile.h b/src/client/tile.h
index d4e25ea6a..e69dbe0c7 100644
--- a/src/client/tile.h
+++ b/src/client/tile.h
@@ -209,7 +209,8 @@ struct TileLayer
texture_id == other.texture_id &&
material_type == other.material_type &&
material_flags == other.material_flags &&
- color == other.color;
+ color == other.color &&
+ scale == other.scale;
}
/*!
@@ -298,6 +299,8 @@ struct TileLayer
* a color then the color of the node owning this tile.
*/
video::SColor color;
+
+ u8 scale;
};
/*!
@@ -325,6 +328,9 @@ struct TileSpec
&& emissive_light == other.emissive_light;
}
+ //! If true, the tile rotation is ignored.
+ bool world_aligned = false;
+ //! Tile rotation.
u8 rotation = 0;
//! This much light does the tile emit.
u8 emissive_light = 0;