Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Added animation mode #1009

Closed
Binary file removed assets/icons/postman collections.zip
Binary file not shown.
53 changes: 53 additions & 0 deletions lib/bademagic_module/utils/byte_array_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,56 @@ List<int> hexStringToByteArray(String hexString) {
logger.d(data.length);
return data;
}

List<List<int>> byteArrayToBinaryArray(List<int> byteArray) {
List<List<int>> binaryArray = List.generate(11, (_) => []);

int rowIndex = 0;
for (int byte in byteArray) {
List<int> binaryRepresentation = [];
for (int i = 7; i >= 0; i--) {
binaryRepresentation.add((byte >> i) & 1);
}

binaryArray[rowIndex].addAll(binaryRepresentation);

rowIndex = (rowIndex + 1) % 11;
}

logger.d(
"binaryArray: $binaryArray"); // Use print instead of logger for standalone example
return binaryArray;
}

String hexToBin(String hex) {
// Convert hex to binary string
String binaryString = BigInt.parse(hex, radix: 16).toRadixString(2);

// Pad the binary string with leading zeros if necessary to ensure it's a multiple of 8 bits
int paddingLength = (8 - (binaryString.length % 8)) % 8;
binaryString = binaryString.padLeft(binaryString.length + paddingLength, '0');
logger.d("binaryString: $binaryString");
return binaryString;
}

List<List<int>> binaryStringTo2DList(String binaryString) {
int maxHeight = 11;
List<List<int>> binary2DList = List.generate(maxHeight, (_) => []);

for (int x = 0; x < binaryString.length; x++) {
int a = 0;
for (int y = a; y < 11; y++) {
for (int z = 0; z < 8; z++) {
binary2DList[y].add(int.parse(binaryString[x++]));
if (x >= binaryString.length) {
break;
}
}
if (x >= binaryString.length) {
break;
}
}
}
logger.d("binary2DList: $binary2DList");
return binary2DList;
}
23 changes: 19 additions & 4 deletions lib/bademagic_module/utils/converters.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'package:badgemagic/bademagic_module/utils/byte_array_utils.dart';
import 'package:badgemagic/bademagic_module/utils/data_to_bytearray_converter.dart';
import 'package:badgemagic/bademagic_module/utils/file_helper.dart';
import 'package:badgemagic/bademagic_module/utils/image_utils.dart';
import 'package:badgemagic/providers/badgeview_provider.dart';
import 'package:badgemagic/providers/imageprovider.dart';
import 'package:get_it/get_it.dart';

Expand All @@ -12,6 +13,7 @@ class Converters {
DataToByteArrayConverter converter = DataToByteArrayConverter();
ImageUtils imageUtils = ImageUtils();
FileHelper fileHelper = FileHelper();
DrawBadgeProvider badgeList = GetIt.instance.get<DrawBadgeProvider>();

int controllerLength = 0;

Expand All @@ -23,10 +25,8 @@ class Converters {
var key = controllerData.imageCache.keys.toList()[index];
if (key is List) {
String filename = key[0];
logger.d("Filename: $filename");
List<List<int>>? image = await fileHelper.readFromFile(filename);
logger.d("Image: $image");
hexStrings = convertBitmapToLEDHex(image!, true);
hexStrings += convertBitmapToLEDHex(image!, true);
x += 5;
} else {
List<String> hs =
Expand All @@ -43,6 +43,22 @@ class Converters {
return hexStrings;
}

void badgeAnimation(String message) async {
if (message == "") {
//geerate a 2d list with all values as 0
List<List<int>> image =
List.generate(11, (i) => List.generate(44, (j) => 0));
badgeList.setNewGrid(image);
badgeList.startAnimation();
} else {
List<String> hexStrings = await messageTohex(message);
List<int> byteArray = hexStringToByteArray(hexStrings.join());
List<List<int>> binaryArray = byteArrayToBinaryArray(byteArray);
badgeList.setNewGrid(binaryArray);
badgeList.startAnimation();
}
}

//function to convert the bitmap to the LED hex format
//it takes the 2D list of pixels and converts it to the LED hex format
static List<String> convertBitmapToLEDHex(
Expand Down Expand Up @@ -145,7 +161,6 @@ class Converters {

allHexs.add(lineHex.toString()); // Store completed hexadecimal line
}
logger.d("All hexs: $allHexs");
return allHexs; // Return list of hexadecimal strings
}
}
2 changes: 0 additions & 2 deletions lib/bademagic_module/utils/image_utils.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import 'dart:ui' as ui;
import 'dart:ui';
import 'package:badgemagic/bademagic_module/utils/byte_array_utils.dart';
import 'package:badgemagic/bademagic_module/utils/converters.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
Expand Down Expand Up @@ -222,7 +221,6 @@ class ImageUtils {
}
}
}
logger.d("Pixel Array generated = $pixelArray");
return Converters.convertBitmapToLEDHex(pixelArray, false);
}
}
94 changes: 94 additions & 0 deletions lib/badge_animation/ani_animation.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import 'package:badgemagic/bademagic_module/utils/byte_array_utils.dart';
import 'package:badgemagic/badge_animation/animation_abstract.dart';
import 'package:badgemagic/badge_animation/reference_classes.dart';

