@@ -379,11 +379,11 @@ class TextureSource : public IWritableTextureSource
379
379
const TextureFromMeshParams ¶ms);
380
380
381
381
// Generates an image from a full string like
382
- // "stone.png^mineral_coal.png^[crack0 ".
382
+ // "stone.png^mineral_coal.png^[crack:1:0 ".
383
383
// Shall be called from the main thread.
384
384
video::IImage* generateImageFromScratch (std::string name);
385
385
386
- // Generate image based on a string like "stone.png" or "[crack0 ".
386
+ // Generate image based on a string like "stone.png" or "[crack:1:0 ".
387
387
// if baseimg is NULL, it is created. Otherwise stuff is made on it.
388
388
// Shall be called from the main thread.
389
389
bool generateImage (std::string part_of_name, video::IImage *& baseimg);
@@ -543,14 +543,21 @@ u32 TextureSource::getTextureId(const std::string &name)
543
543
return 0 ;
544
544
}
545
545
546
- // Overlay image on top of another image (used for cracks)
547
- void overlay (video::IImage *image, video::IImage *overlay);
548
-
549
546
// Draw an image on top of an another one, using the alpha channel of the
550
547
// source image
551
548
static void blit_with_alpha (video::IImage *src, video::IImage *dst,
552
549
v2s32 src_pos, v2s32 dst_pos, v2u32 size);
553
550
551
+ // Like blit_with_alpha, but only modifies destination pixels that
552
+ // are fully opaque
553
+ static void blit_with_alpha_overlay (video::IImage *src, video::IImage *dst,
554
+ v2s32 src_pos, v2s32 dst_pos, v2u32 size);
555
+
556
+ // Draw or overlay a crack
557
+ static void draw_crack (video::IImage *crack, video::IImage *dst,
558
+ bool use_overlay, u32 frame_count, u32 progression,
559
+ video::IVideoDriver *driver);
560
+
554
561
// Brighten image
555
562
void brighten (video::IImage *image);
556
563
// Parse a transform name
@@ -1032,8 +1039,10 @@ bool TextureSource::generateImage(std::string part_of_name, video::IImage *& bas
1032
1039
<<std::endl;*/
1033
1040
1034
1041
/*
1035
- [crackN
1042
+ [crack:N:P
1043
+ [cracko:N:P
1036
1044
Adds a cracking texture
1045
+ N = animation frame count, P = crack progression
1037
1046
*/
1038
1047
if (part_of_name.substr (0 ,6 ) == " [crack" )
1039
1048
{
@@ -1044,24 +1053,14 @@ bool TextureSource::generateImage(std::string part_of_name, video::IImage *& bas
1044
1053
<<" \" , cancelling." <<std::endl;
1045
1054
return false ;
1046
1055
}
1047
-
1056
+
1048
1057
// Crack image number and overlay option
1049
- s32 progression = 0 ;
1050
- bool use_overlay = false ;
1051
- if (part_of_name.substr (6 ,1 ) == " o" )
1052
- {
1053
- progression = stoi (part_of_name.substr (7 ));
1054
- use_overlay = true ;
1055
- }
1056
- else
1057
- {
1058
- progression = stoi (part_of_name.substr (6 ));
1059
- use_overlay = false ;
1060
- }
1058
+ bool use_overlay = (part_of_name[6 ] == ' o' );
1059
+ Strfnd sf (part_of_name);
1060
+ sf.next (" :" );
1061
+ u32 frame_count = stoi (sf.next (" :" ));
1062
+ u32 progression = stoi (sf.next (" :" ));
1061
1063
1062
- // Size of the base image
1063
- core::dimension2d<u32> dim_base = baseimg->getDimension ();
1064
-
1065
1064
/*
1066
1065
Load crack image.
1067
1066
@@ -1070,60 +1069,12 @@ bool TextureSource::generateImage(std::string part_of_name, video::IImage *& bas
1070
1069
*/
1071
1070
video::IImage *img_crack = m_sourcecache.getOrLoad (
1072
1071
" crack_anylength.png" , m_device);
1073
-
1072
+
1074
1073
if (img_crack && progression >= 0 )
1075
1074
{
1076
- // Dimension of original image
1077
- core::dimension2d<u32> dim_crack
1078
- = img_crack->getDimension ();
1079
- // Count of crack stages
1080
- s32 crack_count = dim_crack.Height / dim_crack.Width ;
1081
- // Limit progression
1082
- if (progression > crack_count-1 )
1083
- progression = crack_count-1 ;
1084
- // Dimension of a single crack stage
1085
- core::dimension2d<u32> dim_crack_cropped (
1086
- dim_crack.Width ,
1087
- dim_crack.Width
1088
- );
1089
- // Create cropped and scaled crack images
1090
- video::IImage *img_crack_cropped = driver->createImage (
1091
- video::ECF_A8R8G8B8, dim_crack_cropped);
1092
- video::IImage *img_crack_scaled = driver->createImage (
1093
- video::ECF_A8R8G8B8, dim_base);
1094
-
1095
- if (img_crack_cropped && img_crack_scaled)
1096
- {
1097
- // Crop crack image
1098
- v2s32 pos_crack (0 , progression*dim_crack.Width );
1099
- img_crack->copyTo (img_crack_cropped,
1100
- v2s32 (0 ,0 ),
1101
- core::rect<s32>(pos_crack, dim_crack_cropped));
1102
- // Scale crack image by copying
1103
- img_crack_cropped->copyToScaling (img_crack_scaled);
1104
- // Copy or overlay crack image
1105
- if (use_overlay)
1106
- {
1107
- overlay (baseimg, img_crack_scaled);
1108
- }
1109
- else
1110
- {
1111
- /* img_crack_scaled->copyToWithAlpha(
1112
- baseimg,
1113
- v2s32(0,0),
1114
- core::rect<s32>(v2s32(0,0), dim_base),
1115
- video::SColor(255,255,255,255));*/
1116
- blit_with_alpha (img_crack_scaled, baseimg,
1117
- v2s32 (0 ,0 ), v2s32 (0 ,0 ), dim_base);
1118
- }
1119
- }
1120
-
1121
- if (img_crack_scaled)
1122
- img_crack_scaled->drop ();
1123
-
1124
- if (img_crack_cropped)
1125
- img_crack_cropped->drop ();
1126
-
1075
+ draw_crack (img_crack, baseimg,
1076
+ use_overlay, frame_count,
1077
+ progression, driver);
1127
1078
img_crack->drop ();
1128
1079
}
1129
1080
}
@@ -1499,37 +1450,6 @@ bool TextureSource::generateImage(std::string part_of_name, video::IImage *& bas
1499
1450
return true ;
1500
1451
}
1501
1452
1502
- void overlay (video::IImage *image, video::IImage *overlay)
1503
- {
1504
- /*
1505
- Copy overlay to image, taking alpha into account.
1506
- Where image is transparent, don't copy from overlay.
1507
- Images sizes must be identical.
1508
- */
1509
- if (image == NULL || overlay == NULL )
1510
- return ;
1511
-
1512
- core::dimension2d<u32> dim = image->getDimension ();
1513
- core::dimension2d<u32> dim_overlay = overlay->getDimension ();
1514
- assert (dim == dim_overlay);
1515
-
1516
- for (u32 y=0 ; y<dim.Height ; y++)
1517
- for (u32 x=0 ; x<dim.Width ; x++)
1518
- {
1519
- video::SColor c1 = image->getPixel (x,y);
1520
- video::SColor c2 = overlay->getPixel (x,y);
1521
- u32 a1 = c1.getAlpha ();
1522
- u32 a2 = c2.getAlpha ();
1523
- if (a1 == 255 && a2 != 0 )
1524
- {
1525
- c1.setRed ((c1.getRed ()*(255 -a2) + c2.getRed ()*a2)/255 );
1526
- c1.setGreen ((c1.getGreen ()*(255 -a2) + c2.getGreen ()*a2)/255 );
1527
- c1.setBlue ((c1.getBlue ()*(255 -a2) + c2.getBlue ()*a2)/255 );
1528
- }
1529
- image->setPixel (x,y,c1);
1530
- }
1531
- }
1532
-
1533
1453
/*
1534
1454
Draw an image on top of an another one, using the alpha channel of the
1535
1455
source image
@@ -1554,6 +1474,100 @@ static void blit_with_alpha(video::IImage *src, video::IImage *dst,
1554
1474
}
1555
1475
}
1556
1476
1477
+ /*
1478
+ Draw an image on top of an another one, using the alpha channel of the
1479
+ source image; only modify fully opaque pixels in destinaion
1480
+ */
1481
+ static void blit_with_alpha_overlay (video::IImage *src, video::IImage *dst,
1482
+ v2s32 src_pos, v2s32 dst_pos, v2u32 size)
1483
+ {
1484
+ for (u32 y0 =0 ; y0 <size.Y ; y0 ++)
1485
+ for (u32 x0=0 ; x0<size.X ; x0++)
1486
+ {
1487
+ s32 src_x = src_pos.X + x0;
1488
+ s32 src_y = src_pos.Y + y0 ;
1489
+ s32 dst_x = dst_pos.X + x0;
1490
+ s32 dst_y = dst_pos.Y + y0 ;
1491
+ video::SColor src_c = src->getPixel (src_x, src_y);
1492
+ video::SColor dst_c = dst->getPixel (dst_x, dst_y);
1493
+ if (dst_c.getAlpha () == 255 && src_c.getAlpha () != 0 )
1494
+ {
1495
+ dst_c = src_c.getInterpolated (dst_c, (float )src_c.getAlpha ()/255 .0f );
1496
+ dst->setPixel (dst_x, dst_y, dst_c);
1497
+ }
1498
+ }
1499
+ }
1500
+
1501
+ static void draw_crack (video::IImage *crack, video::IImage *dst,
1502
+ bool use_overlay, u32 frame_count, u32 progression,
1503
+ video::IVideoDriver *driver)
1504
+ {
1505
+ // Dimension of destination image
1506
+ core::dimension2d<u32> dim_dst = dst->getDimension ();
1507
+ // Dimension of original image
1508
+ core::dimension2d<u32> dim_crack = crack->getDimension ();
1509
+ // Count of crack stages
1510
+ u32 crack_count = dim_crack.Height / dim_crack.Width ;
1511
+ // Limit frame_count
1512
+ if (frame_count > dim_dst.Height )
1513
+ frame_count = dim_dst.Height ;
1514
+ if (frame_count == 0 )
1515
+ frame_count = 1 ;
1516
+ // Limit progression
1517
+ if (progression > crack_count-1 )
1518
+ progression = crack_count-1 ;
1519
+ // Dimension of a single crack stage
1520
+ core::dimension2d<u32> dim_crack_cropped (
1521
+ dim_crack.Width ,
1522
+ dim_crack.Width
1523
+ );
1524
+ // Dimension of the scaled crack stage,
1525
+ // which is the same as the dimension of a single destination frame
1526
+ core::dimension2d<u32> dim_crack_scaled (
1527
+ dim_dst.Width ,
1528
+ dim_dst.Height / frame_count
1529
+ );
1530
+ // Create cropped and scaled crack images
1531
+ video::IImage *crack_cropped = driver->createImage (
1532
+ video::ECF_A8R8G8B8, dim_crack_cropped);
1533
+ video::IImage *crack_scaled = driver->createImage (
1534
+ video::ECF_A8R8G8B8, dim_crack_scaled);
1535
+
1536
+ if (crack_cropped && crack_scaled)
1537
+ {
1538
+ // Crop crack image
1539
+ v2s32 pos_crack (0 , progression*dim_crack.Width );
1540
+ crack->copyTo (crack_cropped,
1541
+ v2s32 (0 ,0 ),
1542
+ core::rect<s32>(pos_crack, dim_crack_cropped));
1543
+ // Scale crack image by copying
1544
+ crack_cropped->copyToScaling (crack_scaled);
1545
+ // Copy or overlay crack image onto each frame
1546
+ for (u32 i = 0 ; i < frame_count; ++i)
1547
+ {
1548
+ v2s32 dst_pos (0 , dim_crack_scaled.Height * i);
1549
+ if (use_overlay)
1550
+ {
1551
+ blit_with_alpha_overlay (crack_scaled, dst,
1552
+ v2s32 (0 ,0 ), dst_pos,
1553
+ dim_crack_scaled);
1554
+ }
1555
+ else
1556
+ {
1557
+ blit_with_alpha (crack_scaled, dst,
1558
+ v2s32 (0 ,0 ), dst_pos,
1559
+ dim_crack_scaled);
1560
+ }
1561
+ }
1562
+ }
1563
+
1564
+ if (crack_scaled)
1565
+ crack_scaled->drop ();
1566
+
1567
+ if (crack_cropped)
1568
+ crack_cropped->drop ();
1569
+ }
1570
+
1557
1571
void brighten (video::IImage *image)
1558
1572
{
1559
1573
if (image == NULL )
0 commit comments