Parcourir la source

[flutter] Fix retention of drawable in SpineWidgetState, beginnings of debug renderer.

Mario Zechner il y a 2 ans
Parent
commit
dbc2e164f0

+ 26 - 0
spine-flutter/example/lib/debug_rendering.dart

@@ -0,0 +1,26 @@
+import 'package:flutter/material.dart';
+import 'package:esotericsoftware_spine_flutter/spine_flutter.dart';
+
+class DebugRendering extends StatelessWidget {
+  const DebugRendering({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    reportLeaks();
+
+    const debugRenderer = DebugRenderer();
+    final controller = SpineWidgetController(
+        onInitialized: (controller) {
+          controller.animationState.setAnimationByName(0, "walk", true);
+        },
+        onAfterPaint: (controller, canvas, commands) {
+          debugRenderer.render(controller.drawable, canvas, commands);
+        }
+    );
+
+    return Scaffold(
+      appBar: AppBar(title: const Text('Debug Renderer')),
+      body: SpineWidget.asset("assets/spineboy.atlas", "assets/spineboy-pro.skel", controller),
+    );
+  }
+}

+ 13 - 0
spine-flutter/example/lib/main.dart

@@ -1,5 +1,6 @@
 import 'package:flutter/material.dart';
 import 'package:esotericsoftware_spine_flutter/spine_flutter.dart';
+import 'package:spine_flutter_example/debug_rendering.dart';
 
 import 'flame_example.dart';
 import 'simple_animation.dart';
@@ -57,6 +58,18 @@ class ExampleSelector extends StatelessWidget {
                 },
               ),
               spacer,
