Joysticks & Slider!

Diffs=
7acff50d4 Joysticks & Slider! (#5249)
e65175b88 Fix flickering caught in high level runtimes. (#5243)
This commit is contained in:
luigi-rosso
2023-05-16 04:44:51 +00:00
parent 6dd6778410
commit 0d010f0191
12 changed files with 362 additions and 35 deletions

View File

@ -1 +1 @@
d0bca2e728b34f658661231469c9e9fb926b8169
7acff50d4632d9e88b1474d6f23b3b1c8d7f7334

View File

@ -1,3 +1,8 @@
## 0.11.0
- Joysticks!
- Bumping to latest rive_common with some changes to AABB math api.
## 0.10.4
- Support for Solos.

BIN
example/assets/coyote.riv Normal file

Binary file not shown.

View File

@ -5,16 +5,22 @@ import 'package:rive/rive.dart';
class SimpleAssetAnimation extends StatelessWidget {
const SimpleAssetAnimation({Key? key}) : super(key: key);
void _onRiveInit(Artboard artboard) {
final controller = StateMachineController.fromArtboard(artboard, 'Coyote');
artboard.addController(controller!);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Simple Animation'),
),
body: const Center(
body: Center(
child: RiveAnimation.asset(
'assets/off_road_car.riv',
'assets/coyote.riv',
fit: BoxFit.cover,
onInit: _onRiveInit,
),
),
);

View File

@ -0,0 +1,115 @@
/// Core automatically generated lib/src/generated/joystick_base.dart.
/// Do not modify manually.
import 'package:rive/src/rive_core/component.dart';
abstract class JoystickBase extends Component {
static const int typeKey = 148;
@override
int get coreType => JoystickBase.typeKey;
@override
Set<int> get coreTypes => {JoystickBase.typeKey, ComponentBase.typeKey};
/// --------------------------------------------------------------------------
/// X field with key 299.
static const double xInitialValue = 0;
double _x = xInitialValue;
static const int xPropertyKey = 299;
double get x => _x;
/// Change the [_x] field value.
/// [xChanged] will be invoked only if the field's value has changed.
set x(double value) {
if (_x == value) {
return;
}
double from = _x;
_x = value;
if (hasValidated) {
xChanged(from, value);
}
}
void xChanged(double from, double to);
/// --------------------------------------------------------------------------
/// Y field with key 300.
static const double yInitialValue = 0;
double _y = yInitialValue;
static const int yPropertyKey = 300;
double get y => _y;
/// Change the [_y] field value.
/// [yChanged] will be invoked only if the field's value has changed.
set y(double value) {
if (_y == value) {
return;
}
double from = _y;
_y = value;
if (hasValidated) {
yChanged(from, value);
}
}
void yChanged(double from, double to);
/// --------------------------------------------------------------------------
/// XId field with key 301.
static const int xIdInitialValue = -1;
int _xId = xIdInitialValue;
static const int xIdPropertyKey = 301;
/// Identifier used to track the animation used for the x axis of the
/// joystick.
int get xId => _xId;
/// Change the [_xId] field value.
/// [xIdChanged] will be invoked only if the field's value has changed.
set xId(int value) {
if (_xId == value) {
return;
}
int from = _xId;
_xId = value;
if (hasValidated) {
xIdChanged(from, value);
}
}
void xIdChanged(int from, int to);
/// --------------------------------------------------------------------------
/// YId field with key 302.
static const int yIdInitialValue = -1;
int _yId = yIdInitialValue;
static const int yIdPropertyKey = 302;
/// Identifier used to track the animation used for the y axis of the
/// joystick.
int get yId => _yId;
/// Change the [_yId] field value.
/// [yIdChanged] will be invoked only if the field's value has changed.
set yId(int value) {
if (_yId == value) {
return;
}
int from = _yId;
_yId = value;
if (hasValidated) {
yIdChanged(from, value);
}
}
void yIdChanged(int from, int to);
@override
void copy(covariant JoystickBase source) {
super.copy(source);
_x = source._x;
_y = source._y;
_xId = source._xId;
_yId = source._yId;
}
}

View File

@ -98,6 +98,7 @@ import 'package:rive/src/rive_core/custom_property_number.dart';
import 'package:rive/src/rive_core/custom_property_string.dart';
import 'package:rive/src/rive_core/draw_rules.dart';
import 'package:rive/src/rive_core/draw_target.dart';
import 'package:rive/src/rive_core/joystick.dart';
import 'package:rive/src/rive_core/nested_artboard.dart';
import 'package:rive/src/rive_core/node.dart';
import 'package:rive/src/rive_core/shapes/clipping_shape.dart';
@ -291,6 +292,8 @@ class RiveCoreContext {
return CustomPropertyBoolean();
case ArtboardBase.typeKey:
return Artboard();
case JoystickBase.typeKey:
return Joystick();
case BackboardBase.typeKey:
return Backboard();
case BoneBase.typeKey:
@ -1121,6 +1124,26 @@ class RiveCoreContext {
object.defaultStateMachineId = value;
}
break;
case JoystickBase.xPropertyKey:
if (object is JoystickBase && value is double) {
object.x = value;
}
break;
case JoystickBase.yPropertyKey:
if (object is JoystickBase && value is double) {
object.y = value;
}
break;
case JoystickBase.xIdPropertyKey:
if (object is JoystickBase && value is int) {
object.xId = value;
}
break;
case JoystickBase.yIdPropertyKey:
if (object is JoystickBase && value is int) {
object.yId = value;
}
break;
case BoneBase.lengthPropertyKey:
if (object is BoneBase && value is double) {
object.length = value;
@ -1365,6 +1388,8 @@ class RiveCoreContext {
case ImageBase.assetIdPropertyKey:
case DrawRulesBase.drawTargetIdPropertyKey:
case ArtboardBase.defaultStateMachineIdPropertyKey:
case JoystickBase.xIdPropertyKey:
case JoystickBase.yIdPropertyKey:
case TendonBase.boneIdPropertyKey:
case TextStyleBase.fontAssetIdPropertyKey:
case TextStyleAxisBase.tagPropertyKey:
@ -1445,6 +1470,8 @@ class RiveCoreContext {
case ArtboardBase.yPropertyKey:
case ArtboardBase.originXPropertyKey:
case ArtboardBase.originYPropertyKey:
case JoystickBase.xPropertyKey:
case JoystickBase.yPropertyKey:
case BoneBase.lengthPropertyKey:
case RootBoneBase.xPropertyKey:
case RootBoneBase.yPropertyKey:
@ -1642,6 +1669,10 @@ class RiveCoreContext {
return (object as DrawRulesBase).drawTargetId;
case ArtboardBase.defaultStateMachineIdPropertyKey:
return (object as ArtboardBase).defaultStateMachineId;
case JoystickBase.xIdPropertyKey:
return (object as JoystickBase).xId;
case JoystickBase.yIdPropertyKey:
return (object as JoystickBase).yId;
case TendonBase.boneIdPropertyKey:
return (object as TendonBase).boneId;
case TextStyleBase.fontAssetIdPropertyKey:
@ -1806,6 +1837,10 @@ class RiveCoreContext {
return (object as ArtboardBase).originX;
case ArtboardBase.originYPropertyKey:
return (object as ArtboardBase).originY;
case JoystickBase.xPropertyKey:
return (object as JoystickBase).x;
case JoystickBase.yPropertyKey:
return (object as JoystickBase).y;
case BoneBase.lengthPropertyKey:
return (object as BoneBase).length;
case RootBoneBase.xPropertyKey:
@ -2262,6 +2297,16 @@ class RiveCoreContext {
object.defaultStateMachineId = value;
}
break;
case JoystickBase.xIdPropertyKey:
if (object is JoystickBase) {
object.xId = value;
}
break;
case JoystickBase.yIdPropertyKey:
if (object is JoystickBase) {
object.yId = value;
}
break;
case TendonBase.boneIdPropertyKey:
if (object is TendonBase) {
object.boneId = value;
@ -2662,6 +2707,16 @@ class RiveCoreContext {
object.originY = value;
}
break;
case JoystickBase.xPropertyKey:
if (object is JoystickBase) {
object.x = value;
}
break;
case JoystickBase.yPropertyKey:
if (object is JoystickBase) {
object.y = value;
}
break;
case BoneBase.lengthPropertyKey:
if (object is BoneBase) {
object.length = value;

View File

@ -38,6 +38,22 @@ class LinearAnimation extends LinearAnimationBase {
return true;
}
bool isObjectKeyed(Core object) => _keyedObjects.containsKey(object.id);
bool removeObjectKeys(Core object) {
var value = _keyedObjects[object.id];
if (value == null) {
return false;
}
bool found = false;
for (final kp in value.keyedProperties) {
for (final kf in kp.keyframes.toList()) {
kf.remove();
found = true;
}
}
return found;
}
/// Returns the seconds where the animiation work area starts
double get startSeconds => (enableWorkArea ? workStart : 0).toDouble() / fps;

View File

@ -12,6 +12,7 @@ import 'package:rive/src/rive_core/draw_rules.dart';
import 'package:rive/src/rive_core/draw_target.dart';
import 'package:rive/src/rive_core/drawable.dart';
import 'package:rive/src/rive_core/event.dart';
import 'package:rive/src/rive_core/joystick.dart';
import 'package:rive/src/rive_core/nested_artboard.dart';
import 'package:rive/src/rive_core/rive_animation_controller.dart';
import 'package:rive/src/rive_core/shapes/paint/shape_paint_mutator.dart';
@ -161,6 +162,14 @@ class Artboard extends ArtboardBase with ShapePaintContainer {
final Set<NestedArtboard> _activeNestedArtboards = {};
Iterable<NestedArtboard> get activeNestedArtboards => _activeNestedArtboards;
final List<Joystick> _joysticks = [];
void applyJoysticks() {
for (final joystick in _joysticks) {
joystick.apply(context);
}
}
/// Update any dirty components in this artboard.
bool advance(double elapsedSeconds, {bool nested = false}) {
bool didUpdate = false;
@ -170,6 +179,7 @@ class Artboard extends ArtboardBase with ShapePaintContainer {
didUpdate = true;
}
}
applyJoysticks();
if (updateComponents() || didUpdate) {
didUpdate = true;
}
@ -274,8 +284,13 @@ class Artboard extends ArtboardBase with ShapePaintContainer {
if (!_components.add(component)) {
return;
}
if (component is NestedArtboard) {
_activeNestedArtboards.add(component);
switch (component.coreType) {
case NestedArtboardBase.typeKey:
_activeNestedArtboards.add(component as NestedArtboard);
break;
case JoystickBase.typeKey:
_joysticks.add(component as Joystick);
break;
}
}
@ -283,8 +298,13 @@ class Artboard extends ArtboardBase with ShapePaintContainer {
/// components.
void removeComponent(Component component) {
_components.remove(component);
if (component is NestedArtboard) {
_activeNestedArtboards.remove(component);
switch (component.coreType) {
case NestedArtboardBase.typeKey:
_activeNestedArtboards.remove(component as NestedArtboard);
break;
case JoystickBase.typeKey:
_joysticks.remove(component as Joystick);
break;
}
}

View File

@ -0,0 +1,89 @@
import 'package:rive/src/generated/joystick_base.dart';
import 'package:rive/src/rive_core/animation/linear_animation.dart';
import 'package:rive/src/rive_core/container_component.dart';
export 'package:rive/src/generated/joystick_base.dart';
class Joystick extends JoystickBase {
double get clampedX => x.clamp(-1, 1);
double get clampedY => y.clamp(-1, 1);
@override
void update(int dirt) {}
void apply(CoreContext context) {
var animation = _xAnimation;
if (animation != null) {
animation.apply(
(x + 1) / 2 * animation.durationSeconds,
coreContext: context,
);
}
animation = _yAnimation;
if (animation != null) {
animation.apply(
(y + 1) / 2 * animation.durationSeconds,
coreContext: context,
);
}
}
@override
void xChanged(double from, double to) {
context.markNeedsAdvance();
}
@override
void yChanged(double from, double to) {
context.markNeedsAdvance();
}
@override
void xIdChanged(int from, int to) {
xAnimation = xId == Core.missingId ? null : context.resolve(xId);
}
@override
void yIdChanged(int from, int to) {
yAnimation = yId == Core.missingId ? null : context.resolve(yId);
}
LinearAnimation? _xAnimation;
LinearAnimation? _yAnimation;
LinearAnimation? get xAnimation => _xAnimation;
LinearAnimation? get yAnimation => _yAnimation;
set xAnimation(LinearAnimation? value) {
if (_xAnimation == value) {
return;
}
_xAnimation = value;
}
set yAnimation(LinearAnimation? value) {
if (_yAnimation == value) {
return;
}
_yAnimation = value;
}
@override
void onAdded() {
super.onAdded();
if (xId >= 0 && xId < context.animations.length) {
var found = context.animations[xId];
if (found is LinearAnimation) {
xAnimation = found;
}
}
if (yId >= 0 && yId < context.animations.length) {
var found = context.animations[yId];
if (found is LinearAnimation) {
yAnimation = found;
}
}
}
}

View File

@ -13,6 +13,8 @@ import 'package:rive_common/math.dart';
export 'package:rive/src/generated/shapes/path_base.dart';
enum Axis { horizontal, vertical }
/// An abstract low level path that gets implemented by parametric and point
/// based paths.
abstract class Path extends PathBase {
@ -414,9 +416,21 @@ class RenderPath implements PathInterface {
point.apply(transform);
}
_expandBoundsForAxis(
bounds, 0, penPosition.x, outPoint.x, inPoint.x, point.x);
bounds,
Axis.horizontal,
penPosition.x,
outPoint.x,
inPoint.x,
point.x,
);
_expandBoundsForAxis(
bounds, 1, penPosition.y, outPoint.y, inPoint.y, point.y);
bounds,
Axis.vertical,
penPosition.y,
outPoint.y,
inPoint.y,
point.y,
);
penPosition = point;
break;
@ -429,38 +443,41 @@ class RenderPath implements PathInterface {
}
/// Expand our bounds to a point (in normalized T space) on the Cubic.
void _expandBoundsToCubicPoint(AABB bounds, int component, double t, double a,
double b, double c, double d) {
void _expandBoundsToCubicPoint(
AABB bounds, Axis axis, 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;
__expandBounds(bounds, axis, extremaY);
}
}
void __expandBounds(AABB bounds, Axis axis, double value) {
if (axis == Axis.horizontal) {
if (value < bounds.left) {
bounds.left = value;
}
if (extremaY > bounds[component + 2]) {
bounds[component + 2] = extremaY;
if (value > bounds.right) {
bounds.right = value;
}
} else {
if (value < bounds.top) {
bounds.top = value;
}
if (value > bounds.bottom) {
bounds.bottom = value;
}
}
}
void _expandBoundsForAxis(AABB bounds, int component, double start, double cp1,
double cp2, double end) {
void _expandBoundsForAxis(
AABB bounds, Axis axis, double start, double cp1, double cp2, double end) {
// Check start/end as cubic goes through those.
if (start < bounds[component]) {
bounds[component] = start;
}
if (start > bounds[component + 2]) {
bounds[component + 2] = start;
}
if (end < bounds[component]) {
bounds[component] = end;
}
if (end > bounds[component + 2]) {
bounds[component + 2] = end;
}
__expandBounds(bounds, axis, start);
__expandBounds(bounds, axis, end);
// Now check extremas.
// Find the first derivative
@ -476,12 +493,12 @@ void _expandBoundsForAxis(AABB bounds, int component, double start, double cp1,
// First root.
_expandBoundsToCubicPoint(
bounds, component, -(m1 + m2) / d, start, cp1, cp2, end);
bounds, axis, -(m1 + m2) / d, start, cp1, cp2, end);
_expandBoundsToCubicPoint(
bounds, component, -(-m1 + m2) / d, start, cp1, cp2, end);
bounds, axis, -(-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);
bounds, axis, (2 * b - c) / (2 * (b - c)), start, cp1, cp2, end);
}
// Derive the first derivative to get the 2nd and use the root of
@ -490,7 +507,7 @@ void _expandBoundsForAxis(AABB bounds, int component, double start, double cp1,
var d2b = 2 * (c - b);
if (d2a != b) {
_expandBoundsToCubicPoint(
bounds, component, d2a / (d2a - d2b), start, cp1, cp2, end);
bounds, axis, d2a / (d2a - d2b), start, cp1, cp2, end);
}
}

View File

@ -51,9 +51,13 @@ abstract class TransformComponent extends TransformComponentBase {
Vec2D get worldTranslation =>
Vec2D.fromValues(worldTransform[4], worldTransform[5]);
@override
double get x;
@override
double get y;
@override
set x(double value);
@override
set y(double value);
@override

View File

@ -1,5 +1,5 @@
name: rive
version: 0.10.4
version: 0.11.0
homepage: https://rive.app
description: Rive 2 Flutter Runtime. This package provides runtime functionality for playing back and interacting with animations built with the Rive editor available at https://rive.app.
repository: https://github.com/rive-app/rive-flutter
@ -15,7 +15,7 @@ dependencies:
http: ^0.13.3
meta: ^1.3.0
plugin_platform_interface: ^2.0.2
rive_common: ^0.0.2
rive_common: ^0.0.6
dev_dependencies:
flutter_test:
sdk: flutter