From d77e5efee573ddcbc84a50be7728d7a9207287f7 Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Mon, 17 Jan 2022 00:22:51 +0100 Subject: [PATCH] refactor: Use canvas.drawImageNine in NineTileBox (#1314) `canvas.drawImageNine` is built-in now a lot of logic was removed from NineTileBox. --- examples/assets/images/nine-box.png | Bin 205 -> 460 bytes .../rendering/nine_tile_box_example.dart | 26 ++-- .../widgets/nine_tile_box_example.dart | 4 +- packages/flame/lib/src/nine_tile_box.dart | 71 +++-------- .../flame/lib/src/widgets/nine_tile_box.dart | 114 +++--------------- 5 files changed, 49 insertions(+), 166 deletions(-) diff --git a/examples/assets/images/nine-box.png b/examples/assets/images/nine-box.png index c5194329ed0cb6ca172f649635a0428052739a1b..166101581e3dcbd49db509594688cd804095f710 100644 GIT binary patch literal 460 zcmeAS@N?(olHy`uVBq!ia0vp^P9V&|1|%PcFuVX#jKx9jP7LeL$-D%z+dN$yLn`LH zy>l_J*+HcBA+xh$hw&|jvMFp^CWK7rb7HRKxN!38!Oc5zB2M@m>)Ac$z31^6AOEFw z^2a4e&)VhsYSyl!*XD>a^u)jK_79NPzbyPUx&6xGHRm$Z%xd+>(l$07}g!Wc_^Rhlcmwd*YjuZe{=lZO8X1-SNiXs-+gRe@{XI{3@85|{lQ^g zz4POay8#?QG=W;*|IGjC7rcE%(rjzLceCp+|M}N+UGA>VfwtYzUq4QI%9NAip3C)6 zzA;AZR?@VzxqGvp$Q=+rXLXyGU%zMPyE>-ro5j-7vbPHtR8L%a-|V5)obcy&_8fFM gb=dm*9goM-_j6xuTHq4v42&KIPgg&ebxsLQ08Prn!2kdN literal 205 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjEX7WqAsj$Z!;#Vf} onLoad() async { await super.onLoad(); final sprite = Sprite(await images.load('nine-box.png')); - nineTileBox = NineTileBox(sprite, tileSize: 8, destTileSize: 24); - } - - @override - void render(Canvas canvas) { - super.render(canvas); - final position = (size - boxSize) / 2; - nineTileBox.draw(canvas, position, boxSize); + final boxSize = Vector2.all(300); + final nineTileBox = NineTileBox(sprite, destTileSize: 148); + add( + nineTileBoxComponent = NineTileBoxComponent( + nineTileBox: nineTileBox, + position: size / 2, + size: boxSize, + anchor: Anchor.center, + ), + ); } @override void onTap() { - boxSize.scale(1.2); + nineTileBoxComponent.scale.scale(1.2); } @override void onDoubleTap() { - boxSize.scale(0.8); + nineTileBoxComponent.scale.scale(0.8); } } diff --git a/examples/lib/stories/widgets/nine_tile_box_example.dart b/examples/lib/stories/widgets/nine_tile_box_example.dart index db06528f1..bc11e29bb 100644 --- a/examples/lib/stories/widgets/nine_tile_box_example.dart +++ b/examples/lib/stories/widgets/nine_tile_box_example.dart @@ -6,9 +6,9 @@ Widget nineTileBoxBuilder(DashbookContext ctx) { return Container( width: ctx.numberProperty('width', 200), height: ctx.numberProperty('height', 200), - child: NineTileBox.asset( + child: NineTileBoxWidget.asset( path: 'nine-box.png', - tileSize: 8, + tileSize: 22, destTileSize: 50, child: const Center( child: Text( diff --git a/packages/flame/lib/src/nine_tile_box.dart b/packages/flame/lib/src/nine_tile_box.dart index e17402032..6992e74a8 100644 --- a/packages/flame/lib/src/nine_tile_box.dart +++ b/packages/flame/lib/src/nine_tile_box.dart @@ -15,19 +15,22 @@ class NineTileBox { static final _whitePaint = BasicPalette.white.paint(); /// The sprite used to render the box, must be a 3x3 grid of square tiles. - Sprite sprite; + final Sprite sprite; /// The size of each tile in the source sprite image. - int tileSize; + final int tileSize; /// The size each tile becomes when rendered /// (optionally used to scale the src image). late int destTileSize; + late final Rect _center; + late final Rect _dst; + /// Creates a nine-box instance. /// /// [sprite] is the 3x3 grid and [tileSize] is the size of each tile. - /// The src sprite must a square of size 3*[tileSize]. + /// The src sprite must be a square of size 3*[tileSize]. /// /// If [tileSize] is not provided, the width of the sprite is assumed as the /// size. Otherwise the width and height properties of the sprite are ignored. @@ -35,61 +38,25 @@ class NineTileBox { /// If [destTileSize] is not provided, the evaluated [tileSize] is used /// instead (so no scaling happens). NineTileBox(this.sprite, {int? tileSize, int? destTileSize}) - : tileSize = tileSize ?? sprite.src.width.toInt() { + : tileSize = tileSize ?? sprite.src.width ~/ 3 { this.destTileSize = destTileSize ?? this.tileSize; + final centerEdge = this.tileSize.toDouble(); + _center = Rect.fromLTWH(centerEdge, centerEdge, centerEdge, centerEdge); + _dst = Rect.fromLTWH(0, 0, this.destTileSize * 3, this.destTileSize * 3); } - /// Renders this nine box with the dimensions provided by [rect]. - void drawRect(Canvas c, Rect rect) { - final position = Vector2(rect.left, rect.top); - final size = Vector2(rect.width, rect.height); - draw(c, position, size); + /// Renders this nine box with the dimensions provided by [dst]. + void drawRect(Canvas c, [Rect? dst]) { + c.drawImageNine(sprite.image, _center, dst ?? _dst, _whitePaint); } /// Renders this nine box as a rectangle at [position] with size [size]. void draw(Canvas c, Vector2 position, Vector2 size) { - // corners - _drawTile(c, _getDest(position), 0, 0); - final bottomLeft = position + Vector2(0, size.y - destTileSize); - _drawTile(c, _getDest(bottomLeft), 0, 2); - final topRight = position + Vector2(size.x - destTileSize, 0); - _drawTile(c, _getDest(topRight), 2, 0); - final bottomRight = Vector2(topRight.x, bottomLeft.y); - _drawTile(c, _getDest(bottomRight), 2, 2); - - // horizontal sides - final mx = size.x - 2 * destTileSize; - final middleLeft = position + Vector2Extension.fromInts(destTileSize, 0); - _drawTile(c, _getDest(middleLeft, width: mx), 1, 0); - final middleRight = middleLeft + Vector2(0, size.y - destTileSize); - _drawTile(c, _getDest(middleRight, width: mx), 1, 2); - - // vertical sides - final my = size.y - 2 * destTileSize; - final topCenter = position + Vector2Extension.fromInts(0, destTileSize); - _drawTile(c, _getDest(topCenter, height: my), 0, 1); - final bottomCenter = topCenter + Vector2(size.x - destTileSize, 0); - _drawTile(c, _getDest(bottomCenter, height: my), 2, 1); - - // center - final center = position + Vector2.all(destTileSize.toDouble()); - _drawTile(c, _getDest(center, width: mx, height: my), 1, 1); - } - - Rect _getDest(Vector2 position, {double? width, double? height}) { - final w = width ?? _destTileSizeDouble; - final h = height ?? _destTileSizeDouble; - return Rect.fromLTWH(position.x, position.y, w, h); - } - - double get _tileSizeDouble => tileSize.toDouble(); - - double get _destTileSizeDouble => destTileSize.toDouble(); - - void _drawTile(Canvas c, Rect dest, int i, int j) { - final xSrc = sprite.src.left + _tileSizeDouble * i; - final ySrc = sprite.src.top + _tileSizeDouble * j; - final src = Rect.fromLTWH(xSrc, ySrc, _tileSizeDouble, _tileSizeDouble); - c.drawImageRect(sprite.image, src, dest, _whitePaint); + c.drawImageNine( + sprite.image, + _center, + Rect.fromLTWH(position.x, position.y, size.x, size.y), + _whitePaint, + ); } } diff --git a/packages/flame/lib/src/widgets/nine_tile_box.dart b/packages/flame/lib/src/widgets/nine_tile_box.dart index e21082dcc..d0701e55c 100644 --- a/packages/flame/lib/src/widgets/nine_tile_box.dart +++ b/packages/flame/lib/src/widgets/nine_tile_box.dart @@ -1,10 +1,11 @@ import 'dart:ui' as ui; +import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import '../../assets.dart'; import '../../flame.dart'; -import '../extensions/vector2.dart'; +import '../nine_tile_box.dart' as non_widget; import '../sprite.dart'; import 'base_future_builder.dart'; @@ -15,117 +16,32 @@ class _Painter extends CustomPainter { final ui.Image image; final double tileSize; final double destTileSize; + late final non_widget.NineTileBox _nineTileBox; _Painter({ required this.image, required this.tileSize, required this.destTileSize, - }); - - Sprite _getSpriteTile(double x, double y) => - Sprite(image, srcPosition: Vector2(x, y), srcSize: Vector2.all(tileSize)); + }) : _nineTileBox = non_widget.NineTileBox( + Sprite(image), + tileSize: tileSize.toInt(), + destTileSize: destTileSize.toInt(), + ); @override void paint(Canvas canvas, Size size) { - final topLeftCorner = _getSpriteTile(0, 0); - final topRightCorner = _getSpriteTile(tileSize * 2, 0); - - final bottomLeftCorner = _getSpriteTile(0, 2 * tileSize); - final bottomRightCorner = _getSpriteTile(tileSize * 2, 2 * tileSize); - - final topSide = _getSpriteTile(tileSize, 0); - final bottomSide = _getSpriteTile(tileSize, tileSize * 2); - - final leftSide = _getSpriteTile(0, tileSize); - final rightSide = _getSpriteTile(tileSize * 2, tileSize); - - final middle = _getSpriteTile(tileSize, tileSize); - - final horizontalWidget = size.width - destTileSize * 2; - final verticalHeight = size.height - destTileSize * 2; - - void render(Sprite sprite, double x, double y, double w, double h) { - sprite.render(canvas, position: Vector2(x, y), size: Vector2(w, h)); - } - - // Middle - render( - middle, - destTileSize, - destTileSize, - horizontalWidget, - verticalHeight, - ); - - // Top and bottom side - render( - topSide, - destTileSize, - 0, - horizontalWidget, - destTileSize, - ); - render( - bottomSide, - destTileSize, - size.height - destTileSize, - horizontalWidget, - destTileSize, - ); - - // Left and right side - render( - leftSide, - 0, - destTileSize, - destTileSize, - verticalHeight, - ); - render( - rightSide, - size.width - destTileSize, - destTileSize, - destTileSize, - verticalHeight, - ); - - // Corners - render( - topLeftCorner, - 0, - 0, - destTileSize, - destTileSize, - ); - render( - topRightCorner, - size.width - destTileSize, - 0, - destTileSize, - destTileSize, - ); - render( - bottomLeftCorner, - 0, - size.height - destTileSize, - destTileSize, - destTileSize, - ); - render( - bottomRightCorner, - size.width - destTileSize, - size.height - destTileSize, - destTileSize, - destTileSize, - ); + _nineTileBox.drawRect(canvas, Offset.zero & size); } @override bool shouldRepaint(_) => false; } +@Deprecated('Renamed to [NineTileBoxWidget]') +typedef NineTileBox = NineTileBoxWidget; + /// A [StatelessWidget] that renders NineTileBox -class NineTileBox extends StatelessWidget { +class NineTileBoxWidget extends StatelessWidget { final Future Function() _imageFuture; /// The size of the tile on the image @@ -144,7 +60,7 @@ class NineTileBox extends StatelessWidget { /// A builder function that is called while the loading is on the way final WidgetBuilder? loadingBuilder; - NineTileBox({ + NineTileBoxWidget({ required ui.Image image, required this.tileSize, required this.destTileSize, @@ -157,7 +73,7 @@ class NineTileBox extends StatelessWidget { }) : _imageFuture = (() => Future.value(image)), super(key: key); - NineTileBox.asset({ + NineTileBoxWidget.asset({ required String path, required this.tileSize, required this.destTileSize,