Skip to content

Commit 5f629b0

Browse files
fix: Behaviour change in the Snowflake animation
fix: Guard against zero framesCount to avoid modulo by zero in SnowFlakeAnimation fix: blicking illusion back fix: added input validation fix: fixed the interchanges animations
1 parent f401ac4 commit 5f629b0

File tree

5 files changed

+114
-68
lines changed

5 files changed

+114
-68
lines changed

lib/badge_animation/ani_animation.dart

Lines changed: 60 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -2,64 +2,76 @@ import 'package:badgemagic/badge_animation/animation_abstract.dart';
22

33
class AniAnimation extends BadgeAnimation {
44
@override
5-
void processAnimation(int badgeHeight, int badgeWidth, int animationIndex,
6-
List<List<bool>> processGrid, List<List<bool>> canvas) {
7-
int newWidth = processGrid[0].length;
8-
int newHeight = processGrid.length;
9-
int verticalOffset = (badgeHeight - newHeight) ~/ 2;
10-
int displayWidth = newWidth > badgeWidth ? badgeWidth : newWidth;
11-
int horizontalOffset = (badgeWidth - displayWidth) ~/ 2;
12-
var totalAnimationLength = badgeWidth;
13-
int frame = animationIndex % totalAnimationLength;
14-
var firstHalf = frame < badgeWidth ~/ 2;
15-
var secondHalf = frame >= badgeWidth ~/ 2;
16-
17-
for (int i = 0; i < badgeHeight; i++) {
18-
for (int j = 0; j < badgeWidth; j++) {
19-
bool lineShow = false;
20-
bool bitmapShowcenter = false;
21-
bool bitmapShowOut = false;
22-
23-
int sourceRow = i - verticalOffset;
24-
int sourceCol = j - horizontalOffset;
5+
void processAnimation(
6+
int badgeHeight,
7+
int badgeWidth,
8+
int animationIndex,
9+
List<List<bool>> processGrid,
10+
List<List<bool>> canvas,
11+
) {
12+
if (processGrid.isEmpty ||
13+
processGrid.any((row) => row.length != processGrid[0].length)) {
14+
throw ArgumentError(
15+
'processGrid must be a non-empty rectangular 2D list',
16+
);
17+
}
18+
int newGridHeight = processGrid.length;
19+
int newGridWidth = processGrid[0].length;
2520

26-
bool isWithinNewGrid = sourceRow >= 0 &&
27-
sourceRow < newHeight &&
28-
sourceCol >= 0 &&
29-
sourceCol < displayWidth;
21+
if (canvas.length < badgeHeight ||
22+
canvas.any((row) => row.length < badgeWidth)) {
23+
throw ArgumentError(
24+
'canvas must have at least $badgeHeight rows and $badgeWidth columns',
25+
);
26+
}
27+
int framesCount = (newGridWidth / badgeWidth).ceil();
28+
framesCount = framesCount == 0 ? 1 : framesCount;
3029

31-
int leftCenterCol = badgeWidth ~/ 2 - 1;
32-
int rightCenterCol = badgeWidth ~/ 2;
30+
int currentFrame = (animationIndex ~/ badgeWidth) % framesCount;
3331

34-
int maxDistance = leftCenterCol;
32+
int startCol = currentFrame * badgeWidth;
33+
if (startCol + badgeWidth > newGridWidth) {
34+
startCol = newGridWidth - badgeWidth;
35+
if (startCol < 0) startCol = 0;
36+
}
3537

36-
int currentAnimationIndex = animationIndex % (maxDistance + 1);
38+
List<List<bool>> tempFrame = List.generate(
39+
badgeHeight,
40+
(_) => List.filled(badgeWidth, false),
41+
);
3742

38-
int leftColPos = leftCenterCol - currentAnimationIndex;
39-
int rightColPos = rightCenterCol + currentAnimationIndex;
43+
for (int i = 0; i < badgeHeight; i++) {
44+
for (int j = 0; j < badgeWidth; j++) {
45+
int gridCol = startCol + j;
46+
bool isValid = i < newGridHeight && gridCol < newGridWidth;
47+
tempFrame[i][j] = isValid ? processGrid[i][gridCol] : false;
48+
}
49+
}
4050

41-
if (leftColPos < 0) leftColPos += badgeWidth;
42-
if (rightColPos >= badgeWidth) rightColPos -= badgeWidth;
51+
int shiftLeftBy =
52+
_countLeadingEmptyCols(tempFrame, badgeHeight, badgeWidth);
4353

44-
if (j == leftColPos || j == rightColPos) {
45-
lineShow = true;
46-
} else {
47-
lineShow = false;
48-
}
54+
for (int i = 0; i < badgeHeight; i++) {
55+
for (int j = 0; j < badgeWidth; j++) {
56+
int sourceCol = j + shiftLeftBy;
57+
canvas[i][j] = sourceCol < badgeWidth ? tempFrame[i][sourceCol] : false;
58+
}
59+
}
60+
}
4961

50-
if (firstHalf) {
51-
if (isWithinNewGrid && j > leftColPos && j < rightColPos) {
52-
bitmapShowcenter = processGrid[sourceRow][sourceCol];
53-
}
54-
}
55-
if (secondHalf) {
56-
if (isWithinNewGrid && (j < leftColPos || j > rightColPos)) {
57-
bitmapShowOut = processGrid[sourceRow][sourceCol];
58-
}
62+
int _countLeadingEmptyCols(List<List<bool>> frame, int height, int width) {
63+
for (int col = 0; col < width; col++) {
64+
bool isColEmpty = true;
65+
for (int row = 0; row < height; row++) {
66+
if (frame[row][col]) {
67+
isColEmpty = false;
68+
break;
5969
}
60-
61-
canvas[i][j] = (lineShow || bitmapShowOut || bitmapShowcenter);
70+
}
71+
if (!isColEmpty) {
72+
return col;
6273
}
6374
}
75+
return 0;
6476
}
6577
}

lib/badge_animation/ani_snowflake.dart

Lines changed: 48 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,61 @@ class SnowFlakeAnimation extends BadgeAnimation {
44
@override
55
void processAnimation(int badgeHeight, int badgeWidth, int animationIndex,
66
List<List<bool>> processGrid, List<List<bool>> canvas) {
7-
int newGridHeight = processGrid.length;
8-
int newGridWidth = processGrid[0].length;
7+
int newWidth = processGrid[0].length;
8+
int newHeight = processGrid.length;
9+
int verticalOffset = (badgeHeight - newHeight) ~/ 2;
10+
int displayWidth = newWidth > badgeWidth ? badgeWidth : newWidth;
11+
int horizontalOffset = (badgeWidth - displayWidth) ~/ 2;
12+
var totalAnimationLength = badgeWidth;
13+
int frame = animationIndex % totalAnimationLength;
14+
var firstHalf = frame < badgeWidth ~/ 2;
15+
var secondHalf = frame >= badgeWidth ~/ 2;
16+
917
for (int i = 0; i < badgeHeight; i++) {
1018
for (int j = 0; j < badgeWidth; j++) {
11-
// Calculate the total number of frames that fit the badge width
12-
int framesCount = (newGridWidth / badgeWidth).ceil();
19+
bool lineShow = false;
20+
bool bitmapShowcenter = false;
21+
bool bitmapShowOut = false;
22+
23+
int sourceRow = i - verticalOffset;
24+
int sourceCol = j - horizontalOffset;
25+
26+
bool isWithinNewGrid = sourceRow >= 0 &&
27+
sourceRow < newHeight &&
28+
sourceCol >= 0 &&
29+
sourceCol < displayWidth;
30+
31+
int leftCenterCol = badgeWidth ~/ 2 - 1;
32+
int rightCenterCol = badgeWidth ~/ 2;
33+
34+
int maxDistance = leftCenterCol;
35+
36+
int currentAnimationIndex = animationIndex % (maxDistance + 1);
1337

14-
// Determine the current frame based on the animation value
15-
int currentcountFrame = animationIndex ~/ badgeWidth % framesCount;
38+
int leftColPos = leftCenterCol - currentAnimationIndex;
39+
int rightColPos = rightCenterCol + currentAnimationIndex;
1640

17-
// Calculate the starting column for the current frame in newGrid
18-
int startCol = currentcountFrame * badgeWidth;
41+
if (leftColPos < 0) leftColPos += badgeWidth;
42+
if (rightColPos >= badgeWidth) rightColPos -= badgeWidth;
1943

20-
bool isNewGridCell = i < newGridHeight && (startCol + j) < newGridWidth;
44+
if (j == leftColPos || j == rightColPos) {
45+
lineShow = true;
46+
} else {
47+
lineShow = false;
48+
}
2149

22-
// Update the grid based on the current frame's data
23-
bool snowflakeCondition =
24-
(isNewGridCell && processGrid[i][startCol + j]);
50+
if (firstHalf) {
51+
if (isWithinNewGrid && j > leftColPos && j < rightColPos) {
52+
bitmapShowcenter = processGrid[sourceRow][sourceCol];
53+
}
54+
}
55+
if (secondHalf) {
56+
if (isWithinNewGrid && (j < leftColPos || j > rightColPos)) {
57+
bitmapShowOut = processGrid[sourceRow][sourceCol];
58+
}
59+
}
2560

26-
canvas[i][j] = snowflakeCondition;
61+
canvas[i][j] = (lineShow || bitmapShowOut || bitmapShowcenter);
2762
}
2863
}
2964
}

lib/constants.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,10 @@ const String aniLeft = 'assets/animations/ic_anim_left.gif';
3030
const String aniDown = 'assets/animations/ic_anim_down.gif';
3131
const String aniFixed = 'assets/animations/ic_anim_fixed.gif';
3232
const String aniLaser = 'assets/animations/ic_anim_laser.gif';
33-
const String aniPicture = 'assets/animations/ic_anim_picture.gif';
33+
const String aniPicture = 'assets/animations/ic_anim_animation.gif';
3434
const String aniUp = 'assets/animations/ic_anim_up.gif';
3535
const String aniRight = 'assets/animations/ic_anim_right.gif';
36+
const String aniSnowflake = 'assets/animations/ic_anim_picture.gif';
3637

3738
//path to all the effects assets used
3839
const String effFlash = 'assets/effects/ic_effect_flash.gif';

lib/providers/animation_badge_provider.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ Map<int, BadgeAnimation?> animationMap = {
2424
2: UpAnimation(),
2525
3: DownAnimation(),
2626
4: FixedAnimation(),
27-
5: SnowFlakeAnimation(),
28-
6: PictureAnimation(),
27+
5: PictureAnimation(),
28+
6: SnowFlakeAnimation(),
2929
7: AniAnimation(),
3030
8: LaserAnimation(),
3131
};

lib/view/widgets/homescreentabs.dart

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,7 @@ class _EffectsTabState extends State<EffectTab> {
4646

4747
//Animation tab to show animation choices for the user
4848
class AnimationTab extends StatefulWidget {
49-
const AnimationTab({
50-
super.key,
51-
});
49+
const AnimationTab({super.key});
5250

5351
@override
5452
State<AnimationTab> createState() => _AnimationTabState();
@@ -91,7 +89,7 @@ class _AnimationTabState extends State<AnimationTab> {
9189
index: 4,
9290
),
9391
AniContainer(
94-
animation: aniFixed,
92+
animation: aniSnowflake,
9593
animationName: 'Snowflake',
9694
index: 5,
9795
),

0 commit comments

Comments
 (0)