[formatters] Dart formatting pass

This commit is contained in:
Mario Zechner 2025-07-16 03:20:14 +02:00
parent 440125252a
commit 81b445302a
15 changed files with 4391 additions and 7260 deletions

View File

@ -36,24 +36,28 @@ class AnimatedLogin extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
reportLeaks(); reportLeaks();
final controller = SpineWidgetController(onInitialized: (controller) { final controller = SpineWidgetController(
controller.skeleton.setSkinByName("nate"); onInitialized: (controller) {
controller.skeleton.setToSetupPose(); controller.skeleton.setSkinByName("nate");
controller.animationState.setAnimationByName(0, "login/look-left-down", true); controller.skeleton.setToSetupPose();
}); controller.animationState.setAnimationByName(0, "login/look-left-down", true);
},
);
return Scaffold( return Scaffold(
appBar: AppBar(title: const Text('Animated login')), appBar: AppBar(title: const Text('Animated login')),
body: Container( body: Container(
margin: const EdgeInsets.all(15.0), margin: const EdgeInsets.all(15.0),
padding: const EdgeInsets.all(3.0), padding: const EdgeInsets.all(3.0),
decoration: BoxDecoration(border: Border.all(color: Colors.blueAccent)), decoration: BoxDecoration(border: Border.all(color: Colors.blueAccent)),
child: SpineWidget.fromAsset( child: SpineWidget.fromAsset(
"assets/chibi/chibi-stickers.atlas", "assets/chibi/chibi-stickers.atlas",
"assets/chibi/chibi-stickers.skel", "assets/chibi/chibi-stickers.skel",
controller, controller,
boundsProvider: SkinAndAnimationBounds(skins: ["nate"], animation: "login/look-left-down"), boundsProvider: SkinAndAnimationBounds(skins: ["nate"], animation: "login/look-left-down"),
sizedByBounds: true, sizedByBounds: true,
))); ),
),
);
} }
} }

View File

@ -8,32 +8,38 @@ class AnimationStateEvents extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
reportLeaks(); reportLeaks();
final controller = SpineWidgetController(onInitialized: (controller) { final controller = SpineWidgetController(
controller.skeleton.setScaleX(0.5); onInitialized: (controller) {
controller.skeleton.setScaleY(0.5); controller.skeleton.setScaleX(0.5);
controller.skeleton.findSlot("gun")?.setColor(Color(1, 0, 0, 1)); controller.skeleton.setScaleY(0.5);
controller.animationStateData.setDefaultMix(0.2); controller.skeleton.findSlot("gun")?.setColor(Color(1, 0, 0, 1));
controller.animationState.setAnimationByName(0, "walk", true).setListener((type, trackEntry, event) { controller.animationStateData.setDefaultMix(0.2);
print("Walk animation event $type"); controller.animationState.setAnimationByName(0, "walk", true).setListener((type, trackEntry, event) {
}); print("Walk animation event $type");
controller.animationState.addAnimationByName(0, "jump", false, 2); });
controller.animationState.addAnimationByName(0, "run", true, 0).setListener((type, trackEntry, event) { controller.animationState.addAnimationByName(0, "jump", false, 2);
print("Run animation event $type"); controller.animationState.addAnimationByName(0, "run", true, 0).setListener((type, trackEntry, event) {
}); print("Run animation event $type");
controller.animationState.setListener((type, trackEntry, event) { });
if (type == EventType.event) { controller.animationState.setListener((type, trackEntry, event) {
print( if (type == EventType.event) {
"User event: { name: ${event?.getData().getName()}, intValue: ${event?.getIntValue()}, floatValue: ${event?.getFloatValue()}, stringValue: ${event?.getStringValue()} }"); print(
} "User event: { name: ${event?.getData().getName()}, intValue: ${event?.getIntValue()}, floatValue: ${event?.getFloatValue()}, stringValue: ${event?.getStringValue()} }",
}); );
print("Current: ${controller.animationState.getCurrent(0)?.getAnimation().getName()}"); }
}); });
print("Current: ${controller.animationState.getCurrent(0)?.getAnimation().getName()}");
},
);
return Scaffold( return Scaffold(
appBar: AppBar(title: const Text('Animation State Listener')), appBar: AppBar(title: const Text('Animation State Listener')),
body: Column(children: [ body: Column(
children: [
const Text("See output in console!"), const Text("See output in console!"),
Expanded(child: SpineWidget.fromAsset("assets/spineboy.atlas", "assets/spineboy-pro.skel", controller)) Expanded(child: SpineWidget.fromAsset("assets/spineboy.atlas", "assets/spineboy-pro.skel", controller)),
])); ],
),
);
} }
} }

View File

