Skip to content

Commit dbc0692

Browse files
Merge pull request #1 from NonymousMorlock/rive-migration
chore: Rive migration
2 parents f4469f1 + 399428a commit dbc0692

13 files changed

Lines changed: 118 additions & 84 deletions

File tree

assets/rive/game_button.bk.riv

834 KB
Binary file not shown.

assets/rive/game_button.riv

419 Bytes
Binary file not shown.

lib/bootstrap.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,12 @@ Future<void> bootstrap(FutureOr<Widget> Function() builder) async {
3131
Bloc.observer = const AppBlocObserver();
3232

3333
// Add cross-flavor configuration here
34+
WidgetsFlutterBinding.ensureInitialized();
3435
HydratedBloc.storage = await HydratedStorage.build(
3536
storageDirectory: kIsWeb
3637
? HydratedStorage.webStorageDirectory
3738
: await getApplicationDocumentsDirectory(),
3839
);
39-
unawaited(RiveFile.initialize());
40+
unawaited(RiveNative.init());
4041
runApp(await builder());
4142
}

lib/core/common/widgets/game_button.dart

Lines changed: 32 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import 'package:flutter/material.dart';
55
import 'package:flutter/services.dart';
66
import 'package:rive/rive.dart';
7-
import 'package:sozzle/core/extensions/rive_extensions.dart';
87
import 'package:sozzle/core/res/media.dart';
98

109
class GameButton extends StatefulWidget {
@@ -18,9 +17,9 @@ class GameButton extends StatefulWidget {
1817
}
1918

2019
class _GameButtonState extends State<GameButton> {
21-
RiveFile? _riveFile;
20+
File? _riveFile;
2221

23-
StateMachineController? controller;
22+
late RiveWidgetController controller;
2423

2524
bool clicked = false;
2625

@@ -32,15 +31,34 @@ class _GameButtonState extends State<GameButton> {
3231

3332
@override
3433
void dispose() {
35-
controller?.dispose();
34+
controller.dispose();
3635
super.dispose();
3736
}
3837

39-
void _preload() {
40-
rootBundle.load(Media.gameButton).then((data) {
41-
setState(() {
42-
_riveFile = RiveFile.import(data);
43-
});
38+
Future<void> _preload() async {
39+
final data = await rootBundle.load(Media.gameButton);
40+
_riveFile = await File.decode(
41+
data.buffer.asUint8List(),
42+
riveFactory: Factory.rive,
43+
);
44+
controller = RiveWidgetController(_riveFile!);
45+
_onInit(controller.artboard);
46+
setState(() {});
47+
}
48+
49+
void _onInit(Artboard artboard) {
50+
artboard.setText('buttonText', widget.text);
51+
52+
final viewModelInstance = controller.dataBind(DataBind.auto());
53+
54+
final currentState = viewModelInstance.string('currentState');
55+
currentState?.addListener((value) {
56+
if (value == 'click') {
57+
clicked = true;
58+
} else if (value == 'rest' && clicked) {
59+
clicked = false;
60+
widget.onPressed?.call();
61+
}
4462
});
4563
}
4664

@@ -51,26 +69,11 @@ class _GameButtonState extends State<GameButton> {
5169
child: SizedBox(
5270
width: 200,
5371
height: 50,
54-
child: RiveAnimation.direct(
55-
_riveFile!,
56-
fit: BoxFit.cover,
57-
stateMachines: const ['Button Animation'],
58-
onInit: (artboard) {
59-
artboard.textRun('buttonText')!.text = widget.text;
60-
controller = StateMachineController.fromArtboard(
61-
artboard,
62-
'Button Animation',
63-
onStateChange: (stateMachine, stateName) {
64-
if (stateName == 'Click') {
65-
clicked = true;
66-
} else if (stateName == 'Rest' && clicked) {
67-
clicked = false;
68-
widget.onPressed?.call();
69-
}
70-
},
71-
);
72-
artboard.addController(controller!);
73-
},
72+
child: RiveWidget(
73+
controller: controller,
74+
fit: Fit.cover,
75+
cursor: SystemMouseCursors.click,
76+
// stateMachines: const ['Button Animation'],
7477
),
7578
),
7679
);

lib/core/extensions/rive_extensions.dart

Lines changed: 0 additions & 6 deletions
This file was deleted.

lib/src/game_play/view/components/hint.dart

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -21,61 +21,68 @@ class Hint extends StatefulWidget {
2121
}
2222

2323
class _HintState extends State<Hint> {
24-
RiveFile? _hintFile;
25-
SMIBool? _luminance;
26-
SMIBool? _theme;
24+
File? _hintFile;
25+
late RiveWidgetController _controller;
26+
late StateMachine? _stateController;
27+
late StateMachine? _themeController;
28+
BooleanInput? _luminance;
29+
BooleanInput? _theme;
2730

2831
@override
2932
void initState() {
3033
super.initState();
3134
preload();
3235
}
3336

34-
void preload() {
35-
rootBundle.load(Media.animatedHint).then((data) {
36-
setState(() {
37-
_hintFile = RiveFile.import(data);
38-
});
39-
});
37+
Future<void> preload() async {
38+
final data = await rootBundle.load(Media.animatedHint);
39+
_hintFile = await File.decode(
40+
data.buffer.asUint8List(),
41+
riveFactory: Factory.rive,
42+
);
43+
_controller = RiveWidgetController(_hintFile!);
44+
_onInit(_controller.artboard);
45+
setState(() {});
4046
}
4147

4248
void _onInit(Artboard artboard) {
43-
final stateController = StateMachineController.fromArtboard(
44-
artboard,
45-
'bulb',
46-
);
47-
final themeController = StateMachineController.fromArtboard(
48-
artboard,
49-
'theme',
50-
);
51-
artboard
52-
..addController(stateController!)
53-
..addController(themeController!);
54-
_luminance = stateController.findInput<bool>('pressed')! as SMIBool;
55-
_theme = themeController.findInput<bool>('isDark')! as SMIBool;
49+
_stateController = artboard.stateMachine('bulb');
50+
_themeController = artboard.stateMachine('theme');
51+
_luminance = _stateController?.boolean('pressed');
52+
_theme = _themeController?.boolean('isDark');
5653
flipBulbByBooster(context.read<UserStatsCubit>().state);
57-
_theme?.change(context.read<ThemeCubit>().state is ThemeStateDark);
54+
_theme?.value = context.read<ThemeCubit>().state is ThemeStateDark;
5855
}
5956

6057
void flipBulbByBooster(UserStatsState statsState) {
6158
final userHasHint = statsState.progress.boosters.any(
6259
(booster) => booster is UseAHint && booster.boosterCount > 0,
6360
);
6461
if (userHasHint) {
65-
_luminance?.change(true);
62+
_luminance?.value = true;
6663
} else {
67-
_luminance?.change(false);
64+
_luminance?.value = false;
6865
}
6966
}
7067

68+
@override
69+
void dispose() {
70+
_controller.dispose();
71+
_stateController?.dispose();
72+
_themeController?.dispose();
73+
_luminance?.dispose();
74+
_theme?.dispose();
75+
super.dispose();
76+
}
77+
7178
@override
7279
Widget build(BuildContext context) {
7380
if (_hintFile == null) return const SizedBox.shrink();
7481
return Tooltip(
7582
message: 'Use a hint',
7683
child: BlocConsumer<ThemeCubit, ThemeState>(
7784
listener: (context, themeState) {
78-
_theme?.change(themeState is ThemeStateDark);
85+
_theme?.value = themeState is ThemeStateDark;
7986
},
8087
builder: (context, themeState) {
8188
return BlocConsumer<UserStatsCubit, UserStatsState>(
@@ -123,11 +130,10 @@ class _HintState extends State<Hint> {
123130
baseline: 45,
124131
child: SizedBox(
125132
width: 50,
126-
child: RiveAnimation.direct(
133+
child: RiveWidget(
127134
key: UniqueKey(),
128-
_hintFile!,
129-
fit: BoxFit.cover,
130-
onInit: _onInit,
135+
controller: _controller,
136+
fit: Fit.cover,
131137
),
132138
),
133139
),

lib/src/level_won/view/level_complete_page.dart

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,46 @@ import 'package:go_router/go_router.dart';
33
import 'package:level_data/level_data.dart';
44
import 'package:rive/rive.dart';
55
import 'package:sozzle/core/common/widgets/sozzle_app_bar.dart';
6+
import 'package:sozzle/core/res/media.dart';
67
import 'package:sozzle/src/game_play/view/game_play_page.dart';
78
import 'package:sozzle/src/home/view/home_page.dart';
89
import 'package:sozzle/src/level_won/level_won.dart';
910

10-
class LevelCompletePage extends StatelessWidget {
11+
class LevelCompletePage extends StatefulWidget {
1112
const LevelCompletePage({required this.levelData, super.key});
1213

1314
static const path = '/won';
1415
final LevelData levelData;
1516

17+
@override
18+
State<LevelCompletePage> createState() => _LevelCompletePageState();
19+
}
20+
21+
class _LevelCompletePageState extends State<LevelCompletePage> {
22+
late File file;
23+
late RiveWidgetController controller;
24+
25+
bool isInitialized = false;
26+
27+
@override
28+
void initState() {
29+
super.initState();
30+
initRive();
31+
}
32+
33+
Future<void> initRive() async {
34+
file = (await File.asset(Media.lake, riveFactory: Factory.rive))!;
35+
controller = RiveWidgetController(file);
36+
setState(() => isInitialized = true);
37+
}
38+
39+
@override
40+
void dispose() {
41+
file.dispose();
42+
controller.dispose();
43+
super.dispose();
44+
}
45+
1646
@override
1747
Widget build(BuildContext context) {
1848
return Scaffold(
@@ -30,10 +60,10 @@ class LevelCompletePage extends StatelessWidget {
3060
builder: (scaffoldContext) {
3161
return Stack(
3262
children: [
33-
const RiveAnimation.asset(
34-
'assets/rive/small_lake_on_a_rainy_day.riv',
35-
fit: BoxFit.cover,
36-
),
63+
if (!isInitialized)
64+
const Center(child: CircularProgressIndicator())
65+
else
66+
RiveWidget(controller: controller, fit: Fit.cover),
3767
Center(
3868
child: SafeArea(
3969
child: Column(
@@ -63,7 +93,7 @@ class LevelCompletePage extends StatelessWidget {
6393
child: NextLevelButton(
6494
onPressed: () {
6595
context.go(
66-
'${GamePlayPage.path}/${levelData.levelId + 1}',
96+
'${GamePlayPage.path}/${widget.levelData.levelId + 1}',
6797
);
6898
},
6999
),

linux/flutter/generated_plugin_registrant.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77
#include "generated_plugin_registrant.h"
88

99
#include <audioplayers_linux/audioplayers_linux_plugin.h>
10-
#include <rive_common/rive_plugin.h>
10+
#include <rive_native/rive_native_plugin.h>
1111

1212
void fl_register_plugins(FlPluginRegistry* registry) {
1313
g_autoptr(FlPluginRegistrar) audioplayers_linux_registrar =
1414
fl_plugin_registry_get_registrar_for_plugin(registry, "AudioplayersLinuxPlugin");
1515
audioplayers_linux_plugin_register_with_registrar(audioplayers_linux_registrar);
16-
g_autoptr(FlPluginRegistrar) rive_common_registrar =
17-
fl_plugin_registry_get_registrar_for_plugin(registry, "RivePlugin");
18-
rive_plugin_register_with_registrar(rive_common_registrar);
16+
g_autoptr(FlPluginRegistrar) rive_native_registrar =
17+
fl_plugin_registry_get_registrar_for_plugin(registry, "RiveNativePlugin");
18+
rive_native_plugin_register_with_registrar(rive_native_registrar);
1919
}

linux/flutter/generated_plugins.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
list(APPEND FLUTTER_PLUGIN_LIST
66
audioplayers_linux
7-
rive_common
7+
rive_native
88
)
99

1010
list(APPEND FLUTTER_FFI_PLUGIN_LIST

macos/Flutter/GeneratedPluginRegistrant.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ import Foundation
77

88
import audioplayers_darwin
99
import path_provider_foundation
10-
import rive_common
10+
import rive_native
1111
import shared_preferences_foundation
1212

1313
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
1414
AudioplayersDarwinPlugin.register(with: registry.registrar(forPlugin: "AudioplayersDarwinPlugin"))
1515
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
16-
RivePlugin.register(with: registry.registrar(forPlugin: "RivePlugin"))
16+
RiveNativePlugin.register(with: registry.registrar(forPlugin: "RiveNativePlugin"))
1717
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
1818
}

0 commit comments

Comments
 (0)