Skip to content

Commit

Permalink
feat: Add SpriteBatch.replace to allow the replacement of the batch i…
Browse files Browse the repository at this point in the history
…nformation (#3079)

This PR adds a new method to the `SpriteBatch` class which allow users
to replace the information, based on an index of the batch.

This is useful when you want to change some of the rendering calls
without having to rebuild the whole batch.

---------

Co-authored-by: Jochum van der Ploeg <jochum@vdploeg.net>
  • Loading branch information
erickzanardo and wolfenrain committed Mar 18, 2024
1 parent 76498eb commit bf3c282
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 0 deletions.
39 changes: 39 additions & 0 deletions packages/flame/lib/src/sprite_batch.dart
Expand Up @@ -243,6 +243,45 @@ class SpriteBatch {
return picture.toImageSafe(image.width * 2, image.height);
}

int get length => _sources.length;

/// Replace provided values of a batch item at the [index], when a parameter
/// is not provided, the original value of the batch item will be used.
///
/// Throws an [ArgumentError] if the [index] is out of bounds.
/// At least one of the parameters must be different from null.
void replace(
int index, {
Rect? source,
Color? color,
RSTransform? transform,
}) {
assert(
source != null || color != null || transform != null,
'At least one of the parameters must be different from null.',
);

if (index < 0 || index >= length) {
throw ArgumentError('Index out of bounds: $index');
}

final currentBatchItem = _batchItems[index];
final newBatchItem = BatchItem(
source: source ?? currentBatchItem.source,
transform: transform ?? currentBatchItem.transform,
color: color ?? currentBatchItem.paint.color,
flip: currentBatchItem.flip,
);

_batchItems[index] = newBatchItem;

_sources[index] = newBatchItem.source;
_transforms[index] = newBatchItem.transform;
if (color != null) {
_colors[index] = color;
}
}

/// Add a new batch item using a RSTransform.
///
/// The [source] parameter is the source location on the [atlas].
Expand Down
60 changes: 60 additions & 0 deletions packages/flame/test/sprite_batch_test.dart
@@ -0,0 +1,60 @@
import 'dart:ui';

import 'package:flame/sprite.dart';
import 'package:flutter/material.dart' hide Image;
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';

class _MockImage extends Mock implements Image {}

void main() {
group('SpriteBatch', () {
test('can add to the batch', () {
final image = _MockImage();
final spriteBatch = SpriteBatch(image);
spriteBatch.add(source: Rect.zero);

expect(spriteBatch.transforms, hasLength(1));
});

test('can replace the color of a batch', () {
final image = _MockImage();
final spriteBatch = SpriteBatch(image);
spriteBatch.add(source: Rect.zero, color: Colors.blue);

spriteBatch.replace(0, color: Colors.red);

expect(spriteBatch.colors, hasLength(1));
expect(spriteBatch.colors.first, Colors.red);
});

test('can replace the source of a batch', () {
final image = _MockImage();
final spriteBatch = SpriteBatch(image);
spriteBatch.add(source: Rect.zero);

spriteBatch.replace(0, source: const Rect.fromLTWH(1, 1, 1, 1));

expect(spriteBatch.sources, hasLength(1));
expect(spriteBatch.sources.first, const Rect.fromLTWH(1, 1, 1, 1));
});

test('can replace the transform of a batch', () {
final image = _MockImage();
final spriteBatch = SpriteBatch(image);
spriteBatch.add(source: Rect.zero);

spriteBatch.replace(0, transform: RSTransform(1, 1, 1, 1));

expect(spriteBatch.transforms, hasLength(1));
expect(
spriteBatch.transforms.first,
isA<RSTransform>()
.having((t) => t.scos, 'scos', 1)
.having((t) => t.ssin, 'ssin', 1)
.having((t) => t.tx, 'tx', 1)
.having((t) => t.ty, 'ty', 1),
);
});
});
}

0 comments on commit bf3c282

Please sign in to comment.