@ -38,36 +38,40 @@ class DebugRendering extends StatelessWidget {
reportLeaks(); reportLeaks();
const debugRenderer = DebugRenderer(); const debugRenderer = DebugRenderer();
final controller = SpineWidgetController(onInitialized: (controller) { final controller = SpineWidgetController(
controller.animationState.setAnimationByName(0, "walk", true); onInitialized: (controller) {
}, onBeforePaint: (controller, canvas) { controller.animationState.setAnimationByName(0, "walk", true);
// Save the current transform and other canvas state },
canvas.save(); onBeforePaint: (controller, canvas) {
// Save the current transform and other canvas state
canvas.save();
// Get the current canvas transform an invert it, so we can work in the // Get the current canvas transform an invert it, so we can work in the
// canvas coordinate system. // canvas coordinate system.
final currentMatrix = canvas.getTransform(); final currentMatrix = canvas.getTransform();
final invertedMatrix = Matrix4.tryInvert(Matrix4.fromFloat64List(currentMatrix)); final invertedMatrix = Matrix4.tryInvert(Matrix4.fromFloat64List(currentMatrix));
if (invertedMatrix != null) { if (invertedMatrix != null) {
canvas.transform(invertedMatrix.storage); canvas.transform(invertedMatrix.storage);
} }
// Draw something. // Draw something.
final Paint paint = Paint() final Paint paint = Paint()
..color = Colors.black ..color = Colors.black
..strokeWidth = 2.0; ..strokeWidth = 2.0;
canvas.drawLine( canvas.drawLine(
Offset(0, 0), Offset(0, 0),
Offset(canvas.getLocalClipBounds().width, canvas.getLocalClipBounds().height), Offset(canvas.getLocalClipBounds().width, canvas.getLocalClipBounds().height),
paint, paint,
); );
// Restore the old transform and canvas state // Restore the old transform and canvas state
canvas.restore(); canvas.restore();
}, onAfterPaint: (controller, canvas, commands) { },
debugRenderer.render(controller.drawable, canvas, commands); onAfterPaint: (controller, canvas, commands) {
}); debugRenderer.render(controller.drawable, canvas, commands);
},
);
return Scaffold( return Scaffold(
appBar: AppBar(title: const Text('Debug Renderer')), appBar: AppBar(title: const Text('Debug Renderer')),

View File

@ -84,23 +84,26 @@ class DressUpState extends State<DressUp> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final controller = SpineWidgetController(onInitialized: (controller) { final controller = SpineWidgetController(
controller.animationState.setAnimationByName(0, "dance", true); onInitialized: (controller) {
}); controller.animationState.setAnimationByName(0, "dance", true);
},
);
return Scaffold( return Scaffold(
appBar: AppBar(title: const Text('Dress Up')), appBar: AppBar(title: const Text('Dress Up')),
body: _skinImages.isEmpty body: _skinImages.isEmpty
? const SizedBox() ? const SizedBox()
: Row(children: [ : Row(
children: [
SizedBox( SizedBox(
width: thumbnailSize, width: thumbnailSize,
child: ListView( child: ListView(
children: _skinImages.keys.map((skinName) { children: _skinImages.keys.map((skinName) {
var rawImageData = _skinImages[skinName]!; var rawImageData = _skinImages[skinName]!;
var image = Image(image: RawImageProvider(rawImageData)); var image = Image(image: RawImageProvider(rawImageData));
var box = SizedBox(width: 200, height: 200, child: image); var box = SizedBox(width: 200, height: 200, child: image);
return GestureDetector( return GestureDetector(
onTap: () { onTap: () {
_toggleSkin(skinName); _toggleSkin(skinName);
setState(() {}); setState(() {});
@ -114,16 +117,22 @@ class DressUpState extends State<DressUp> {
color: Colors.grey, color: Colors.grey,
backgroundBlendMode: painting.BlendMode.saturation, backgroundBlendMode: painting.BlendMode.saturation,
), ),
child: box)); child: box,
}).toList()), ),
);
}).toList(),
),
), ),
Expanded( Expanded(
child: SpineWidget.fromDrawable( child: SpineWidget.fromDrawable(
_drawable, _drawable,
controller, controller,
boundsProvider: SkinAndAnimationBounds(skins: ["full-skins/girl"]), boundsProvider: SkinAndAnimationBounds(skins: ["full-skins/girl"]),
)) ),
])); ),
],
),
);
} }
@override @override

View File

@ -50,8 +50,8 @@ class SpineComponent extends PositionComponent {
Anchor super.anchor = Anchor.topLeft, Anchor super.anchor = Anchor.topLeft,
super.children, super.children,
super.priority, super.priority,
}) : _ownsDrawable = ownsDrawable, }) : _ownsDrawable = ownsDrawable,
_boundsProvider = boundsProvider { _boundsProvider = boundsProvider {
_drawable.update(0); _drawable.update(0);
_bounds = _boundsProvider.computeBounds(_drawable); _bounds = _boundsProvider.computeBounds(_drawable);
size = Vector2(_bounds.width, _bounds.height); size = Vector2(_bounds.width, _bounds.height);
@ -69,15 +69,17 @@ class SpineComponent extends PositionComponent {
Iterable<Component>? children, Iterable<Component>? children,
int? priority, int? priority,
}) async { }) async {
return SpineComponent(await SkeletonDrawable.fromAsset(atlasFile, skeletonFile, bundle: bundle), return SpineComponent(
ownsDrawable: true, await SkeletonDrawable.fromAsset(atlasFile, skeletonFile, bundle: bundle),
boundsProvider: boundsProvider, ownsDrawable: true,
position: position, boundsProvider: boundsProvider,
scale: scale, position: position,
angle: angle, scale: scale,
anchor: anchor, angle: angle,
children: children, anchor: anchor,
priority: priority); children: children,
priority: priority,
);
} }
void dispose() { void dispose() {
@ -114,8 +116,13 @@ class SimpleFlameExample extends FlameGame {
// Load the Spineboy atlas and skeleton data from asset files // Load the Spineboy atlas and skeleton data from asset files
// and create a SpineComponent from them, scaled down and // and create a SpineComponent from them, scaled down and
// centered on the screen // centered on the screen
spineboy = await SpineComponent.fromAssets("assets/spineboy.atlas", "assets/spineboy-pro.json", spineboy = await SpineComponent.fromAssets(
scale: Vector2(0.4, 0.4), anchor: Anchor.center, position: Vector2(size.x / 2, size.y / 2)); "assets/spineboy.atlas",
"assets/spineboy-pro.json",
scale: Vector2(0.4, 0.4),
anchor: Anchor.center,
position: Vector2(size.x / 2, size.y / 2),
);
// Set the "walk" animation on track 0 in looping mode // Set the "walk" animation on track 0 in looping mode
spineboy.animationState.setAnimationByName(0, "walk", true); spineboy.animationState.setAnimationByName(0, "walk", true);
@ -205,6 +212,9 @@ class SpineFlameGameWidget extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold(appBar: AppBar(title: const Text('Flame Integration')), body: GameWidget(game: game)); return Scaffold(
appBar: AppBar(title: const Text('Flame Integration')),
body: GameWidget(game: game),
);
} }
} }

View File

@ -45,19 +45,22 @@ class IkFollowingState extends State<IkFollowing> {
void initState() { void initState() {
super.initState(); super.initState();
controller = SpineWidgetController(onInitialized: (controller) { controller = SpineWidgetController(
// Set the walk animation on track 0, let it loop onInitialized: (controller) {
controller.animationState.setAnimationByName(0, "walk", true); // Set the walk animation on track 0, let it loop
controller.animationState.setAnimationByName(1, "aim", true); controller.animationState.setAnimationByName(0, "walk", true);
}, onAfterUpdateWorldTransforms: (controller) { controller.animationState.setAnimationByName(1, "aim", true);
final worldPosition = crossHairPosition; },
if (worldPosition == null) return; onAfterUpdateWorldTransforms: (controller) {
final bone = controller.skeleton.findBone("crosshair")!; final worldPosition = crossHairPosition;
final parent = bone.getParent()!; if (worldPosition == null) return;
final position = parent.worldToLocal(worldPosition.dx, worldPosition.dy); final bone = controller.skeleton.findBone("crosshair")!;
bone.setX(position.x); final parent = bone.getParent()!;
bone.setY(position.y); final position = parent.worldToLocal(worldPosition.dx, worldPosition.dy);
}); bone.setX(position.x);
bone.setY(position.y);
},
);
} }
void _updateBonePosition(Offset position) { void _updateBonePosition(Offset position) {
@ -69,16 +72,17 @@ class IkFollowingState extends State<IkFollowing> {
reportLeaks(); reportLeaks();
return Scaffold( return Scaffold(
appBar: AppBar(title: const Text('IK Following')), appBar: AppBar(title: const Text('IK Following')),
body: GestureDetector( body: GestureDetector(
onPanDown: (drag) => _updateBonePosition(drag.localPosition), onPanDown: (drag) => _updateBonePosition(drag.localPosition),
onPanUpdate: (drag) => _updateBonePosition(drag.localPosition), onPanUpdate: (drag) => _updateBonePosition(drag.localPosition),
child: SpineWidget.fromAsset( child: SpineWidget.fromAsset(
"assets/spineboy.atlas", "assets/spineboy.atlas",
"assets/spineboy-pro.skel", "assets/spineboy-pro.skel",
controller, controller,
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
), ),
)); ),
);
} }
} }

View File

