diff --git a/CHANGELOG.md b/CHANGELOG.md index b6a365b..5e9a5bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +## [0.0.4] - 2020-07-28 18:35:44 + +- Fundamental changes to runtime format enabling smaller file sizes. Format bumps to version 3.0 as it breaks backwards compatibility. + +## [0.0.3] - 2020-07-19 18:18:50 + +- Support shorter string encoding. Format bumps to version 2.0 as it breaks backwards compatibility. + +## [0.0.1+3] - 2020-07-09 11:13:22 + +- Fixing up ```flutter analyze``` issues thanks to @creativecreatorormaybenot. + ## [0.0.1+2] - 2020-07-08 16:47:10 - Updating meta dependency to one that is compatible with Flutter 😶 diff --git a/README.md b/README.md index defa1b7..c2a1943 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Rive +# Rive [![Pub Version](https://img.shields.io/pub/v/rive)](https://pub.dev/packages/rive) [Flutter package](https://pub.dev/packages/rive) for Rive 2. ## Bring Your Apps and Games to Life with Real-Time Animation @@ -7,8 +7,8 @@ ## Add to pubspec.yaml ```yaml dependencies: - rive: ^0.0.1+2 + rive: ^0.0.1+3 ``` ## Example -See how to use it in [example](example/). \ No newline at end of file +See how to use it in [example](example). diff --git a/example/assets/blue_artboard.riv b/example/assets/blue_artboard.riv deleted file mode 100644 index 53252c8..0000000 Binary files a/example/assets/blue_artboard.riv and /dev/null differ diff --git a/example/assets/colors_juice.riv b/example/assets/colors_juice.riv deleted file mode 100644 index 4231d67..0000000 Binary files a/example/assets/colors_juice.riv and /dev/null differ diff --git a/example/assets/cubic_work.riv b/example/assets/cubic_work.riv deleted file mode 100644 index 8e85833..0000000 Binary files a/example/assets/cubic_work.riv and /dev/null differ diff --git a/example/assets/draworderanimation_3.riv b/example/assets/draworderanimation_3.riv deleted file mode 100644 index 29ea0ac..0000000 Binary files a/example/assets/draworderanimation_3.riv and /dev/null differ diff --git a/example/assets/jet_fighter.riv b/example/assets/jet_fighter.riv deleted file mode 100644 index 2cbbae7..0000000 Binary files a/example/assets/jet_fighter.riv and /dev/null differ diff --git a/example/assets/ping_pong.riv b/example/assets/ping_pong.riv deleted file mode 100644 index 0a513b8..0000000 Binary files a/example/assets/ping_pong.riv and /dev/null differ diff --git a/example/assets/tape_deck.riv b/example/assets/tape_deck.riv deleted file mode 100644 index 96fcaa6..0000000 Binary files a/example/assets/tape_deck.riv and /dev/null differ diff --git a/example/assets/teeny_tiny.riv b/example/assets/teeny_tiny.riv new file mode 100644 index 0000000..e9b3a5b Binary files /dev/null and b/example/assets/teeny_tiny.riv differ diff --git a/example/assets/web_&_desktop_2.riv b/example/assets/web_&_desktop_2.riv deleted file mode 100644 index 09329cb..0000000 Binary files a/example/assets/web_&_desktop_2.riv and /dev/null differ diff --git a/example/lib/main.dart b/example/lib/main.dart index 88729b6..6b8fd0f 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -44,7 +44,7 @@ class _MyHomePageState extends State { // 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/colors_juice.riv').then( + rootBundle.load('assets/teeny_tiny.riv').then( (data) async { var file = RiveFile(); // Load the RiveFile from the binary data. @@ -56,7 +56,7 @@ class _MyHomePageState extends State { // 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('walk'), + _controller = SimpleAnimation('idle'), ); setState(() => _riveArtboard = artboard); } diff --git a/example/pubspec.lock b/example/pubspec.lock index ff38332..45a6529 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -21,7 +21,7 @@ packages: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.0.0" + version: "1.1.0-nullsafety" charcode: dependency: transitive description: @@ -42,7 +42,7 @@ packages: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.14.13" + version: "1.15.0-nullsafety" fake_async: dependency: transitive description: @@ -80,7 +80,7 @@ packages: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.1.8" + version: "1.3.0-nullsafety" path: dependency: transitive description: @@ -94,7 +94,7 @@ packages: path: ".." relative: true source: path - version: "0.0.1+2" + version: "0.0.4" sky_engine: dependency: transitive description: flutter @@ -148,13 +148,13 @@ packages: name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.3.0-nullsafety" vector_math: dependency: transitive description: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.0.8" + version: "2.1.0-nullsafety" sdks: - dart: ">=2.9.0-14.0.dev <3.0.0" + dart: ">=2.9.0-18.0 <2.9.0" diff --git a/lib/rive.dart b/lib/rive.dart index d9393ee..3a7f369 100644 --- a/lib/rive.dart +++ b/lib/rive.dart @@ -1,6 +1,16 @@ +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/controllers/simple_controller.dart'; -export 'package:rive/src/controllers/simple_controller.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/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'; \ No newline at end of file diff --git a/lib/src/controllers/simple_controller.dart b/lib/src/controllers/simple_controller.dart index 62d3e49..790d793 100644 --- a/lib/src/controllers/simple_controller.dart +++ b/lib/src/controllers/simple_controller.dart @@ -1,5 +1,5 @@ import 'package:rive/src/rive_core/animation/linear_animation.dart'; -import 'package:rive/src/rive_core/animation/loop.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'; @@ -7,70 +7,29 @@ import 'package:rive/src/runtime_artboard.dart'; /// by an artist. All playback parameters (looping, speed, keyframes) are artist /// defined in the Rive editor. class SimpleAnimation extends RiveAnimationController { - LinearAnimation _animation; - double _time = 0; - int _direction = 1; + LinearAnimationInstance _instance; final String animationName; SimpleAnimation(this.animationName); @override bool init(RuntimeArtboard artboard) { - _animation = artboard.animations.firstWhere( - (animation) => animation.name == animationName, + var animation = artboard.animations.firstWhere( + (animation) => + animation is LinearAnimation && animation.name == animationName, orElse: () => null, - ) as LinearAnimation; + ); + if (animation != null) { + _instance = LinearAnimationInstance(animation as LinearAnimation); + } isActive = true; - return _animation != null; + return _instance != null; } @override void apply(RuntimeArtboard artboard, double elapsedSeconds) { - _animation.apply(_time, coreContext: artboard); - _time += elapsedSeconds * _animation.speed * _direction; - - double frames = _time * _animation.fps; - - var start = _animation.enableWorkArea ? _animation.workStart : 0; - var end = - _animation.enableWorkArea ? _animation.workEnd : _animation.duration; - var range = end - start; - - switch (_animation.loop) { - case Loop.oneShot: - if (frames > end) { - isActive = false; - frames = end.toDouble(); - _time = frames / _animation.fps; - } - break; - case Loop.loop: - if (frames >= end) { - frames = _time * _animation.fps; - frames = start + (frames - start) % range; - _time = frames / _animation.fps; - } - break; - case Loop.pingPong: - // ignore: literal_only_boolean_expressions - while (true) { - if (_direction == 1 && frames >= end) { - _direction = -1; - frames = end + (end - frames); - _time = frames / _animation.fps; - } else if (_direction == -1 && frames < start) { - _direction = 1; - frames = start + (start - frames); - _time = frames / _animation.fps; - } else { - // we're within the range, we can stop fixing. We do this in a - // loop to fix conditions when time has advanced so far that we've - // ping-ponged back and forth a few times in a single frame. We - // want to accomodate for this in cases where animations are not - // advanced on regular intervals. - break; - } - } - break; + _instance.animation.apply(_instance.time, coreContext: artboard); + if (!_instance.advance(elapsedSeconds)) { + isActive = false; } } diff --git a/lib/src/core/field_types/core_bool_type.dart b/lib/src/core/field_types/core_bool_type.dart index 8c5b8e5..70bb679 100644 --- a/lib/src/core/field_types/core_bool_type.dart +++ b/lib/src/core/field_types/core_bool_type.dart @@ -1,11 +1,7 @@ import 'package:rive/src/core/field_types/core_field_type.dart'; import 'package:rive/src/utilities/binary_buffer/binary_reader.dart'; - class CoreBoolType extends CoreFieldType { @override bool deserialize(BinaryReader reader) => reader.readInt8() == 1; - - @override - bool lerp(bool from, bool to, double f) => from; } diff --git a/lib/src/core/field_types/core_color_type.dart b/lib/src/core/field_types/core_color_type.dart new file mode 100644 index 0000000..321942f --- /dev/null +++ b/lib/src/core/field_types/core_color_type.dart @@ -0,0 +1,7 @@ +import 'package:rive/src/core/field_types/core_field_type.dart'; +import 'package:rive/src/utilities/binary_buffer/binary_reader.dart'; + +class CoreColorType extends CoreFieldType { + @override + int deserialize(BinaryReader reader) => reader.readUint32(); +} diff --git a/lib/src/core/field_types/core_double_type.dart b/lib/src/core/field_types/core_double_type.dart index 8722d30..71f8784 100644 --- a/lib/src/core/field_types/core_double_type.dart +++ b/lib/src/core/field_types/core_double_type.dart @@ -3,10 +3,5 @@ import 'package:rive/src/utilities/binary_buffer/binary_reader.dart'; class CoreDoubleType extends CoreFieldType { @override - double deserialize(BinaryReader reader) => reader.buffer.lengthInBytes == 4 - ? reader.readFloat32() - : reader.readFloat64(); - - @override - double lerp(double from, double to, double f) => from + (to - from) * f; + double deserialize(BinaryReader reader) => reader.readFloat32(); } diff --git a/lib/src/core/field_types/core_field_type.dart b/lib/src/core/field_types/core_field_type.dart index c9e3f7d..a123e05 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 { T deserialize(BinaryReader reader); - T lerp(T from, T to, double f); } diff --git a/lib/src/core/field_types/core_fractional_index_type.dart b/lib/src/core/field_types/core_fractional_index_type.dart deleted file mode 100644 index 9ecb79a..0000000 --- a/lib/src/core/field_types/core_fractional_index_type.dart +++ /dev/null @@ -1,18 +0,0 @@ - -import 'package:rive/src/core/core.dart'; -import 'package:rive/src/core/field_types/core_field_type.dart'; -import 'package:rive/src/utilities/binary_buffer/binary_reader.dart'; - - -class CoreFractionalIndexType extends CoreFieldType { - @override - FractionalIndex deserialize(BinaryReader reader) { - var numerator = reader.readVarInt(); - var denominator = reader.readVarInt(); - return FractionalIndex(numerator, denominator); - } - - @override - FractionalIndex lerp(FractionalIndex from, FractionalIndex to, double f) => - from; -} diff --git a/lib/src/core/field_types/core_int_type.dart b/lib/src/core/field_types/core_int_type.dart index 056a0f0..5642bb1 100644 --- a/lib/src/core/field_types/core_int_type.dart +++ b/lib/src/core/field_types/core_int_type.dart @@ -1,11 +1,7 @@ import 'package:rive/src/core/field_types/core_field_type.dart'; import 'package:rive/src/utilities/binary_buffer/binary_reader.dart'; - class CoreIntType extends CoreFieldType { @override int deserialize(BinaryReader reader) => reader.readVarInt(); - - @override - int lerp(int from, int to, double f) => (from + (to - from) * f).round(); } diff --git a/lib/src/core/field_types/core_string_type.dart b/lib/src/core/field_types/core_string_type.dart index 1599a9c..80c3317 100644 --- a/lib/src/core/field_types/core_string_type.dart +++ b/lib/src/core/field_types/core_string_type.dart @@ -3,8 +3,6 @@ import 'package:rive/src/utilities/binary_buffer/binary_reader.dart'; class CoreStringType extends CoreFieldType { @override - String deserialize(BinaryReader reader) => reader.readString(); - - @override - String lerp(String from, String to, double f) => from; + String deserialize(BinaryReader reader) => + reader.readString(explicitLength: true); } diff --git a/lib/src/core/field_types/core_uint_type.dart b/lib/src/core/field_types/core_uint_type.dart new file mode 100644 index 0000000..cf4bdb1 --- /dev/null +++ b/lib/src/core/field_types/core_uint_type.dart @@ -0,0 +1,7 @@ +import 'package:rive/src/core/field_types/core_field_type.dart'; +import 'package:rive/src/utilities/binary_buffer/binary_reader.dart'; + +class CoreUintType extends CoreFieldType { + @override + int deserialize(BinaryReader reader) => reader.readVarUint(); +} diff --git a/lib/src/generated/rive_core_context.dart b/lib/src/generated/rive_core_context.dart index fd73615..5459e8b 100644 --- a/lib/src/generated/rive_core_context.dart +++ b/lib/src/generated/rive_core_context.dart @@ -1,9 +1,11 @@ import 'package:rive/src/core/core.dart'; import 'package:rive/src/core/field_types/core_bool_type.dart'; +import 'package:rive/src/core/field_types/core_color_type.dart'; import 'package:rive/src/core/field_types/core_double_type.dart'; import 'package:rive/src/core/field_types/core_field_type.dart'; import 'package:rive/src/core/field_types/core_int_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/cubic_interpolator_base.dart'; import 'package:rive/src/generated/animation/keyed_object_base.dart'; @@ -67,6 +69,7 @@ import 'package:rive/src/rive_core/shapes/shape.dart'; import 'package:rive/src/rive_core/shapes/straight_vertex.dart'; import 'package:rive/src/rive_core/shapes/triangle.dart'; +// ignore: avoid_classes_with_only_static_members class RiveCoreContext { static Core makeCoreInstance(int typeKey) { switch (typeKey) { @@ -475,30 +478,32 @@ class RiveCoreContext { } } + static CoreFieldType uintType = CoreUintType(); static CoreFieldType intType = CoreIntType(); static CoreFieldType stringType = CoreStringType(); static CoreFieldType doubleType = CoreDoubleType(); - static CoreFieldType colorType = CoreIntType(); + static CoreFieldType colorType = CoreColorType(); static CoreFieldType boolType = CoreBoolType(); static CoreFieldType coreType(int propertyKey) { switch (propertyKey) { case KeyedObjectBase.objectIdPropertyKey: + case KeyFrameBase.interpolatorIdPropertyKey: + case KeyFrameDrawOrderValueBase.drawableIdPropertyKey: + case KeyFrameDrawOrderValueBase.valuePropertyKey: + case ComponentBase.parentIdPropertyKey: + case DrawableBase.drawOrderPropertyKey: + return uintType; case KeyedPropertyBase.propertyKeyPropertyKey: case KeyFrameBase.framePropertyKey: case KeyFrameBase.interpolationTypePropertyKey: - case KeyFrameBase.interpolatorIdPropertyKey: case LinearAnimationBase.fpsPropertyKey: case LinearAnimationBase.durationPropertyKey: case LinearAnimationBase.loopValuePropertyKey: case LinearAnimationBase.workStartPropertyKey: case LinearAnimationBase.workEndPropertyKey: - case KeyFrameDrawOrderValueBase.drawableIdPropertyKey: - case KeyFrameDrawOrderValueBase.valuePropertyKey: - case ComponentBase.parentIdPropertyKey: case StrokeBase.capPropertyKey: case StrokeBase.joinPropertyKey: case FillBase.fillRulePropertyKey: - case DrawableBase.drawOrderPropertyKey: case DrawableBase.blendModeValuePropertyKey: return intType; case AnimationBase.namePropertyKey: @@ -559,18 +564,32 @@ class RiveCoreContext { } } - static int getInt(Core object, int propertyKey) { + static int getUint(Core object, int propertyKey) { switch (propertyKey) { case KeyedObjectBase.objectIdPropertyKey: return (object as KeyedObjectBase).objectId; + case KeyFrameBase.interpolatorIdPropertyKey: + return (object as KeyFrameBase).interpolatorId; + case KeyFrameDrawOrderValueBase.drawableIdPropertyKey: + return (object as KeyFrameDrawOrderValueBase).drawableId; + case KeyFrameDrawOrderValueBase.valuePropertyKey: + return (object as KeyFrameDrawOrderValueBase).value; + case ComponentBase.parentIdPropertyKey: + return (object as ComponentBase).parentId; + case DrawableBase.drawOrderPropertyKey: + return (object as DrawableBase).drawOrder; + } + return 0; + } + + static int getInt(Core object, int propertyKey) { + switch (propertyKey) { case KeyedPropertyBase.propertyKeyPropertyKey: return (object as KeyedPropertyBase).propertyKey; case KeyFrameBase.framePropertyKey: return (object as KeyFrameBase).frame; case KeyFrameBase.interpolationTypePropertyKey: return (object as KeyFrameBase).interpolationType; - case KeyFrameBase.interpolatorIdPropertyKey: - return (object as KeyFrameBase).interpolatorId; case LinearAnimationBase.fpsPropertyKey: return (object as LinearAnimationBase).fps; case LinearAnimationBase.durationPropertyKey: @@ -581,20 +600,12 @@ class RiveCoreContext { return (object as LinearAnimationBase).workStart; case LinearAnimationBase.workEndPropertyKey: return (object as LinearAnimationBase).workEnd; - case KeyFrameDrawOrderValueBase.drawableIdPropertyKey: - return (object as KeyFrameDrawOrderValueBase).drawableId; - case KeyFrameDrawOrderValueBase.valuePropertyKey: - return (object as KeyFrameDrawOrderValueBase).value; - case ComponentBase.parentIdPropertyKey: - return (object as ComponentBase).parentId; case StrokeBase.capPropertyKey: return (object as StrokeBase).cap; case StrokeBase.joinPropertyKey: return (object as StrokeBase).join; case FillBase.fillRulePropertyKey: return (object as FillBase).fillRule; - case DrawableBase.drawOrderPropertyKey: - return (object as DrawableBase).drawOrder; case DrawableBase.blendModeValuePropertyKey: return (object as DrawableBase).blendModeValue; } @@ -723,11 +734,31 @@ class RiveCoreContext { return false; } - static void setInt(Core object, int propertyKey, int value) { + static void setUint(Core object, int propertyKey, int value) { switch (propertyKey) { case KeyedObjectBase.objectIdPropertyKey: (object as KeyedObjectBase).objectId = value; break; + case KeyFrameBase.interpolatorIdPropertyKey: + (object as KeyFrameBase).interpolatorId = value; + break; + case KeyFrameDrawOrderValueBase.drawableIdPropertyKey: + (object as KeyFrameDrawOrderValueBase).drawableId = value; + break; + case KeyFrameDrawOrderValueBase.valuePropertyKey: + (object as KeyFrameDrawOrderValueBase).value = value; + break; + case ComponentBase.parentIdPropertyKey: + (object as ComponentBase).parentId = value; + break; + case DrawableBase.drawOrderPropertyKey: + (object as DrawableBase).drawOrder = value; + break; + } + } + + static void setInt(Core object, int propertyKey, int value) { + switch (propertyKey) { case KeyedPropertyBase.propertyKeyPropertyKey: (object as KeyedPropertyBase).propertyKey = value; break; @@ -737,9 +768,6 @@ class RiveCoreContext { case KeyFrameBase.interpolationTypePropertyKey: (object as KeyFrameBase).interpolationType = value; break; - case KeyFrameBase.interpolatorIdPropertyKey: - (object as KeyFrameBase).interpolatorId = value; - break; case LinearAnimationBase.fpsPropertyKey: (object as LinearAnimationBase).fps = value; break; @@ -755,15 +783,6 @@ class RiveCoreContext { case LinearAnimationBase.workEndPropertyKey: (object as LinearAnimationBase).workEnd = value; break; - case KeyFrameDrawOrderValueBase.drawableIdPropertyKey: - (object as KeyFrameDrawOrderValueBase).drawableId = value; - break; - case KeyFrameDrawOrderValueBase.valuePropertyKey: - (object as KeyFrameDrawOrderValueBase).value = value; - break; - case ComponentBase.parentIdPropertyKey: - (object as ComponentBase).parentId = value; - break; case StrokeBase.capPropertyKey: (object as StrokeBase).cap = value; break; @@ -773,9 +792,6 @@ class RiveCoreContext { case FillBase.fillRulePropertyKey: (object as FillBase).fillRule = value; break; - case DrawableBase.drawOrderPropertyKey: - (object as DrawableBase).drawOrder = value; - break; case DrawableBase.blendModeValuePropertyKey: (object as DrawableBase).blendModeValue = value; break; diff --git a/lib/src/generated/shapes/rectangle_base.dart b/lib/src/generated/shapes/rectangle_base.dart index ddda4fc..60d1de4 100644 --- a/lib/src/generated/shapes/rectangle_base.dart +++ b/lib/src/generated/shapes/rectangle_base.dart @@ -24,7 +24,7 @@ abstract class RectangleBase extends ParametricPath { /// -------------------------------------------------------------------------- /// CornerRadius field with key 31. - double _cornerRadius; + double _cornerRadius = 0; static const int cornerRadiusPropertyKey = 31; /// Radius of the corners of this rectangle diff --git a/lib/src/rive_core/animation/keyframe_draw_order_value.dart b/lib/src/rive_core/animation/keyframe_draw_order_value.dart index ae5f7a7..06a5241 100644 --- a/lib/src/rive_core/animation/keyframe_draw_order_value.dart +++ b/lib/src/rive_core/animation/keyframe_draw_order_value.dart @@ -19,10 +19,4 @@ class KeyFrameDrawOrderValue extends KeyFrameDrawOrderValueBase { drawable.drawOrder = value; } } - - @override - int runtimeValueValue(int editorValue) { - assert(false, 'this should never get called'); - return 0; - } } diff --git a/lib/src/rive_core/animation/linear_animation_instance.dart b/lib/src/rive_core/animation/linear_animation_instance.dart new file mode 100644 index 0000000..1b1465f --- /dev/null +++ b/lib/src/rive_core/animation/linear_animation_instance.dart @@ -0,0 +1,58 @@ +import 'package:rive/src/rive_core/animation/linear_animation.dart'; +import 'package:rive/src/rive_core/animation/loop.dart'; + +class LinearAnimationInstance { + final LinearAnimation animation; + double _time = 0; + int direction = 1; + LinearAnimationInstance(this.animation); + double get time => _time; + set time(double value) { + if (_time == value) { + return; + } + _time = value; + direction = 1; + } + + bool advance(double elapsedSeconds) { + _time += elapsedSeconds * animation.speed * direction; + double frames = _time * animation.fps; + var start = animation.enableWorkArea ? animation.workStart : 0; + var end = animation.enableWorkArea ? animation.workEnd : animation.duration; + var range = end - start; + bool keepGoing = true; + switch (animation.loop) { + case Loop.oneShot: + if (frames > end) { + keepGoing = false; + frames = end.toDouble(); + _time = frames / animation.fps; + } + break; + case Loop.loop: + if (frames >= end) { + frames = _time * animation.fps; + frames = start + (frames - start) % range; + _time = frames / animation.fps; + } + break; + case Loop.pingPong: + while (true) { + if (direction == 1 && frames >= end) { + direction = -1; + frames = end + (end - frames); + _time = frames / animation.fps; + } else if (direction == -1 && frames < start) { + direction = 1; + frames = start + (start - frames); + _time = frames / animation.fps; + } else { + break; + } + } + break; + } + return keepGoing; + } +} diff --git a/lib/src/rive_core/artboard.dart b/lib/src/rive_core/artboard.dart index fda90d6..813206d 100644 --- a/lib/src/rive_core/artboard.dart +++ b/lib/src/rive_core/artboard.dart @@ -189,6 +189,7 @@ class Artboard extends ArtboardBase with ShapePaintContainer { } canvas.save(); canvas.clipRect(Rect.fromLTWH(0, 0, width, height)); + canvas.translate(width * (originX ?? 0), height * (originY ?? 0)); for (final drawable in _drawables) { drawable.draw(canvas); } @@ -202,9 +203,15 @@ class Artboard extends ArtboardBase with ShapePaintContainer { @override Mat2D get worldTransform => Mat2D(); @override - void originXChanged(double from, double to) {} + void originXChanged(double from, double to) { + addDirt(ComponentDirt.worldTransform); + } + @override - void originYChanged(double from, double to) {} + void originYChanged(double from, double to) { + addDirt(ComponentDirt.worldTransform); + } + bool internalAddAnimation(Animation animation) { if (_animations.contains(animation)) { return false; diff --git a/lib/src/rive_core/bounds_delegate.dart b/lib/src/rive_core/bounds_delegate.dart deleted file mode 100644 index 48de16b..0000000 --- a/lib/src/rive_core/bounds_delegate.dart +++ /dev/null @@ -1,3 +0,0 @@ -abstract class BoundsDelegate { - void boundsChanged(); -} diff --git a/lib/src/rive_core/math/mat2d.dart b/lib/src/rive_core/math/mat2d.dart index cab0418..ac86869 100644 --- a/lib/src/rive_core/math/mat2d.dart +++ b/lib/src/rive_core/math/mat2d.dart @@ -48,6 +48,10 @@ class Mat2D { 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); } diff --git a/lib/src/rive_core/math/segment2d.dart b/lib/src/rive_core/math/segment2d.dart index 14eb98c..a852574 100644 --- a/lib/src/rive_core/math/segment2d.dart +++ b/lib/src/rive_core/math/segment2d.dart @@ -12,7 +12,7 @@ class Segment2D { Vec2D diff; double lengthSquared; Segment2D(this.start, this.end); - ProjectionResult projectPoint(Vec2D point) { + ProjectionResult projectPoint(Vec2D point, {bool clamp = true}) { if (diff == null) { diff = Vec2D.subtract(Vec2D(), start, end); lengthSquared = Vec2D.squaredLength(diff); @@ -23,11 +23,13 @@ class Segment2D { double t = ((point[0] - start[0]) * (end[0] - start[0]) + (point[1] - start[1]) * (end[1] - start[1])) / lengthSquared; - if (t < 0.0) { - return ProjectionResult(0, start); - } - if (t > 1.0) { - return ProjectionResult(1, end); + if (clamp) { + if (t < 0.0) { + return ProjectionResult(0, start); + } + if (t > 1.0) { + return ProjectionResult(1, end); + } } return ProjectionResult( t, diff --git a/lib/src/rive_core/node.dart b/lib/src/rive_core/node.dart index afd195e..4460500 100644 --- a/lib/src/rive_core/node.dart +++ b/lib/src/rive_core/node.dart @@ -1,7 +1,7 @@ import 'package:flutter/foundation.dart'; -import 'package:rive/src/rive_core/bounds_delegate.dart'; import 'package:rive/src/rive_core/component_dirt.dart'; import 'package:rive/src/rive_core/container_component.dart'; +import 'package:rive/src/rive_core/math/aabb.dart'; import 'package:rive/src/rive_core/math/mat2d.dart'; import 'package:rive/src/rive_core/math/vec2d.dart'; import 'package:rive/src/generated/node_base.dart'; @@ -11,7 +11,6 @@ export 'package:rive/src/generated/node_base.dart'; class Node extends NodeBase { final Mat2D transform = Mat2D(); final Mat2D worldTransform = Mat2D(); - BoundsDelegate _delegate; double _renderOpacity = 0; double get renderOpacity => _renderOpacity; @override @@ -60,16 +59,6 @@ class Node extends NodeBase { } else { Mat2D.copy(worldTransform, transform); } - _delegate?.boundsChanged(); - } - - @override - void userDataChanged(dynamic from, dynamic to) { - if (to is BoundsDelegate) { - _delegate = to; - } else { - _delegate = null; - } } void calculateWorldTransform() { @@ -139,4 +128,6 @@ class Node extends NodeBase { super.parentChanged(from, to); markWorldTransformDirty(); } + + AABB get localBounds => AABB.fromValues(x, y, x, y); } diff --git a/lib/src/rive_core/runtime/runtime_header.dart b/lib/src/rive_core/runtime/runtime_header.dart index 231920f..00ce8ee 100644 --- a/lib/src/rive_core/runtime/runtime_header.dart +++ b/lib/src/rive_core/runtime/runtime_header.dart @@ -4,7 +4,7 @@ import 'package:rive/src/utilities/binary_buffer/binary_reader.dart'; import 'exceptions/rive_format_error_exception.dart'; class RuntimeHeader { - static const int majorVersion = 1; + static const int majorVersion = 3; static const int minorVersion = 0; static const String fingerprint = 'RIVE'; final int ownerId; diff --git a/lib/src/rive_core/shapes/cubic_asymmetric_vertex.dart b/lib/src/rive_core/shapes/cubic_asymmetric_vertex.dart index e377105..bad8694 100644 --- a/lib/src/rive_core/shapes/cubic_asymmetric_vertex.dart +++ b/lib/src/rive_core/shapes/cubic_asymmetric_vertex.dart @@ -16,6 +16,11 @@ class CubicAsymmetricVertex extends CubicAsymmetricVertexBase { cos(rotation) * outDistance, sin(rotation) * outDistance)); } + @override + set outPoint(Vec2D value) { + _outPoint = Vec2D.clone(value); + } + @override Vec2D get inPoint { return _inPoint ??= Vec2D.add( @@ -25,6 +30,11 @@ class CubicAsymmetricVertex extends CubicAsymmetricVertexBase { cos(rotation) * -inDistance, sin(rotation) * -inDistance)); } + @override + set inPoint(Vec2D value) { + _inPoint = Vec2D.clone(value); + } + @override String toString() { return 'in ${inPoint[0]}, ${inPoint[1]} | ${translation.toString()} ' diff --git a/lib/src/rive_core/shapes/cubic_mirrored_vertex.dart b/lib/src/rive_core/shapes/cubic_mirrored_vertex.dart index 1899835..d03e9fb 100644 --- a/lib/src/rive_core/shapes/cubic_mirrored_vertex.dart +++ b/lib/src/rive_core/shapes/cubic_mirrored_vertex.dart @@ -13,12 +13,23 @@ class CubicMirroredVertex extends CubicMirroredVertexBase { Vec2D.fromValues(cos(rotation) * distance, sin(rotation) * distance)); } + @override + set outPoint(Vec2D value) { + _outPoint = Vec2D.clone(value); + } + @override Vec2D get inPoint { return _inPoint ??= Vec2D.add(Vec2D(), translation, Vec2D.fromValues(cos(rotation) * -distance, sin(rotation) * -distance)); } + @override + set inPoint(Vec2D value) { + var diffIn = Vec2D.fromValues(value[0] - x, value[1] - y); + outPoint = Vec2D.subtract(Vec2D(), translation, diffIn); + } + @override String toString() { return 'in ${inPoint[0]}, ${inPoint[1]} | ${translation.toString()} ' diff --git a/lib/src/rive_core/shapes/cubic_vertex.dart b/lib/src/rive_core/shapes/cubic_vertex.dart index 2ea5b38..a52e95f 100644 --- a/lib/src/rive_core/shapes/cubic_vertex.dart +++ b/lib/src/rive_core/shapes/cubic_vertex.dart @@ -4,4 +4,6 @@ import 'package:rive/src/generated/shapes/cubic_vertex_base.dart'; abstract class CubicVertex extends CubicVertexBase { Vec2D get outPoint; Vec2D get inPoint; + set outPoint(Vec2D value); + set inPoint(Vec2D value); } diff --git a/lib/src/rive_core/shapes/paint/gradient_stop.dart b/lib/src/rive_core/shapes/paint/gradient_stop.dart index 324d203..4c543a4 100644 --- a/lib/src/rive_core/shapes/paint/gradient_stop.dart +++ b/lib/src/rive_core/shapes/paint/gradient_stop.dart @@ -1,17 +1,10 @@ import 'dart:ui' as ui; -import 'package:rive/src/rive_core/component.dart'; import 'package:rive/src/rive_core/container_component.dart'; import 'package:rive/src/generated/shapes/paint/gradient_stop_base.dart'; 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 { - @override - Component get timelineParent => - _gradient is LinearGradient ? _gradient.parent : null; - @override - String get timelineName => - 'Stop ${_gradient.gradientStops.indexOf(this) + 1}'; LinearGradient _gradient; LinearGradient get gradient => _gradient; ui.Color get color => ui.Color(colorValue); diff --git a/lib/src/rive_core/shapes/paint/linear_gradient.dart b/lib/src/rive_core/shapes/paint/linear_gradient.dart index c78ea02..b518d7d 100644 --- a/lib/src/rive_core/shapes/paint/linear_gradient.dart +++ b/lib/src/rive_core/shapes/paint/linear_gradient.dart @@ -10,8 +10,6 @@ export 'package:rive/src/generated/shapes/paint/linear_gradient_base.dart'; class LinearGradient extends LinearGradientBase with ShapePaintMutator { final List gradientStops = []; - @override - Component get timelineProxy => parent; bool _paintsInWorldSpace = true; bool get paintsInWorldSpace => _paintsInWorldSpace; set paintsInWorldSpace(bool value) { diff --git a/lib/src/rive_core/shapes/paint/shape_paint.dart b/lib/src/rive_core/shapes/paint/shape_paint.dart index 402914d..e17b0ed 100644 --- a/lib/src/rive_core/shapes/paint/shape_paint.dart +++ b/lib/src/rive_core/shapes/paint/shape_paint.dart @@ -21,8 +21,6 @@ abstract class ShapePaint extends ShapePaintBase { set blendMode(BlendMode value) => _paint.blendMode = value; double get renderOpacity => _paintMutator.renderOpacity; set renderOpacity(double value) => _paintMutator.renderOpacity = value; - @override - Component get timelineParent => _shapePaintContainer as Component; ShapePaintMutator get paintMutator => _paintMutator; void _changeMutator(ShapePaintMutator mutator) { _paint = makePaint(); diff --git a/lib/src/rive_core/shapes/paint/solid_color.dart b/lib/src/rive_core/shapes/paint/solid_color.dart index 0cde995..3d8b3c3 100644 --- a/lib/src/rive_core/shapes/paint/solid_color.dart +++ b/lib/src/rive_core/shapes/paint/solid_color.dart @@ -1,5 +1,4 @@ import 'dart:ui'; -import 'package:rive/src/rive_core/component.dart'; import 'package:rive/src/rive_core/component_dirt.dart'; import 'package:rive/src/rive_core/shapes/paint/shape_paint_mutator.dart'; import 'package:rive/src/rive_core/shapes/shape_paint_container.dart'; @@ -7,8 +6,6 @@ import 'package:rive/src/generated/shapes/paint/solid_color_base.dart'; export 'package:rive/src/generated/shapes/paint/solid_color_base.dart'; class SolidColor extends SolidColorBase with ShapePaintMutator { - @override - Component get timelineProxy => parent; Color get color => Color(colorValue); set color(Color c) { colorValue = c.value; diff --git a/lib/src/rive_core/shapes/paint/stroke.dart b/lib/src/rive_core/shapes/paint/stroke.dart index 4f97189..fe65130 100644 --- a/lib/src/rive_core/shapes/paint/stroke.dart +++ b/lib/src/rive_core/shapes/paint/stroke.dart @@ -11,8 +11,6 @@ class Stroke extends StrokeBase { ..strokeCap = strokeCap ..strokeJoin = strokeJoin ..strokeWidth = thickness; - @override - String get timelineParentGroup => 'strokes'; StrokeCap get strokeCap => StrokeCap.values[cap]; set strokeCap(StrokeCap value) => cap = value.index; StrokeJoin get strokeJoin => StrokeJoin.values[join]; diff --git a/lib/src/rive_core/shapes/path.dart b/lib/src/rive_core/shapes/path.dart index 51c10ca..06d4f67 100644 --- a/lib/src/rive_core/shapes/path.dart +++ b/lib/src/rive_core/shapes/path.dart @@ -1,6 +1,5 @@ import 'dart:math'; import 'dart:ui' as ui; -import 'package:rive/src/rive_core/bounds_delegate.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/aabb.dart'; @@ -33,27 +32,11 @@ abstract class Path extends PathBase { Mat2D get inversePathTransform; Mat2D get inverseWorldTransform => _inverseWorldTransform; @override - Component get timelineParent => _shape; - @override bool resolveArtboard() { _changeShape(null); return super.resolveArtboard(); } - BoundsDelegate _delegate; - void markBoundsDirty() { - _delegate?.boundsChanged(); - } - - @override - void userDataChanged(dynamic from, dynamic to) { - if (to is BoundsDelegate) { - _delegate = to; - } else { - _delegate = null; - } - } - @override void visitAncestor(Component ancestor) { if (_shape == null && ancestor is Shape) { @@ -95,18 +78,9 @@ abstract class Path extends PathBase { void markPathDirty() { addDirt(ComponentDirt.path); - _shape?.pathChanged(this); - } - - void _invalidatePath() { _isValid = false; _cachedRenderVertices = null; - } - - @override - bool addDirt(int value, {bool recurse = false}) { - _invalidatePath(); - return super.addDirt(value, recurse: recurse); + _shape?.pathChanged(this); } List get vertices; @@ -126,6 +100,7 @@ abstract class Path extends PathBase { List renderPoints = []; int pl = pts.length; const double iarcConstant = 1.0 - circleConstant; + PathVertex previous = isClosed ? pts[pl - 1] : null; for (int i = 0; i < pl; i++) { PathVertex point = pts[i]; @@ -221,7 +196,10 @@ abstract class Path extends PathBase { return true; } - AABB preciseComputeBounds(List renderPoints, Mat2D transform) { + @override + AABB get localBounds => preciseComputeBounds(renderVertices, Mat2D()); + AABB preciseComputeBounds(List renderPoints, Mat2D transform, + {bool debug = false}) { if (renderPoints.isEmpty) { return AABB(); } @@ -247,7 +225,6 @@ abstract class Path extends PathBase { cin = Vec2D.transformMat2D(Vec2D(), cin, transform); cout = Vec2D.transformMat2D(Vec2D(), cout, transform); } - const double epsilon = 0.000000001; final double startX = lastPoint[0]; final double startY = lastPoint[1]; final double cpX1 = cout[0]; @@ -257,121 +234,55 @@ abstract class Path extends PathBase { final double endX = next[0]; final double endY = next[1]; lastPoint = next; - double extremaX; - double extremaY; - double a, b, c; - if (!(((startX < cpX1) && (cpX1 < cpX2) && (cpX2 < endX)) || - ((startX > cpX1) && (cpX1 > cpX2) && (cpX2 > endX)))) { - a = -startX + (3 * (cpX1 - cpX2)) + endX; - b = 2 * (startX - (2 * cpX1) + cpX2); - c = -startX + cpX1; - double s = (b * b) - (4 * a * c); - if ((s >= 0.0) && (a.abs() > epsilon)) { - if (s == 0.0) { - final double t = -b / (2 * a); - final double tprime = 1.0 - t; - if ((t >= 0.0) && (t <= 1.0)) { - extremaX = ((tprime * tprime * tprime) * startX) + - ((3 * tprime * tprime * t) * cpX1) + - ((3 * tprime * t * t) * cpX2) + - (t * t * t * endX); - if (extremaX < bounds[0]) { - bounds[0] = extremaX; - } - if (extremaX > bounds[2]) { - bounds[2] = extremaX; - } - } - } else { - s = sqrt(s); - double t = (-b - s) / (2 * a); - double tprime = 1.0 - t; - if ((t >= 0.0) && (t <= 1.0)) { - extremaX = ((tprime * tprime * tprime) * startX) + - ((3 * tprime * tprime * t) * cpX1) + - ((3 * tprime * t * t) * cpX2) + - (t * t * t * endX); - if (extremaX < bounds[0]) { - bounds[0] = extremaX; - } - if (extremaX > bounds[2]) { - bounds[2] = extremaX; - } - } - t = (-b + s) / (2 * a); - tprime = 1.0 - t; - if ((t >= 0.0) && (t <= 1.0)) { - extremaX = ((tprime * tprime * tprime) * startX) + - ((3 * tprime * tprime * t) * cpX1) + - ((3 * tprime * t * t) * cpX2) + - (t * t * t * endX); - if (extremaX < bounds[0]) { - bounds[0] = extremaX; - } - if (extremaX > bounds[2]) { - bounds[2] = extremaX; - } - } - } - } - } - if (!(((startY < cpY1) && (cpY1 < cpY2) && (cpY2 < endY)) || - ((startY > cpY1) && (cpY1 > cpY2) && (cpY2 > endY)))) { - a = -startY + (3 * (cpY1 - cpY2)) + endY; - b = 2 * (startY - (2 * cpY1) + cpY2); - c = -startY + cpY1; - double s = (b * b) - (4 * a * c); - if ((s >= 0.0) && (a.abs() > epsilon)) { - if (s == 0.0) { - final double t = -b / (2 * a); - final double tprime = 1.0 - t; - if ((t >= 0.0) && (t <= 1.0)) { - extremaY = ((tprime * tprime * tprime) * startY) + - ((3 * tprime * tprime * t) * cpY1) + - ((3 * tprime * t * t) * cpY2) + - (t * t * t * endY); - if (extremaY < bounds[1]) { - bounds[1] = extremaY; - } - if (extremaY > bounds[3]) { - bounds[3] = extremaY; - } - } - } else { - s = sqrt(s); - final double t = (-b - s) / (2 * a); - final double tprime = 1.0 - t; - if ((t >= 0.0) && (t <= 1.0)) { - extremaY = ((tprime * tprime * tprime) * startY) + - ((3 * tprime * tprime * t) * cpY1) + - ((3 * tprime * t * t) * cpY2) + - (t * t * t * endY); - if (extremaY < bounds[1]) { - bounds[1] = extremaY; - } - if (extremaY > bounds[3]) { - bounds[3] = extremaY; - } - } - final double t2 = (-b + s) / (2 * a); - final double tprime2 = 1.0 - t2; - if ((t2 >= 0.0) && (t2 <= 1.0)) { - extremaY = ((tprime2 * tprime2 * tprime2) * startY) + - ((3 * tprime2 * tprime2 * t2) * cpY1) + - ((3 * tprime2 * t2 * t2) * cpY2) + - (t2 * t2 * t2 * endY); - if (extremaY < bounds[1]) { - bounds[1] = extremaY; - } - if (extremaY > bounds[3]) { - bounds[3] = extremaY; - } - } - } - } - } + _expandBoundsForAxis(bounds, 0, startX, cpX1, cpX2, endX); + _expandBoundsForAxis(bounds, 1, startY, cpY1, cpY2, endY); } } return bounds; } } + +void _expandBoundsToCubicPoint(AABB bounds, int component, double t, double a, + double b, double c, double d) { + if (t >= 0 && t <= 1) { + var ti = 1 - t; + double extremaY = ((ti * ti * ti) * a) + + ((3 * ti * ti * t) * b) + + ((3 * ti * t * t) * c) + + (t * t * t * d); + if (extremaY < bounds[component]) { + bounds[component] = extremaY; + } + if (extremaY > bounds[component + 2]) { + bounds[component + 2] = extremaY; + } + } +} + +void _expandBoundsForAxis(AABB bounds, int component, double start, double cp1, + double cp2, double end) { + if (!(((start < cp1) && (cp1 < cp2) && (cp2 < end)) || + ((start > cp1) && (cp1 > cp2) && (cp2 > end)))) { + var a = 3 * (cp1 - start); + var b = 3 * (cp2 - cp1); + var c = 3 * (end - cp2); + var d = a - 2 * b + c; + if (d != 0) { + var m1 = -sqrt(b * b - a * c); + var m2 = -a + b; + _expandBoundsToCubicPoint( + bounds, component, -(m1 + m2) / d, start, cp1, cp2, end); + _expandBoundsToCubicPoint( + bounds, component, -(-m1 + m2) / d, start, cp1, cp2, end); + } else if (b != c && d == 0) { + _expandBoundsToCubicPoint( + bounds, component, (2 * b - c) / (2 * (b - c)), start, cp1, cp2, end); + } + var d2a = 2 * (b - a); + var d2b = 2 * (c - b); + if (d2a != b) { + _expandBoundsToCubicPoint( + bounds, component, d2a / (d2a - d2b), start, cp1, cp2, end); + } + } +} diff --git a/lib/src/rive_core/shapes/render_cubic_vertex.dart b/lib/src/rive_core/shapes/render_cubic_vertex.dart index ca561a4..64451ed 100644 --- a/lib/src/rive_core/shapes/render_cubic_vertex.dart +++ b/lib/src/rive_core/shapes/render_cubic_vertex.dart @@ -1,18 +1,11 @@ -import 'dart:collection'; import 'package:rive/src/rive_core/math/vec2d.dart'; import 'package:rive/src/rive_core/shapes/cubic_vertex.dart'; -import 'package:rive/src/utilities/binary_buffer/binary_writer.dart'; class RenderCubicVertex extends CubicVertex { - @override - void changeNonNull() {} @override Vec2D inPoint; @override Vec2D outPoint; @override void onAddedDirty() {} - @override - void writeRuntimeProperties( - BinaryWriter writer, HashMap idLookup) {} } diff --git a/lib/src/rive_core/shapes/shape.dart b/lib/src/rive_core/shapes/shape.dart index 4abb181..9536f6c 100644 --- a/lib/src/rive_core/shapes/shape.dart +++ b/lib/src/rive_core/shapes/shape.dart @@ -1,5 +1,4 @@ import 'dart:ui'; -import 'package:rive/src/rive_core/bounds_delegate.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/aabb.dart'; @@ -34,17 +33,12 @@ class Shape extends ShapeBase with ShapePaintContainer { AABB _worldBounds; AABB _localBounds; - BoundsDelegate _delegate; @override AABB get worldBounds => _worldBounds ??= computeWorldBounds(); @override AABB get localBounds => _localBounds ??= computeLocalBounds(); void markBoundsDirty() { _worldBounds = _localBounds = null; - _delegate?.boundsChanged(); - for (final path in paths) { - path.markBoundsDirty(); - } } @override @@ -202,15 +196,6 @@ class Shape extends ShapeBase with ShapePaintContainer { return localBounds; } - @override - void userDataChanged(dynamic from, dynamic to) { - if (to is BoundsDelegate) { - _delegate = to; - } else { - _delegate = null; - } - } - @override void blendModeValueChanged(int from, int to) => _markBlendModeDirty(); @override diff --git a/lib/src/rive_file.dart b/lib/src/rive_file.dart index 68171cf..871d51b 100644 --- a/lib/src/rive_file.dart +++ b/lib/src/rive_file.dart @@ -97,10 +97,10 @@ class RiveFile { continue; } else if (keyframe is KeyFrameDrawOrder) { int numValues = reader.readVarUint(); - for (int i = 0; i < numValues; i++) { + for (int m = 0; m < numValues; m++) { var valueObject = KeyFrameDrawOrderValue(); - valueObject.drawableId = reader.readVarInt(); - valueObject.value = i; + valueObject.drawableId = reader.readVarUint(); + valueObject.value = m; keyframe.internalAddValue(valueObject); } } @@ -153,30 +153,15 @@ T readRuntimeObject>(BinaryReader reader, // Terminator. https://media.giphy.com/media/7TtvTUMm9mp20/giphy.gif break; } - int propertyLength = reader.readVarUint(); - Uint8List valueBytes = reader.read(propertyLength); var fieldType = RiveCoreContext.coreType(propertyKey); if (fieldType == null) { - // This is considered an acceptable failure. A runtime may not support - // the same properties that were exported. The older object could still - // function without them, however, so it's up to the implementation to - // make sure that major versions are revved when breaking properties are - // added. Note that we intentionally first read the entire value bytes - // for the property so we can advance as expected even if we are - // skipping this value. - continue; + throw UnsupportedError('Unsupported property key $propertyKey. ' + 'A new runtime is likely necessary to play this file.'); } - // We know what to expect, let's try to read the value. We instance a new - // reader here so that we don't overflow the exact length we're allowed to - // read. - var valueReader = BinaryReader.fromList(valueBytes); - - // This will attempt to set the object property, but failure here is - // acceptable. RiveCoreContext.setObjectProperty( - object, propertyKey, fieldType.deserialize(valueReader)); + object, propertyKey, fieldType.deserialize(reader)); } return object as T; } diff --git a/lib/src/utilities/binary_buffer/binary_reader.dart b/lib/src/utilities/binary_buffer/binary_reader.dart index eb529b1..b5b85e7 100644 --- a/lib/src/utilities/binary_buffer/binary_reader.dart +++ b/lib/src/utilities/binary_buffer/binary_reader.dart @@ -7,6 +7,7 @@ class BinaryReader { final ByteData buffer; final Endian endian; int _readIndex = 0; + int get position => _readIndex; BinaryReader(this.buffer, {this.endian = Endian.little}); @@ -115,8 +116,8 @@ class BinaryReader { /// Read a string encoded into the stream. Strings are encoded with a varuint /// integer length written first followed by length number of utf8 encoded /// bytes. - String readString() { - int length = readVarUint(); + String readString({bool explicitLength = true}) { + int length = explicitLength ? readVarUint() : buffer.lengthInBytes; String value = _utf8Decoder.convert(Uint8List.view( buffer.buffer, buffer.offsetInBytes + _readIndex, length)); _readIndex += length; diff --git a/lib/src/utilities/binary_buffer/binary_writer.dart b/lib/src/utilities/binary_buffer/binary_writer.dart index 5c9a4af..1ef1ae7 100644 --- a/lib/src/utilities/binary_buffer/binary_writer.dart +++ b/lib/src/utilities/binary_buffer/binary_writer.dart @@ -151,9 +151,11 @@ class BinaryWriter { /// Encode a string into the buffer. Strings are encoded with a varuint /// integer length written first followed by length number of utf8 encoded /// bytes. - void writeString(String value) { + void writeString(String value, {bool explicitLength = true}) { var list = _utf8Encoder.convert(value); - writeVarUint(list.length); + if (explicitLength) { + writeVarUint(list.length); + } write(list); } diff --git a/pubspec.lock b/pubspec.lock index 6d15d4e..b7a035f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -21,7 +21,7 @@ packages: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.0.0" + version: "1.1.0-nullsafety" charcode: dependency: transitive description: @@ -42,7 +42,7 @@ packages: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.14.13" + version: "1.15.0-nullsafety" fake_async: dependency: transitive description: @@ -80,7 +80,7 @@ packages: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.1.8" + version: "1.3.0-nullsafety" path: dependency: transitive description: @@ -141,13 +141,13 @@ packages: name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.3.0-nullsafety" vector_math: dependency: transitive description: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.0.8" + version: "2.1.0-nullsafety" sdks: - dart: ">=2.9.0-14.0.dev <3.0.0" + dart: ">=2.9.0-18.0 <2.9.0" diff --git a/pubspec.yaml b/pubspec.yaml index daf701a..dd775f9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,8 @@ name: rive description: Rive 2 Flutter Runtime -version: 0.0.1+2 +version: 0.0.4 repository: https://github.com/rive-app/rive-flutter +homepage: https://rive.app environment: sdk: ">=2.2.2 <3.0.0" @@ -15,5 +16,3 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - -flutter: \ No newline at end of file