mirror of https://github.com/flutter/pinball.git
fix: rendering with `FilterQuality.medium` (#334)
* feat: defined HighFilterQualityCanvas * refactor: removed trailing comma * refactor: started defining CanvasComponent * feat: implemented CanvasComponent * docs: fixed typos * docs: changed template name * fix: merge conflict * refactor: set filterQuality to Medium * refactor: removed nullable from typdef * test: updated tests to FilterQuality.mediumpull/344/head
parent
155e316ba1
commit
5fb9a40e66
@ -0,0 +1,2 @@
|
||||
export 'canvas_component.dart';
|
||||
export 'z_canvas_component.dart';
|
@ -0,0 +1,47 @@
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flame/components.dart';
|
||||
import 'package:pinball_flame/src/canvas/canvas_wrapper.dart';
|
||||
|
||||
/// Called right before [Canvas.drawImageRect] is called.
|
||||
///
|
||||
/// This is useful since [Sprite.render] uses [Canvas.drawImageRect] to draw
|
||||
/// the [Sprite].
|
||||
typedef PaintFunction = void Function(Paint);
|
||||
|
||||
/// {@template canvas_component}
|
||||
/// Allows listening before the rendering of [Sprite]s.
|
||||
///
|
||||
/// The existance of this class is to hack around the fact that Flame doesn't
|
||||
/// provide a global way to modify the default [Paint] before rendering a
|
||||
/// [Sprite].
|
||||
/// {@endtemplate}
|
||||
class CanvasComponent extends Component {
|
||||
/// {@macro canvas_component}
|
||||
CanvasComponent({
|
||||
PaintFunction? onSpritePainted,
|
||||
Iterable<Component>? children,
|
||||
}) : _canvas = _Canvas(onSpritePainted: onSpritePainted),
|
||||
super(children: children);
|
||||
|
||||
final _Canvas _canvas;
|
||||
|
||||
@override
|
||||
void renderTree(Canvas canvas) {
|
||||
_canvas.canvas = canvas;
|
||||
super.renderTree(_canvas);
|
||||
}
|
||||
}
|
||||
|
||||
class _Canvas extends CanvasWrapper {
|
||||
_Canvas({PaintFunction? onSpritePainted})
|
||||
: _onSpritePainted = onSpritePainted;
|
||||
|
||||
final PaintFunction? _onSpritePainted;
|
||||
|
||||
@override
|
||||
void drawImageRect(Image image, Rect src, Rect dst, Paint paint) {
|
||||
_onSpritePainted?.call(paint);
|
||||
super.drawImageRect(image, src, dst, paint);
|
||||
}
|
||||
}
|
@ -1,85 +1,11 @@
|
||||
// ignore_for_file: public_member_api_docs
|
||||
|
||||
import 'dart:typed_data';
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flame/components.dart';
|
||||
|
||||
/// {@template z_canvas_component}
|
||||
/// Draws [ZIndex] components after the all non-[ZIndex] components have been
|
||||
/// drawn.
|
||||
/// {@endtemplate}
|
||||
class ZCanvasComponent extends Component {
|
||||
/// {@macro z_canvas_component}
|
||||
ZCanvasComponent({
|
||||
Iterable<Component>? children,
|
||||
}) : _zCanvas = ZCanvas(),
|
||||
super(children: children);
|
||||
|
||||
final ZCanvas _zCanvas;
|
||||
|
||||
@override
|
||||
void renderTree(Canvas canvas) {
|
||||
_zCanvas.canvas = canvas;
|
||||
super.renderTree(_zCanvas);
|
||||
_zCanvas.render();
|
||||
}
|
||||
}
|
||||
|
||||
/// Apply to any [Component] that will be rendered according to a
|
||||
/// [ZIndex.zIndex].
|
||||
///
|
||||
/// [ZIndex] components must be descendants of a [ZCanvasComponent].
|
||||
///
|
||||
/// {@macro z_canvas.render}
|
||||
mixin ZIndex on Component {
|
||||
/// The z-index of this component.
|
||||
///
|
||||
/// The higher the value, the later the component will be drawn. Hence,
|
||||
/// rendering in front of [Component]s with lower [zIndex] values.
|
||||
int zIndex = 0;
|
||||
|
||||
@override
|
||||
void renderTree(
|
||||
Canvas canvas,
|
||||
) {
|
||||
if (canvas is ZCanvas) {
|
||||
canvas.buffer(this);
|
||||
} else {
|
||||
super.renderTree(canvas);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The [ZCanvas] allows to postpone the rendering of [ZIndex] components.
|
||||
///
|
||||
/// You should not use this class directly.
|
||||
class ZCanvas implements Canvas {
|
||||
/// The [Canvas] to render to.
|
||||
///
|
||||
/// This is set by [ZCanvasComponent] when rendering.
|
||||
class CanvasWrapper implements Canvas {
|
||||
late Canvas canvas;
|
||||
|
||||
final List<ZIndex> _zBuffer = [];
|
||||
|
||||
/// Postpones the rendering of [ZIndex] component and its children.
|
||||
void buffer(ZIndex component) => _zBuffer.add(component);
|
||||
|
||||
/// Renders all [ZIndex] components and their children.
|
||||
///
|
||||
/// {@template z_canvas.render}
|
||||
/// The rendering order is defined by the parent [ZIndex]. The children of
|
||||
/// the same parent are rendered in the order they were added.
|
||||
///
|
||||
/// If two [Component]s ever overlap each other, and have the same
|
||||
/// [ZIndex.zIndex], there is no guarantee that the first one will be rendered
|
||||
/// before the second one.
|
||||
/// {@endtemplate}
|
||||
void render() => _zBuffer
|
||||
..sort((a, b) => a.zIndex.compareTo(b.zIndex))
|
||||
..whereType<Component>().forEach(_render)
|
||||
..clear();
|
||||
|
||||
void _render(Component component) => component.renderTree(canvas);
|
||||
|
||||
@override
|
||||
void clipPath(Path path, {bool doAntiAlias = true}) =>
|
||||
canvas.clipPath(path, doAntiAlias: doAntiAlias);
|
@ -0,0 +1,77 @@
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flame/components.dart';
|
||||
import 'package:pinball_flame/src/canvas/canvas_wrapper.dart';
|
||||
|
||||
/// {@template z_canvas_component}
|
||||
/// Draws [ZIndex] components after the all non-[ZIndex] components have been
|
||||
/// drawn.
|
||||
/// {@endtemplate}
|
||||
class ZCanvasComponent extends Component {
|
||||
/// {@macro z_canvas_component}
|
||||
ZCanvasComponent({
|
||||
Iterable<Component>? children,
|
||||
}) : _zCanvas = _ZCanvas(),
|
||||
super(children: children);
|
||||
|
||||
final _ZCanvas _zCanvas;
|
||||
|
||||
@override
|
||||
void renderTree(Canvas canvas) {
|
||||
_zCanvas.canvas = canvas;
|
||||
super.renderTree(_zCanvas);
|
||||
_zCanvas.render();
|
||||
}
|
||||
}
|
||||
|
||||
/// Apply to any [Component] that will be rendered according to a
|
||||
/// [ZIndex.zIndex].
|
||||
///
|
||||
/// [ZIndex] components must be descendants of a [ZCanvasComponent].
|
||||
///
|
||||
/// {@macro z_canvas.render}
|
||||
mixin ZIndex on Component {
|
||||
/// The z-index of this component.
|
||||
///
|
||||
/// The higher the value, the later the component will be drawn. Hence,
|
||||
/// rendering in front of [Component]s with lower [zIndex] values.
|
||||
int zIndex = 0;
|
||||
|
||||
@override
|
||||
void renderTree(
|
||||
Canvas canvas,
|
||||
) {
|
||||
if (canvas is _ZCanvas) {
|
||||
canvas.buffer(this);
|
||||
} else {
|
||||
super.renderTree(canvas);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The [_ZCanvas] allows to postpone the rendering of [ZIndex] components.
|
||||
///
|
||||
/// You should not use this class directly.
|
||||
class _ZCanvas extends CanvasWrapper {
|
||||
final List<ZIndex> _zBuffer = [];
|
||||
|
||||
/// Postpones the rendering of [ZIndex] component and its children.
|
||||
void buffer(ZIndex component) => _zBuffer.add(component);
|
||||
|
||||
/// Renders all [ZIndex] components and their children.
|
||||
///
|
||||
/// {@template z_canvas.render}
|
||||
/// The rendering order is defined by the parent [ZIndex]. The children of
|
||||
/// the same parent are rendered in the order they were added.
|
||||
///
|
||||
/// If two [Component]s ever overlap each other, and have the same
|
||||
/// [ZIndex.zIndex], there is no guarantee that the first one will be rendered
|
||||
/// before the second one.
|
||||
/// {@endtemplate}
|
||||
void render() => _zBuffer
|
||||
..sort((a, b) => a.zIndex.compareTo(b.zIndex))
|
||||
..whereType<Component>().forEach(_render)
|
||||
..clear();
|
||||
|
||||
void _render(Component component) => component.renderTree(canvas);
|
||||
}
|
@ -0,0 +1,144 @@
|
||||
// ignore_for_file: cascade_invocations
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flame/components.dart';
|
||||
import 'package:flame/game.dart';
|
||||
import 'package:flame_test/flame_test.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:pinball_flame/src/canvas/canvas_component.dart';
|
||||
|
||||
class _TestSpriteComponent extends SpriteComponent {}
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
group('CanvasComponent', () {
|
||||
final flameTester = FlameTester(FlameGame.new);
|
||||
|
||||
test('can be instantiated', () {
|
||||
expect(
|
||||
CanvasComponent(),
|
||||
isA<CanvasComponent>(),
|
||||
);
|
||||
});
|
||||
|
||||
flameTester.test('loads correctly', (game) async {
|
||||
final component = CanvasComponent();
|
||||
await game.ensureAdd(component);
|
||||
expect(game.contains(component), isTrue);
|
||||
});
|
||||
|
||||
flameTester.test(
|
||||
'adds children',
|
||||
(game) async {
|
||||
final component = Component();
|
||||
final canvas = CanvasComponent(
|
||||
onSpritePainted: (paint) => paint.filterQuality = FilterQuality.high,
|
||||
children: [component],
|
||||
);
|
||||
|
||||
await game.ensureAdd(canvas);
|
||||
|
||||
expect(
|
||||
canvas.children.contains(component),
|
||||
isTrue,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
flameTester.testGameWidget(
|
||||
'calls onSpritePainted when paiting a sprite',
|
||||
setUp: (game, tester) async {
|
||||
final spriteComponent = _TestSpriteComponent();
|
||||
|
||||
final completer = Completer<Image>();
|
||||
decodeImageFromList(
|
||||
Uint8List.fromList(_image),
|
||||
completer.complete,
|
||||
);
|
||||
spriteComponent.sprite = Sprite(await completer.future);
|
||||
|
||||
var calls = 0;
|
||||
final canvas = CanvasComponent(
|
||||
onSpritePainted: (paint) => calls++,
|
||||
children: [spriteComponent],
|
||||
);
|
||||
|
||||
await game.ensureAdd(canvas);
|
||||
await tester.pump();
|
||||
|
||||
expect(calls, equals(1));
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
const List<int> _image = <int>[
|
||||
0x89,
|
||||
0x50,
|
||||
0x4E,
|
||||
0x47,
|
||||
0x0D,
|
||||
0x0A,
|
||||
0x1A,
|
||||
0x0A,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x0D,
|
||||
0x49,
|
||||
0x48,
|
||||
0x44,
|
||||
0x52,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x01,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x01,
|
||||
0x08,
|
||||
0x06,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x1F,
|
||||
0x15,
|
||||
0xC4,
|
||||
0x89,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x0A,
|
||||
0x49,
|
||||
0x44,
|
||||
0x41,
|
||||
0x54,
|
||||
0x78,
|
||||
0x9C,
|
||||
0x63,
|
||||
0x00,
|
||||
0x01,
|
||||
0x00,
|
||||
0x00,
|
||||
0x05,
|
||||
0x00,
|
||||
0x01,
|
||||
0x0D,
|
||||
0x0A,
|
||||
0x2D,
|
||||
0xB4,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x49,
|
||||
0x45,
|
||||
0x4E,
|
||||
0x44,
|
||||
0xAE,
|
||||
];
|
@ -0,0 +1,353 @@
|
||||
import 'dart:typed_data';
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flutter/material.dart' hide Image;
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
import 'package:pinball_flame/src/canvas/canvas_wrapper.dart';
|
||||
|
||||
class _MockCanvas extends Mock implements Canvas {}
|
||||
|
||||
class _MockImage extends Mock implements Image {}
|
||||
|
||||
class _MockPicture extends Mock implements Picture {}
|
||||
|
||||
class _MockParagraph extends Mock implements Paragraph {}
|
||||
|
||||
class _MockVertices extends Mock implements Vertices {}
|
||||
|
||||
void main() {
|
||||
group('CanvasWrapper', () {
|
||||
group('CanvasWrapper', () {
|
||||
late Canvas canvas;
|
||||
late Path path;
|
||||
late RRect rRect;
|
||||
late Rect rect;
|
||||
late Paint paint;
|
||||
late Image atlas;
|
||||
late BlendMode blendMode;
|
||||
late Color color;
|
||||
late Offset offset;
|
||||
late Float64List float64list;
|
||||
late Float32List float32list;
|
||||
late Int32List int32list;
|
||||
late Picture picture;
|
||||
late Paragraph paragraph;
|
||||
late Vertices vertices;
|
||||
|
||||
setUp(() {
|
||||
canvas = _MockCanvas();
|
||||
path = Path();
|
||||
rRect = RRect.zero;
|
||||
rect = Rect.zero;
|
||||
paint = Paint();
|
||||
atlas = _MockImage();
|
||||
blendMode = BlendMode.clear;
|
||||
color = Colors.black;
|
||||
offset = Offset.zero;
|
||||
float64list = Float64List(1);
|
||||
float32list = Float32List(1);
|
||||
int32list = Int32List(1);
|
||||
picture = _MockPicture();
|
||||
paragraph = _MockParagraph();
|
||||
vertices = _MockVertices();
|
||||
});
|
||||
|
||||
test("clipPath calls Canvas's clipPath", () {
|
||||
CanvasWrapper()
|
||||
..canvas = canvas
|
||||
..clipPath(path, doAntiAlias: false);
|
||||
verify(
|
||||
() => canvas.clipPath(path, doAntiAlias: false),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("clipRRect calls Canvas's clipRRect", () {
|
||||
CanvasWrapper()
|
||||
..canvas = canvas
|
||||
..clipRRect(rRect, doAntiAlias: false);
|
||||
verify(
|
||||
() => canvas.clipRRect(rRect, doAntiAlias: false),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("clipRect calls Canvas's clipRect", () {
|
||||
CanvasWrapper()
|
||||
..canvas = canvas
|
||||
..clipRect(rect, doAntiAlias: false);
|
||||
verify(
|
||||
() => canvas.clipRect(rect, doAntiAlias: false),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawArc calls Canvas's drawArc", () {
|
||||
CanvasWrapper()
|
||||
..canvas = canvas
|
||||
..drawArc(rect, 0, 1, false, paint);
|
||||
verify(
|
||||
() => canvas.drawArc(rect, 0, 1, false, paint),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawAtlas calls Canvas's drawAtlas", () {
|
||||
CanvasWrapper()
|
||||
..canvas = canvas
|
||||
..drawAtlas(atlas, [], [], [], blendMode, rect, paint);
|
||||
verify(
|
||||
() => canvas.drawAtlas(atlas, [], [], [], blendMode, rect, paint),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawCircle calls Canvas's drawCircle", () {
|
||||
CanvasWrapper()
|
||||
..canvas = canvas
|
||||
..drawCircle(offset, 0, paint);
|
||||
verify(
|
||||
() => canvas.drawCircle(offset, 0, paint),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawColor calls Canvas's drawColor", () {
|
||||
CanvasWrapper()
|
||||
..canvas = canvas
|
||||
..drawColor(color, blendMode);
|
||||
verify(
|
||||
() => canvas.drawColor(color, blendMode),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawDRRect calls Canvas's drawDRRect", () {
|
||||
CanvasWrapper()
|
||||
..canvas = canvas
|
||||
..drawDRRect(rRect, rRect, paint);
|
||||
verify(
|
||||
() => canvas.drawDRRect(rRect, rRect, paint),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawImage calls Canvas's drawImage", () {
|
||||
CanvasWrapper()
|
||||
..canvas = canvas
|
||||
..drawImage(atlas, offset, paint);
|
||||
verify(
|
||||
() => canvas.drawImage(atlas, offset, paint),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawImageNine calls Canvas's drawImageNine", () {
|
||||
CanvasWrapper()
|
||||
..canvas = canvas
|
||||
..drawImageNine(atlas, rect, rect, paint);
|
||||
verify(
|
||||
() => canvas.drawImageNine(atlas, rect, rect, paint),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawImageRect calls Canvas's drawImageRect", () {
|
||||
CanvasWrapper()
|
||||
..canvas = canvas
|
||||
..drawImageRect(atlas, rect, rect, paint);
|
||||
verify(
|
||||
() => canvas.drawImageRect(atlas, rect, rect, paint),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawLine calls Canvas's drawLine", () {
|
||||
CanvasWrapper()
|
||||
..canvas = canvas
|
||||
..drawLine(offset, offset, paint);
|
||||
verify(
|
||||
() => canvas.drawLine(offset, offset, paint),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawOval calls Canvas's drawOval", () {
|
||||
CanvasWrapper()
|
||||
..canvas = canvas
|
||||
..drawOval(rect, paint);
|
||||
verify(
|
||||
() => canvas.drawOval(rect, paint),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawPaint calls Canvas's drawPaint", () {
|
||||
CanvasWrapper()
|
||||
..canvas = canvas
|
||||
..drawPaint(paint);
|
||||
verify(
|
||||
() => canvas.drawPaint(paint),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawParagraph calls Canvas's drawParagraph", () {
|
||||
CanvasWrapper()
|
||||
..canvas = canvas
|
||||
..drawParagraph(paragraph, offset);
|
||||
verify(
|
||||
() => canvas.drawParagraph(paragraph, offset),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawPath calls Canvas's drawPath", () {
|
||||
CanvasWrapper()
|
||||
..canvas = canvas
|
||||
..drawPath(path, paint);
|
||||
verify(
|
||||
() => canvas.drawPath(path, paint),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawPicture calls Canvas's drawPicture", () {
|
||||
CanvasWrapper()
|
||||
..canvas = canvas
|
||||
..drawPicture(picture);
|
||||
verify(
|
||||
() => canvas.drawPicture(picture),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawPoints calls Canvas's drawPoints", () {
|
||||
CanvasWrapper()
|
||||
..canvas = canvas
|
||||
..drawPoints(PointMode.points, [offset], paint);
|
||||
verify(
|
||||
() => canvas.drawPoints(PointMode.points, [offset], paint),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawRRect calls Canvas's drawRRect", () {
|
||||
CanvasWrapper()
|
||||
..canvas = canvas
|
||||
..drawRRect(rRect, paint);
|
||||
verify(
|
||||
() => canvas.drawRRect(rRect, paint),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawRawAtlas calls Canvas's drawRawAtlas", () {
|
||||
CanvasWrapper()
|
||||
..canvas = canvas
|
||||
..drawRawAtlas(
|
||||
atlas,
|
||||
float32list,
|
||||
float32list,
|
||||
int32list,
|
||||
BlendMode.clear,
|
||||
rect,
|
||||
paint,
|
||||
);
|
||||
verify(
|
||||
() => canvas.drawRawAtlas(
|
||||
atlas,
|
||||
float32list,
|
||||
float32list,
|
||||
int32list,
|
||||
BlendMode.clear,
|
||||
rect,
|
||||
paint,
|
||||
),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawRawPoints calls Canvas's drawRawPoints", () {
|
||||
CanvasWrapper()
|
||||
..canvas = canvas
|
||||
..drawRawPoints(PointMode.points, float32list, paint);
|
||||
verify(
|
||||
() => canvas.drawRawPoints(PointMode.points, float32list, paint),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawRect calls Canvas's drawRect", () {
|
||||
CanvasWrapper()
|
||||
..canvas = canvas
|
||||
..drawRect(rect, paint);
|
||||
verify(
|
||||
() => canvas.drawRect(rect, paint),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawShadow calls Canvas's drawShadow", () {
|
||||
CanvasWrapper()
|
||||
..canvas = canvas
|
||||
..drawShadow(path, color, 0, false);
|
||||
verify(
|
||||
() => canvas.drawShadow(path, color, 0, false),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawVertices calls Canvas's drawVertices", () {
|
||||
CanvasWrapper()
|
||||
..canvas = canvas
|
||||
..drawVertices(vertices, blendMode, paint);
|
||||
verify(
|
||||
() => canvas.drawVertices(vertices, blendMode, paint),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("getSaveCount calls Canvas's getSaveCount", () {
|
||||
final canvasWrapper = CanvasWrapper()..canvas = canvas;
|
||||
when(() => canvas.getSaveCount()).thenReturn(1);
|
||||
canvasWrapper.getSaveCount();
|
||||
verify(() => canvas.getSaveCount()).called(1);
|
||||
expect(canvasWrapper.getSaveCount(), 1);
|
||||
});
|
||||
|
||||
test("restore calls Canvas's restore", () {
|
||||
CanvasWrapper()
|
||||
..canvas = canvas
|
||||
..restore();
|
||||
verify(() => canvas.restore()).called(1);
|
||||
});
|
||||
|
||||
test("rotate calls Canvas's rotate", () {
|
||||
CanvasWrapper()
|
||||
..canvas = canvas
|
||||
..rotate(0);
|
||||
verify(() => canvas.rotate(0)).called(1);
|
||||
});
|
||||
|
||||
test("save calls Canvas's save", () {
|
||||
CanvasWrapper()
|
||||
..canvas = canvas
|
||||
..save();
|
||||
verify(() => canvas.save()).called(1);
|
||||
});
|
||||
|
||||
test("saveLayer calls Canvas's saveLayer", () {
|
||||
CanvasWrapper()
|
||||
..canvas = canvas
|
||||
..saveLayer(rect, paint);
|
||||
verify(() => canvas.saveLayer(rect, paint)).called(1);
|
||||
});
|
||||
|
||||
test("scale calls Canvas's scale", () {
|
||||
CanvasWrapper()
|
||||
..canvas = canvas
|
||||
..scale(0, 0);
|
||||
verify(() => canvas.scale(0, 0)).called(1);
|
||||
});
|
||||
|
||||
test("skew calls Canvas's skew", () {
|
||||
CanvasWrapper()
|
||||
..canvas = canvas
|
||||
..skew(0, 0);
|
||||
verify(() => canvas.skew(0, 0)).called(1);
|
||||
});
|
||||
|
||||
test("transform calls Canvas's transform", () {
|
||||
CanvasWrapper()
|
||||
..canvas = canvas
|
||||
..transform(float64list);
|
||||
verify(() => canvas.transform(float64list)).called(1);
|
||||
});
|
||||
|
||||
test("translate calls Canvas's translate", () {
|
||||
CanvasWrapper()
|
||||
..canvas = canvas
|
||||
..translate(0, 0);
|
||||
verify(() => canvas.translate(0, 0)).called(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
// ignore_for_file: cascade_invocations
|
||||
|
||||
import 'package:flame/components.dart';
|
||||
import 'package:flame/game.dart';
|
||||
import 'package:flame_test/flame_test.dart';
|
||||
import 'package:flutter/material.dart' hide Image;
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:pinball_flame/pinball_flame.dart';
|
||||
|
||||
class _TestCircleComponent extends CircleComponent with ZIndex {
|
||||
_TestCircleComponent(Color color)
|
||||
: super(
|
||||
paint: Paint()..color = color,
|
||||
radius: 10,
|
||||
);
|
||||
}
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
group('ZCanvasComponent', () {
|
||||
final flameTester = FlameTester(FlameGame.new);
|
||||
const goldensFilePath = '../goldens/rendering/';
|
||||
|
||||
test('can be instantiated', () {
|
||||
expect(
|
||||
ZCanvasComponent(),
|
||||
isA<ZCanvasComponent>(),
|
||||
);
|
||||
});
|
||||
|
||||
flameTester.test('loads correctly', (game) async {
|
||||
final component = ZCanvasComponent();
|
||||
await game.ensureAdd(component);
|
||||
expect(game.contains(component), isTrue);
|
||||
});
|
||||
|
||||
flameTester.testGameWidget(
|
||||
'red circle renders behind blue circle',
|
||||
setUp: (game, tester) async {
|
||||
final canvas = ZCanvasComponent(
|
||||
children: [
|
||||
_TestCircleComponent(Colors.blue)..zIndex = 1,
|
||||
_TestCircleComponent(Colors.red)..zIndex = 0,
|
||||
],
|
||||
);
|
||||
await game.ensureAdd(canvas);
|
||||
|
||||
game.camera.followVector2(Vector2.zero());
|
||||
},
|
||||
verify: (game, tester) async {
|
||||
await expectLater(
|
||||
find.byGame<FlameGame>(),
|
||||
matchesGoldenFile('${goldensFilePath}red_blue.png'),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
flameTester.testGameWidget(
|
||||
'blue circle renders behind red circle',
|
||||
setUp: (game, tester) async {
|
||||
final canvas = ZCanvasComponent(
|
||||
children: [
|
||||
_TestCircleComponent(Colors.blue)..zIndex = 0,
|
||||
_TestCircleComponent(Colors.red)..zIndex = 1
|
||||
],
|
||||
);
|
||||
await game.ensureAdd(canvas);
|
||||
|
||||
game.camera.followVector2(Vector2.zero());
|
||||
},
|
||||
verify: (game, tester) async {
|
||||
await expectLater(
|
||||
find.byGame<FlameGame>(),
|
||||
matchesGoldenFile('${goldensFilePath}blue_red.png'),
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 22 KiB |
@ -1,385 +0,0 @@
|
||||
// ignore_for_file: cascade_invocations
|
||||
|
||||
import 'dart:typed_data';
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flame/components.dart';
|
||||
import 'package:flame/game.dart';
|
||||
import 'package:flame_test/flame_test.dart';
|
||||
import 'package:flutter/material.dart' hide Image;
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
import 'package:pinball_flame/pinball_flame.dart';
|
||||
|
||||
class _TestCircleComponent extends CircleComponent with ZIndex {
|
||||
_TestCircleComponent(Color color)
|
||||
: super(
|
||||
paint: Paint()..color = color,
|
||||
radius: 10,
|
||||
);
|
||||
}
|
||||
|
||||
class _MockCanvas extends Mock implements Canvas {}
|
||||
|
||||
class _MockImage extends Mock implements Image {}
|
||||
|
||||
class _MockPicture extends Mock implements Picture {}
|
||||
|
||||
class _MockParagraph extends Mock implements Paragraph {}
|
||||
|
||||
class _MockVertices extends Mock implements Vertices {}
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
final flameTester = FlameTester(FlameGame.new);
|
||||
const goldenPrefix = 'golden/rendering/';
|
||||
|
||||
group('ZCanvasComponent', () {
|
||||
flameTester.test('loads correctly', (game) async {
|
||||
final component = ZCanvasComponent();
|
||||
await game.ensureAdd(component);
|
||||
expect(game.contains(component), isTrue);
|
||||
});
|
||||
|
||||
flameTester.testGameWidget(
|
||||
'red circle renders behind blue circle',
|
||||
setUp: (game, tester) async {
|
||||
final canvas = ZCanvasComponent(
|
||||
children: [
|
||||
_TestCircleComponent(Colors.blue)..zIndex = 1,
|
||||
_TestCircleComponent(Colors.red)..zIndex = 0,
|
||||
],
|
||||
);
|
||||
await game.ensureAdd(canvas);
|
||||
|
||||
game.camera.followVector2(Vector2.zero());
|
||||
},
|
||||
verify: (game, tester) async {
|
||||
await expectLater(
|
||||
find.byGame<FlameGame>(),
|
||||
matchesGoldenFile('${goldenPrefix}red_blue.png'),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
flameTester.testGameWidget(
|
||||
'blue circle renders behind red circle',
|
||||
setUp: (game, tester) async {
|
||||
final canvas = ZCanvasComponent(
|
||||
children: [
|
||||
_TestCircleComponent(Colors.blue)..zIndex = 0,
|
||||
_TestCircleComponent(Colors.red)..zIndex = 1
|
||||
],
|
||||
);
|
||||
await game.ensureAdd(canvas);
|
||||
|
||||
game.camera.followVector2(Vector2.zero());
|
||||
},
|
||||
verify: (game, tester) async {
|
||||
await expectLater(
|
||||
find.byGame<FlameGame>(),
|
||||
matchesGoldenFile('${goldenPrefix}blue_red.png'),
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
group('ZCanvas', () {
|
||||
late Canvas canvas;
|
||||
late Path path;
|
||||
late RRect rRect;
|
||||
late Rect rect;
|
||||
late Paint paint;
|
||||
late Image atlas;
|
||||
late BlendMode blendMode;
|
||||
late Color color;
|
||||
late Offset offset;
|
||||
late Float64List float64list;
|
||||
late Float32List float32list;
|
||||
late Int32List int32list;
|
||||
late Picture picture;
|
||||
late Paragraph paragraph;
|
||||
late Vertices vertices;
|
||||
|
||||
setUp(() {
|
||||
canvas = _MockCanvas();
|
||||
path = Path();
|
||||
rRect = RRect.zero;
|
||||
rect = Rect.zero;
|
||||
paint = Paint();
|
||||
atlas = _MockImage();
|
||||
blendMode = BlendMode.clear;
|
||||
color = Colors.black;
|
||||
offset = Offset.zero;
|
||||
float64list = Float64List(1);
|
||||
float32list = Float32List(1);
|
||||
int32list = Int32List(1);
|
||||
picture = _MockPicture();
|
||||
paragraph = _MockParagraph();
|
||||
vertices = _MockVertices();
|
||||
});
|
||||
|
||||
test("clipPath calls Canvas's clipPath", () {
|
||||
final zcanvas = ZCanvas()..canvas = canvas;
|
||||
zcanvas.clipPath(path, doAntiAlias: false);
|
||||
verify(
|
||||
() => canvas.clipPath(path, doAntiAlias: false),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("clipRRect calls Canvas's clipRRect", () {
|
||||
final zcanvas = ZCanvas()..canvas = canvas;
|
||||
zcanvas.clipRRect(rRect, doAntiAlias: false);
|
||||
verify(
|
||||
() => canvas.clipRRect(rRect, doAntiAlias: false),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("clipRect calls Canvas's clipRect", () {
|
||||
final zcanvas = ZCanvas()..canvas = canvas;
|
||||
zcanvas.clipRect(rect, doAntiAlias: false);
|
||||
verify(
|
||||
() => canvas.clipRect(rect, doAntiAlias: false),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawArc calls Canvas's drawArc", () {
|
||||
final zcanvas = ZCanvas()..canvas = canvas;
|
||||
zcanvas.drawArc(rect, 0, 1, false, paint);
|
||||
verify(
|
||||
() => canvas.drawArc(rect, 0, 1, false, paint),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawAtlas calls Canvas's drawAtlas", () {
|
||||
final zcanvas = ZCanvas()..canvas = canvas;
|
||||
zcanvas.drawAtlas(atlas, [], [], [], blendMode, rect, paint);
|
||||
verify(
|
||||
() => canvas.drawAtlas(atlas, [], [], [], blendMode, rect, paint),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawCircle calls Canvas's drawCircle", () {
|
||||
final zcanvas = ZCanvas()..canvas = canvas;
|
||||
zcanvas.drawCircle(offset, 0, paint);
|
||||
verify(
|
||||
() => canvas.drawCircle(offset, 0, paint),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawColor calls Canvas's drawColor", () {
|
||||
final zcanvas = ZCanvas()..canvas = canvas;
|
||||
zcanvas.drawColor(color, blendMode);
|
||||
verify(
|
||||
() => canvas.drawColor(color, blendMode),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawDRRect calls Canvas's drawDRRect", () {
|
||||
final zcanvas = ZCanvas()..canvas = canvas;
|
||||
zcanvas.drawDRRect(rRect, rRect, paint);
|
||||
verify(
|
||||
() => canvas.drawDRRect(rRect, rRect, paint),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawImage calls Canvas's drawImage", () {
|
||||
final zcanvas = ZCanvas()..canvas = canvas;
|
||||
zcanvas.drawImage(atlas, offset, paint);
|
||||
verify(
|
||||
() => canvas.drawImage(atlas, offset, paint),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawImageNine calls Canvas's drawImageNine", () {
|
||||
final zcanvas = ZCanvas()..canvas = canvas;
|
||||
zcanvas.drawImageNine(atlas, rect, rect, paint);
|
||||
verify(
|
||||
() => canvas.drawImageNine(atlas, rect, rect, paint),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawImageRect calls Canvas's drawImageRect", () {
|
||||
final zcanvas = ZCanvas()..canvas = canvas;
|
||||
zcanvas.drawImageRect(atlas, rect, rect, paint);
|
||||
verify(
|
||||
() => canvas.drawImageRect(atlas, rect, rect, paint),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawLine calls Canvas's drawLine", () {
|
||||
final zcanvas = ZCanvas()..canvas = canvas;
|
||||
zcanvas.drawLine(offset, offset, paint);
|
||||
verify(
|
||||
() => canvas.drawLine(offset, offset, paint),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawOval calls Canvas's drawOval", () {
|
||||
final zcanvas = ZCanvas()..canvas = canvas;
|
||||
zcanvas.drawOval(rect, paint);
|
||||
verify(
|
||||
() => canvas.drawOval(rect, paint),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawPaint calls Canvas's drawPaint", () {
|
||||
final zcanvas = ZCanvas()..canvas = canvas;
|
||||
zcanvas.drawPaint(paint);
|
||||
verify(
|
||||
() => canvas.drawPaint(paint),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawParagraph calls Canvas's drawParagraph", () {
|
||||
final zcanvas = ZCanvas()..canvas = canvas;
|
||||
zcanvas.drawParagraph(paragraph, offset);
|
||||
verify(
|
||||
() => canvas.drawParagraph(paragraph, offset),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawPath calls Canvas's drawPath", () {
|
||||
final zcanvas = ZCanvas()..canvas = canvas;
|
||||
zcanvas.drawPath(path, paint);
|
||||
verify(
|
||||
() => canvas.drawPath(path, paint),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawPicture calls Canvas's drawPicture", () {
|
||||
final zcanvas = ZCanvas()..canvas = canvas;
|
||||
zcanvas.drawPicture(picture);
|
||||
verify(
|
||||
() => canvas.drawPicture(picture),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawPoints calls Canvas's drawPoints", () {
|
||||
final zcanvas = ZCanvas()..canvas = canvas;
|
||||
zcanvas.drawPoints(PointMode.points, [offset], paint);
|
||||
verify(
|
||||
() => canvas.drawPoints(PointMode.points, [offset], paint),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawRRect calls Canvas's drawRRect", () {
|
||||
final zcanvas = ZCanvas()..canvas = canvas;
|
||||
zcanvas.drawRRect(rRect, paint);
|
||||
verify(
|
||||
() => canvas.drawRRect(rRect, paint),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawRawAtlas calls Canvas's drawRawAtlas", () {
|
||||
final zcanvas = ZCanvas()..canvas = canvas;
|
||||
zcanvas.drawRawAtlas(
|
||||
atlas,
|
||||
float32list,
|
||||
float32list,
|
||||
int32list,
|
||||
BlendMode.clear,
|
||||
rect,
|
||||
paint,
|
||||
);
|
||||
verify(
|
||||
() => canvas.drawRawAtlas(
|
||||
atlas,
|
||||
float32list,
|
||||
float32list,
|
||||
int32list,
|
||||
BlendMode.clear,
|
||||
rect,
|
||||
paint,
|
||||
),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawRawPoints calls Canvas's drawRawPoints", () {
|
||||
final zcanvas = ZCanvas()..canvas = canvas;
|
||||
zcanvas.drawRawPoints(PointMode.points, float32list, paint);
|
||||
verify(
|
||||
() => canvas.drawRawPoints(PointMode.points, float32list, paint),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawRect calls Canvas's drawRect", () {
|
||||
final zcanvas = ZCanvas()..canvas = canvas;
|
||||
zcanvas.drawRect(rect, paint);
|
||||
verify(
|
||||
() => canvas.drawRect(rect, paint),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawShadow calls Canvas's drawShadow", () {
|
||||
final zcanvas = ZCanvas()..canvas = canvas;
|
||||
zcanvas.drawShadow(path, color, 0, false);
|
||||
verify(
|
||||
() => canvas.drawShadow(path, color, 0, false),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("drawVertices calls Canvas's drawVertices", () {
|
||||
final zcanvas = ZCanvas()..canvas = canvas;
|
||||
zcanvas.drawVertices(vertices, blendMode, paint);
|
||||
verify(
|
||||
() => canvas.drawVertices(vertices, blendMode, paint),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test("getSaveCount calls Canvas's getSaveCount", () {
|
||||
final zcanvas = ZCanvas()..canvas = canvas;
|
||||
when(() => canvas.getSaveCount()).thenReturn(1);
|
||||
zcanvas.getSaveCount();
|
||||
verify(() => canvas.getSaveCount()).called(1);
|
||||
});
|
||||
|
||||
test("restore calls Canvas's restore", () {
|
||||
final zcanvas = ZCanvas()..canvas = canvas;
|
||||
zcanvas.restore();
|
||||
verify(() => canvas.restore()).called(1);
|
||||
});
|
||||
|
||||
test("rotate calls Canvas's rotate", () {
|
||||
final zcanvas = ZCanvas()..canvas = canvas;
|
||||
zcanvas.rotate(0);
|
||||
verify(() => canvas.rotate(0)).called(1);
|
||||
});
|
||||
|
||||
test("save calls Canvas's save", () {
|
||||
final zcanvas = ZCanvas()..canvas = canvas;
|
||||
zcanvas.save();
|
||||
verify(() => canvas.save()).called(1);
|
||||
});
|
||||
|
||||
test("saveLayer calls Canvas's saveLayer", () {
|
||||
final zcanvas = ZCanvas()..canvas = canvas;
|
||||
zcanvas.saveLayer(rect, paint);
|
||||
verify(() => canvas.saveLayer(rect, paint)).called(1);
|
||||
});
|
||||
|
||||
test("scale calls Canvas's scale", () {
|
||||
final zcanvas = ZCanvas()..canvas = canvas;
|
||||
zcanvas.scale(0, 0);
|
||||
verify(() => canvas.scale(0, 0)).called(1);
|
||||
});
|
||||
|
||||
test("skew calls Canvas's skew", () {
|
||||
final zcanvas = ZCanvas()..canvas = canvas;
|
||||
zcanvas.skew(0, 0);
|
||||
verify(() => canvas.skew(0, 0)).called(1);
|
||||
});
|
||||
|
||||
test("transform calls Canvas's transform", () {
|
||||
final zcanvas = ZCanvas()..canvas = canvas;
|
||||
zcanvas.transform(float64list);
|
||||
verify(() => canvas.transform(float64list)).called(1);
|
||||
});
|
||||
|
||||
test("translate calls Canvas's translate", () {
|
||||
final zcanvas = ZCanvas()..canvas = canvas;
|
||||
zcanvas.translate(0, 0);
|
||||
verify(() => canvas.translate(0, 0)).called(1);
|
||||
});
|
||||
});
|
||||
}
|
Loading…
Reference in new issue