[flutter] Fixed dress-up example.

This commit is contained in:
Mario Zechner 2022-11-18 03:14:44 +01:00
parent 11add2a56d
commit 410f30d485
4 changed files with 86 additions and 16 deletions

View File

@ -2,8 +2,9 @@ import 'dart:math';
import 'dart:ui' as ui; import 'dart:ui' as ui;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/painting.dart' as painting;
import 'package:spine_flutter/spine_flutter.dart'; import 'package:spine_flutter/spine_flutter.dart';
import 'package:flutter/rendering.dart' as rendering; import 'package:raw_image_provider/raw_image_provider.dart';
class DressUp extends StatefulWidget { class DressUp extends StatefulWidget {
const DressUp({Key? key}) : super(key: key); const DressUp({Key? key}) : super(key: key);
@ -14,11 +15,15 @@ class DressUp extends StatefulWidget {
class DressUpState extends State<DressUp> { class DressUpState extends State<DressUp> {
static const double thumbnailSize = 200; static const double thumbnailSize = 200;
late SpineWidgetController _controller;
SkeletonDrawable? _drawable; SkeletonDrawable? _drawable;
final List<Image> _skinImages = []; Skin? _customSkin;
final Map<String, RawImageData> _skinImages = {};
final Map<String, bool> _selectedSkins = {};
@override @override
void initState() { void initState() {
reportLeaks();
super.initState(); super.initState();
SkeletonDrawable.fromAsset("assets/mix-and-match-pro.skel", "assets/mix-and-match.atlas").then((drawable) async { SkeletonDrawable.fromAsset("assets/mix-and-match-pro.skel", "assets/mix-and-match.atlas").then((drawable) async {
for (var skin in drawable.skeletonData.getSkins()) { for (var skin in drawable.skeletonData.getSkins()) {
@ -38,19 +43,42 @@ class DressUpState extends State<DressUp> {
..color = ui.Color(bgColor) ..color = ui.Color(bgColor)
..style = PaintingStyle.fill; ..style = PaintingStyle.fill;
canvas.drawRect(const Rect.fromLTWH(0, 0, thumbnailSize, thumbnailSize), paint); canvas.drawRect(const Rect.fromLTWH(0, 0, thumbnailSize, thumbnailSize), paint);
canvas.translate(thumbnailSize / 2, thumbnailSize / 2);
canvas.scale(scale, scale); canvas.scale(scale, scale);
canvas.translate(-bounds.x + bounds.width / 2, -bounds.y); canvas.translate(-(bounds.x + bounds.width / 2), -(bounds.y + bounds.height / 2));
canvas.drawRect(Rect.fromLTRB(-5, -5, 5, -5), paint..color = Colors.red); canvas.drawRect(Rect.fromLTRB(-5, -5, 5, -5), paint..color = Colors.red);
drawable.renderToCanvas(canvas); drawable.renderToCanvas(canvas);
var imageData = await (await recorder.endRecording().toImage(thumbnailSize.toInt(), thumbnailSize.toInt())).toByteData(format: ui.ImageByteFormat.png); var rawImageData = (await (await recorder.endRecording().toImage(thumbnailSize.toInt(), thumbnailSize.toInt())).toByteData(format: ui.ImageByteFormat.rawRgba))!.buffer.asUint8List();
_skinImages.add(Image.memory(imageData!.buffer.asUint8List(), fit: BoxFit.contain)); _skinImages[skin.getName()] = (RawImageData(rawImageData, thumbnailSize.toInt(), thumbnailSize.toInt()));
_selectedSkins[skin.getName()] = false;
} }
_drawable = drawable; _drawable = drawable;
setState(() {}); _controller = SpineWidgetController((controller) {
controller.animationState.setAnimationByName(0, "dance", true);
});
setState(() {
_selectedSkins["full-skins/girl"] = true;
drawable.skeleton.setSkinByName("full-skins/girl");
drawable.skeleton.setToSetupPose();
});
}); });
} }
void _toggleSkin(String skinName) {
_selectedSkins[skinName] = !_selectedSkins[skinName]!;
if (_customSkin != null) _customSkin?.dispose();
_customSkin = Skin("custom-skin");
for (var skinName in _selectedSkins.keys) {
if (_selectedSkins[skinName] == true) {
var skin = _controller.skeletonData.findSkin(skinName);
if (skin != null) _customSkin?.addSkin(skin);
}
}
_controller.skeleton.setSkin(_customSkin!);
_controller.skeleton.setToSetupPose();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
@ -58,16 +86,36 @@ class DressUpState extends State<DressUp> {
body: _skinImages.isEmpty body: _skinImages.isEmpty
? const SizedBox() ? const SizedBox()
: Row( : Row(
children: [ children: [
Expanded( Container(width: thumbnailSize, child:
child:ListView( ListView(
children: _skinImages.map((image) { children: _skinImages.keys.map((skinName) {
return SizedBox(width: 200, height: 200, child: image); var rawImageData = _skinImages[skinName]!;
}).toList() var image = Image(image: RawImageProvider(rawImageData));
) var box = SizedBox(width: 200, height: 200, child: image);
), return GestureDetector(
] onTap: () {
) _toggleSkin(skinName);
setState(() {});
},
child: _selectedSkins[skinName] == true
? box
: ColorFiltered(colorFilter: ColorFilter.mode(Colors.grey, painting.BlendMode.saturation,), child: box)
);
}).toList()
),
),
Expanded(
child: SpineWidget.drawable(_drawable, _controller, boundsProvider: SkinAndAnimationBounds(["full-skins/girl"]),)
)
]
)
); );
} }
@override
void dispose() {
super.dispose();
_drawable?.dispose();
}
} }

View File

@ -76,4 +76,10 @@ class SkinsState extends State<Skins> {
) )
); );
} }
@override
void dispose() {
super.dispose();
_drawable?.dispose();
}
} }

View File

@ -36,6 +36,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.16.0" version: "1.16.0"
crypto:
dependency: transitive
description:
name: crypto
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.2"
cupertino_icons: cupertino_icons:
dependency: "direct main" dependency: "direct main"
description: description:
@ -130,6 +137,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.2" version: "2.1.2"
raw_image_provider:
dependency: "direct main"
description:
name: raw_image_provider
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.0"
sky_engine: sky_engine:
dependency: transitive dependency: transitive
description: flutter description: flutter

View File

@ -42,6 +42,8 @@ dependencies:
# Use with the CupertinoIcons class for iOS style icons. # Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2 cupertino_icons: ^1.0.2
raw_image_provider: ^0.2.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter