mirror of
https://github.com/flame-engine/flame.git
synced 2025-11-01 01:18:38 +08:00
feat: Add paint layers to HasPaint and associated component renders (#2073)
This commit is contained in:
@ -34,7 +34,8 @@ class Ball extends CircleComponent
|
|||||||
static const degree = math.pi / 180;
|
static const degree = math.pi / 180;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void>? onLoad() {
|
Future<void> onLoad() async {
|
||||||
|
super.onLoad();
|
||||||
_resetBall;
|
_resetBall;
|
||||||
final hitBox = CircleHitbox(
|
final hitBox = CircleHitbox(
|
||||||
radius: radius,
|
radius: radius,
|
||||||
@ -43,8 +44,6 @@ class Ball extends CircleComponent
|
|||||||
addAll([
|
addAll([
|
||||||
hitBox,
|
hitBox,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return super.onLoad();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@ -4,21 +4,22 @@ import 'dart:ui';
|
|||||||
import 'package:flame/components.dart';
|
import 'package:flame/components.dart';
|
||||||
import 'package:flame/effects.dart';
|
import 'package:flame/effects.dart';
|
||||||
import 'package:flame/src/palette.dart';
|
import 'package:flame/src/palette.dart';
|
||||||
|
import 'package:meta/meta.dart';
|
||||||
|
|
||||||
/// Adds a collection of paints to a component
|
/// Adds a collection of paints and paint layers to a component
|
||||||
///
|
///
|
||||||
/// Component will always have a main Paint that can be accessed
|
/// Component will always have a main Paint that can be accessed
|
||||||
/// by the [paint] attribute and other paints can be manipulated/accessed
|
/// by the [paint] attribute and other paints can be manipulated/accessed
|
||||||
/// using [getPaint], [setPaint] and [deletePaint] by a paintId of generic type
|
/// using [getPaint], [setPaint] and [deletePaint] by a paintId of generic type
|
||||||
/// [T], that can be omitted if the component only have one paint.
|
/// [T], that can be omitted if the component only has one paint.
|
||||||
|
/// [paintLayers] paints should be drawn in list order during the render. The
|
||||||
|
/// main Paint is the first element.
|
||||||
mixin HasPaint<T extends Object> on Component implements OpacityProvider {
|
mixin HasPaint<T extends Object> on Component implements OpacityProvider {
|
||||||
final Map<T, Paint> _paints = {};
|
late final Map<T, Paint> _paints = {};
|
||||||
|
|
||||||
Paint paint = BasicPalette.white.paint();
|
Paint paint = BasicPalette.white.paint();
|
||||||
|
|
||||||
void _assertGenerics() {
|
@internal
|
||||||
assert(T != Object, 'A generics type is missing on the HasPaint mixin');
|
List<Paint>? paintLayersInternal;
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets a paint from the collection.
|
/// Gets a paint from the collection.
|
||||||
///
|
///
|
||||||
@ -28,7 +29,6 @@ mixin HasPaint<T extends Object> on Component implements OpacityProvider {
|
|||||||
return paint;
|
return paint;
|
||||||
}
|
}
|
||||||
|
|
||||||
_assertGenerics();
|
|
||||||
final _paint = _paints[paintId];
|
final _paint = _paints[paintId];
|
||||||
|
|
||||||
if (_paint == null) {
|
if (_paint == null) {
|
||||||
@ -40,16 +40,29 @@ mixin HasPaint<T extends Object> on Component implements OpacityProvider {
|
|||||||
|
|
||||||
/// Sets a paint on the collection.
|
/// Sets a paint on the collection.
|
||||||
void setPaint(T paintId, Paint paint) {
|
void setPaint(T paintId, Paint paint) {
|
||||||
_assertGenerics();
|
|
||||||
_paints[paintId] = paint;
|
_paints[paintId] = paint;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes a paint from the collection.
|
/// Removes a paint from the collection.
|
||||||
void deletePaint(T paintId) {
|
void deletePaint(T paintId) {
|
||||||
_assertGenerics();
|
|
||||||
_paints.remove(paintId);
|
_paints.remove(paintId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// List of paints to use (in order) during render.
|
||||||
|
List<Paint> get paintLayers {
|
||||||
|
if (!hasPaintLayers) {
|
||||||
|
return paintLayersInternal = [];
|
||||||
|
}
|
||||||
|
return paintLayersInternal!;
|
||||||
|
}
|
||||||
|
|
||||||
|
set paintLayers(List<Paint> paintLayers) {
|
||||||
|
paintLayersInternal = paintLayers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Whether there are any paint layers defined for the component.
|
||||||
|
bool get hasPaintLayers => paintLayersInternal?.isNotEmpty ?? false;
|
||||||
|
|
||||||
/// Manipulate the paint to make it fully transparent.
|
/// Manipulate the paint to make it fully transparent.
|
||||||
void makeTransparent({T? paintId}) {
|
void makeTransparent({T? paintId}) {
|
||||||
setOpacity(0, paintId: paintId);
|
setOpacity(0, paintId: paintId);
|
||||||
@ -130,9 +143,13 @@ mixin HasPaint<T extends Object> on Component implements OpacityProvider {
|
|||||||
///
|
///
|
||||||
/// Note: Each call results in a new [OpacityProvider] and hence the cached
|
/// Note: Each call results in a new [OpacityProvider] and hence the cached
|
||||||
/// opacity ratios are calculated using opacities when this method was called.
|
/// opacity ratios are calculated using opacities when this method was called.
|
||||||
OpacityProvider opacityProviderOfList({List<T?>? paintIds}) {
|
OpacityProvider opacityProviderOfList({
|
||||||
|
List<T?>? paintIds,
|
||||||
|
bool includeLayers = true,
|
||||||
|
}) {
|
||||||
return _MultiPaintOpacityProvider(
|
return _MultiPaintOpacityProvider(
|
||||||
paintIds ?? (List<T?>.from(_paints.keys)..add(null)),
|
paintIds ?? (List<T?>.from(_paints.keys)..add(null)),
|
||||||
|
includeLayers,
|
||||||
this,
|
this,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -152,19 +169,25 @@ class _ProxyOpacityProvider<T extends Object> implements OpacityProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _MultiPaintOpacityProvider<T extends Object> implements OpacityProvider {
|
class _MultiPaintOpacityProvider<T extends Object> implements OpacityProvider {
|
||||||
_MultiPaintOpacityProvider(this.paintIds, this.target) {
|
_MultiPaintOpacityProvider(this.paintIds, this.includeLayers, this.target) {
|
||||||
final maxOpacity = opacity;
|
final maxOpacity = opacity;
|
||||||
|
|
||||||
_opacityRatios = List<double>.generate(
|
_opacityRatios = [
|
||||||
paintIds.length,
|
for (final paintId in paintIds)
|
||||||
(index) =>
|
target.getOpacity(paintId: paintId) / maxOpacity,
|
||||||
target.getOpacity(paintId: paintIds.elementAt(index)) / maxOpacity,
|
];
|
||||||
);
|
_layerOpacityRatios = target.paintLayersInternal
|
||||||
|
?.map(
|
||||||
|
(paint) => paint.color.opacity / maxOpacity,
|
||||||
|
)
|
||||||
|
.toList(growable: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<T?> paintIds;
|
final List<T?> paintIds;
|
||||||
final HasPaint<T> target;
|
final HasPaint<T> target;
|
||||||
|
final bool includeLayers;
|
||||||
late final List<double> _opacityRatios;
|
late final List<double> _opacityRatios;
|
||||||
|
late final List<double>? _layerOpacityRatios;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
double get opacity {
|
double get opacity {
|
||||||
@ -173,6 +196,11 @@ class _MultiPaintOpacityProvider<T extends Object> implements OpacityProvider {
|
|||||||
for (final paintId in paintIds) {
|
for (final paintId in paintIds) {
|
||||||
maxOpacity = max(target.getOpacity(paintId: paintId), maxOpacity);
|
maxOpacity = max(target.getOpacity(paintId: paintId), maxOpacity);
|
||||||
}
|
}
|
||||||
|
if (includeLayers) {
|
||||||
|
target.paintLayersInternal?.forEach(
|
||||||
|
(paint) => maxOpacity = max(paint.color.opacity, maxOpacity),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return maxOpacity;
|
return maxOpacity;
|
||||||
}
|
}
|
||||||
@ -185,5 +213,13 @@ class _MultiPaintOpacityProvider<T extends Object> implements OpacityProvider {
|
|||||||
paintId: paintIds.elementAt(i),
|
paintId: paintIds.elementAt(i),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (includeLayers) {
|
||||||
|
final paintLayersInternal = target.paintLayersInternal;
|
||||||
|
for (var i = 0; i < (paintLayersInternal?.length ?? 0); ++i) {
|
||||||
|
paintLayersInternal![i].color = paintLayersInternal[i]
|
||||||
|
.color
|
||||||
|
.withOpacity(value * _layerOpacityRatios![i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import 'package:flame/extensions.dart';
|
|||||||
import 'package:flame/geometry.dart';
|
import 'package:flame/geometry.dart';
|
||||||
import 'package:flame/src/effects/provider_interfaces.dart';
|
import 'package:flame/src/effects/provider_interfaces.dart';
|
||||||
import 'package:flame/src/utils/solve_quadratic.dart';
|
import 'package:flame/src/utils/solve_quadratic.dart';
|
||||||
|
import 'package:meta/meta.dart';
|
||||||
|
|
||||||
class CircleComponent extends ShapeComponent implements SizeProvider {
|
class CircleComponent extends ShapeComponent implements SizeProvider {
|
||||||
/// With this constructor you can create your [CircleComponent] from a radius
|
/// With this constructor you can create your [CircleComponent] from a radius
|
||||||
@ -18,6 +19,7 @@ class CircleComponent extends ShapeComponent implements SizeProvider {
|
|||||||
super.children,
|
super.children,
|
||||||
super.priority,
|
super.priority,
|
||||||
super.paint,
|
super.paint,
|
||||||
|
super.paintLayers,
|
||||||
}) : super(size: Vector2.all((radius ?? 0) * 2));
|
}) : super(size: Vector2.all((radius ?? 0) * 2));
|
||||||
|
|
||||||
/// With this constructor you define the [CircleComponent] in relation to the
|
/// With this constructor you define the [CircleComponent] in relation to the
|
||||||
@ -30,8 +32,19 @@ class CircleComponent extends ShapeComponent implements SizeProvider {
|
|||||||
super.angle,
|
super.angle,
|
||||||
super.anchor,
|
super.anchor,
|
||||||
super.paint,
|
super.paint,
|
||||||
|
super.paintLayers,
|
||||||
}) : super(size: Vector2.all(relation * min(parentSize.x, parentSize.y)));
|
}) : super(size: Vector2.all(relation * min(parentSize.x, parentSize.y)));
|
||||||
|
|
||||||
|
@override
|
||||||
|
@mustCallSuper
|
||||||
|
Future<void> onLoad() async {
|
||||||
|
void updateCenterOffset() => _centerOffset = Offset(size.x / 2, size.y / 2);
|
||||||
|
size.addListener(updateCenterOffset);
|
||||||
|
updateCenterOffset();
|
||||||
|
}
|
||||||
|
|
||||||
|
late Offset _centerOffset;
|
||||||
|
|
||||||
/// Get the radius of the circle before scaling.
|
/// Get the radius of the circle before scaling.
|
||||||
double get radius {
|
double get radius {
|
||||||
return min(size.x, size.y) / 2;
|
return min(size.x, size.y) / 2;
|
||||||
@ -56,14 +69,20 @@ class CircleComponent extends ShapeComponent implements SizeProvider {
|
|||||||
@override
|
@override
|
||||||
void render(Canvas canvas) {
|
void render(Canvas canvas) {
|
||||||
if (renderShape) {
|
if (renderShape) {
|
||||||
canvas.drawCircle((size / 2).toOffset(), radius, paint);
|
if (hasPaintLayers) {
|
||||||
|
for (final paint in paintLayers) {
|
||||||
|
canvas.drawCircle(_centerOffset, radius, paint);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
canvas.drawCircle(_centerOffset, radius, paint);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void renderDebugMode(Canvas canvas) {
|
void renderDebugMode(Canvas canvas) {
|
||||||
super.renderDebugMode(canvas);
|
super.renderDebugMode(canvas);
|
||||||
canvas.drawCircle((size / 2).toOffset(), radius, debugPaint);
|
canvas.drawCircle(_centerOffset, radius, debugPaint);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks whether the represented circle contains the [point].
|
/// Checks whether the represented circle contains the [point].
|
||||||
|
|||||||
@ -38,6 +38,7 @@ class PolygonComponent extends ShapeComponent {
|
|||||||
super.children,
|
super.children,
|
||||||
super.priority,
|
super.priority,
|
||||||
super.paint,
|
super.paint,
|
||||||
|
super.paintLayers,
|
||||||
bool? shrinkToBounds,
|
bool? shrinkToBounds,
|
||||||
}) : assert(
|
}) : assert(
|
||||||
_vertices.length > 2,
|
_vertices.length > 2,
|
||||||
@ -76,6 +77,7 @@ class PolygonComponent extends ShapeComponent {
|
|||||||
Anchor? anchor,
|
Anchor? anchor,
|
||||||
int? priority,
|
int? priority,
|
||||||
Paint? paint,
|
Paint? paint,
|
||||||
|
List<Paint>? paintLayers,
|
||||||
bool? shrinkToBounds,
|
bool? shrinkToBounds,
|
||||||
}) : this(
|
}) : this(
|
||||||
normalsToVertices(relation, parentSize),
|
normalsToVertices(relation, parentSize),
|
||||||
@ -86,6 +88,7 @@ class PolygonComponent extends ShapeComponent {
|
|||||||
scale: scale,
|
scale: scale,
|
||||||
priority: priority,
|
priority: priority,
|
||||||
paint: paint,
|
paint: paint,
|
||||||
|
paintLayers: paintLayers,
|
||||||
shrinkToBounds: shrinkToBounds,
|
shrinkToBounds: shrinkToBounds,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -171,8 +174,14 @@ class PolygonComponent extends ShapeComponent {
|
|||||||
@override
|
@override
|
||||||
void render(Canvas canvas) {
|
void render(Canvas canvas) {
|
||||||
if (renderShape) {
|
if (renderShape) {
|
||||||
|
if (hasPaintLayers) {
|
||||||
|
for (final paint in paintLayers) {
|
||||||
canvas.drawPath(_path, paint);
|
canvas.drawPath(_path, paint);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
canvas.drawPath(_path, paint);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@ -13,6 +13,7 @@ class RectangleComponent extends PolygonComponent {
|
|||||||
super.children,
|
super.children,
|
||||||
super.priority,
|
super.priority,
|
||||||
super.paint,
|
super.paint,
|
||||||
|
super.paintLayers,
|
||||||
}) : super(sizeToVertices(size ?? Vector2.zero(), anchor));
|
}) : super(sizeToVertices(size ?? Vector2.zero(), anchor));
|
||||||
|
|
||||||
RectangleComponent.square({
|
RectangleComponent.square({
|
||||||
@ -22,6 +23,7 @@ class RectangleComponent extends PolygonComponent {
|
|||||||
super.anchor,
|
super.anchor,
|
||||||
super.priority,
|
super.priority,
|
||||||
super.paint,
|
super.paint,
|
||||||
|
super.paintLayers,
|
||||||
super.children,
|
super.children,
|
||||||
}) : super(sizeToVertices(Vector2.all(size), anchor));
|
}) : super(sizeToVertices(Vector2.all(size), anchor));
|
||||||
|
|
||||||
@ -38,6 +40,7 @@ class RectangleComponent extends PolygonComponent {
|
|||||||
super.anchor,
|
super.anchor,
|
||||||
super.priority,
|
super.priority,
|
||||||
super.paint,
|
super.paint,
|
||||||
|
super.paintLayers,
|
||||||
super.shrinkToBounds,
|
super.shrinkToBounds,
|
||||||
}) : super.relative([
|
}) : super.relative([
|
||||||
relation.clone(),
|
relation.clone(),
|
||||||
@ -53,6 +56,7 @@ class RectangleComponent extends PolygonComponent {
|
|||||||
Anchor anchor = Anchor.topLeft,
|
Anchor anchor = Anchor.topLeft,
|
||||||
int? priority,
|
int? priority,
|
||||||
Paint? paint,
|
Paint? paint,
|
||||||
|
List<Paint>? paintLayers,
|
||||||
}) {
|
}) {
|
||||||
return RectangleComponent(
|
return RectangleComponent(
|
||||||
position: anchor == Anchor.topLeft
|
position: anchor == Anchor.topLeft
|
||||||
@ -67,6 +71,7 @@ class RectangleComponent extends PolygonComponent {
|
|||||||
anchor: anchor,
|
anchor: anchor,
|
||||||
priority: priority,
|
priority: priority,
|
||||||
paint: paint,
|
paint: paint,
|
||||||
|
paintLayers: paintLayers,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -16,8 +16,14 @@ abstract class ShapeComponent extends PositionComponent with HasPaint {
|
|||||||
super.children,
|
super.children,
|
||||||
super.priority,
|
super.priority,
|
||||||
Paint? paint,
|
Paint? paint,
|
||||||
|
List<Paint>? paintLayers,
|
||||||
}) {
|
}) {
|
||||||
this.paint = paint ?? this.paint;
|
this.paint = paint ?? this.paint;
|
||||||
|
// Only read from this.paintLayers if paintLayers not null to prevent
|
||||||
|
// unnecessary creation of the paintLayers list.
|
||||||
|
if (paintLayers != null) {
|
||||||
|
this.paintLayers = paintLayers;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool renderShape = true;
|
bool renderShape = true;
|
||||||
|
|||||||
@ -1,77 +1,113 @@
|
|||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
|
|
||||||
import 'package:flame/components.dart';
|
import 'package:flame/components.dart';
|
||||||
import 'package:flame_test/flame_test.dart';
|
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
group('HasPaint', () {
|
group('HasPaint', () {
|
||||||
test('paint returns the default paint', () {
|
test('paint returns the default paint', () {
|
||||||
final comp = _MyComponent();
|
final component = _MyComponent();
|
||||||
|
|
||||||
expect(comp.paint, comp.getPaint());
|
expect(component.paint, component.getPaint());
|
||||||
});
|
});
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'paint setter sets the main paint',
|
'paint setter sets the main paint',
|
||||||
() {
|
() {
|
||||||
final comp = _MyComponent();
|
final component = _MyComponent();
|
||||||
|
|
||||||
const color = Color(0xFFE5E5E5);
|
const color = Color(0xFFE5E5E5);
|
||||||
comp.paint = Paint()..color = color;
|
component.paint = Paint()..color = color;
|
||||||
|
|
||||||
expect(comp.getPaint().color, color);
|
expect(component.getPaint().color, color);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
test(
|
test('paintLayers defaults to empty list', () {
|
||||||
'getPaint throws exception when retrieving a paint that does not exists',
|
final component = _MyComponent();
|
||||||
() {
|
|
||||||
final comp = _MyComponentWithType();
|
const color = Color(0xFFE5E5E5);
|
||||||
|
component.paint = Paint()..color = color;
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
() => comp.getPaint(_MyComponentKeys.background),
|
component.paintLayers,
|
||||||
|
equals(<Paint>[]),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('paintLayers returns correct colors', () {
|
||||||
|
const firstColor = Color(0xFFE5E5E5);
|
||||||
|
const secondColor = Color(0xFF123456);
|
||||||
|
const thirdColor = Color(0xFFABABAB);
|
||||||
|
final firstPaint = Paint()..color = firstColor;
|
||||||
|
final secondPaint = Paint()..color = secondColor;
|
||||||
|
final thirdPaint = Paint()..color = thirdColor;
|
||||||
|
|
||||||
|
final circle = CircleComponent(
|
||||||
|
radius: 10,
|
||||||
|
paint: firstPaint,
|
||||||
|
paintLayers: [secondPaint, thirdPaint],
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
circle.paintLayers,
|
||||||
|
equals([secondPaint, thirdPaint]),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
circle.paint,
|
||||||
|
equals(firstPaint),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('can clear paintLayers', () {
|
||||||
|
const firstColor = Color(0xFFE5E5E5);
|
||||||
|
const secondColor = Color(0xFF123456);
|
||||||
|
const thirdColor = Color(0xFFABABAB);
|
||||||
|
final firstPaint = Paint()..color = firstColor;
|
||||||
|
final secondPaint = Paint()..color = secondColor;
|
||||||
|
final thirdPaint = Paint()..color = thirdColor;
|
||||||
|
|
||||||
|
final circle = CircleComponent(
|
||||||
|
radius: 10,
|
||||||
|
paint: firstPaint,
|
||||||
|
paintLayers: [secondPaint, thirdPaint],
|
||||||
|
);
|
||||||
|
|
||||||
|
circle.paintLayers.clear();
|
||||||
|
|
||||||
|
expect(
|
||||||
|
circle.paintLayers,
|
||||||
|
equals(<Paint>[]),
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
circle.paint,
|
||||||
|
equals(firstPaint),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test(
|
||||||
|
'getPaint throws exception when retrieving a paint that does not exist',
|
||||||
|
() {
|
||||||
|
final component = _MyComponentWithType();
|
||||||
|
|
||||||
|
expect(
|
||||||
|
() => component.getPaint(_MyComponentKeys.background),
|
||||||
throwsArgumentError,
|
throwsArgumentError,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
test(
|
|
||||||
'getPaint throws exception when used on genericless component',
|
|
||||||
() {
|
|
||||||
final comp = _MyComponent();
|
|
||||||
|
|
||||||
expect(
|
|
||||||
() => comp.getPaint(_MyComponentKeys.background),
|
|
||||||
failsAssert('A generics type is missing on the HasPaint mixin'),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'setPaint sets a paint',
|
'setPaint sets a paint',
|
||||||
() {
|
() {
|
||||||
final comp = _MyComponentWithType();
|
final component = _MyComponentWithType();
|
||||||
|
|
||||||
const color = Color(0xFFA9A9A9);
|
const color = Color(0xFFA9A9A9);
|
||||||
comp.setPaint(_MyComponentKeys.background, Paint()..color = color);
|
component.setPaint(_MyComponentKeys.background, Paint()..color = color);
|
||||||
|
|
||||||
expect(comp.getPaint(_MyComponentKeys.background).color, color);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
test(
|
|
||||||
'setPaint throws exception when used on genericless component',
|
|
||||||
() {
|
|
||||||
final comp = _MyComponent();
|
|
||||||
|
|
||||||
const color = Color(0xFFA9A9A9);
|
|
||||||
expect(
|
expect(
|
||||||
() => comp.setPaint(
|
component.getPaint(_MyComponentKeys.background).color,
|
||||||
_MyComponentKeys.background,
|
equals(color),
|
||||||
Paint()..color = color,
|
|
||||||
),
|
|
||||||
failsAssert('A generics type is missing on the HasPaint mixin'),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -79,26 +115,51 @@ void main() {
|
|||||||
test(
|
test(
|
||||||
'deletePaint removes a paint from the map',
|
'deletePaint removes a paint from the map',
|
||||||
() {
|
() {
|
||||||
final comp = _MyComponentWithType();
|
final component = _MyComponentWithType();
|
||||||
|
|
||||||
comp.setPaint(_MyComponentKeys.foreground, Paint());
|
component.setPaint(_MyComponentKeys.foreground, Paint());
|
||||||
comp.deletePaint(_MyComponentKeys.foreground);
|
component.deletePaint(_MyComponentKeys.foreground);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
() => comp.getPaint(_MyComponentKeys.foreground),
|
() => component.getPaint(_MyComponentKeys.foreground),
|
||||||
throwsArgumentError,
|
throwsArgumentError,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'deletePaint throws exception when used on genericless component',
|
'append paint to paintLayers',
|
||||||
() {
|
() {
|
||||||
final comp = _MyComponent();
|
final component = _MyComponent();
|
||||||
|
|
||||||
|
const color = Color(0xFFE5E5E5);
|
||||||
|
component.paintLayers.add(Paint()..color = color);
|
||||||
|
|
||||||
|
expect(component.paintLayers[0].color, equals(color));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
test(
|
||||||
|
'use setPaintLayers to set multiple paintIds in paintLayers',
|
||||||
|
() {
|
||||||
|
final component = _MyComponent();
|
||||||
|
|
||||||
|
const color = Color(0xFFE5E5E5);
|
||||||
|
const anotherColor = Color(0xFFABABAB);
|
||||||
|
const thirdColor = Color(0xFF123456);
|
||||||
|
component.setPaint('test', Paint()..color = color);
|
||||||
|
component.setPaint('anotherTest', Paint()..color = anotherColor);
|
||||||
|
component.setPaint('thirdTest', Paint()..color = thirdColor);
|
||||||
|
|
||||||
|
component.paintLayers = [
|
||||||
|
component.getPaint('thirdTest'),
|
||||||
|
component.getPaint('test'),
|
||||||
|
];
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
() => comp.deletePaint(_MyComponentKeys.background),
|
(component.paintLayers[0].color == thirdColor) &&
|
||||||
failsAssert('A generics type is missing on the HasPaint mixin'),
|
(component.paintLayers[1].color == color),
|
||||||
|
isTrue,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -106,77 +167,86 @@ void main() {
|
|||||||
test(
|
test(
|
||||||
'makeTransparent sets opacity to 0 on the main when paintId is omitted',
|
'makeTransparent sets opacity to 0 on the main when paintId is omitted',
|
||||||
() {
|
() {
|
||||||
final comp = _MyComponent();
|
final component = _MyComponent();
|
||||||
comp.makeTransparent();
|
component.makeTransparent();
|
||||||
|
|
||||||
expect(comp.paint.color.opacity, 0);
|
expect(component.paint.color.opacity, 0);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'makeTransparent sets opacity to 0 on informed paintId',
|
'makeTransparent sets opacity to 0 on informed paintId',
|
||||||
() {
|
() {
|
||||||
final comp = _MyComponentWithType();
|
final component = _MyComponentWithType();
|
||||||
comp.setPaint(_MyComponentKeys.background, Paint());
|
component.setPaint(_MyComponentKeys.background, Paint());
|
||||||
comp.makeTransparent(paintId: _MyComponentKeys.background);
|
component.makeTransparent(paintId: _MyComponentKeys.background);
|
||||||
|
|
||||||
expect(comp.getPaint(_MyComponentKeys.background).color.opacity, 0);
|
expect(
|
||||||
|
component.getPaint(_MyComponentKeys.background).color.opacity,
|
||||||
|
0,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'makeOpaque sets opacity to 1 on the main when paintId is omitted',
|
'makeOpaque sets opacity to 1 on the main when paintId is omitted',
|
||||||
() {
|
() {
|
||||||
final comp = _MyComponent();
|
final component = _MyComponent();
|
||||||
comp.makeTransparent();
|
component.makeTransparent();
|
||||||
comp.makeOpaque();
|
component.makeOpaque();
|
||||||
|
|
||||||
expect(comp.paint.color.opacity, 1);
|
expect(component.paint.color.opacity, 1);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'makeOpaque sets opacity to 1 on informed paintId',
|
'makeOpaque sets opacity to 1 on informed paintId',
|
||||||
() {
|
() {
|
||||||
final comp = _MyComponentWithType();
|
final component = _MyComponentWithType();
|
||||||
comp.setPaint(
|
component.setPaint(
|
||||||
_MyComponentKeys.background,
|
_MyComponentKeys.background,
|
||||||
Paint()..color = const Color(0x00E5E5E5),
|
Paint()..color = const Color(0x00E5E5E5),
|
||||||
);
|
);
|
||||||
comp.makeOpaque(paintId: _MyComponentKeys.background);
|
component.makeOpaque(paintId: _MyComponentKeys.background);
|
||||||
|
|
||||||
expect(comp.getPaint(_MyComponentKeys.background).color.opacity, 1);
|
expect(
|
||||||
|
component.getPaint(_MyComponentKeys.background).color.opacity,
|
||||||
|
1,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'setOpacity sets opacity of the main when paintId is omitted',
|
'setOpacity sets opacity of the main when paintId is omitted',
|
||||||
() {
|
() {
|
||||||
final comp = _MyComponent();
|
final component = _MyComponent();
|
||||||
comp.setOpacity(0.2);
|
component.setOpacity(0.2);
|
||||||
|
|
||||||
expect(comp.paint.color.opacity, 0.2);
|
expect(component.paint.color.opacity, 0.2);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'setOpacity sets opacity of the informed paintId',
|
'setOpacity sets opacity of the informed paintId',
|
||||||
() {
|
() {
|
||||||
final comp = _MyComponentWithType();
|
final component = _MyComponentWithType();
|
||||||
comp.setPaint(_MyComponentKeys.background, Paint());
|
component.setPaint(_MyComponentKeys.background, Paint());
|
||||||
comp.setOpacity(0.2, paintId: _MyComponentKeys.background);
|
component.setOpacity(0.2, paintId: _MyComponentKeys.background);
|
||||||
|
|
||||||
expect(comp.getPaint(_MyComponentKeys.background).color.opacity, 0.2);
|
expect(
|
||||||
|
component.getPaint(_MyComponentKeys.background).color.opacity,
|
||||||
|
0.2,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'throws error if opacity is less than 0',
|
'throws error if opacity is less than 0',
|
||||||
() {
|
() {
|
||||||
final comp = _MyComponent();
|
final component = _MyComponent();
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
() => comp.setOpacity(-0.5),
|
() => component.setOpacity(-0.5),
|
||||||
throwsArgumentError,
|
throwsArgumentError,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -185,10 +255,10 @@ void main() {
|
|||||||
test(
|
test(
|
||||||
'throws error if opacity is greater than 1',
|
'throws error if opacity is greater than 1',
|
||||||
() {
|
() {
|
||||||
final comp = _MyComponent();
|
final component = _MyComponent();
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
() => comp.setOpacity(1.1),
|
() => component.setOpacity(1.1),
|
||||||
throwsArgumentError,
|
throwsArgumentError,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -197,35 +267,35 @@ void main() {
|
|||||||
test(
|
test(
|
||||||
'setColor sets color of the main when paintId is omitted',
|
'setColor sets color of the main when paintId is omitted',
|
||||||
() {
|
() {
|
||||||
final comp = _MyComponent();
|
final component = _MyComponent();
|
||||||
const color = Color(0xFFE5E5E5);
|
const color = Color(0xFFE5E5E5);
|
||||||
comp.setColor(color);
|
component.setColor(color);
|
||||||
|
|
||||||
expect(comp.paint.color, color);
|
expect(component.paint.color, color);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'setOpacity sets opacity of the informed paintId',
|
'setOpacity sets opacity of the informed paintId',
|
||||||
() {
|
() {
|
||||||
final comp = _MyComponentWithType();
|
final component = _MyComponentWithType();
|
||||||
const color = Color(0xFFE5E5E5);
|
const color = Color(0xFFE5E5E5);
|
||||||
comp.setPaint(_MyComponentKeys.background, Paint());
|
component.setPaint(_MyComponentKeys.background, Paint());
|
||||||
comp.setColor(color, paintId: _MyComponentKeys.background);
|
component.setColor(color, paintId: _MyComponentKeys.background);
|
||||||
|
|
||||||
expect(comp.getPaint(_MyComponentKeys.background).color, color);
|
expect(component.getPaint(_MyComponentKeys.background).color, color);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'tint sets the correct color filter of the main when paintId is omitted',
|
'tint sets the correct color filter of the main when paintId is omitted',
|
||||||
() {
|
() {
|
||||||
final comp = _MyComponent();
|
final component = _MyComponent();
|
||||||
const color = Color(0xFFE5E5E5);
|
const color = Color(0xFFE5E5E5);
|
||||||
comp.tint(color);
|
component.tint(color);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
comp.paint.colorFilter,
|
component.paint.colorFilter,
|
||||||
const ColorFilter.mode(color, BlendMode.srcATop),
|
const ColorFilter.mode(color, BlendMode.srcATop),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -234,13 +304,13 @@ void main() {
|
|||||||
test(
|
test(
|
||||||
'setOpacity sets opacity of the informed paintId',
|
'setOpacity sets opacity of the informed paintId',
|
||||||
() {
|
() {
|
||||||
final comp = _MyComponentWithType();
|
final component = _MyComponentWithType();
|
||||||
const color = Color(0xFFE5E5E5);
|
const color = Color(0xFFE5E5E5);
|
||||||
comp.setPaint(_MyComponentKeys.background, Paint());
|
component.setPaint(_MyComponentKeys.background, Paint());
|
||||||
comp.tint(color, paintId: _MyComponentKeys.background);
|
component.tint(color, paintId: _MyComponentKeys.background);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
comp.getPaint(_MyComponentKeys.background).colorFilter,
|
component.getPaint(_MyComponentKeys.background).colorFilter,
|
||||||
const ColorFilter.mode(color, BlendMode.srcATop),
|
const ColorFilter.mode(color, BlendMode.srcATop),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user