@ -46,130 +46,96 @@ class ExampleSelector extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
const spacer = SizedBox(height: 10); const spacer = SizedBox(height: 10);
return Scaffold( return Scaffold(
appBar: AppBar(title: const Text('Spine Examples')), appBar: AppBar(title: const Text('Spine Examples')),
body: Center( body: Center(
child: Column(mainAxisSize: MainAxisSize.min, children: [ child: Column(
ElevatedButton( mainAxisSize: MainAxisSize.min,
child: const Text('Simple Animation'), children: [
onPressed: () { ElevatedButton(
Navigator.push( child: const Text('Simple Animation'),
context, onPressed: () {
MaterialPageRoute<void>( Navigator.push(context, MaterialPageRoute<void>(builder: (context) => const SimpleAnimation()));
builder: (context) => const SimpleAnimation(), },
), ),
); spacer,
}, ElevatedButton(
), child: const Text('Pause/Play animation'),
spacer, onPressed: () {
ElevatedButton( Navigator.push(context, MaterialPageRoute<void>(builder: (context) => const PlayPauseAnimation()));
child: const Text('Pause/Play animation'), },
onPressed: () { ),
Navigator.push( spacer,
context, ElevatedButton(
MaterialPageRoute<void>( child: const Text('Animation State Listener'),
builder: (context) => const PlayPauseAnimation(), onPressed: () {
), Navigator.push(context, MaterialPageRoute<void>(builder: (context) => const AnimationStateEvents()));
); },
}, ),
), spacer,
spacer, ElevatedButton(
ElevatedButton( child: const Text('Debug Rendering'),
child: const Text('Animation State Listener'), onPressed: () {
onPressed: () { Navigator.push(context, MaterialPageRoute<void>(builder: (context) => const DebugRendering()));
Navigator.push( },
context, ),
MaterialPageRoute<void>( spacer,
builder: (context) => const AnimationStateEvents(), ElevatedButton(
), child: const Text('Dress Up'),
); onPressed: () {
}, Navigator.push(context, MaterialPageRoute<void>(builder: (context) => const DressUp()));
), },
spacer, ),
ElevatedButton( spacer,
child: const Text('Debug Rendering'), ElevatedButton(
onPressed: () { child: const Text('IK Following'),
Navigator.push( onPressed: () {
context, Navigator.push(context, MaterialPageRoute<void>(builder: (context) => const IkFollowing()));
MaterialPageRoute<void>( },
builder: (context) => const DebugRendering(), ),
), spacer,
); ElevatedButton(
}, child: const Text('Physics'),
), onPressed: () {
spacer, Navigator.push(context, MaterialPageRoute<void>(builder: (context) => const PhysicsTest()));
ElevatedButton( },
child: const Text('Dress Up'), ),
onPressed: () { spacer,
Navigator.push( ElevatedButton(
context, child: const Text('Flame: Simple Example'),
MaterialPageRoute<void>( onPressed: () {
builder: (context) => const DressUp(), Navigator.push(
), context,
); MaterialPageRoute<void>(builder: (context) => SpineFlameGameWidget(SimpleFlameExample())),
}, );
), },
spacer, ),
ElevatedButton( spacer,
child: const Text('IK Following'), ElevatedButton(
onPressed: () { child: const Text('Flame: Pre-load and share Spine data'),
Navigator.push( onPressed: () {
context, Navigator.push(
MaterialPageRoute<void>( context,
builder: (context) => const IkFollowing(), MaterialPageRoute<void>(
), builder: (context) => SpineFlameGameWidget(PreloadAndShareSpineDataExample()),
); ),
}, );
), },
spacer, ),
ElevatedButton( spacer,
child: const Text('Physics'), ElevatedButton(
onPressed: () { child: const Text('Flame: Dragon Example'),
Navigator.push( onPressed: () {
context, Navigator.push(
MaterialPageRoute<void>( context,
builder: (context) => const PhysicsTest(), MaterialPageRoute<void>(builder: (context) => SpineFlameGameWidget(DragonExample())),
), );
); },
}, ),
), spacer,
spacer, ],
ElevatedButton( ),
child: const Text('Flame: Simple Example'), ),
onPressed: () { );
Navigator.push(
context,
MaterialPageRoute<void>(
builder: (context) => SpineFlameGameWidget(SimpleFlameExample()),
),
);
},
),
spacer,
ElevatedButton(
child: const Text('Flame: Pre-load and share Spine data'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute<void>(
builder: (context) => SpineFlameGameWidget(PreloadAndShareSpineDataExample()),
),
);
},
),
spacer,
ElevatedButton(
child: const Text('Flame: Dragon Example'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute<void>(
builder: (context) => SpineFlameGameWidget(DragonExample()),
),
);
},
),
spacer,
])));
} }
} }

View File

@ -43,9 +43,11 @@ class PlayPauseAnimationState extends State<PlayPauseAnimation> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
controller = SpineWidgetController(onInitialized: (controller) { controller = SpineWidgetController(
controller.animationState.setAnimationByName(0, "flying", true); onInitialized: (controller) {
}); controller.animationState.setAnimationByName(0, "flying", true);
},
);
} }
void _togglePlay() { void _togglePlay() {

View File

@ -46,26 +46,29 @@ class PhysicsState extends State<PhysicsTest> {
void initState() { void initState() {
super.initState(); super.initState();
controller = SpineWidgetController(onInitialized: (controller) { controller = SpineWidgetController(
controller.animationState.setAnimationByName(0, "eyeblink-long", true); onInitialized: (controller) {
controller.animationState.setAnimationByName(1, "wings-and-feet", true); controller.animationState.setAnimationByName(0, "eyeblink-long", true);
}, onAfterUpdateWorldTransforms: (controller) { controller.animationState.setAnimationByName(1, "wings-and-feet", true);
if (lastMousePosition == null) { },
lastMousePosition = mousePosition; onAfterUpdateWorldTransforms: (controller) {
return; if (lastMousePosition == null) {
} lastMousePosition = mousePosition;
if (mousePosition == null) { return;
return; }
} if (mousePosition == null) {
return;
}
final dx = mousePosition!.dx - lastMousePosition!.dx; final dx = mousePosition!.dx - lastMousePosition!.dx;
final dy = mousePosition!.dy - lastMousePosition!.dy; final dy = mousePosition!.dy - lastMousePosition!.dy;
final position = controller.skeleton.getPosition(); final position = controller.skeleton.getPosition();
position.x += dx; position.x += dx;
position.y += dy; position.y += dy;
controller.skeleton.setPosition(position.x, position.y); controller.skeleton.setPosition(position.x, position.y);
lastMousePosition = mousePosition; lastMousePosition = mousePosition;
}); },
);
} }
void _updateBonePosition(Offset position) { void _updateBonePosition(Offset position) {
@ -77,11 +80,12 @@ class PhysicsState extends State<PhysicsTest> {
reportLeaks(); reportLeaks();
return Scaffold( return Scaffold(
appBar: AppBar(title: const Text('Physics (drag anywhere)')), appBar: AppBar(title: const Text('Physics (drag anywhere)')),
body: GestureDetector( body: GestureDetector(
onPanDown: (drag) => _updateBonePosition(drag.localPosition), onPanDown: (drag) => _updateBonePosition(drag.localPosition),
onPanUpdate: (drag) => _updateBonePosition(drag.localPosition), onPanUpdate: (drag) => _updateBonePosition(drag.localPosition),
child: SpineWidget.fromAsset("assets/celestial-circus.atlas", "assets/celestial-circus-pro.skel", controller), child: SpineWidget.fromAsset("assets/celestial-circus.atlas", "assets/celestial-circus-pro.skel", controller),
)); ),
);
} }
} }

View File

@ -36,17 +36,20 @@ class SimpleAnimation extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
reportLeaks(); reportLeaks();
final controller = SpineWidgetController(onInitialized: (controller) { final controller = SpineWidgetController(
// Set the default mixing time between animations onInitialized: (controller) {
controller.animationState.getData().setDefaultMix(0.2); // Set the default mixing time between animations
// Set the portal animation on track 0 controller.animationState.getData().setDefaultMix(0.2);
controller.animationState.setAnimationByName(0, "portal", true); // Set the portal animation on track 0
// Queue the run animation after the portal animation controller.animationState.setAnimationByName(0, "portal", true);
controller.animationState.addAnimationByName(0, "run", true, 0); // Queue the run animation after the portal animation
}); controller.animationState.addAnimationByName(0, "run", true, 0);
},
);
return Scaffold( return Scaffold(
appBar: AppBar(title: const Text('Simple Animation')), appBar: AppBar(title: const Text('Simple Animation')),
body: SpineWidget.fromAsset("assets/spineboy.atlas", "assets/spineboy-pro.skel", controller)); body: SpineWidget.fromAsset("assets/spineboy.atlas", "assets/spineboy-pro.skel", controller),
);
} }
} }

