mirror of
				https://github.com/flame-engine/flame.git
				synced 2025-10-31 08:56:01 +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; | ||||
|  | ||||
|   @override | ||||
|   Future<void>? onLoad() { | ||||
|   Future<void> onLoad() async { | ||||
|     super.onLoad(); | ||||
|     _resetBall; | ||||
|     final hitBox = CircleHitbox( | ||||
|       radius: radius, | ||||
| @ -43,8 +44,6 @@ class Ball extends CircleComponent | ||||
|     addAll([ | ||||
|       hitBox, | ||||
|     ]); | ||||
|  | ||||
|     return super.onLoad(); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|  | ||||
| @ -4,21 +4,22 @@ import 'dart:ui'; | ||||
| import 'package:flame/components.dart'; | ||||
| import 'package:flame/effects.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 | ||||
| /// by the [paint] attribute and other paints can be manipulated/accessed | ||||
| /// 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 { | ||||
|   final Map<T, Paint> _paints = {}; | ||||
|  | ||||
|   late final Map<T, Paint> _paints = {}; | ||||
|   Paint paint = BasicPalette.white.paint(); | ||||
|  | ||||
|   void _assertGenerics() { | ||||
|     assert(T != Object, 'A generics type is missing on the HasPaint mixin'); | ||||
|   } | ||||
|   @internal | ||||
|   List<Paint>? paintLayersInternal; | ||||
|  | ||||
|   /// Gets a paint from the collection. | ||||
|   /// | ||||
| @ -28,7 +29,6 @@ mixin HasPaint<T extends Object> on Component implements OpacityProvider { | ||||
|       return paint; | ||||
|     } | ||||
|  | ||||
|     _assertGenerics(); | ||||
|     final _paint = _paints[paintId]; | ||||
|  | ||||
|     if (_paint == null) { | ||||
| @ -40,16 +40,29 @@ mixin HasPaint<T extends Object> on Component implements OpacityProvider { | ||||
|  | ||||
|   /// Sets a paint on the collection. | ||||
|   void setPaint(T paintId, Paint paint) { | ||||
|     _assertGenerics(); | ||||
|     _paints[paintId] = paint; | ||||
|   } | ||||
|  | ||||
|   /// Removes a paint from the collection. | ||||
|   void deletePaint(T paintId) { | ||||
|     _assertGenerics(); | ||||
|     _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. | ||||
|   void makeTransparent({T? 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 | ||||
|   /// 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( | ||||
|       paintIds ?? (List<T?>.from(_paints.keys)..add(null)), | ||||
|       includeLayers, | ||||
|       this, | ||||
|     ); | ||||
|   } | ||||
| @ -152,19 +169,25 @@ class _ProxyOpacityProvider<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; | ||||
|  | ||||
|     _opacityRatios = List<double>.generate( | ||||
|       paintIds.length, | ||||
|       (index) => | ||||
|           target.getOpacity(paintId: paintIds.elementAt(index)) / maxOpacity, | ||||
|     ); | ||||
|     _opacityRatios = [ | ||||
|       for (final paintId in paintIds) | ||||
|         target.getOpacity(paintId: paintId) / maxOpacity, | ||||
|     ]; | ||||
|     _layerOpacityRatios = target.paintLayersInternal | ||||
|         ?.map( | ||||
|           (paint) => paint.color.opacity / maxOpacity, | ||||
|         ) | ||||
|         .toList(growable: false); | ||||
|   } | ||||
|  | ||||
|   final List<T?> paintIds; | ||||
|   final HasPaint<T> target; | ||||
|   final bool includeLayers; | ||||
|   late final List<double> _opacityRatios; | ||||
|   late final List<double>? _layerOpacityRatios; | ||||
|  | ||||
|   @override | ||||
|   double get opacity { | ||||
| @ -173,6 +196,11 @@ class _MultiPaintOpacityProvider<T extends Object> implements OpacityProvider { | ||||
|     for (final paintId in paintIds) { | ||||
|       maxOpacity = max(target.getOpacity(paintId: paintId), maxOpacity); | ||||
|     } | ||||
|     if (includeLayers) { | ||||
|       target.paintLayersInternal?.forEach( | ||||
|         (paint) => maxOpacity = max(paint.color.opacity, maxOpacity), | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     return maxOpacity; | ||||
|   } | ||||
| @ -185,5 +213,13 @@ class _MultiPaintOpacityProvider<T extends Object> implements OpacityProvider { | ||||
|         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/src/effects/provider_interfaces.dart'; | ||||
| import 'package:flame/src/utils/solve_quadratic.dart'; | ||||
| import 'package:meta/meta.dart'; | ||||
|  | ||||
| class CircleComponent extends ShapeComponent implements SizeProvider { | ||||
|   /// With this constructor you can create your [CircleComponent] from a radius | ||||
| @ -18,6 +19,7 @@ class CircleComponent extends ShapeComponent implements SizeProvider { | ||||
|     super.children, | ||||
|     super.priority, | ||||
|     super.paint, | ||||
|     super.paintLayers, | ||||
|   }) : super(size: Vector2.all((radius ?? 0) * 2)); | ||||
|  | ||||
|   /// With this constructor you define the [CircleComponent] in relation to the | ||||
| @ -30,8 +32,19 @@ class CircleComponent extends ShapeComponent implements SizeProvider { | ||||
|     super.angle, | ||||
|     super.anchor, | ||||
|     super.paint, | ||||
|     super.paintLayers, | ||||
|   }) : 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. | ||||
|   double get radius { | ||||
|     return min(size.x, size.y) / 2; | ||||
| @ -56,14 +69,20 @@ class CircleComponent extends ShapeComponent implements SizeProvider { | ||||
|   @override | ||||
|   void render(Canvas canvas) { | ||||
|     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 | ||||
|   void renderDebugMode(Canvas canvas) { | ||||
|     super.renderDebugMode(canvas); | ||||
|     canvas.drawCircle((size / 2).toOffset(), radius, debugPaint); | ||||
|     canvas.drawCircle(_centerOffset, radius, debugPaint); | ||||
|   } | ||||
|  | ||||
|   /// Checks whether the represented circle contains the [point]. | ||||
|  | ||||
| @ -38,6 +38,7 @@ class PolygonComponent extends ShapeComponent { | ||||
|     super.children, | ||||
|     super.priority, | ||||
|     super.paint, | ||||
|     super.paintLayers, | ||||
|     bool? shrinkToBounds, | ||||
|   })  : assert( | ||||
|           _vertices.length > 2, | ||||
| @ -76,6 +77,7 @@ class PolygonComponent extends ShapeComponent { | ||||
|     Anchor? anchor, | ||||
|     int? priority, | ||||
|     Paint? paint, | ||||
|     List<Paint>? paintLayers, | ||||
|     bool? shrinkToBounds, | ||||
|   }) : this( | ||||
|           normalsToVertices(relation, parentSize), | ||||
| @ -86,6 +88,7 @@ class PolygonComponent extends ShapeComponent { | ||||
|           scale: scale, | ||||
|           priority: priority, | ||||
|           paint: paint, | ||||
|           paintLayers: paintLayers, | ||||
|           shrinkToBounds: shrinkToBounds, | ||||
|         ); | ||||
|  | ||||
| @ -171,8 +174,14 @@ class PolygonComponent extends ShapeComponent { | ||||
|   @override | ||||
|   void render(Canvas canvas) { | ||||
|     if (renderShape) { | ||||
|       if (hasPaintLayers) { | ||||
|         for (final paint in paintLayers) { | ||||
|           canvas.drawPath(_path, paint); | ||||
|         } | ||||
|       } else { | ||||
|         canvas.drawPath(_path, paint); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|  | ||||
| @ -13,6 +13,7 @@ class RectangleComponent extends PolygonComponent { | ||||
|     super.children, | ||||
|     super.priority, | ||||
|     super.paint, | ||||
|     super.paintLayers, | ||||
|   }) : super(sizeToVertices(size ?? Vector2.zero(), anchor)); | ||||
|  | ||||
|   RectangleComponent.square({ | ||||
| @ -22,6 +23,7 @@ class RectangleComponent extends PolygonComponent { | ||||
|     super.anchor, | ||||
|     super.priority, | ||||
|     super.paint, | ||||
|     super.paintLayers, | ||||
|     super.children, | ||||
|   }) : super(sizeToVertices(Vector2.all(size), anchor)); | ||||
|  | ||||
| @ -38,6 +40,7 @@ class RectangleComponent extends PolygonComponent { | ||||
|     super.anchor, | ||||
|     super.priority, | ||||
|     super.paint, | ||||
|     super.paintLayers, | ||||
|     super.shrinkToBounds, | ||||
|   }) : super.relative([ | ||||
|           relation.clone(), | ||||
| @ -53,6 +56,7 @@ class RectangleComponent extends PolygonComponent { | ||||
|     Anchor anchor = Anchor.topLeft, | ||||
|     int? priority, | ||||
|     Paint? paint, | ||||
|     List<Paint>? paintLayers, | ||||
|   }) { | ||||
|     return RectangleComponent( | ||||
|       position: anchor == Anchor.topLeft | ||||
| @ -67,6 +71,7 @@ class RectangleComponent extends PolygonComponent { | ||||
|       anchor: anchor, | ||||
|       priority: priority, | ||||
|       paint: paint, | ||||
|       paintLayers: paintLayers, | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|  | ||||
| @ -16,8 +16,14 @@ abstract class ShapeComponent extends PositionComponent with HasPaint { | ||||
|     super.children, | ||||
|     super.priority, | ||||
|     Paint? paint, | ||||
|     List<Paint>? paintLayers, | ||||
|   }) { | ||||
|     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; | ||||
|  | ||||
| @ -1,77 +1,113 @@ | ||||
| import 'dart:ui'; | ||||
|  | ||||
| import 'package:flame/components.dart'; | ||||
| import 'package:flame_test/flame_test.dart'; | ||||
| import 'package:flutter_test/flutter_test.dart'; | ||||
|  | ||||
| void main() { | ||||
|   group('HasPaint', () { | ||||
|     test('paint returns the default paint', () { | ||||
|       final comp = _MyComponent(); | ||||
|       final component = _MyComponent(); | ||||
|  | ||||
|       expect(comp.paint, comp.getPaint()); | ||||
|       expect(component.paint, component.getPaint()); | ||||
|     }); | ||||
|  | ||||
|     test( | ||||
|       'paint setter sets the main paint', | ||||
|       () { | ||||
|         final comp = _MyComponent(); | ||||
|         final component = _MyComponent(); | ||||
|  | ||||
|         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( | ||||
|       'getPaint throws exception when retrieving a paint that does not exists', | ||||
|       () { | ||||
|         final comp = _MyComponentWithType(); | ||||
|     test('paintLayers defaults to empty list', () { | ||||
|       final component = _MyComponent(); | ||||
|  | ||||
|       const color = Color(0xFFE5E5E5); | ||||
|       component.paint = Paint()..color = color; | ||||
|  | ||||
|       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, | ||||
|         ); | ||||
|       }, | ||||
|     ); | ||||
|  | ||||
|     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( | ||||
|       'setPaint sets a paint', | ||||
|       () { | ||||
|         final comp = _MyComponentWithType(); | ||||
|         final component = _MyComponentWithType(); | ||||
|  | ||||
|         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( | ||||
|           () => comp.setPaint( | ||||
|             _MyComponentKeys.background, | ||||
|             Paint()..color = color, | ||||
|           ), | ||||
|           failsAssert('A generics type is missing on the HasPaint mixin'), | ||||
|           component.getPaint(_MyComponentKeys.background).color, | ||||
|           equals(color), | ||||
|         ); | ||||
|       }, | ||||
|     ); | ||||
| @ -79,26 +115,51 @@ void main() { | ||||
|     test( | ||||
|       'deletePaint removes a paint from the map', | ||||
|       () { | ||||
|         final comp = _MyComponentWithType(); | ||||
|         final component = _MyComponentWithType(); | ||||
|  | ||||
|         comp.setPaint(_MyComponentKeys.foreground, Paint()); | ||||
|         comp.deletePaint(_MyComponentKeys.foreground); | ||||
|         component.setPaint(_MyComponentKeys.foreground, Paint()); | ||||
|         component.deletePaint(_MyComponentKeys.foreground); | ||||
|  | ||||
|         expect( | ||||
|           () => comp.getPaint(_MyComponentKeys.foreground), | ||||
|           () => component.getPaint(_MyComponentKeys.foreground), | ||||
|           throwsArgumentError, | ||||
|         ); | ||||
|       }, | ||||
|     ); | ||||
|  | ||||
|     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( | ||||
|           () => comp.deletePaint(_MyComponentKeys.background), | ||||
|           failsAssert('A generics type is missing on the HasPaint mixin'), | ||||
|           (component.paintLayers[0].color == thirdColor) && | ||||
|               (component.paintLayers[1].color == color), | ||||
|           isTrue, | ||||
|         ); | ||||
|       }, | ||||
|     ); | ||||
| @ -106,77 +167,86 @@ void main() { | ||||
|     test( | ||||
|       'makeTransparent sets opacity to 0 on the main when paintId is omitted', | ||||
|       () { | ||||
|         final comp = _MyComponent(); | ||||
|         comp.makeTransparent(); | ||||
|         final component = _MyComponent(); | ||||
|         component.makeTransparent(); | ||||
|  | ||||
|         expect(comp.paint.color.opacity, 0); | ||||
|         expect(component.paint.color.opacity, 0); | ||||
|       }, | ||||
|     ); | ||||
|  | ||||
|     test( | ||||
|       'makeTransparent sets opacity to 0 on informed paintId', | ||||
|       () { | ||||
|         final comp = _MyComponentWithType(); | ||||
|         comp.setPaint(_MyComponentKeys.background, Paint()); | ||||
|         comp.makeTransparent(paintId: _MyComponentKeys.background); | ||||
|         final component = _MyComponentWithType(); | ||||
|         component.setPaint(_MyComponentKeys.background, Paint()); | ||||
|         component.makeTransparent(paintId: _MyComponentKeys.background); | ||||
|  | ||||
|         expect(comp.getPaint(_MyComponentKeys.background).color.opacity, 0); | ||||
|         expect( | ||||
|           component.getPaint(_MyComponentKeys.background).color.opacity, | ||||
|           0, | ||||
|         ); | ||||
|       }, | ||||
|     ); | ||||
|  | ||||
|     test( | ||||
|       'makeOpaque sets opacity to 1 on the main when paintId is omitted', | ||||
|       () { | ||||
|         final comp = _MyComponent(); | ||||
|         comp.makeTransparent(); | ||||
|         comp.makeOpaque(); | ||||
|         final component = _MyComponent(); | ||||
|         component.makeTransparent(); | ||||
|         component.makeOpaque(); | ||||
|  | ||||
|         expect(comp.paint.color.opacity, 1); | ||||
|         expect(component.paint.color.opacity, 1); | ||||
|       }, | ||||
|     ); | ||||
|  | ||||
|     test( | ||||
|       'makeOpaque sets opacity to 1 on informed paintId', | ||||
|       () { | ||||
|         final comp = _MyComponentWithType(); | ||||
|         comp.setPaint( | ||||
|         final component = _MyComponentWithType(); | ||||
|         component.setPaint( | ||||
|           _MyComponentKeys.background, | ||||
|           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( | ||||
|       'setOpacity sets opacity of the main when paintId is omitted', | ||||
|       () { | ||||
|         final comp = _MyComponent(); | ||||
|         comp.setOpacity(0.2); | ||||
|         final component = _MyComponent(); | ||||
|         component.setOpacity(0.2); | ||||
|  | ||||
|         expect(comp.paint.color.opacity, 0.2); | ||||
|         expect(component.paint.color.opacity, 0.2); | ||||
|       }, | ||||
|     ); | ||||
|  | ||||
|     test( | ||||
|       'setOpacity sets opacity of the informed paintId', | ||||
|       () { | ||||
|         final comp = _MyComponentWithType(); | ||||
|         comp.setPaint(_MyComponentKeys.background, Paint()); | ||||
|         comp.setOpacity(0.2, paintId: _MyComponentKeys.background); | ||||
|         final component = _MyComponentWithType(); | ||||
|         component.setPaint(_MyComponentKeys.background, Paint()); | ||||
|         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( | ||||
|       'throws error if opacity is less than 0', | ||||
|       () { | ||||
|         final comp = _MyComponent(); | ||||
|         final component = _MyComponent(); | ||||
|  | ||||
|         expect( | ||||
|           () => comp.setOpacity(-0.5), | ||||
|           () => component.setOpacity(-0.5), | ||||
|           throwsArgumentError, | ||||
|         ); | ||||
|       }, | ||||
| @ -185,10 +255,10 @@ void main() { | ||||
|     test( | ||||
|       'throws error if opacity is greater than 1', | ||||
|       () { | ||||
|         final comp = _MyComponent(); | ||||
|         final component = _MyComponent(); | ||||
|  | ||||
|         expect( | ||||
|           () => comp.setOpacity(1.1), | ||||
|           () => component.setOpacity(1.1), | ||||
|           throwsArgumentError, | ||||
|         ); | ||||
|       }, | ||||
| @ -197,35 +267,35 @@ void main() { | ||||
|     test( | ||||
|       'setColor sets color of the main when paintId is omitted', | ||||
|       () { | ||||
|         final comp = _MyComponent(); | ||||
|         final component = _MyComponent(); | ||||
|         const color = Color(0xFFE5E5E5); | ||||
|         comp.setColor(color); | ||||
|         component.setColor(color); | ||||
|  | ||||
|         expect(comp.paint.color, color); | ||||
|         expect(component.paint.color, color); | ||||
|       }, | ||||
|     ); | ||||
|  | ||||
|     test( | ||||
|       'setOpacity sets opacity of the informed paintId', | ||||
|       () { | ||||
|         final comp = _MyComponentWithType(); | ||||
|         final component = _MyComponentWithType(); | ||||
|         const color = Color(0xFFE5E5E5); | ||||
|         comp.setPaint(_MyComponentKeys.background, Paint()); | ||||
|         comp.setColor(color, paintId: _MyComponentKeys.background); | ||||
|         component.setPaint(_MyComponentKeys.background, Paint()); | ||||
|         component.setColor(color, paintId: _MyComponentKeys.background); | ||||
|  | ||||
|         expect(comp.getPaint(_MyComponentKeys.background).color, color); | ||||
|         expect(component.getPaint(_MyComponentKeys.background).color, color); | ||||
|       }, | ||||
|     ); | ||||
|  | ||||
|     test( | ||||
|       'tint sets the correct color filter of the main when paintId is omitted', | ||||
|       () { | ||||
|         final comp = _MyComponent(); | ||||
|         final component = _MyComponent(); | ||||
|         const color = Color(0xFFE5E5E5); | ||||
|         comp.tint(color); | ||||
|         component.tint(color); | ||||
|  | ||||
|         expect( | ||||
|           comp.paint.colorFilter, | ||||
|           component.paint.colorFilter, | ||||
|           const ColorFilter.mode(color, BlendMode.srcATop), | ||||
|         ); | ||||
|       }, | ||||
| @ -234,13 +304,13 @@ void main() { | ||||
|     test( | ||||
|       'setOpacity sets opacity of the informed paintId', | ||||
|       () { | ||||
|         final comp = _MyComponentWithType(); | ||||
|         final component = _MyComponentWithType(); | ||||
|         const color = Color(0xFFE5E5E5); | ||||
|         comp.setPaint(_MyComponentKeys.background, Paint()); | ||||
|         comp.tint(color, paintId: _MyComponentKeys.background); | ||||
|         component.setPaint(_MyComponentKeys.background, Paint()); | ||||
|         component.tint(color, paintId: _MyComponentKeys.background); | ||||
|  | ||||
|         expect( | ||||
|           comp.getPaint(_MyComponentKeys.background).colorFilter, | ||||
|           component.getPaint(_MyComponentKeys.background).colorFilter, | ||||
|           const ColorFilter.mode(color, BlendMode.srcATop), | ||||
|         ); | ||||
|       }, | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Matt Bennett
					Matt Bennett