class AniAnimation extends BadgeAnimation {
@override
void animation(
List<List<bool>> grid,
List<List<int>> newGrid,
int animationIndex,
bool validMarquee,
bool flashLEDOn,
IntReference countFrame,
int i,
int j,
int newHeight,
int newWidth,
int badgeHeight,
int badgeWidth,
IntReference lastFrame) {
// Calculate vertical and horizontal offsets to center the newGrid in the badge grid
int verticalOffset = (badgeHeight - newHeight) ~/ 2;
int horizontalOffset = (badgeWidth - newWidth) ~/ 2;

bool lineShow = false;
bool bitmapShowcenter = false;
bool bitmapShowOut = false;

// Calculate the corresponding row and column in the newGrid
int sourceRow = i - verticalOffset;
int sourceCol = j - horizontalOffset;

// Check if the current cell is within the bounds of the newGrid
bool isWithinNewGrid = sourceRow >= 0 &&
sourceRow < newHeight &&
sourceCol >= 0 &&
sourceCol < newWidth;

// Calculate center columns
int leftCenterCol = badgeWidth ~/ 2 - 1;
int rightCenterCol = badgeWidth ~/ 2;

// Calculate the maximum distance the lines can travel
int maxDistance =
leftCenterCol; // The maximum distance from the center to the edge

// Adjust the animationIndex to loop back to the center when it reaches maxDistance
int currentAnimationIndex = animationIndex % (maxDistance + 1);

// Calculate the current positions of the vertical lines
int leftColPos = leftCenterCol - currentAnimationIndex;
int rightColPos = rightCenterCol + currentAnimationIndex;

// Ensure valid positions
if (leftColPos < 0) leftColPos += badgeWidth;
if (rightColPos >= badgeWidth) rightColPos -= badgeWidth;

// Animation phase control
// First phase: Only between the two center columns
if (j == leftColPos || j == rightColPos) {
lineShow = true; // Draw vertical lines in the center columns
} else {
lineShow = false;
}

if (countFrame.value == 0) {
if (isWithinNewGrid && j > leftColPos && j < rightColPos) {
bitmapShowcenter =
newGrid[sourceRow][sourceCol] == 1; // Display the inner grid
}
}

// Second phase: Outside the center columns, executed after the first phase is complete
if (countFrame.value == 1) {
if (isWithinNewGrid && (j < leftColPos || j > rightColPos)) {
bitmapShowcenter = newGrid[sourceRow][sourceCol] ==
1; // Display grid outside the center columns
}
}

grid[i][j] = validMarquee ||
(flashLEDOn && (lineShow || bitmapShowOut || bitmapShowcenter));

// Alternate the phase between 0 and 1
if (i == 0 &&
j == 0 &&
leftColPos == leftCenterCol &&
rightColPos == rightCenterCol) {
// Toggle only once per full grid cycle
countFrame.value = (countFrame.value == 0) ? 1 : 0;
logger.i("countFrame toggled to ${countFrame.value}");
}
}
}
33 changes: 33 additions & 0 deletions lib/badge_animation/ani_dpwn.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import 'package:badgemagic/badge_animation/animation_abstract.dart';
import 'package:badgemagic/badge_animation/reference_classes.dart';

