Flutter release 0.13.5

Tested out the latest rive-common that now uses `package:web` and `dart:js_interop`

The `RiveFile.initializeText` and everything associated with it are deprecated. Instead, use `RiveFile.initialize`, which will always need to be called when initializing text, audio, and layout.

Calling it `initializeText` is confusing to users as they may not be using text, but still need to call this manually when using RiveFile.import.

There is maybe additional cleanup we could do here, but at least want to make sure the public API is not confusing.

Diffs=
fa7c55934 Flutter release 0.13.5 (#7305)
973ff2276 Fix warnings about invalid toolsets (#7300)

Co-authored-by: Gordon <pggordonhayes@gmail.com>
This commit is contained in:
HayesGordon
2024-05-23 19:22:06 +00:00
parent a0e22e4250
commit 04d3908f57
10 changed files with 121 additions and 116 deletions

View File

@ -1 +1 @@
0b1834a1ac1df3392314f44a3d7dfb135a8a3f6b fa7c55934e1523fd1de55dcc1540d9c19934cdc0

View File

@ -1,4 +1,9 @@
## 0.13.5
- Migrates to `dart:js_interop` and `package:web` APIs.
- DEPRECATED: `RiveFile.initializeText` - use `RiveFile.initialize` instead. This now initializes the Rive audio, text, and layout engine. Call `await RiveFile.initialize()` before doing `RiveFile.import`. `RiveFile.asset`, `RiveFile.network`, and `RiveFile.file` will call initialize automatically if it has not been initialized. Alternatively, you can also call `unawaited(RiveFile.initialize());` in the `main` method on app start to make the first graphic load faster.
## 0.13.4 ## 0.13.4
- Fixed an issue with [TickerMode](https://api.flutter.dev/flutter/widgets/TickerMode-class.html) value not pausing a Rive graphic. Thanks to 'jaggernod' for the [contribution](https://github.com/rive-app/rive-flutter/pull/380). - Fixed an issue with [TickerMode](https://api.flutter.dev/flutter/widgets/TickerMode-class.html) value not pausing a Rive graphic. Thanks to 'jaggernod' for the [contribution](https://github.com/rive-app/rive-flutter/pull/380).
- Bump rive_common to pick up the Privacy manifest for iOS & macOS runtimes - Bump rive_common to pick up the Privacy manifest for iOS & macOS runtimes

View File

@ -1,5 +1,4 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:rive/rive.dart'; import 'package:rive/rive.dart';
/// An example showing how to drive two boolean state machine inputs. /// An example showing how to drive two boolean state machine inputs.
@ -11,11 +10,7 @@ class ExampleStateMachine extends StatefulWidget {
} }
class _ExampleStateMachineState extends State<ExampleStateMachine> { class _ExampleStateMachineState extends State<ExampleStateMachine> {
/// Tracks if the animation is playing by whether controller is running.
bool get isPlaying => _controller?.isActive ?? false;
Artboard? _riveArtboard; Artboard? _riveArtboard;
StateMachineController? _controller;
SMIBool? _hoverInput; SMIBool? _hoverInput;
SMIBool? _pressInput; SMIBool? _pressInput;
@ -23,26 +18,23 @@ class _ExampleStateMachineState extends State<ExampleStateMachine> {
void initState() { void initState() {
super.initState(); super.initState();
// Load the animation file from the bundle, note that you could also _loadRiveFile();
// download this. The RiveFile just expects a list of bytes. }
rootBundle.load('assets/rocket.riv').then(
(data) async { Future<void> _loadRiveFile() async {
// Load the RiveFile from the binary data. // Load the animation file from the bundle.
final file = RiveFile.import(data); final riveFile = await RiveFile.asset('assets/rocket.riv');
// The artboard is the root of the animation and gets drawn in the // The artboard is the root of the animation and gets drawn in the
// Rive widget. // Rive widget.
final artboard = file.mainArtboard; final artboard = riveFile.mainArtboard;
var controller = var controller = StateMachineController.fromArtboard(artboard, 'Button');
StateMachineController.fromArtboard(artboard, 'Button'); if (controller != null) {
if (controller != null) { artboard.addController(controller);
artboard.addController(controller); _hoverInput = controller.getBoolInput('Hover');
_hoverInput = controller.getBoolInput('Hover'); _pressInput = controller.getBoolInput('Press');
_pressInput = controller.getBoolInput('Press'); }
} setState(() => _riveArtboard = artboard);
setState(() => _riveArtboard = artboard);
},
);
} }
@override @override

View File

@ -1,5 +1,4 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:rive/rive.dart'; import 'package:rive/rive.dart';
/// An example showing how to drive a StateMachine via a trigger and number /// An example showing how to drive a StateMachine via a trigger and number
@ -12,38 +11,28 @@ class LiquidDownload extends StatefulWidget {
} }
class _LiquidDownloadState extends State<LiquidDownload> { class _LiquidDownloadState extends State<LiquidDownload> {
/// Tracks if the animation is playing by whether controller is running.
bool get isPlaying => _controller?.isActive ?? false;
Artboard? _riveArtboard; Artboard? _riveArtboard;
StateMachineController? _controller;
SMITrigger? _start; SMITrigger? _start;
SMINumber? _progress; SMINumber? _progress;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_loadRiveFile();
}
// Load the animation file from the bundle, note that you could also Future<void> _loadRiveFile() async {
// download this. The RiveFile just expects a list of bytes. final file = await RiveFile.asset('assets/liquid_download.riv');
rootBundle.load('assets/liquid_download.riv').then( // The artboard is the root of the animation and gets drawn in the
(data) async { // Rive widget.
// Load the RiveFile from the binary data. final artboard = file.mainArtboard;
final file = RiveFile.import(data); var controller = StateMachineController.fromArtboard(artboard, 'Download');
if (controller != null) {
// The artboard is the root of the animation and gets drawn in the artboard.addController(controller);
// Rive widget. _start = controller.getTriggerInput('Download');
final artboard = file.mainArtboard; _progress = controller.getNumberInput('Progress');
var controller = }
StateMachineController.fromArtboard(artboard, 'Download'); setState(() => _riveArtboard = artboard);
if (controller != null) {
artboard.addController(controller);
_start = controller.getTriggerInput('Download');
_progress = controller.getNumberInput('Progress');
}
setState(() => _riveArtboard = artboard);
},
);
} }
@override @override

View File

@ -1,5 +1,4 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:rive/rive.dart'; import 'package:rive/rive.dart';
/// An example showing how to drive a StateMachine via a trigger input. /// An example showing how to drive a StateMachine via a trigger input.
@ -11,42 +10,34 @@ class LittleMachine extends StatefulWidget {
} }
class _LittleMachineState extends State<LittleMachine> { class _LittleMachineState extends State<LittleMachine> {
/// Tracks if the animation is playing by whether controller is running.
bool get isPlaying => _controller?.isActive ?? false;
/// Message that displays when state has changed /// Message that displays when state has changed
String stateChangeMessage = ''; String stateChangeMessage = '';
Artboard? _riveArtboard; Artboard? _riveArtboard;
StateMachineController? _controller;
SMITrigger? _trigger; SMITrigger? _trigger;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_loadRiveFile();
}
// Load the animation file from the bundle, note that you could also Future<void> _loadRiveFile() async {
// download this. The RiveFile just expects a list of bytes. final file = await RiveFile.asset('assets/little_machine.riv');
rootBundle.load('assets/little_machine.riv').then(
(data) async {
// Load the RiveFile from the binary data.
final file = RiveFile.import(data);
// The artboard is the root of the animation and gets drawn in the // The artboard is the root of the animation and gets drawn in the
// Rive widget. // Rive widget.
final artboard = file.mainArtboard; final artboard = file.mainArtboard;
var controller = StateMachineController.fromArtboard( var controller = StateMachineController.fromArtboard(
artboard, artboard,
'State Machine 1', 'State Machine 1',
onStateChange: _onStateChange, onStateChange: _onStateChange,
);
if (controller != null) {
artboard.addController(controller);
_trigger = controller.getTriggerInput('Trigger 1');
}
setState(() => _riveArtboard = artboard);
},
); );
if (controller != null) {
artboard.addController(controller);
_trigger = controller.getTriggerInput('Trigger 1');
}
setState(() => _riveArtboard = artboard);
} }
/// Do something when the state machine changes state /// Do something when the state machine changes state

View File

@ -1,4 +1,7 @@
import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:rive/rive.dart';
import 'package:rive_example/custom_asset_loading.dart'; import 'package:rive_example/custom_asset_loading.dart';
import 'package:rive_example/custom_cached_asset_loading.dart'; import 'package:rive_example/custom_cached_asset_loading.dart';
@ -22,19 +25,27 @@ import 'package:rive_example/skinning_demo.dart';
import 'package:rive_example/state_machine_skills.dart'; import 'package:rive_example/state_machine_skills.dart';
import 'package:rive_example/basic_text.dart'; import 'package:rive_example/basic_text.dart';
void main() => runApp( void main() {
MaterialApp( /// Initialize Rive's text, audio, and layout engines.
title: 'Rive Example', /// This will automatically be called the first time a RiveFile is loaded if
home: const RiveExampleApp(), /// it has not been initialized. And does not need to be called.
darkTheme: ThemeData.dark().copyWith( ///
scaffoldBackgroundColor: _backgroundColor, /// However, calling it early here makes the first
appBarTheme: const AppBarTheme(backgroundColor: _appBarColor), /// visible Rive graphic load faster.
colorScheme: unawaited(RiveFile.initialize());
ColorScheme.fromSwatch().copyWith(primary: _primaryColor), runApp(
), MaterialApp(
themeMode: ThemeMode.dark, title: 'Rive Example',
home: const RiveExampleApp(),
darkTheme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: _backgroundColor,
appBarTheme: const AppBarTheme(backgroundColor: _appBarColor),
colorScheme: ColorScheme.fromSwatch().copyWith(primary: _primaryColor),
), ),
); themeMode: ThemeMode.dark,
),
);
}
/// An example application demoing Rive. /// An example application demoing Rive.
class RiveExampleApp extends StatefulWidget { class RiveExampleApp extends StatefulWidget {

View File

@ -1,5 +1,4 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:rive/rive.dart'; import 'package:rive/rive.dart';
/// An example showing how to drive a StateMachine via one numeric input. /// An example showing how to drive a StateMachine via one numeric input.
@ -11,36 +10,29 @@ class StateMachineSkills extends StatefulWidget {
} }
class _StateMachineSkillsState extends State<StateMachineSkills> { class _StateMachineSkillsState extends State<StateMachineSkills> {
/// Tracks if the animation is playing by whether controller is running.
bool get isPlaying => _controller?.isActive ?? false;
Artboard? _riveArtboard; Artboard? _riveArtboard;
StateMachineController? _controller;
SMINumber? _levelInput; SMINumber? _levelInput;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
// Load the animation file from the bundle, note that you could also _loadRiveFile();
// download this. The RiveFile just expects a list of bytes. }
rootBundle.load('assets/skills.riv').then(
(data) async { Future<void> _loadRiveFile() async {
// Load the RiveFile from the binary data. final file = await RiveFile.asset('assets/skills.riv');
final file = RiveFile.import(data);
// The artboard is the root of the animation and gets drawn in the // The artboard is the root of the animation and gets drawn in the
// Rive widget. // Rive widget.
final artboard = file.mainArtboard; final artboard = file.mainArtboard;
var controller = var controller =
StateMachineController.fromArtboard(artboard, 'Designer\'s Test'); StateMachineController.fromArtboard(artboard, 'Designer\'s Test');
if (controller != null) { if (controller != null) {
artboard.addController(controller); artboard.addController(controller);
_levelInput = controller.getNumberInput('Level'); _levelInput = controller.getNumberInput('Level');
} }
setState(() => _riveArtboard = artboard); setState(() => _riveArtboard = artboard);
},
);
} }
@override @override

View File

@ -16,6 +16,7 @@ import 'package:rive_common/math.dart';
export 'package:rive/src/generated/nested_artboard_base.dart'; export 'package:rive/src/generated/nested_artboard_base.dart';
enum NestedArtboardFitType { enum NestedArtboardFitType {
// ignore: lines_longer_than_80_chars
fill, // Default value - scales to fill available view without maintaining aspect ratio fill, // Default value - scales to fill available view without maintaining aspect ratio
contain, contain,
cover, cover,

View File

@ -38,7 +38,6 @@ import 'package:rive/src/rive_core/runtime/exceptions/rive_format_error_exceptio
import 'package:rive/src/rive_core/runtime/runtime_header.dart'; import 'package:rive/src/rive_core/runtime/runtime_header.dart';
import 'package:rive/src/runtime_nested_artboard.dart'; import 'package:rive/src/runtime_nested_artboard.dart';
import 'package:rive_common/rive_text.dart'; import 'package:rive_common/rive_text.dart';
import 'package:rive_common/utilities.dart'; import 'package:rive_common/utilities.dart';
typedef Core<CoreContext>? ObjectGenerator(int coreTypeKey); typedef Core<CoreContext>? ObjectGenerator(int coreTypeKey);
@ -137,6 +136,7 @@ class RiveFile {
return propertyToField; return propertyToField;
} }
@Deprecated('This method will always return true and is no longer accurate')
// Peek into the bytes to see if we're going to need to use the text runtime. // Peek into the bytes to see if we're going to need to use the text runtime.
static bool needsTextRuntime(ByteData bytes) { static bool needsTextRuntime(ByteData bytes) {
var reader = BinaryReader(bytes); var reader = BinaryReader(bytes);
@ -343,6 +343,14 @@ class RiveFile {
ObjectGenerator? objectGenerator, ObjectGenerator? objectGenerator,
bool loadCdnAssets = true, bool loadCdnAssets = true,
}) { }) {
// TODO: in the next major version add an assert here to make this a
// requirement
if (!_initializedText) {
debugPrint('''Rive: RiveFile.import called before RiveFile.initialize()
Consider calling `await RiveFile.initialize()` before using `RiveFile.import`''');
}
var reader = BinaryReader(bytes); var reader = BinaryReader(bytes);
return RiveFile._( return RiveFile._(
reader, reader,
@ -359,8 +367,18 @@ class RiveFile {
static bool _initializedText = false; static bool _initializedText = false;
/// Initialize Rive's text engine if it hasn't been yet. /// Initialize Rive's text, audio, and layout engines.
static Future<void> initializeText() async { ///
/// This method is automatically called when using `RiveFile.asset`,
/// `RiveFile.network`, and `RiveFile.file`.
///
/// When using `RiveFile.import` then `RiveFile.initialize()` should be
/// called manually.
///
/// Consider calling `unawaited(RiveFile.initialize());` in the `main` method
/// to ensure the engine has initialized before displaying the first Rive
/// graphic.
static Future<void> initialize() async {
if (!_initializedText) { if (!_initializedText) {
final status = await Font.initialize(); final status = await Font.initialize();
if (status == FontInitStatus.success || if (status == FontInitStatus.success ||
@ -370,6 +388,12 @@ class RiveFile {
} }
} }
/// Initialize Rive's text engine if it hasn't been yet.
@Deprecated('Use `initialize()` instead')
static Future<void> initializeText() async {
await initialize();
}
static Future<RiveFile> _initTextAndImport( static Future<RiveFile> _initTextAndImport(
ByteData bytes, { ByteData bytes, {
FileAssetLoader? assetLoader, FileAssetLoader? assetLoader,
@ -377,8 +401,8 @@ class RiveFile {
ObjectGenerator? objectGenerator, ObjectGenerator? objectGenerator,
}) async { }) async {
/// If the file looks like it needs the text runtime, let's load it. /// If the file looks like it needs the text runtime, let's load it.
if (!_initializedText && RiveFile.needsTextRuntime(bytes)) { if (!_initializedText) {
await initializeText(); await initialize();
} }
return RiveFile.import( return RiveFile.import(
bytes, bytes,

View File

@ -1,5 +1,5 @@
name: rive name: rive
version: 0.13.4 version: 0.13.5
homepage: https://rive.app homepage: https://rive.app
description: Rive 2 Flutter Runtime. This package provides runtime functionality for playing back and interacting with animations built with the Rive editor available at https://rive.app. description: Rive 2 Flutter Runtime. This package provides runtime functionality for playing back and interacting with animations built with the Rive editor available at https://rive.app.
repository: https://github.com/rive-app/rive-flutter repository: https://github.com/rive-app/rive-flutter