View File

@ -91,8 +91,9 @@ Future<SpineFlutterFFI> initSpineFlutterFFI(bool useStaticLinkage) async {
registerOpaqueType<spine_skin_entries_wrapper>(); registerOpaqueType<spine_skin_entries_wrapper>();
await js.importLibrary('assets/packages/spine_flutter/lib/assets/libspine_flutter.js'); await js.importLibrary('assets/packages/spine_flutter/lib/assets/libspine_flutter.js');
Uint8List wasmBinaries = Uint8List wasmBinaries = (await rootBundle.load(
(await rootBundle.load('packages/spine_flutter/lib/assets/libspine_flutter.wasm')).buffer.asUint8List(); 'packages/spine_flutter/lib/assets/libspine_flutter.wasm',
)).buffer.asUint8List();
_module = await EmscriptenModule.compile(wasmBinaries, 'libspine_flutter'); _module = await EmscriptenModule.compile(wasmBinaries, 'libspine_flutter');
} }
Module? m = _module; Module? m = _module;

View File

@ -32,12 +32,7 @@ class RawImageProvider extends ImageProvider<_RawImageKey> {
final double? scale; final double? scale;
final int? targetWidth; final int? targetWidth;
final int? targetHeight; final int? targetHeight;
RawImageProvider( RawImageProvider(this.image, {this.scale = 1.0, this.targetWidth, this.targetHeight});
this.image, {
this.scale = 1.0,
this.targetWidth,
this.targetHeight,
});
@override @override
ImageStreamCompleter loadImage(_RawImageKey key, ImageDecoderCallback decode) { ImageStreamCompleter loadImage(_RawImageKey key, ImageDecoderCallback decode) {
@ -104,12 +99,7 @@ class RawImageData {
final int height; final int height;
final ui.PixelFormat pixelFormat; final ui.PixelFormat pixelFormat;
RawImageData( RawImageData(this.pixels, this.width, this.height, {this.pixelFormat = ui.PixelFormat.rgba8888});
this.pixels,
this.width,
this.height, {
this.pixelFormat = ui.PixelFormat.rgba8888,
});
_RawImageKey? _key; _RawImageKey? _key;
_RawImageKey _obtainKey() { _RawImageKey _obtainKey() {

View File

@ -136,8 +136,13 @@ class Atlas {
Map<BlendMode, Paint> paints = {}; Map<BlendMode, Paint> paints = {};
for (final blendMode in BlendMode.values) { for (final blendMode in BlendMode.values) {
paints[blendMode] = Paint() paints[blendMode] = Paint()
..shader = ImageShader(image, TileMode.clamp, TileMode.clamp, Matrix4.identity().storage, ..shader = ImageShader(
filterQuality: Atlas.filterQuality) image,
TileMode.clamp,
TileMode.clamp,
Matrix4.identity().storage,
filterQuality: Atlas.filterQuality,
)
..isAntiAlias = true ..isAntiAlias = true
..blendMode = blendMode.canvasBlendMode; ..blendMode = blendMode.canvasBlendMode;
} }
@ -745,8 +750,12 @@ class BoneData {
/// rendered at runtime. /// rendered at runtime.
Color getColor() { Color getColor() {
final color = _bindings.spine_bone_data_get_color(_data); final color = _bindings.spine_bone_data_get_color(_data);
return Color(_bindings.spine_color_get_r(color), _bindings.spine_color_get_g(color), return Color(
_bindings.spine_color_get_b(color), _bindings.spine_color_get_a(color)); _bindings.spine_color_get_r(color),
_bindings.spine_color_get_g(color),
_bindings.spine_color_get_b(color),
_bindings.spine_color_get_a(color),
);
} }
void setColor(double r, double g, double b, double a) { void setColor(double r, double g, double b, double a) {
@ -796,7 +805,14 @@ class Bone {
/// See [World transform](http://esotericsoftware.com/spine-runtime-skeletons#World-transforms) in the Spine /// See [World transform](http://esotericsoftware.com/spine-runtime-skeletons#World-transforms) in the Spine
/// Runtimes Guide. /// Runtimes Guide.
void updateWorldTransformWith( void updateWorldTransformWith(
double x, double y, double rotation, double scaleX, double scaleY, double shearX, double shearY) { double x,
double y,
double rotation,
double scaleX,
double scaleY,
double shearX,
double shearY,
) {
_bindings.spine_bone_update_world_transform_with(_bone, x, y, rotation, scaleX, scaleY, shearX, shearY); _bindings.spine_bone_update_world_transform_with(_bone, x, y, rotation, scaleX, scaleY, shearX, shearY);
} }
@ -1122,8 +1138,12 @@ class SlotData {
/// color tinting. /// color tinting.
Color getColor() { Color getColor() {
final color = _bindings.spine_slot_data_get_color(_data); final color = _bindings.spine_slot_data_get_color(_data);
return Color(_bindings.spine_color_get_r(color), _bindings.spine_color_get_g(color), return Color(
_bindings.spine_color_get_b(color), _bindings.spine_color_get_a(color)); _bindings.spine_color_get_r(color),
_bindings.spine_color_get_g(color),
_bindings.spine_color_get_b(color),
_bindings.spine_color_get_a(color),
);
} }
void setColor(double r, double g, double b, double a) { void setColor(double r, double g, double b, double a) {
@ -1134,8 +1154,12 @@ class SlotData {
/// color's alpha is not used. /// color's alpha is not used.
Color getDarkColor() { Color getDarkColor() {
final color = _bindings.spine_slot_data_get_dark_color(_data); final color = _bindings.spine_slot_data_get_dark_color(_data);
return Color(_bindings.spine_color_get_r(color), _bindings.spine_color_get_g(color), return Color(
_bindings.spine_color_get_b(color), _bindings.spine_color_get_a(color)); _bindings.spine_color_get_r(color),
_bindings.spine_color_get_g(color),
_bindings.spine_color_get_b(color),
_bindings.spine_color_get_a(color),
);
} }
void setDarkColor(double r, double g, double b, double a) { void setDarkColor(double r, double g, double b, double a) {
@ -1210,8 +1234,12 @@ class Slot {
/// color tinting. /// color tinting.
Color getColor() { Color getColor() {
final color = _bindings.spine_slot_get_color(_slot); final color = _bindings.spine_slot_get_color(_slot);
return Color(_bindings.spine_color_get_r(color), _bindings.spine_color_get_g(color), return Color(
_bindings.spine_color_get_b(color), _bindings.spine_color_get_a(color)); _bindings.spine_color_get_r(color),
_bindings.spine_color_get_g(color),
_bindings.spine_color_get_b(color),
_bindings.spine_color_get_a(color),
);
} }
void setColor(Color color) { void setColor(Color color) {
@ -1222,8 +1250,12 @@ class Slot {
/// color's alpha is not used. /// color's alpha is not used.
Color getDarkColor() { Color getDarkColor() {
final color = _bindings.spine_slot_get_dark_color(_slot); final color = _bindings.spine_slot_get_dark_color(_slot);
return Color(_bindings.spine_color_get_r(color), _bindings.spine_color_get_g(color), return Color(
_bindings.spine_color_get_b(color), _bindings.spine_color_get_a(color)); _bindings.spine_color_get_r(color),
_bindings.spine_color_get_g(color),
_bindings.spine_color_get_b(color),
_bindings.spine_color_get_a(color),
);
} }
void setDarkColor(Color color) { void setDarkColor(Color color) {
@ -1573,8 +1605,12 @@ class RegionAttachment extends Attachment<spine_region_attachment> {
Color getColor() { Color getColor() {
final color = _bindings.spine_region_attachment_get_color(_attachment); final color = _bindings.spine_region_attachment_get_color(_attachment);
return Color(_bindings.spine_color_get_r(color), _bindings.spine_color_get_g(color), return Color(
_bindings.spine_color_get_b(color), _bindings.spine_color_get_a(color)); _bindings.spine_color_get_r(color),
_bindings.spine_color_get_g(color),
_bindings.spine_color_get_b(color),
_bindings.spine_color_get_a(color),
);
} }
void setColor(double r, double g, double b, double a) { void setColor(double r, double g, double b, double a) {
@ -1661,7 +1697,9 @@ class VertexAttachment<T extends Pointer> extends Attachment<T> {
void setTimelineAttachment(Attachment? attachment) { void setTimelineAttachment(Attachment? attachment) {
_bindings.spine_vertex_attachment_set_timeline_attachment( _bindings.spine_vertex_attachment_set_timeline_attachment(
_attachment.cast(), attachment == null ? nullptr : attachment._attachment.cast()); _attachment.cast(),
attachment == null ? nullptr : attachment._attachment.cast(),
);
} }
} }
@ -1712,8 +1750,12 @@ class MeshAttachment extends VertexAttachment<spine_mesh_attachment> {
Color getColor() { Color getColor() {
final color = _bindings.spine_mesh_attachment_get_color(_attachment); final color = _bindings.spine_mesh_attachment_get_color(_attachment);
return Color(_bindings.spine_color_get_r(color), _bindings.spine_color_get_g(color), return Color(
_bindings.spine_color_get_b(color), _bindings.spine_color_get_a(color)); _bindings.spine_color_get_r(color),
_bindings.spine_color_get_g(color),
_bindings.spine_color_get_b(color),
_bindings.spine_color_get_a(color),
);
} }
void setColor(double r, double g, double b, double a) { void setColor(double r, double g, double b, double a) {
@ -1797,8 +1839,12 @@ class ClippingAttachment extends VertexAttachment<spine_clipping_attachment> {
/// attachments are not usually rendered at runtime. /// attachments are not usually rendered at runtime.
Color getColor() { Color getColor() {
final color = _bindings.spine_clipping_attachment_get_color(_attachment); final color = _bindings.spine_clipping_attachment_get_color(_attachment);
return Color(_bindings.spine_color_get_r(color), _bindings.spine_color_get_g(color), return Color(
_bindings.spine_color_get_b(color), _bindings.spine_color_get_a(color)); _bindings.spine_color_get_r(color),
_bindings.spine_color_get_g(color),
_bindings.spine_color_get_b(color),
_bindings.spine_color_get_a(color),
);
} }
void setColor(double r, double g, double b, double a) { void setColor(double r, double g, double b, double a) {
@ -1818,8 +1864,12 @@ class BoundingBoxAttachment extends VertexAttachment<spine_bounding_box_attachme
/// are not usually rendered at runtime. /// are not usually rendered at runtime.
Color getColor() { Color getColor() {
final color = _bindings.spine_bounding_box_attachment_get_color(_attachment); final color = _bindings.spine_bounding_box_attachment_get_color(_attachment);
return Color(_bindings.spine_color_get_r(color), _bindings.spine_color_get_g(color), return Color(
_bindings.spine_color_get_b(color), _bindings.spine_color_get_a(color)); _bindings.spine_color_get_r(color),
_bindings.spine_color_get_g(color),
_bindings.spine_color_get_b(color),
_bindings.spine_color_get_a(color),
);
} }
void setColor(double r, double g, double b, double a) { void setColor(double r, double g, double b, double a) {
@ -1863,8 +1913,12 @@ class PathAttachment extends VertexAttachment<spine_path_attachment> {
/// rendered at runtime. /// rendered at runtime.
Color getColor() { Color getColor() {
final color = _bindings.spine_path_attachment_get_color(_attachment); final color = _bindings.spine_path_attachment_get_color(_attachment);
return Color(_bindings.spine_color_get_r(color), _bindings.spine_color_get_g(color), return Color(
_bindings.spine_color_get_b(color), _bindings.spine_color_get_a(color)); _bindings.spine_color_get_r(color),
_bindings.spine_color_get_g(color),
_bindings.spine_color_get_b(color),
_bindings.spine_color_get_a(color),
);
} }
void setColor(double r, double g, double b, double a) { void setColor(double r, double g, double b, double a) {
@ -1918,8 +1972,12 @@ class PointAttachment extends Attachment<spine_point_attachment> {
/// attachments are not usually rendered at runtime. /// attachments are not usually rendered at runtime.
Color getColor() { Color getColor() {
final color = _bindings.spine_point_attachment_get_color(_attachment); final color = _bindings.spine_point_attachment_get_color(_attachment);
return Color(_bindings.spine_color_get_r(color), _bindings.spine_color_get_g(color), return Color(
_bindings.spine_color_get_b(color), _bindings.spine_color_get_a(color)); _bindings.spine_color_get_r(color),
_bindings.spine_color_get_g(color),
_bindings.spine_color_get_b(color),
_bindings.spine_color_get_a(color),
);
} }
void setColor(double r, double g, double b, double a) { void setColor(double r, double g, double b, double a) {
@ -1968,7 +2026,11 @@ class Skin {
void setAttachment(int slotIndex, String name, Attachment? attachment) { void setAttachment(int slotIndex, String name, Attachment? attachment) {
final nativeName = name.toNativeUtf8(allocator: _allocator); final nativeName = name.toNativeUtf8(allocator: _allocator);
_bindings.spine_skin_set_attachment( _bindings.spine_skin_set_attachment(
_skin, slotIndex, nativeName.cast(), attachment == null ? nullptr : attachment._attachment.cast()); _skin,
slotIndex,
nativeName.cast(),
attachment == null ? nullptr : attachment._attachment.cast(),
);
_allocator.free(nativeName); _allocator.free(nativeName);
} }
@ -2007,12 +2069,15 @@ class Skin {
for (int i = 0; i < numEntries; i++) { for (int i = 0; i < numEntries; i++) {
final entry = _bindings.spine_skin_entries_get_entry(entries, i); final entry = _bindings.spine_skin_entries_get_entry(entries, i);
Pointer<Utf8> name = _bindings.spine_skin_entry_get_name(entry).cast(); Pointer<Utf8> name = _bindings.spine_skin_entry_get_name(entry).cast();
result.add(SkinEntry( result.add(
SkinEntry(
_bindings.spine_skin_entry_get_slot_index(entry), _bindings.spine_skin_entry_get_slot_index(entry),
name.toDartString(), name.toDartString(),
_bindings.spine_skin_entry_get_attachment(entry).address == nullptr.address _bindings.spine_skin_entry_get_attachment(entry).address == nullptr.address
? null ? null
: Attachment._toSubclass(_bindings.spine_skin_entry_get_attachment(entry)))); : Attachment._toSubclass(_bindings.spine_skin_entry_get_attachment(entry)),
),
);
} }
return result; return result;
} }
@ -2836,8 +2901,11 @@ class Skeleton {
Attachment? getAttachmentByName(String slotName, String attachmentName) { Attachment? getAttachmentByName(String slotName, String attachmentName) {
final slotNameNative = slotName.toNativeUtf8(allocator: _allocator); final slotNameNative = slotName.toNativeUtf8(allocator: _allocator);
final attachmentNameNative = attachmentName.toNativeUtf8(allocator: _allocator); final attachmentNameNative = attachmentName.toNativeUtf8(allocator: _allocator);
final attachment = final attachment = _bindings.spine_skeleton_get_attachment_by_name(
_bindings.spine_skeleton_get_attachment_by_name(_skeleton, slotNameNative.cast(), attachmentNameNative.cast()); _skeleton,
slotNameNative.cast(),
attachmentNameNative.cast(),
);
_allocator.free(slotNameNative); _allocator.free(slotNameNative);
_allocator.free(attachmentNameNative); _allocator.free(attachmentNameNative);
if (attachment.address == nullptr.address) return null; if (attachment.address == nullptr.address) return null;
@ -2899,8 +2967,12 @@ class Skeleton {
/// Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose. /// Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose.
Bounds getBounds() { Bounds getBounds() {
final nativeBounds = _bindings.spine_skeleton_get_bounds(_skeleton); final nativeBounds = _bindings.spine_skeleton_get_bounds(_skeleton);
final bounds = Bounds(_bindings.spine_bounds_get_x(nativeBounds), _bindings.spine_bounds_get_y(nativeBounds), final bounds = Bounds(
_bindings.spine_bounds_get_width(nativeBounds), _bindings.spine_bounds_get_height(nativeBounds)); _bindings.spine_bounds_get_x(nativeBounds),
_bindings.spine_bounds_get_y(nativeBounds),
_bindings.spine_bounds_get_width(nativeBounds),
_bindings.spine_bounds_get_height(nativeBounds),
);
return bounds; return bounds;
} }
@ -2994,8 +3066,12 @@ class Skeleton {
/// The color to tint all the skeleton's attachments. /// The color to tint all the skeleton's attachments.
Color getColor() { Color getColor() {
final color = _bindings.spine_skeleton_get_color(_skeleton); final color = _bindings.spine_skeleton_get_color(_skeleton);
return Color(_bindings.spine_color_get_r(color), _bindings.spine_color_get_g(color), return Color(
_bindings.spine_color_get_b(color), _bindings.spine_color_get_a(color)); _bindings.spine_color_get_r(color),
_bindings.spine_color_get_g(color),
_bindings.spine_color_get_b(color),
_bindings.spine_color_get_a(color),
);
} }
void setColor(Color color) { void setColor(Color color) {
@ -3509,7 +3585,7 @@ enum EventType {
/// ///
/// Because this event is triggered at the end of [AnimationState.apply], any animations set in response to /// Because this event is triggered at the end of [AnimationState.apply], any animations set in response to
/// the event won't be applied until the next time the [AnimationState] is applied. /// the event won't be applied until the next time the [AnimationState] is applied.
event event,
} }
/// Stores the setup pose values for an [Event]. /// Stores the setup pose values for an [Event].
@ -3802,8 +3878,12 @@ class AnimationState {
/// See [setAnimation]. /// See [setAnimation].
TrackEntry setAnimationByName(int trackIndex, String animationName, bool loop) { TrackEntry setAnimationByName(int trackIndex, String animationName, bool loop) {
final animation = animationName.toNativeUtf8(allocator: _allocator); final animation = animationName.toNativeUtf8(allocator: _allocator);
final entry = final entry = _bindings.spine_animation_state_set_animation_by_name(
_bindings.spine_animation_state_set_animation_by_name(_state, trackIndex, animation.cast(), loop ? -1 : 0); _state,
trackIndex,
animation.cast(),
loop ? -1 : 0,
);
_allocator.free(animation); _allocator.free(animation);
if (entry.address == nullptr.address) throw Exception("Couldn't set animation $animationName"); if (entry.address == nullptr.address) throw Exception("Couldn't set animation $animationName");
return TrackEntry._(entry, this); return TrackEntry._(entry, this);
@ -3818,8 +3898,12 @@ class AnimationState {
/// Returns a track entry to allow further customization of animation playback. References to the track entry must not be kept /// Returns a track entry to allow further customization of animation playback. References to the track entry must not be kept
/// after the [EventType.dispose] event occurs. /// after the [EventType.dispose] event occurs.
TrackEntry setAnimation(int trackIndex, Animation animation, bool loop) { TrackEntry setAnimation(int trackIndex, Animation animation, bool loop) {
final entry = final entry = _bindings.spine_animation_state_set_animation(
_bindings.spine_animation_state_set_animation(_state, trackIndex, animation._animation, loop ? -1 : 0); _state,
trackIndex,
animation._animation,
loop ? -1 : 0,
);
if (entry.address == nullptr.address) throw Exception("Couldn't set animation ${animation.getName()}"); if (entry.address == nullptr.address) throw Exception("Couldn't set animation ${animation.getName()}");
return TrackEntry._(entry, this); return TrackEntry._(entry, this);
} }
@ -3830,7 +3914,12 @@ class AnimationState {
TrackEntry addAnimationByName(int trackIndex, String animationName, bool loop, double delay) { TrackEntry addAnimationByName(int trackIndex, String animationName, bool loop, double delay) {
final animation = animationName.toNativeUtf8(allocator: _allocator); final animation = animationName.toNativeUtf8(allocator: _allocator);
final entry = _bindings.spine_animation_state_add_animation_by_name( final entry = _bindings.spine_animation_state_add_animation_by_name(
_state, trackIndex, animation.cast(), loop ? -1 : 0, delay); _state,
trackIndex,
animation.cast(),
loop ? -1 : 0,
delay,
);
_allocator.free(animation); _allocator.free(animation);
if (entry.address == nullptr.address) throw Exception("Couldn't add animation $animationName"); if (entry.address == nullptr.address) throw Exception("Couldn't add animation $animationName");
return TrackEntry._(entry, this); return TrackEntry._(entry, this);
@ -3847,8 +3936,13 @@ class AnimationState {
/// Returns a track entry to allow further customization of animation playback. References to the track entry must not be kept /// Returns a track entry to allow further customization of animation playback. References to the track entry must not be kept
/// after the [EventType.dispose] event occurs. /// after the [EventType.dispose] event occurs.
TrackEntry addAnimation(int trackIndex, Animation animation, bool loop, double delay) { TrackEntry addAnimation(int trackIndex, Animation animation, bool loop, double delay) {
final entry = final entry = _bindings.spine_animation_state_add_animation(
_bindings.spine_animation_state_add_animation(_state, trackIndex, animation._animation, loop ? -1 : 0, delay); _state,
trackIndex,
animation._animation,
loop ? -1 : 0,
delay,
);
if (entry.address == nullptr.address) throw Exception("Couldn't add animation ${animation.getName()}"); if (entry.address == nullptr.address) throw Exception("Couldn't add animation ${animation.getName()}");
return TrackEntry._(entry, this); return TrackEntry._(entry, this);
} }
@ -3971,8 +4065,10 @@ class SkeletonDrawable {
_drawable = _bindings.spine_skeleton_drawable_create(skeletonData._data); _drawable = _bindings.spine_skeleton_drawable_create(skeletonData._data);
skeleton = Skeleton._(_bindings.spine_skeleton_drawable_get_skeleton(_drawable)); skeleton = Skeleton._(_bindings.spine_skeleton_drawable_get_skeleton(_drawable));
animationStateData = AnimationStateData._(_bindings.spine_skeleton_drawable_get_animation_state_data(_drawable)); animationStateData = AnimationStateData._(_bindings.spine_skeleton_drawable_get_animation_state_data(_drawable));
animationState = AnimationState._(_bindings.spine_skeleton_drawable_get_animation_state(_drawable), animationState = AnimationState._(
_bindings.spine_skeleton_drawable_get_animation_state_events(_drawable)); _bindings.spine_skeleton_drawable_get_animation_state(_drawable),
_bindings.spine_skeleton_drawable_get_animation_state_events(_drawable),
);
skeleton.updateWorldTransform(Physics.none); skeleton.updateWorldTransform(Physics.none);
} }
@ -4036,7 +4132,10 @@ class SkeletonDrawable {
var commands = render(); var commands = render();
for (final cmd in commands) { for (final cmd in commands) {
canvas.drawVertices( canvas.drawVertices(
cmd.vertices, rendering.BlendMode.modulate, atlas.atlasPagePaints[cmd.atlasPageIndex][cmd.blendMode]!); cmd.vertices,
rendering.BlendMode.modulate,
atlas.atlasPagePaints[cmd.atlasPageIndex][cmd.blendMode]!,
);
} }
return commands; return commands;
} }
@ -4076,10 +4175,10 @@ class SkeletonDrawable {
/// Scales and centers the skeleton to fit the within the bounds of [width] and [height]. /// Scales and centers the skeleton to fit the within the bounds of [width] and [height].
Future<RawImageData> renderToRawImageData(double width, double height, int bgColor) async { Future<RawImageData> renderToRawImageData(double width, double height, int bgColor) async {
final recorder = renderToPictureRecorder(width, height, bgColor); final recorder = renderToPictureRecorder(width, height, bgColor);
var rawImageData = (await (await recorder.endRecording().toImage(width.toInt(), height.toInt())) var rawImageData = (await (await recorder.endRecording().toImage(
.toByteData(format: ImageByteFormat.rawRgba))! width.toInt(),
.buffer height.toInt(),
.asUint8List(); )).toByteData(format: ImageByteFormat.rawRgba))!.buffer.asUint8List();
return RawImageData(rawImageData, width.toInt(), height.toInt()); return RawImageData(rawImageData, width.toInt(), height.toInt());
} }
@ -4141,8 +4240,13 @@ class RenderCommand {
if (colors.isNotEmpty && colors[0] == -1) { if (colors.isNotEmpty && colors[0] == -1) {
vertices = Vertices.raw(VertexMode.triangles, positions, textureCoordinates: uvs, indices: indices); vertices = Vertices.raw(VertexMode.triangles, positions, textureCoordinates: uvs, indices: indices);
} else { } else {
vertices = vertices = Vertices.raw(
Vertices.raw(VertexMode.triangles, positions, textureCoordinates: uvs, colors: colors, indices: indices); VertexMode.triangles,
positions,
textureCoordinates: uvs,
colors: colors,
indices: indices,
);
} }
} else { } else {
// On the web, rendering is done through CanvasKit, which requires copies of the native data. // On the web, rendering is done through CanvasKit, which requires copies of the native data.
@ -4150,8 +4254,13 @@ class RenderCommand {
final uvsCopy = Float32List.fromList(uvs); final uvsCopy = Float32List.fromList(uvs);
final colorsCopy = Int32List.fromList(colors); final colorsCopy = Int32List.fromList(colors);
final indicesCopy = Uint16List.fromList(indices); final indicesCopy = Uint16List.fromList(indices);
vertices = Vertices.raw(VertexMode.triangles, positionsCopy, vertices = Vertices.raw(
textureCoordinates: uvsCopy, colors: colorsCopy, indices: indicesCopy); VertexMode.triangles,
positionsCopy,
textureCoordinates: uvsCopy,
colors: colorsCopy,
indices: indicesCopy,
);
} }
} }
} }
@ -4167,7 +4276,9 @@ class DebugRenderer {
..style = PaintingStyle.fill; ..style = PaintingStyle.fill;
for (final bone in drawable.skeleton.getBones()) { for (final bone in drawable.skeleton.getBones()) {
canvas.drawRect( canvas.drawRect(
Rect.fromCenter(center: Offset(bone.getWorldX(), bone.getWorldY()), width: 5, height: 5), bonePaint); Rect.fromCenter(center: Offset(bone.getWorldX(), bone.getWorldY()), width: 5, height: 5),
bonePaint,
);
} }
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -74,12 +74,13 @@ class SpineWidgetController {
/// Constructs a new [SpineWidget] controller. See the class documentation of [SpineWidgetController] for information on /// Constructs a new [SpineWidget] controller. See the class documentation of [SpineWidgetController] for information on
/// the optional arguments. /// the optional arguments.
SpineWidgetController( SpineWidgetController({
{this.onInitialized, this.onInitialized,
this.onBeforeUpdateWorldTransforms, this.onBeforeUpdateWorldTransforms,
this.onAfterUpdateWorldTransforms, this.onAfterUpdateWorldTransforms,
this.onBeforePaint, this.onBeforePaint,
this.onAfterPaint}); this.onAfterPaint,
});
void _initialize(SkeletonDrawable drawable) { void _initialize(SkeletonDrawable drawable) {
var wasInitialized = _drawable != null; var wasInitialized = _drawable != null;
@ -207,7 +208,7 @@ class SkinAndAnimationBounds extends BoundsProvider {
/// The [stepTime], given in seconds, defines at what interval the bounds should be sampled /// The [stepTime], given in seconds, defines at what interval the bounds should be sampled
/// across the entire animation. /// across the entire animation.
SkinAndAnimationBounds({List<String>? skins, this.animation, this.stepTime = 0.1}) SkinAndAnimationBounds({List<String>? skins, this.animation, this.stepTime = 0.1})
: skins = skins == null || skins.isEmpty ? ["default"] : skins; : skins = skins == null || skins.isEmpty ? ["default"] : skins;
@override @override
Bounds computeBounds(SkeletonDrawable drawable) { Bounds computeBounds(SkeletonDrawable drawable) {
@ -286,20 +287,23 @@ class SpineWidget extends StatefulWidget {
/// are used. /// are used.
/// ///
/// The widget can optionally by sized by the bounds provided by the [BoundsProvider] by passing `true` for [sizedByBounds]. /// The widget can optionally by sized by the bounds provided by the [BoundsProvider] by passing `true` for [sizedByBounds].
SpineWidget.fromAsset(this._atlasFile, this._skeletonFile, this._controller, SpineWidget.fromAsset(
{AssetBundle? bundle, this._atlasFile,
BoxFit? fit, this._skeletonFile,
Alignment? alignment, this._controller, {
BoundsProvider? boundsProvider, AssetBundle? bundle,
bool? sizedByBounds, BoxFit? fit,
super.key}) Alignment? alignment,
: _assetType = _AssetType.asset, BoundsProvider? boundsProvider,
_fit = fit ?? BoxFit.contain, bool? sizedByBounds,
_alignment = alignment ?? Alignment.center, super.key,
_boundsProvider = boundsProvider ?? const SetupPoseBounds(), }) : _assetType = _AssetType.asset,
_sizedByBounds = sizedByBounds ?? false, _fit = fit ?? BoxFit.contain,
_drawable = null, _alignment = alignment ?? Alignment.center,
_bundle = bundle ?? rootBundle; _boundsProvider = boundsProvider ?? const SetupPoseBounds(),
_sizedByBounds = sizedByBounds ?? false,
_drawable = null,
_bundle = bundle ?? rootBundle;
/// Constructs a new [SpineWidget] from files. The [_atlasFile] specifies the `.atlas` file to be loaded for the images used to render /// Constructs a new [SpineWidget] from files. The [_atlasFile] specifies the `.atlas` file to be loaded for the images used to render
/// the skeleton. The [_skeletonFile] specifies either a Skeleton `.json` or `.skel` file containing the skeleton data. /// the skeleton. The [_skeletonFile] specifies either a Skeleton `.json` or `.skel` file containing the skeleton data.
@ -312,15 +316,22 @@ class SpineWidget extends StatefulWidget {
/// are used. /// are used.
/// ///
/// The widget can optionally by sized by the bounds provided by the [BoundsProvider] by passing `true` for [sizedByBounds]. /// The widget can optionally by sized by the bounds provided by the [BoundsProvider] by passing `true` for [sizedByBounds].
const SpineWidget.fromFile(this._atlasFile, this._skeletonFile, this._controller, const SpineWidget.fromFile(
{BoxFit? fit, Alignment? alignment, BoundsProvider? boundsProvider, bool? sizedByBounds, super.key}) this._atlasFile,
: _assetType = _AssetType.file, this._skeletonFile,
_bundle = null, this._controller, {
_fit = fit ?? BoxFit.contain, BoxFit? fit,
_alignment = alignment ?? Alignment.center, Alignment? alignment,
_boundsProvider = boundsProvider ?? const SetupPoseBounds(), BoundsProvider? boundsProvider,
_sizedByBounds = sizedByBounds ?? false, bool? sizedByBounds,
_drawable = null; super.key,
}) : _assetType = _AssetType.file,
_bundle = null,
_fit = fit ?? BoxFit.contain,
_alignment = alignment ?? Alignment.center,
_boundsProvider = boundsProvider ?? const SetupPoseBounds(),
_sizedByBounds = sizedByBounds ?? false,
_drawable = null;
/// Constructs a new [SpineWidget] from HTTP URLs. The [_atlasFile] specifies the `.atlas` file to be loaded for the images used to render /// Constructs a new [SpineWidget] from HTTP URLs. The [_atlasFile] specifies the `.atlas` file to be loaded for the images used to render
/// the skeleton. The [_skeletonFile] specifies either a Skeleton `.json` or `.skel` file containing the skeleton data. /// the skeleton. The [_skeletonFile] specifies either a Skeleton `.json` or `.skel` file containing the skeleton data.
@ -333,15 +344,22 @@ class SpineWidget extends StatefulWidget {
/// are used. /// are used.
/// ///
/// The widget can optionally by sized by the bounds provided by the [BoundsProvider] by passing `true` for [sizedByBounds]. /// The widget can optionally by sized by the bounds provided by the [BoundsProvider] by passing `true` for [sizedByBounds].
const SpineWidget.fromHttp(this._atlasFile, this._skeletonFile, this._controller, const SpineWidget.fromHttp(
{BoxFit? fit, Alignment? alignment, BoundsProvider? boundsProvider, bool? sizedByBounds, super.key}) this._atlasFile,
: _assetType = _AssetType.http, this._skeletonFile,
_bundle = null, this._controller, {
_fit = fit ?? BoxFit.contain, BoxFit? fit,
_alignment = alignment ?? Alignment.center, Alignment? alignment,
_boundsProvider = boundsProvider ?? const SetupPoseBounds(), BoundsProvider? boundsProvider,
_sizedByBounds = sizedByBounds ?? false, bool? sizedByBounds,
_drawable = null; super.key,
}) : _assetType = _AssetType.http,
_bundle = null,
_fit = fit ?? BoxFit.contain,
_alignment = alignment ?? Alignment.center,
_boundsProvider = boundsProvider ?? const SetupPoseBounds(),
_sizedByBounds = sizedByBounds ?? false,
_drawable = null;
/// Constructs a new [SpineWidget] from a [SkeletonDrawable]. /// Constructs a new [SpineWidget] from a [SkeletonDrawable].
/// ///
@ -353,16 +371,22 @@ class SpineWidget extends StatefulWidget {
/// are used. /// are used.
/// ///
/// The widget can optionally by sized by the bounds provided by the [BoundsProvider] by passing `true` for [sizedByBounds]. /// The widget can optionally by sized by the bounds provided by the [BoundsProvider] by passing `true` for [sizedByBounds].
const SpineWidget.fromDrawable(this._drawable, this._controller, const SpineWidget.fromDrawable(
{BoxFit? fit, Alignment? alignment, BoundsProvider? boundsProvider, bool? sizedByBounds, super.key}) this._drawable,
: _assetType = _AssetType.drawable, this._controller, {
_bundle = null, BoxFit? fit,
_fit = fit ?? BoxFit.contain, Alignment? alignment,
_alignment = alignment ?? Alignment.center, BoundsProvider? boundsProvider,
_boundsProvider = boundsProvider ?? const SetupPoseBounds(), bool? sizedByBounds,
_sizedByBounds = sizedByBounds ?? false, super.key,
_skeletonFile = null, }) : _assetType = _AssetType.drawable,
_atlasFile = null; _bundle = null,
_fit = fit ?? BoxFit.contain,
_alignment = alignment ?? Alignment.center,
_boundsProvider = boundsProvider ?? const SetupPoseBounds(),
_sizedByBounds = sizedByBounds ?? false,
_skeletonFile = null,
_atlasFile = null;
@override @override
State<SpineWidget> createState() => _SpineWidgetState(); State<SpineWidget> createState() => _SpineWidgetState();
@ -439,7 +463,13 @@ class _SpineWidgetState extends State<SpineWidget> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (_drawable != null) { if (_drawable != null) {
return _SpineRenderObjectWidget( return _SpineRenderObjectWidget(
_drawable!, widget._controller, widget._fit, widget._alignment, _computedBounds, widget._sizedByBounds); _drawable!,
widget._controller,
widget._fit,
widget._alignment,
_computedBounds,
widget._sizedByBounds,
);
} else { } else {
return const SizedBox(); return const SizedBox();
} }
@ -461,7 +491,13 @@ class _SpineRenderObjectWidget extends LeafRenderObjectWidget {
final bool _sizedByBounds; final bool _sizedByBounds;
const _SpineRenderObjectWidget( const _SpineRenderObjectWidget(
this._skeletonDrawable, this._controller, this._fit, this._alignment, this._bounds, this._sizedByBounds); this._skeletonDrawable,
this._controller,
this._fit,
this._alignment,
this._bounds,
this._sizedByBounds,
);
@override @override
RenderObject createRenderObject(BuildContext context) { RenderObject createRenderObject(BuildContext context) {
@ -491,7 +527,13 @@ class _SpineRenderObject extends RenderBox {
bool _firstUpdated = false; bool _firstUpdated = false;
_SpineRenderObject( _SpineRenderObject(
this._skeletonDrawable, this._controller, this._fit, this._alignment, this._bounds, this._sizedByBounds); this._skeletonDrawable,
this._controller,
this._fit,
this._alignment,
this._bounds,
this._sizedByBounds,
);
set skeletonDrawable(SkeletonDrawable skeletonDrawable) { set skeletonDrawable(SkeletonDrawable skeletonDrawable) {
if (_skeletonDrawable == skeletonDrawable) return; if (_skeletonDrawable == skeletonDrawable) return;