mirror of
				https://github.com/flame-engine/flame.git
				synced 2025-10-31 08:56:01 +08:00 
			
		
		
		
	feat: Adding paint attribute to SpriteWidget and SpriteAnimationWidget (#3298)
Adds a `Paint` attribute to the `SpriteWidget` and `SpriteAnimationWidget` for an improved API. --------- Co-authored-by: Lukas Klingsbo <me@lukas.fyi>
This commit is contained in:
		
							
								
								
									
										28
									
								
								examples/lib/stories/widgets/paints.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								examples/lib/stories/widgets/paints.dart
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | |||||||
|  | import 'dart:ui'; | ||||||
|  |  | ||||||
|  | final paintChoices = [ | ||||||
|  |   'none', | ||||||
|  |   'transparent', | ||||||
|  |   'red tinted', | ||||||
|  |   'green tinted', | ||||||
|  |   'blue tinted', | ||||||
|  | ]; | ||||||
|  | final paintList = [ | ||||||
|  |   null, | ||||||
|  |   Paint()..color = const Color(0x22FFFFFF), | ||||||
|  |   Paint() | ||||||
|  |     ..colorFilter = const ColorFilter.mode( | ||||||
|  |       Color(0x88FF0000), | ||||||
|  |       BlendMode.srcATop, | ||||||
|  |     ), | ||||||
|  |   Paint() | ||||||
|  |     ..colorFilter = const ColorFilter.mode( | ||||||
|  |       Color(0x8800FF00), | ||||||
|  |       BlendMode.srcATop, | ||||||
|  |     ), | ||||||
|  |   Paint() | ||||||
|  |     ..colorFilter = const ColorFilter.mode( | ||||||
|  |       Color(0x880000FF), | ||||||
|  |       BlendMode.srcATop, | ||||||
|  |     ), | ||||||
|  | ]; | ||||||
| @ -1,4 +1,5 @@ | |||||||
| import 'package:dashbook/dashbook.dart'; | import 'package:dashbook/dashbook.dart'; | ||||||
|  | import 'package:examples/stories/widgets/paints.dart'; | ||||||
| import 'package:flame/extensions.dart'; | import 'package:flame/extensions.dart'; | ||||||
| import 'package:flame/widgets.dart'; | import 'package:flame/widgets.dart'; | ||||||
| import 'package:flutter/widgets.dart'; | import 'package:flutter/widgets.dart'; | ||||||
| @ -20,6 +21,13 @@ Widget spriteAnimationWidgetBuilder(DashbookContext ctx) { | |||||||
|       anchor: Anchor.valueOf( |       anchor: Anchor.valueOf( | ||||||
|         ctx.listProperty('anchor', 'center', anchorOptions), |         ctx.listProperty('anchor', 'center', anchorOptions), | ||||||
|       ), |       ), | ||||||
|  |       paint: paintList[paintChoices.indexOf( | ||||||
|  |         ctx.listProperty( | ||||||
|  |           'paint', | ||||||
|  |           'none', | ||||||
|  |           paintChoices, | ||||||
|  |         ), | ||||||
|  |       )], | ||||||
|     ), |     ), | ||||||
|   ); |   ); | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,6 +1,7 @@ | |||||||
| import 'dart:math'; | import 'dart:math'; | ||||||
|  |  | ||||||
| import 'package:dashbook/dashbook.dart'; | import 'package:dashbook/dashbook.dart'; | ||||||
|  | import 'package:examples/stories/widgets/paints.dart'; | ||||||
| import 'package:flame/widgets.dart'; | import 'package:flame/widgets.dart'; | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
|  |  | ||||||
| @ -17,6 +18,13 @@ Widget spriteWidgetBuilder(DashbookContext ctx) { | |||||||
|       anchor: Anchor.valueOf( |       anchor: Anchor.valueOf( | ||||||
|         ctx.listProperty('anchor', 'center', anchorOptions), |         ctx.listProperty('anchor', 'center', anchorOptions), | ||||||
|       ), |       ), | ||||||
|  |       paint: paintList[paintChoices.indexOf( | ||||||
|  |         ctx.listProperty( | ||||||
|  |           'paint', | ||||||
|  |           'none', | ||||||
|  |           paintChoices, | ||||||
|  |         ), | ||||||
|  |       )], | ||||||
|     ), |     ), | ||||||
|   ); |   ); | ||||||
| } | } | ||||||
|  | |||||||
| @ -30,6 +30,10 @@ class SpriteAnimationWidget extends StatelessWidget { | |||||||
|   /// A callback that is called when the animation completes. |   /// A callback that is called when the animation completes. | ||||||
|   final VoidCallback? onComplete; |   final VoidCallback? onComplete; | ||||||
|  |  | ||||||
|  |   /// A custom [Paint] to be used when rendering the sprite. | ||||||
|  |   /// When omitted the default paint from the [Sprite] class will be used. | ||||||
|  |   final Paint? paint; | ||||||
|  |  | ||||||
|   const SpriteAnimationWidget({ |   const SpriteAnimationWidget({ | ||||||
|     required SpriteAnimation animation, |     required SpriteAnimation animation, | ||||||
|     required SpriteAnimationTicker animationTicker, |     required SpriteAnimationTicker animationTicker, | ||||||
| @ -38,6 +42,7 @@ class SpriteAnimationWidget extends StatelessWidget { | |||||||
|     this.errorBuilder, |     this.errorBuilder, | ||||||
|     this.loadingBuilder, |     this.loadingBuilder, | ||||||
|     this.onComplete, |     this.onComplete, | ||||||
|  |     this.paint, | ||||||
|     super.key, |     super.key, | ||||||
|   })  : _animationFuture = animation, |   })  : _animationFuture = animation, | ||||||
|         _animationTicker = animationTicker; |         _animationTicker = animationTicker; | ||||||
| @ -57,6 +62,7 @@ class SpriteAnimationWidget extends StatelessWidget { | |||||||
|     this.errorBuilder, |     this.errorBuilder, | ||||||
|     this.loadingBuilder, |     this.loadingBuilder, | ||||||
|     this.onComplete, |     this.onComplete, | ||||||
|  |     this.paint, | ||||||
|     super.key, |     super.key, | ||||||
|   })  : _animationFuture = SpriteAnimation.load(path, data, images: images), |   })  : _animationFuture = SpriteAnimation.load(path, data, images: images), | ||||||
|         _animationTicker = null; |         _animationTicker = null; | ||||||
| @ -74,6 +80,7 @@ class SpriteAnimationWidget extends StatelessWidget { | |||||||
|           animationTicker: ticker, |           animationTicker: ticker, | ||||||
|           anchor: anchor, |           anchor: anchor, | ||||||
|           playing: playing, |           playing: playing, | ||||||
|  |           paint: paint, | ||||||
|         ); |         ); | ||||||
|       }, |       }, | ||||||
|       errorBuilder: errorBuilder, |       errorBuilder: errorBuilder, | ||||||
| @ -97,11 +104,14 @@ class InternalSpriteAnimationWidget extends StatefulWidget { | |||||||
|   /// Should the [animation] be playing or not |   /// Should the [animation] be playing or not | ||||||
|   final bool playing; |   final bool playing; | ||||||
|  |  | ||||||
|  |   final Paint? paint; | ||||||
|  |  | ||||||
|   const InternalSpriteAnimationWidget({ |   const InternalSpriteAnimationWidget({ | ||||||
|     required this.animation, |     required this.animation, | ||||||
|     required this.animationTicker, |     required this.animationTicker, | ||||||
|     this.playing = true, |     this.playing = true, | ||||||
|     this.anchor = Anchor.topLeft, |     this.anchor = Anchor.topLeft, | ||||||
|  |     this.paint, | ||||||
|     super.key, |     super.key, | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
| @ -193,6 +203,7 @@ class _InternalSpriteAnimationWidgetState | |||||||
|       painter: SpritePainter( |       painter: SpritePainter( | ||||||
|         widget.animationTicker.getSprite(), |         widget.animationTicker.getSprite(), | ||||||
|         widget.anchor, |         widget.anchor, | ||||||
|  |         widget.paint, | ||||||
|       ), |       ), | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -8,16 +8,18 @@ import 'package:flutter/widgets.dart'; | |||||||
| class SpritePainter extends CustomPainter { | class SpritePainter extends CustomPainter { | ||||||
|   final Sprite _sprite; |   final Sprite _sprite; | ||||||
|   final Anchor _anchor; |   final Anchor _anchor; | ||||||
|  |   final Paint? _paint; | ||||||
|   final double _angle; |   final double _angle; | ||||||
|  |  | ||||||
|   SpritePainter(this._sprite, this._anchor, {double angle = 0}) |   SpritePainter(this._sprite, this._anchor, this._paint, {double angle = 0}) | ||||||
|       : _angle = angle; |       : _angle = angle; | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   bool shouldRepaint(SpritePainter oldDelegate) { |   bool shouldRepaint(SpritePainter oldDelegate) { | ||||||
|     return oldDelegate._sprite != _sprite || |     return oldDelegate._sprite != _sprite || | ||||||
|         oldDelegate._anchor != _anchor || |         oldDelegate._anchor != _anchor || | ||||||
|         oldDelegate._angle != _angle; |         oldDelegate._angle != _angle || | ||||||
|  |         oldDelegate._paint != _paint; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
| @ -33,12 +35,16 @@ class SpritePainter extends CustomPainter { | |||||||
|     canvas.translateVector(boxAnchorPosition..sub(spriteAnchorPosition)); |     canvas.translateVector(boxAnchorPosition..sub(spriteAnchorPosition)); | ||||||
|  |  | ||||||
|     if (_angle == 0) { |     if (_angle == 0) { | ||||||
|       _sprite.render(canvas, size: paintSize); |       _sprite.render(canvas, size: paintSize, overridePaint: _paint); | ||||||
|     } else { |     } else { | ||||||
|       canvas.renderRotated( |       canvas.renderRotated( | ||||||
|         _angle, |         _angle, | ||||||
|         spriteAnchorPosition, |         spriteAnchorPosition, | ||||||
|         (canvas) => _sprite.render(canvas, size: paintSize), |         (canvas) => _sprite.render( | ||||||
|  |           canvas, | ||||||
|  |           size: paintSize, | ||||||
|  |           overridePaint: _paint, | ||||||
|  |         ), | ||||||
|       ); |       ); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -25,6 +25,10 @@ class SpriteWidget extends StatelessWidget { | |||||||
|   /// A builder function that is called while the loading is on the way |   /// A builder function that is called while the loading is on the way | ||||||
|   final WidgetBuilder? loadingBuilder; |   final WidgetBuilder? loadingBuilder; | ||||||
|  |  | ||||||
|  |   /// A custom [Paint] to be used when rendering the sprite. | ||||||
|  |   /// When omitted the default paint from the [Sprite] class will be used. | ||||||
|  |   final Paint? paint; | ||||||
|  |  | ||||||
|   final FutureOr<Sprite> _spriteFuture; |   final FutureOr<Sprite> _spriteFuture; | ||||||
|  |  | ||||||
|   /// renders the [sprite] as a Widget. |   /// renders the [sprite] as a Widget. | ||||||
| @ -36,6 +40,7 @@ class SpriteWidget extends StatelessWidget { | |||||||
|     this.angle = 0, |     this.angle = 0, | ||||||
|     this.errorBuilder, |     this.errorBuilder, | ||||||
|     this.loadingBuilder, |     this.loadingBuilder, | ||||||
|  |     this.paint, | ||||||
|     super.key, |     super.key, | ||||||
|   }) : _spriteFuture = sprite; |   }) : _spriteFuture = sprite; | ||||||
|  |  | ||||||
| @ -54,6 +59,7 @@ class SpriteWidget extends StatelessWidget { | |||||||
|     Vector2? srcSize, |     Vector2? srcSize, | ||||||
|     this.errorBuilder, |     this.errorBuilder, | ||||||
|     this.loadingBuilder, |     this.loadingBuilder, | ||||||
|  |     this.paint, | ||||||
|     super.key, |     super.key, | ||||||
|   }) : _spriteFuture = Sprite.load( |   }) : _spriteFuture = Sprite.load( | ||||||
|           path, |           path, | ||||||
| @ -71,6 +77,7 @@ class SpriteWidget extends StatelessWidget { | |||||||
|           sprite: sprite, |           sprite: sprite, | ||||||
|           anchor: anchor, |           anchor: anchor, | ||||||
|           angle: angle, |           angle: angle, | ||||||
|  |           paint: paint, | ||||||
|         ); |         ); | ||||||
|       }, |       }, | ||||||
|       errorBuilder: errorBuilder, |       errorBuilder: errorBuilder, | ||||||
| @ -91,17 +98,20 @@ class InternalSpriteWidget extends StatelessWidget { | |||||||
|   /// The angle to rotate this [sprite], in rad. (default = 0) |   /// The angle to rotate this [sprite], in rad. (default = 0) | ||||||
|   final double angle; |   final double angle; | ||||||
|  |  | ||||||
|  |   final Paint? paint; | ||||||
|  |  | ||||||
|   const InternalSpriteWidget({ |   const InternalSpriteWidget({ | ||||||
|     required this.sprite, |     required this.sprite, | ||||||
|     this.anchor = Anchor.topLeft, |     this.anchor = Anchor.topLeft, | ||||||
|     this.angle = 0, |     this.angle = 0, | ||||||
|  |     this.paint, | ||||||
|     super.key, |     super.key, | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
|     return CustomPaint( |     return CustomPaint( | ||||||
|       painter: SpritePainter(sprite, anchor, angle: angle), |       painter: SpritePainter(sprite, anchor, paint, angle: angle), | ||||||
|       size: sprite.srcSize.toSize(), |       size: sprite.srcSize.toSize(), | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 Erick
					Erick