Skip to main content
c
14d ago

Unable to fire triggers in rive_native

When using the rive_native package here https://pub.dev/documentation/rive_native/latest/

The docs start that setting state state inputs is supported (we are running MacOS).

Here is our code to test it out - all inputs (triggers/booleans/numbers) seem to not be working when set in code - any suggestions? Through print logs I can see the objects are found but next step of fire() / setting value don't seem to do anything. The inputs are all created at the top level i.e. not nested

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:rive_native/rive_native.dart';

bool isRiveRender = true;

class RivePlayer extends StatefulWidget {
  const RivePlayer({
    super.key,
    required this.asset,
    required this.stateMachineName,
    this.artboardName,
    this.hitTestBehavior = RiveHitTestBehavior.opaque,
    this.cursor = MouseCursor.defer,
    this.fit = Fit.contain,
    this.alignment = Alignment.center,
    this.layoutScaleFactor = 1.0,
    this.withStateMachine,
    this.onArtboardInitialized,
  });

  final String asset;
  final String? stateMachineName;
  final String? artboardName;
  final RiveHitTestBehavior hitTestBehavior;
  final MouseCursor cursor;
  final Fit fit;
  final Alignment alignment;
  final double layoutScaleFactor;
  final void Function(Artboard)? onArtboardInitialized; // New callback
  final void Function(StateMachine)? withStateMachine;

  @override
  State<RivePlayer> createState() => _RivePlayerState();
}

class _RivePlayerState extends State<RivePlayer> {
  File? riveFile;

  late Artboard artboard;
  late StateMachinePainter stateMachinePainter;

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

  Future<File?> _loadFile() async {
    final bytes = await rootBundle.load(widget.asset);
    return File.decode(bytes.buffer.asUint8List(),
        riveFactory: isRiveRender ? Factory.rive : Factory.flutter);
  }

  Future<void> init() async {
    riveFile = await _loadFile();

    if (widget.artboardName != null) {
      artboard = riveFile!.artboard(widget.artboardName!)!;
    } else {
      artboard = riveFile!.artboardAt(0)!;
    }

    stateMachinePainter = RivePainter.stateMachine(
      widget.stateMachineName,
      withStateMachine: widget.withStateMachine,
    )
      ..hitTestBehavior = widget.hitTestBehavior
      ..cursor = widget.cursor
      ..fit = widget.fit
      ..alignment = widget.alignment
      ..layoutScaleFactor = widget.layoutScaleFactor;

    widget.onArtboardInitialized?.call(artboard);

    setState(() {});
  }

  @override
  void didUpdateWidget(covariant RivePlayer oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (widget.hitTestBehavior != oldWidget.hitTestBehavior) {
      stateMachinePainter.hitTestBehavior = widget.hitTestBehavior;
    }
    if (widget.cursor != oldWidget.cursor) {
      stateMachinePainter.cursor = widget.cursor;
    }
    if (widget.fit != oldWidget.fit) {
      stateMachinePainter.fit = widget.fit;
    }
    if (widget.alignment != oldWidget.alignment) {
      stateMachinePainter.alignment = widget.alignment;
    }
    if (widget.layoutScaleFactor != oldWidget.layoutScaleFactor) {
      stateMachinePainter.layoutScaleFactor = widget.layoutScaleFactor;
    }
  }

  @override
  Widget build(BuildContext context) {
    return riveFile != null
        ? RiveArtboardWidget(
            artboard: artboard,
            painter: stateMachinePainter,
          )
        : const SizedBox();
  }
}

class ExampleBasic extends StatelessWidget {
  const ExampleBasic({super.key});

  @override
  Widget build(BuildContext context) {
    return RivePlayer(
      asset: "assets/slot_boy.riv",
      stateMachineName: "State Machine 1",
      artboardName: "Motherboard",
      onArtboardInitialized: (Artboard artboard) {
        StateMachine? state_machine = artboard.stateMachine("State Machine 1");
        // flutter: state machine: Instance of 'FFIStateMachine'
        print('state machine: $state_machine');

        // triggers - these all exist but fire doesn't work
        // flutter: trigger: Instance of 'FFITriggerInput'
        // flutter: trigger2: Instance of 'FFITriggerInput'
        // flutter: trigger3: Instance of 'FFITriggerInput'
        TriggerInput? trigger = state_machine!.trigger("Shuffle 1");
        print('trigger: $trigger');
        trigger!.fire();
        TriggerInput? trigger2 = state_machine!.trigger("Shuffle 2");
        print('trigger2: $trigger2');
        trigger2!.fire();
        TriggerInput? trigger3 = state_machine!.trigger("Scale");
        print('trigger3: $trigger3');
        trigger3!.fire();

        // bool/number inputs - these also exist but fail to animated when set to a value that should trigger
        // flutter: booleaninput: Instance of 'FFIBooleanInput'
        // flutter: numberinput: Instance of 'FFINumberInput'
        BooleanInput? b = state_machine!.boolean("Boolean 1");
        print('booleaninput: $b');
        b!.value = true;
        NumberInput? n = state_machine!.number("Number 1");
        print('numberinput: $n');
        n!.value = 3;
      },
    );
  }
}

1 reply
12d ago

It looks like the inputs aren't being defined correctly. Here are the docs: https://rive.app/community/doc/state-machines/docxeznG7iiK#inputs-3

I would expect to see something like:

final controller = StateMachineController.fromArtboard(artboard, 'State Machine 1');
artboard.addController(controller!);
trigger2 = controller.getTriggerInput('Shuffle 1')!;