class DownAnimation extends BadgeAnimation {
@override
void animation(
List<List<bool>> grid,
List<List<int>> newGrid,
int animationIndex,
bool validMarquee,
bool flashLEDOn,
IntReference currentcountFrame,
int i,
int j,
int newHeight,
int newWidth,
int badgeHeight,
int badgeWidth,
IntReference lastFrame) {
if (i < badgeHeight && j < badgeWidth) {
int newGridRow = (i - animationIndex + newHeight) % newHeight;
bool upCondition = validMarquee ||
flashLEDOn &&
(i >= 0 &&
i < newHeight &&
j >= 0 &&
j < newWidth &&
newGrid[newGridRow][j] == 1);

grid[i][j] = upCondition;
}
}
}
29 changes: 29 additions & 0 deletions lib/badge_animation/ani_fixed.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import 'package:badgemagic/badge_animation/animation_abstract.dart';
import 'package:badgemagic/badge_animation/reference_classes.dart';

class FixedAnimation extends BadgeAnimation {
@override
void animation(
List<List<bool>> grid,
List<List<int>> newGrid,
int animationIndex,
bool validMarquee,
bool flashLEDOn,
IntReference currentcountFrame,
int i,
int j,
int newHeight,
int newWidth,
int badgeHeight,
int badgeWidth,
IntReference lastFrame) {
if (newWidth <= badgeWidth + 4) {
grid[i][j] = validMarquee ||
i >= 0 &&
i < newHeight &&
j >= 0 &&
j < newWidth &&
(flashLEDOn && newGrid[i][j] == 1);
}
}
}
34 changes: 34 additions & 0 deletions lib/badge_animation/ani_right.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import 'package:badgemagic/badge_animation/animation_abstract.dart';
import 'package:badgemagic/badge_animation/reference_classes.dart';

class RightAnimation extends BadgeAnimation {
@override
void animation(
List<List<bool>> grid,
List<List<int>> newGrid,
int animationIndex,
bool validMarquee,
bool flashLEDOn,
IntReference currentcountFrame,
int i,
int j,
int newHeight,
int newWidth,
int badgeHeight,
int badgeWidth,
IntReference lastFrame) {
// Calculate the scroll offset to move from left to right
int scrollOffset = animationIndex % (newWidth + badgeWidth);

// Get the corresponding column in the new grid based on the reversed scroll position
int sourceCol = newWidth - scrollOffset + j;

// If sourceCol is within bounds of the new grid, display it, else blank space
if (sourceCol >= 0 && sourceCol < newWidth) {
grid[i][j] =
validMarquee || flashLEDOn && newGrid[i % newHeight][sourceCol] == 1;
} else {
validMarquee ? grid[i][j] = true : grid[i][j] = false;
}
}
}
43 changes: 43 additions & 0 deletions lib/badge_animation/ani_snowflake.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import 'package:badgemagic/badge_animation/animation_abstract.dart';
import 'package:badgemagic/badge_animation/reference_classes.dart';

class SnowFlakeAnimation extends BadgeAnimation {
@override
void animation(
List<List<bool>> grid,
List<List<int>> newGrid,
int animationIndex,
bool validMarquee,
bool flashLEDOn,
IntReference currentcountFrame,
int i,
int j,
int newHeight,
int newWidth,
int badgeHeight,
int badgeWidth,
IntReference lastFrame) {
// Animation value to determine the current frame
int animationValue = animationIndex ~/ 1;

int newGridHeight = newGrid.length;
int newGridWidth = newGrid[0].length;

// Calculate the total number of frames that fit the badge width
int framesCount = (newGridWidth / badgeWidth).ceil();

// Determine the current frame based on the animation value
int currentcountFrame = animationValue ~/ badgeWidth % framesCount;

// Calculate the starting column for the current frame in newGrid
int startCol = currentcountFrame * badgeWidth;

bool isNewGridCell = i < newGridHeight && (startCol + j) < newGridWidth;

// Update the grid based on the current frame's data
bool snowflakeCondition = validMarquee ||
flashLEDOn && (isNewGridCell && newGrid[i][startCol + j] == 1);

grid[i][j] = snowflakeCondition;
}
}
Loading
Loading