mirror of
https://github.com/flame-engine/flame.git
synced 2025-10-28 19:33:37 +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:examples/stories/widgets/paints.dart';
|
||||
import 'package:flame/extensions.dart';
|
||||
import 'package:flame/widgets.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
@ -20,6 +21,13 @@ Widget spriteAnimationWidgetBuilder(DashbookContext ctx) {
|
||||
anchor: Anchor.valueOf(
|
||||
ctx.listProperty('anchor', 'center', anchorOptions),
|
||||
),
|
||||
paint: paintList[paintChoices.indexOf(
|
||||
ctx.listProperty(
|
||||
'paint',
|
||||
'none',
|
||||
paintChoices,
|
||||
),
|
||||
)],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:dashbook/dashbook.dart';
|
||||
import 'package:examples/stories/widgets/paints.dart';
|
||||
import 'package:flame/widgets.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
@ -17,6 +18,13 @@ Widget spriteWidgetBuilder(DashbookContext ctx) {
|
||||
anchor: Anchor.valueOf(
|
||||
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.
|
||||
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({
|
||||
required SpriteAnimation animation,
|
||||
required SpriteAnimationTicker animationTicker,
|
||||
@ -38,6 +42,7 @@ class SpriteAnimationWidget extends StatelessWidget {
|
||||
this.errorBuilder,
|
||||
this.loadingBuilder,
|
||||
this.onComplete,
|
||||
this.paint,
|
||||
super.key,
|
||||
}) : _animationFuture = animation,
|
||||
_animationTicker = animationTicker;
|
||||
@ -57,6 +62,7 @@ class SpriteAnimationWidget extends StatelessWidget {
|
||||
this.errorBuilder,
|
||||
this.loadingBuilder,
|
||||
this.onComplete,
|
||||
this.paint,
|
||||
super.key,
|
||||
}) : _animationFuture = SpriteAnimation.load(path, data, images: images),
|
||||
_animationTicker = null;
|
||||
@ -74,6 +80,7 @@ class SpriteAnimationWidget extends StatelessWidget {
|
||||
animationTicker: ticker,
|
||||
anchor: anchor,
|
||||
playing: playing,
|
||||
paint: paint,
|
||||
);
|
||||
},
|
||||
errorBuilder: errorBuilder,
|
||||
@ -97,11 +104,14 @@ class InternalSpriteAnimationWidget extends StatefulWidget {
|
||||
/// Should the [animation] be playing or not
|
||||
final bool playing;
|
||||
|
||||
final Paint? paint;
|
||||
|
||||
const InternalSpriteAnimationWidget({
|
||||
required this.animation,
|
||||
required this.animationTicker,
|
||||
this.playing = true,
|
||||
this.anchor = Anchor.topLeft,
|
||||
this.paint,
|
||||
super.key,
|
||||
});
|
||||
|
||||
@ -193,6 +203,7 @@ class _InternalSpriteAnimationWidgetState
|
||||
painter: SpritePainter(
|
||||
widget.animationTicker.getSprite(),
|
||||
widget.anchor,
|
||||
widget.paint,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@ -8,16 +8,18 @@ import 'package:flutter/widgets.dart';
|
||||
class SpritePainter extends CustomPainter {
|
||||
final Sprite _sprite;
|
||||
final Anchor _anchor;
|
||||
final Paint? _paint;
|
||||
final double _angle;
|
||||
|
||||
SpritePainter(this._sprite, this._anchor, {double angle = 0})
|
||||
SpritePainter(this._sprite, this._anchor, this._paint, {double angle = 0})
|
||||
: _angle = angle;
|
||||
|
||||
@override
|
||||
bool shouldRepaint(SpritePainter oldDelegate) {
|
||||
return oldDelegate._sprite != _sprite ||
|
||||
oldDelegate._anchor != _anchor ||
|
||||
oldDelegate._angle != _angle;
|
||||
oldDelegate._angle != _angle ||
|
||||
oldDelegate._paint != _paint;
|
||||
}
|
||||
|
||||
@override
|
||||
@ -33,12 +35,16 @@ class SpritePainter extends CustomPainter {
|
||||
canvas.translateVector(boxAnchorPosition..sub(spriteAnchorPosition));
|
||||
|
||||
if (_angle == 0) {
|
||||
_sprite.render(canvas, size: paintSize);
|
||||
_sprite.render(canvas, size: paintSize, overridePaint: _paint);
|
||||
} else {
|
||||
canvas.renderRotated(
|
||||
_angle,
|
||||
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
|
||||
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;
|
||||
|
||||
/// renders the [sprite] as a Widget.
|
||||
@ -36,6 +40,7 @@ class SpriteWidget extends StatelessWidget {
|
||||
this.angle = 0,
|
||||
this.errorBuilder,
|
||||
this.loadingBuilder,
|
||||
this.paint,
|
||||
super.key,
|
||||
}) : _spriteFuture = sprite;
|
||||
|
||||
@ -54,6 +59,7 @@ class SpriteWidget extends StatelessWidget {
|
||||
Vector2? srcSize,
|
||||
this.errorBuilder,
|
||||
this.loadingBuilder,
|
||||
this.paint,
|
||||
super.key,
|
||||
}) : _spriteFuture = Sprite.load(
|
||||
path,
|
||||
@ -71,6 +77,7 @@ class SpriteWidget extends StatelessWidget {
|
||||
sprite: sprite,
|
||||
anchor: anchor,
|
||||
angle: angle,
|
||||
paint: paint,
|
||||
);
|
||||
},
|
||||
errorBuilder: errorBuilder,
|
||||
@ -91,17 +98,20 @@ class InternalSpriteWidget extends StatelessWidget {
|
||||
/// The angle to rotate this [sprite], in rad. (default = 0)
|
||||
final double angle;
|
||||
|
||||
final Paint? paint;
|
||||
|
||||
const InternalSpriteWidget({
|
||||
required this.sprite,
|
||||
this.anchor = Anchor.topLeft,
|
||||
this.angle = 0,
|
||||
this.paint,
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CustomPaint(
|
||||
painter: SpritePainter(sprite, anchor, angle: angle),
|
||||
painter: SpritePainter(sprite, anchor, paint, angle: angle),
|
||||
size: sprite.srcSize.toSize(),
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user