diff --git a/CHANGELOG.md b/CHANGELOG.md index 55cccec..921f30a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [0.7.0-nullsafety.0] - 2021-03-29 16:58:23 + +- NNBD support. +- State Machine runtime support. +- New binary format 7.0 with improved flexibility which is not compatible with 6.0 files. The Rive editor will be able to export both format 6.0 and 7.0, but please note that 6.0 is now deprecated and all new improvements and bug fixes to the format will be done on 7.0. + ## [0.6.8] - 2021-02-12 11:11:11 - Adds support for Flutter's `getMinIntrinsicWidth` (max, height, etc.), e.g. for `IntrinsicWidth` diff --git a/example/assets/rocket.riv b/example/assets/rocket.riv new file mode 100644 index 0000000..dbc9042 Binary files /dev/null and b/example/assets/rocket.riv differ diff --git a/example/lib/example_animation.dart b/example/lib/example_animation.dart new file mode 100644 index 0000000..229672a --- /dev/null +++ b/example/lib/example_animation.dart @@ -0,0 +1,68 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; +import 'package:rive/rive.dart'; + +class ExampleAnimation extends StatefulWidget { + const ExampleAnimation({Key? key}) : super(key: key); + + @override + _ExampleAnimationState createState() => _ExampleAnimationState(); +} + +class _ExampleAnimationState extends State { + void _togglePlay() { + if (_controller == null) { + return; + } + setState(() => _controller!.isActive = !_controller!.isActive); + } + + /// Tracks if the animation is playing by whether controller is running. + bool get isPlaying => _controller?.isActive ?? false; + + Artboard? _riveArtboard; + RiveAnimationController? _controller; + @override + void initState() { + super.initState(); + + // Load the animation file from the bundle, note that you could also + // download this. The RiveFile just expects a list of bytes. + rootBundle.load('assets/dino.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 + // Rive widget. + final artboard = file.mainArtboard; + // Add a controller to play back a known animation on the main/default + // artboard. We store a reference to it so we can toggle playback. + artboard.addController(_controller = SimpleAnimation('Run')); + setState(() => _riveArtboard = artboard); + }, + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Animation Example'), + ), + body: Center( + child: _riveArtboard == null + ? const SizedBox() + : Rive(artboard: _riveArtboard!), + ), + floatingActionButton: FloatingActionButton( + onPressed: _togglePlay, + tooltip: isPlaying ? 'Pause' : 'Play', + child: Icon( + isPlaying ? Icons.pause : Icons.play_arrow, + ), + ), + ); + } +} diff --git a/example/lib/example_state_machine.dart b/example/lib/example_state_machine.dart new file mode 100644 index 0000000..ec8db10 --- /dev/null +++ b/example/lib/example_state_machine.dart @@ -0,0 +1,77 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; +import 'package:rive/rive.dart'; + +class ExampleStateMachine extends StatefulWidget { + const ExampleStateMachine({Key? key}) : super(key: key); + + @override + _ExampleStateMachineState createState() => _ExampleStateMachineState(); +} + +class _ExampleStateMachineState extends State { + /// Tracks if the animation is playing by whether controller is running. + bool get isPlaying => _controller?.isActive ?? false; + + Artboard? _riveArtboard; + StateMachineController? _controller; + StateMachineInput? _hoverInput; + StateMachineInput? _pressInput; + + @override + void initState() { + super.initState(); + + // Load the animation file from the bundle, note that you could also + // download this. The RiveFile just expects a list of bytes. + rootBundle.load('assets/rocket.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 + // Rive widget. + final artboard = file.mainArtboard; + var controller = + StateMachineController.fromArtboard(artboard, 'Button'); + if (controller != null) { + artboard.addController(controller); + _hoverInput = controller.findInput('Hover'); + _pressInput = controller.findInput('Press'); + } + setState(() => _riveArtboard = artboard); + }, + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.grey, + appBar: AppBar( + title: const Text('State Machine Example'), + ), + body: Center( + child: _riveArtboard == null + ? const SizedBox() + : MouseRegion( + onEnter: (_) => _hoverInput?.value = true, + onExit: (_) => _hoverInput?.value = false, + child: GestureDetector( + onTapDown: (_) => _pressInput?.value = true, + onTapCancel: () => _pressInput?.value = false, + onTapUp: (_) => _pressInput?.value = false, + child: SizedBox( + width: 250, + height: 250, + child: Rive( + artboard: _riveArtboard!, + ), + ), + ), + ), + ), + ); + } +} diff --git a/example/lib/main.dart b/example/lib/main.dart index 5705960..a89e7a1 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,77 +1,49 @@ import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:rive/rive.dart'; +import 'package:rive_example/example_animation.dart'; +import 'package:rive_example/example_state_machine.dart'; -void main() => runApp(MyApp()); - -class MyApp extends StatefulWidget { - @override - _MyAppState createState() => _MyAppState(); -} - -class _MyAppState extends State with SingleTickerProviderStateMixin { - @override - Widget build(BuildContext context) { - return const MaterialApp( - home: MyHomePage(), - ); - } -} - -class MyHomePage extends StatefulWidget { - const MyHomePage({Key key}) : super(key: key); - - @override - _MyHomePageState createState() => _MyHomePageState(); -} - -class _MyHomePageState extends State { - void _togglePlay() { - setState(() => _controller.isActive = !_controller.isActive); - } - - /// Tracks if the animation is playing by whether controller is running. - bool get isPlaying => _controller?.isActive ?? false; - - Artboard _riveArtboard; - RiveAnimationController _controller; - @override - void initState() { - super.initState(); - - // Load the animation file from the bundle, note that you could also - // download this. The RiveFile just expects a list of bytes. - rootBundle.load('assets/off_road_car.riv').then( - (data) async { - final file = RiveFile(); - - // Load the RiveFile from the binary data. - if (file.import(data)) { - // The artboard is the root of the animation and gets drawn in the - // Rive widget. - final artboard = file.mainArtboard; - // Add a controller to play back a known animation on the main/default - // artboard.We store a reference to it so we can toggle playback. - artboard.addController(_controller = SimpleAnimation('idle')); - setState(() => _riveArtboard = artboard); - } - }, - ); - } +void main() => runApp(MaterialApp( + title: 'Navigation Basics', + home: Home(), + )); +class Home extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - body: Center( - child: _riveArtboard == null - ? const SizedBox() - : Rive(artboard: _riveArtboard), + appBar: AppBar( + title: const Text('Rive Examples'), ), - floatingActionButton: FloatingActionButton( - onPressed: _togglePlay, - tooltip: isPlaying ? 'Pause' : 'Play', - child: Icon( - isPlaying ? Icons.pause : Icons.play_arrow, + body: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + ElevatedButton( + child: const Text('Animation'), + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const ExampleAnimation(), + ), + ); + }, + ), + const SizedBox( + height: 10, + ), + ElevatedButton( + child: const Text('State Machine'), + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const ExampleStateMachine(), + ), + ); + }, + ), + ], ), ), ); diff --git a/example/macos/Runner.xcodeproj/project.pbxproj b/example/macos/Runner.xcodeproj/project.pbxproj index 2e5079f..cc89c87 100644 --- a/example/macos/Runner.xcodeproj/project.pbxproj +++ b/example/macos/Runner.xcodeproj/project.pbxproj @@ -54,7 +54,7 @@ /* Begin PBXFileReference section */ 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; - 33CC10ED2044A3C60003C045 /* rive_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "rive_example.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10ED2044A3C60003C045 /* example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "example.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; @@ -105,7 +105,7 @@ 33CC10EE2044A3C60003C045 /* Products */ = { isa = PBXGroup; children = ( - 33CC10ED2044A3C60003C045 /* rive_example.app */, + 33CC10ED2044A3C60003C045 /* example.app */, ); name = Products; sourceTree = ""; @@ -172,7 +172,7 @@ ); name = Runner; productName = Runner; - productReference = 33CC10ED2044A3C60003C045 /* rive_example.app */; + productReference = 33CC10ED2044A3C60003C045 /* example.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ @@ -183,7 +183,7 @@ attributes = { LastSwiftUpdateCheck = 0920; LastUpgradeCheck = 0930; - ORGANIZATIONNAME = "The Flutter Authors"; + ORGANIZATIONNAME = ""; TargetAttributes = { 33CC10EC2044A3C60003C045 = { CreatedOnToolsVersion = 9.2; @@ -202,7 +202,7 @@ }; }; buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; - compatibilityVersion = "Xcode 8.0"; + compatibilityVersion = "Xcode 9.3"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( @@ -268,7 +268,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh\ntouch Flutter/ephemeral/tripwire\n"; + shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; }; /* End PBXShellScriptBuildPhase section */ @@ -361,10 +361,6 @@ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter/ephemeral", - ); INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -491,10 +487,6 @@ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter/ephemeral", - ); INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -515,10 +507,6 @@ CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter/ephemeral", - ); INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", diff --git a/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index ac06267..ae8ff59 100644 --- a/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -15,7 +15,7 @@ @@ -27,23 +27,11 @@ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" shouldUseLaunchSchemeArgsEnv = "YES"> - - - - - - @@ -66,7 +54,7 @@ @@ -75,7 +63,7 @@ diff --git a/example/macos/Runner/Configs/AppInfo.xcconfig b/example/macos/Runner/Configs/AppInfo.xcconfig index 37afbe8..cf9be60 100644 --- a/example/macos/Runner/Configs/AppInfo.xcconfig +++ b/example/macos/Runner/Configs/AppInfo.xcconfig @@ -5,10 +5,10 @@ // 'flutter create' template. // The application's name. By default this is also the title of the Flutter window. -PRODUCT_NAME = rive_example +PRODUCT_NAME = example // The application's bundle identifier -PRODUCT_BUNDLE_IDENTIFIER = com.example.riveExample +PRODUCT_BUNDLE_IDENTIFIER = com.example.example // The copyright displayed in application information -PRODUCT_COPYRIGHT = Copyright © 2020 com.example. All rights reserved. +PRODUCT_COPYRIGHT = Copyright © 2021 com.example. All rights reserved. diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 9454133..3e4cdad 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -1,12 +1,12 @@ name: rive_example description: A new Flutter project. -publish_to: 'none' # Remove this line if you wish to publish to pub.dev +publish_to: "none" # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: - sdk: ">=2.7.0 <3.0.0" + sdk: ">=2.12.0 <3.0.0" dependencies: flutter: diff --git a/lib/rive.dart b/lib/rive.dart index ccba7da..a9eff5b 100644 --- a/lib/rive.dart +++ b/lib/rive.dart @@ -1,20 +1,23 @@ library rive; -export 'package:rive/src/rive_file.dart'; -export 'package:rive/src/rive.dart'; -export 'package:rive/src/runtime_artboard.dart'; export 'package:rive/src/controllers/simple_controller.dart'; -export 'package:rive/src/rive_core/rive_animation_controller.dart'; +export 'package:rive/src/extensions.dart'; +export 'package:rive/src/extensions.dart'; +export 'package:rive/src/rive.dart'; export 'package:rive/src/rive_core/animation/linear_animation.dart'; export 'package:rive/src/rive_core/animation/linear_animation_instance.dart'; export 'package:rive/src/rive_core/animation/loop.dart'; +export 'package:rive/src/rive_core/animation/state_machine.dart'; export 'package:rive/src/rive_core/artboard.dart'; -export 'package:rive/src/rive_core/shapes/shape.dart'; -export 'package:rive/src/rive_core/shapes/paint/fill.dart'; -export 'package:rive/src/rive_core/shapes/paint/stroke.dart'; -export 'package:rive/src/rive_core/shapes/paint/solid_color.dart'; -export 'package:rive/src/rive_core/shapes/paint/linear_gradient.dart'; -export 'package:rive/src/rive_core/shapes/paint/radial_gradient.dart'; +export 'package:rive/src/rive_core/rive_animation_controller.dart'; export 'package:rive/src/rive_core/runtime/runtime_header.dart' show riveVersion; -export 'package:rive/src/extensions.dart'; +export 'package:rive/src/rive_core/shapes/paint/fill.dart'; +export 'package:rive/src/rive_core/shapes/paint/linear_gradient.dart'; +export 'package:rive/src/rive_core/shapes/paint/radial_gradient.dart'; +export 'package:rive/src/rive_core/shapes/paint/solid_color.dart'; +export 'package:rive/src/rive_core/shapes/paint/stroke.dart'; +export 'package:rive/src/rive_core/shapes/shape.dart'; +export 'package:rive/src/rive_file.dart'; +export 'package:rive/src/runtime_artboard.dart'; +export 'package:rive/src/state_machine_controller.dart'; diff --git a/lib/src/animation_list.dart b/lib/src/animation_list.dart index cbf095c..ef0d250 100644 --- a/lib/src/animation_list.dart +++ b/lib/src/animation_list.dart @@ -1,10 +1,10 @@ import 'dart:collection'; import 'package:rive/src/rive_core/animation/animation.dart'; -// TODO: figure out how to make this cleaner. class AnimationList extends ListBase { - final List _values = []; - List get values => _values; + // Lame way to do this due to how ListBase needs to expand a nullable list. + final List _values = []; + List get values => _values.cast(); @override int get length => _values.length; @@ -13,7 +13,7 @@ class AnimationList extends ListBase { set length(int value) => _values.length = value; @override - Animation operator [](int index) => _values[index]; + Animation operator [](int index) => _values[index]!; @override void operator []=(int index, Animation value) => _values[index] = value; diff --git a/lib/src/container_children.dart b/lib/src/container_children.dart index cfe9c75..7287fd5 100644 --- a/lib/src/container_children.dart +++ b/lib/src/container_children.dart @@ -3,8 +3,8 @@ import 'package:rive/src/rive_core/component.dart'; // TODO: figure out how to make this cleaner. class ContainerChildren extends ListBase { - final List _values = []; - List get values => _values; + final List _values = []; + List get values => _values.cast(); @override int get length => _values.length; @@ -13,7 +13,7 @@ class ContainerChildren extends ListBase { set length(int value) => _values.length = value; @override - Component operator [](int index) => _values[index]; + Component operator [](int index) => _values[index]!; @override void operator []=(int index, Component value) => _values[index] = value; diff --git a/lib/src/controllers/simple_controller.dart b/lib/src/controllers/simple_controller.dart index ec931e6..784e534 100644 --- a/lib/src/controllers/simple_controller.dart +++ b/lib/src/controllers/simple_controller.dart @@ -1,43 +1,37 @@ -import 'package:rive/src/rive_core/animation/linear_animation.dart'; +import 'package:rive/src/extensions.dart'; import 'package:rive/src/rive_core/animation/linear_animation_instance.dart'; import 'package:rive/src/rive_core/rive_animation_controller.dart'; import 'package:rive/src/runtime_artboard.dart'; /// A simple [RiveAnimationController] that plays back a LinearAnimation defined /// by an artist. All playback parameters (looping, speed, keyframes) are artist -/// defined in the Rive editor. +/// defined in the Rive editor. This takes a declaritive approach of using an +/// [animationName] as the only requirement for resolving the animation. When +/// the controller is added to an artboard (note that due to widget lifecycles +/// it could get re-initialized on another artboard later) it'll look for the +/// animation. Not finding the animation is a condition this example deals with +/// by simply nulling the [AnimationInstance] _instance which means it won't be +/// applied during advance cycles. Another approach would be let this throw, but +/// this one is a little more forgiving which can be desireable with files +/// dynamically loaded (downloaded even) at runtime. class SimpleAnimation extends RiveAnimationController { - SimpleAnimation(this.animationName, {double mix}) - : _mix = mix?.clamp(0, 1)?.toDouble() ?? 1.0; + LinearAnimationInstance? _instance; - LinearAnimationInstance _instance; final String animationName; bool _stopOnNextApply = false; + double _mix; // Controls the level of mix for the animation, clamped between 0 and 1 - double _mix; + SimpleAnimation(this.animationName, {double mix = 1}) + : _mix = mix.clamp(0, 1).toDouble(); + LinearAnimationInstance? get instance => _instance; double get mix => _mix; - set mix(double value) => _mix = value?.clamp(0, 1)?.toDouble() ?? 1; - LinearAnimationInstance get instance => _instance; - - @override - bool init(RuntimeArtboard artboard) { - var animation = artboard.animations.firstWhere( - (animation) => - animation is LinearAnimation && animation.name == animationName, - orElse: () => null, - ); - if (animation != null) { - _instance = LinearAnimationInstance(animation as LinearAnimation); - } - isActive = true; - return _instance != null; - } + set mix(double value) => _mix = value.clamp(0, 1).toDouble(); @override void apply(RuntimeArtboard artboard, double elapsedSeconds) { - if (_stopOnNextApply) { + if (_stopOnNextApply || _instance == null) { isActive = false; } @@ -47,12 +41,20 @@ class SimpleAnimation extends RiveAnimationController { // stopping playback. We do this by tracking _stopOnNextApply making sure to // reset it when the controller is re-activated. Fixes #28 and should help // with issues #51 and #56. - _instance.animation.apply(_instance.time, coreContext: artboard, mix: mix); - if (!_instance.advance(elapsedSeconds)) { + _instance!.animation + .apply(_instance!.time, coreContext: artboard, mix: mix); + if (!_instance!.advance(elapsedSeconds)) { _stopOnNextApply = true; } } + @override + bool init(RuntimeArtboard artboard) { + _instance = artboard.animationByName(animationName); + isActive = true; + return _instance != null; + } + @override void onActivate() { // We override onActivate to reset stopOnNextApply. This ensures that when diff --git a/lib/src/core/core.dart b/lib/src/core/core.dart index 91c7921..8635b7c 100644 --- a/lib/src/core/core.dart +++ b/lib/src/core/core.dart @@ -1,29 +1,111 @@ +import 'dart:collection'; + +import 'package:rive/src/rive_core/runtime/exceptions/rive_format_error_exception.dart'; + export 'package:rive/src/animation_list.dart'; +export 'package:rive/src/state_machine_components.dart'; +export 'package:rive/src/state_transition_conditions.dart'; export 'package:rive/src/container_children.dart'; export 'package:rive/src/runtime_artboard.dart'; export 'package:rive/src/generated/rive_core_context.dart'; +export 'package:rive/src/core/importers/artboard_importer.dart'; +export 'package:rive/src/core/importers/linear_animation_importer.dart'; +export 'package:rive/src/core/importers/keyed_object_importer.dart'; +export 'package:rive/src/core/importers/keyed_property_importer.dart'; +export 'package:rive/src/core/importers/state_machine_importer.dart'; +export 'package:rive/src/core/importers/state_machine_layer_importer.dart'; +export 'package:rive/src/core/importers/layer_state_importer.dart'; +export 'package:rive/src/core/importers/state_transition_importer.dart'; typedef PropertyChangeCallback = void Function(dynamic from, dynamic to); typedef BatchAddCallback = void Function(); abstract class Core { - covariant T context; + static const int missingId = -1; + covariant late T context; int get coreType; - int id; + int id = missingId; Set get coreTypes => {}; + bool _hasValidated = false; + bool get hasValidated => _hasValidated; void onAddedDirty(); - void onAdded(); - void onRemoved(); + void onAdded() {} + void onRemoved() {} + void remove() => context.removeObject(this); + bool import(ImportStack stack) => true; + + bool validate() => true; +} + +class InternalCoreHelper { + static void markValid(Core object) { + object._hasValidated = true; + } } abstract class CoreContext { - Core makeCoreInstance(int typeKey); - T resolve(int id); + static const int invalidPropertyKey = 0; + + Core? makeCoreInstance(int typeKey); + T? resolve(int id); + T resolveWithDefault(int id, T defaultValue); void markDependencyOrderDirty(); bool markDependenciesDirty(covariant Core rootObject); void removeObject(T object); - T addObject(T object); + T? addObject(T? object); void markNeedsAdvance(); void dirty(void Function() dirt); } + +// ignore: one_member_abstracts +abstract class ImportStackObject { + bool resolve(); +} + +/// Stack to help the RiveFile locate latest ImportStackObject created of a +/// certain type. +class ImportStack { + final _latests = HashMap(); + T? latest(int coreType) { + var latest = _latests[coreType]; + if (latest is T) { + return latest; + } + return null; + } + + T requireLatest(int coreType) { + var object = latest(coreType); + if (object == null) { + throw RiveFormatErrorException( + 'Rive file is corrupt. Couldn\'t find expected object of type ' + '$coreType in import stack.'); + } + return object; + } + + bool makeLatest(int coreType, ImportStackObject? importObject) { + var latest = _latests[coreType]; + if (latest != null) { + if (!latest.resolve()) { + return false; + } + } + if (importObject != null) { + _latests[coreType] = importObject; + } else { + _latests.remove(coreType); + } + return true; + } + + bool resolve() { + for (final object in _latests.values) { + if (!object.resolve()) { + return false; + } + } + return true; + } +} diff --git a/lib/src/core/field_types/core_field_type.dart b/lib/src/core/field_types/core_field_type.dart index a123e05..da10238 100644 --- a/lib/src/core/field_types/core_field_type.dart +++ b/lib/src/core/field_types/core_field_type.dart @@ -1,6 +1,6 @@ import 'package:rive/src/utilities/binary_buffer/binary_reader.dart'; // ignore: one_member_abstracts -abstract class CoreFieldType { +abstract class CoreFieldType { T deserialize(BinaryReader reader); } diff --git a/lib/src/core/importers/artboard_importer.dart b/lib/src/core/importers/artboard_importer.dart new file mode 100644 index 0000000..79c847c --- /dev/null +++ b/lib/src/core/importers/artboard_importer.dart @@ -0,0 +1,44 @@ +import 'package:rive/rive.dart'; +import 'package:rive/src/core/core.dart'; +import 'package:rive/src/rive_core/animation/animation.dart'; +import 'package:rive/src/rive_core/animation/state_machine.dart'; +import 'package:rive/src/rive_core/component.dart'; + +class ArtboardImporter extends ImportStackObject { + final RuntimeArtboard artboard; + ArtboardImporter(this.artboard); + final List animations = []; + + void addComponent(Core? object) => artboard.addObject(object); + + void addAnimation(Animation animation) { + if (animation is LinearAnimation) { + animations.add(animation); + } + artboard.addObject(animation); + animation.artboard = artboard; + } + + void addStateMachine(StateMachine animation) => addAnimation(animation); + + @override + bool resolve() { + for (final object in artboard.objects.skip(1)) { + if (object is Component && + object.parentId == ComponentBase.parentIdInitialValue) { + object.parent = artboard; + } + object?.onAddedDirty(); + } + assert(!artboard.children.contains(artboard), + 'artboard should never contain itself as a child'); + for (final object in artboard.objects.toList(growable: false)) { + if (object == null) { + continue; + } + object.onAdded(); + } + artboard.clean(); + return true; + } +} diff --git a/lib/src/core/importers/keyed_object_importer.dart b/lib/src/core/importers/keyed_object_importer.dart new file mode 100644 index 0000000..67d990c --- /dev/null +++ b/lib/src/core/importers/keyed_object_importer.dart @@ -0,0 +1,17 @@ +import 'package:rive/src/core/core.dart'; +import 'package:rive/src/rive_core/animation/keyed_object.dart'; +import 'package:rive/src/rive_core/animation/keyed_property.dart'; + +class KeyedObjectImporter extends ImportStackObject { + final KeyedObject keyedObject; + + KeyedObjectImporter(this.keyedObject); + + void addKeyedProperty(KeyedProperty property) { + keyedObject.context.addObject(property); + keyedObject.internalAddKeyedProperty(property); + } + + @override + bool resolve() => true; +} diff --git a/lib/src/core/importers/keyed_property_importer.dart b/lib/src/core/importers/keyed_property_importer.dart new file mode 100644 index 0000000..1d9d7c2 --- /dev/null +++ b/lib/src/core/importers/keyed_property_importer.dart @@ -0,0 +1,20 @@ +import 'package:rive/src/core/core.dart'; +import 'package:rive/src/rive_core/animation/keyed_property.dart'; +import 'package:rive/src/rive_core/animation/keyframe.dart'; +import 'package:rive/src/rive_core/animation/linear_animation.dart'; + +class KeyedPropertyImporter extends ImportStackObject { + final KeyedProperty keyedProperty; + final LinearAnimation animation; + + KeyedPropertyImporter(this.keyedProperty, this.animation); + + void addKeyFrame(KeyFrame keyFrame) { + keyedProperty.context.addObject(keyFrame); + keyedProperty.internalAddKeyFrame(keyFrame); + keyFrame.computeSeconds(animation); + } + + @override + bool resolve() => true; +} diff --git a/lib/src/core/importers/layer_state_importer.dart b/lib/src/core/importers/layer_state_importer.dart new file mode 100644 index 0000000..5ca93d2 --- /dev/null +++ b/lib/src/core/importers/layer_state_importer.dart @@ -0,0 +1,16 @@ +import 'package:rive/src/core/core.dart'; +import 'package:rive/src/rive_core/animation/layer_state.dart'; +import 'package:rive/src/rive_core/animation/state_transition.dart'; + +class LayerStateImporter extends ImportStackObject { + final LayerState state; + LayerStateImporter(this.state); + + void addTransition(StateTransition transition) { + state.context.addObject(transition); + state.internalAddTransition(transition); + } + + @override + bool resolve() => true; +} diff --git a/lib/src/core/importers/linear_animation_importer.dart b/lib/src/core/importers/linear_animation_importer.dart new file mode 100644 index 0000000..999b55c --- /dev/null +++ b/lib/src/core/importers/linear_animation_importer.dart @@ -0,0 +1,25 @@ +import 'package:rive/rive.dart'; +import 'package:rive/src/core/core.dart'; +import 'package:rive/src/rive_core/animation/keyed_object.dart'; + +class LinearAnimationImporter extends ImportStackObject { + final LinearAnimation linearAnimation; + // final keyedObjects = []; + + LinearAnimationImporter(this.linearAnimation); + + void addKeyedObject(KeyedObject object) { + linearAnimation.context.addObject(object); + + // keyedObjects.add(object); + linearAnimation.internalAddKeyedObject(object); + } + + @override + bool resolve() { + // for (final keyedObject in keyedObjects) { + // keyedObject.objectId ??= linearAnimation.artboard.id; + // } + return true; + } +} diff --git a/lib/src/core/importers/state_machine_importer.dart b/lib/src/core/importers/state_machine_importer.dart new file mode 100644 index 0000000..881a6dd --- /dev/null +++ b/lib/src/core/importers/state_machine_importer.dart @@ -0,0 +1,16 @@ +import 'package:rive/src/core/core.dart'; +import 'package:rive/src/rive_core/animation/state_machine.dart'; +import 'package:rive/src/rive_core/animation/state_machine_component.dart'; + +class StateMachineImporter extends ImportStackObject { + final StateMachine machine; + StateMachineImporter(this.machine); + + void addMachineComponent(StateMachineComponent object) { + machine.context.addObject(object); + object.stateMachine = machine; + } + + @override + bool resolve() => true; +} diff --git a/lib/src/core/importers/state_machine_layer_importer.dart b/lib/src/core/importers/state_machine_layer_importer.dart new file mode 100644 index 0000000..ff358db --- /dev/null +++ b/lib/src/core/importers/state_machine_layer_importer.dart @@ -0,0 +1,45 @@ +import 'package:rive/src/core/core.dart'; +import 'package:rive/src/rive_core/animation/animation_state.dart'; +import 'package:rive/src/rive_core/animation/layer_state.dart'; +import 'package:rive/src/rive_core/animation/state_machine_layer.dart'; + +class StateMachineLayerImporter extends ImportStackObject { + final StateMachineLayer layer; + final ArtboardImporter artboardImporter; + StateMachineLayerImporter(this.layer, this.artboardImporter); + + final List importedStates = []; + + void addState(LayerState state) { + importedStates.add(state); + // Here the state gets assigned a core (artboard) id. + layer.context.addObject(state); + layer.internalAddState(state); + } + + bool _resolved = false; + @override + bool resolve() { + assert(!_resolved); + _resolved = true; + for (final state in importedStates) { + if (state is AnimationState) { + int artboardAnimationIndex = state.animationId; + assert(artboardAnimationIndex >= 0 && + artboardAnimationIndex < artboardImporter.animations.length); + state.animation = artboardImporter.animations[artboardAnimationIndex]; + } + for (final transition in state.transitions) { + // At import time the stateToId is an index relative to the entire layer + // (which state in this layer). We can use that to find the matching + // importedState and assign back the core id that will resolve after the + // entire artboard imports. + assert(transition.stateToId >= 0 && + transition.stateToId < importedStates.length); + // transition.stateToId = importedStates[transition.stateToId].id; + transition.stateTo = importedStates[transition.stateToId]; + } + } + return true; + } +} diff --git a/lib/src/core/importers/state_transition_importer.dart b/lib/src/core/importers/state_transition_importer.dart new file mode 100644 index 0000000..416343f --- /dev/null +++ b/lib/src/core/importers/state_transition_importer.dart @@ -0,0 +1,25 @@ +import 'package:rive/src/core/core.dart'; +import 'package:rive/src/rive_core/animation/state_transition.dart'; +import 'package:rive/src/rive_core/animation/transition_condition.dart'; + +class StateTransitionImporter extends ImportStackObject { + final StateMachineImporter stateMachineImporter; + final StateTransition transition; + StateTransitionImporter(this.transition, this.stateMachineImporter); + + void addCondition(TransitionCondition condition) { + transition.context.addObject(condition); + transition.internalAddCondition(condition); + } + + @override + bool resolve() { + var inputs = stateMachineImporter.machine.inputs; + for (final condition in transition.conditions) { + var inputIndex = condition.inputId; + assert(inputIndex >= 0 && inputIndex < inputs.length); + condition.inputId = inputs[inputIndex].id; + } + return true; + } +} diff --git a/lib/src/extensions.dart b/lib/src/extensions.dart index 198a430..3bdc72f 100644 --- a/lib/src/extensions.dart +++ b/lib/src/extensions.dart @@ -1,18 +1,16 @@ /// Extensions to the runtime core classes - -import 'package:rive/src/rive_core/artboard.dart'; +import 'package:collection/collection.dart'; import 'package:rive/src/rive_core/animation/linear_animation.dart'; import 'package:rive/src/rive_core/animation/linear_animation_instance.dart'; +import 'package:rive/src/rive_core/artboard.dart'; /// Artboard extensions extension ArtboardAdditions on Artboard { /// Returns an animation with the given name, or null if no animation with /// that name exists in the artboard - LinearAnimationInstance animationByName(String name) { - final animation = animations.firstWhere( - (animation) => animation is LinearAnimation && animation.name == name, - orElse: () => null, - ); + LinearAnimationInstance? animationByName(String name) { + final animation = animations.firstWhereOrNull( + (animation) => animation is LinearAnimation && animation.name == name); if (animation != null) { return LinearAnimationInstance(animation as LinearAnimation); } diff --git a/lib/src/generated/animation/animation_base.dart b/lib/src/generated/animation/animation_base.dart index 60ebe7f..dc26616 100644 --- a/lib/src/generated/animation/animation_base.dart +++ b/lib/src/generated/animation/animation_base.dart @@ -13,7 +13,8 @@ abstract class AnimationBase extends Core { /// -------------------------------------------------------------------------- /// Name field with key 55. - String _name; + static const String nameInitialValue = ''; + String _name = nameInitialValue; static const int namePropertyKey = 55; /// Name of the animation. @@ -27,7 +28,9 @@ abstract class AnimationBase extends Core { } String from = _name; _name = value; - nameChanged(from, value); + if (hasValidated) { + nameChanged(from, value); + } } void nameChanged(String from, String to); diff --git a/lib/src/generated/animation/animation_state_base.dart b/lib/src/generated/animation/animation_state_base.dart new file mode 100644 index 0000000..c91877e --- /dev/null +++ b/lib/src/generated/animation/animation_state_base.dart @@ -0,0 +1,44 @@ +/// Core automatically generated +/// lib/src/generated/animation/animation_state_base.dart. +/// Do not modify manually. + +import 'package:rive/src/generated/animation/layer_state_base.dart'; +import 'package:rive/src/generated/animation/state_machine_layer_component_base.dart'; +import 'package:rive/src/rive_core/animation/layer_state.dart'; + +abstract class AnimationStateBase extends LayerState { + static const int typeKey = 61; + @override + int get coreType => AnimationStateBase.typeKey; + @override + Set get coreTypes => { + AnimationStateBase.typeKey, + LayerStateBase.typeKey, + StateMachineLayerComponentBase.typeKey + }; + + /// -------------------------------------------------------------------------- + /// AnimationId field with key 149. + static const int animationIdInitialValue = -1; + int _animationId = animationIdInitialValue; + static const int animationIdPropertyKey = 149; + + /// Id of the animation this layer state refers to. + int get animationId => _animationId; + + /// Change the [_animationId] field value. + /// [animationIdChanged] will be invoked only if the field's value has + /// changed. + set animationId(int value) { + if (_animationId == value) { + return; + } + int from = _animationId; + _animationId = value; + if (hasValidated) { + animationIdChanged(from, value); + } + } + + void animationIdChanged(int from, int to); +} diff --git a/lib/src/generated/animation/any_state_base.dart b/lib/src/generated/animation/any_state_base.dart new file mode 100644 index 0000000..7c35b97 --- /dev/null +++ b/lib/src/generated/animation/any_state_base.dart @@ -0,0 +1,19 @@ +/// Core automatically generated +/// lib/src/generated/animation/any_state_base.dart. +/// Do not modify manually. + +import 'package:rive/src/generated/animation/layer_state_base.dart'; +import 'package:rive/src/generated/animation/state_machine_layer_component_base.dart'; +import 'package:rive/src/rive_core/animation/layer_state.dart'; + +abstract class AnyStateBase extends LayerState { + static const int typeKey = 62; + @override + int get coreType => AnyStateBase.typeKey; + @override + Set get coreTypes => { + AnyStateBase.typeKey, + LayerStateBase.typeKey, + StateMachineLayerComponentBase.typeKey + }; +} diff --git a/lib/src/generated/animation/cubic_interpolator_base.dart b/lib/src/generated/animation/cubic_interpolator_base.dart index a3ebd40..f847649 100644 --- a/lib/src/generated/animation/cubic_interpolator_base.dart +++ b/lib/src/generated/animation/cubic_interpolator_base.dart @@ -13,7 +13,8 @@ abstract class CubicInterpolatorBase extends Core { /// -------------------------------------------------------------------------- /// X1 field with key 63. - double _x1 = 0.42; + static const double x1InitialValue = 0.42; + double _x1 = x1InitialValue; static const int x1PropertyKey = 63; double get x1 => _x1; @@ -25,14 +26,17 @@ abstract class CubicInterpolatorBase extends Core { } double from = _x1; _x1 = value; - x1Changed(from, value); + if (hasValidated) { + x1Changed(from, value); + } } void x1Changed(double from, double to); /// -------------------------------------------------------------------------- /// Y1 field with key 64. - double _y1 = 0; + static const double y1InitialValue = 0; + double _y1 = y1InitialValue; static const int y1PropertyKey = 64; double get y1 => _y1; @@ -44,14 +48,17 @@ abstract class CubicInterpolatorBase extends Core { } double from = _y1; _y1 = value; - y1Changed(from, value); + if (hasValidated) { + y1Changed(from, value); + } } void y1Changed(double from, double to); /// -------------------------------------------------------------------------- /// X2 field with key 65. - double _x2 = 0.58; + static const double x2InitialValue = 0.58; + double _x2 = x2InitialValue; static const int x2PropertyKey = 65; double get x2 => _x2; @@ -63,14 +70,17 @@ abstract class CubicInterpolatorBase extends Core { } double from = _x2; _x2 = value; - x2Changed(from, value); + if (hasValidated) { + x2Changed(from, value); + } } void x2Changed(double from, double to); /// -------------------------------------------------------------------------- /// Y2 field with key 66. - double _y2 = 1; + static const double y2InitialValue = 1; + double _y2 = y2InitialValue; static const int y2PropertyKey = 66; double get y2 => _y2; @@ -82,7 +92,9 @@ abstract class CubicInterpolatorBase extends Core { } double from = _y2; _y2 = value; - y2Changed(from, value); + if (hasValidated) { + y2Changed(from, value); + } } void y2Changed(double from, double to); diff --git a/lib/src/generated/animation/entry_state_base.dart b/lib/src/generated/animation/entry_state_base.dart new file mode 100644 index 0000000..f2b1bd2 --- /dev/null +++ b/lib/src/generated/animation/entry_state_base.dart @@ -0,0 +1,19 @@ +/// Core automatically generated +/// lib/src/generated/animation/entry_state_base.dart. +/// Do not modify manually. + +import 'package:rive/src/generated/animation/layer_state_base.dart'; +import 'package:rive/src/generated/animation/state_machine_layer_component_base.dart'; +import 'package:rive/src/rive_core/animation/layer_state.dart'; + +abstract class EntryStateBase extends LayerState { + static const int typeKey = 63; + @override + int get coreType => EntryStateBase.typeKey; + @override + Set get coreTypes => { + EntryStateBase.typeKey, + LayerStateBase.typeKey, + StateMachineLayerComponentBase.typeKey + }; +} diff --git a/lib/src/generated/animation/exit_state_base.dart b/lib/src/generated/animation/exit_state_base.dart new file mode 100644 index 0000000..939ae6f --- /dev/null +++ b/lib/src/generated/animation/exit_state_base.dart @@ -0,0 +1,19 @@ +/// Core automatically generated +/// lib/src/generated/animation/exit_state_base.dart. +/// Do not modify manually. + +import 'package:rive/src/generated/animation/layer_state_base.dart'; +import 'package:rive/src/generated/animation/state_machine_layer_component_base.dart'; +import 'package:rive/src/rive_core/animation/layer_state.dart'; + +abstract class ExitStateBase extends LayerState { + static const int typeKey = 64; + @override + int get coreType => ExitStateBase.typeKey; + @override + Set get coreTypes => { + ExitStateBase.typeKey, + LayerStateBase.typeKey, + StateMachineLayerComponentBase.typeKey + }; +} diff --git a/lib/src/generated/animation/keyed_object_base.dart b/lib/src/generated/animation/keyed_object_base.dart index 9baa2ec..f2d6f45 100644 --- a/lib/src/generated/animation/keyed_object_base.dart +++ b/lib/src/generated/animation/keyed_object_base.dart @@ -13,7 +13,8 @@ abstract class KeyedObjectBase extends Core { /// -------------------------------------------------------------------------- /// ObjectId field with key 51. - int _objectId; + static const int objectIdInitialValue = 0; + int _objectId = objectIdInitialValue; static const int objectIdPropertyKey = 51; /// Identifier used to track the object that is keyed. @@ -27,7 +28,9 @@ abstract class KeyedObjectBase extends Core { } int from = _objectId; _objectId = value; - objectIdChanged(from, value); + if (hasValidated) { + objectIdChanged(from, value); + } } void objectIdChanged(int from, int to); diff --git a/lib/src/generated/animation/keyed_property_base.dart b/lib/src/generated/animation/keyed_property_base.dart index 0d1361c..86e7619 100644 --- a/lib/src/generated/animation/keyed_property_base.dart +++ b/lib/src/generated/animation/keyed_property_base.dart @@ -13,7 +13,8 @@ abstract class KeyedPropertyBase extends Core { /// -------------------------------------------------------------------------- /// PropertyKey field with key 53. - int _propertyKey; + static const int propertyKeyInitialValue = CoreContext.invalidPropertyKey; + int _propertyKey = propertyKeyInitialValue; static const int propertyKeyPropertyKey = 53; /// The property type that is keyed. @@ -28,7 +29,9 @@ abstract class KeyedPropertyBase extends Core { } int from = _propertyKey; _propertyKey = value; - propertyKeyChanged(from, value); + if (hasValidated) { + propertyKeyChanged(from, value); + } } void propertyKeyChanged(int from, int to); diff --git a/lib/src/generated/animation/keyframe_base.dart b/lib/src/generated/animation/keyframe_base.dart index 1d123cf..233b638 100644 --- a/lib/src/generated/animation/keyframe_base.dart +++ b/lib/src/generated/animation/keyframe_base.dart @@ -12,7 +12,8 @@ abstract class KeyFrameBase extends Core { /// -------------------------------------------------------------------------- /// Frame field with key 67. - int _frame; + static const int frameInitialValue = 0; + int _frame = frameInitialValue; static const int framePropertyKey = 67; /// Timecode as frame number can be converted to time by dividing by animation @@ -27,14 +28,17 @@ abstract class KeyFrameBase extends Core { } int from = _frame; _frame = value; - frameChanged(from, value); + if (hasValidated) { + frameChanged(from, value); + } } void frameChanged(int from, int to); /// -------------------------------------------------------------------------- /// InterpolationType field with key 68. - int _interpolationType; + static const int interpolationTypeInitialValue = 0; + int _interpolationType = interpolationTypeInitialValue; static const int interpolationTypePropertyKey = 68; /// The type of interpolation index in KeyframeInterpolation applied to this @@ -50,14 +54,17 @@ abstract class KeyFrameBase extends Core { } int from = _interpolationType; _interpolationType = value; - interpolationTypeChanged(from, value); + if (hasValidated) { + interpolationTypeChanged(from, value); + } } void interpolationTypeChanged(int from, int to); /// -------------------------------------------------------------------------- /// InterpolatorId field with key 69. - int _interpolatorId; + static const int interpolatorIdInitialValue = -1; + int _interpolatorId = interpolatorIdInitialValue; static const int interpolatorIdPropertyKey = 69; /// The id of the custom interpolator used when interpolation is Cubic. @@ -72,7 +79,9 @@ abstract class KeyFrameBase extends Core { } int from = _interpolatorId; _interpolatorId = value; - interpolatorIdChanged(from, value); + if (hasValidated) { + interpolatorIdChanged(from, value); + } } void interpolatorIdChanged(int from, int to); diff --git a/lib/src/generated/animation/keyframe_color_base.dart b/lib/src/generated/animation/keyframe_color_base.dart index a0e97b7..d2a2e1d 100644 --- a/lib/src/generated/animation/keyframe_color_base.dart +++ b/lib/src/generated/animation/keyframe_color_base.dart @@ -14,7 +14,8 @@ abstract class KeyFrameColorBase extends KeyFrame { /// -------------------------------------------------------------------------- /// Value field with key 88. - int _value; + static const int valueInitialValue = 0; + int _value = valueInitialValue; static const int valuePropertyKey = 88; int get value => _value; @@ -26,7 +27,9 @@ abstract class KeyFrameColorBase extends KeyFrame { } int from = _value; _value = value; - valueChanged(from, value); + if (hasValidated) { + valueChanged(from, value); + } } void valueChanged(int from, int to); diff --git a/lib/src/generated/animation/keyframe_double_base.dart b/lib/src/generated/animation/keyframe_double_base.dart index 7598695..ff00757 100644 --- a/lib/src/generated/animation/keyframe_double_base.dart +++ b/lib/src/generated/animation/keyframe_double_base.dart @@ -14,7 +14,8 @@ abstract class KeyFrameDoubleBase extends KeyFrame { /// -------------------------------------------------------------------------- /// Value field with key 70. - double _value; + static const double valueInitialValue = 0; + double _value = valueInitialValue; static const int valuePropertyKey = 70; double get value => _value; @@ -26,7 +27,9 @@ abstract class KeyFrameDoubleBase extends KeyFrame { } double from = _value; _value = value; - valueChanged(from, value); + if (hasValidated) { + valueChanged(from, value); + } } void valueChanged(double from, double to); diff --git a/lib/src/generated/animation/keyframe_draw_order_base.dart b/lib/src/generated/animation/keyframe_draw_order_base.dart deleted file mode 100644 index 9fc13ae..0000000 --- a/lib/src/generated/animation/keyframe_draw_order_base.dart +++ /dev/null @@ -1,15 +0,0 @@ -/// Core automatically generated -/// lib/src/generated/animation/keyframe_draw_order_base.dart. -/// Do not modify manually. - -import 'package:rive/src/generated/animation/keyframe_base.dart'; -import 'package:rive/src/rive_core/animation/keyframe.dart'; - -abstract class KeyFrameDrawOrderBase extends KeyFrame { - static const int typeKey = 32; - @override - int get coreType => KeyFrameDrawOrderBase.typeKey; - @override - Set get coreTypes => - {KeyFrameDrawOrderBase.typeKey, KeyFrameBase.typeKey}; -} diff --git a/lib/src/generated/animation/keyframe_draw_order_value_base.dart b/lib/src/generated/animation/keyframe_draw_order_value_base.dart deleted file mode 100644 index 905d7d0..0000000 --- a/lib/src/generated/animation/keyframe_draw_order_value_base.dart +++ /dev/null @@ -1,56 +0,0 @@ -/// Core automatically generated -/// lib/src/generated/animation/keyframe_draw_order_value_base.dart. -/// Do not modify manually. - -import 'package:rive/src/core/core.dart'; - -abstract class KeyFrameDrawOrderValueBase - extends Core { - static const int typeKey = 33; - @override - int get coreType => KeyFrameDrawOrderValueBase.typeKey; - @override - Set get coreTypes => {KeyFrameDrawOrderValueBase.typeKey}; - - /// -------------------------------------------------------------------------- - /// DrawableId field with key 77. - int _drawableId; - static const int drawableIdPropertyKey = 77; - - /// The id of the Drawable this KeyFrameDrawOrderValue's value is for. - int get drawableId => _drawableId; - - /// Change the [_drawableId] field value. - /// [drawableIdChanged] will be invoked only if the field's value has changed. - set drawableId(int value) { - if (_drawableId == value) { - return; - } - int from = _drawableId; - _drawableId = value; - drawableIdChanged(from, value); - } - - void drawableIdChanged(int from, int to); - - /// -------------------------------------------------------------------------- - /// Value field with key 78. - int _value; - static const int valuePropertyKey = 78; - - /// The draw order value to apply to the Drawable. - int get value => _value; - - /// Change the [_value] field value. - /// [valueChanged] will be invoked only if the field's value has changed. - set value(int value) { - if (_value == value) { - return; - } - int from = _value; - _value = value; - valueChanged(from, value); - } - - void valueChanged(int from, int to); -} diff --git a/lib/src/generated/animation/keyframe_id_base.dart b/lib/src/generated/animation/keyframe_id_base.dart index bc9180d..79ec3b8 100644 --- a/lib/src/generated/animation/keyframe_id_base.dart +++ b/lib/src/generated/animation/keyframe_id_base.dart @@ -14,7 +14,8 @@ abstract class KeyFrameIdBase extends KeyFrame { /// -------------------------------------------------------------------------- /// Value field with key 122. - int _value; + static const int valueInitialValue = -1; + int _value = valueInitialValue; static const int valuePropertyKey = 122; int get value => _value; @@ -26,7 +27,9 @@ abstract class KeyFrameIdBase extends KeyFrame { } int from = _value; _value = value; - valueChanged(from, value); + if (hasValidated) { + valueChanged(from, value); + } } void valueChanged(int from, int to); diff --git a/lib/src/generated/animation/layer_state_base.dart b/lib/src/generated/animation/layer_state_base.dart new file mode 100644 index 0000000..a5e1415 --- /dev/null +++ b/lib/src/generated/animation/layer_state_base.dart @@ -0,0 +1,15 @@ +/// Core automatically generated +/// lib/src/generated/animation/layer_state_base.dart. +/// Do not modify manually. + +import 'package:rive/src/generated/animation/state_machine_layer_component_base.dart'; +import 'package:rive/src/rive_core/animation/state_machine_layer_component.dart'; + +abstract class LayerStateBase extends StateMachineLayerComponent { + static const int typeKey = 60; + @override + int get coreType => LayerStateBase.typeKey; + @override + Set get coreTypes => + {LayerStateBase.typeKey, StateMachineLayerComponentBase.typeKey}; +} diff --git a/lib/src/generated/animation/linear_animation_base.dart b/lib/src/generated/animation/linear_animation_base.dart index de2b23d..0675925 100644 --- a/lib/src/generated/animation/linear_animation_base.dart +++ b/lib/src/generated/animation/linear_animation_base.dart @@ -15,7 +15,8 @@ abstract class LinearAnimationBase extends Animation { /// -------------------------------------------------------------------------- /// Fps field with key 56. - int _fps = 60; + static const int fpsInitialValue = 60; + int _fps = fpsInitialValue; static const int fpsPropertyKey = 56; /// Frames per second used to quantize keyframe times to discrete values that @@ -30,14 +31,17 @@ abstract class LinearAnimationBase extends Animation { } int from = _fps; _fps = value; - fpsChanged(from, value); + if (hasValidated) { + fpsChanged(from, value); + } } void fpsChanged(int from, int to); /// -------------------------------------------------------------------------- /// Duration field with key 57. - int _duration = 60; + static const int durationInitialValue = 60; + int _duration = durationInitialValue; static const int durationPropertyKey = 57; /// Duration expressed in number of frames. @@ -51,14 +55,17 @@ abstract class LinearAnimationBase extends Animation { } int from = _duration; _duration = value; - durationChanged(from, value); + if (hasValidated) { + durationChanged(from, value); + } } void durationChanged(int from, int to); /// -------------------------------------------------------------------------- /// Speed field with key 58. - double _speed = 1; + static const double speedInitialValue = 1; + double _speed = speedInitialValue; static const int speedPropertyKey = 58; /// Playback speed multiplier. @@ -72,14 +79,17 @@ abstract class LinearAnimationBase extends Animation { } double from = _speed; _speed = value; - speedChanged(from, value); + if (hasValidated) { + speedChanged(from, value); + } } void speedChanged(double from, double to); /// -------------------------------------------------------------------------- /// LoopValue field with key 59. - int _loopValue = 0; + static const int loopValueInitialValue = 0; + int _loopValue = loopValueInitialValue; static const int loopValuePropertyKey = 59; /// Loop value option matches Loop enumeration. @@ -93,14 +103,17 @@ abstract class LinearAnimationBase extends Animation { } int from = _loopValue; _loopValue = value; - loopValueChanged(from, value); + if (hasValidated) { + loopValueChanged(from, value); + } } void loopValueChanged(int from, int to); /// -------------------------------------------------------------------------- /// WorkStart field with key 60. - int _workStart; + static const int workStartInitialValue = -1; + int _workStart = workStartInitialValue; static const int workStartPropertyKey = 60; /// Start of the work area in frames. @@ -114,14 +127,17 @@ abstract class LinearAnimationBase extends Animation { } int from = _workStart; _workStart = value; - workStartChanged(from, value); + if (hasValidated) { + workStartChanged(from, value); + } } void workStartChanged(int from, int to); /// -------------------------------------------------------------------------- /// WorkEnd field with key 61. - int _workEnd; + static const int workEndInitialValue = -1; + int _workEnd = workEndInitialValue; static const int workEndPropertyKey = 61; /// End of the work area in frames. @@ -135,14 +151,17 @@ abstract class LinearAnimationBase extends Animation { } int from = _workEnd; _workEnd = value; - workEndChanged(from, value); + if (hasValidated) { + workEndChanged(from, value); + } } void workEndChanged(int from, int to); /// -------------------------------------------------------------------------- /// EnableWorkArea field with key 62. - bool _enableWorkArea = false; + static const bool enableWorkAreaInitialValue = false; + bool _enableWorkArea = enableWorkAreaInitialValue; static const int enableWorkAreaPropertyKey = 62; /// Whether or not the work area is enabled. @@ -157,7 +176,9 @@ abstract class LinearAnimationBase extends Animation { } bool from = _enableWorkArea; _enableWorkArea = value; - enableWorkAreaChanged(from, value); + if (hasValidated) { + enableWorkAreaChanged(from, value); + } } void enableWorkAreaChanged(bool from, bool to); diff --git a/lib/src/generated/animation/state_machine_base.dart b/lib/src/generated/animation/state_machine_base.dart new file mode 100644 index 0000000..5cde80f --- /dev/null +++ b/lib/src/generated/animation/state_machine_base.dart @@ -0,0 +1,14 @@ +/// Core automatically generated +/// lib/src/generated/animation/state_machine_base.dart. +/// Do not modify manually. + +import 'package:rive/src/generated/animation/animation_base.dart'; +import 'package:rive/src/rive_core/animation/animation.dart'; + +abstract class StateMachineBase extends Animation { + static const int typeKey = 53; + @override + int get coreType => StateMachineBase.typeKey; + @override + Set get coreTypes => {StateMachineBase.typeKey, AnimationBase.typeKey}; +} diff --git a/lib/src/generated/animation/state_machine_bool_base.dart b/lib/src/generated/animation/state_machine_bool_base.dart new file mode 100644 index 0000000..b55375b --- /dev/null +++ b/lib/src/generated/animation/state_machine_bool_base.dart @@ -0,0 +1,41 @@ +/// Core automatically generated +/// lib/src/generated/animation/state_machine_bool_base.dart. +/// Do not modify manually. + +import 'package:rive/src/generated/animation/state_machine_component_base.dart'; +import 'package:rive/src/generated/animation/state_machine_input_base.dart'; +import 'package:rive/src/rive_core/animation/state_machine_input.dart'; + +abstract class StateMachineBoolBase extends StateMachineInput { + static const int typeKey = 59; + @override + int get coreType => StateMachineBoolBase.typeKey; + @override + Set get coreTypes => { + StateMachineBoolBase.typeKey, + StateMachineInputBase.typeKey, + StateMachineComponentBase.typeKey + }; + + /// -------------------------------------------------------------------------- + /// Value field with key 141. + static const bool valueInitialValue = false; + bool _value = valueInitialValue; + static const int valuePropertyKey = 141; + bool get value => _value; + + /// Change the [_value] field value. + /// [valueChanged] will be invoked only if the field's value has changed. + set value(bool value) { + if (_value == value) { + return; + } + bool from = _value; + _value = value; + if (hasValidated) { + valueChanged(from, value); + } + } + + void valueChanged(bool from, bool to); +} diff --git a/lib/src/generated/animation/state_machine_component_base.dart b/lib/src/generated/animation/state_machine_component_base.dart new file mode 100644 index 0000000..1a9bce9 --- /dev/null +++ b/lib/src/generated/animation/state_machine_component_base.dart @@ -0,0 +1,39 @@ +/// Core automatically generated +/// lib/src/generated/animation/state_machine_component_base.dart. +/// Do not modify manually. + +import 'package:rive/src/core/core.dart'; + +abstract class StateMachineComponentBase + extends Core { + static const int typeKey = 54; + @override + int get coreType => StateMachineComponentBase.typeKey; + @override + Set get coreTypes => {StateMachineComponentBase.typeKey}; + + /// -------------------------------------------------------------------------- + /// Name field with key 138. + static const String nameInitialValue = ''; + String _name = nameInitialValue; + static const int namePropertyKey = 138; + + /// Non-unique identifier, used to give friendly names to state machine + /// components (like layers or inputs). + String get name => _name; + + /// Change the [_name] field value. + /// [nameChanged] will be invoked only if the field's value has changed. + set name(String value) { + if (_name == value) { + return; + } + String from = _name; + _name = value; + if (hasValidated) { + nameChanged(from, value); + } + } + + void nameChanged(String from, String to); +} diff --git a/lib/src/generated/animation/state_machine_double_base.dart b/lib/src/generated/animation/state_machine_double_base.dart new file mode 100644 index 0000000..5aac4ba --- /dev/null +++ b/lib/src/generated/animation/state_machine_double_base.dart @@ -0,0 +1,41 @@ +/// Core automatically generated +/// lib/src/generated/animation/state_machine_double_base.dart. +/// Do not modify manually. + +import 'package:rive/src/generated/animation/state_machine_component_base.dart'; +import 'package:rive/src/generated/animation/state_machine_input_base.dart'; +import 'package:rive/src/rive_core/animation/state_machine_input.dart'; + +abstract class StateMachineDoubleBase extends StateMachineInput { + static const int typeKey = 56; + @override + int get coreType => StateMachineDoubleBase.typeKey; + @override + Set get coreTypes => { + StateMachineDoubleBase.typeKey, + StateMachineInputBase.typeKey, + StateMachineComponentBase.typeKey + }; + + /// -------------------------------------------------------------------------- + /// Value field with key 140. + static const double valueInitialValue = 0; + double _value = valueInitialValue; + static const int valuePropertyKey = 140; + double get value => _value; + + /// Change the [_value] field value. + /// [valueChanged] will be invoked only if the field's value has changed. + set value(double value) { + if (_value == value) { + return; + } + double from = _value; + _value = value; + if (hasValidated) { + valueChanged(from, value); + } + } + + void valueChanged(double from, double to); +} diff --git a/lib/src/generated/animation/state_machine_input_base.dart b/lib/src/generated/animation/state_machine_input_base.dart new file mode 100644 index 0000000..31603a4 --- /dev/null +++ b/lib/src/generated/animation/state_machine_input_base.dart @@ -0,0 +1,15 @@ +/// Core automatically generated +/// lib/src/generated/animation/state_machine_input_base.dart. +/// Do not modify manually. + +import 'package:rive/src/generated/animation/state_machine_component_base.dart'; +import 'package:rive/src/rive_core/animation/state_machine_component.dart'; + +abstract class StateMachineInputBase extends StateMachineComponent { + static const int typeKey = 55; + @override + int get coreType => StateMachineInputBase.typeKey; + @override + Set get coreTypes => + {StateMachineInputBase.typeKey, StateMachineComponentBase.typeKey}; +} diff --git a/lib/src/generated/animation/state_machine_layer_base.dart b/lib/src/generated/animation/state_machine_layer_base.dart new file mode 100644 index 0000000..0e79048 --- /dev/null +++ b/lib/src/generated/animation/state_machine_layer_base.dart @@ -0,0 +1,15 @@ +/// Core automatically generated +/// lib/src/generated/animation/state_machine_layer_base.dart. +/// Do not modify manually. + +import 'package:rive/src/generated/animation/state_machine_component_base.dart'; +import 'package:rive/src/rive_core/animation/state_machine_component.dart'; + +abstract class StateMachineLayerBase extends StateMachineComponent { + static const int typeKey = 57; + @override + int get coreType => StateMachineLayerBase.typeKey; + @override + Set get coreTypes => + {StateMachineLayerBase.typeKey, StateMachineComponentBase.typeKey}; +} diff --git a/lib/src/generated/animation/state_machine_layer_component_base.dart b/lib/src/generated/animation/state_machine_layer_component_base.dart new file mode 100644 index 0000000..9872b26 --- /dev/null +++ b/lib/src/generated/animation/state_machine_layer_component_base.dart @@ -0,0 +1,14 @@ +/// Core automatically generated +/// lib/src/generated/animation/state_machine_layer_component_base.dart. +/// Do not modify manually. + +import 'package:rive/src/core/core.dart'; + +abstract class StateMachineLayerComponentBase + extends Core { + static const int typeKey = 66; + @override + int get coreType => StateMachineLayerComponentBase.typeKey; + @override + Set get coreTypes => {StateMachineLayerComponentBase.typeKey}; +} diff --git a/lib/src/generated/animation/state_machine_trigger_base.dart b/lib/src/generated/animation/state_machine_trigger_base.dart new file mode 100644 index 0000000..7e39d74 --- /dev/null +++ b/lib/src/generated/animation/state_machine_trigger_base.dart @@ -0,0 +1,19 @@ +/// Core automatically generated +/// lib/src/generated/animation/state_machine_trigger_base.dart. +/// Do not modify manually. + +import 'package:rive/src/generated/animation/state_machine_component_base.dart'; +import 'package:rive/src/generated/animation/state_machine_input_base.dart'; +import 'package:rive/src/rive_core/animation/state_machine_input.dart'; + +abstract class StateMachineTriggerBase extends StateMachineInput { + static const int typeKey = 58; + @override + int get coreType => StateMachineTriggerBase.typeKey; + @override + Set get coreTypes => { + StateMachineTriggerBase.typeKey, + StateMachineInputBase.typeKey, + StateMachineComponentBase.typeKey + }; +} diff --git a/lib/src/generated/animation/state_transition_base.dart b/lib/src/generated/animation/state_transition_base.dart new file mode 100644 index 0000000..68bd390 --- /dev/null +++ b/lib/src/generated/animation/state_transition_base.dart @@ -0,0 +1,85 @@ +/// Core automatically generated +/// lib/src/generated/animation/state_transition_base.dart. +/// Do not modify manually. + +import 'package:rive/src/generated/animation/state_machine_layer_component_base.dart'; +import 'package:rive/src/rive_core/animation/state_machine_layer_component.dart'; + +abstract class StateTransitionBase extends StateMachineLayerComponent { + static const int typeKey = 65; + @override + int get coreType => StateTransitionBase.typeKey; + @override + Set get coreTypes => + {StateTransitionBase.typeKey, StateMachineLayerComponentBase.typeKey}; + + /// -------------------------------------------------------------------------- + /// StateToId field with key 151. + static const int stateToIdInitialValue = -1; + int _stateToId = stateToIdInitialValue; + static const int stateToIdPropertyKey = 151; + + /// Id of the state this transition originates from. + int get stateToId => _stateToId; + + /// Change the [_stateToId] field value. + /// [stateToIdChanged] will be invoked only if the field's value has changed. + set stateToId(int value) { + if (_stateToId == value) { + return; + } + int from = _stateToId; + _stateToId = value; + if (hasValidated) { + stateToIdChanged(from, value); + } + } + + void stateToIdChanged(int from, int to); + + /// -------------------------------------------------------------------------- + /// Flags field with key 152. + static const int flagsInitialValue = 0; + int _flags = flagsInitialValue; + static const int flagsPropertyKey = 152; + int get flags => _flags; + + /// Change the [_flags] field value. + /// [flagsChanged] will be invoked only if the field's value has changed. + set flags(int value) { + if (_flags == value) { + return; + } + int from = _flags; + _flags = value; + if (hasValidated) { + flagsChanged(from, value); + } + } + + void flagsChanged(int from, int to); + + /// -------------------------------------------------------------------------- + /// Duration field with key 158. + static const int durationInitialValue = 0; + int _duration = durationInitialValue; + static const int durationPropertyKey = 158; + + /// Duration of the trasition (mix time) in milliseconds. + int get duration => _duration; + + /// Change the [_duration] field value. + /// [durationChanged] will be invoked only if the field's value has changed. + set duration(int value) { + if (_duration == value) { + return; + } + int from = _duration; + _duration = value; + if (hasValidated) { + durationChanged(from, value); + } + } + + void durationChanged(int from, int to); +} diff --git a/lib/src/generated/animation/transition_bool_condition_base.dart b/lib/src/generated/animation/transition_bool_condition_base.dart new file mode 100644 index 0000000..aef7e4f --- /dev/null +++ b/lib/src/generated/animation/transition_bool_condition_base.dart @@ -0,0 +1,19 @@ +/// Core automatically generated +/// lib/src/generated/animation/transition_bool_condition_base.dart. +/// Do not modify manually. + +import 'package:rive/src/generated/animation/transition_condition_base.dart'; +import 'package:rive/src/generated/animation/transition_value_condition_base.dart'; +import 'package:rive/src/rive_core/animation/transition_value_condition.dart'; + +abstract class TransitionBoolConditionBase extends TransitionValueCondition { + static const int typeKey = 71; + @override + int get coreType => TransitionBoolConditionBase.typeKey; + @override + Set get coreTypes => { + TransitionBoolConditionBase.typeKey, + TransitionValueConditionBase.typeKey, + TransitionConditionBase.typeKey + }; +} diff --git a/lib/src/generated/animation/transition_condition_base.dart b/lib/src/generated/animation/transition_condition_base.dart new file mode 100644 index 0000000..ddcefb4 --- /dev/null +++ b/lib/src/generated/animation/transition_condition_base.dart @@ -0,0 +1,37 @@ +/// Core automatically generated +/// lib/src/generated/animation/transition_condition_base.dart. +/// Do not modify manually. + +import 'package:rive/src/core/core.dart'; + +abstract class TransitionConditionBase extends Core { + static const int typeKey = 67; + @override + int get coreType => TransitionConditionBase.typeKey; + @override + Set get coreTypes => {TransitionConditionBase.typeKey}; + + /// -------------------------------------------------------------------------- + /// InputId field with key 155. + static const int inputIdInitialValue = -1; + int _inputId = inputIdInitialValue; + static const int inputIdPropertyKey = 155; + + /// Id of the StateMachineInput referenced. + int get inputId => _inputId; + + /// Change the [_inputId] field value. + /// [inputIdChanged] will be invoked only if the field's value has changed. + set inputId(int value) { + if (_inputId == value) { + return; + } + int from = _inputId; + _inputId = value; + if (hasValidated) { + inputIdChanged(from, value); + } + } + + void inputIdChanged(int from, int to); +} diff --git a/lib/src/generated/animation/transition_double_condition_base.dart b/lib/src/generated/animation/transition_double_condition_base.dart new file mode 100644 index 0000000..3aa9ef3 --- /dev/null +++ b/lib/src/generated/animation/transition_double_condition_base.dart @@ -0,0 +1,41 @@ +/// Core automatically generated +/// lib/src/generated/animation/transition_double_condition_base.dart. +/// Do not modify manually. + +import 'package:rive/src/generated/animation/transition_condition_base.dart'; +import 'package:rive/src/generated/animation/transition_value_condition_base.dart'; +import 'package:rive/src/rive_core/animation/transition_value_condition.dart'; + +abstract class TransitionDoubleConditionBase extends TransitionValueCondition { + static const int typeKey = 70; + @override + int get coreType => TransitionDoubleConditionBase.typeKey; + @override + Set get coreTypes => { + TransitionDoubleConditionBase.typeKey, + TransitionValueConditionBase.typeKey, + TransitionConditionBase.typeKey + }; + + /// -------------------------------------------------------------------------- + /// Value field with key 157. + static const double valueInitialValue = 0; + double _value = valueInitialValue; + static const int valuePropertyKey = 157; + double get value => _value; + + /// Change the [_value] field value. + /// [valueChanged] will be invoked only if the field's value has changed. + set value(double value) { + if (_value == value) { + return; + } + double from = _value; + _value = value; + if (hasValidated) { + valueChanged(from, value); + } + } + + void valueChanged(double from, double to); +} diff --git a/lib/src/generated/animation/transition_trigger_condition_base.dart b/lib/src/generated/animation/transition_trigger_condition_base.dart new file mode 100644 index 0000000..e7bd330 --- /dev/null +++ b/lib/src/generated/animation/transition_trigger_condition_base.dart @@ -0,0 +1,15 @@ +/// Core automatically generated +/// lib/src/generated/animation/transition_trigger_condition_base.dart. +/// Do not modify manually. + +import 'package:rive/src/generated/animation/transition_condition_base.dart'; +import 'package:rive/src/rive_core/animation/transition_condition.dart'; + +abstract class TransitionTriggerConditionBase extends TransitionCondition { + static const int typeKey = 68; + @override + int get coreType => TransitionTriggerConditionBase.typeKey; + @override + Set get coreTypes => + {TransitionTriggerConditionBase.typeKey, TransitionConditionBase.typeKey}; +} diff --git a/lib/src/generated/animation/transition_value_condition_base.dart b/lib/src/generated/animation/transition_value_condition_base.dart new file mode 100644 index 0000000..25491e9 --- /dev/null +++ b/lib/src/generated/animation/transition_value_condition_base.dart @@ -0,0 +1,39 @@ +/// Core automatically generated +/// lib/src/generated/animation/transition_value_condition_base.dart. +/// Do not modify manually. + +import 'package:rive/src/generated/animation/transition_condition_base.dart'; +import 'package:rive/src/rive_core/animation/transition_condition.dart'; + +abstract class TransitionValueConditionBase extends TransitionCondition { + static const int typeKey = 69; + @override + int get coreType => TransitionValueConditionBase.typeKey; + @override + Set get coreTypes => + {TransitionValueConditionBase.typeKey, TransitionConditionBase.typeKey}; + + /// -------------------------------------------------------------------------- + /// OpValue field with key 156. + static const int opValueInitialValue = 0; + int _opValue = opValueInitialValue; + static const int opValuePropertyKey = 156; + + /// Integer representation of the StateMachineOp enum. + int get opValue => _opValue; + + /// Change the [_opValue] field value. + /// [opValueChanged] will be invoked only if the field's value has changed. + set opValue(int value) { + if (_opValue == value) { + return; + } + int from = _opValue; + _opValue = value; + if (hasValidated) { + opValueChanged(from, value); + } + } + + void opValueChanged(int from, int to); +} diff --git a/lib/src/generated/artboard_base.dart b/lib/src/generated/artboard_base.dart index d5b688a..1bdc565 100644 --- a/lib/src/generated/artboard_base.dart +++ b/lib/src/generated/artboard_base.dart @@ -18,7 +18,8 @@ abstract class ArtboardBase extends ContainerComponent { /// -------------------------------------------------------------------------- /// Width field with key 7. - double _width; + static const double widthInitialValue = 0; + double _width = widthInitialValue; static const int widthPropertyKey = 7; /// Width of the artboard. @@ -32,14 +33,17 @@ abstract class ArtboardBase extends ContainerComponent { } double from = _width; _width = value; - widthChanged(from, value); + if (hasValidated) { + widthChanged(from, value); + } } void widthChanged(double from, double to); /// -------------------------------------------------------------------------- /// Height field with key 8. - double _height; + static const double heightInitialValue = 0; + double _height = heightInitialValue; static const int heightPropertyKey = 8; /// Height of the artboard. @@ -53,14 +57,17 @@ abstract class ArtboardBase extends ContainerComponent { } double from = _height; _height = value; - heightChanged(from, value); + if (hasValidated) { + heightChanged(from, value); + } } void heightChanged(double from, double to); /// -------------------------------------------------------------------------- /// X field with key 9. - double _x; + static const double xInitialValue = 0; + double _x = xInitialValue; static const int xPropertyKey = 9; /// X coordinate in editor world space. @@ -74,14 +81,17 @@ abstract class ArtboardBase extends ContainerComponent { } double from = _x; _x = value; - xChanged(from, value); + if (hasValidated) { + xChanged(from, value); + } } void xChanged(double from, double to); /// -------------------------------------------------------------------------- /// Y field with key 10. - double _y; + static const double yInitialValue = 0; + double _y = yInitialValue; static const int yPropertyKey = 10; /// Y coordinate in editor world space. @@ -95,14 +105,17 @@ abstract class ArtboardBase extends ContainerComponent { } double from = _y; _y = value; - yChanged(from, value); + if (hasValidated) { + yChanged(from, value); + } } void yChanged(double from, double to); /// -------------------------------------------------------------------------- /// OriginX field with key 11. - double _originX; + static const double originXInitialValue = 0; + double _originX = originXInitialValue; static const int originXPropertyKey = 11; /// Origin x in normalized coordinates (0.5 = center, 0 = left, 1 = right). @@ -116,14 +129,17 @@ abstract class ArtboardBase extends ContainerComponent { } double from = _originX; _originX = value; - originXChanged(from, value); + if (hasValidated) { + originXChanged(from, value); + } } void originXChanged(double from, double to); /// -------------------------------------------------------------------------- /// OriginY field with key 12. - double _originY; + static const double originYInitialValue = 0; + double _originY = originYInitialValue; static const int originYPropertyKey = 12; /// Origin y in normalized coordinates (0.5 = center, 0 = top, 1 = bottom). @@ -137,7 +153,9 @@ abstract class ArtboardBase extends ContainerComponent { } double from = _originY; _originY = value; - originYChanged(from, value); + if (hasValidated) { + originYChanged(from, value); + } } void originYChanged(double from, double to); diff --git a/lib/src/generated/bones/bone_base.dart b/lib/src/generated/bones/bone_base.dart index ace67a5..c69bacd 100644 --- a/lib/src/generated/bones/bone_base.dart +++ b/lib/src/generated/bones/bone_base.dart @@ -22,7 +22,8 @@ abstract class BoneBase extends SkeletalComponent { /// -------------------------------------------------------------------------- /// Length field with key 89. - double _length = 0; + static const double lengthInitialValue = 0; + double _length = lengthInitialValue; static const int lengthPropertyKey = 89; double get length => _length; @@ -34,7 +35,9 @@ abstract class BoneBase extends SkeletalComponent { } double from = _length; _length = value; - lengthChanged(from, value); + if (hasValidated) { + lengthChanged(from, value); + } } void lengthChanged(double from, double to); diff --git a/lib/src/generated/bones/cubic_weight_base.dart b/lib/src/generated/bones/cubic_weight_base.dart index f4b3178..9a4c0ac 100644 --- a/lib/src/generated/bones/cubic_weight_base.dart +++ b/lib/src/generated/bones/cubic_weight_base.dart @@ -15,7 +15,8 @@ abstract class CubicWeightBase extends Weight { /// -------------------------------------------------------------------------- /// InValues field with key 110. - int _inValues = 255; + static const int inValuesInitialValue = 255; + int _inValues = inValuesInitialValue; static const int inValuesPropertyKey = 110; int get inValues => _inValues; @@ -27,14 +28,17 @@ abstract class CubicWeightBase extends Weight { } int from = _inValues; _inValues = value; - inValuesChanged(from, value); + if (hasValidated) { + inValuesChanged(from, value); + } } void inValuesChanged(int from, int to); /// -------------------------------------------------------------------------- /// InIndices field with key 111. - int _inIndices = 1; + static const int inIndicesInitialValue = 1; + int _inIndices = inIndicesInitialValue; static const int inIndicesPropertyKey = 111; int get inIndices => _inIndices; @@ -46,14 +50,17 @@ abstract class CubicWeightBase extends Weight { } int from = _inIndices; _inIndices = value; - inIndicesChanged(from, value); + if (hasValidated) { + inIndicesChanged(from, value); + } } void inIndicesChanged(int from, int to); /// -------------------------------------------------------------------------- /// OutValues field with key 112. - int _outValues = 255; + static const int outValuesInitialValue = 255; + int _outValues = outValuesInitialValue; static const int outValuesPropertyKey = 112; int get outValues => _outValues; @@ -65,14 +72,17 @@ abstract class CubicWeightBase extends Weight { } int from = _outValues; _outValues = value; - outValuesChanged(from, value); + if (hasValidated) { + outValuesChanged(from, value); + } } void outValuesChanged(int from, int to); /// -------------------------------------------------------------------------- /// OutIndices field with key 113. - int _outIndices = 1; + static const int outIndicesInitialValue = 1; + int _outIndices = outIndicesInitialValue; static const int outIndicesPropertyKey = 113; int get outIndices => _outIndices; @@ -84,7 +94,9 @@ abstract class CubicWeightBase extends Weight { } int from = _outIndices; _outIndices = value; - outIndicesChanged(from, value); + if (hasValidated) { + outIndicesChanged(from, value); + } } void outIndicesChanged(int from, int to); diff --git a/lib/src/generated/bones/root_bone_base.dart b/lib/src/generated/bones/root_bone_base.dart index 33c9173..5fd37af 100644 --- a/lib/src/generated/bones/root_bone_base.dart +++ b/lib/src/generated/bones/root_bone_base.dart @@ -24,7 +24,8 @@ abstract class RootBoneBase extends Bone { /// -------------------------------------------------------------------------- /// X field with key 90. - double _x = 0; + static const double xInitialValue = 0; + double _x = xInitialValue; static const int xPropertyKey = 90; @override double get x => _x; @@ -38,14 +39,17 @@ abstract class RootBoneBase extends Bone { } double from = _x; _x = value; - xChanged(from, value); + if (hasValidated) { + xChanged(from, value); + } } void xChanged(double from, double to); /// -------------------------------------------------------------------------- /// Y field with key 91. - double _y = 0; + static const double yInitialValue = 0; + double _y = yInitialValue; static const int yPropertyKey = 91; @override double get y => _y; @@ -59,7 +63,9 @@ abstract class RootBoneBase extends Bone { } double from = _y; _y = value; - yChanged(from, value); + if (hasValidated) { + yChanged(from, value); + } } void yChanged(double from, double to); diff --git a/lib/src/generated/bones/skin_base.dart b/lib/src/generated/bones/skin_base.dart index 7d3f999..300c488 100644 --- a/lib/src/generated/bones/skin_base.dart +++ b/lib/src/generated/bones/skin_base.dart @@ -15,7 +15,8 @@ abstract class SkinBase extends ContainerComponent { /// -------------------------------------------------------------------------- /// Xx field with key 104. - double _xx = 1; + static const double xxInitialValue = 1; + double _xx = xxInitialValue; static const int xxPropertyKey = 104; /// x component of x unit vector in the bind transform @@ -29,14 +30,17 @@ abstract class SkinBase extends ContainerComponent { } double from = _xx; _xx = value; - xxChanged(from, value); + if (hasValidated) { + xxChanged(from, value); + } } void xxChanged(double from, double to); /// -------------------------------------------------------------------------- /// Yx field with key 105. - double _yx = 0; + static const double yxInitialValue = 0; + double _yx = yxInitialValue; static const int yxPropertyKey = 105; /// y component of x unit vector in the bind transform @@ -50,14 +54,17 @@ abstract class SkinBase extends ContainerComponent { } double from = _yx; _yx = value; - yxChanged(from, value); + if (hasValidated) { + yxChanged(from, value); + } } void yxChanged(double from, double to); /// -------------------------------------------------------------------------- /// Xy field with key 106. - double _xy = 0; + static const double xyInitialValue = 0; + double _xy = xyInitialValue; static const int xyPropertyKey = 106; /// x component of y unit vector in the bind transform @@ -71,14 +78,17 @@ abstract class SkinBase extends ContainerComponent { } double from = _xy; _xy = value; - xyChanged(from, value); + if (hasValidated) { + xyChanged(from, value); + } } void xyChanged(double from, double to); /// -------------------------------------------------------------------------- /// Yy field with key 107. - double _yy = 1; + static const double yyInitialValue = 1; + double _yy = yyInitialValue; static const int yyPropertyKey = 107; /// y component of y unit vector in the bind transform @@ -92,14 +102,17 @@ abstract class SkinBase extends ContainerComponent { } double from = _yy; _yy = value; - yyChanged(from, value); + if (hasValidated) { + yyChanged(from, value); + } } void yyChanged(double from, double to); /// -------------------------------------------------------------------------- /// Tx field with key 108. - double _tx = 0; + static const double txInitialValue = 0; + double _tx = txInitialValue; static const int txPropertyKey = 108; /// x position component of the bind transform @@ -113,14 +126,17 @@ abstract class SkinBase extends ContainerComponent { } double from = _tx; _tx = value; - txChanged(from, value); + if (hasValidated) { + txChanged(from, value); + } } void txChanged(double from, double to); /// -------------------------------------------------------------------------- /// Ty field with key 109. - double _ty = 0; + static const double tyInitialValue = 0; + double _ty = tyInitialValue; static const int tyPropertyKey = 109; /// y position component of the bind transform @@ -134,7 +150,9 @@ abstract class SkinBase extends ContainerComponent { } double from = _ty; _ty = value; - tyChanged(from, value); + if (hasValidated) { + tyChanged(from, value); + } } void tyChanged(double from, double to); diff --git a/lib/src/generated/bones/tendon_base.dart b/lib/src/generated/bones/tendon_base.dart index 99c7700..32a419a 100644 --- a/lib/src/generated/bones/tendon_base.dart +++ b/lib/src/generated/bones/tendon_base.dart @@ -13,7 +13,8 @@ abstract class TendonBase extends Component { /// -------------------------------------------------------------------------- /// BoneId field with key 95. - int _boneId; + static const int boneIdInitialValue = -1; + int _boneId = boneIdInitialValue; static const int boneIdPropertyKey = 95; /// Identifier used to track the bone this tendon connects to. @@ -27,14 +28,17 @@ abstract class TendonBase extends Component { } int from = _boneId; _boneId = value; - boneIdChanged(from, value); + if (hasValidated) { + boneIdChanged(from, value); + } } void boneIdChanged(int from, int to); /// -------------------------------------------------------------------------- /// Xx field with key 96. - double _xx = 1; + static const double xxInitialValue = 1; + double _xx = xxInitialValue; static const int xxPropertyKey = 96; /// x component of x unit vector in the bind transform @@ -48,14 +52,17 @@ abstract class TendonBase extends Component { } double from = _xx; _xx = value; - xxChanged(from, value); + if (hasValidated) { + xxChanged(from, value); + } } void xxChanged(double from, double to); /// -------------------------------------------------------------------------- /// Yx field with key 97. - double _yx = 0; + static const double yxInitialValue = 0; + double _yx = yxInitialValue; static const int yxPropertyKey = 97; /// y component of x unit vector in the bind transform @@ -69,14 +76,17 @@ abstract class TendonBase extends Component { } double from = _yx; _yx = value; - yxChanged(from, value); + if (hasValidated) { + yxChanged(from, value); + } } void yxChanged(double from, double to); /// -------------------------------------------------------------------------- /// Xy field with key 98. - double _xy = 0; + static const double xyInitialValue = 0; + double _xy = xyInitialValue; static const int xyPropertyKey = 98; /// x component of y unit vector in the bind transform @@ -90,14 +100,17 @@ abstract class TendonBase extends Component { } double from = _xy; _xy = value; - xyChanged(from, value); + if (hasValidated) { + xyChanged(from, value); + } } void xyChanged(double from, double to); /// -------------------------------------------------------------------------- /// Yy field with key 99. - double _yy = 1; + static const double yyInitialValue = 1; + double _yy = yyInitialValue; static const int yyPropertyKey = 99; /// y component of y unit vector in the bind transform @@ -111,14 +124,17 @@ abstract class TendonBase extends Component { } double from = _yy; _yy = value; - yyChanged(from, value); + if (hasValidated) { + yyChanged(from, value); + } } void yyChanged(double from, double to); /// -------------------------------------------------------------------------- /// Tx field with key 100. - double _tx = 0; + static const double txInitialValue = 0; + double _tx = txInitialValue; static const int txPropertyKey = 100; /// x position component of the bind transform @@ -132,14 +148,17 @@ abstract class TendonBase extends Component { } double from = _tx; _tx = value; - txChanged(from, value); + if (hasValidated) { + txChanged(from, value); + } } void txChanged(double from, double to); /// -------------------------------------------------------------------------- /// Ty field with key 101. - double _ty = 0; + static const double tyInitialValue = 0; + double _ty = tyInitialValue; static const int tyPropertyKey = 101; /// y position component of the bind transform @@ -153,7 +172,9 @@ abstract class TendonBase extends Component { } double from = _ty; _ty = value; - tyChanged(from, value); + if (hasValidated) { + tyChanged(from, value); + } } void tyChanged(double from, double to); diff --git a/lib/src/generated/bones/weight_base.dart b/lib/src/generated/bones/weight_base.dart index 3cf80e4..60e945a 100644 --- a/lib/src/generated/bones/weight_base.dart +++ b/lib/src/generated/bones/weight_base.dart @@ -13,7 +13,8 @@ abstract class WeightBase extends Component { /// -------------------------------------------------------------------------- /// Values field with key 102. - int _values = 255; + static const int valuesInitialValue = 255; + int _values = valuesInitialValue; static const int valuesPropertyKey = 102; int get values => _values; @@ -25,14 +26,17 @@ abstract class WeightBase extends Component { } int from = _values; _values = value; - valuesChanged(from, value); + if (hasValidated) { + valuesChanged(from, value); + } } void valuesChanged(int from, int to); /// -------------------------------------------------------------------------- /// Indices field with key 103. - int _indices = 1; + static const int indicesInitialValue = 1; + int _indices = indicesInitialValue; static const int indicesPropertyKey = 103; int get indices => _indices; @@ -44,7 +48,9 @@ abstract class WeightBase extends Component { } int from = _indices; _indices = value; - indicesChanged(from, value); + if (hasValidated) { + indicesChanged(from, value); + } } void indicesChanged(int from, int to); diff --git a/lib/src/generated/component_base.dart b/lib/src/generated/component_base.dart index 8988b8b..644fd68 100644 --- a/lib/src/generated/component_base.dart +++ b/lib/src/generated/component_base.dart @@ -12,7 +12,8 @@ abstract class ComponentBase extends Core { /// -------------------------------------------------------------------------- /// Name field with key 4. - String _name; + static const String nameInitialValue = ''; + String _name = nameInitialValue; static const int namePropertyKey = 4; /// Non-unique identifier, used to give friendly names to elements in the @@ -27,14 +28,17 @@ abstract class ComponentBase extends Core { } String from = _name; _name = value; - nameChanged(from, value); + if (hasValidated) { + nameChanged(from, value); + } } void nameChanged(String from, String to); /// -------------------------------------------------------------------------- /// ParentId field with key 5. - int _parentId; + static const int parentIdInitialValue = 0; + int _parentId = parentIdInitialValue; static const int parentIdPropertyKey = 5; /// Identifier used to track parent ContainerComponent. @@ -48,7 +52,9 @@ abstract class ComponentBase extends Core { } int from = _parentId; _parentId = value; - parentIdChanged(from, value); + if (hasValidated) { + parentIdChanged(from, value); + } } void parentIdChanged(int from, int to); diff --git a/lib/src/generated/draw_rules_base.dart b/lib/src/generated/draw_rules_base.dart index 1179f1d..73e03e5 100644 --- a/lib/src/generated/draw_rules_base.dart +++ b/lib/src/generated/draw_rules_base.dart @@ -18,7 +18,8 @@ abstract class DrawRulesBase extends ContainerComponent { /// -------------------------------------------------------------------------- /// DrawTargetId field with key 121. - int _drawTargetId; + static const int drawTargetIdInitialValue = -1; + int _drawTargetId = drawTargetIdInitialValue; static const int drawTargetIdPropertyKey = 121; /// Id of the DrawTarget that is currently active for this set of rules. @@ -33,7 +34,9 @@ abstract class DrawRulesBase extends ContainerComponent { } int from = _drawTargetId; _drawTargetId = value; - drawTargetIdChanged(from, value); + if (hasValidated) { + drawTargetIdChanged(from, value); + } } void drawTargetIdChanged(int from, int to); diff --git a/lib/src/generated/draw_target_base.dart b/lib/src/generated/draw_target_base.dart index 251f24e..fceb4f8 100644 --- a/lib/src/generated/draw_target_base.dart +++ b/lib/src/generated/draw_target_base.dart @@ -13,7 +13,8 @@ abstract class DrawTargetBase extends Component { /// -------------------------------------------------------------------------- /// DrawableId field with key 119. - int _drawableId; + static const int drawableIdInitialValue = -1; + int _drawableId = drawableIdInitialValue; static const int drawableIdPropertyKey = 119; /// Id of the drawable this target references. @@ -27,14 +28,17 @@ abstract class DrawTargetBase extends Component { } int from = _drawableId; _drawableId = value; - drawableIdChanged(from, value); + if (hasValidated) { + drawableIdChanged(from, value); + } } void drawableIdChanged(int from, int to); /// -------------------------------------------------------------------------- /// PlacementValue field with key 120. - int _placementValue = 0; + static const int placementValueInitialValue = 0; + int _placementValue = placementValueInitialValue; static const int placementValuePropertyKey = 120; /// Backing enum value for the Placement. @@ -49,7 +53,9 @@ abstract class DrawTargetBase extends Component { } int from = _placementValue; _placementValue = value; - placementValueChanged(from, value); + if (hasValidated) { + placementValueChanged(from, value); + } } void placementValueChanged(int from, int to); diff --git a/lib/src/generated/drawable_base.dart b/lib/src/generated/drawable_base.dart index 7fe29be..1b8cb4e 100644 --- a/lib/src/generated/drawable_base.dart +++ b/lib/src/generated/drawable_base.dart @@ -22,7 +22,8 @@ abstract class DrawableBase extends Node { /// -------------------------------------------------------------------------- /// BlendModeValue field with key 23. - int _blendModeValue = 3; + static const int blendModeValueInitialValue = 3; + int _blendModeValue = blendModeValueInitialValue; static const int blendModeValuePropertyKey = 23; int get blendModeValue => _blendModeValue; @@ -35,14 +36,17 @@ abstract class DrawableBase extends Node { } int from = _blendModeValue; _blendModeValue = value; - blendModeValueChanged(from, value); + if (hasValidated) { + blendModeValueChanged(from, value); + } } void blendModeValueChanged(int from, int to); /// -------------------------------------------------------------------------- /// DrawableFlags field with key 129. - int _drawableFlags = 0; + static const int drawableFlagsInitialValue = 0; + int _drawableFlags = drawableFlagsInitialValue; static const int drawableFlagsPropertyKey = 129; int get drawableFlags => _drawableFlags; @@ -55,7 +59,9 @@ abstract class DrawableBase extends Node { } int from = _drawableFlags; _drawableFlags = value; - drawableFlagsChanged(from, value); + if (hasValidated) { + drawableFlagsChanged(from, value); + } } void drawableFlagsChanged(int from, int to); diff --git a/lib/src/generated/node_base.dart b/lib/src/generated/node_base.dart index 7837348..35f1fd7 100644 --- a/lib/src/generated/node_base.dart +++ b/lib/src/generated/node_base.dart @@ -20,7 +20,8 @@ abstract class NodeBase extends TransformComponent { /// -------------------------------------------------------------------------- /// X field with key 13. - double _x = 0; + static const double xInitialValue = 0; + double _x = xInitialValue; static const int xPropertyKey = 13; @override double get x => _x; @@ -34,14 +35,17 @@ abstract class NodeBase extends TransformComponent { } double from = _x; _x = value; - xChanged(from, value); + if (hasValidated) { + xChanged(from, value); + } } void xChanged(double from, double to); /// -------------------------------------------------------------------------- /// Y field with key 14. - double _y = 0; + static const double yInitialValue = 0; + double _y = yInitialValue; static const int yPropertyKey = 14; @override double get y => _y; @@ -55,7 +59,9 @@ abstract class NodeBase extends TransformComponent { } double from = _y; _y = value; - yChanged(from, value); + if (hasValidated) { + yChanged(from, value); + } } void yChanged(double from, double to); diff --git a/lib/src/generated/rive_core_context.dart b/lib/src/generated/rive_core_context.dart index d58f922..097df3d 100644 --- a/lib/src/generated/rive_core_context.dart +++ b/lib/src/generated/rive_core_context.dart @@ -6,7 +6,11 @@ import 'package:rive/src/core/field_types/core_field_type.dart'; import 'package:rive/src/core/field_types/core_string_type.dart'; import 'package:rive/src/core/field_types/core_uint_type.dart'; import 'package:rive/src/generated/animation/animation_base.dart'; +import 'package:rive/src/generated/animation/animation_state_base.dart'; +import 'package:rive/src/generated/animation/any_state_base.dart'; import 'package:rive/src/generated/animation/cubic_interpolator_base.dart'; +import 'package:rive/src/generated/animation/entry_state_base.dart'; +import 'package:rive/src/generated/animation/exit_state_base.dart'; import 'package:rive/src/generated/animation/keyed_object_base.dart'; import 'package:rive/src/generated/animation/keyed_property_base.dart'; import 'package:rive/src/generated/animation/keyframe_base.dart'; @@ -14,6 +18,18 @@ import 'package:rive/src/generated/animation/keyframe_color_base.dart'; import 'package:rive/src/generated/animation/keyframe_double_base.dart'; import 'package:rive/src/generated/animation/keyframe_id_base.dart'; import 'package:rive/src/generated/animation/linear_animation_base.dart'; +import 'package:rive/src/generated/animation/state_machine_base.dart'; +import 'package:rive/src/generated/animation/state_machine_bool_base.dart'; +import 'package:rive/src/generated/animation/state_machine_component_base.dart'; +import 'package:rive/src/generated/animation/state_machine_double_base.dart'; +import 'package:rive/src/generated/animation/state_machine_layer_base.dart'; +import 'package:rive/src/generated/animation/state_machine_trigger_base.dart'; +import 'package:rive/src/generated/animation/state_transition_base.dart'; +import 'package:rive/src/generated/animation/transition_bool_condition_base.dart'; +import 'package:rive/src/generated/animation/transition_condition_base.dart'; +import 'package:rive/src/generated/animation/transition_double_condition_base.dart'; +import 'package:rive/src/generated/animation/transition_trigger_condition_base.dart'; +import 'package:rive/src/generated/animation/transition_value_condition_base.dart'; import 'package:rive/src/generated/artboard_base.dart'; import 'package:rive/src/generated/backboard_base.dart'; import 'package:rive/src/generated/bones/bone_base.dart'; @@ -42,7 +58,6 @@ import 'package:rive/src/generated/shapes/paint/stroke_base.dart'; import 'package:rive/src/generated/shapes/paint/trim_path_base.dart'; import 'package:rive/src/generated/shapes/parametric_path_base.dart'; import 'package:rive/src/generated/shapes/path_base.dart'; -import 'package:rive/src/generated/shapes/path_composer_base.dart'; import 'package:rive/src/generated/shapes/path_vertex_base.dart'; import 'package:rive/src/generated/shapes/points_path_base.dart'; import 'package:rive/src/generated/shapes/polygon_base.dart'; @@ -53,13 +68,26 @@ import 'package:rive/src/generated/shapes/straight_vertex_base.dart'; import 'package:rive/src/generated/shapes/triangle_base.dart'; import 'package:rive/src/generated/transform_component_base.dart'; import 'package:rive/src/rive_core/animation/animation.dart'; +import 'package:rive/src/rive_core/animation/animation_state.dart'; +import 'package:rive/src/rive_core/animation/any_state.dart'; import 'package:rive/src/rive_core/animation/cubic_interpolator.dart'; +import 'package:rive/src/rive_core/animation/entry_state.dart'; +import 'package:rive/src/rive_core/animation/exit_state.dart'; import 'package:rive/src/rive_core/animation/keyed_object.dart'; import 'package:rive/src/rive_core/animation/keyed_property.dart'; import 'package:rive/src/rive_core/animation/keyframe_color.dart'; import 'package:rive/src/rive_core/animation/keyframe_double.dart'; import 'package:rive/src/rive_core/animation/keyframe_id.dart'; import 'package:rive/src/rive_core/animation/linear_animation.dart'; +import 'package:rive/src/rive_core/animation/state_machine.dart'; +import 'package:rive/src/rive_core/animation/state_machine_bool.dart'; +import 'package:rive/src/rive_core/animation/state_machine_double.dart'; +import 'package:rive/src/rive_core/animation/state_machine_layer.dart'; +import 'package:rive/src/rive_core/animation/state_machine_trigger.dart'; +import 'package:rive/src/rive_core/animation/state_transition.dart'; +import 'package:rive/src/rive_core/animation/transition_bool_condition.dart'; +import 'package:rive/src/rive_core/animation/transition_double_condition.dart'; +import 'package:rive/src/rive_core/animation/transition_trigger_condition.dart'; import 'package:rive/src/rive_core/artboard.dart'; import 'package:rive/src/rive_core/backboard.dart'; import 'package:rive/src/rive_core/bones/bone.dart'; @@ -83,7 +111,6 @@ import 'package:rive/src/rive_core/shapes/paint/radial_gradient.dart'; import 'package:rive/src/rive_core/shapes/paint/solid_color.dart'; import 'package:rive/src/rive_core/shapes/paint/stroke.dart'; import 'package:rive/src/rive_core/shapes/paint/trim_path.dart'; -import 'package:rive/src/rive_core/shapes/path_composer.dart'; import 'package:rive/src/rive_core/shapes/points_path.dart'; import 'package:rive/src/rive_core/shapes/polygon.dart'; import 'package:rive/src/rive_core/shapes/rectangle.dart'; @@ -94,26 +121,52 @@ import 'package:rive/src/rive_core/shapes/triangle.dart'; // ignore: avoid_classes_with_only_static_members class RiveCoreContext { - static Core makeCoreInstance(int typeKey) { + static Core? makeCoreInstance(int typeKey) { switch (typeKey) { case DrawTargetBase.typeKey: return DrawTarget(); + case AnimationStateBase.typeKey: + return AnimationState(); case KeyedObjectBase.typeKey: return KeyedObject(); + case TransitionTriggerConditionBase.typeKey: + return TransitionTriggerCondition(); case KeyedPropertyBase.typeKey: return KeyedProperty(); + case StateMachineDoubleBase.typeKey: + return StateMachineDouble(); case KeyFrameIdBase.typeKey: return KeyFrameId(); + case AnyStateBase.typeKey: + return AnyState(); + case StateMachineLayerBase.typeKey: + return StateMachineLayer(); case AnimationBase.typeKey: return Animation(); case CubicInterpolatorBase.typeKey: return CubicInterpolator(); + case TransitionDoubleConditionBase.typeKey: + return TransitionDoubleCondition(); + case StateTransitionBase.typeKey: + return StateTransition(); case KeyFrameDoubleBase.typeKey: return KeyFrameDouble(); case KeyFrameColorBase.typeKey: return KeyFrameColor(); + case StateMachineBase.typeKey: + return StateMachine(); + case EntryStateBase.typeKey: + return EntryState(); case LinearAnimationBase.typeKey: return LinearAnimation(); + case StateMachineTriggerBase.typeKey: + return StateMachineTrigger(); + case ExitStateBase.typeKey: + return ExitState(); + case TransitionBoolConditionBase.typeKey: + return TransitionBoolCondition(); + case StateMachineBoolBase.typeKey: + return StateMachineBool(); case LinearGradientBase.typeKey: return LinearGradient(); case RadialGradientBase.typeKey: @@ -156,8 +209,6 @@ class RiveCoreContext { return Polygon(); case StarBase.typeKey: return Star(); - case PathComposerBase.typeKey: - return PathComposer(); case CubicDetachedVertexBase.typeKey: return CubicDetachedVertex(); case DrawRulesBase.typeKey: @@ -182,12 +233,8 @@ class RiveCoreContext { static void setObjectProperty(Core object, int propertyKey, Object value) { switch (propertyKey) { case ComponentBase.namePropertyKey: - if (object is ComponentBase) { - if (value is String) { - object.name = value; - } else if (value == null) { - object.name = null; - } + if (object is ComponentBase && value is String) { + object.name = value; } break; case ComponentBase.parentIdPropertyKey: @@ -205,16 +252,36 @@ class RiveCoreContext { object.placementValue = value; } break; + case AnimationStateBase.animationIdPropertyKey: + if (object is AnimationStateBase && value is int) { + object.animationId = value; + } + break; case KeyedObjectBase.objectIdPropertyKey: if (object is KeyedObjectBase && value is int) { object.objectId = value; } break; + case TransitionConditionBase.inputIdPropertyKey: + if (object is TransitionConditionBase && value is int) { + object.inputId = value; + } + break; + case StateMachineComponentBase.namePropertyKey: + if (object is StateMachineComponentBase && value is String) { + object.name = value; + } + break; case KeyedPropertyBase.propertyKeyPropertyKey: if (object is KeyedPropertyBase && value is int) { object.propertyKey = value; } break; + case StateMachineDoubleBase.valuePropertyKey: + if (object is StateMachineDoubleBase && value is double) { + object.value = value; + } + break; case KeyFrameBase.framePropertyKey: if (object is KeyFrameBase && value is int) { object.frame = value; @@ -226,12 +293,8 @@ class RiveCoreContext { } break; case KeyFrameBase.interpolatorIdPropertyKey: - if (object is KeyFrameBase) { - if (value is int) { - object.interpolatorId = value; - } else if (value == null) { - object.interpolatorId = null; - } + if (object is KeyFrameBase && value is int) { + object.interpolatorId = value; } break; case KeyFrameIdBase.valuePropertyKey: @@ -264,6 +327,31 @@ class RiveCoreContext { object.y2 = value; } break; + case TransitionValueConditionBase.opValuePropertyKey: + if (object is TransitionValueConditionBase && value is int) { + object.opValue = value; + } + break; + case TransitionDoubleConditionBase.valuePropertyKey: + if (object is TransitionDoubleConditionBase && value is double) { + object.value = value; + } + break; + case StateTransitionBase.stateToIdPropertyKey: + if (object is StateTransitionBase && value is int) { + object.stateToId = value; + } + break; + case StateTransitionBase.flagsPropertyKey: + if (object is StateTransitionBase && value is int) { + object.flags = value; + } + break; + case StateTransitionBase.durationPropertyKey: + if (object is StateTransitionBase && value is int) { + object.duration = value; + } + break; case KeyFrameDoubleBase.valuePropertyKey: if (object is KeyFrameDoubleBase && value is double) { object.value = value; @@ -309,6 +397,11 @@ class RiveCoreContext { object.enableWorkArea = value; } break; + case StateMachineBoolBase.valuePropertyKey: + if (object is StateMachineBoolBase && value is bool) { + object.value = value; + } + break; case ShapePaintBase.isVisiblePropertyKey: if (object is ShapePaintBase && value is bool) { object.isVisible = value; @@ -717,20 +810,27 @@ class RiveCoreContext { static CoreFieldType doubleType = CoreDoubleType(); static CoreFieldType colorType = CoreColorType(); static CoreFieldType boolType = CoreBoolType(); - static CoreFieldType coreType(int propertyKey) { + static CoreFieldType? coreType(int propertyKey) { switch (propertyKey) { case ComponentBase.namePropertyKey: + case StateMachineComponentBase.namePropertyKey: case AnimationBase.namePropertyKey: return stringType; case ComponentBase.parentIdPropertyKey: case DrawTargetBase.drawableIdPropertyKey: case DrawTargetBase.placementValuePropertyKey: + case AnimationStateBase.animationIdPropertyKey: case KeyedObjectBase.objectIdPropertyKey: + case TransitionConditionBase.inputIdPropertyKey: case KeyedPropertyBase.propertyKeyPropertyKey: case KeyFrameBase.framePropertyKey: case KeyFrameBase.interpolationTypePropertyKey: case KeyFrameBase.interpolatorIdPropertyKey: case KeyFrameIdBase.valuePropertyKey: + case TransitionValueConditionBase.opValuePropertyKey: + case StateTransitionBase.stateToIdPropertyKey: + case StateTransitionBase.flagsPropertyKey: + case StateTransitionBase.durationPropertyKey: case LinearAnimationBase.fpsPropertyKey: case LinearAnimationBase.durationPropertyKey: case LinearAnimationBase.loopValuePropertyKey: @@ -755,10 +855,12 @@ class RiveCoreContext { case DrawRulesBase.drawTargetIdPropertyKey: case TendonBase.boneIdPropertyKey: return uintType; + case StateMachineDoubleBase.valuePropertyKey: case CubicInterpolatorBase.x1PropertyKey: case CubicInterpolatorBase.y1PropertyKey: case CubicInterpolatorBase.x2PropertyKey: case CubicInterpolatorBase.y2PropertyKey: + case TransitionDoubleConditionBase.valuePropertyKey: case KeyFrameDoubleBase.valuePropertyKey: case LinearAnimationBase.speedPropertyKey: case LinearGradientBase.startXPropertyKey: @@ -823,6 +925,7 @@ class RiveCoreContext { case GradientStopBase.colorValuePropertyKey: return colorType; case LinearAnimationBase.enableWorkAreaPropertyKey: + case StateMachineBoolBase.valuePropertyKey: case ShapePaintBase.isVisiblePropertyKey: case StrokeBase.transformAffectsStrokePropertyKey: case PointsPathBase.isClosedPropertyKey: @@ -837,10 +940,12 @@ class RiveCoreContext { switch (propertyKey) { case ComponentBase.namePropertyKey: return (object as ComponentBase).name; + case StateMachineComponentBase.namePropertyKey: + return (object as StateMachineComponentBase).name; case AnimationBase.namePropertyKey: return (object as AnimationBase).name; } - return null; + return ''; } static int getUint(Core object, int propertyKey) { @@ -851,8 +956,12 @@ class RiveCoreContext { return (object as DrawTargetBase).drawableId; case DrawTargetBase.placementValuePropertyKey: return (object as DrawTargetBase).placementValue; + case AnimationStateBase.animationIdPropertyKey: + return (object as AnimationStateBase).animationId; case KeyedObjectBase.objectIdPropertyKey: return (object as KeyedObjectBase).objectId; + case TransitionConditionBase.inputIdPropertyKey: + return (object as TransitionConditionBase).inputId; case KeyedPropertyBase.propertyKeyPropertyKey: return (object as KeyedPropertyBase).propertyKey; case KeyFrameBase.framePropertyKey: @@ -863,6 +972,14 @@ class RiveCoreContext { return (object as KeyFrameBase).interpolatorId; case KeyFrameIdBase.valuePropertyKey: return (object as KeyFrameIdBase).value; + case TransitionValueConditionBase.opValuePropertyKey: + return (object as TransitionValueConditionBase).opValue; + case StateTransitionBase.stateToIdPropertyKey: + return (object as StateTransitionBase).stateToId; + case StateTransitionBase.flagsPropertyKey: + return (object as StateTransitionBase).flags; + case StateTransitionBase.durationPropertyKey: + return (object as StateTransitionBase).duration; case LinearAnimationBase.fpsPropertyKey: return (object as LinearAnimationBase).fps; case LinearAnimationBase.durationPropertyKey: @@ -915,6 +1032,8 @@ class RiveCoreContext { static double getDouble(Core object, int propertyKey) { switch (propertyKey) { + case StateMachineDoubleBase.valuePropertyKey: + return (object as StateMachineDoubleBase).value; case CubicInterpolatorBase.x1PropertyKey: return (object as CubicInterpolatorBase).x1; case CubicInterpolatorBase.y1PropertyKey: @@ -923,6 +1042,8 @@ class RiveCoreContext { return (object as CubicInterpolatorBase).x2; case CubicInterpolatorBase.y2PropertyKey: return (object as CubicInterpolatorBase).y2; + case TransitionDoubleConditionBase.valuePropertyKey: + return (object as TransitionDoubleConditionBase).value; case KeyFrameDoubleBase.valuePropertyKey: return (object as KeyFrameDoubleBase).value; case LinearAnimationBase.speedPropertyKey: @@ -1059,6 +1180,8 @@ class RiveCoreContext { switch (propertyKey) { case LinearAnimationBase.enableWorkAreaPropertyKey: return (object as LinearAnimationBase).enableWorkArea; + case StateMachineBoolBase.valuePropertyKey: + return (object as StateMachineBoolBase).value; case ShapePaintBase.isVisiblePropertyKey: return (object as ShapePaintBase).isVisible; case StrokeBase.transformAffectsStrokePropertyKey: @@ -1076,6 +1199,9 @@ class RiveCoreContext { case ComponentBase.namePropertyKey: (object as ComponentBase).name = value; break; + case StateMachineComponentBase.namePropertyKey: + (object as StateMachineComponentBase).name = value; + break; case AnimationBase.namePropertyKey: (object as AnimationBase).name = value; break; @@ -1093,9 +1219,15 @@ class RiveCoreContext { case DrawTargetBase.placementValuePropertyKey: (object as DrawTargetBase).placementValue = value; break; + case AnimationStateBase.animationIdPropertyKey: + (object as AnimationStateBase).animationId = value; + break; case KeyedObjectBase.objectIdPropertyKey: (object as KeyedObjectBase).objectId = value; break; + case TransitionConditionBase.inputIdPropertyKey: + (object as TransitionConditionBase).inputId = value; + break; case KeyedPropertyBase.propertyKeyPropertyKey: (object as KeyedPropertyBase).propertyKey = value; break; @@ -1111,6 +1243,18 @@ class RiveCoreContext { case KeyFrameIdBase.valuePropertyKey: (object as KeyFrameIdBase).value = value; break; + case TransitionValueConditionBase.opValuePropertyKey: + (object as TransitionValueConditionBase).opValue = value; + break; + case StateTransitionBase.stateToIdPropertyKey: + (object as StateTransitionBase).stateToId = value; + break; + case StateTransitionBase.flagsPropertyKey: + (object as StateTransitionBase).flags = value; + break; + case StateTransitionBase.durationPropertyKey: + (object as StateTransitionBase).duration = value; + break; case LinearAnimationBase.fpsPropertyKey: (object as LinearAnimationBase).fps = value; break; @@ -1185,6 +1329,9 @@ class RiveCoreContext { static void setDouble(Core object, int propertyKey, double value) { switch (propertyKey) { + case StateMachineDoubleBase.valuePropertyKey: + (object as StateMachineDoubleBase).value = value; + break; case CubicInterpolatorBase.x1PropertyKey: (object as CubicInterpolatorBase).x1 = value; break; @@ -1197,6 +1344,9 @@ class RiveCoreContext { case CubicInterpolatorBase.y2PropertyKey: (object as CubicInterpolatorBase).y2 = value; break; + case TransitionDoubleConditionBase.valuePropertyKey: + (object as TransitionDoubleConditionBase).value = value; + break; case KeyFrameDoubleBase.valuePropertyKey: (object as KeyFrameDoubleBase).value = value; break; @@ -1393,6 +1543,9 @@ class RiveCoreContext { case LinearAnimationBase.enableWorkAreaPropertyKey: (object as LinearAnimationBase).enableWorkArea = value; break; + case StateMachineBoolBase.valuePropertyKey: + (object as StateMachineBoolBase).value = value; + break; case ShapePaintBase.isVisiblePropertyKey: (object as ShapePaintBase).isVisible = value; break; diff --git a/lib/src/generated/shapes/clipping_shape_base.dart b/lib/src/generated/shapes/clipping_shape_base.dart index 07cbcd0..ee5a4b5 100644 --- a/lib/src/generated/shapes/clipping_shape_base.dart +++ b/lib/src/generated/shapes/clipping_shape_base.dart @@ -14,7 +14,8 @@ abstract class ClippingShapeBase extends Component { /// -------------------------------------------------------------------------- /// SourceId field with key 92. - int _sourceId; + static const int sourceIdInitialValue = -1; + int _sourceId = sourceIdInitialValue; static const int sourceIdPropertyKey = 92; /// Identifier used to track the node to use as a clipping source. @@ -28,14 +29,17 @@ abstract class ClippingShapeBase extends Component { } int from = _sourceId; _sourceId = value; - sourceIdChanged(from, value); + if (hasValidated) { + sourceIdChanged(from, value); + } } void sourceIdChanged(int from, int to); /// -------------------------------------------------------------------------- /// FillRule field with key 93. - int _fillRule = 0; + static const int fillRuleInitialValue = 0; + int _fillRule = fillRuleInitialValue; static const int fillRulePropertyKey = 93; /// Backing enum value for the clipping fill rule (nonZero or evenOdd). @@ -49,14 +53,17 @@ abstract class ClippingShapeBase extends Component { } int from = _fillRule; _fillRule = value; - fillRuleChanged(from, value); + if (hasValidated) { + fillRuleChanged(from, value); + } } void fillRuleChanged(int from, int to); /// -------------------------------------------------------------------------- /// IsVisible field with key 94. - bool _isVisible = true; + static const bool isVisibleInitialValue = true; + bool _isVisible = isVisibleInitialValue; static const int isVisiblePropertyKey = 94; bool get isVisible => _isVisible; @@ -68,7 +75,9 @@ abstract class ClippingShapeBase extends Component { } bool from = _isVisible; _isVisible = value; - isVisibleChanged(from, value); + if (hasValidated) { + isVisibleChanged(from, value); + } } void isVisibleChanged(bool from, bool to); diff --git a/lib/src/generated/shapes/cubic_asymmetric_vertex_base.dart b/lib/src/generated/shapes/cubic_asymmetric_vertex_base.dart index 0564f51..35d77fb 100644 --- a/lib/src/generated/shapes/cubic_asymmetric_vertex_base.dart +++ b/lib/src/generated/shapes/cubic_asymmetric_vertex_base.dart @@ -23,7 +23,8 @@ abstract class CubicAsymmetricVertexBase extends CubicVertex { /// -------------------------------------------------------------------------- /// Rotation field with key 79. - double _rotation = 0; + static const double rotationInitialValue = 0; + double _rotation = rotationInitialValue; static const int rotationPropertyKey = 79; /// The control points' angle. @@ -37,14 +38,17 @@ abstract class CubicAsymmetricVertexBase extends CubicVertex { } double from = _rotation; _rotation = value; - rotationChanged(from, value); + if (hasValidated) { + rotationChanged(from, value); + } } void rotationChanged(double from, double to); /// -------------------------------------------------------------------------- /// InDistance field with key 80. - double _inDistance = 0; + static const double inDistanceInitialValue = 0; + double _inDistance = inDistanceInitialValue; static const int inDistancePropertyKey = 80; /// The in point's distance from the translation of the point. @@ -58,14 +62,17 @@ abstract class CubicAsymmetricVertexBase extends CubicVertex { } double from = _inDistance; _inDistance = value; - inDistanceChanged(from, value); + if (hasValidated) { + inDistanceChanged(from, value); + } } void inDistanceChanged(double from, double to); /// -------------------------------------------------------------------------- /// OutDistance field with key 81. - double _outDistance = 0; + static const double outDistanceInitialValue = 0; + double _outDistance = outDistanceInitialValue; static const int outDistancePropertyKey = 81; /// The out point's distance from the translation of the point. @@ -80,7 +87,9 @@ abstract class CubicAsymmetricVertexBase extends CubicVertex { } double from = _outDistance; _outDistance = value; - outDistanceChanged(from, value); + if (hasValidated) { + outDistanceChanged(from, value); + } } void outDistanceChanged(double from, double to); diff --git a/lib/src/generated/shapes/cubic_detached_vertex_base.dart b/lib/src/generated/shapes/cubic_detached_vertex_base.dart index b994bc2..5467ce2 100644 --- a/lib/src/generated/shapes/cubic_detached_vertex_base.dart +++ b/lib/src/generated/shapes/cubic_detached_vertex_base.dart @@ -23,7 +23,8 @@ abstract class CubicDetachedVertexBase extends CubicVertex { /// -------------------------------------------------------------------------- /// InRotation field with key 84. - double _inRotation = 0; + static const double inRotationInitialValue = 0; + double _inRotation = inRotationInitialValue; static const int inRotationPropertyKey = 84; /// The in point's angle. @@ -37,14 +38,17 @@ abstract class CubicDetachedVertexBase extends CubicVertex { } double from = _inRotation; _inRotation = value; - inRotationChanged(from, value); + if (hasValidated) { + inRotationChanged(from, value); + } } void inRotationChanged(double from, double to); /// -------------------------------------------------------------------------- /// InDistance field with key 85. - double _inDistance = 0; + static const double inDistanceInitialValue = 0; + double _inDistance = inDistanceInitialValue; static const int inDistancePropertyKey = 85; /// The in point's distance from the translation of the point. @@ -58,14 +62,17 @@ abstract class CubicDetachedVertexBase extends CubicVertex { } double from = _inDistance; _inDistance = value; - inDistanceChanged(from, value); + if (hasValidated) { + inDistanceChanged(from, value); + } } void inDistanceChanged(double from, double to); /// -------------------------------------------------------------------------- /// OutRotation field with key 86. - double _outRotation = 0; + static const double outRotationInitialValue = 0; + double _outRotation = outRotationInitialValue; static const int outRotationPropertyKey = 86; /// The out point's angle. @@ -80,14 +87,17 @@ abstract class CubicDetachedVertexBase extends CubicVertex { } double from = _outRotation; _outRotation = value; - outRotationChanged(from, value); + if (hasValidated) { + outRotationChanged(from, value); + } } void outRotationChanged(double from, double to); /// -------------------------------------------------------------------------- /// OutDistance field with key 87. - double _outDistance = 0; + static const double outDistanceInitialValue = 0; + double _outDistance = outDistanceInitialValue; static const int outDistancePropertyKey = 87; /// The out point's distance from the translation of the point. @@ -102,7 +112,9 @@ abstract class CubicDetachedVertexBase extends CubicVertex { } double from = _outDistance; _outDistance = value; - outDistanceChanged(from, value); + if (hasValidated) { + outDistanceChanged(from, value); + } } void outDistanceChanged(double from, double to); diff --git a/lib/src/generated/shapes/cubic_mirrored_vertex_base.dart b/lib/src/generated/shapes/cubic_mirrored_vertex_base.dart index 7955178..6b8d866 100644 --- a/lib/src/generated/shapes/cubic_mirrored_vertex_base.dart +++ b/lib/src/generated/shapes/cubic_mirrored_vertex_base.dart @@ -23,7 +23,8 @@ abstract class CubicMirroredVertexBase extends CubicVertex { /// -------------------------------------------------------------------------- /// Rotation field with key 82. - double _rotation = 0; + static const double rotationInitialValue = 0; + double _rotation = rotationInitialValue; static const int rotationPropertyKey = 82; /// The control points' angle. @@ -37,14 +38,17 @@ abstract class CubicMirroredVertexBase extends CubicVertex { } double from = _rotation; _rotation = value; - rotationChanged(from, value); + if (hasValidated) { + rotationChanged(from, value); + } } void rotationChanged(double from, double to); /// -------------------------------------------------------------------------- /// Distance field with key 83. - double _distance = 0; + static const double distanceInitialValue = 0; + double _distance = distanceInitialValue; static const int distancePropertyKey = 83; /// The control points' distance from the translation of the point. @@ -58,7 +62,9 @@ abstract class CubicMirroredVertexBase extends CubicVertex { } double from = _distance; _distance = value; - distanceChanged(from, value); + if (hasValidated) { + distanceChanged(from, value); + } } void distanceChanged(double from, double to); diff --git a/lib/src/generated/shapes/paint/fill_base.dart b/lib/src/generated/shapes/paint/fill_base.dart index 7a87593..42e7eac 100644 --- a/lib/src/generated/shapes/paint/fill_base.dart +++ b/lib/src/generated/shapes/paint/fill_base.dart @@ -20,7 +20,8 @@ abstract class FillBase extends ShapePaint { /// -------------------------------------------------------------------------- /// FillRule field with key 40. - int _fillRule = 0; + static const int fillRuleInitialValue = 0; + int _fillRule = fillRuleInitialValue; static const int fillRulePropertyKey = 40; int get fillRule => _fillRule; @@ -32,7 +33,9 @@ abstract class FillBase extends ShapePaint { } int from = _fillRule; _fillRule = value; - fillRuleChanged(from, value); + if (hasValidated) { + fillRuleChanged(from, value); + } } void fillRuleChanged(int from, int to); diff --git a/lib/src/generated/shapes/paint/gradient_stop_base.dart b/lib/src/generated/shapes/paint/gradient_stop_base.dart index 8284ef8..0eebf10 100644 --- a/lib/src/generated/shapes/paint/gradient_stop_base.dart +++ b/lib/src/generated/shapes/paint/gradient_stop_base.dart @@ -14,7 +14,8 @@ abstract class GradientStopBase extends Component { /// -------------------------------------------------------------------------- /// ColorValue field with key 38. - int _colorValue = 0xFFFFFFFF; + static const int colorValueInitialValue = 0xFFFFFFFF; + int _colorValue = colorValueInitialValue; static const int colorValuePropertyKey = 38; int get colorValue => _colorValue; @@ -26,14 +27,17 @@ abstract class GradientStopBase extends Component { } int from = _colorValue; _colorValue = value; - colorValueChanged(from, value); + if (hasValidated) { + colorValueChanged(from, value); + } } void colorValueChanged(int from, int to); /// -------------------------------------------------------------------------- /// Position field with key 39. - double _position = 0; + static const double positionInitialValue = 0; + double _position = positionInitialValue; static const int positionPropertyKey = 39; double get position => _position; @@ -45,7 +49,9 @@ abstract class GradientStopBase extends Component { } double from = _position; _position = value; - positionChanged(from, value); + if (hasValidated) { + positionChanged(from, value); + } } void positionChanged(double from, double to); diff --git a/lib/src/generated/shapes/paint/linear_gradient_base.dart b/lib/src/generated/shapes/paint/linear_gradient_base.dart index b7e339b..e394b12 100644 --- a/lib/src/generated/shapes/paint/linear_gradient_base.dart +++ b/lib/src/generated/shapes/paint/linear_gradient_base.dart @@ -19,7 +19,8 @@ abstract class LinearGradientBase extends ContainerComponent { /// -------------------------------------------------------------------------- /// StartX field with key 42. - double _startX = 0; + static const double startXInitialValue = 0; + double _startX = startXInitialValue; static const int startXPropertyKey = 42; double get startX => _startX; @@ -31,14 +32,17 @@ abstract class LinearGradientBase extends ContainerComponent { } double from = _startX; _startX = value; - startXChanged(from, value); + if (hasValidated) { + startXChanged(from, value); + } } void startXChanged(double from, double to); /// -------------------------------------------------------------------------- /// StartY field with key 33. - double _startY = 0; + static const double startYInitialValue = 0; + double _startY = startYInitialValue; static const int startYPropertyKey = 33; double get startY => _startY; @@ -50,14 +54,17 @@ abstract class LinearGradientBase extends ContainerComponent { } double from = _startY; _startY = value; - startYChanged(from, value); + if (hasValidated) { + startYChanged(from, value); + } } void startYChanged(double from, double to); /// -------------------------------------------------------------------------- /// EndX field with key 34. - double _endX = 0; + static const double endXInitialValue = 0; + double _endX = endXInitialValue; static const int endXPropertyKey = 34; double get endX => _endX; @@ -69,14 +76,17 @@ abstract class LinearGradientBase extends ContainerComponent { } double from = _endX; _endX = value; - endXChanged(from, value); + if (hasValidated) { + endXChanged(from, value); + } } void endXChanged(double from, double to); /// -------------------------------------------------------------------------- /// EndY field with key 35. - double _endY = 0; + static const double endYInitialValue = 0; + double _endY = endYInitialValue; static const int endYPropertyKey = 35; double get endY => _endY; @@ -88,14 +98,17 @@ abstract class LinearGradientBase extends ContainerComponent { } double from = _endY; _endY = value; - endYChanged(from, value); + if (hasValidated) { + endYChanged(from, value); + } } void endYChanged(double from, double to); /// -------------------------------------------------------------------------- /// Opacity field with key 46. - double _opacity = 1; + static const double opacityInitialValue = 1; + double _opacity = opacityInitialValue; static const int opacityPropertyKey = 46; double get opacity => _opacity; @@ -107,7 +120,9 @@ abstract class LinearGradientBase extends ContainerComponent { } double from = _opacity; _opacity = value; - opacityChanged(from, value); + if (hasValidated) { + opacityChanged(from, value); + } } void opacityChanged(double from, double to); diff --git a/lib/src/generated/shapes/paint/shape_paint_base.dart b/lib/src/generated/shapes/paint/shape_paint_base.dart index f4c680c..2df03c5 100644 --- a/lib/src/generated/shapes/paint/shape_paint_base.dart +++ b/lib/src/generated/shapes/paint/shape_paint_base.dart @@ -19,7 +19,8 @@ abstract class ShapePaintBase extends ContainerComponent { /// -------------------------------------------------------------------------- /// IsVisible field with key 41. - bool _isVisible = true; + static const bool isVisibleInitialValue = true; + bool _isVisible = isVisibleInitialValue; static const int isVisiblePropertyKey = 41; bool get isVisible => _isVisible; @@ -31,7 +32,9 @@ abstract class ShapePaintBase extends ContainerComponent { } bool from = _isVisible; _isVisible = value; - isVisibleChanged(from, value); + if (hasValidated) { + isVisibleChanged(from, value); + } } void isVisibleChanged(bool from, bool to); diff --git a/lib/src/generated/shapes/paint/solid_color_base.dart b/lib/src/generated/shapes/paint/solid_color_base.dart index 4d38d44..58ec5b9 100644 --- a/lib/src/generated/shapes/paint/solid_color_base.dart +++ b/lib/src/generated/shapes/paint/solid_color_base.dart @@ -14,7 +14,8 @@ abstract class SolidColorBase extends Component { /// -------------------------------------------------------------------------- /// ColorValue field with key 37. - int _colorValue = 0xFF747474; + static const int colorValueInitialValue = 0xFF747474; + int _colorValue = colorValueInitialValue; static const int colorValuePropertyKey = 37; int get colorValue => _colorValue; @@ -26,7 +27,9 @@ abstract class SolidColorBase extends Component { } int from = _colorValue; _colorValue = value; - colorValueChanged(from, value); + if (hasValidated) { + colorValueChanged(from, value); + } } void colorValueChanged(int from, int to); diff --git a/lib/src/generated/shapes/paint/stroke_base.dart b/lib/src/generated/shapes/paint/stroke_base.dart index ba93e18..4998acd 100644 --- a/lib/src/generated/shapes/paint/stroke_base.dart +++ b/lib/src/generated/shapes/paint/stroke_base.dart @@ -21,7 +21,8 @@ abstract class StrokeBase extends ShapePaint { /// -------------------------------------------------------------------------- /// Thickness field with key 47. - double _thickness = 1; + static const double thicknessInitialValue = 1; + double _thickness = thicknessInitialValue; static const int thicknessPropertyKey = 47; double get thickness => _thickness; @@ -33,14 +34,17 @@ abstract class StrokeBase extends ShapePaint { } double from = _thickness; _thickness = value; - thicknessChanged(from, value); + if (hasValidated) { + thicknessChanged(from, value); + } } void thicknessChanged(double from, double to); /// -------------------------------------------------------------------------- /// Cap field with key 48. - int _cap = 0; + static const int capInitialValue = 0; + int _cap = capInitialValue; static const int capPropertyKey = 48; int get cap => _cap; @@ -52,14 +56,17 @@ abstract class StrokeBase extends ShapePaint { } int from = _cap; _cap = value; - capChanged(from, value); + if (hasValidated) { + capChanged(from, value); + } } void capChanged(int from, int to); /// -------------------------------------------------------------------------- /// Join field with key 49. - int _join = 0; + static const int joinInitialValue = 0; + int _join = joinInitialValue; static const int joinPropertyKey = 49; int get join => _join; @@ -71,14 +78,17 @@ abstract class StrokeBase extends ShapePaint { } int from = _join; _join = value; - joinChanged(from, value); + if (hasValidated) { + joinChanged(from, value); + } } void joinChanged(int from, int to); /// -------------------------------------------------------------------------- /// TransformAffectsStroke field with key 50. - bool _transformAffectsStroke = true; + static const bool transformAffectsStrokeInitialValue = true; + bool _transformAffectsStroke = transformAffectsStrokeInitialValue; static const int transformAffectsStrokePropertyKey = 50; bool get transformAffectsStroke => _transformAffectsStroke; @@ -91,7 +101,9 @@ abstract class StrokeBase extends ShapePaint { } bool from = _transformAffectsStroke; _transformAffectsStroke = value; - transformAffectsStrokeChanged(from, value); + if (hasValidated) { + transformAffectsStrokeChanged(from, value); + } } void transformAffectsStrokeChanged(bool from, bool to); diff --git a/lib/src/generated/shapes/paint/trim_path_base.dart b/lib/src/generated/shapes/paint/trim_path_base.dart index 4b10e46..cac118c 100644 --- a/lib/src/generated/shapes/paint/trim_path_base.dart +++ b/lib/src/generated/shapes/paint/trim_path_base.dart @@ -14,7 +14,8 @@ abstract class TrimPathBase extends Component { /// -------------------------------------------------------------------------- /// Start field with key 114. - double _start = 0; + static const double startInitialValue = 0; + double _start = startInitialValue; static const int startPropertyKey = 114; double get start => _start; @@ -26,14 +27,17 @@ abstract class TrimPathBase extends Component { } double from = _start; _start = value; - startChanged(from, value); + if (hasValidated) { + startChanged(from, value); + } } void startChanged(double from, double to); /// -------------------------------------------------------------------------- /// End field with key 115. - double _end = 0; + static const double endInitialValue = 0; + double _end = endInitialValue; static const int endPropertyKey = 115; double get end => _end; @@ -45,14 +49,17 @@ abstract class TrimPathBase extends Component { } double from = _end; _end = value; - endChanged(from, value); + if (hasValidated) { + endChanged(from, value); + } } void endChanged(double from, double to); /// -------------------------------------------------------------------------- /// Offset field with key 116. - double _offset = 0; + static const double offsetInitialValue = 0; + double _offset = offsetInitialValue; static const int offsetPropertyKey = 116; double get offset => _offset; @@ -64,14 +71,17 @@ abstract class TrimPathBase extends Component { } double from = _offset; _offset = value; - offsetChanged(from, value); + if (hasValidated) { + offsetChanged(from, value); + } } void offsetChanged(double from, double to); /// -------------------------------------------------------------------------- /// ModeValue field with key 117. - int _modeValue = 0; + static const int modeValueInitialValue = 0; + int _modeValue = modeValueInitialValue; static const int modeValuePropertyKey = 117; int get modeValue => _modeValue; @@ -83,7 +93,9 @@ abstract class TrimPathBase extends Component { } int from = _modeValue; _modeValue = value; - modeValueChanged(from, value); + if (hasValidated) { + modeValueChanged(from, value); + } } void modeValueChanged(int from, int to); diff --git a/lib/src/generated/shapes/parametric_path_base.dart b/lib/src/generated/shapes/parametric_path_base.dart index 79ad3e6..070945d 100644 --- a/lib/src/generated/shapes/parametric_path_base.dart +++ b/lib/src/generated/shapes/parametric_path_base.dart @@ -25,7 +25,8 @@ abstract class ParametricPathBase extends Path { /// -------------------------------------------------------------------------- /// Width field with key 20. - double _width = 0; + static const double widthInitialValue = 0; + double _width = widthInitialValue; static const int widthPropertyKey = 20; /// Width of the parametric path. @@ -39,14 +40,17 @@ abstract class ParametricPathBase extends Path { } double from = _width; _width = value; - widthChanged(from, value); + if (hasValidated) { + widthChanged(from, value); + } } void widthChanged(double from, double to); /// -------------------------------------------------------------------------- /// Height field with key 21. - double _height = 0; + static const double heightInitialValue = 0; + double _height = heightInitialValue; static const int heightPropertyKey = 21; /// Height of the parametric path. @@ -60,14 +64,17 @@ abstract class ParametricPathBase extends Path { } double from = _height; _height = value; - heightChanged(from, value); + if (hasValidated) { + heightChanged(from, value); + } } void heightChanged(double from, double to); /// -------------------------------------------------------------------------- /// OriginX field with key 123. - double _originX = 0.5; + static const double originXInitialValue = 0.5; + double _originX = originXInitialValue; static const int originXPropertyKey = 123; /// Origin x in normalized coordinates (0.5 = center, 0 = left, 1 = right). @@ -81,14 +88,17 @@ abstract class ParametricPathBase extends Path { } double from = _originX; _originX = value; - originXChanged(from, value); + if (hasValidated) { + originXChanged(from, value); + } } void originXChanged(double from, double to); /// -------------------------------------------------------------------------- /// OriginY field with key 124. - double _originY = 0.5; + static const double originYInitialValue = 0.5; + double _originY = originYInitialValue; static const int originYPropertyKey = 124; /// Origin y in normalized coordinates (0.5 = center, 0 = top, 1 = bottom). @@ -102,7 +112,9 @@ abstract class ParametricPathBase extends Path { } double from = _originY; _originY = value; - originYChanged(from, value); + if (hasValidated) { + originYChanged(from, value); + } } void originYChanged(double from, double to); diff --git a/lib/src/generated/shapes/path_base.dart b/lib/src/generated/shapes/path_base.dart index affe8e7..5277d22 100644 --- a/lib/src/generated/shapes/path_base.dart +++ b/lib/src/generated/shapes/path_base.dart @@ -22,7 +22,8 @@ abstract class PathBase extends Node { /// -------------------------------------------------------------------------- /// PathFlags field with key 128. - int _pathFlags = 0; + static const int pathFlagsInitialValue = 0; + int _pathFlags = pathFlagsInitialValue; static const int pathFlagsPropertyKey = 128; int get pathFlags => _pathFlags; @@ -34,7 +35,9 @@ abstract class PathBase extends Node { } int from = _pathFlags; _pathFlags = value; - pathFlagsChanged(from, value); + if (hasValidated) { + pathFlagsChanged(from, value); + } } void pathFlagsChanged(int from, int to); diff --git a/lib/src/generated/shapes/path_vertex_base.dart b/lib/src/generated/shapes/path_vertex_base.dart index 7fabf55..5dc1819 100644 --- a/lib/src/generated/shapes/path_vertex_base.dart +++ b/lib/src/generated/shapes/path_vertex_base.dart @@ -18,7 +18,8 @@ abstract class PathVertexBase extends ContainerComponent { /// -------------------------------------------------------------------------- /// X field with key 24. - double _x; + static const double xInitialValue = 0; + double _x = xInitialValue; static const int xPropertyKey = 24; /// X value for the translation of the vertex. @@ -32,14 +33,17 @@ abstract class PathVertexBase extends ContainerComponent { } double from = _x; _x = value; - xChanged(from, value); + if (hasValidated) { + xChanged(from, value); + } } void xChanged(double from, double to); /// -------------------------------------------------------------------------- /// Y field with key 25. - double _y; + static const double yInitialValue = 0; + double _y = yInitialValue; static const int yPropertyKey = 25; /// Y value for the translation of the vertex. @@ -53,7 +57,9 @@ abstract class PathVertexBase extends ContainerComponent { } double from = _y; _y = value; - yChanged(from, value); + if (hasValidated) { + yChanged(from, value); + } } void yChanged(double from, double to); diff --git a/lib/src/generated/shapes/points_path_base.dart b/lib/src/generated/shapes/points_path_base.dart index bb98050..20fd2ec 100644 --- a/lib/src/generated/shapes/points_path_base.dart +++ b/lib/src/generated/shapes/points_path_base.dart @@ -24,7 +24,8 @@ abstract class PointsPathBase extends Path { /// -------------------------------------------------------------------------- /// IsClosed field with key 32. - bool _isClosed; + static const bool isClosedInitialValue = false; + bool _isClosed = isClosedInitialValue; static const int isClosedPropertyKey = 32; /// If the path should close back on its first vertex. @@ -39,7 +40,9 @@ abstract class PointsPathBase extends Path { } bool from = _isClosed; _isClosed = value; - isClosedChanged(from, value); + if (hasValidated) { + isClosedChanged(from, value); + } } void isClosedChanged(bool from, bool to); diff --git a/lib/src/generated/shapes/polygon_base.dart b/lib/src/generated/shapes/polygon_base.dart index 3f10c86..e2ad7a5 100644 --- a/lib/src/generated/shapes/polygon_base.dart +++ b/lib/src/generated/shapes/polygon_base.dart @@ -26,7 +26,8 @@ abstract class PolygonBase extends ParametricPath { /// -------------------------------------------------------------------------- /// Points field with key 125. - int _points = 5; + static const int pointsInitialValue = 5; + int _points = pointsInitialValue; static const int pointsPropertyKey = 125; /// The number of points for the polygon. @@ -40,14 +41,17 @@ abstract class PolygonBase extends ParametricPath { } int from = _points; _points = value; - pointsChanged(from, value); + if (hasValidated) { + pointsChanged(from, value); + } } void pointsChanged(int from, int to); /// -------------------------------------------------------------------------- /// CornerRadius field with key 126. - double _cornerRadius = 0; + static const double cornerRadiusInitialValue = 0; + double _cornerRadius = cornerRadiusInitialValue; static const int cornerRadiusPropertyKey = 126; /// The corner radius. @@ -62,7 +66,9 @@ abstract class PolygonBase extends ParametricPath { } double from = _cornerRadius; _cornerRadius = value; - cornerRadiusChanged(from, value); + if (hasValidated) { + cornerRadiusChanged(from, value); + } } void cornerRadiusChanged(double from, double to); diff --git a/lib/src/generated/shapes/rectangle_base.dart b/lib/src/generated/shapes/rectangle_base.dart index 31f2351..99df832 100644 --- a/lib/src/generated/shapes/rectangle_base.dart +++ b/lib/src/generated/shapes/rectangle_base.dart @@ -26,7 +26,8 @@ abstract class RectangleBase extends ParametricPath { /// -------------------------------------------------------------------------- /// CornerRadius field with key 31. - double _cornerRadius = 0; + static const double cornerRadiusInitialValue = 0; + double _cornerRadius = cornerRadiusInitialValue; static const int cornerRadiusPropertyKey = 31; /// Radius of the corners of this rectangle @@ -41,7 +42,9 @@ abstract class RectangleBase extends ParametricPath { } double from = _cornerRadius; _cornerRadius = value; - cornerRadiusChanged(from, value); + if (hasValidated) { + cornerRadiusChanged(from, value); + } } void cornerRadiusChanged(double from, double to); diff --git a/lib/src/generated/shapes/star_base.dart b/lib/src/generated/shapes/star_base.dart index 746a257..b5df447 100644 --- a/lib/src/generated/shapes/star_base.dart +++ b/lib/src/generated/shapes/star_base.dart @@ -28,7 +28,8 @@ abstract class StarBase extends Polygon { /// -------------------------------------------------------------------------- /// InnerRadius field with key 127. - double _innerRadius = 0.5; + static const double innerRadiusInitialValue = 0.5; + double _innerRadius = innerRadiusInitialValue; static const int innerRadiusPropertyKey = 127; /// Percentage of width/height to project inner points of the star. @@ -43,7 +44,9 @@ abstract class StarBase extends Polygon { } double from = _innerRadius; _innerRadius = value; - innerRadiusChanged(from, value); + if (hasValidated) { + innerRadiusChanged(from, value); + } } void innerRadiusChanged(double from, double to); diff --git a/lib/src/generated/shapes/straight_vertex_base.dart b/lib/src/generated/shapes/straight_vertex_base.dart index 278a09e..636df8a 100644 --- a/lib/src/generated/shapes/straight_vertex_base.dart +++ b/lib/src/generated/shapes/straight_vertex_base.dart @@ -22,7 +22,8 @@ abstract class StraightVertexBase extends PathVertex { /// -------------------------------------------------------------------------- /// Radius field with key 26. - double _radius = 0; + static const double radiusInitialValue = 0; + double _radius = radiusInitialValue; static const int radiusPropertyKey = 26; /// Radius of the vertex @@ -36,7 +37,9 @@ abstract class StraightVertexBase extends PathVertex { } double from = _radius; _radius = value; - radiusChanged(from, value); + if (hasValidated) { + radiusChanged(from, value); + } } void radiusChanged(double from, double to); diff --git a/lib/src/generated/transform_component_base.dart b/lib/src/generated/transform_component_base.dart index d947069..c13de90 100644 --- a/lib/src/generated/transform_component_base.dart +++ b/lib/src/generated/transform_component_base.dart @@ -19,7 +19,8 @@ abstract class TransformComponentBase extends ContainerComponent { /// -------------------------------------------------------------------------- /// Rotation field with key 15. - double _rotation = 0; + static const double rotationInitialValue = 0; + double _rotation = rotationInitialValue; static const int rotationPropertyKey = 15; double get rotation => _rotation; @@ -31,14 +32,17 @@ abstract class TransformComponentBase extends ContainerComponent { } double from = _rotation; _rotation = value; - rotationChanged(from, value); + if (hasValidated) { + rotationChanged(from, value); + } } void rotationChanged(double from, double to); /// -------------------------------------------------------------------------- /// ScaleX field with key 16. - double _scaleX = 1; + static const double scaleXInitialValue = 1; + double _scaleX = scaleXInitialValue; static const int scaleXPropertyKey = 16; double get scaleX => _scaleX; @@ -50,14 +54,17 @@ abstract class TransformComponentBase extends ContainerComponent { } double from = _scaleX; _scaleX = value; - scaleXChanged(from, value); + if (hasValidated) { + scaleXChanged(from, value); + } } void scaleXChanged(double from, double to); /// -------------------------------------------------------------------------- /// ScaleY field with key 17. - double _scaleY = 1; + static const double scaleYInitialValue = 1; + double _scaleY = scaleYInitialValue; static const int scaleYPropertyKey = 17; double get scaleY => _scaleY; @@ -69,14 +76,17 @@ abstract class TransformComponentBase extends ContainerComponent { } double from = _scaleY; _scaleY = value; - scaleYChanged(from, value); + if (hasValidated) { + scaleYChanged(from, value); + } } void scaleYChanged(double from, double to); /// -------------------------------------------------------------------------- /// Opacity field with key 18. - double _opacity = 1; + static const double opacityInitialValue = 1; + double _opacity = opacityInitialValue; static const int opacityPropertyKey = 18; double get opacity => _opacity; @@ -88,7 +98,9 @@ abstract class TransformComponentBase extends ContainerComponent { } double from = _opacity; _opacity = value; - opacityChanged(from, value); + if (hasValidated) { + opacityChanged(from, value); + } } void opacityChanged(double from, double to); diff --git a/lib/src/rive.dart b/lib/src/rive.dart index 6b4a111..a2cc9da 100644 --- a/lib/src/rive.dart +++ b/lib/src/rive.dart @@ -31,25 +31,18 @@ class Rive extends LeafRenderObjectWidget { final Alignment alignment; const Rive({ - @required - this.artboard, - @Deprecated("Replaced by [useArtboardSize] in order to avoid confusion " - "with Flutter's intrinsics contract.") - bool useIntrinsicSize, - bool useArtboardSize = false, + required this.artboard, + this.useArtboardSize = false, this.fit = BoxFit.contain, this.alignment = Alignment.center, - }) : assert(useArtboardSize != null), - useArtboardSize = useIntrinsicSize ?? useArtboardSize; + }); @override RenderObject createRenderObject(BuildContext context) { - return RiveRenderObject() - ..artboard = artboard + return RiveRenderObject(artboard as RuntimeArtboard) ..fit = fit ..alignment = alignment - ..artboardSize = - artboard == null ? Size.zero : Size(artboard.width, artboard.height) + ..artboardSize = Size(artboard.width, artboard.height) ..useArtboardSize = useArtboardSize; } @@ -60,8 +53,7 @@ class Rive extends LeafRenderObjectWidget { ..artboard = artboard ..fit = fit ..alignment = alignment - ..artboardSize = - artboard == null ? Size.zero : Size(artboard.width, artboard.height) + ..artboardSize = Size(artboard.width, artboard.height) ..useArtboardSize = useArtboardSize; } @@ -73,6 +65,9 @@ class Rive extends LeafRenderObjectWidget { class RiveRenderObject extends RiveRenderBox { RuntimeArtboard _artboard; + RiveRenderObject(this._artboard) { + _artboard.redraw.addListener(scheduleRepaint); + } RuntimeArtboard get artboard => _artboard; @@ -80,15 +75,13 @@ class RiveRenderObject extends RiveRenderBox { if (_artboard == value) { return; } - _artboard?.redraw?.removeListener(scheduleRepaint); + _artboard.redraw.removeListener(scheduleRepaint); _artboard = value as RuntimeArtboard; - _artboard?.redraw?.addListener(scheduleRepaint); + _artboard.redraw.addListener(scheduleRepaint); markNeedsLayout(); } - void dispose() { - _artboard?.redraw?.removeListener(scheduleRepaint); - } + void dispose() => _artboard.redraw.removeListener(scheduleRepaint); @override AABB get aabb { diff --git a/lib/src/rive_core/animation/animation.dart b/lib/src/rive_core/animation/animation.dart index d8c59d0..a1afb27 100644 --- a/lib/src/rive_core/animation/animation.dart +++ b/lib/src/rive_core/animation/animation.dart @@ -4,9 +4,9 @@ import 'package:rive/src/generated/animation/animation_base.dart'; export 'package:rive/src/generated/animation/animation_base.dart'; class Animation extends AnimationBase { - Artboard _artboard; - Artboard get artboard => _artboard; - set artboard(Artboard value) { + Artboard? _artboard; + Artboard? get artboard => _artboard; + set artboard(Artboard? value) { if (_artboard == value) { return; } @@ -15,15 +15,12 @@ class Animation extends AnimationBase { _artboard?.internalAddAnimation(this); } - @override - void onAdded() {} @override void onAddedDirty() {} @override - void onRemoved() { - artboard = null; - } - + void onAdded() {} + @override + bool validate() => super.validate() && _artboard != null; @override void nameChanged(String from, String to) {} } diff --git a/lib/src/rive_core/animation/animation_state.dart b/lib/src/rive_core/animation/animation_state.dart new file mode 100644 index 0000000..5cb2c3f --- /dev/null +++ b/lib/src/rive_core/animation/animation_state.dart @@ -0,0 +1,26 @@ +import 'package:rive/src/core/core.dart'; +import 'package:rive/src/rive_core/animation/linear_animation.dart'; +import 'package:rive/src/generated/animation/animation_state_base.dart'; +export 'package:rive/src/generated/animation/animation_state_base.dart'; + +class AnimationState extends AnimationStateBase { + @override + String toString() { + return '${super.toString()} ($id) -> ${_animation?.name}'; + } + + LinearAnimation? _animation; + LinearAnimation? get animation => _animation; + set animation(LinearAnimation? value) { + if (_animation == value) { + return; + } + _animation = value; + animationId = value?.id ?? Core.missingId; + } + + @override + void animationIdChanged(int from, int to) { + animation = id == Core.missingId ? null : context.resolve(to); + } +} diff --git a/lib/src/rive_core/animation/any_state.dart b/lib/src/rive_core/animation/any_state.dart new file mode 100644 index 0000000..116405f --- /dev/null +++ b/lib/src/rive_core/animation/any_state.dart @@ -0,0 +1,4 @@ +import 'package:rive/src/generated/animation/any_state_base.dart'; +export 'package:rive/src/generated/animation/any_state_base.dart'; + +class AnyState extends AnyStateBase {} diff --git a/lib/src/rive_core/animation/cubic_interpolator.dart b/lib/src/rive_core/animation/cubic_interpolator.dart index 430fb6b..c972192 100644 --- a/lib/src/rive_core/animation/cubic_interpolator.dart +++ b/lib/src/rive_core/animation/cubic_interpolator.dart @@ -1,5 +1,7 @@ import 'dart:typed_data'; +import 'package:rive/src/core/core.dart'; import 'package:rive/src/rive_core/animation/interpolator.dart'; +import 'package:rive/src/rive_core/artboard.dart'; import 'package:rive/src/generated/animation/cubic_interpolator_base.dart'; const int newtonIterations = 4; @@ -21,7 +23,7 @@ double _getSlope(double aT, double aA1, double aA2) { } class CubicInterpolator extends CubicInterpolatorBase implements Interpolator { - _CubicEase _ease; + _CubicEase _ease = _CubicEase.make(0.42, 0, 0.58, 1); @override bool equalParameters(Interpolator other) { if (other is CubicInterpolator) { @@ -34,15 +36,10 @@ class CubicInterpolator extends CubicInterpolatorBase implements Interpolator { } @override - void onAdded() { - _updateStoredCubic(); - } - + void onAdded() => _updateStoredCubic(); @override void onAddedDirty() {} @override - void onRemoved() {} - @override double transform(double value) => _ease.transform(value); @override void x1Changed(double from, double to) => _updateStoredCubic(); @@ -55,13 +52,22 @@ class CubicInterpolator extends CubicInterpolatorBase implements Interpolator { void _updateStoredCubic() { _ease = _CubicEase.make(x1, y1, x2, y2); } + + @override + bool import(ImportStack stack) { + var artboardHelper = stack.latest(ArtboardBase.typeKey); + if (artboardHelper == null) { + return false; + } + artboardHelper.addComponent(this); + return super.import(stack); + } } class _Cubic extends _CubicEase { - Float64List _values; + final Float64List _values = Float64List(splineTableSize); final double x1, y1, x2, y2; _Cubic(this.x1, this.y1, this.x2, this.y2) { - _values = Float64List(splineTableSize); for (int i = 0; i < splineTableSize; ++i) { _values[i] = _calcBezier(i * sampleStepSize, x1, x2); } diff --git a/lib/src/rive_core/animation/entry_state.dart b/lib/src/rive_core/animation/entry_state.dart new file mode 100644 index 0000000..81f9c97 --- /dev/null +++ b/lib/src/rive_core/animation/entry_state.dart @@ -0,0 +1,4 @@ +import 'package:rive/src/generated/animation/entry_state_base.dart'; +export 'package:rive/src/generated/animation/entry_state_base.dart'; + +class EntryState extends EntryStateBase {} diff --git a/lib/src/rive_core/animation/exit_state.dart b/lib/src/rive_core/animation/exit_state.dart new file mode 100644 index 0000000..a8e6e1c --- /dev/null +++ b/lib/src/rive_core/animation/exit_state.dart @@ -0,0 +1,4 @@ +import 'package:rive/src/generated/animation/exit_state_base.dart'; +export 'package:rive/src/generated/animation/exit_state_base.dart'; + +class ExitState extends ExitStateBase {} diff --git a/lib/src/rive_core/animation/keyed_object.dart b/lib/src/rive_core/animation/keyed_object.dart index c4bf8ab..d752b70 100644 --- a/lib/src/rive_core/animation/keyed_object.dart +++ b/lib/src/rive_core/animation/keyed_object.dart @@ -1,7 +1,9 @@ import 'dart:collection'; import 'package:rive/src/core/core.dart'; import 'package:rive/src/rive_core/animation/keyed_property.dart'; +import 'package:rive/src/rive_core/component.dart'; import 'package:rive/src/generated/animation/keyed_object_base.dart'; +import 'linear_animation.dart'; export 'package:rive/src/generated/animation/keyed_object_base.dart'; class KeyedObject extends KeyedObjectBase { @@ -9,11 +11,34 @@ class KeyedObject extends KeyedObjectBase { HashMap(); Iterable get keyedProperties => _keyedProperties.values; @override - void onAdded() {} - @override void onAddedDirty() {} @override - void onRemoved() {} + void onAdded() {} + @override + bool validate() { + if (!super.validate()) { + return false; + } + var component = context.resolve(objectId); + if (component == null) { + return false; + } + return true; + } + + @override + void onRemoved() { + super.onRemoved(); + } + + bool isValidKeyedProperty(KeyedProperty property) { + var value = _keyedProperties[property.propertyKey]; + if (value != null && value != property) { + return false; + } + return true; + } + bool internalAddKeyedProperty(KeyedProperty property) { var value = _keyedProperties[property.propertyKey]; if (value != null && value != property) { @@ -32,7 +57,7 @@ class KeyedObject extends KeyedObjectBase { } void apply(double time, double mix, CoreContext coreContext) { - Core object = coreContext.resolve(objectId); + Core? object = coreContext.resolve(objectId); if (object == null) { return; } @@ -43,4 +68,14 @@ class KeyedObject extends KeyedObjectBase { @override void objectIdChanged(int from, int to) {} + @override + bool import(ImportStack stack) { + var animationHelper = + stack.latest(LinearAnimationBase.typeKey); + if (animationHelper == null) { + return false; + } + animationHelper.addKeyedObject(this); + return super.import(stack); + } } diff --git a/lib/src/rive_core/animation/keyed_property.dart b/lib/src/rive_core/animation/keyed_property.dart index 7b2d6ae..5a9cec8 100644 --- a/lib/src/rive_core/animation/keyed_property.dart +++ b/lib/src/rive_core/animation/keyed_property.dart @@ -1,4 +1,5 @@ import 'package:rive/src/core/core.dart'; +import 'package:rive/src/rive_core/animation/keyed_object.dart'; import 'package:rive/src/rive_core/animation/keyframe.dart'; import 'package:rive/src/generated/animation/keyed_property_base.dart'; export 'package:rive/src/generated/animation/keyed_property_base.dart'; @@ -11,7 +12,7 @@ class KeyFrameList { List _keyframes = []; Iterable get keyframes => _keyframes; set keyframes(Iterable frames) => _keyframes = frames.toList(); - T after(T keyframe) { + T? after(T keyframe) { var index = _keyframes.indexOf(keyframe); if (index != -1 && index + 1 < _keyframes.length) { return _keyframes[index + 1]; @@ -51,7 +52,10 @@ class KeyedProperty extends KeyedPropertyBase @override void onAddedDirty() {} @override - void onRemoved() {} + void onRemoved() { + super.onRemoved(); + } + bool internalAddKeyFrame(KeyFrame frame) { if (_keyframes.contains(frame)) { return false; @@ -64,19 +68,19 @@ class KeyedProperty extends KeyedPropertyBase bool internalRemoveKeyFrame(KeyFrame frame) { var removed = _keyframes.remove(frame); if (_keyframes.isEmpty) { - context?.dirty(_checkShouldRemove); + context.dirty(_checkShouldRemove); } return removed; } void _checkShouldRemove() { if (_keyframes.isEmpty) { - context?.removeObject(this); + context.removeObject(this); } } void markKeyFrameOrderDirty() { - context?.dirty(_sortAndValidateKeyFrames); + context.dirty(_sortAndValidateKeyFrames); } void _sortAndValidateKeyFrames() { @@ -146,4 +150,13 @@ class KeyedProperty extends KeyedPropertyBase @override void propertyKeyChanged(int from, int to) {} + @override + bool import(ImportStack stack) { + var importer = stack.latest(KeyedObjectBase.typeKey); + if (importer == null) { + return false; + } + importer.addKeyedProperty(this); + return super.import(stack); + } } diff --git a/lib/src/rive_core/animation/keyframe.dart b/lib/src/rive_core/animation/keyframe.dart index 39b924a..49a1747 100644 --- a/lib/src/rive_core/animation/keyframe.dart +++ b/lib/src/rive_core/animation/keyframe.dart @@ -8,12 +8,11 @@ export 'package:rive/src/generated/animation/keyframe_base.dart'; abstract class KeyFrame extends KeyFrameBase implements KeyFrameInterface { - double _timeInSeconds; + double _timeInSeconds = 0; double get seconds => _timeInSeconds; bool get canInterpolate => true; - KeyFrameInterpolation get interpolation => interpolationType == null - ? null - : KeyFrameInterpolation.values[interpolationType]; + KeyFrameInterpolation get interpolation => + KeyFrameInterpolation.values[interpolationType]; set interpolation(KeyFrameInterpolation value) { interpolationType = value.index; } @@ -22,7 +21,7 @@ abstract class KeyFrame extends KeyFrameBase void interpolationTypeChanged(int from, int to) {} @override void interpolatorIdChanged(int from, int to) { - interpolator = context?.resolve(to); + interpolator = context.resolve(to); } @override @@ -33,25 +32,39 @@ abstract class KeyFrame extends KeyFrameBase @override void onAddedDirty() { - if (interpolatorId != null) { - interpolator = context?.resolve(interpolatorId); + if (interpolatorId != Core.missingId) { + interpolator = context.resolve(interpolatorId); } } @override - void onRemoved() {} + void onRemoved() { + super.onRemoved(); + } + @override void frameChanged(int from, int to) {} void apply(Core object, int propertyKey, double mix); void applyInterpolation(Core object, int propertyKey, double seconds, covariant KeyFrame nextFrame, double mix); - Interpolator _interpolator; - Interpolator get interpolator => _interpolator; - set interpolator(Interpolator value) { + Interpolator? _interpolator; + Interpolator? get interpolator => _interpolator; + set interpolator(Interpolator? value) { if (_interpolator == value) { return; } _interpolator = value; - interpolatorId = value?.id; + interpolatorId = value?.id ?? Core.missingId; + } + + @override + bool import(ImportStack importStack) { + var keyedPropertyHelper = + importStack.latest(KeyedPropertyBase.typeKey); + if (keyedPropertyHelper == null) { + return false; + } + keyedPropertyHelper.addKeyFrame(this); + return super.import(importStack); } } diff --git a/lib/src/rive_core/animation/keyframe_color.dart b/lib/src/rive_core/animation/keyframe_color.dart index 39a905c..9b3b8d2 100644 --- a/lib/src/rive_core/animation/keyframe_color.dart +++ b/lib/src/rive_core/animation/keyframe_color.dart @@ -13,7 +13,9 @@ void _apply(Core object, int propertyKey, double mix, int value) { Color(RiveCoreContext.getColor(object, propertyKey)), Color(value), mix); - RiveCoreContext.setColor(object, propertyKey, mixedColor.value); + if (mixedColor != null) { + RiveCoreContext.setColor(object, propertyKey, mixedColor.value); + } } } @@ -21,21 +23,20 @@ class KeyFrameColor extends KeyFrameColorBase { @override void apply(Core object, int propertyKey, double mix) => _apply(object, propertyKey, mix, value); - @override - void onAdded() { - super.onAdded(); - interpolation ??= KeyFrameInterpolation.linear; + KeyFrameColor() { + interpolation = KeyFrameInterpolation.linear; } - @override void applyInterpolation(Core object, int propertyKey, double currentTime, KeyFrameColor nextFrame, double mix) { var f = (currentTime - seconds) / (nextFrame.seconds - seconds); if (interpolator != null) { - f = interpolator.transform(f); + f = interpolator!.transform(f); + } + var color = Color.lerp(Color(value), Color(nextFrame.value), f); + if (color != null) { + _apply(object, propertyKey, mix, color.value); } - _apply(object, propertyKey, mix, - Color.lerp(Color(value), Color(nextFrame.value), f).value); } @override diff --git a/lib/src/rive_core/animation/keyframe_double.dart b/lib/src/rive_core/animation/keyframe_double.dart index 0e7dac3..ada181a 100644 --- a/lib/src/rive_core/animation/keyframe_double.dart +++ b/lib/src/rive_core/animation/keyframe_double.dart @@ -4,6 +4,10 @@ import 'package:rive/src/generated/animation/keyframe_double_base.dart'; import 'package:rive/src/generated/rive_core_context.dart'; export 'package:rive/src/generated/animation/keyframe_double_base.dart'; +double toDegrees(double rad) { + return rad / 3.14 * 180; +} + void _apply( Core object, int propertyKey, double mix, double value) { if (mix == 1) { @@ -19,18 +23,15 @@ class KeyFrameDouble extends KeyFrameDoubleBase { @override void apply(Core object, int propertyKey, double mix) => _apply(object, propertyKey, mix, value); - @override - void onAdded() { - super.onAdded(); - interpolation ??= KeyFrameInterpolation.linear; + KeyFrameDouble() { + interpolation = KeyFrameInterpolation.linear; } - @override void applyInterpolation(Core object, int propertyKey, double currentTime, KeyFrameDouble nextFrame, double mix) { var f = (currentTime - seconds) / (nextFrame.seconds - seconds); if (interpolator != null) { - f = interpolator.transform(f); + f = interpolator!.transform(f); } _apply(object, propertyKey, mix, value + (nextFrame.value - value) * f); } diff --git a/lib/src/rive_core/animation/keyframe_id.dart b/lib/src/rive_core/animation/keyframe_id.dart index fe13552..235029c 100644 --- a/lib/src/rive_core/animation/keyframe_id.dart +++ b/lib/src/rive_core/animation/keyframe_id.dart @@ -1,5 +1,4 @@ import 'package:rive/src/core/core.dart'; -import 'package:rive/src/rive_core/animation/keyframe_interpolation.dart'; import 'package:rive/src/generated/animation/keyframe_id_base.dart'; import 'package:rive/src/generated/rive_core_context.dart'; export 'package:rive/src/generated/animation/keyframe_id_base.dart'; @@ -12,12 +11,6 @@ class KeyFrameId extends KeyFrameIdBase { RiveCoreContext.setUint(object, propertyKey, value); } - @override - void onAdded() { - super.onAdded(); - interpolation ??= KeyFrameInterpolation.hold; - } - @override void applyInterpolation(Core object, int propertyKey, double currentTime, KeyFrameId nextFrame, double mix) { diff --git a/lib/src/rive_core/animation/layer_state.dart b/lib/src/rive_core/animation/layer_state.dart new file mode 100644 index 0000000..324c175 --- /dev/null +++ b/lib/src/rive_core/animation/layer_state.dart @@ -0,0 +1,37 @@ +import 'package:rive/src/core/core.dart'; +import 'package:rive/src/rive_core/animation/state_machine_layer.dart'; +import 'package:rive/src/rive_core/animation/state_transition.dart'; +import 'package:rive/src/generated/animation/layer_state_base.dart'; +export 'package:rive/src/generated/animation/layer_state_base.dart'; + +abstract class LayerState extends LayerStateBase { + final Set _transitions = {}; + Iterable get transitions => _transitions; + @override + void onAdded() {} + @override + void onAddedDirty() {} + void internalAddTransition(StateTransition transition) { + _transitions.add(transition); + } + + void internalRemoveTransition(StateTransition transition) { + _transitions.remove(transition); + } + + @override + void onRemoved() { + super.onRemoved(); + } + + @override + bool import(ImportStack stack) { + var importer = + stack.latest(StateMachineLayerBase.typeKey); + if (importer == null) { + return false; + } + importer.addState(this); + return super.import(stack); + } +} diff --git a/lib/src/rive_core/animation/linear_animation.dart b/lib/src/rive_core/animation/linear_animation.dart index 92c1162..9c6c239 100644 --- a/lib/src/rive_core/animation/linear_animation.dart +++ b/lib/src/rive_core/animation/linear_animation.dart @@ -2,6 +2,7 @@ import 'dart:collection'; import 'package:rive/src/core/core.dart'; import 'package:rive/src/rive_core/animation/keyed_object.dart'; import 'package:rive/src/rive_core/animation/loop.dart'; +import 'package:rive/src/rive_core/artboard.dart'; import 'package:rive/src/generated/animation/linear_animation_base.dart'; export 'package:rive/src/generated/animation/linear_animation_base.dart'; @@ -9,20 +10,22 @@ class LinearAnimation extends LinearAnimationBase { final _keyedObjects = HashMap(); Iterable get keyedObjects => _keyedObjects.values; bool internalAddKeyedObject(KeyedObject object) { - assert( - object.objectId != null, - 'KeyedObject must be referencing a Core object ' - 'before being added to an animation.'); + if (internalCheckAddKeyedObject(object)) { + _keyedObjects[object.objectId] = object; + return true; + } + return false; + } + + bool internalCheckAddKeyedObject(KeyedObject object) { var value = _keyedObjects[object.objectId]; if (value != null && value != object) { return false; } - _keyedObjects[object.objectId] = object; return true; } - void apply(double time, {double mix = 1, CoreContext coreContext}) { - coreContext ??= context; + void apply(double time, {required CoreContext coreContext, double mix = 1}) { for (final keyedObject in _keyedObjects.values) { keyedObject.apply(time, mix, coreContext); } @@ -44,4 +47,13 @@ class LinearAnimation extends LinearAnimationBase { void workEndChanged(int from, int to) {} @override void workStartChanged(int from, int to) {} + @override + bool import(ImportStack stack) { + var artboardImporter = stack.latest(ArtboardBase.typeKey); + if (artboardImporter == null) { + return false; + } + artboardImporter.addAnimation(this); + return super.import(stack); + } } diff --git a/lib/src/rive_core/animation/linear_animation_instance.dart b/lib/src/rive_core/animation/linear_animation_instance.dart index 1f8b6f9..9a7b461 100644 --- a/lib/src/rive_core/animation/linear_animation_instance.dart +++ b/lib/src/rive_core/animation/linear_animation_instance.dart @@ -5,6 +5,10 @@ class LinearAnimationInstance { final LinearAnimation animation; double _time = 0; int _direction = 1; + bool _didLoop = false; + bool get didLoop => _didLoop; + double _spilledTime = 0; + double get spilledTime => _spilledTime; LinearAnimationInstance(this.animation) : _time = (animation.enableWorkArea ? animation.workStart : 0).toDouble() / @@ -27,7 +31,9 @@ class LinearAnimationInstance { double get startTime => (animation.enableWorkArea ? animation.workStart : 0).toDouble() / animation.fps; + double get progress => (_time - startTime) / (endTime - startTime); void reset() => _time = startTime; + bool get keepGoing => animation.loop != Loop.oneShot || !_didLoop; bool advance(double elapsedSeconds) { _time += elapsedSeconds * animation.speed * _direction; double frames = _time * animation.fps; @@ -35,31 +41,41 @@ class LinearAnimationInstance { var end = animation.enableWorkArea ? animation.workEnd : animation.duration; var range = end - start; bool keepGoing = true; + _didLoop = false; + _spilledTime = 0; switch (animation.loop) { case Loop.oneShot: if (frames > end) { keepGoing = false; + _spilledTime = (frames - end) / animation.fps; frames = end.toDouble(); _time = frames / animation.fps; + _didLoop = true; } break; case Loop.loop: if (frames >= end) { + _spilledTime = (frames - end) / animation.fps; frames = _time * animation.fps; frames = start + (frames - start) % range; _time = frames / animation.fps; + _didLoop = true; } break; case Loop.pingPong: while (true) { if (_direction == 1 && frames >= end) { + _spilledTime = (frames - end) / animation.fps; _direction = -1; frames = end + (end - frames); _time = frames / animation.fps; + _didLoop = true; } else if (_direction == -1 && frames < start) { + _spilledTime = (start - frames) / animation.fps; _direction = 1; frames = start + (start - frames); _time = frames / animation.fps; + _didLoop = true; } else { break; } diff --git a/lib/src/rive_core/animation/state_machine.dart b/lib/src/rive_core/animation/state_machine.dart new file mode 100644 index 0000000..e4009a9 --- /dev/null +++ b/lib/src/rive_core/animation/state_machine.dart @@ -0,0 +1,22 @@ +import 'package:rive/src/core/core.dart'; +import 'package:rive/src/rive_core/animation/state_machine_input.dart'; +import 'package:rive/src/rive_core/animation/state_machine_layer.dart'; +import 'package:rive/src/rive_core/artboard.dart'; +import 'package:rive/src/generated/animation/state_machine_base.dart'; +export 'package:rive/src/generated/animation/state_machine_base.dart'; + +class StateMachine extends StateMachineBase { + final StateMachineComponents inputs = + StateMachineComponents(); + final StateMachineComponents layers = + StateMachineComponents(); + @override + bool import(ImportStack stack) { + var artboardImporter = stack.latest(ArtboardBase.typeKey); + if (artboardImporter == null) { + return false; + } + artboardImporter.addStateMachine(this); + return super.import(stack); + } +} diff --git a/lib/src/rive_core/animation/state_machine_bool.dart b/lib/src/rive_core/animation/state_machine_bool.dart new file mode 100644 index 0000000..36601c3 --- /dev/null +++ b/lib/src/rive_core/animation/state_machine_bool.dart @@ -0,0 +1,11 @@ +import 'package:rive/src/generated/animation/state_machine_bool_base.dart'; +export 'package:rive/src/generated/animation/state_machine_bool_base.dart'; + +class StateMachineBool extends StateMachineBoolBase { + @override + void valueChanged(bool from, bool to) {} + @override + bool isValidType() => T == bool; + @override + dynamic get controllerValue => value; +} diff --git a/lib/src/rive_core/animation/state_machine_component.dart b/lib/src/rive_core/animation/state_machine_component.dart new file mode 100644 index 0000000..710bf83 --- /dev/null +++ b/lib/src/rive_core/animation/state_machine_component.dart @@ -0,0 +1,44 @@ +import 'dart:collection'; +import 'package:rive/src/core/core.dart'; +import 'package:rive/src/rive_core/animation/state_machine.dart'; +import 'package:rive/src/generated/animation/state_machine_component_base.dart'; +export 'package:rive/src/generated/animation/state_machine_component_base.dart'; + +abstract class StateMachineComponent extends StateMachineComponentBase { + StateMachine? _stateMachine; + StateMachine? get stateMachine => _stateMachine; + set stateMachine(StateMachine? machine) { + if (_stateMachine == machine) { + return; + } + if (_stateMachine != null) { + machineComponentList(_stateMachine!).remove(this); + } + _stateMachine = machine; + if (_stateMachine != null) { + machineComponentList(_stateMachine!).add(this); + } + } + + ListBase machineComponentList(StateMachine machine); + @override + void nameChanged(String from, String to) {} + @override + void onAddedDirty() {} + @override + void onRemoved() { + super.onRemoved(); + stateMachine = null; + } + + @override + bool import(ImportStack importStack) { + var importer = + importStack.latest(StateMachineBase.typeKey); + if (importer == null) { + return false; + } + importer.addMachineComponent(this); + return super.import(importStack); + } +} diff --git a/lib/src/rive_core/animation/state_machine_double.dart b/lib/src/rive_core/animation/state_machine_double.dart new file mode 100644 index 0000000..1fe1463 --- /dev/null +++ b/lib/src/rive_core/animation/state_machine_double.dart @@ -0,0 +1,11 @@ +import 'package:rive/src/generated/animation/state_machine_double_base.dart'; +export 'package:rive/src/generated/animation/state_machine_double_base.dart'; + +class StateMachineDouble extends StateMachineDoubleBase { + @override + void valueChanged(double from, double to) {} + @override + bool isValidType() => T == double; + @override + dynamic get controllerValue => value; +} diff --git a/lib/src/rive_core/animation/state_machine_input.dart b/lib/src/rive_core/animation/state_machine_input.dart new file mode 100644 index 0000000..2f9ff4b --- /dev/null +++ b/lib/src/rive_core/animation/state_machine_input.dart @@ -0,0 +1,16 @@ +import 'dart:collection'; +import 'package:rive/src/rive_core/animation/state_machine.dart'; +import 'package:rive/src/rive_core/animation/state_machine_component.dart'; +import 'package:rive/src/generated/animation/state_machine_input_base.dart'; +export 'package:rive/src/generated/animation/state_machine_input_base.dart'; + +abstract class StateMachineInput extends StateMachineInputBase { + static final StateMachineInput unknown = _StateMachineUnknownInput(); + @override + ListBase machineComponentList(StateMachine machine) => + machine.inputs; + bool isValidType() => false; + dynamic get controllerValue => null; +} + +class _StateMachineUnknownInput extends StateMachineInput {} diff --git a/lib/src/rive_core/animation/state_machine_layer.dart b/lib/src/rive_core/animation/state_machine_layer.dart new file mode 100644 index 0000000..f9caa2c --- /dev/null +++ b/lib/src/rive_core/animation/state_machine_layer.dart @@ -0,0 +1,36 @@ +import 'dart:collection'; +import 'package:rive/src/rive_core/animation/any_state.dart'; +import 'package:rive/src/rive_core/animation/entry_state.dart'; +import 'package:rive/src/rive_core/animation/exit_state.dart'; +import 'package:rive/src/rive_core/animation/layer_state.dart'; +import 'package:rive/src/rive_core/animation/state_machine.dart'; +import 'package:rive/src/rive_core/animation/state_machine_component.dart'; +import 'package:rive/src/generated/animation/any_state_base.dart'; +import 'package:rive/src/generated/animation/state_machine_layer_base.dart'; +export 'package:rive/src/generated/animation/state_machine_layer_base.dart'; + +class StateMachineLayer extends StateMachineLayerBase { + LayerState? _entryState; + LayerState? _anyState; + LayerState? _exitState; + LayerState? get entryState => _entryState; + LayerState? get anyState => _anyState; + LayerState? get exitState => _exitState; + @override + ListBase machineComponentList(StateMachine machine) => + machine.layers; + bool internalAddState(LayerState state) { + switch (state.coreType) { + case AnyStateBase.typeKey: + _anyState = state; + break; + case ExitStateBase.typeKey: + _exitState = state; + break; + case EntryStateBase.typeKey: + _entryState = state; + break; + } + return true; + } +} diff --git a/lib/src/rive_core/animation/state_machine_layer_component.dart b/lib/src/rive_core/animation/state_machine_layer_component.dart new file mode 100644 index 0000000..0b41057 --- /dev/null +++ b/lib/src/rive_core/animation/state_machine_layer_component.dart @@ -0,0 +1,6 @@ +import 'package:rive/src/core/core.dart'; +import 'package:rive/src/generated/animation/state_machine_layer_component_base.dart'; +export 'package:rive/src/generated/animation/state_machine_layer_component_base.dart'; + +abstract class StateMachineLayerComponent + extends StateMachineLayerComponentBase {} diff --git a/lib/src/rive_core/animation/state_machine_trigger.dart b/lib/src/rive_core/animation/state_machine_trigger.dart new file mode 100644 index 0000000..b265ced --- /dev/null +++ b/lib/src/rive_core/animation/state_machine_trigger.dart @@ -0,0 +1,19 @@ +import 'package:rive/src/generated/animation/state_machine_trigger_base.dart'; +export 'package:rive/src/generated/animation/state_machine_trigger_base.dart'; + +class StateMachineTrigger extends StateMachineTriggerBase { + bool _triggered = false; + bool get triggered => _triggered; + void fire() { + _triggered = true; + } + + void reset() { + _triggered = false; + } + + @override + bool isValidType() => T == bool; + @override + dynamic get controllerValue => _triggered; +} diff --git a/lib/src/rive_core/animation/state_transition.dart b/lib/src/rive_core/animation/state_transition.dart new file mode 100644 index 0000000..10a5ba0 --- /dev/null +++ b/lib/src/rive_core/animation/state_transition.dart @@ -0,0 +1,57 @@ +import 'package:rive/src/core/core.dart'; +import 'package:rive/src/rive_core/animation/layer_state.dart'; +import 'package:rive/src/rive_core/animation/transition_condition.dart'; +import 'package:rive/src/generated/animation/state_transition_base.dart'; +import 'package:rive/src/rive_core/state_transition_flags.dart'; +export 'package:rive/src/generated/animation/state_transition_base.dart'; + +class StateTransition extends StateTransitionBase { + final StateTransitionConditions conditions = StateTransitionConditions(); + LayerState? stateTo; + static final StateTransition unknown = StateTransition(); + @override + bool validate() { + return super.validate() && stateTo != null; + } + + @override + void onAdded() {} + @override + void onAddedDirty() {} + @override + void onRemoved() { + super.onRemoved(); + } + + bool get isDisabled => (flags & StateTransitionFlags.disabled) != 0; + @override + bool import(ImportStack importStack) { + var importer = + importStack.latest(LayerStateBase.typeKey); + if (importer == null) { + return false; + } + importer.addTransition(this); + return super.import(importStack); + } + + bool internalAddCondition(TransitionCondition condition) { + if (conditions.contains(condition)) { + return false; + } + conditions.add(condition); + return true; + } + + bool internalRemoveCondition(TransitionCondition condition) { + var removed = conditions.remove(condition); + return removed; + } + + @override + void flagsChanged(int from, int to) {} + @override + void durationChanged(int from, int to) {} + @override + void stateToIdChanged(int from, int to) {} +} diff --git a/lib/src/rive_core/animation/transition_bool_condition.dart b/lib/src/rive_core/animation/transition_bool_condition.dart new file mode 100644 index 0000000..aafba6d --- /dev/null +++ b/lib/src/rive_core/animation/transition_bool_condition.dart @@ -0,0 +1,16 @@ +import 'dart:collection'; +import 'package:rive/src/rive_core/animation/state_machine_bool.dart'; +import 'package:rive/src/rive_core/animation/transition_condition.dart'; +import 'package:rive/src/generated/animation/transition_bool_condition_base.dart'; +export 'package:rive/src/generated/animation/transition_bool_condition_base.dart'; + +class TransitionBoolCondition extends TransitionBoolConditionBase { + @override + bool evaluate(HashMap values) { + var boolInput = input as StateMachineBool; + dynamic providedValue = values[input.id]; + bool value = providedValue is bool ? providedValue : boolInput.value; + return (value && op == TransitionConditionOp.equal) || + (!value && op == TransitionConditionOp.notEqual); + } +} diff --git a/lib/src/rive_core/animation/transition_condition.dart b/lib/src/rive_core/animation/transition_condition.dart new file mode 100644 index 0000000..79bb752 --- /dev/null +++ b/lib/src/rive_core/animation/transition_condition.dart @@ -0,0 +1,51 @@ +import 'dart:collection'; +import 'package:rive/src/core/core.dart'; +import 'package:rive/src/rive_core/animation/state_machine_input.dart'; +import 'package:rive/src/rive_core/animation/state_transition.dart'; +import 'package:rive/src/generated/animation/transition_condition_base.dart'; +export 'package:rive/src/generated/animation/transition_condition_base.dart'; + +enum TransitionConditionOp { + equal, + notEqual, + lessThanOrEqual, + greaterThanOrEqual, + lessThan, + greaterThan +} + +abstract class TransitionCondition extends TransitionConditionBase { + StateMachineInput _input = StateMachineInput.unknown; + StateMachineInput get input => _input; + set input(StateMachineInput value) { + if (_input == value) { + return; + } + _input = value; + inputId = _input.id; + } + + @override + void inputIdChanged(int from, int to) { + input = context.resolveWithDefault(to, StateMachineInput.unknown); + } + + @override + void onAdded() {} + @override + void onAddedDirty() { + input = context.resolveWithDefault(inputId, StateMachineInput.unknown); + } + + bool evaluate(HashMap values); + @override + bool import(ImportStack importStack) { + var importer = importStack + .latest(StateTransitionBase.typeKey); + if (importer == null) { + return false; + } + importer.addCondition(this); + return super.import(importStack); + } +} diff --git a/lib/src/rive_core/animation/transition_double_condition.dart b/lib/src/rive_core/animation/transition_double_condition.dart new file mode 100644 index 0000000..e823275 --- /dev/null +++ b/lib/src/rive_core/animation/transition_double_condition.dart @@ -0,0 +1,31 @@ +import 'dart:collection'; +import 'package:rive/src/rive_core/animation/state_machine_double.dart'; +import 'package:rive/src/rive_core/animation/transition_condition.dart'; +import 'package:rive/src/generated/animation/transition_double_condition_base.dart'; +export 'package:rive/src/generated/animation/transition_double_condition_base.dart'; + +class TransitionDoubleCondition extends TransitionDoubleConditionBase { + @override + void valueChanged(double from, double to) {} + @override + bool evaluate(HashMap values) { + var doubleInput = input as StateMachineDouble; + dynamic providedValue = values[input.id]; + double inputValue = + providedValue is double ? providedValue : doubleInput.value; + switch (op) { + case TransitionConditionOp.equal: + return inputValue == value; + case TransitionConditionOp.notEqual: + return inputValue != value; + case TransitionConditionOp.lessThanOrEqual: + return inputValue <= value; + case TransitionConditionOp.lessThan: + return inputValue < value; + case TransitionConditionOp.greaterThanOrEqual: + return inputValue >= value; + case TransitionConditionOp.greaterThan: + return inputValue > value; + } + } +} diff --git a/lib/src/rive_core/animation/transition_trigger_condition.dart b/lib/src/rive_core/animation/transition_trigger_condition.dart new file mode 100644 index 0000000..9d8dbe1 --- /dev/null +++ b/lib/src/rive_core/animation/transition_trigger_condition.dart @@ -0,0 +1,21 @@ +import 'dart:collection'; +import 'package:rive/src/rive_core/animation/state_machine_trigger.dart'; +import 'package:rive/src/generated/animation/transition_trigger_condition_base.dart'; +export 'package:rive/src/generated/animation/transition_trigger_condition_base.dart'; + +class TransitionTriggerCondition extends TransitionTriggerConditionBase { + @override + bool evaluate(HashMap values) { + dynamic providedValue = values[input.id]; + if (providedValue is bool && providedValue) { + values[input.id] = false; + return true; + } + var triggerInput = input as StateMachineTrigger; + if (triggerInput.triggered) { + triggerInput.reset(); + return true; + } + return false; + } +} diff --git a/lib/src/rive_core/animation/transition_value_condition.dart b/lib/src/rive_core/animation/transition_value_condition.dart new file mode 100644 index 0000000..9c6fd1b --- /dev/null +++ b/lib/src/rive_core/animation/transition_value_condition.dart @@ -0,0 +1,9 @@ +import 'package:rive/src/rive_core/animation/transition_condition.dart'; +import 'package:rive/src/generated/animation/transition_value_condition_base.dart'; +export 'package:rive/src/generated/animation/transition_value_condition_base.dart'; + +abstract class TransitionValueCondition extends TransitionValueConditionBase { + TransitionConditionOp get op => TransitionConditionOp.values[opValue]; + @override + void opValueChanged(int from, int to) {} +} diff --git a/lib/src/rive_core/artboard.dart b/lib/src/rive_core/artboard.dart index d2fd2a9..a31751b 100644 --- a/lib/src/rive_core/artboard.dart +++ b/lib/src/rive_core/artboard.dart @@ -22,7 +22,7 @@ class Artboard extends ArtboardBase with ShapePaintContainer { List _dependencyOrder = []; final List _drawables = []; final List _rules = []; - List _sortedDrawRules; + List _sortedDrawRules = []; final Set _components = {}; List get drawables => _drawables; final AnimationList _animations = AnimationList(); @@ -35,8 +35,7 @@ class Artboard extends ArtboardBase with ShapePaintContainer { @override Artboard get artboard => this; Vec2D get originWorld { - return Vec2D.fromValues( - x + width * (originX ?? 0), y + height * (originY ?? 0)); + return Vec2D.fromValues(x + width * originX, y + height * originY); } bool updateComponents() { @@ -91,7 +90,7 @@ class Artboard extends ArtboardBase with ShapePaintContainer { void onComponentDirty(Component component) { if ((dirt & ComponentDirt.components) == 0) { - context?.markNeedsAdvance(); + context.markNeedsAdvance(); _dirt |= ComponentDirt.components; } if (component.graphOrder < _dirtDepth) { @@ -104,7 +103,7 @@ class Artboard extends ArtboardBase with ShapePaintContainer { void sortDependencies() { var optimistic = DependencySorter(); var order = optimistic.sort(this); - if (order == null) { + if (order.isEmpty) { var robust = TarjansDependencySorter(); order = robust.sort(this); } @@ -118,8 +117,8 @@ class Artboard extends ArtboardBase with ShapePaintContainer { @override void update(int dirt) { if (dirt & ComponentDirt.worldTransform != 0) { - var rect = Rect.fromLTWH( - width * -(originX ?? 0), height * -(originY ?? 0), width, height); + var rect = + Rect.fromLTWH(width * -originX, height * -originY, width, height); path.reset(); path.addRect(rect); } @@ -158,7 +157,7 @@ class Artboard extends ArtboardBase with ShapePaintContainer { void markDrawOrderDirty() { if ((dirt & ComponentDirt.drawOrder) == 0) { - context?.markNeedsAdvance(); + context.markNeedsAdvance(); _dirt |= ComponentDirt.drawOrder; } } @@ -166,7 +165,7 @@ class Artboard extends ArtboardBase with ShapePaintContainer { void draw(Canvas canvas) { canvas.save(); canvas.clipRect(Rect.fromLTWH(0, 0, width, height)); - canvas.translate(width * (originX ?? 0), height * (originY ?? 0)); + canvas.translate(width * originX, height * originY); for (final fill in fills) { fill.draw(canvas, path); } @@ -208,7 +207,6 @@ class Artboard extends ArtboardBase with ShapePaintContainer { final Set _animationControllers = {}; bool addController(RiveAnimationController controller) { - assert(controller != null); if (_animationControllers.contains(controller) || !controller.init(context)) { return false; @@ -216,13 +214,12 @@ class Artboard extends ArtboardBase with ShapePaintContainer { controller.isActiveChanged.addListener(_onControllerPlayingChanged); _animationControllers.add(controller); if (controller.isActive) { - context?.markNeedsAdvance(); + context.markNeedsAdvance(); } return true; } bool removeController(RiveAnimationController controller) { - assert(controller != null); if (_animationControllers.remove(controller)) { controller.isActiveChanged.removeListener(_onControllerPlayingChanged); controller.dispose(); @@ -231,7 +228,7 @@ class Artboard extends ArtboardBase with ShapePaintContainer { return false; } - void _onControllerPlayingChanged() => context?.markNeedsAdvance(); + void _onControllerPlayingChanged() => context.markNeedsAdvance(); @override void onFillsChanged() {} @override @@ -240,7 +237,7 @@ class Artboard extends ArtboardBase with ShapePaintContainer { void onStrokesChanged() {} @override Vec2D get worldTranslation => Vec2D(); - Drawable _firstDrawable; + Drawable? _firstDrawable; void computeDrawOrder() { _drawables.clear(); _rules.clear(); @@ -272,7 +269,7 @@ class Artboard extends ArtboardBase with ShapePaintContainer { rule.first = rule.last = null; } _firstDrawable = null; - Drawable lastDrawable; + Drawable? lastDrawable; for (final drawable in _drawables) { var rules = drawable.flattenedDrawRules; var target = rules?.activeTarget; @@ -281,7 +278,7 @@ class Artboard extends ArtboardBase with ShapePaintContainer { target.first = target.last = drawable; drawable.prev = drawable.next = null; } else { - target.last.next = drawable; + target.last?.next = drawable; drawable.prev = target.last; target.last = drawable; drawable.next = null; @@ -303,26 +300,26 @@ class Artboard extends ArtboardBase with ShapePaintContainer { } switch (rule.placement) { case DrawTargetPlacement.before: - if (rule.drawable.prev != null) { - rule.drawable.prev.next = rule.first; - rule.first.prev = rule.drawable.prev; + if (rule.drawable?.prev != null) { + rule.drawable!.prev?.next = rule.first; + rule.first?.prev = rule.drawable!.prev; } if (rule.drawable == _firstDrawable) { _firstDrawable = rule.first; } - rule.drawable.prev = rule.last; - rule.last.next = rule.drawable; + rule.drawable?.prev = rule.last; + rule.last?.next = rule.drawable; break; case DrawTargetPlacement.after: - if (rule.drawable.next != null) { - rule.drawable.next.prev = rule.last; - rule.last.next = rule.drawable.next; + if (rule.drawable?.next != null) { + rule.drawable!.next!.prev = rule.last; + rule.last?.next = rule.drawable?.next; } if (rule.drawable == lastDrawable) { lastDrawable = rule.last; } - rule.drawable.next = rule.first; - rule.first.prev = rule.drawable; + rule.drawable?.next = rule.first; + rule.first?.prev = rule.drawable; break; } } diff --git a/lib/src/rive_core/backboard.dart b/lib/src/rive_core/backboard.dart index eb0fc9a..ebda29f 100644 --- a/lib/src/rive_core/backboard.dart +++ b/lib/src/rive_core/backboard.dart @@ -2,10 +2,9 @@ import 'package:rive/src/generated/backboard_base.dart'; export 'package:rive/src/generated/backboard_base.dart'; class Backboard extends BackboardBase { + static final Backboard unknown = Backboard(); @override void onAdded() {} @override void onAddedDirty() {} - @override - void onRemoved() {} } diff --git a/lib/src/rive_core/bones/bone.dart b/lib/src/rive_core/bones/bone.dart index ef7dd15..12d2a3d 100644 --- a/lib/src/rive_core/bones/bone.dart +++ b/lib/src/rive_core/bones/bone.dart @@ -13,7 +13,7 @@ class Bone extends BoneBase { } } - Bone get firstChildBone { + Bone? get firstChildBone { for (final child in children) { if (child.coreType == BoneBase.typeKey) { return child as Bone; diff --git a/lib/src/rive_core/bones/skin.dart b/lib/src/rive_core/bones/skin.dart index 5be8277..1f8fba6 100644 --- a/lib/src/rive_core/bones/skin.dart +++ b/lib/src/rive_core/bones/skin.dart @@ -10,7 +10,7 @@ export 'package:rive/src/generated/bones/skin_base.dart'; class Skin extends SkinBase { final List _tendons = []; List get tendons => _tendons; - Float32List _boneTransforms; + Float32List _boneTransforms = Float32List(0); final Mat2D _worldTransform = Mat2D(); @override void onDirty(int mask) { @@ -20,7 +20,7 @@ class Skin extends SkinBase { @override void update(int dirt) { var size = (_tendons.length + 1) * 6; - if (_boneTransforms == null || _boneTransforms.length != size) { + if (_boneTransforms.length != size) { _boneTransforms = Float32List(size); _boneTransforms[0] = 1; _boneTransforms[1] = 0; @@ -32,7 +32,10 @@ class Skin extends SkinBase { var temp = Mat2D(); var bidx = 6; for (final tendon in _tendons) { - var boneWorld = tendon.bone.worldTransform; + if (tendon.bone == null) { + continue; + } + var boneWorld = tendon.bone!.worldTransform; var wt = Mat2D.multiply(temp, boneWorld, tendon.inverseBind); _boneTransforms[bidx++] = wt[0]; _boneTransforms[bidx++] = wt[1]; @@ -54,15 +57,21 @@ class Skin extends SkinBase { super.onAddedDirty(); if (parent is Skinnable) { (parent as Skinnable).addSkin(this); - parent.markRebuildDependencies(); + parent!.markRebuildDependencies(); } + _worldTransform[0] = xx; + _worldTransform[1] = xy; + _worldTransform[2] = yx; + _worldTransform[3] = yy; + _worldTransform[4] = tx; + _worldTransform[5] = ty; } @override void onRemoved() { if (parent is Skinnable) { (parent as Skinnable).removeSkin(this); - parent.markRebuildDependencies(); + parent!.markRebuildDependencies(); } super.onRemoved(); } @@ -82,7 +91,9 @@ class Skin extends SkinBase { case TendonBase.typeKey: _tendons.add(child as Tendon); markRebuildDependencies(); - parent?.markRebuildDependencies(); + if (parent is Skinnable) { + parent!.markRebuildDependencies(); + } break; } } diff --git a/lib/src/rive_core/bones/skinnable.dart b/lib/src/rive_core/bones/skinnable.dart index 72cfb1d..4054abd 100644 --- a/lib/src/rive_core/bones/skinnable.dart +++ b/lib/src/rive_core/bones/skinnable.dart @@ -2,11 +2,10 @@ import 'package:rive/src/rive_core/bones/skin.dart'; import 'package:rive/src/rive_core/component.dart'; abstract class Skinnable { - Skin _skin; - Skin get skin => _skin; + Skin? _skin; + Skin? get skin => _skin; void appendChild(Component child); void addSkin(Skin skin) { - assert(skin != null); _skin = skin; markSkinDirty(); } diff --git a/lib/src/rive_core/bones/tendon.dart b/lib/src/rive_core/bones/tendon.dart index b4c23e6..05466a1 100644 --- a/lib/src/rive_core/bones/tendon.dart +++ b/lib/src/rive_core/bones/tendon.dart @@ -5,15 +5,15 @@ export 'package:rive/src/generated/bones/tendon_base.dart'; class Tendon extends TendonBase { final Mat2D _bind = Mat2D(); - Mat2D _inverseBind; - SkeletalComponent _bone; - SkeletalComponent get bone => _bone; + Mat2D? _inverseBind; + SkeletalComponent? _bone; + SkeletalComponent? get bone => _bone; Mat2D get inverseBind { if (_inverseBind == null) { _inverseBind = Mat2D(); - Mat2D.invert(_inverseBind, _bind); + Mat2D.invert(_inverseBind!, _bind); } - return _inverseBind; + return _inverseBind!; } @override @@ -21,9 +21,13 @@ class Tendon extends TendonBase { @override void onAddedDirty() { super.onAddedDirty(); - if (boneId != null) { - _bone = context?.resolve(boneId); - } + _bone = context.resolve(boneId); + _bind[0] = xx; + _bind[1] = xy; + _bind[2] = yx; + _bind[3] = yy; + _bind[4] = tx; + _bind[5] = ty; } @override diff --git a/lib/src/rive_core/component.dart b/lib/src/rive_core/component.dart index f8240d9..abe65ef 100644 --- a/lib/src/rive_core/component.dart +++ b/lib/src/rive_core/component.dart @@ -9,7 +9,7 @@ export 'package:rive/src/generated/component_base.dart'; abstract class Component extends ComponentBase implements DependencyGraphNode, Parentable { - Artboard _artboard; + Artboard? _artboard; dynamic _userData; bool get canBeOrphaned => false; int graphOrder = 0; @@ -33,8 +33,8 @@ abstract class Component extends ComponentBase void onDirty(int mask) {} void update(int dirt); - Artboard get artboard => _artboard; - void _changeArtboard(Artboard value) { + Artboard? get artboard => _artboard; + void _changeArtboard(Artboard? value) { if (_artboard == value) { return; } @@ -47,7 +47,7 @@ abstract class Component extends ComponentBase void visitAncestor(Component ancestor) {} bool resolveArtboard() { int sanity = maxTreeDepth; - for (Component curr = this; + for (Component? curr = this; curr != null && sanity > 0; curr = curr.parent, sanity--) { visitAncestor(curr); @@ -73,32 +73,28 @@ abstract class Component extends ComponentBase void userDataChanged(dynamic from, dynamic to) {} @override void parentIdChanged(int from, int to) { - parent = context?.resolve(to); + parent = context.resolve(to); } - ContainerComponent _parent; + ContainerComponent? _parent; @override - ContainerComponent get parent => _parent; - set parent(ContainerComponent value) { + ContainerComponent? get parent => _parent; + set parent(ContainerComponent? value) { if (_parent == value) { return; } var old = _parent; _parent = value; - parentId = value?.id; + parentId = value?.id ?? Core.missingId; parentChanged(old, value); } @protected - void parentChanged(ContainerComponent from, ContainerComponent to) { - if (from != null) { - from.children.remove(this); - from.childRemoved(this); - } - if (to != null) { - to.children.add(this); - to.childAdded(this); - } + void parentChanged(ContainerComponent? from, ContainerComponent? to) { + from?.children.remove(this); + from?.childRemoved(this); + to?.children.add(this); + to?.childAdded(this); markRebuildDependencies(); } @@ -107,7 +103,6 @@ abstract class Component extends ComponentBase @override Set get dependents => _dependents; bool addDependent(Component dependent) { - assert(dependent != null, 'Dependent cannot be null.'); assert(artboard == dependent.artboard, 'Components must be in the same artboard.'); if (!_dependents.add(dependent)) { @@ -119,7 +114,7 @@ abstract class Component extends ComponentBase bool isValidParent(Component parent) => parent is ContainerComponent; void markRebuildDependencies() { - if (context == null || !context.markDependenciesDirty(this)) { + if (!context.markDependenciesDirty(this)) { return; } for (final dependent in _dependents) { @@ -140,14 +135,15 @@ abstract class Component extends ComponentBase void onAdded() {} @override void onAddedDirty() { - if (parentId != null) { - parent = context?.resolve(parentId); + if (parentId != Core.missingId) { + parent = context.resolve(parentId); } } @override @mustCallSuper void onRemoved() { + super.onRemoved(); for (final parentDep in _dependsOn) { parentDep._dependents.remove(this); } @@ -157,21 +153,29 @@ abstract class Component extends ComponentBase } _dependents.clear(); if (parent != null) { - parent.children.remove(this); - parent.childRemoved(this); + parent!.children.remove(this); + parent!.childRemoved(this); } if (artboard != null) { - context?.markDependencyOrderDirty(); + context.markDependencyOrderDirty(); _changeArtboard(null); } } @override String toString() { - return '${super.toString()} ($id)'; + return '${super.toString()} ($id) -> $name'; } - void remove() => context?.removeObject(this); @override void nameChanged(String from, String to) {} + @override + bool import(ImportStack stack) { + var artboardImporter = stack.latest(ArtboardBase.typeKey); + if (artboardImporter == null) { + return false; + } + artboardImporter.addComponent(this); + return super.import(stack); + } } diff --git a/lib/src/rive_core/container_component.dart b/lib/src/rive_core/container_component.dart index c7967a7..4ab8e17 100644 --- a/lib/src/rive_core/container_component.dart +++ b/lib/src/rive_core/container_component.dart @@ -40,14 +40,13 @@ abstract class ContainerComponent extends ContainerComponentBase { } void removeRecursive() { - assert(context != null); Set deathRow = {this}; forEachChild((child) => deathRow.add(child)); deathRow.forEach(context.removeObject); } void buildDrawOrder( - List drawables, DrawRules rules, List allRules) { + List drawables, DrawRules? rules, List allRules) { for (final child in children) { if (child is ContainerComponent) { child.buildDrawOrder(drawables, rules, allRules); diff --git a/lib/src/rive_core/draw_rules.dart b/lib/src/rive_core/draw_rules.dart index c3668c3..7a11973 100644 --- a/lib/src/rive_core/draw_rules.dart +++ b/lib/src/rive_core/draw_rules.dart @@ -1,3 +1,4 @@ +import 'package:rive/src/core/core.dart'; import 'package:rive/src/rive_core/component.dart'; import 'package:rive/src/rive_core/draw_target.dart'; import 'package:rive/src/generated/draw_rules_base.dart'; @@ -6,23 +7,20 @@ export 'package:rive/src/generated/draw_rules_base.dart'; class DrawRules extends DrawRulesBase { final Set _targets = {}; Set get targets => _targets; - DrawTarget _activeTarget; - DrawTarget get activeTarget => _activeTarget; - set activeTarget(DrawTarget value) => drawTargetId = value?.id; + DrawTarget? _activeTarget; + DrawTarget? get activeTarget => _activeTarget; + set activeTarget(DrawTarget? value) => + drawTargetId = value?.id ?? Core.missingId; @override void drawTargetIdChanged(int from, int to) { - _activeTarget = to == null ? null : context?.resolve(to); + _activeTarget = context.resolve(to); artboard?.markDrawOrderDirty(); } @override void onAddedDirty() { super.onAddedDirty(); - if (drawTargetId != null) { - _activeTarget = context?.resolve(drawTargetId); - } else { - _activeTarget = null; - } + _activeTarget = context.resolve(drawTargetId); } @override diff --git a/lib/src/rive_core/draw_target.dart b/lib/src/rive_core/draw_target.dart index 2c875c8..42dd856 100644 --- a/lib/src/rive_core/draw_target.dart +++ b/lib/src/rive_core/draw_target.dart @@ -1,3 +1,4 @@ +import 'package:rive/src/core/core.dart'; import 'package:rive/src/rive_core/drawable.dart'; import 'package:rive/src/generated/draw_target_base.dart'; export 'package:rive/src/generated/draw_target_base.dart'; @@ -5,16 +6,16 @@ export 'package:rive/src/generated/draw_target_base.dart'; enum DrawTargetPlacement { before, after } class DrawTarget extends DrawTargetBase { - Drawable first; - Drawable last; - Drawable _drawable; - Drawable get drawable => _drawable; - set drawable(Drawable value) { + Drawable? first; + Drawable? last; + Drawable? _drawable; + Drawable? get drawable => _drawable; + set drawable(Drawable? value) { if (_drawable == value) { return; } _drawable = value; - drawableId = value?.id; + drawableId = value?.id ?? Core.missingId; } DrawTargetPlacement get placement => @@ -22,17 +23,13 @@ class DrawTarget extends DrawTargetBase { set placement(DrawTargetPlacement value) => placementValue = value.index; @override void drawableIdChanged(int from, int to) { - drawable = context?.resolve(to); + drawable = context.resolve(to); } @override void onAddedDirty() { super.onAddedDirty(); - if (drawableId != null) { - drawable = context?.resolve(drawableId); - } else { - drawable = null; - } + drawable = context.resolve(drawableId); } @override diff --git a/lib/src/rive_core/drawable.dart b/lib/src/rive_core/drawable.dart index 8d66249..60a3d9f 100644 --- a/lib/src/rive_core/drawable.dart +++ b/lib/src/rive_core/drawable.dart @@ -9,12 +9,12 @@ import 'package:rive/src/rive_core/transform_component.dart'; export 'package:rive/src/generated/drawable_base.dart'; abstract class Drawable extends DrawableBase { - DrawRules flattenedDrawRules; - Drawable prev; - Drawable next; + DrawRules? flattenedDrawRules; + Drawable? prev; + Drawable? next; @override void buildDrawOrder( - List drawables, DrawRules rules, List allRules) { + List drawables, DrawRules? rules, List allRules) { flattenedDrawRules = drawRules ?? rules; drawables.add(this); super.buildDrawOrder(drawables, rules, allRules); @@ -25,9 +25,9 @@ abstract class Drawable extends DrawableBase { set blendMode(BlendMode value) => blendModeValue = value.index; @override void blendModeValueChanged(int from, int to) {} - List _clippingShapes; + List _clippingShapes = []; bool clip(Canvas canvas) { - if (_clippingShapes == null) { + if (_clippingShapes.isEmpty) { return false; } canvas.save(); @@ -41,7 +41,7 @@ abstract class Drawable extends DrawableBase { } @override - void parentChanged(ContainerComponent from, ContainerComponent to) { + void parentChanged(ContainerComponent? from, ContainerComponent? to) { super.parentChanged(from, to); addDirt(ComponentDirt.clip); } @@ -51,14 +51,14 @@ abstract class Drawable extends DrawableBase { super.update(dirt); if (dirt & ComponentDirt.clip != 0) { List clippingShapes = []; - for (ContainerComponent p = this; p != null; p = p.parent) { + for (ContainerComponent? p = this; p != null; p = p.parent) { if (p is TransformComponent) { - if (p.clippingShapes != null) { + if (p.clippingShapes.isNotEmpty) { clippingShapes.addAll(p.clippingShapes); } } } - _clippingShapes = clippingShapes.isEmpty ? null : clippingShapes; + _clippingShapes = clippingShapes; } } diff --git a/lib/src/rive_core/math/aabb.dart b/lib/src/rive_core/math/aabb.dart index 4c796dc..9a291bf 100644 --- a/lib/src/rive_core/math/aabb.dart +++ b/lib/src/rive_core/math/aabb.dart @@ -1,7 +1,7 @@ import 'dart:math'; -import "dart:typed_data"; +import 'dart:typed_data'; import 'package:rive/src/rive_core/math/mat2d.dart'; -import "vec2d.dart"; +import 'package:rive/src/rive_core/math/vec2d.dart'; class AABB { Float32List _buffer; @@ -27,23 +27,21 @@ class AABB { return Vec2D.fromValues(_buffer[2], _buffer[3]); } - AABB() { - _buffer = Float32List.fromList([0.0, 0.0, 0.0, 0.0]); - } - AABB.clone(AABB a) { - _buffer = Float32List.fromList(a.values); - } - AABB.fromValues(double a, double b, double c, double d) { - _buffer = Float32List.fromList([a, b, c, d]); - } - AABB.empty() { - _buffer = Float32List.fromList([ - double.maxFinite, - double.maxFinite, - -double.maxFinite, - -double.maxFinite - ]); - } + double get minX => _buffer[0]; + double get maxX => _buffer[2]; + double get minY => _buffer[1]; + double get maxY => _buffer[3]; + AABB() : _buffer = Float32List.fromList([0.0, 0.0, 0.0, 0.0]); + AABB.clone(AABB a) : _buffer = Float32List.fromList(a.values); + AABB.fromValues(double a, double b, double c, double d) + : _buffer = Float32List.fromList([a, b, c, d]); + AABB.empty() + : _buffer = Float32List.fromList([ + double.maxFinite, + double.maxFinite, + -double.maxFinite, + -double.maxFinite + ]); factory AABB.expand(AABB from, double amount) { var aabb = AABB.clone(from); if (aabb.width < amount) { @@ -56,8 +54,16 @@ class AABB { } return aabb; } + factory AABB.pad(AABB from, double amount) { + var aabb = AABB.clone(from); + aabb[0] -= amount; + aabb[2] += amount; + aabb[1] -= amount; + aabb[3] += amount; + return aabb; + } bool get isEmpty => !AABB.isValid(this); - Vec2D includePoint(Vec2D point, Mat2D transform) { + Vec2D includePoint(Vec2D point, Mat2D? transform) { var transformedPoint = transform == null ? point : Vec2D.transformMat2D(Vec2D(), point, transform); @@ -82,9 +88,8 @@ class AABB { } } - AABB.fromMinMax(Vec2D min, Vec2D max) { - _buffer = Float32List.fromList([min[0], min[1], max[0], max[1]]); - } + AABB.fromMinMax(Vec2D min, Vec2D max) + : _buffer = Float32List.fromList([min[0], min[1], max[0], max[1]]); static bool areEqual(AABB a, AABB b) { return a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3]; } @@ -190,8 +195,8 @@ class AABB { ], transform: matrix); } - AABB.fromPoints(Iterable points, - {Mat2D transform, double expand = 0}) { + factory AABB.fromPoints(Iterable points, + {Mat2D? transform, double expand = 0}) { double minX = double.maxFinite; double minY = double.maxFinite; double maxX = -double.maxFinite; @@ -231,6 +236,6 @@ class AABB { maxY += diff; } } - _buffer = Float32List.fromList([minX, minY, maxX, maxY]); + return AABB.fromValues(minX, minY, maxX, maxY); } } diff --git a/lib/src/rive_core/math/mat2d.dart b/lib/src/rive_core/math/mat2d.dart index ac86869..24a0753 100644 --- a/lib/src/rive_core/math/mat2d.dart +++ b/lib/src/rive_core/math/mat2d.dart @@ -1,10 +1,17 @@ -import "dart:math"; -import "dart:typed_data"; -import "transform_components.dart"; -import "vec2d.dart"; +import 'dart:math'; +import 'dart:typed_data'; +import 'package:rive/src/rive_core/math/transform_components.dart'; +import 'package:rive/src/rive_core/math/vec2d.dart'; + +class _Identity extends Mat2D { + @override + void operator []=(int index, double value) => throw UnsupportedError( + 'Cannot change components of the identity matrix.'); +} class Mat2D { - Float32List _buffer; + static final Mat2D identity = _Identity(); + final Float32List _buffer; Float32List get values { return _buffer; } @@ -38,23 +45,16 @@ class Mat2D { _buffer[index] = value; } - Mat2D() { - _buffer = Float32List.fromList([1.0, 0.0, 0.0, 1.0, 0.0, 0.0]); - } - Mat2D.fromTranslation(Vec2D translation) { - _buffer = Float32List.fromList( - [1.0, 0.0, 0.0, 1.0, translation[0], translation[1]]); - } - Mat2D.fromScaling(Vec2D scaling) { - _buffer = Float32List.fromList([scaling[0], 0, 0, scaling[1], 0, 0]); - } - Mat2D.fromMat4(Float64List mat4) { - _buffer = Float32List.fromList( - [mat4[0], mat4[1], mat4[4], mat4[5], mat4[12], mat4[13]]); - } - Mat2D.clone(Mat2D copy) { - _buffer = Float32List.fromList(copy.values); - } + Mat2D() : _buffer = Float32List.fromList([1.0, 0.0, 0.0, 1.0, 0.0, 0.0]); + Mat2D.fromTranslation(Vec2D translation) + : _buffer = Float32List.fromList( + [1.0, 0.0, 0.0, 1.0, translation[0], translation[1]]); + Mat2D.fromScaling(Vec2D scaling) + : _buffer = Float32List.fromList([scaling[0], 0, 0, scaling[1], 0, 0]); + Mat2D.fromMat4(Float64List mat4) + : _buffer = Float32List.fromList( + [mat4[0], mat4[1], mat4[4], mat4[5], mat4[12], mat4[13]]); + Mat2D.clone(Mat2D copy) : _buffer = Float32List.fromList(copy.values); static Mat2D fromRotation(Mat2D o, double rad) { double s = sin(rad); double c = cos(rad); @@ -109,6 +109,17 @@ class Mat2D { o[3] *= y; } + // ignore: prefer_constructors_over_static_methods + static Mat2D multiplySkipIdentity(Mat2D a, Mat2D b) { + if (a == Mat2D.identity) { + return b; + } else if (b == Mat2D.identity) { + return a; + } else { + return multiply(Mat2D(), a, b); + } + } + static Mat2D multiply(Mat2D o, Mat2D a, Mat2D b) { double a0 = a[0], a1 = a[1], @@ -181,7 +192,7 @@ class Mat2D { return t; } - static void identity(Mat2D mat) { + static void setIdentity(Mat2D mat) { mat[0] = 1.0; mat[1] = 0.0; mat[2] = 0.0; @@ -210,7 +221,7 @@ class Mat2D { if (r != 0.0) { Mat2D.fromRotation(m, r); } else { - Mat2D.identity(m); + Mat2D.setIdentity(m); } m[4] = result[0]; m[5] = result[1]; diff --git a/lib/src/rive_core/math/segment2d.dart b/lib/src/rive_core/math/segment2d.dart index a852574..04d48dd 100644 --- a/lib/src/rive_core/math/segment2d.dart +++ b/lib/src/rive_core/math/segment2d.dart @@ -9,13 +9,13 @@ class ProjectionResult { class Segment2D { final Vec2D start; final Vec2D end; - Vec2D diff; - double lengthSquared; + Vec2D? diff; + double lengthSquared = 0; Segment2D(this.start, this.end); ProjectionResult projectPoint(Vec2D point, {bool clamp = true}) { if (diff == null) { diff = Vec2D.subtract(Vec2D(), start, end); - lengthSquared = Vec2D.squaredLength(diff); + lengthSquared = Vec2D.squaredLength(diff!); } if (lengthSquared == 0) { return ProjectionResult(0, start); diff --git a/lib/src/rive_core/math/transform_components.dart b/lib/src/rive_core/math/transform_components.dart index 1e6fab8..34bc35c 100644 --- a/lib/src/rive_core/math/transform_components.dart +++ b/lib/src/rive_core/math/transform_components.dart @@ -1,9 +1,9 @@ import 'dart:math'; import 'dart:typed_data'; -import 'vec2d.dart'; +import 'package:rive/src/rive_core/math/vec2d.dart'; class TransformComponents { - Float32List _buffer; + final Float32List _buffer; Float32List get values { return _buffer; } @@ -16,12 +16,10 @@ class TransformComponents { _buffer[index] = value; } - TransformComponents() { - _buffer = Float32List.fromList([1.0, 0.0, 0.0, 1.0, 0.0, 0.0]); - } - TransformComponents.clone(TransformComponents copy) { - _buffer = Float32List.fromList(copy.values); - } + TransformComponents() + : _buffer = Float32List.fromList([1.0, 0.0, 0.0, 1.0, 0.0, 0.0]); + TransformComponents.clone(TransformComponents copy) + : _buffer = Float32List.fromList(copy.values); double get x { return _buffer[0]; } diff --git a/lib/src/rive_core/math/vec2d.dart b/lib/src/rive_core/math/vec2d.dart index fff56f4..ddefa8f 100644 --- a/lib/src/rive_core/math/vec2d.dart +++ b/lib/src/rive_core/math/vec2d.dart @@ -1,10 +1,10 @@ import 'dart:math'; import 'dart:typed_data'; +import 'package:rive/src/rive_core/math/mat2d.dart'; import 'package:rive/src/utilities/utilities.dart'; -import 'mat2d.dart'; class Vec2D { - Float32List _buffer; + final Float32List _buffer; Float32List get values { return _buffer; } @@ -17,15 +17,9 @@ class Vec2D { _buffer[index] = value; } - Vec2D() { - _buffer = Float32List.fromList([0.0, 0.0]); - } - Vec2D.clone(Vec2D copy) { - _buffer = Float32List.fromList(copy._buffer); - } - Vec2D.fromValues(double x, double y) { - _buffer = Float32List.fromList([x, y]); - } + Vec2D() : _buffer = Float32List.fromList([0.0, 0.0]); + Vec2D.clone(Vec2D copy) : _buffer = Float32List.fromList(copy._buffer); + Vec2D.fromValues(double x, double y) : _buffer = Float32List.fromList([x, y]); static void copy(Vec2D o, Vec2D a) { o[0] = a[0]; o[1] = a[1]; diff --git a/lib/src/rive_core/node.dart b/lib/src/rive_core/node.dart index 8a1711c..eaf97b2 100644 --- a/lib/src/rive_core/node.dart +++ b/lib/src/rive_core/node.dart @@ -3,7 +3,10 @@ import 'package:rive/src/rive_core/math/vec2d.dart'; import 'package:rive/src/generated/node_base.dart'; export 'package:rive/src/generated/node_base.dart'; +class _UnknownNode extends Node {} + class Node extends NodeBase { + static final Node unknown = _UnknownNode(); set translation(Vec2D pos) { x = pos[0]; y = pos[1]; diff --git a/lib/src/rive_core/runtime/runtime_header.dart b/lib/src/rive_core/runtime/runtime_header.dart index 3e5b01c..b5c6565 100644 --- a/lib/src/rive_core/runtime/runtime_header.dart +++ b/lib/src/rive_core/runtime/runtime_header.dart @@ -1,28 +1,28 @@ import 'dart:collection'; -import 'package:meta/meta.dart'; +import 'package:rive/src/rive_core/runtime/exceptions/rive_format_error_exception.dart'; import 'package:rive/src/rive_core/runtime/exceptions/rive_unsupported_version_exception.dart'; import 'package:rive/src/utilities/binary_buffer/binary_reader.dart'; -import 'exceptions/rive_format_error_exception.dart'; class RuntimeVersion { final int major; final int minor; const RuntimeVersion(this.major, this.minor); + String versionString() { + return '$major.$minor'; + } } -const riveVersion = RuntimeVersion(6, 3); +const riveVersion = RuntimeVersion(7, 0); class RuntimeHeader { static const String fingerprint = 'RIVE'; final RuntimeVersion version; - final int projectId; final int fileId; final HashMap propertyToFieldIndex; RuntimeHeader( - {@required this.projectId, - @required this.fileId, - @required this.version, - this.propertyToFieldIndex}); + {required this.fileId, + required this.version, + required this.propertyToFieldIndex}); factory RuntimeHeader.read(BinaryReader reader) { var fingerprint = RuntimeHeader.fingerprint.codeUnits; for (int i = 0; i < fingerprint.length; i++) { @@ -36,7 +36,9 @@ class RuntimeHeader { throw RiveUnsupportedVersionException(riveVersion.major, riveVersion.minor, readMajorVersion, readMinorVersion); } - int projectId = reader.readVarUint(); + if (readMajorVersion == 6) { + reader.readVarUint(); + } int fileId = reader.readVarUint(); var propertyFields = HashMap(); var propertyKeys = []; @@ -57,7 +59,6 @@ class RuntimeHeader { currentBit += 2; } return RuntimeHeader( - projectId: projectId, fileId: fileId, version: RuntimeVersion(readMajorVersion, readMinorVersion), propertyToFieldIndex: propertyFields); diff --git a/lib/src/rive_core/shapes/clipping_shape.dart b/lib/src/rive_core/shapes/clipping_shape.dart index 9de56e5..f8258cd 100644 --- a/lib/src/rive_core/shapes/clipping_shape.dart +++ b/lib/src/rive_core/shapes/clipping_shape.dart @@ -10,14 +10,14 @@ class ClippingShape extends ClippingShapeBase { final List _shapes = []; PathFillType get fillType => PathFillType.values[fillRule]; set fillType(PathFillType type) => fillRule = type.index; - Node _source; + Node _source = Node.unknown; Node get source => _source; set source(Node value) { if (_source == value) { return; } _source = value; - sourceId = value?.id; + sourceId = value.id; } @override @@ -28,22 +28,20 @@ class ClippingShape extends ClippingShapeBase { @override void sourceIdChanged(int from, int to) { - source = context?.resolve(to); + source = context.resolveWithDefault(to, Node.unknown); } @override void onAddedDirty() { super.onAddedDirty(); - if (sourceId != null) { - _source = context?.resolve(sourceId); - } + source = context.resolveWithDefault(sourceId, Node.unknown); } @override void buildDependencies() { super.buildDependencies(); _shapes.clear(); - _source?.forAll((component) { + _source.forAll((component) { if (component is Shape) { _shapes.add(component); component.pathComposer.addDependent(this); @@ -61,8 +59,7 @@ class ClippingShape extends ClippingShapeBase { @override void update(int dirt) { - if (dirt & (ComponentDirt.worldTransform | ComponentDirt.path) != 0 && - source != null) { + if (dirt & (ComponentDirt.worldTransform | ComponentDirt.path) != 0) { clippingPath.reset(); clippingPath.fillType = fillType; for (final shape in _shapes) { @@ -78,6 +75,6 @@ class ClippingShape extends ClippingShapeBase { @override void isVisibleChanged(bool from, bool to) { - _source?.addDirt(ComponentDirt.paint); + _source.addDirt(ComponentDirt.paint); } } diff --git a/lib/src/rive_core/shapes/cubic_asymmetric_vertex.dart b/lib/src/rive_core/shapes/cubic_asymmetric_vertex.dart index 0e7b284..fec3ba2 100644 --- a/lib/src/rive_core/shapes/cubic_asymmetric_vertex.dart +++ b/lib/src/rive_core/shapes/cubic_asymmetric_vertex.dart @@ -1,12 +1,17 @@ import 'dart:math'; +import 'package:rive/src/core/core.dart'; import 'package:rive/src/rive_core/component_dirt.dart'; import 'package:rive/src/rive_core/math/vec2d.dart'; import 'package:rive/src/generated/shapes/cubic_asymmetric_vertex_base.dart'; export 'package:rive/src/generated/shapes/cubic_asymmetric_vertex_base.dart'; class CubicAsymmetricVertex extends CubicAsymmetricVertexBase { - Vec2D _inPoint; - Vec2D _outPoint; + CubicAsymmetricVertex(); + CubicAsymmetricVertex.procedural() { + InternalCoreHelper.markValid(this); + } + Vec2D? _inPoint; + Vec2D? _outPoint; @override Vec2D get outPoint { return _outPoint ??= Vec2D.add( diff --git a/lib/src/rive_core/shapes/cubic_detached_vertex.dart b/lib/src/rive_core/shapes/cubic_detached_vertex.dart index 43631eb..7566bac 100644 --- a/lib/src/rive_core/shapes/cubic_detached_vertex.dart +++ b/lib/src/rive_core/shapes/cubic_detached_vertex.dart @@ -1,26 +1,29 @@ import 'dart:math'; +import 'package:rive/src/core/core.dart'; import 'package:rive/src/rive_core/component_dirt.dart'; import 'package:rive/src/rive_core/math/vec2d.dart'; import 'package:rive/src/generated/shapes/cubic_detached_vertex_base.dart'; export 'package:rive/src/generated/shapes/cubic_detached_vertex_base.dart'; class CubicDetachedVertex extends CubicDetachedVertexBase { - Vec2D _inPoint; - Vec2D _outPoint; + Vec2D? _inPoint; + Vec2D? _outPoint; CubicDetachedVertex(); CubicDetachedVertex.fromValues( - {double x, - double y, - double inX, - double inY, - double outX, - double outY, - Vec2D inPoint, - Vec2D outPoint}) { + {required double x, + required double y, + double? inX, + double? inY, + double? outX, + double? outY, + Vec2D? inPoint, + Vec2D? outPoint}) { + InternalCoreHelper.markValid(this); this.x = x; this.y = y; - this.inPoint = Vec2D.fromValues(inX ?? inPoint[0], inY ?? inPoint[1]); - this.outPoint = Vec2D.fromValues(outX ?? outPoint[0], outY ?? outPoint[1]); + this.inPoint = Vec2D.fromValues(inX ?? inPoint![0], inY ?? inPoint![1]); + this.outPoint = + Vec2D.fromValues(outX ?? outPoint![0], outY ?? outPoint![1]); } @override Vec2D get outPoint => _outPoint ??= Vec2D.add( diff --git a/lib/src/rive_core/shapes/cubic_mirrored_vertex.dart b/lib/src/rive_core/shapes/cubic_mirrored_vertex.dart index 8cb3c27..e6aa9bc 100644 --- a/lib/src/rive_core/shapes/cubic_mirrored_vertex.dart +++ b/lib/src/rive_core/shapes/cubic_mirrored_vertex.dart @@ -1,12 +1,17 @@ import 'dart:math'; +import 'package:rive/src/core/core.dart'; import 'package:rive/src/rive_core/component_dirt.dart'; import 'package:rive/src/rive_core/math/vec2d.dart'; import 'package:rive/src/generated/shapes/cubic_mirrored_vertex_base.dart'; export 'package:rive/src/generated/shapes/cubic_mirrored_vertex_base.dart'; class CubicMirroredVertex extends CubicMirroredVertexBase { - Vec2D _inPoint; - Vec2D _outPoint; + CubicMirroredVertex(); + CubicMirroredVertex.procedural() { + InternalCoreHelper.markValid(this); + } + Vec2D? _inPoint; + Vec2D? _outPoint; @override Vec2D get outPoint { return _outPoint ??= Vec2D.add(Vec2D(), translation, diff --git a/lib/src/rive_core/shapes/cubic_vertex.dart b/lib/src/rive_core/shapes/cubic_vertex.dart index c689f0e..f97e437 100644 --- a/lib/src/rive_core/shapes/cubic_vertex.dart +++ b/lib/src/rive_core/shapes/cubic_vertex.dart @@ -17,9 +17,9 @@ abstract class CubicVertex extends CubicVertexBase { @override void deform(Mat2D world, Float32List boneTransforms) { super.deform(world, boneTransforms); - Weight.deform(outPoint[0], outPoint[1], weight.outIndices, weight.outValues, - world, boneTransforms, weight.outTranslation); - Weight.deform(inPoint[0], inPoint[1], weight.inIndices, weight.inValues, - world, boneTransforms, weight.inTranslation); + Weight.deform(outPoint[0], outPoint[1], weight!.outIndices, + weight!.outValues, world, boneTransforms, weight!.outTranslation); + Weight.deform(inPoint[0], inPoint[1], weight!.inIndices, weight!.inValues, + world, boneTransforms, weight!.inTranslation); } } diff --git a/lib/src/rive_core/shapes/paint/fill.dart b/lib/src/rive_core/shapes/paint/fill.dart index dbf6446..410a3ca 100644 --- a/lib/src/rive_core/shapes/paint/fill.dart +++ b/lib/src/rive_core/shapes/paint/fill.dart @@ -10,10 +10,8 @@ class Fill extends FillBase { PathFillType get fillType => PathFillType.values[fillRule]; set fillType(PathFillType type) => fillRule = type.index; @override - void fillRuleChanged(int from, int to) { - parent?.addDirt(ComponentDirt.paint); - } - + void fillRuleChanged(int from, int to) => + parent?.addDirt(ComponentDirt.paint); @override void update(int dirt) {} @override diff --git a/lib/src/rive_core/shapes/paint/gradient_stop.dart b/lib/src/rive_core/shapes/paint/gradient_stop.dart index 4c543a4..7bb440c 100644 --- a/lib/src/rive_core/shapes/paint/gradient_stop.dart +++ b/lib/src/rive_core/shapes/paint/gradient_stop.dart @@ -5,8 +5,8 @@ import 'package:rive/src/rive_core/shapes/paint/linear_gradient.dart'; export 'package:rive/src/generated/shapes/paint/gradient_stop_base.dart'; class GradientStop extends GradientStopBase { - LinearGradient _gradient; - LinearGradient get gradient => _gradient; + LinearGradient? _gradient; + LinearGradient? get gradient => _gradient; ui.Color get color => ui.Color(colorValue); set color(ui.Color c) { colorValue = c.value; @@ -25,7 +25,9 @@ class GradientStop extends GradientStopBase { @override void update(int dirt) {} @override - void parentChanged(ContainerComponent from, ContainerComponent to) { + bool validate() => super.validate() && _gradient != null; + @override + void parentChanged(ContainerComponent? from, ContainerComponent? to) { super.parentChanged(from, to); if (parent is LinearGradient) { _gradient = parent as LinearGradient; diff --git a/lib/src/rive_core/shapes/paint/linear_gradient.dart b/lib/src/rive_core/shapes/paint/linear_gradient.dart index b518d7d..c2accbf 100644 --- a/lib/src/rive_core/shapes/paint/linear_gradient.dart +++ b/lib/src/rive_core/shapes/paint/linear_gradient.dart @@ -69,7 +69,7 @@ class LinearGradient extends LinearGradientBase with ShapePaintMutator { colorPositions.add(stop.position); } if (paintsInWorldSpace) { - var world = shapePaintContainer.worldTransform; + var world = shapePaintContainer!.worldTransform; var worldStart = Vec2D.transformMat2D(Vec2D(), start, world); var worldEnd = Vec2D.transformMat2D(Vec2D(), end, world); paint.shader = makeGradient(ui.Offset(worldStart[0], worldStart[1]), @@ -105,15 +105,24 @@ class LinearGradient extends LinearGradientBase with ShapePaintMutator { addDirt(ComponentDirt.transform); } + @override + void onAdded() { + super.onAdded(); + syncColor(); + } + @override void opacityChanged(double from, double to) { syncColor(); - shapePaintContainer?.addDirt(ComponentDirt.paint); + shapePaintContainer!.addDirt(ComponentDirt.paint); } @override void syncColor() { - paint?.color = const ui.Color(0xFFFFFFFF) + paint.color = const ui.Color(0xFFFFFFFF) .withOpacity((opacity * renderOpacity).clamp(0, 1).toDouble()); } + + @override + bool validate() => super.validate() && shapePaintContainer != null; } diff --git a/lib/src/rive_core/shapes/paint/shape_paint.dart b/lib/src/rive_core/shapes/paint/shape_paint.dart index e17b0ed..c5b0ea4 100644 --- a/lib/src/rive_core/shapes/paint/shape_paint.dart +++ b/lib/src/rive_core/shapes/paint/shape_paint.dart @@ -9,20 +9,20 @@ import 'package:rive/src/generated/shapes/paint/shape_paint_base.dart'; export 'package:rive/src/generated/shapes/paint/shape_paint_base.dart'; abstract class ShapePaint extends ShapePaintBase { - Paint _paint; + late Paint _paint; Paint get paint => _paint; - ShapePaintMutator _paintMutator; - ShapePaintContainer _shapePaintContainer; - ShapePaintContainer get shapePaintContainer => _shapePaintContainer; + ShapePaintMutator? _paintMutator; + ShapePaintContainer? get shapePaintContainer => + parent is ShapePaintContainer ? parent as ShapePaintContainer : null; ShapePaint() { _paint = makePaint(); } BlendMode get blendMode => _paint.blendMode; set blendMode(BlendMode value) => _paint.blendMode = value; - double get renderOpacity => _paintMutator.renderOpacity; - set renderOpacity(double value) => _paintMutator.renderOpacity = value; - ShapePaintMutator get paintMutator => _paintMutator; - void _changeMutator(ShapePaintMutator mutator) { + double get renderOpacity => _paintMutator!.renderOpacity; + set renderOpacity(double value) => _paintMutator!.renderOpacity = value; + ShapePaintMutator? get paintMutator => _paintMutator; + void _changeMutator(ShapePaintMutator? mutator) { _paint = makePaint(); _paintMutator = mutator; } @@ -34,13 +34,28 @@ abstract class ShapePaint extends ShapePaintBase { super.childAdded(child); if (child is ShapePaintMutator) { _changeMutator(child as ShapePaintMutator); + if (shapePaintContainer != null) { + _initMutator(); + } + } + } + + @override + void parentChanged(ContainerComponent? from, ContainerComponent? to) { + super.parentChanged(from, to); + if (shapePaintContainer != null) { _initMutator(); } } + @override + bool validate() => + super.validate() && + parent is ShapePaintContainer && + _paintMutator != null; @override void isVisibleChanged(bool from, bool to) { - _shapePaintContainer?.addDirt(ComponentDirt.paint); + shapePaintContainer?.addDirt(ComponentDirt.paint); } @override @@ -52,22 +67,7 @@ abstract class ShapePaint extends ShapePaintBase { } } - @override - void parentChanged(ContainerComponent from, ContainerComponent to) { - super.parentChanged(from, to); - if (parent is ShapePaintContainer) { - _shapePaintContainer = parent as ShapePaintContainer; - _initMutator(); - } else { - _shapePaintContainer = null; - } - } - - void _initMutator() { - if (_shapePaintContainer != null && _paintMutator != null) { - _paintMutator.initializePaintMutator(_shapePaintContainer, paint); - } - } - + void _initMutator() => + _paintMutator?.initializePaintMutator(shapePaintContainer!, paint); void draw(Canvas canvas, Path path); } diff --git a/lib/src/rive_core/shapes/paint/shape_paint_mutator.dart b/lib/src/rive_core/shapes/paint/shape_paint_mutator.dart index 409e7fa..dfea358 100644 --- a/lib/src/rive_core/shapes/paint/shape_paint_mutator.dart +++ b/lib/src/rive_core/shapes/paint/shape_paint_mutator.dart @@ -3,9 +3,9 @@ import 'package:flutter/material.dart'; import 'package:rive/src/rive_core/shapes/shape_paint_container.dart'; abstract class ShapePaintMutator { - ShapePaintContainer _shapePaintContainer; - Paint _paint; - ShapePaintContainer get shapePaintContainer => _shapePaintContainer; + ShapePaintContainer? _shapePaintContainer; + late Paint _paint; + ShapePaintContainer? get shapePaintContainer => _shapePaintContainer; Paint get paint => _paint; double _renderOpacity = 1; double get renderOpacity => _renderOpacity; diff --git a/lib/src/rive_core/shapes/paint/solid_color.dart b/lib/src/rive_core/shapes/paint/solid_color.dart index 3d8b3c3..6ed8aac 100644 --- a/lib/src/rive_core/shapes/paint/solid_color.dart +++ b/lib/src/rive_core/shapes/paint/solid_color.dart @@ -1,7 +1,7 @@ import 'dart:ui'; import 'package:rive/src/rive_core/component_dirt.dart'; +import 'package:rive/src/rive_core/shapes/paint/shape_paint.dart'; import 'package:rive/src/rive_core/shapes/paint/shape_paint_mutator.dart'; -import 'package:rive/src/rive_core/shapes/shape_paint_container.dart'; import 'package:rive/src/generated/shapes/paint/solid_color_base.dart'; export 'package:rive/src/generated/shapes/paint/solid_color_base.dart'; @@ -20,14 +20,16 @@ class SolidColor extends SolidColorBase with ShapePaintMutator { @override void update(int dirt) {} @override - void initializePaintMutator(ShapePaintContainer paintContainer, Paint paint) { - super.initializePaintMutator(paintContainer, paint); - syncColor(); + void syncColor() { + paint.color = color + .withOpacity((color.opacity * renderOpacity).clamp(0, 1).toDouble()); } @override - void syncColor() { - paint?.color = color - .withOpacity((color.opacity * renderOpacity).clamp(0, 1).toDouble()); + bool validate() => super.validate() && parent is ShapePaint; + @override + void onAdded() { + super.onAdded(); + syncColor(); } } diff --git a/lib/src/rive_core/shapes/paint/stroke.dart b/lib/src/rive_core/shapes/paint/stroke.dart index 5929462..ef78ccd 100644 --- a/lib/src/rive_core/shapes/paint/stroke.dart +++ b/lib/src/rive_core/shapes/paint/stroke.dart @@ -7,8 +7,8 @@ import 'package:rive/src/generated/shapes/paint/stroke_base.dart'; export 'package:rive/src/generated/shapes/paint/stroke_base.dart'; class Stroke extends StrokeBase { - StrokeEffect _effect; - StrokeEffect get effect => _effect; + StrokeEffect? _effect; + StrokeEffect? get effect => _effect; // ignore: use_setters_to_change_properties void addStrokeEffect(StrokeEffect effect) { _effect = effect; @@ -66,10 +66,7 @@ class Stroke extends StrokeBase { } } - void invalidateEffects() { - _effect?.invalidateEffect(); - } - + void invalidateEffects() => _effect?.invalidateEffect(); @override void draw(Canvas canvas, Path path) { if (!isVisible) { diff --git a/lib/src/rive_core/shapes/paint/trim_path.dart b/lib/src/rive_core/shapes/paint/trim_path.dart index 87116ae..bca13f7 100644 --- a/lib/src/rive_core/shapes/paint/trim_path.dart +++ b/lib/src/rive_core/shapes/paint/trim_path.dart @@ -10,11 +10,11 @@ enum TrimPathMode { none, sequential, synchronized } class TrimPath extends TrimPathBase implements StrokeEffect { final Path _trimmedPath = Path(); - Path _renderPath; + Path? _renderPath; @override Path effectPath(Path source) { if (_renderPath != null) { - return _renderPath; + return _renderPath!; } _trimmedPath.reset(); var isSequential = mode == TrimPathMode.sequential; @@ -48,7 +48,7 @@ class TrimPath extends TrimPathBase implements StrokeEffect { return _renderPath = _trimmedPath; } - Stroke get stroke => parent as Stroke; + Stroke? get stroke => parent as Stroke?; TrimPathMode get mode => TrimPathMode.values[modeValue]; set mode(TrimPathMode value) => modeValue = value.index; @override diff --git a/lib/src/rive_core/shapes/paint/trim_path_drawing.dart b/lib/src/rive_core/shapes/paint/trim_path_drawing.dart index 71e0e67..eb08e56 100644 --- a/lib/src/rive_core/shapes/paint/trim_path_drawing.dart +++ b/lib/src/rive_core/shapes/paint/trim_path_drawing.dart @@ -8,9 +8,9 @@ class _FirstExtractedPath { _FirstExtractedPath(this.path, this.metric, this.length); } -_FirstExtractedPath _appendPathSegmentSequential( +_FirstExtractedPath? _appendPathSegmentSequential( Iterable metrics, Path result, double start, double stop, - {_FirstExtractedPath first}) { + {_FirstExtractedPath? first}) { double nextOffset = 0; double offset = 0; for (final metric in metrics) { @@ -20,23 +20,21 @@ _FirstExtractedPath _appendPathSegmentSequential( var et = min(metric.length, stop - offset); var extractLength = et - st; Path extracted = metric.extractPath(st, et); - if (extracted != null) { - if (first == null) { - // ignore: parameter_assignments - first = _FirstExtractedPath(extracted, metric, extractLength); - } else if (first.metric == metric) { - first.length += extractLength; - if (metric.isClosed) { - first.path.extendWithPath(extracted, Offset.zero); - } else { - result.addPath(extracted, Offset.zero); - } + if (first == null) { + // ignore: parameter_assignments + first = _FirstExtractedPath(extracted, metric, extractLength); + } else if (first.metric == metric) { + first.length += extractLength; + if (metric.isClosed) { + first.path.extendWithPath(extracted, Offset.zero); } else { - if (metric.isClosed && extractLength == metric.length) { - extracted.close(); - } result.addPath(extracted, Offset.zero); } + } else { + if (metric.isClosed && extractLength == metric.length) { + extracted.close(); + } + result.addPath(extracted, Offset.zero); } if (stop < nextOffset) { break; @@ -53,12 +51,10 @@ void _appendPathSegmentSync( double nextOffset = metric.length; if (start < nextOffset) { Path extracted = metric.extractPath(start, stop); - if (extracted != null) { - if (startWithMoveTo) { - to.addPath(extracted, Offset.zero); - } else { - to.extendWithPath(extracted, Offset.zero); - } + if (startWithMoveTo) { + to.addPath(extracted, Offset.zero); + } else { + to.extendWithPath(extracted, Offset.zero); } } } @@ -72,7 +68,7 @@ void _trimPathSequential( } double trimStart = totalLength * startT; double trimStop = totalLength * stopT; - _FirstExtractedPath first; + _FirstExtractedPath? first; if (complement) { if (trimStop < totalLength) { first = diff --git a/lib/src/rive_core/shapes/path.dart b/lib/src/rive_core/shapes/path.dart index 2f0434d..451993e 100644 --- a/lib/src/rive_core/shapes/path.dart +++ b/lib/src/rive_core/shapes/path.dart @@ -25,8 +25,8 @@ abstract class Path extends PathBase { bool _isValid = false; bool get isClosed; - Shape _shape; - Shape get shape => _shape; + Shape? _shape; + Shape? get shape => _shape; Mat2D get pathTransform; Mat2D get inversePathTransform; Mat2D get inverseWorldTransform => _inverseWorldTransform; @@ -44,7 +44,7 @@ abstract class Path extends PathBase { } } - void _changeShape(Shape value) { + void _changeShape(Shape? value) { if (_shape == value) { return; } @@ -64,7 +64,7 @@ abstract class Path extends PathBase { super.updateWorldTransform(); _shape?.pathChanged(this); if (!Mat2D.invert(_inverseWorldTransform, pathTransform)) { - Mat2D.identity(_inverseWorldTransform); + Mat2D.setIdentity(_inverseWorldTransform); } } @@ -88,7 +88,7 @@ abstract class Path extends PathBase { _renderPath.reset(); List vertices = this.vertices; var length = vertices.length; - if (vertices == null || length < 2) { + if (length < 2) { return false; } var firstPoint = vertices.first; diff --git a/lib/src/rive_core/shapes/path_composer.dart b/lib/src/rive_core/shapes/path_composer.dart index 00a481c..59e31c5 100644 --- a/lib/src/rive_core/shapes/path_composer.dart +++ b/lib/src/rive_core/shapes/path_composer.dart @@ -1,72 +1,57 @@ import 'dart:ui' as ui; +import 'package:rive/src/rive_core/artboard.dart'; import 'package:rive/src/rive_core/component.dart'; import 'package:rive/src/rive_core/component_dirt.dart'; import 'package:rive/src/rive_core/math/mat2d.dart'; import 'package:rive/src/rive_core/shapes/shape.dart'; -import 'package:rive/src/generated/shapes/path_composer_base.dart'; -class PathComposer extends PathComposerBase { - Shape _shape; - Shape get shape => _shape; +class PathComposer extends Component { + final Shape shape; + PathComposer(this.shape); + @override + Artboard? get artboard => shape.artboard; final ui.Path worldPath = ui.Path(); final ui.Path localPath = ui.Path(); - ui.Path _fillPath; + ui.Path _fillPath = ui.Path(); ui.Path get fillPath => _fillPath; - void _changeShape(Shape value) { - if (value == _shape) { - return; - } - if (_shape != null && _shape.pathComposer == this) { - _shape.pathComposer = null; - } - value?.pathComposer = this; - _shape = value; - } - void _recomputePath() { - var buildLocalPath = _shape.wantLocalPath; - var buildWorldPath = _shape.wantWorldPath || !buildLocalPath; + var buildLocalPath = shape.wantLocalPath; + var buildWorldPath = shape.wantWorldPath || !buildLocalPath; if (buildLocalPath) { localPath.reset(); - var world = _shape.worldTransform; + var world = shape.worldTransform; Mat2D inverseWorld = Mat2D(); if (Mat2D.invert(inverseWorld, world)) { - for (final path in _shape.paths) { + for (final path in shape.paths) { if (path.isHidden) { continue; } - Mat2D localTransform; - var transform = path.pathTransform; - if (transform != null) { - localTransform = Mat2D(); - Mat2D.multiply(localTransform, inverseWorld, transform); - } localPath.addPath(path.uiPath, ui.Offset.zero, - matrix4: localTransform?.mat4); + matrix4: + Mat2D.multiplySkipIdentity(inverseWorld, path.pathTransform) + .mat4); } } } if (buildWorldPath) { worldPath.reset(); - for (final path in _shape.paths) { + for (final path in shape.paths) { if (path.isHidden) { continue; } worldPath.addPath(path.uiPath, ui.Offset.zero, - matrix4: path.pathTransform?.mat4); + matrix4: path.pathTransform.mat4); } } - _fillPath = _shape.fillInWorld ? worldPath : localPath; + _fillPath = shape.fillInWorld ? worldPath : localPath; } @override void buildDependencies() { super.buildDependencies(); - if (_shape != null) { - _shape.addDependent(this); - for (final path in _shape?.paths) { - path.addDependent(this); - } + shape.addDependent(this); + for (final path in shape.paths) { + path.addDependent(this); } } @@ -76,18 +61,4 @@ class PathComposer extends PathComposerBase { _recomputePath(); } } - - @override - bool resolveArtboard() { - _changeShape(null); - return super.resolveArtboard(); - } - - @override - void visitAncestor(Component ancestor) { - super.visitAncestor(ancestor); - if (_shape == null && ancestor is Shape) { - _changeShape(ancestor); - } - } } diff --git a/lib/src/rive_core/shapes/path_vertex.dart b/lib/src/rive_core/shapes/path_vertex.dart index b2d7c7e..7f4848a 100644 --- a/lib/src/rive_core/shapes/path_vertex.dart +++ b/lib/src/rive_core/shapes/path_vertex.dart @@ -8,9 +8,9 @@ import 'package:rive/src/generated/shapes/path_vertex_base.dart'; export 'package:rive/src/generated/shapes/path_vertex_base.dart'; abstract class PathVertex extends PathVertexBase { - T _weight; - T get weight => _weight; - Path get path => parent is Path ? parent as Path : null; + T? _weight; + T? get weight => _weight; + Path? get path => parent as Path?; @override void update(int dirt) {} final Vec2D _renderTranslation = Vec2D(); @@ -21,6 +21,13 @@ abstract class PathVertex extends PathVertexBase { y = value[1]; } + @override + void onAddedDirty() { + super.onAddedDirty(); + _renderTranslation[0] = x; + _renderTranslation[1] = y; + } + @override void xChanged(double from, double to) { _renderTranslation[0] = to; @@ -55,7 +62,7 @@ abstract class PathVertex extends PathVertexBase { } void deform(Mat2D world, Float32List boneTransforms) { - Weight.deform(x, y, weight.indices, weight.values, world, boneTransforms, - _weight.translation); + Weight.deform(x, y, weight!.indices, weight!.values, world, boneTransforms, + _weight!.translation); } } diff --git a/lib/src/rive_core/shapes/points_path.dart b/lib/src/rive_core/shapes/points_path.dart index 0a2c8f0..81b4468 100644 --- a/lib/src/rive_core/shapes/points_path.dart +++ b/lib/src/rive_core/shapes/points_path.dart @@ -6,15 +6,13 @@ import 'package:rive/src/rive_core/shapes/path_vertex.dart'; import 'package:rive/src/generated/shapes/points_path_base.dart'; export 'package:rive/src/generated/shapes/points_path_base.dart'; -enum PointsPathEditMode { off, creating, editing } - class PointsPath extends PointsPathBase with Skinnable { final List _vertices = []; PointsPath() { isClosed = false; } @override - Mat2D get pathTransform => skin != null ? Mat2D() : worldTransform; + Mat2D get pathTransform => skin != null ? Mat2D.identity : worldTransform; @override Mat2D get inversePathTransform => skin != null ? Mat2D() : inverseWorldTransform; diff --git a/lib/src/rive_core/shapes/polygon.dart b/lib/src/rive_core/shapes/polygon.dart index 589bcbb..bdfcb3c 100644 --- a/lib/src/rive_core/shapes/polygon.dart +++ b/lib/src/rive_core/shapes/polygon.dart @@ -12,16 +12,16 @@ class Polygon extends PolygonBase { void pointsChanged(int from, int to) => markPathDirty(); @override List> get vertices { - var vertexList = List.filled(points, null); + var vertexList = >[]; var halfWidth = width / 2; var halfHeight = height / 2; var angle = -pi / 2; var inc = 2 * pi / points; for (int i = 0; i < points; i++) { - vertexList[i] = StraightVertex() + vertexList.add(StraightVertex.procedural() ..x = cos(angle) * halfWidth ..y = sin(angle) * halfHeight - ..radius = cornerRadius; + ..radius = cornerRadius); angle += inc; } return vertexList; diff --git a/lib/src/rive_core/shapes/rectangle.dart b/lib/src/rive_core/shapes/rectangle.dart index 2d460e4..077f340 100644 --- a/lib/src/rive_core/shapes/rectangle.dart +++ b/lib/src/rive_core/shapes/rectangle.dart @@ -9,19 +9,19 @@ class Rectangle extends RectangleBase { double ox = -originX * width; double oy = -originY * height; return [ - StraightVertex() + StraightVertex.procedural() ..x = ox ..y = oy ..radius = cornerRadius, - StraightVertex() + StraightVertex.procedural() ..x = ox + width ..y = oy ..radius = cornerRadius, - StraightVertex() + StraightVertex.procedural() ..x = ox + width ..y = oy + height ..radius = cornerRadius, - StraightVertex() + StraightVertex.procedural() ..x = ox ..y = oy + height ..radius = cornerRadius diff --git a/lib/src/rive_core/shapes/shape.dart b/lib/src/rive_core/shapes/shape.dart index 8b8d286..f1c9231 100644 --- a/lib/src/rive_core/shapes/shape.dart +++ b/lib/src/rive_core/shapes/shape.dart @@ -7,6 +7,7 @@ import 'package:rive/src/rive_core/shapes/path.dart'; import 'package:rive/src/rive_core/shapes/path_composer.dart'; import 'package:rive/src/rive_core/shapes/shape_paint_container.dart'; import 'package:rive/src/generated/shapes/shape_base.dart'; +import 'package:collection/collection.dart'; export 'package:rive/src/generated/shapes/shape_base.dart'; class Shape extends ShapeBase with ShapePaintContainer { @@ -17,24 +18,18 @@ class Shape extends ShapeBase with ShapePaintContainer { bool get wantLocalPath => _wantLocalPath; bool _fillInWorld = false; bool get fillInWorld => _fillInWorld; - PathComposer _pathComposer; - PathComposer get pathComposer => _pathComposer; - set pathComposer(PathComposer value) { - if (_pathComposer == value) { - return; - } - _pathComposer = value; - paintChanged(); + late PathComposer pathComposer; + Shape() { + pathComposer = PathComposer(this); } - - ui.Path get fillPath => _pathComposer.fillPath; + ui.Path get fillPath => pathComposer.fillPath; bool addPath(Path path) { paintChanged(); return paths.add(path); } void _markComposerDirty() { - _pathComposer?.addDirt(ComponentDirt.path, recurse: true); + pathComposer.addDirt(ComponentDirt.path, recurse: true); invalidateStrokeEffects(); } @@ -91,9 +86,8 @@ class Shape extends ShapeBase with ShapePaintContainer { } } _fillInWorld = _wantWorldPath || !_wantLocalPath; - var mustFillLocal = fills.firstWhere( - (fill) => fill.paintMutator is core.LinearGradient, - orElse: () => null) != + var mustFillLocal = fills.firstWhereOrNull( + (fill) => fill.paintMutator is core.LinearGradient) != null; if (mustFillLocal) { _fillInWorld = false; @@ -123,10 +117,8 @@ class Shape extends ShapeBase with ShapePaintContainer { void blendModeValueChanged(int from, int to) => _markBlendModeDirty(); @override void draw(ui.Canvas canvas) { - assert(_pathComposer != null); bool clipped = clip(canvas); - var path = _pathComposer.fillPath; - assert(path != null, 'path should\'ve been generated by the time we draw'); + var path = pathComposer.fillPath; if (!_fillInWorld) { canvas.save(); canvas.transform(worldTransform.mat4); @@ -140,8 +132,8 @@ class Shape extends ShapeBase with ShapePaintContainer { for (final stroke in strokes) { var transformAffectsStroke = stroke.transformAffectsStroke; var path = transformAffectsStroke - ? _pathComposer.localPath - : _pathComposer.worldPath; + ? pathComposer.localPath + : pathComposer.worldPath; if (transformAffectsStroke) { canvas.save(); canvas.transform(worldTransform.mat4); @@ -167,4 +159,9 @@ class Shape extends ShapeBase with ShapePaintContainer { void onStrokesChanged() => paintChanged(); @override void onFillsChanged() => paintChanged(); + @override + void buildDependencies() { + super.buildDependencies(); + pathComposer.buildDependencies(); + } } diff --git a/lib/src/rive_core/shapes/star.dart b/lib/src/rive_core/shapes/star.dart index f309bcf..bd5c784 100644 --- a/lib/src/rive_core/shapes/star.dart +++ b/lib/src/rive_core/shapes/star.dart @@ -11,24 +11,23 @@ class Star extends StarBase { @override List> get vertices { var actualPoints = points * 2; - var vertexList = - List.filled(actualPoints, null, growable: false); + var vertexList = >[]; var halfWidth = width / 2; var halfHeight = height / 2; var innerHalfWidth = width * innerRadius / 2; var innerHalfHeight = height * innerRadius / 2; var angle = -pi / 2; var inc = 2 * pi / actualPoints; - for (int i = 0; i < actualPoints; i++) { - vertexList[i++] = StraightVertex() + while (vertexList.length < actualPoints) { + vertexList.add(StraightVertex.procedural() ..x = cos(angle) * halfWidth ..y = sin(angle) * halfHeight - ..radius = cornerRadius; + ..radius = cornerRadius); angle += inc; - vertexList[i] = StraightVertex() + vertexList.add(StraightVertex.procedural() ..x = cos(angle) * innerHalfWidth ..y = sin(angle) * innerHalfHeight - ..radius = cornerRadius; + ..radius = cornerRadius); angle += inc; } return vertexList; diff --git a/lib/src/rive_core/shapes/straight_vertex.dart b/lib/src/rive_core/shapes/straight_vertex.dart index 0cc1e74..ad3a715 100644 --- a/lib/src/rive_core/shapes/straight_vertex.dart +++ b/lib/src/rive_core/shapes/straight_vertex.dart @@ -1,3 +1,4 @@ +import 'package:rive/src/core/core.dart'; import 'package:rive/src/rive_core/bones/weight.dart'; import 'package:rive/src/rive_core/component.dart'; import 'package:rive/src/rive_core/math/vec2d.dart'; @@ -5,7 +6,11 @@ import 'package:rive/src/generated/shapes/straight_vertex_base.dart'; export 'package:rive/src/generated/shapes/straight_vertex_base.dart'; class StraightVertex extends StraightVertexBase { - Weight _weight; + Weight? _weight; + StraightVertex(); + StraightVertex.procedural() { + InternalCoreHelper.markValid(this); + } @override String toString() => 'x[$x], y[$y], r[$radius]'; @override diff --git a/lib/src/rive_core/shapes/triangle.dart b/lib/src/rive_core/shapes/triangle.dart index 7c6af84..1ce3a5e 100644 --- a/lib/src/rive_core/shapes/triangle.dart +++ b/lib/src/rive_core/shapes/triangle.dart @@ -9,13 +9,13 @@ class Triangle extends TriangleBase { double ox = -originX * width; double oy = -originY * height; return [ - StraightVertex() + StraightVertex.procedural() ..x = ox + width / 2 ..y = oy, - StraightVertex() + StraightVertex.procedural() ..x = ox + width ..y = oy + height, - StraightVertex() + StraightVertex.procedural() ..x = ox ..y = oy + height ]; diff --git a/lib/src/rive_core/state_machine_controller.dart b/lib/src/rive_core/state_machine_controller.dart new file mode 100644 index 0000000..16d7c5c --- /dev/null +++ b/lib/src/rive_core/state_machine_controller.dart @@ -0,0 +1,150 @@ +import 'dart:collection'; +import 'package:rive/src/core/core.dart'; +import 'package:rive/src/rive_core/animation/animation_state.dart'; +import 'package:rive/src/rive_core/animation/layer_state.dart'; +import 'package:rive/src/rive_core/animation/linear_animation_instance.dart'; +import 'package:rive/src/rive_core/animation/state_machine.dart'; +import 'package:rive/src/rive_core/animation/state_machine_layer.dart'; +import 'package:rive/src/rive_core/animation/state_transition.dart'; +import 'package:rive/src/rive_core/rive_animation_controller.dart'; + +class LayerController { + final StateMachineLayer layer; + LayerState? _currentState; + LinearAnimationInstance? _animationInstanceFrom; + StateTransition? _transition; + double _mix = 1.0; + LinearAnimationInstance? _animationInstance; + LayerController(this.layer) { + _changeState(layer.entryState); + } + bool _changeState(LayerState? state) { + if (state == _currentState) { + return false; + } + _currentState = state; + return true; + } + + void dispose() { + _changeState(null); + } + + bool apply(CoreContext core, double elapsedSeconds, + HashMap inputValues) { + if (_animationInstance != null) { + _animationInstance!.advance(elapsedSeconds); + } + for (int i = 0; updateState(inputValues); i++) { + if (i == 100) { + print('StateMachineController.apply exceeded max iterations.'); + return false; + } + } + if (_transition != null && _transition!.duration != 0) { + _mix = (_mix + elapsedSeconds / (_transition!.duration / 1000)) + .clamp(0, 1) + .toDouble(); + } else { + _mix = 1; + } + var keepGoing = _mix != 1; + if (_animationInstanceFrom != null && _mix < 1) { + _animationInstanceFrom!.advance(elapsedSeconds); + _animationInstanceFrom!.animation.apply(_animationInstanceFrom!.time, + mix: 1 - _mix, coreContext: core); + } + if (_animationInstance != null) { + _animationInstance!.animation + .apply(_animationInstance!.time, mix: _mix, coreContext: core); + if (_animationInstance!.keepGoing) { + keepGoing = true; + } + } + return keepGoing; + } + + bool updateState(HashMap inputValues) { + if (tryChangeState(layer.anyState, inputValues)) { + return true; + } + return tryChangeState(_currentState, inputValues); + } + + bool tryChangeState( + LayerState? stateFrom, HashMap inputValues) { + if (stateFrom == null) { + return false; + } + for (final transition in stateFrom.transitions) { + bool valid = true; + for (final condition in transition.conditions) { + if (!condition.evaluate(inputValues)) { + valid = false; + break; + } + } + if (valid && _changeState(transition.stateTo)) { + _transition = transition; + if (_mix != 0) { + _animationInstanceFrom = _animationInstance; + } + if (_currentState is AnimationState) { + var animationState = _currentState as AnimationState; + var spilledTime = _animationInstanceFrom?.spilledTime ?? 0; + if (animationState.animation != null) { + _animationInstance = + LinearAnimationInstance(animationState.animation!); + _animationInstance!.advance(spilledTime); + } else { + _animationInstance = null; + } + _mix = 0; + } else { + _animationInstance = null; + } + return true; + } + } + return false; + } +} + +class StateMachineController extends RiveAnimationController { + final StateMachine stateMachine; + final inputValues = HashMap(); + StateMachineController(this.stateMachine); + final layerControllers = []; + void _clearLayerControllers() { + for (final layer in layerControllers) { + layer.dispose(); + } + layerControllers.clear(); + } + + @override + bool init(CoreContext core) { + _clearLayerControllers(); + for (final layer in stateMachine.layers) { + layerControllers.add(LayerController(layer)); + } + return super.init(core); + } + + @override + void dispose() { + _clearLayerControllers(); + super.dispose(); + } + + @override + void apply(CoreContext core, double elapsedSeconds) { + bool keepGoing = false; + for (final layerController in layerControllers) { + if (layerController.apply(core, elapsedSeconds, inputValues)) { + keepGoing = true; + } + } + isActive = keepGoing; + } +} diff --git a/lib/src/rive_core/state_transition_flags.dart b/lib/src/rive_core/state_transition_flags.dart new file mode 100644 index 0000000..b917ed4 --- /dev/null +++ b/lib/src/rive_core/state_transition_flags.dart @@ -0,0 +1,4 @@ +class StateTransitionFlags { + static const int disabled = 1 << 0; + static const int durationIsPercentage = 1 << 1; +} diff --git a/lib/src/rive_core/transform_component.dart b/lib/src/rive_core/transform_component.dart index f069546..f4a4d03 100644 --- a/lib/src/rive_core/transform_component.dart +++ b/lib/src/rive_core/transform_component.dart @@ -12,9 +12,9 @@ import 'package:rive/src/generated/transform_component_base.dart'; export 'package:rive/src/generated/transform_component_base.dart'; abstract class TransformComponent extends TransformComponentBase { - DrawRules _drawRules; - DrawRules get drawRules => _drawRules; - List _clippingShapes; + DrawRules? _drawRules; + DrawRules? get drawRules => _drawRules; + final List _clippingShapes = []; Iterable get clippingShapes => _clippingShapes; double _renderOpacity = 0; double get renderOpacity => _renderOpacity; @@ -41,7 +41,7 @@ abstract class TransformComponent extends TransformComponentBase { if (rotation != 0) { Mat2D.fromRotation(transform, rotation); } else { - Mat2D.identity(transform); + Mat2D.setIdentity(transform); } transform[4] = x; transform[5] = y; @@ -120,7 +120,7 @@ abstract class TransformComponent extends TransformComponentBase { } @override - void parentChanged(ContainerComponent from, ContainerComponent to) { + void parentChanged(ContainerComponent? from, ContainerComponent? to) { super.parentChanged(from, to); markWorldTransformDirty(); } @@ -133,7 +133,6 @@ abstract class TransformComponent extends TransformComponentBase { _drawRules = child as DrawRules; break; case ClippingShapeBase.typeKey: - _clippingShapes ??= []; _clippingShapes.add(child as ClippingShape); addDirt(ComponentDirt.clip, recurse: true); break; @@ -150,11 +149,8 @@ abstract class TransformComponent extends TransformComponentBase { } break; case ClippingShapeBase.typeKey: - if (_clippingShapes != null) { + if (_clippingShapes.isNotEmpty) { _clippingShapes.remove(child as ClippingShape); - if (_clippingShapes.isEmpty) { - _clippingShapes = null; - } addDirt(ComponentDirt.clip, recurse: true); } break; @@ -163,10 +159,10 @@ abstract class TransformComponent extends TransformComponentBase { @override void buildDrawOrder( - List drawables, DrawRules rules, List allRules) { + List drawables, DrawRules? rules, List allRules) { if (drawRules != null) { // ignore: parameter_assignments - rules = drawRules; + rules = drawRules!; allRules.add(rules); } super.buildDrawOrder(drawables, rules, allRules); diff --git a/lib/src/rive_file.dart b/lib/src/rive_file.dart index cef8b95..3018e32 100644 --- a/lib/src/rive_file.dart +++ b/lib/src/rive_file.dart @@ -1,188 +1,40 @@ import 'dart:collection'; import 'dart:typed_data'; -import 'package:rive/src/core/field_types/core_field_type.dart'; -import 'package:rive/src/rive_core/component.dart'; -import 'package:rive/src/rive_core/runtime/runtime_header.dart'; -import 'package:rive/src/rive_core/backboard.dart'; +import 'package:collection/collection.dart'; import 'package:rive/src/core/core.dart'; -import 'package:rive/src/utilities/binary_buffer/binary_reader.dart'; -import 'package:rive/src/rive_core/runtime/exceptions/rive_format_error_exception.dart'; -import 'package:rive/src/rive_core/animation/animation.dart'; +import 'package:rive/src/core/field_types/core_field_type.dart'; +import 'package:rive/src/generated/animation/animation_state_base.dart'; +import 'package:rive/src/generated/animation/any_state_base.dart'; +import 'package:rive/src/generated/animation/entry_state_base.dart'; +import 'package:rive/src/generated/animation/exit_state_base.dart'; +import 'package:rive/src/generated/animation/keyed_property_base.dart'; +import 'package:rive/src/generated/animation/state_machine_base.dart'; import 'package:rive/src/rive_core/animation/keyed_object.dart'; import 'package:rive/src/rive_core/animation/keyed_property.dart'; -import 'package:rive/src/rive_core/animation/keyframe.dart'; +import 'package:rive/src/rive_core/animation/layer_state.dart'; import 'package:rive/src/rive_core/animation/linear_animation.dart'; +import 'package:rive/src/rive_core/animation/state_machine.dart'; +import 'package:rive/src/rive_core/animation/state_machine_layer.dart'; import 'package:rive/src/rive_core/artboard.dart'; +import 'package:rive/src/rive_core/backboard.dart'; +import 'package:rive/src/rive_core/component.dart'; +import 'package:rive/src/rive_core/runtime/exceptions/rive_format_error_exception.dart'; +import 'package:rive/src/rive_core/runtime/runtime_header.dart'; +import 'package:rive/src/utilities/binary_buffer/binary_reader.dart'; -class RiveFile { - RuntimeHeader _header; - RuntimeHeader get header => _header; - Backboard _backboard; - Backboard get backboard => _backboard; +import 'rive_core/animation/state_transition.dart'; - final _artboards = []; - - /// Returns all artboards in the file - List get artboards => _artboards; - - /// Returns the first (main) artboard - Artboard get mainArtboard => _artboards.first; - - /// Returns an artboard from the specified name, or null if no artboard with - /// that name exists in the file - Artboard artboardByName(String name) => - _artboards.firstWhere((a) => a.name == name, orElse: () => null); - - /// Imports a Rive file from an array of bytes. Returns true if successfully - /// imported, false otherwise. - bool import(ByteData bytes) { - assert(_header == null, 'can only import once'); - var reader = BinaryReader(bytes); - _header = RuntimeHeader.read(reader); - - /// Property fields table of contents - final propertyToField = HashMap(); - - // List of core file types - final indexToField = [ - RiveCoreContext.uintType, - RiveCoreContext.stringType, - RiveCoreContext.doubleType, - RiveCoreContext.colorType - ]; - - _header.propertyToFieldIndex.forEach((key, fieldIndex) { - if (fieldIndex < 0 || fieldIndex >= indexToField.length) { - throw RiveFormatErrorException('unexpected field index $fieldIndex'); - } - - propertyToField[key] = indexToField[fieldIndex]; - }); - - _backboard = _readRuntimeObject(reader, propertyToField); - if (_backboard == null) { - throw const RiveFormatErrorException( - 'expected first object to be a Backboard'); - } - - int numArtboards = reader.readVarUint(); - for (int i = 0; i < numArtboards; i++) { - var numObjects = reader.readVarUint(); - if (numObjects == 0) { - throw const RiveFormatErrorException( - 'artboards must contain at least one object (themselves)'); - } - var artboard = - _readRuntimeObject(reader, propertyToField, RuntimeArtboard()); - // Kind of weird, but the artboard is the core context at runtime, so we - // want other objects to be able to resolve it. It's always at the 0 - // index. - artboard?.addObject(artboard); - _artboards.add(artboard); - // var objects = List>(numObjects); - for (int i = 1; i < numObjects; i++) { - Core object = _readRuntimeObject(reader, propertyToField); - // N.B. we add objects that don't load (null) too as we need to look - // them up by index. - artboard.addObject(object); - } - - // Animations also need to reference objects, so make sure they get read - // in before the hierarchy resolves (batch add completes). - var numAnimations = reader.readVarUint(); - for (int i = 0; i < numAnimations; i++) { - var animation = _readRuntimeObject(reader, propertyToField); - if (animation == null) { - continue; - } - artboard.addObject(animation); - animation.artboard = artboard; - if (animation is LinearAnimation) { - var numKeyedObjects = reader.readVarUint(); - var keyedObjects = List.filled(numKeyedObjects, null); - for (int j = 0; j < numKeyedObjects; j++) { - var keyedObject = - _readRuntimeObject(reader, propertyToField); - if (keyedObject == null) { - continue; - } - keyedObjects[j] = keyedObject; - artboard.addObject(keyedObject); - - animation.internalAddKeyedObject(keyedObject); - - var numKeyedProperties = reader.readVarUint(); - for (int k = 0; k < numKeyedProperties; k++) { - var keyedProperty = - _readRuntimeObject(reader, propertyToField); - if (keyedProperty == null) { - continue; - } - artboard.addObject(keyedProperty); - keyedObject.internalAddKeyedProperty(keyedProperty); - - var numKeyframes = reader.readVarUint(); - for (int l = 0; l < numKeyframes; l++) { - var keyframe = - _readRuntimeObject(reader, propertyToField); - if (keyframe == null) { - continue; - } - artboard.addObject(keyframe); - keyedProperty.internalAddKeyFrame(keyframe); - keyframe.computeSeconds(animation); - } - } - } - - for (final keyedObject in keyedObjects) { - keyedObject?.objectId ??= artboard.id; - } - } - } - - // Any component objects with no id map to the artboard. Skip first item - // as it's the artboard itself. - for (final object in artboard.objects.skip(1)) { - if (object is Component && object.parentId == null) { - object.parent = artboard; - } - object?.onAddedDirty(); - } - - assert(!artboard.children.contains(artboard), - 'artboard should never contain itself as a child'); - for (final object in artboard.objects.toList(growable: false)) { - if (object == null) { - continue; - } - object.onAdded(); - } - artboard.clean(); - } - - return true; - } -} - -void _skipProperty(BinaryReader reader, int propertyKey, - HashMap propertyToField) { - var field = - RiveCoreContext.coreType(propertyKey) ?? propertyToField[propertyKey]; - if (field == null) { - throw UnsupportedError('Unsupported property key $propertyKey. ' - 'A new runtime is likely necessary to play this file.'); - } - // Desrialize but don't do anything with the contents... - field.deserialize(reader); -} - -T _readRuntimeObject>( - BinaryReader reader, HashMap propertyToField, - [T instance]) { +Core? _readRuntimeObject( + BinaryReader reader, HashMap propertyToField) { int coreObjectKey = reader.readVarUint(); + Core? instance; + switch (coreObjectKey) { + case ArtboardBase.typeKey: + instance = RuntimeArtboard(); + break; + } var object = instance ?? RiveCoreContext.makeCoreInstance(coreObjectKey); while (true) { @@ -200,5 +52,179 @@ T _readRuntimeObject>( object, propertyKey, fieldType.deserialize(reader)); } } - return object as T; + return object; +} + +void _skipProperty(BinaryReader reader, int propertyKey, + HashMap propertyToField) { + var field = + RiveCoreContext.coreType(propertyKey) ?? propertyToField[propertyKey]; + if (field == null) { + throw UnsupportedError('Unsupported property key $propertyKey. ' + 'A new runtime is likely necessary to play this file.'); + } + // Desrialize but don't do anything with the contents... + field.deserialize(reader); +} + +/// Encapsulates a [RiveFile] and provides access to the list of [Artboard] +/// objects it contains. +class RiveFile { + /// Contains the [RiveFile]'s version information. + final RuntimeHeader header; + + Backboard _backboard = Backboard.unknown; + final _artboards = []; + + RiveFile._( + BinaryReader reader, + this.header, + ) { + /// Property fields table of contents + final propertyToField = HashMap(); + + // List of core file types + final indexToField = [ + RiveCoreContext.uintType, + RiveCoreContext.stringType, + RiveCoreContext.doubleType, + RiveCoreContext.colorType + ]; + + header.propertyToFieldIndex.forEach((key, fieldIndex) { + if (fieldIndex < 0 || fieldIndex >= indexToField.length) { + throw RiveFormatErrorException('unexpected field index $fieldIndex'); + } + + propertyToField[key] = indexToField[fieldIndex]; + }); + var importStack = ImportStack(); + while (!reader.isEOF) { + final object = _readRuntimeObject(reader, propertyToField); + if (object == null) { + // See if there's an artboard on the stack, need to track the null + // object as it'll still hold an id. + var artboardImporter = + importStack.latest(ArtboardBase.typeKey); + if (artboardImporter != null) { + artboardImporter.addComponent(null); + } + continue; + } + + ImportStackObject? stackObject; + var stackType = object.coreType; + switch (object.coreType) { + case ArtboardBase.typeKey: + stackObject = ArtboardImporter(object as RuntimeArtboard); + break; + case LinearAnimationBase.typeKey: + stackObject = LinearAnimationImporter(object as LinearAnimation); + // helper = _AnimationImportHelper(); + break; + case KeyedObjectBase.typeKey: + stackObject = KeyedObjectImporter(object as KeyedObject); + break; + case KeyedPropertyBase.typeKey: + { + // KeyedProperty importer requires a linear animation importer, so + // make sure there's one on the stack. + var linearAnimationImporter = + importStack.requireLatest( + LinearAnimationBase.typeKey); + stackObject = KeyedPropertyImporter(object as KeyedProperty, + linearAnimationImporter.linearAnimation); + break; + } + case StateMachineBase.typeKey: + stackObject = StateMachineImporter(object as StateMachine); + break; + case StateMachineLayerBase.typeKey: + { + // Needs artboard importer to resolve linear animations. + var artboardImporter = importStack + .requireLatest(ArtboardBase.typeKey); + stackObject = StateMachineLayerImporter( + object as StateMachineLayer, artboardImporter); + break; + } + case EntryStateBase.typeKey: + case AnyStateBase.typeKey: + case ExitStateBase.typeKey: + case AnimationStateBase.typeKey: + stackObject = LayerStateImporter(object as LayerState); + stackType = LayerStateBase.typeKey; + break; + case StateTransitionBase.typeKey: + { + var stateMachineImporter = importStack + .requireLatest(StateMachineBase.typeKey); + stackObject = StateTransitionImporter( + object as StateTransition, stateMachineImporter); + break; + } + default: + if (object is Component) { + // helper = _ArtboardObjectImportHelper(); + } + break; + } + + if (!importStack.makeLatest(stackType, stackObject)) { + throw const RiveFormatErrorException('Rive file is corrupt.'); + } + + if (object.import(importStack)) { + switch (object.coreType) { + case ArtboardBase.typeKey: + _artboards.add(object as Artboard); + break; + case BackboardBase.typeKey: + if (_backboard != Backboard.unknown) { + throw const RiveFormatErrorException( + 'Rive file expects only one backboard.'); + } + _backboard = object as Backboard; + break; + } + } + } + if (!importStack.resolve()) { + throw const RiveFormatErrorException('Rive file is corrupt.'); + } + if (_backboard == Backboard.unknown) { + throw const RiveFormatErrorException('Rive file is missing a backboard.'); + } + + for (final artboard in _artboards) { + var runtimeArtboard = artboard as RuntimeArtboard; + for (final object in runtimeArtboard.objects.whereNotNull()) { + if (object.validate()) { + InternalCoreHelper.markValid(object); + } else { + throw RiveFormatErrorException( + 'Rive file is corrupt. Invalid $object.'); + } + } + } + } + + /// Imports a Rive file from an array of bytes. Will throw + /// [RiveFormatErrorException] if data is malformed. Will throw + /// [RiveUnsupportedVersionException] if the version is not supported. + factory RiveFile.import(ByteData bytes) { + var reader = BinaryReader(bytes); + return RiveFile._(reader, RuntimeHeader.read(reader)); + } + + /// Returns all artboards in the file + List get artboards => _artboards; + + /// Returns the first (main) artboard + Artboard get mainArtboard => _artboards.first; + + /// Returns an artboard from the specified name, or null if no artboard with + /// that name exists in the file + Artboard? artboardByName(String name) => + _artboards.firstWhereOrNull((a) => a.name == name); } diff --git a/lib/src/rive_render_box.dart b/lib/src/rive_render_box.dart index 4e38d8e..0db6de4 100644 --- a/lib/src/rive_render_box.dart +++ b/lib/src/rive_render_box.dart @@ -9,8 +9,8 @@ import 'package:rive/src/rive_core/math/vec2d.dart'; abstract class RiveRenderBox extends RenderBox { final Stopwatch _stopwatch = Stopwatch(); - BoxFit _fit; - Alignment _alignment; + BoxFit _fit = BoxFit.none; + Alignment _alignment = Alignment.center; bool _useArtboardSize = false; bool get useArtboardSize => _useArtboardSize; @@ -25,7 +25,7 @@ abstract class RiveRenderBox extends RenderBox { } } - Size _artboardSize; + Size _artboardSize = Size.zero; Size get artboardSize => _artboardSize; @@ -58,7 +58,7 @@ abstract class RiveRenderBox extends RenderBox { } @override - bool get sizedByParent => !useArtboardSize || artboardSize == null; + bool get sizedByParent => !useArtboardSize; /// Finds the intrinsic size for the rive render box given the [constraints] /// and [sizedByParent]. @@ -176,19 +176,19 @@ abstract class RiveRenderBox extends RenderBox { markNeedsPaint(); } - int _frameCallbackId; + int _frameCallbackId = -1; void scheduleRepaint() { - if (_frameCallbackId != null) { + if (_frameCallbackId != -1) { return; } _frameCallbackId = - SchedulerBinding.instance.scheduleFrameCallback(_frameCallback); + SchedulerBinding.instance?.scheduleFrameCallback(_frameCallback) ?? -1; } @override void paint(PaintingContext context, Offset offset) { - _frameCallbackId = null; + _frameCallbackId = -1; if (advance(_elapsedSeconds)) { scheduleRepaint(); } else { @@ -199,78 +199,82 @@ abstract class RiveRenderBox extends RenderBox { final Canvas canvas = context.canvas; AABB bounds = aabb; - if (bounds != null) { - double contentWidth = bounds[2] - bounds[0]; - double contentHeight = bounds[3] - bounds[1]; - double x = -1 * bounds[0] - - contentWidth / 2.0 - - (_alignment.x * contentWidth / 2.0); - double y = -1 * bounds[1] - - contentHeight / 2.0 - - (_alignment.y * contentHeight / 2.0); - double scaleX = 1.0, scaleY = 1.0; + double contentWidth = bounds[2] - bounds[0]; + double contentHeight = bounds[3] - bounds[1]; - canvas.save(); - beforeDraw(canvas, offset); - - switch (_fit) { - case BoxFit.fill: - scaleX = size.width / contentWidth; - scaleY = size.height / contentHeight; - break; - case BoxFit.contain: - double minScale = - min(size.width / contentWidth, size.height / contentHeight); - scaleX = scaleY = minScale; - break; - case BoxFit.cover: - double maxScale = - max(size.width / contentWidth, size.height / contentHeight); - scaleX = scaleY = maxScale; - break; - case BoxFit.fitHeight: - double minScale = size.height / contentHeight; - scaleX = scaleY = minScale; - break; - case BoxFit.fitWidth: - double minScale = size.width / contentWidth; - scaleX = scaleY = minScale; - break; - case BoxFit.none: - scaleX = scaleY = 1.0; - break; - case BoxFit.scaleDown: - double minScale = - min(size.width / contentWidth, size.height / contentHeight); - scaleX = scaleY = minScale < 1.0 ? minScale : 1.0; - break; - } - - Mat2D transform = Mat2D(); - transform[4] = - offset.dx + size.width / 2.0 + (_alignment.x * size.width / 2.0); - transform[5] = - offset.dy + size.height / 2.0 + (_alignment.y * size.height / 2.0); - Mat2D.scale(transform, transform, Vec2D.fromValues(scaleX, scaleY)); - Mat2D center = Mat2D(); - center[4] = x; - center[5] = y; - Mat2D.multiply(transform, transform, center); - - canvas.translate( - offset.dx + size.width / 2.0 + (_alignment.x * size.width / 2.0), - offset.dy + size.height / 2.0 + (_alignment.y * size.height / 2.0), - ); - - canvas.scale(scaleX, scaleY); - canvas.translate(x, y); - - draw(canvas, transform); - - canvas.restore(); - afterDraw(canvas, offset); + if (contentWidth == 0 || contentHeight == 0) { + return; } + + double x = -1 * bounds[0] - + contentWidth / 2.0 - + (_alignment.x * contentWidth / 2.0); + double y = -1 * bounds[1] - + contentHeight / 2.0 - + (_alignment.y * contentHeight / 2.0); + + double scaleX = 1.0, scaleY = 1.0; + + canvas.save(); + beforeDraw(canvas, offset); + + switch (_fit) { + case BoxFit.fill: + scaleX = size.width / contentWidth; + scaleY = size.height / contentHeight; + break; + case BoxFit.contain: + double minScale = + min(size.width / contentWidth, size.height / contentHeight); + scaleX = scaleY = minScale; + break; + case BoxFit.cover: + double maxScale = + max(size.width / contentWidth, size.height / contentHeight); + scaleX = scaleY = maxScale; + break; + case BoxFit.fitHeight: + double minScale = size.height / contentHeight; + scaleX = scaleY = minScale; + break; + case BoxFit.fitWidth: + double minScale = size.width / contentWidth; + scaleX = scaleY = minScale; + break; + case BoxFit.none: + scaleX = scaleY = 1.0; + break; + case BoxFit.scaleDown: + double minScale = + min(size.width / contentWidth, size.height / contentHeight); + scaleX = scaleY = minScale < 1.0 ? minScale : 1.0; + break; + } + + Mat2D transform = Mat2D(); + transform[4] = + offset.dx + size.width / 2.0 + (_alignment.x * size.width / 2.0); + transform[5] = + offset.dy + size.height / 2.0 + (_alignment.y * size.height / 2.0); + Mat2D.scale(transform, transform, Vec2D.fromValues(scaleX, scaleY)); + Mat2D center = Mat2D(); + center[4] = x; + center[5] = y; + Mat2D.multiply(transform, transform, center); + + canvas.translate( + offset.dx + size.width / 2.0 + (_alignment.x * size.width / 2.0), + offset.dy + size.height / 2.0 + (_alignment.y * size.height / 2.0), + ); + + canvas.scale(scaleX, scaleY); + canvas.translate(x, y); + + draw(canvas, transform); + + canvas.restore(); + afterDraw(canvas, offset); } /// Advance animations, physics, etc by elapsedSeconds, returns true if it diff --git a/lib/src/runtime_artboard.dart b/lib/src/runtime_artboard.dart index 5430a97..969d5ce 100644 --- a/lib/src/runtime_artboard.dart +++ b/lib/src/runtime_artboard.dart @@ -11,17 +11,18 @@ class RuntimeArtboard extends Artboard implements CoreContext { final _redraw = Event(); ChangeNotifier get redraw => _redraw; - final List _objects = []; + /// Note that objects must be nullable as some may not resolve during load due + /// to format differences. + final List _objects = []; - Iterable get objects => _objects; + Iterable get objects => _objects; final Set _needDependenciesBuilt = {}; @override - T addObject(T object) { - if (object != null) { - object.context = this; - object.id = _objects.length; - } + T? addObject(T? object) { + object?.context = this; + object?.id = _objects.length; + _objects.add(object); return object; } @@ -32,9 +33,7 @@ class RuntimeArtboard extends Artboard implements CoreContext { } @override - void markDependencyOrderDirty() { - // TODO: implement markDependencyOrderDirty - } + void markDependencyOrderDirty() {} @override bool markDependenciesDirty(covariant Core object) { @@ -70,8 +69,8 @@ class RuntimeArtboard extends Artboard implements CoreContext { } @override - T resolve(int id) { - if (id >= _objects.length) { + T? resolve(int id) { + if (id >= _objects.length || id < 0) { return null; } var object = _objects[id]; @@ -82,7 +81,19 @@ class RuntimeArtboard extends Artboard implements CoreContext { } @override - Core makeCoreInstance(int typeKey) { + T resolveWithDefault(int id, T defaultValue) { + if (id >= _objects.length) { + return defaultValue; + } + var object = _objects[id]; + if (object is T) { + return object as T; + } + return defaultValue; + } + + @override + Core? makeCoreInstance(int typeKey) { return null; } diff --git a/lib/src/state_machine_components.dart b/lib/src/state_machine_components.dart new file mode 100644 index 0000000..927ae98 --- /dev/null +++ b/lib/src/state_machine_components.dart @@ -0,0 +1,20 @@ +import 'dart:collection'; +import 'package:rive/src/rive_core/animation/state_machine_component.dart'; + +class StateMachineComponents + extends ListBase { + final List _values = []; + List get values => _values.cast(); + + @override + int get length => _values.length; + + @override + set length(int value) => _values.length = value; + + @override + T operator [](int index) => _values[index]!; + + @override + void operator []=(int index, T value) => _values[index] = value; +} diff --git a/lib/src/state_machine_controller.dart b/lib/src/state_machine_controller.dart new file mode 100644 index 0000000..f70065a --- /dev/null +++ b/lib/src/state_machine_controller.dart @@ -0,0 +1,51 @@ +import 'package:rive/src/rive_core/animation/state_machine.dart'; +import 'package:rive/src/rive_core/artboard.dart'; +import 'package:rive/src/rive_core/state_machine_controller.dart' as core; + +class StateMachineInput { + final int id; + final StateMachineController controller; + StateMachineInput._(this.id, this.controller); + + T get value => controller.inputValues[id] as T; + set value(T newValue) => change(newValue); + + /// Change the value of the input, returns true if the value was changed the + /// and [StateMachineController] was activated. + bool change(T value) { + if (controller.inputValues[id] == value) { + return false; + } + controller.inputValues[id] = value; + controller.isActive = true; + return true; + } +} + +/// An AnimationController which controls a StateMachine and provides access to +/// the inputs of the StateMachine. +class StateMachineController extends core.StateMachineController { + StateMachineController(StateMachine stateMachine) : super(stateMachine) { + isActive = true; + } + + static StateMachineController? fromArtboard( + Artboard artboard, String stateMachineName) { + for (final animation in artboard.animations) { + if (animation is StateMachine && animation.name == stateMachineName) { + return StateMachineController(animation); + } + } + return null; + } + + StateMachineInput? findInput(String name) { + for (final input in stateMachine.inputs) { + if (input.name == name && input.isValidType()) { + inputValues[input.id] = input.controllerValue; + return StateMachineInput._(input.id, this); + } + } + return null; + } +} diff --git a/lib/src/state_transition_conditions.dart b/lib/src/state_transition_conditions.dart new file mode 100644 index 0000000..b25d858 --- /dev/null +++ b/lib/src/state_transition_conditions.dart @@ -0,0 +1,20 @@ +import 'dart:collection'; +import 'package:rive/src/rive_core/animation/transition_condition.dart'; + +class StateTransitionConditions extends ListBase { + final List _values = []; + List get values => _values.cast(); + + @override + int get length => _values.length; + + @override + set length(int value) => _values.length = value; + + @override + TransitionCondition operator [](int index) => _values[index]!; + + @override + void operator []=(int index, TransitionCondition value) => + _values[index] = value; +} diff --git a/lib/src/utilities/binary_buffer/binary_writer.dart b/lib/src/utilities/binary_buffer/binary_writer.dart index 427705e..7a2312e 100644 --- a/lib/src/utilities/binary_buffer/binary_writer.dart +++ b/lib/src/utilities/binary_buffer/binary_writer.dart @@ -12,13 +12,13 @@ class BinaryWriter { int get alignment => _alignment; final Endian endian; - Uint8List _buffer; + late Uint8List _buffer; ByteData get buffer => ByteData.view(_buffer.buffer, _buffer.offsetInBytes, size); Uint8List get uint8Buffer => Uint8List.view(_buffer.buffer, _buffer.offsetInBytes, size); - ByteData _byteData; + late ByteData _byteData; int _writeIndex = 0; int get size => _writeIndex; @@ -100,7 +100,7 @@ class BinaryWriter { /// Write bytes into the buffer. Optional [length] to write a specific number /// of [bytes], otherwise the length from [bytes] is used. - void write(Uint8List bytes, [int length]) { + void write(Uint8List bytes, [int? length]) { length ??= bytes.length; _ensureAvailable(length); _buffer.setRange(_writeIndex, _writeIndex + length, bytes); diff --git a/lib/src/utilities/dependency_sorter.dart b/lib/src/utilities/dependency_sorter.dart index 6625eec..94aa4f1 100644 --- a/lib/src/utilities/dependency_sorter.dart +++ b/lib/src/utilities/dependency_sorter.dart @@ -12,20 +12,15 @@ abstract class DependencyGraphNode { /// scenarios. Use this as a best case first run and fall back to a more complex /// solver if this one finds a cycle. class DependencySorter> { - HashSet _perm; - HashSet _temp; - List _order; + final _perm = HashSet(); + final _temp = HashSet(); + var _order = []; List get order => _order.reversed.toList(); - DependencySorter() { - _perm = HashSet(); - _temp = HashSet(); - } - List sort(T root) { _order = []; if (!visit(root)) { - return null; + return []; } return _order.reversed.toList(); } @@ -45,12 +40,10 @@ class DependencySorter> { _temp.add(n); - Set dependents = n.dependents; - if (dependents != null) { - for (final T d in dependents) { - if (!visit(d)) { - return false; - } + final dependents = n.dependents; + for (final T d in dependents) { + if (!visit(d)) { + return false; } } _perm.add(n); @@ -72,12 +65,7 @@ class DependencySorter> { /// on A class TarjansDependencySorter> extends DependencySorter { - HashSet _cycleNodes; - TarjansDependencySorter() { - _perm = HashSet(); - _temp = HashSet(); - _cycleNodes = HashSet(); - } + final _cycleNodes = HashSet(); HashSet get cycleNodes => _cycleNodes; @@ -102,15 +90,12 @@ class TarjansDependencySorter> _cycleNodes.clear(); _order.clear(); - var cycles = - stronglyConnectedComponents([n], (T node) => node.dependents); + var cycles = stronglyConnectedComponents([n], (node) => node.dependents); cycles.forEach((cycle) { // cycles of len 1 are not cycles. if (cycle.length > 1) { - cycle.forEach((cycleMember) { - _cycleNodes.add(cycleMember); - }); + cycle.forEach(_cycleNodes.add); } }); return _cycleNodes; diff --git a/lib/src/utilities/tops.dart b/lib/src/utilities/tops.dart index 44094be..ea3a151 100644 --- a/lib/src/utilities/tops.dart +++ b/lib/src/utilities/tops.dart @@ -1,5 +1,5 @@ abstract class Parentable { - T get parent; + T? get parent; } /// Get the top most components (any child that has an ancestor in the set @@ -8,7 +8,7 @@ Set tops>(Iterable parentables) { var tips = {}; outerLoop: for (final item in parentables) { - for (var parent = item.parent; parent != null; parent = parent.parent) { + for (T? parent = item.parent; parent != null; parent = parent.parent) { if (parentables.contains(parent)) { continue outerLoop; } @@ -19,7 +19,7 @@ Set tops>(Iterable parentables) { } bool isChildOf>(T child, Iterable parents) { - for (var parent = child; parent != null; parent = parent.parent) { + for (T? parent = child; parent != null; parent = parent.parent) { if (parents.contains(parent)) { return true; } diff --git a/lib/src/utilities/utilities.dart b/lib/src/utilities/utilities.dart index 7411003..5003232 100644 --- a/lib/src/utilities/utilities.dart +++ b/lib/src/utilities/utilities.dart @@ -1,8 +1,6 @@ /// Szudzik's function for hashing two ints together int szudzik(int a, int b) { - assert(a != null && b != null); // a and b must be >= 0 - int x = a.abs(); int y = b.abs(); return x >= y ? x * x + x + y : x + y * y; diff --git a/pubspec.yaml b/pubspec.yaml index 73cf102..73b6b77 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,16 +1,17 @@ name: rive 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. -version: 0.6.8 +version: 0.7.0-nullsafety.0 repository: https://github.com/rive-app/rive-flutter homepage: https://rive.app environment: - sdk: ">=2.7.0 <3.0.0" + sdk: ">=2.12.0 <3.0.0" dependencies: + collection: ^1.14.13 flutter: sdk: flutter - graphs: ^0.2.0 + graphs: ^1.0.0 meta: ^1.2.3 dev_dependencies: diff --git a/test/artboard_test.dart b/test/artboard_test.dart index 15efb42..58f0da7 100644 --- a/test/artboard_test.dart +++ b/test/artboard_test.dart @@ -5,7 +5,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:rive/rive.dart'; void main() { - ByteData multipleArtboardsBytes; + late ByteData multipleArtboardsBytes; void loadTestAssets() { multipleArtboardsBytes = ByteData.sublistView( @@ -15,14 +15,12 @@ void main() { setUp(loadTestAssets); test('Artboards can be read from files', () { - final riveFile = RiveFile(); - expect(riveFile.import(multipleArtboardsBytes), true); + RiveFile riveFile = RiveFile.import(multipleArtboardsBytes); expect(riveFile.mainArtboard.name, 'My Artboard'); }); test('Animations can be read from artboards', () { - final riveFile = RiveFile(); - expect(riveFile.import(multipleArtboardsBytes), true); + final riveFile = RiveFile.import(multipleArtboardsBytes); final artboard = riveFile.mainArtboard; expect(artboard.animations.length, 2); expect(artboard.animations.first.name, 'First'); @@ -30,8 +28,7 @@ void main() { }); test('Animations can be read by name from artboards', () { - final riveFile = RiveFile(); - expect(riveFile.import(multipleArtboardsBytes), true); + final riveFile = RiveFile.import(multipleArtboardsBytes); final artboard = riveFile.mainArtboard; expect(artboard.animationByName('First'), isNotNull); expect(artboard.animationByName('Second'), isNotNull); diff --git a/test/linear_animation_instance_test.dart b/test/linear_animation_instance_test.dart index 616fb31..585cefe 100644 --- a/test/linear_animation_instance_test.dart +++ b/test/linear_animation_instance_test.dart @@ -5,14 +5,13 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:rive/rive.dart'; void main() { - Artboard artboard; + late Artboard artboard; void loadTestAssets() { final riveData = ByteData.sublistView( File('assets/one_shot_0_6_5.riv').readAsBytesSync(), ); - final riveFile = RiveFile(); - expect(riveFile.import(riveData), true); + final riveFile = RiveFile.import(riveData); artboard = riveFile.mainArtboard; } diff --git a/test/rive_file_test.dart b/test/rive_file_test.dart index c8e96a9..df44829 100644 --- a/test/rive_file_test.dart +++ b/test/rive_file_test.dart @@ -5,7 +5,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:rive/rive.dart'; void main() { - ByteData multipleArtboardsBytes; + late ByteData multipleArtboardsBytes; void loadTestAssets() { multipleArtboardsBytes = ByteData.sublistView( @@ -16,37 +16,33 @@ void main() { test('Rive files load', () { // Create a dummy RiveFile - final riveFile = RiveFile(); - expect(riveFile.import(multipleArtboardsBytes), true); + RiveFile.import(multipleArtboardsBytes); }); test('Rive files contain the correct number of artboards', () { // Create a dummy RiveFile - final riveFile = RiveFile(); - riveFile.import(multipleArtboardsBytes); + final riveFile = RiveFile.import(multipleArtboardsBytes); expect(riveFile.artboards.length, 4); }); test('A default artboard is available in a Rive file', () { // Create a dummy RiveFile - final riveFile = RiveFile(); - riveFile.import(multipleArtboardsBytes); + final riveFile = RiveFile.import(multipleArtboardsBytes); expect(riveFile.mainArtboard, isNotNull); expect(riveFile.mainArtboard.name, 'Artboard 1'); }); test('Artboards can be retrieved by name', () { // Create a dummy RiveFile - final riveFile = RiveFile(); - riveFile.import(multipleArtboardsBytes); + final riveFile = RiveFile.import(multipleArtboardsBytes); var artboard = riveFile.artboardByName('Artboard 1'); expect(artboard, isNotNull); - expect(artboard.name, 'Artboard 1'); + expect(artboard!.name, 'Artboard 1'); artboard = riveFile.artboardByName('Artboard 3'); expect(artboard, isNotNull); - expect(artboard.name, 'Artboard 3'); + expect(artboard!.name, 'Artboard 3'); artboard = riveFile.artboardByName('Nonexistant'); expect(artboard, isNull); diff --git a/test/simple_animation_test.dart b/test/simple_animation_test.dart index b65edfb..a5d4df2 100644 --- a/test/simple_animation_test.dart +++ b/test/simple_animation_test.dart @@ -5,7 +5,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:rive/rive.dart'; void main() { - ByteData riveData; + late ByteData riveData; void loadTestAssets() { riveData = ByteData.sublistView( @@ -17,8 +17,7 @@ void main() { test('SimpleAnimation exposes mix', () { // Load a Rive file - final riveFile = RiveFile(); - expect(riveFile.import(riveData), true); + final riveFile = RiveFile.import(riveData); expect(riveFile.mainArtboard.name, 'My Artboard'); final firstController =