mirror of
https://github.com/flame-engine/flame.git
synced 2025-11-01 19:12:31 +08:00
TextPaint to use TextStyle instead of TextPaintConfig (#1086)
* `TextPaint` to use `TextStyle` instead of `TextPaintConfig` * Update packages/flame/lib/src/text.dart Co-authored-by: Pasha Stetsenko <stpasha@google.com> * Removed BaseTextConfig and TextPaintConfig * Update text docs * Apply suggestions from code review Co-authored-by: Erick <erickzanardoo@gmail.com> * Remove generics * Update TextBoxExample * Update text examples variable names * Fix TextPaint in collision_detection example Co-authored-by: Pasha Stetsenko <stpasha@google.com> Co-authored-by: Erick <erickzanardoo@gmail.com>
This commit is contained in:
38
doc/text.md
38
doc/text.md
@ -10,32 +10,45 @@ and create a custom way to render text.
|
||||
|
||||
## TextPaint
|
||||
|
||||
A Text Paint is the built in implementation of text rendering on Flame, it is based on top of
|
||||
Flutter's `TextPainter` class (hence the name), it can be configured by its config class
|
||||
`TextPaintConfig` which contains all typographical information required to render text; i.e., font
|
||||
size and color, family, etc.
|
||||
A `TextPaint` is the built in implementation of text rendering in Flame, it is based on top of
|
||||
Flutter's `TextPainter` class (hence the name), it can be configured by the style class `TextStyle`
|
||||
which contains all typographical information required to render text; i.e., font size and color,
|
||||
font family, etc.
|
||||
|
||||
Example usage:
|
||||
|
||||
```dart
|
||||
const TextPaint textPaint = TextPaint(
|
||||
config: TextPaintConfig(
|
||||
style: TextStyle(
|
||||
fontSize: 48.0,
|
||||
fontFamily: 'Awesome Font',
|
||||
),
|
||||
);
|
||||
```
|
||||
|
||||
Note: there are several packages that contain the class `TextStyle`, make sure that you import
|
||||
either `package:flutter/material.dart` or `package:flutter/painting.dart` and if you also need to
|
||||
import `dart:ui` you need to import it like this (since that contains another class that is also
|
||||
named `TextStyle`):
|
||||
|
||||
```dart
|
||||
import 'dart:ui' hide TextStyle;
|
||||
```
|
||||
|
||||
Some common properties of `TextStyle` are the following (here is the
|
||||
[full list](https://api.flutter.dev/flutter/painting/TextStyle-class.html)):
|
||||
|
||||
- `fontFamily`: a commonly available font, like Arial (default), or a custom font added in your
|
||||
pubspec (see [here](https://flutter.io/custom-fonts/) how to do it).
|
||||
- `fontSize`: font size, in pts (default `24.0`).
|
||||
- `lineHeight`: height of text line, as a multiple of font size (default `null`).
|
||||
- `color`: the color, as a `ui.Color` (default black).
|
||||
- `height`: height of text line, as a multiple of font size (default `null`).
|
||||
- `color`: the color, as a `ui.Color` (default white).
|
||||
|
||||
For more information regarding colors and how to create then, see the
|
||||
[Colors and the Palette](palette.md) guide.
|
||||
|
||||
After the creation of the text paint you can use its `render` method to draw some string on a canvas:
|
||||
After the creation of the `TextPaint` object you can use its `render` method to draw strings on
|
||||
a canvas:
|
||||
|
||||
```dart
|
||||
textPaint.render(canvas, "Flame is awesome", Vector2(10, 10));
|
||||
@ -60,7 +73,8 @@ Flame provides two text components that make it even easier to render text in yo
|
||||
Example usage:
|
||||
|
||||
```dart
|
||||
TextPaint regular = TextPaint(color: BasicPalette.white.color);
|
||||
final style = TextStyle(color: BasicPalette.white.color);
|
||||
final regular = TextPaint(style: style);
|
||||
|
||||
class MyGame extends FlameGame {
|
||||
@override
|
||||
@ -95,9 +109,9 @@ class MyTextBox extends TextBoxComponent {
|
||||
c.drawRect(rect, Paint()..color = Color(0xFFFF00FF));
|
||||
c.drawRect(
|
||||
rect.deflate(boxConfig.margin),
|
||||
Paint()
|
||||
..color = BasicPalette.black.color
|
||||
..style = PaintingStyle.stroke);
|
||||
BasicPalette.black.Paint()
|
||||
..style = PaintingStyle.stroke,
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@ -101,10 +101,7 @@ class CoordinateSystemsGame extends FlameGame
|
||||
..strokeWidth = 2
|
||||
..color = BasicPalette.red.color;
|
||||
static final _text = TextPaint(
|
||||
config: TextPaintConfig(
|
||||
color: BasicPalette.red.color,
|
||||
fontSize: 12,
|
||||
),
|
||||
style: TextStyle(color: BasicPalette.red.color, fontSize: 12),
|
||||
);
|
||||
|
||||
String? lastEventDescription;
|
||||
|
||||
@ -14,9 +14,7 @@ class MovableSquare extends SquareComponent
|
||||
with Collidable, HasGameRef<CameraAndViewportGame>, KeyboardHandler {
|
||||
static const double speed = 300;
|
||||
static final TextPaint textRenderer = TextPaint(
|
||||
config: const TextPaintConfig(
|
||||
fontSize: 12,
|
||||
),
|
||||
style: const TextStyle(fontSize: 12),
|
||||
);
|
||||
|
||||
final Vector2 velocity = Vector2.zero();
|
||||
|
||||
@ -26,11 +26,7 @@ class MultipleShapesExample extends FlameGame
|
||||
any direction.
|
||||
''';
|
||||
|
||||
final TextPaint fpsTextPaint = TextPaint(
|
||||
config: TextPaintConfig(
|
||||
color: BasicPalette.white.color,
|
||||
),
|
||||
);
|
||||
final TextPaint fpsTextPaint = TextPaint();
|
||||
|
||||
@override
|
||||
Future<void> onLoad() async {
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import 'dart:ui';
|
||||
import 'dart:ui' hide TextStyle;
|
||||
|
||||
import 'package:flame/components.dart';
|
||||
import 'package:flame/game.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class LogoCompomnent extends SpriteComponent with HasGameRef<DebugGame> {
|
||||
static const int speed = 150;
|
||||
@ -35,9 +36,7 @@ class LogoCompomnent extends SpriteComponent with HasGameRef<DebugGame> {
|
||||
|
||||
class DebugGame extends FlameGame with FPSCounter {
|
||||
static final fpsTextPaint = TextPaint(
|
||||
config: const TextPaintConfig(
|
||||
color: Color(0xFFFFFFFF),
|
||||
),
|
||||
style: const TextStyle(color: Color(0xFFFFFFFF)),
|
||||
);
|
||||
|
||||
@override
|
||||
|
||||
@ -102,8 +102,9 @@ class JoystickAdvancedGame extends FlameGame
|
||||
),
|
||||
);
|
||||
|
||||
final _regularTextConfig = TextPaintConfig(color: BasicPalette.white.color);
|
||||
final _regular = TextPaint(config: _regularTextConfig);
|
||||
final _regular = TextPaint(
|
||||
style: TextStyle(color: BasicPalette.white.color),
|
||||
);
|
||||
speedText = TextComponent(
|
||||
'Speed: 0',
|
||||
textRenderer: _regular,
|
||||
|
||||
@ -5,39 +5,45 @@ import 'package:flame/game.dart';
|
||||
import 'package:flame/palette.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
final _regularTextConfig = TextPaintConfig(color: BasicPalette.white.color);
|
||||
final _regular = TextPaint(config: _regularTextConfig);
|
||||
final _tiny = TextPaint(config: _regularTextConfig.withFontSize(12.0));
|
||||
|
||||
final _white = Paint()
|
||||
..color = BasicPalette.white.color
|
||||
..style = PaintingStyle.stroke;
|
||||
final _regularTextStyle =
|
||||
TextStyle(fontSize: 18, color: BasicPalette.white.color);
|
||||
final _regular = TextPaint(style: _regularTextStyle);
|
||||
final _tiny = TextPaint(style: _regularTextStyle.copyWith(fontSize: 14.0));
|
||||
final _box = _regular.copyWith(
|
||||
(style) => style.copyWith(
|
||||
color: Colors.lightGreenAccent,
|
||||
fontFamily: 'monospace',
|
||||
letterSpacing: 2.0,
|
||||
),
|
||||
);
|
||||
final _shaded = TextPaint(
|
||||
style: TextStyle(
|
||||
color: BasicPalette.white.color,
|
||||
fontSize: 40.0,
|
||||
shadows: const [
|
||||
Shadow(color: Colors.red, offset: Offset(2, 2), blurRadius: 2),
|
||||
Shadow(color: Colors.yellow, offset: Offset(4, 4), blurRadius: 4),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
class MyTextBox extends TextBoxComponent {
|
||||
MyTextBox(String text)
|
||||
: super(
|
||||
text,
|
||||
textRenderer: _regular,
|
||||
textRenderer: _box,
|
||||
boxConfig: TextBoxConfig(
|
||||
maxWidth: 400,
|
||||
timePerChar: 0.05,
|
||||
growingBox: true,
|
||||
margins: const EdgeInsets.symmetric(horizontal: 10, vertical: 15),
|
||||
margins: const EdgeInsets.all(25),
|
||||
),
|
||||
);
|
||||
|
||||
@override
|
||||
void drawBackground(Canvas c) {
|
||||
final rect = Rect.fromLTWH(0, 0, width, height);
|
||||
c.drawRect(rect, Paint()..color = Colors.amber);
|
||||
final margin = boxConfig.margins;
|
||||
final innerRect = Rect.fromLTWH(
|
||||
margin.left,
|
||||
margin.top,
|
||||
width - margin.horizontal,
|
||||
height - margin.vertical,
|
||||
);
|
||||
c.drawRect(innerRect, _white);
|
||||
c.drawRect(rect, Paint()..color = Colors.white10);
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,6 +58,12 @@ class TextGame extends FlameGame {
|
||||
..y = 32.0,
|
||||
);
|
||||
|
||||
add(
|
||||
TextComponent('Text with shade', textRenderer: _shaded)
|
||||
..anchor = Anchor.topRight
|
||||
..position = size - Vector2.all(100),
|
||||
);
|
||||
|
||||
add(
|
||||
TextComponent('center', textRenderer: _tiny)
|
||||
..anchor = Anchor.center
|
||||
@ -66,7 +78,11 @@ class TextGame extends FlameGame {
|
||||
|
||||
add(
|
||||
MyTextBox(
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam eget ligula eu lectus lobortis condimentum.',
|
||||
'"This is our world now. The world of the electron and the switch; '
|
||||
'the beauty of the baud. We exist without nationality, skin color, '
|
||||
'or religious bias. You wage wars, murder, cheat, lie to us and try '
|
||||
"to make us believe it's for our own good, yet we're the "
|
||||
'criminals. Yes, I am a criminal. My crime is that of curiosity."',
|
||||
)
|
||||
..anchor = Anchor.bottomLeft
|
||||
..y = size.y,
|
||||
|
||||
@ -23,9 +23,7 @@ class ParticlesGame extends FlameGame with FPSCounter {
|
||||
final StepTween steppedTween = StepTween(begin: 0, end: 5);
|
||||
final trafficLight = TrafficLightComponent();
|
||||
final TextPaint fpsTextPaint = TextPaint(
|
||||
config: const TextPaintConfig(
|
||||
color: Color(0xFFFFFFFF),
|
||||
),
|
||||
style: const TextStyle(color: Colors.white),
|
||||
);
|
||||
|
||||
/// Defines the lifespan of all the particles in these examples
|
||||
|
||||
@ -5,9 +5,7 @@ import 'package:flutter/material.dart';
|
||||
|
||||
class TimerGame extends FlameGame with TapDetector {
|
||||
final TextPaint textConfig = TextPaint(
|
||||
config: const TextPaintConfig(
|
||||
color: Color(0xFFFFFFFF),
|
||||
),
|
||||
style: const TextStyle(color: Colors.white),
|
||||
);
|
||||
late Timer countdown;
|
||||
late Timer interval;
|
||||
|
||||
@ -5,9 +5,7 @@ import 'package:flutter/material.dart';
|
||||
|
||||
class RenderedTimeComponent extends TimerComponent {
|
||||
final TextPaint textPaint = TextPaint(
|
||||
config: const TextPaintConfig(
|
||||
color: Color(0xFFFFFFFF),
|
||||
),
|
||||
style: const TextStyle(color: Colors.white),
|
||||
);
|
||||
|
||||
final double yOffset;
|
||||
|
||||
@ -22,6 +22,7 @@
|
||||
- Components that manipulate canvas state are now responsible for saving/restoring that state
|
||||
- Remove `super.render` calls that are no longer needed
|
||||
- Fixed typo in error message
|
||||
- `TextPaint` to use `TextStyle` (material) instead of `TextPaintConfig`
|
||||
- Underlying `Shape`s in `ShapeComponent` transform with components position, size and angle
|
||||
- `HitboxShape` takes parents ancestors transformations into consideration (not scaling)
|
||||
|
||||
|
||||
@ -104,10 +104,7 @@ class Component with Loadable {
|
||||
TextPaint get debugTextPaint {
|
||||
if (!_debugTextPaintCache.isCacheValid([debugColor])) {
|
||||
final textPaint = TextPaint(
|
||||
config: TextPaintConfig(
|
||||
color: debugColor,
|
||||
fontSize: 12,
|
||||
),
|
||||
style: TextStyle(color: debugColor, fontSize: 12),
|
||||
);
|
||||
_debugTextPaintCache.updateCache(textPaint, [debugColor]);
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import 'dart:ui';
|
||||
import 'dart:ui' hide TextStyle, TextDirection;
|
||||
|
||||
import 'package:flutter/material.dart' as material;
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'anchor.dart';
|
||||
import 'components/cache/memory_cache.dart';
|
||||
@ -8,34 +8,38 @@ import 'components/text_component.dart';
|
||||
import 'extensions/size.dart';
|
||||
import 'extensions/vector2.dart';
|
||||
|
||||
/// [TextRenderer] is the abstract API that Flame uses for rendering text in its features
|
||||
/// this class can be extended to provide an implementation of text rendering in the engine.
|
||||
/// [TextRenderer] is the abstract API that Flame uses for rendering text.
|
||||
/// This class can be extended to provide another implementation of text
|
||||
/// rendering in the engine.
|
||||
///
|
||||
/// See [TextPaint] for the default implementation offered by Flame
|
||||
abstract class TextRenderer<T extends BaseTextConfig> {
|
||||
abstract class TextRenderer {
|
||||
/// A registry containing default providers for every [TextRenderer] subclass;
|
||||
/// used by [createDefault] to create default parameter values.
|
||||
///
|
||||
/// If you add a new [TextRenderer] child, you can register it by adding it,
|
||||
/// alongisde a provider lambda, to this map.
|
||||
static Map<Type, TextRenderer Function()> defaultCreatorsRegistry = {
|
||||
/// together with a provider lambda, to this map.
|
||||
static Map<Type, TextRenderer Function()> defaultRenderersRegistry = {
|
||||
TextRenderer: () => TextPaint(),
|
||||
TextPaint: () => TextPaint(),
|
||||
};
|
||||
|
||||
final T config;
|
||||
final TextDirection textDirection;
|
||||
|
||||
TextRenderer({required this.config});
|
||||
TextRenderer({TextDirection? textDirection})
|
||||
: textDirection = textDirection ?? TextDirection.ltr;
|
||||
|
||||
/// Renders a given [text] in a given position [position] using the provided [canvas] and [anchor].
|
||||
/// Renders a given [text] in a given position [position] using the provided
|
||||
/// [canvas] and [anchor].
|
||||
///
|
||||
/// Renders it in the given position, considering the [anchor] specified.
|
||||
/// For example, if [Anchor.center] is specified, it's going to be drawn centered around [position].
|
||||
/// For example, if [Anchor.center] is specified, it's going to be drawn
|
||||
/// centered around [position].
|
||||
///
|
||||
/// Example usage (Using TextPaint implementation):
|
||||
///
|
||||
/// const TextPaint config = TextPaint(fontSize: 48.0, fontFamily: 'Awesome Font');
|
||||
/// config.render(canvas, Vector2(size.x - 10, size.y - 10, anchor: Anchor.bottomRight);
|
||||
/// const TextStyle style = TextStyle(fontSize: 48.0, fontFamily: 'Awesome Font');
|
||||
/// const TextPaint textPaint = TextPaint(style: style);
|
||||
/// textPaint.render(canvas, Vector2(size.x - 10, size.y - 10, anchor: Anchor.bottomRight);
|
||||
void render(
|
||||
Canvas canvas,
|
||||
String text,
|
||||
@ -57,161 +61,36 @@ abstract class TextRenderer<T extends BaseTextConfig> {
|
||||
);
|
||||
}
|
||||
|
||||
/// Creates a new instance of this painter but transforming the [config]
|
||||
/// object via the provided lambda.
|
||||
TextRenderer<T> copyWith(T Function(T) transform);
|
||||
|
||||
/// Given a generic type [T], creates a default renderer of that type.
|
||||
static T createDefault<T extends TextRenderer>() {
|
||||
final creator = defaultCreatorsRegistry[T];
|
||||
final creator = defaultRenderersRegistry[T];
|
||||
if (creator != null) {
|
||||
return creator() as T;
|
||||
} else {
|
||||
throw 'Unkown implementation of TextRenderer: $T. Please register it under [defaultCreatorsRegistry].';
|
||||
throw 'Unknown implementation of TextRenderer: $T. Please register it under [defaultCreatorsRegistry].';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A Text Config contains all typographical information required to render texts; i.e., font size, text direction, etc.
|
||||
abstract class BaseTextConfig {
|
||||
/// The font size to be used, in points.
|
||||
final double fontSize;
|
||||
/// It does not hold information regarding the position of the text to be
|
||||
/// rendered, nor does it contain the text itself (the string).
|
||||
/// To use that information, use the [TextComponent], which uses [TextPaint].
|
||||
class TextPaint extends TextRenderer {
|
||||
static const TextStyle defaultTextStyle = TextStyle(
|
||||
color: Colors.white,
|
||||
fontFamily: 'Arial',
|
||||
fontSize: 24,
|
||||
);
|
||||
|
||||
/// The direction to render this text (left to right or right to left).
|
||||
///
|
||||
/// Normally, leave this as is for most languages.
|
||||
/// For proper fonts of languages like Hebrew or Arabic, replace this with [TextDirection.rtl].
|
||||
final TextDirection textDirection;
|
||||
final MemoryCache<String, TextPainter> _textPainterCache = MemoryCache();
|
||||
final TextStyle style;
|
||||
|
||||
/// The height of line, as a multiple of font size.
|
||||
final double? lineHeight;
|
||||
|
||||
const BaseTextConfig({
|
||||
this.fontSize = 24.0,
|
||||
this.textDirection = TextDirection.ltr,
|
||||
this.lineHeight,
|
||||
});
|
||||
}
|
||||
|
||||
/// An extension of the BaseTextConfig which includes more configs supported by
|
||||
/// TextPaint
|
||||
class TextPaintConfig extends BaseTextConfig {
|
||||
/// The font color to be used.
|
||||
///
|
||||
/// Dart's [Color] class is just a plain wrapper on top of ARGB color (0xAARRGGBB).
|
||||
/// For example,
|
||||
///
|
||||
/// const TextPaint config = TextPaint(color: const Color(0xFF00FF00)); // green
|
||||
///
|
||||
/// You can also use your Palette class to access colors used in your game.
|
||||
final Color color;
|
||||
|
||||
/// The font family to be used. You can use available by default fonts for your platform (like Arial), or you can add custom fonts.
|
||||
///
|
||||
/// To add custom fonts, add the following code to your pubspec.yaml file:
|
||||
///
|
||||
/// flutter:
|
||||
/// fonts:
|
||||
/// - family: 5x5
|
||||
/// fonts:
|
||||
/// - asset: assets/fonts/5x5_pixel.ttf
|
||||
///
|
||||
/// In this example we are adding a font family that's being named '5x5' provided in the specified ttf file.
|
||||
/// You must provide the full path of the ttf file (from root); you should put it into your assets folder, and preferably inside a fonts folder.
|
||||
/// You don't need to add this together with the other assets on the flutter/assets bit.
|
||||
/// The name you choose for the font family can be any name (it's not inside the TTF file and the filename doesn't need to match).
|
||||
final String fontFamily;
|
||||
|
||||
/// Creates a constant [TextPaint] with sensible defaults.
|
||||
///
|
||||
/// Every parameter can be specified.
|
||||
const TextPaintConfig({
|
||||
this.color = const Color(0xFF000000),
|
||||
this.fontFamily = 'Arial',
|
||||
double fontSize = 24.0,
|
||||
TextDirection textDirection = TextDirection.ltr,
|
||||
double? lineHeight,
|
||||
}) : super(
|
||||
fontSize: fontSize,
|
||||
TextPaint({TextStyle? style, TextDirection? textDirection})
|
||||
: style = style ?? defaultTextStyle,
|
||||
super(
|
||||
textDirection: textDirection,
|
||||
lineHeight: lineHeight,
|
||||
);
|
||||
|
||||
/// Creates a new [TextPaintConfig] changing only the [fontSize].
|
||||
///
|
||||
/// This does not change the original (as it's immutable).
|
||||
TextPaintConfig withFontSize(double fontSize) {
|
||||
return TextPaintConfig(
|
||||
fontSize: fontSize,
|
||||
color: color,
|
||||
fontFamily: fontFamily,
|
||||
textDirection: textDirection,
|
||||
);
|
||||
}
|
||||
|
||||
/// Creates a new [TextPaintConfig] changing only the [color].
|
||||
///
|
||||
/// This does not change the original (as it's immutable).
|
||||
TextPaintConfig withColor(Color color) {
|
||||
return TextPaintConfig(
|
||||
fontSize: fontSize,
|
||||
color: color,
|
||||
fontFamily: fontFamily,
|
||||
textDirection: textDirection,
|
||||
);
|
||||
}
|
||||
|
||||
/// Creates a new [TextPaintConfig] changing only the [fontFamily].
|
||||
///
|
||||
/// This does not change the original (as it's immutable).
|
||||
TextPaintConfig withFontFamily(String fontFamily) {
|
||||
return TextPaintConfig(
|
||||
fontSize: fontSize,
|
||||
color: color,
|
||||
fontFamily: fontFamily,
|
||||
textDirection: textDirection,
|
||||
);
|
||||
}
|
||||
|
||||
/// Creates a new [TextPaintConfig] changing only the [textAlign].
|
||||
///
|
||||
/// This does not change the original (as it's immutable).
|
||||
TextPaintConfig withTextAlign(TextAlign textAlign) {
|
||||
return TextPaintConfig(
|
||||
fontSize: fontSize,
|
||||
color: color,
|
||||
fontFamily: fontFamily,
|
||||
textDirection: textDirection,
|
||||
);
|
||||
}
|
||||
|
||||
/// Creates a new [TextPaintConfig] changing only the [textDirection].
|
||||
///
|
||||
/// This does not change the original (as it's immutable).
|
||||
TextPaintConfig withTextDirection(TextDirection textDirection) {
|
||||
return TextPaintConfig(
|
||||
fontSize: fontSize,
|
||||
color: color,
|
||||
fontFamily: fontFamily,
|
||||
textDirection: textDirection,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// A Text Config contains all typographical information required to render texts; i.e., font size and color, family, etc.
|
||||
///
|
||||
/// It does not hold information regarding the position of the text to be render neither the text itself (the string).
|
||||
/// To hold all those information, use the Text component.
|
||||
///
|
||||
/// It is used by [TextComponent].
|
||||
class TextPaint extends TextRenderer<TextPaintConfig> {
|
||||
final MemoryCache<String, material.TextPainter> _textPainterCache =
|
||||
MemoryCache();
|
||||
|
||||
TextPaint({
|
||||
TextPaintConfig config = const TextPaintConfig(),
|
||||
}) : super(config: config);
|
||||
|
||||
@override
|
||||
void render(
|
||||
Canvas canvas,
|
||||
@ -234,9 +113,11 @@ class TextPaint extends TextRenderer<TextPaintConfig> {
|
||||
return toTextPainter(text).height;
|
||||
}
|
||||
|
||||
/// Returns a [material.TextPainter] that allows for text rendering and size measuring.
|
||||
/// Returns a [TextPainter] that allows for text rendering and size
|
||||
/// measuring.
|
||||
///
|
||||
/// A [material.TextPainter] has three important properties: paint, width and height (or size).
|
||||
/// A [TextPainter] has three important properties: paint, width and
|
||||
/// height (or size).
|
||||
///
|
||||
/// Example usage:
|
||||
///
|
||||
@ -244,23 +125,18 @@ class TextPaint extends TextRenderer<TextPaintConfig> {
|
||||
/// final tp = config.toTextPainter('Score: $score');
|
||||
/// tp.paint(c, Offset(size.width - p.width - 10, size.height - p.height - 10));
|
||||
///
|
||||
/// However, you probably want to use the [render] method which already renders for you considering the anchor.
|
||||
/// That way, you don't need to perform the math for yourself.
|
||||
material.TextPainter toTextPainter(String text) {
|
||||
/// However, you probably want to use the [render] method which already
|
||||
/// takes the anchor into consideration.
|
||||
/// That way, you don't need to perform the math for that yourself.
|
||||
TextPainter toTextPainter(String text) {
|
||||
if (!_textPainterCache.containsKey(text)) {
|
||||
final style = material.TextStyle(
|
||||
color: config.color,
|
||||
fontSize: config.fontSize,
|
||||
fontFamily: config.fontFamily,
|
||||
height: config.lineHeight,
|
||||
);
|
||||
final span = material.TextSpan(
|
||||
final span = TextSpan(
|
||||
style: style,
|
||||
text: text,
|
||||
);
|
||||
final tp = material.TextPainter(
|
||||
final tp = TextPainter(
|
||||
text: span,
|
||||
textDirection: config.textDirection,
|
||||
textDirection: textDirection,
|
||||
);
|
||||
tp.layout();
|
||||
|
||||
@ -269,10 +145,10 @@ class TextPaint extends TextRenderer<TextPaintConfig> {
|
||||
return _textPainterCache.getValue(text)!;
|
||||
}
|
||||
|
||||
@override
|
||||
TextPaint copyWith(
|
||||
TextPaintConfig Function(TextPaintConfig) transform,
|
||||
) {
|
||||
return TextPaint(config: transform(config));
|
||||
TextStyle Function(TextStyle) transform, {
|
||||
TextDirection? textDirection,
|
||||
}) {
|
||||
return TextPaint(style: transform(style), textDirection: textDirection);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,17 +1,10 @@
|
||||
import 'dart:ui';
|
||||
import 'dart:ui' hide TextStyle;
|
||||
|
||||
import 'package:flame/components.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
class _CustomTextRenderer extends TextRenderer<TextPaintConfig> {
|
||||
_CustomTextRenderer() : super(config: const TextPaintConfig());
|
||||
@override
|
||||
TextRenderer<TextPaintConfig> copyWith(
|
||||
BaseTextConfig Function(TextPaintConfig) transform,
|
||||
) {
|
||||
return this;
|
||||
}
|
||||
|
||||
class _CustomTextRenderer extends TextRenderer {
|
||||
@override
|
||||
double measureTextHeight(String text) {
|
||||
return 0;
|
||||
@ -34,11 +27,11 @@ class _CustomTextRenderer extends TextRenderer<TextPaintConfig> {
|
||||
void main() {
|
||||
group('Text', () {
|
||||
test('copyWith', () {
|
||||
const config = TextPaintConfig(fontSize: 12, fontFamily: 'Times');
|
||||
final tp = TextPaint(config: config)
|
||||
.copyWith((t) => t.withFontFamily('Helvetica'));
|
||||
expect(tp.config.fontSize, 12);
|
||||
expect(tp.config.fontFamily, 'Helvetica');
|
||||
const style = TextStyle(fontSize: 12, fontFamily: 'Times');
|
||||
final tp = TextPaint(style: style)
|
||||
.copyWith((t) => t.copyWith(fontFamily: 'Helvetica'));
|
||||
expect(tp.style.fontSize, 12);
|
||||
expect(tp.style.fontFamily, 'Helvetica');
|
||||
});
|
||||
test('createDefault', () {
|
||||
final tp = TextRenderer.createDefault<TextPaint>();
|
||||
@ -51,11 +44,13 @@ void main() {
|
||||
});
|
||||
test('change parameters of text component', () {
|
||||
final tc = TextComponent<TextPaint>('foo');
|
||||
tc.textRenderer = tc.textRenderer.copyWith((c) => c.withFontSize(200));
|
||||
expect(tc.textRenderer.config.fontSize, 200);
|
||||
tc.textRenderer = tc.textRenderer.copyWith(
|
||||
(c) => c.copyWith(fontSize: 200),
|
||||
);
|
||||
expect(tc.textRenderer.style.fontSize, 200);
|
||||
});
|
||||
test('custom renderer', () {
|
||||
TextRenderer.defaultCreatorsRegistry[_CustomTextRenderer] =
|
||||
TextRenderer.defaultRenderersRegistry[_CustomTextRenderer] =
|
||||
() => _CustomTextRenderer();
|
||||
final tc = TextComponent<_CustomTextRenderer>('foo');
|
||||
expect(tc.textRenderer, isA<_CustomTextRenderer>());
|
||||
|
||||
@ -22,7 +22,7 @@ class AudioGame extends FlameGame with TapDetector {
|
||||
static Paint black = BasicPalette.black.paint();
|
||||
static Paint gray = const PaletteEntry(Color(0xFFCCCCCC)).paint();
|
||||
static TextPaint text = TextPaint(
|
||||
config: TextPaintConfig(color: BasicPalette.white.color),
|
||||
style: TextStyle(color: BasicPalette.white.color),
|
||||
);
|
||||
|
||||
late AudioPool pool;
|
||||
|
||||
@ -2,6 +2,7 @@ import 'package:flame/components.dart';
|
||||
import 'package:flame/palette.dart';
|
||||
import 'package:flame_forge2d/flame_forge2d.dart';
|
||||
import 'package:flame_forge2d/forge2d_game.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:forge2d/forge2d.dart';
|
||||
|
||||
import 'balls.dart';
|
||||
@ -28,8 +29,8 @@ component. Click the ball to see the number increment.
|
||||
class TapableBall extends Ball with Tappable {
|
||||
late final TextComponent textComponent;
|
||||
int counter = 0;
|
||||
final TextPaintConfig _textConfig =
|
||||
TextPaintConfig(color: BasicPalette.white.color, fontSize: 4);
|
||||
final TextStyle _textStyle =
|
||||
TextStyle(color: BasicPalette.white.color, fontSize: 4);
|
||||
late final TextPaint _textPaint;
|
||||
|
||||
TapableBall(Vector2 position) : super(position) {
|
||||
@ -40,7 +41,7 @@ class TapableBall extends Ball with Tappable {
|
||||
@override
|
||||
Future<void> onLoad() async {
|
||||
super.onLoad();
|
||||
_textPaint = TextPaint(config: _textConfig);
|
||||
_textPaint = TextPaint(style: _textStyle);
|
||||
textComponent = TextComponent(counter.toString(), textRenderer: _textPaint);
|
||||
add(textComponent);
|
||||
}
|
||||
|
||||
@ -8,17 +8,11 @@ class DebugSystem extends BaseSystem {
|
||||
..style = PaintingStyle.stroke;
|
||||
|
||||
final textPainter = TextPaint(
|
||||
config: const TextPaintConfig(
|
||||
color: Colors.green,
|
||||
fontSize: 10,
|
||||
),
|
||||
style: const TextStyle(color: Colors.green, fontSize: 10),
|
||||
);
|
||||
|
||||
final statusPainter = TextPaint(
|
||||
config: const TextPaintConfig(
|
||||
color: Colors.green,
|
||||
fontSize: 16,
|
||||
),
|
||||
style: const TextStyle(color: Colors.green, fontSize: 16),
|
||||
);
|
||||
|
||||
@override
|
||||
|
||||
@ -16,8 +16,8 @@ class KawabungaSystem extends BaseSystem with UpdateSystem {
|
||||
final timer = entity.get<TimerComponent>()!;
|
||||
final textComponent = entity.get<TextComponent>()!;
|
||||
final textRenderer = TextPaint(
|
||||
config: textComponent.config.withColor(
|
||||
textComponent.config.color.withOpacity(1 - timer.percentage),
|
||||
style: textComponent.style.copyWith(
|
||||
color: textComponent.style.color!.withOpacity(1 - timer.percentage),
|
||||
),
|
||||
);
|
||||
|
||||
@ -33,7 +33,7 @@ class KawabungaSystem extends BaseSystem with UpdateSystem {
|
||||
for (final entity in entities) {
|
||||
final textComponent = entity.get<TextComponent>()!;
|
||||
final size = entity.get<SizeComponent>()!.size;
|
||||
final textRenderer = TextPaint(config: textComponent.config);
|
||||
final textRenderer = TextPaint(style: textComponent.style);
|
||||
size.setFrom(textRenderer.measureText(textComponent.text));
|
||||
|
||||
final timer = entity.get<TimerComponent>()!;
|
||||
|
||||
@ -46,7 +46,7 @@ class MoveSystem extends System with UpdateSystem, GameRef<ExampleGame> {
|
||||
..add<TextComponent, TextInit>(
|
||||
TextInit(
|
||||
'Kawabunga',
|
||||
config: const TextPaintConfig(color: Colors.blue, fontSize: 12),
|
||||
style: const TextStyle(color: Colors.blue, fontSize: 12),
|
||||
),
|
||||
)
|
||||
..add<TimerComponent, double>(3);
|
||||
|
||||
@ -1,31 +1,31 @@
|
||||
import 'package:flame/game.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:oxygen/oxygen.dart';
|
||||
|
||||
class TextInit {
|
||||
final String text;
|
||||
|
||||
TextPaintConfig? config;
|
||||
TextStyle? style;
|
||||
|
||||
TextInit(
|
||||
this.text, {
|
||||
this.config,
|
||||
this.style,
|
||||
});
|
||||
}
|
||||
|
||||
class TextComponent extends Component<TextInit> {
|
||||
late String text;
|
||||
|
||||
late TextPaintConfig config;
|
||||
late TextStyle style;
|
||||
|
||||
@override
|
||||
void init([TextInit? initValue]) {
|
||||
config = initValue?.config ?? const TextPaintConfig();
|
||||
style = initValue?.style ?? const TextStyle();
|
||||
text = initValue?.text ?? '';
|
||||
}
|
||||
|
||||
@override
|
||||
void reset() {
|
||||
config = const TextPaintConfig();
|
||||
style = const TextStyle();
|
||||
text = '';
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user