+              ElevatedButton(
+                child: const Text('Debug Rendering'),
+                onPressed: () {
+                  Navigator.push(
+                    context,
+                    MaterialPageRoute<void>(
+                      builder: (context) => DebugRendering(),
+                    ),
+                  );
+                },
+              ),
+              spacer,
               ElevatedButton(
                 child: const Text('Skins'),
                 onPressed: () {

+ 22 - 5
spine-flutter/lib/spine_flutter.dart

@@ -3,6 +3,7 @@ import 'dart:io';
 import 'dart:typed_data';
 import 'dart:ui';
 
+import 'package:flutter/material.dart' as material;
 import 'package:flutter/rendering.dart' as rendering;
 import 'package:flutter/services.dart';
 import 'package:http/http.dart' as http;
@@ -3242,7 +3243,6 @@ class AnimationState {
   }
 }
 
-// FIXME add callbacks for update, apply and updateWorldTransform. Pass through SpineWidgetController
 class SkeletonDrawable {
   final Atlas atlas;
   final SkeletonData skeletonData;
@@ -3321,19 +3321,23 @@ class SkeletonDrawable {
 class RenderCommand {
   late final Vertices vertices;
   late final int atlasPageIndex;
+  late final Float32List positions;
+  late final Float32List uvs;
+  late final Int32List colors;
+  late final Uint16List indices;
 
   RenderCommand._(spine_render_command nativeCmd, double pageWidth, double pageHeight) {
     atlasPageIndex = _bindings.spine_render_command_get_atlas_page(nativeCmd);
     int numVertices = _bindings.spine_render_command_get_num_vertices(nativeCmd);
     int numIndices = _bindings.spine_render_command_get_num_indices(nativeCmd);
-    final positions = _bindings.spine_render_command_get_positions(nativeCmd).asTypedList(numVertices * 2);
-    final uvs = _bindings.spine_render_command_get_uvs(nativeCmd).asTypedList(numVertices * 2);
+    positions = _bindings.spine_render_command_get_positions(nativeCmd).asTypedList(numVertices * 2);
+    uvs = _bindings.spine_render_command_get_uvs(nativeCmd).asTypedList(numVertices * 2);
     for (int i = 0; i < numVertices * 2; i += 2) {
       uvs[i] *= pageWidth;
       uvs[i + 1] *= pageHeight;
     }
-    final colors = _bindings.spine_render_command_get_colors(nativeCmd).asTypedList(numVertices);
-    final indices = _bindings.spine_render_command_get_indices(nativeCmd).asTypedList(numIndices);
+    colors = _bindings.spine_render_command_get_colors(nativeCmd).asTypedList(numVertices);
+    indices = _bindings.spine_render_command_get_indices(nativeCmd).asTypedList(numIndices);
 
     if (!kIsWeb) {
       // We pass the native data as views directly to Vertices.raw. According to the sources, the data
@@ -3356,4 +3360,17 @@ class RenderCommand {
           indices: indicesCopy);
     }
   }
+}
+
+class DebugRenderer {
+  const DebugRenderer();
+
+  void render(SkeletonDrawable drawable, Canvas canvas, List<RenderCommand> commands) {
+    final bonePaint = Paint()
+      ..color = material.Colors.blue
+      ..style = PaintingStyle.fill;
+    for (final bone in drawable.skeleton.getBones()) {
+      canvas.drawRect(Rect.fromCenter(center: Offset(bone.getWorldX(), bone.getWorldY()), width: 5, height: 5), bonePaint);
+    }
+  }
 }

+ 10 - 5
spine-flutter/lib/spine_widget.dart

@@ -14,7 +14,7 @@ class SpineWidgetController {
   final void Function(SpineWidgetController controller)? onBeforeUpdateWorldTransforms;
   final void Function(SpineWidgetController controller)? onAfterUpdateWorldTransforms;
   final void Function(SpineWidgetController controller, Canvas canvas)? onBeforePaint;
-  final void Function(SpineWidgetController controller, Canvas canvas)? onAfterPaint;
+  final void Function(SpineWidgetController controller, Canvas canvas, List<RenderCommand> commands)? onAfterPaint;
 
   SpineWidgetController({this.onInitialized, this.onBeforeUpdateWorldTransforms, this.onAfterUpdateWorldTransforms, this.onBeforePaint, this.onAfterPaint});
 
@@ -211,6 +211,7 @@ class SpineWidget extends StatefulWidget {
 
 class _SpineWidgetState extends State<SpineWidget> {
   late Bounds _computedBounds;
+  SkeletonDrawable? _drawable;
 
   @override
   void initState() {
@@ -223,6 +224,7 @@ class _SpineWidgetState extends State<SpineWidget> {
   }
 
   void loadDrawable(SkeletonDrawable drawable) {
+    _drawable = drawable;
     _computedBounds = widget._boundsProvider.computeBounds(drawable);
     widget._controller._initialize(drawable);
     setState(() {});
@@ -246,8 +248,8 @@ class _SpineWidgetState extends State<SpineWidget> {
 
   @override
   Widget build(BuildContext context) {
-    if (widget._controller._drawable != null) {
-      return _SpineRenderObjectWidget(widget._controller._drawable!, widget._controller, widget._fit, widget._alignment, _computedBounds, widget._sizedByBounds);
+    if (_drawable != null) {
+      return _SpineRenderObjectWidget(_drawable!, widget._controller, widget._fit, widget._alignment, _computedBounds, widget._sizedByBounds);
     } else {
       return const SizedBox();
     }
@@ -461,8 +463,11 @@ class _SpineRenderObject extends RenderBox {
     _setCanvasTransform(canvas, offset);
 
     _controller.onBeforePaint?.call(_controller, canvas);
-    _skeletonDrawable.renderToCanvas(canvas);
-    _controller.onAfterPaint?.call(_controller, canvas);
+    var commands = _skeletonDrawable.render();
+    for (final cmd in commands) {
+      canvas.drawVertices(cmd.vertices, rendering.BlendMode.modulate, _skeletonDrawable.atlas.atlasPagePaints[cmd.atlasPageIndex]);
+    }
+    _controller.onAfterPaint?.call(_controller, canvas, commands);
 
     canvas.restore();
     SchedulerBinding.instance.scheduleFrameCallback(_beginFrame);