feat(flutter): add shared texture through rive panel (#10451) 7359e8b824

* feat(flutter): add shared texture through rive panel

* feat: updates to rive panel

* chore: revert pub path change

* docs: update api level docs

* feat: expose drawOrder

feat: Add fallback AtlasTypes that don't need float color buffers (#10475) 5e6f683b9e
Floating point color buffers are only supported via extensions in GL.
Previously, the feather atlas would just break when this functionality
wasn't present.

This PR adds support for multiple different AtlasTypes that make use of
various GL extensions to render the atlas. As a final resort, if none of
the other extensions are available, it can split coverage up into rgba8
compoments. This mode works on unextended GL at the cost of quality.

Co-authored-by: Gordon <pggordonhayes@gmail.com>
This commit is contained in:
HayesGordon
2025-09-03 17:20:33 +00:00
parent 38f40c8309
commit ce00421de5
22 changed files with 1169 additions and 3 deletions

View File

@ -14,6 +14,7 @@ export 'responsive_layouts.dart';
export 'rive_audio.dart';
export 'rive_widget.dart';
export 'rive_widget_builder.dart';
export 'rive_panel.dart';
export 'state_machine_painter.dart';
export 'text_runs.dart';
export 'ticker_mode.dart';

View File

@ -0,0 +1,168 @@
import 'package:flutter/material.dart';
import 'package:rive/rive.dart';
class ExampleRivePanel extends StatelessWidget {
const ExampleRivePanel({super.key});
@override
Widget build(BuildContext context) {
return const RivePanel(
child: ListViewExample(),
);
}
}
class RowExample extends StatefulWidget {
const RowExample({super.key});
@override
State<RowExample> createState() => _RowExampleState();
}
class _RowExampleState extends State<RowExample> {
// Only useful when using `Factory.rive`. `Factory.flutter` draws to a single
// render target already.
final factory = Factory.rive;
late List<FileLoader> listOfFileLoaders = [
FileLoader.fromAsset(
'assets/rating.riv',
riveFactory: factory,
),
FileLoader.fromAsset(
'assets/vehicles.riv',
riveFactory: factory,
),
FileLoader.fromAsset(
'assets/perf/rivs/travel_icons.riv',
riveFactory: factory,
),
FileLoader.fromAsset(
'assets/coyote.riv',
riveFactory: factory,
),
FileLoader.fromAsset(
'assets/perf/rivs/Tom_Morello_2.riv',
riveFactory: factory,
),
FileLoader.fromAsset(
'assets/perf/rivs/towersDemo.riv',
riveFactory: factory,
),
FileLoader.fromAsset(
'assets/perf/rivs/walking.riv',
riveFactory: factory,
),
FileLoader.fromAsset(
'assets/perf/rivs/skull_404.riv',
riveFactory: factory,
),
FileLoader.fromAsset(
'assets/perf/rivs/adventuretime_marceline_pb.riv',
riveFactory: factory,
),
FileLoader.fromAsset(
'assets/perf/rivs/Zombie_Character.riv',
riveFactory: factory,
),
];
@override
void dispose() {
for (var fileLoader in listOfFileLoaders) {
fileLoader.dispose();
}
super.dispose();
}
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(top: 50.0),
child: SingleChildScrollView(
child: Wrap(
children: [
...listOfFileLoaders
.map((fileLoader) => SizedSample(fileLoader: fileLoader)),
],
),
),
);
}
}
class SizedSample extends StatelessWidget {
const SizedSample({super.key, required this.fileLoader});
final FileLoader fileLoader;
@override
Widget build(BuildContext context) {
return SizedBox(
width: 200,
height: 200,
child: MyRiveWidget(fileLoader: fileLoader),
);
}
}
class ListViewExample extends StatefulWidget {
const ListViewExample({super.key});
@override
State<ListViewExample> createState() => _ListViewExampleState();
}
class _ListViewExampleState extends State<ListViewExample> {
late final fileLoader = FileLoader.fromAsset(
'assets/rating.riv',
riveFactory: Factory.rive,
);
@override
void dispose() {
fileLoader.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: 10,
itemBuilder: (context, index) {
return SizedBox(
width: 500,
height: 100,
child: MyRiveWidget(fileLoader: fileLoader),
);
},
);
}
}
class MyRiveWidget extends StatelessWidget {
const MyRiveWidget({super.key, required this.fileLoader});
final FileLoader fileLoader;
@override
Widget build(BuildContext context) {
return RiveWidgetBuilder(
fileLoader: fileLoader,
builder: (context, state) => switch (state) {
RiveLoading() => const Center(
child: Center(child: CircularProgressIndicator()),
),
RiveFailed() => ErrorWidget.withDetails(
message: state.error.toString(),
error: FlutterError(state.error.toString()),
),
RiveLoaded() => RiveWidget(
controller: state.controller,
fit: Fit.contain,
/// Set this to true to draw to the nearest `RivePanel`
useSharedTexture: true,
)
},
);
}
}