rive-app / rive-app/rive-flutter

[rive_native] Setting RenderTexturePainter clear to false not working

Open
#512 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

triage
Dominant language
Dart
Stars
1.5k
Forks
240
PR merge metrics
No merged PRs in 30d

Description

Hi @HayesGordon glad to see rive_native in the main package now!

Just moving this issue here from the previous tracker:

On web: setting RenderTexturePainter clear to false does nothing

On desktop: setting RenderTexturePainter clear to false prevents clearing but renders previous vectors with a jitter/vibration

Here is the example again that I have been testing with:

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:rive/rive.dart' as rive;


class RenderTexturePainterExample extends StatefulWidget {
  const RenderTexturePainterExample({super.key});

  @override
  State<RenderTexturePainterExample> createState() =>
      _RenderTexturePainterExampleState();
}

class _RenderTexturePainterExampleState
    extends State<RenderTexturePainterExample> {

  bool isRiveRender = true;

  final rive.RenderTexture _renderTexture =
  rive.RiveNative.instance.makeRenderTexture();


  GamePainter? _myRivePainter;

  @override
  void initState() {
    loadFile();
    super.initState();
  }

  rive.File? riveFile;

  Future<void> loadFile() async {
    final bytes = await rootBundle.load("assets/zombie.riv");
    riveFile = await rive.File.decode(bytes.buffer.asUint8List(),
        riveFactory: isRiveRender ? rive.Factory.rive : rive.Factory.flutter);

    if (riveFile != null) {
      setState(() {
        _myRivePainter = GamePainter(riveFile!);
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    if (riveFile == null) return const SizedBox();
    return ColoredBox(
      color: const Color(0xFF507FBA),
      child: Center(
        child: _myRivePainter == null
            ? const SizedBox()
            : _renderTexture.widget(painter: _myRivePainter!),
      ),
    );
  }
}


final class GamePainter extends rive.RenderTexturePainter {

  final rive.File riveFile;

  final Set<rive.Artboard> allZombieArtboards = {};
  final Set<rive.StateMachine> allZombieStateMachines = {};



  GamePainter(this.riveFile) {

    int numZombies = 10;
    for (int i = 0; i < numZombies; i++) {
      var ab = riveFile.artboard("Zombie man")!;
      allZombieArtboards.add(ab);
      allZombieStateMachines.add(ab.stateMachine("Motion")!);
      allZombieStateMachines.last.number("numSkins")!.value = i%6;
    }

  }

  double y = 0;/// used to show trail

  @override
  bool paint(rive.RenderTexture texture, double devicePixelRatio, Size size, double elapsedSeconds) {

    final renderer = texture.renderer;

    /// draw zombies
    double spacing = size.width / allZombieArtboards.length;
    for (int i = 0; i < allZombieArtboards.length; i++) {
      var artboard = allZombieArtboards.elementAt(i);
      var statemachine = allZombieStateMachines.elementAt(i);
      statemachine.advanceAndApply(elapsedSeconds);
      renderer.save();
      renderer.translate(spacing * i - spacing/2, y);
      artboard.draw(renderer);
      renderer.restore();
    }

    ///draw test ellipse
    final rive.RenderPaint paintFill = texture.renderer.riveFactory.makePaint()
      ..style = rive.PaintingStyle.fill
      ..color = Colors.white;
    final rive.RenderPaint paintStroke = texture.renderer.riveFactory.makePaint()
      ..style = rive.PaintingStyle.stroke
      ..color = Colors.black;
    texture.renderer.drawCircle( Offset(y, y), 50, paintFill);
    texture.renderer.drawCircle( Offset(y, y), 50, paintStroke);

    y += 1;

    return true;
  }

  @override
  bool get clear => false;//does not work


  @override
  void dispose() {
    riveFile.dispose();
    for (var ab in allZombieArtboards) {
      ab.dispose();
    }
    for (var sm in allZombieStateMachines) {
      sm.dispose();
    }
    super.dispose();
  }

  @override
  Color get background => Colors.transparent;
}

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the provided RenderTexturePainterExample and trace how the RenderTexturePainter.clear getter is handled in the web and desktop rendering paths. Reproduce the example with clear set to false on both platforms, then verify that prior frames persist without the desktop jitter and that clearing is disabled on web.

Written by the indexing model from the issue text.

Assessment

Tech stack
dart, flutter
Domain
computer-graphics
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.