From 3dbef04b8b3e1832055a4a2c6d092c2006d220eb Mon Sep 17 00:00:00 2001 From: bodymovin Date: Fri, 9 Aug 2024 22:15:53 +0000 Subject: [PATCH] update flutter objects Diffs= e0816fdfa update flutter objects (#7797) 8c7ac0329 added a blt command for render targets that do not support VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT (#7757) 66d9f1725 Better premake support for Visual Studio (#7779) f0da6a7a0 Add Xcode support to build_rive.sh (#7780) c12b0bb24 Added support for xcode builds (#7774) Co-authored-by: hernan --- .rive_head | 2 +- .../listener_viewmodel_change_base.dart | 14 ++ .../converters/data_converter_base.dart | 45 +++++ .../generated/data_bind/data_bind_base.dart | 26 +++ lib/src/generated/rive_core_context.dart | 30 ++++ .../animation/listener_viewmodel_change.dart | 11 ++ .../animation/state_machine_listener.dart | 4 +- lib/src/rive_core/data_bind/data_bind.dart | 4 +- .../rive_core/state_machine_controller.dart | 162 ++++++++++++++---- 9 files changed, 263 insertions(+), 35 deletions(-) create mode 100644 lib/src/generated/animation/listener_viewmodel_change_base.dart create mode 100644 lib/src/generated/data_bind/converters/data_converter_base.dart create mode 100644 lib/src/rive_core/animation/listener_viewmodel_change.dart diff --git a/.rive_head b/.rive_head index eb57b2c0..ef57cefa 100644 --- a/.rive_head +++ b/.rive_head @@ -1 +1 @@ -0dc0b435ffb0df61de0afcdc2cea0c69bb8fedd4 +e0816fdfa0adde292f343b4a018b2f515a8bc1c4 diff --git a/lib/src/generated/animation/listener_viewmodel_change_base.dart b/lib/src/generated/animation/listener_viewmodel_change_base.dart new file mode 100644 index 00000000..79cc0257 --- /dev/null +++ b/lib/src/generated/animation/listener_viewmodel_change_base.dart @@ -0,0 +1,14 @@ +// Core automatically generated +// lib/src/generated/animation/listener_viewmodel_change_base.dart. +// Do not modify manually. + +import 'package:rive/src/rive_core/animation/listener_action.dart'; + +abstract class ListenerViewModelChangeBase extends ListenerAction { + static const int typeKey = 487; + @override + int get coreType => ListenerViewModelChangeBase.typeKey; + @override + Set get coreTypes => + {ListenerViewModelChangeBase.typeKey, ListenerActionBase.typeKey}; +} diff --git a/lib/src/generated/data_bind/converters/data_converter_base.dart b/lib/src/generated/data_bind/converters/data_converter_base.dart new file mode 100644 index 00000000..2c5624fe --- /dev/null +++ b/lib/src/generated/data_bind/converters/data_converter_base.dart @@ -0,0 +1,45 @@ +// Core automatically generated +// lib/src/generated/data_bind/converters/data_converter_base.dart. +// Do not modify manually. + +import 'package:rive/src/core/core.dart'; + +abstract class DataConverterBase extends Core { + static const int typeKey = 488; + @override + int get coreType => DataConverterBase.typeKey; + @override + Set get coreTypes => {DataConverterBase.typeKey}; + + /// -------------------------------------------------------------------------- + /// Name field with key 662. + static const int namePropertyKey = 662; + static const String nameInitialValue = ''; + String _name = nameInitialValue; + + /// Non-unique identifier, used to give friendly names to data converters. + 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); + + @override + void copy(Core source) { + super.copy(source); + if (source is DataConverterBase) { + _name = source._name; + } + } +} diff --git a/lib/src/generated/data_bind/data_bind_base.dart b/lib/src/generated/data_bind/data_bind_base.dart index 152641e5..221ca9dc 100644 --- a/lib/src/generated/data_bind/data_bind_base.dart +++ b/lib/src/generated/data_bind/data_bind_base.dart @@ -58,12 +58,38 @@ abstract class DataBindBase extends Core { void flagsChanged(int from, int to); + /// -------------------------------------------------------------------------- + /// ConverterId field with key 660. + static const int converterIdPropertyKey = 660; + static const int converterIdInitialValue = -1; + int _converterId = converterIdInitialValue; + + /// Identifier used to link to a data converter. + int get converterId => _converterId; + + /// Change the [_converterId] field value. + /// [converterIdChanged] will be invoked only if the field's value has + /// changed. + set converterId(int value) { + if (_converterId == value) { + return; + } + int from = _converterId; + _converterId = value; + if (hasValidated) { + converterIdChanged(from, value); + } + } + + void converterIdChanged(int from, int to); + @override void copy(Core source) { super.copy(source); if (source is DataBindBase) { _propertyKey = source._propertyKey; _flags = source._flags; + _converterId = source._converterId; } } } diff --git a/lib/src/generated/rive_core_context.dart b/lib/src/generated/rive_core_context.dart index c0bd5aea..00681cc8 100644 --- a/lib/src/generated/rive_core_context.dart +++ b/lib/src/generated/rive_core_context.dart @@ -30,6 +30,7 @@ import 'package:rive/src/generated/constraints/targeted_constraint_base.dart'; import 'package:rive/src/generated/constraints/transform_component_constraint_base.dart'; import 'package:rive/src/generated/constraints/transform_component_constraint_y_base.dart'; import 'package:rive/src/generated/constraints/transform_space_constraint_base.dart'; +import 'package:rive/src/generated/data_bind/converters/data_converter_base.dart'; import 'package:rive/src/generated/drawable_base.dart'; import 'package:rive/src/generated/nested_animation_base.dart'; import 'package:rive/src/generated/shapes/paint/shape_paint_base.dart'; @@ -68,6 +69,7 @@ import 'package:rive/src/rive_core/animation/listener_bool_change.dart'; import 'package:rive/src/rive_core/animation/listener_fire_event.dart'; import 'package:rive/src/rive_core/animation/listener_number_change.dart'; import 'package:rive/src/rive_core/animation/listener_trigger_change.dart'; +import 'package:rive/src/rive_core/animation/listener_viewmodel_change.dart'; import 'package:rive/src/rive_core/animation/nested_bool.dart'; import 'package:rive/src/rive_core/animation/nested_number.dart'; import 'package:rive/src/rive_core/animation/nested_remap_animation.dart'; @@ -336,6 +338,8 @@ class RiveCoreContext { return ListenerTriggerChange(); case BlendStateDirectBase.typeKey: return BlendStateDirect(); + case ListenerViewModelChangeBase.typeKey: + return ListenerViewModelChange(); case TransitionValueNumberComparatorBase.typeKey: return TransitionValueNumberComparator(); case NestedStateMachineBase.typeKey: @@ -1994,6 +1998,16 @@ class RiveCoreContext { object.flags = value; } break; + case DataBindBase.converterIdPropertyKey: + if (object is DataBindBase && value is int) { + object.converterId = value; + } + break; + case DataConverterBase.namePropertyKey: + if (object is DataConverterBase && value is String) { + object.name = value; + } + break; case DataBindContextBase.sourcePathIdsPropertyKey: if (object is DataBindContextBase && value is Uint8List) { object.sourcePathIds = value; @@ -2532,6 +2546,7 @@ class RiveCoreContext { case OpenUrlEventBase.targetValuePropertyKey: case DataBindBase.propertyKeyPropertyKey: case DataBindBase.flagsPropertyKey: + case DataBindBase.converterIdPropertyKey: case BindablePropertyEnumBase.propertyValuePropertyKey: case TendonBase.boneIdPropertyKey: case TextModifierRangeBase.unitsValuePropertyKey: @@ -2569,6 +2584,7 @@ class RiveCoreContext { case KeyFrameStringBase.valuePropertyKey: case TransitionValueStringComparatorBase.valuePropertyKey: case OpenUrlEventBase.urlPropertyKey: + case DataConverterBase.namePropertyKey: case BindablePropertyStringBase.propertyValuePropertyKey: case TextValueRunBase.textPropertyKey: case CustomPropertyStringBase.propertyValuePropertyKey: @@ -3101,6 +3117,8 @@ class RiveCoreContext { return (object as DataBindBase).propertyKey; case DataBindBase.flagsPropertyKey: return (object as DataBindBase).flags; + case DataBindBase.converterIdPropertyKey: + return (object as DataBindBase).converterId; case BindablePropertyEnumBase.propertyValuePropertyKey: return (object as BindablePropertyEnumBase).propertyValue; case TendonBase.boneIdPropertyKey: @@ -3183,6 +3201,8 @@ class RiveCoreContext { return (object as TransitionValueStringComparatorBase).value; case OpenUrlEventBase.urlPropertyKey: return (object as OpenUrlEventBase).url; + case DataConverterBase.namePropertyKey: + return (object as DataConverterBase).name; case BindablePropertyStringBase.propertyValuePropertyKey: return (object as BindablePropertyStringBase).propertyValue; case TextValueRunBase.textPropertyKey: @@ -4377,6 +4397,11 @@ class RiveCoreContext { object.flags = value; } break; + case DataBindBase.converterIdPropertyKey: + if (object is DataBindBase) { + object.converterId = value; + } + break; case BindablePropertyEnumBase.propertyValuePropertyKey: if (object is BindablePropertyEnumBase) { object.propertyValue = value; @@ -4562,6 +4587,11 @@ class RiveCoreContext { object.url = value; } break; + case DataConverterBase.namePropertyKey: + if (object is DataConverterBase) { + object.name = value; + } + break; case BindablePropertyStringBase.propertyValuePropertyKey: if (object is BindablePropertyStringBase) { object.propertyValue = value; diff --git a/lib/src/rive_core/animation/listener_viewmodel_change.dart b/lib/src/rive_core/animation/listener_viewmodel_change.dart new file mode 100644 index 00000000..023b9211 --- /dev/null +++ b/lib/src/rive_core/animation/listener_viewmodel_change.dart @@ -0,0 +1,11 @@ +import 'package:rive/src/generated/animation/listener_viewmodel_change_base.dart'; +import 'package:rive/src/rive_core/state_machine_controller.dart'; +import 'package:rive_common/math.dart'; + +export 'package:rive/src/generated/animation/listener_viewmodel_change_base.dart'; + +class ListenerViewModelChange extends ListenerViewModelChangeBase { + @override + void perform(StateMachineController controller, Vec2D position, + Vec2D previousPosition) {} +} diff --git a/lib/src/rive_core/animation/state_machine_listener.dart b/lib/src/rive_core/animation/state_machine_listener.dart index 036a6e3b..b557f459 100644 --- a/lib/src/rive_core/animation/state_machine_listener.dart +++ b/lib/src/rive_core/animation/state_machine_listener.dart @@ -12,7 +12,9 @@ import 'package:rive_common/math.dart'; export 'package:rive/src/generated/animation/state_machine_listener_base.dart'; -enum ListenerType { enter, exit, down, up, move, event } +enum ListenerType { enter, exit, down, up, move, event, click } + +enum GestureClickPhase { out, down, clicked } class StateMachineListener extends StateMachineListenerBase { final ListenerActions actions = ListenerActions(); diff --git a/lib/src/rive_core/data_bind/data_bind.dart b/lib/src/rive_core/data_bind/data_bind.dart index 9d76260a..126dbf5a 100644 --- a/lib/src/rive_core/data_bind/data_bind.dart +++ b/lib/src/rive_core/data_bind/data_bind.dart @@ -49,11 +49,13 @@ class DataBind extends DataBindBase { } @override - // ignore: override_on_non_overriding_member void targetIdChanged(int from, int to) { // TODO: @hernan implement nameChanged } + @override + void converterIdChanged(int from, int to) {} + @override void flagsChanged(int from, int to) {} diff --git a/lib/src/rive_core/state_machine_controller.dart b/lib/src/rive_core/state_machine_controller.dart index 5212e4f5..f6d84e7e 100644 --- a/lib/src/rive_core/state_machine_controller.dart +++ b/lib/src/rive_core/state_machine_controller.dart @@ -447,6 +447,7 @@ class StateMachineController extends RiveAnimationController }); late List<_HitComponent> hitComponents = []; + final List<_ListenerGroup> listenerGroups = []; Artboard? _artboard; @@ -484,6 +485,8 @@ class StateMachineController extends RiveAnimationController if (node == null) { continue; } + _ListenerGroup listenerGroup = _ListenerGroup(event); + listenerGroups.add(listenerGroup); node.forAll((component) { if (component is Shape) { @@ -491,7 +494,7 @@ class StateMachineController extends RiveAnimationController if (hitShape == null) { hitShapeLookup[component] = hitShape = _HitShape(component, this); } - hitShape.addEvent(event); + hitShape.addListener(listenerGroup); } // Keep iterating so we find all shapes. return true; @@ -653,6 +656,12 @@ class StateMachineController extends RiveAnimationController ); } + for (final listenerGroup in listenerGroups) { + listenerGroup.reset(); + } + for (final hitComponent in hitComponents) { + hitComponent.prepareEvent(position, hitEvent); + } bool hitSomething = false; bool hitOpaque = false; HitResult hitResult = HitResult.none; @@ -755,6 +764,45 @@ enum HitResult { hitOpaque, } +class _ListenerGroup { + final StateMachineListener listener; + bool _isConsumed = false; + bool _isHovered = false; + bool _prevIsHovered = false; + GestureClickPhase clickPhase = GestureClickPhase.out; + final Vec2D previousPosition = Vec2D(); + + _ListenerGroup(this.listener); + void consume() { + _isConsumed = true; + } + + void hover() { + _isHovered = true; + } + + void reset() { + _isConsumed = false; + _prevIsHovered = _isHovered; + _isHovered = false; + if (clickPhase == GestureClickPhase.clicked) { + clickPhase = GestureClickPhase.out; + } + } + + bool isConsumed() { + return _isConsumed; + } + + bool isHovered() { + return _isHovered; + } + + bool prevHovered() { + return _prevIsHovered; + } +} + class _HitComponent { final Component component; final StateMachineController controller; @@ -767,6 +815,8 @@ class _HitComponent { return HitResult.none; } + void prepareEvent(Vec2D position, ListenerType? hitType) {} + bool hitTest(Vec2D position) { return false; } @@ -784,8 +834,7 @@ class _HitShape extends _HitComponent { bool canEarlyOut = true; bool hasDownListener = false; bool hasUpListener = false; - final Vec2D previousPosition = Vec2D(); - List events = []; + List<_ListenerGroup> listenerGroups = []; _HitShape(this.shape, StateMachineController controller) : super(shape, controller) { @@ -813,6 +862,23 @@ class _HitShape extends _HitComponent { return false; } + @override + void prepareEvent(Vec2D position, ListenerType? hitType) { + if (canEarlyOut && + (hitType != ListenerType.down || !hasDownListener) && + (hitType != ListenerType.up || !hasUpListener)) { + return; + } + isHovered = hitTest(position); + + // iterate all listeners associated with this hit shape + if (isHovered) { + for (final listenerGroup in listenerGroups) { + listenerGroup.hover(); + } + } + } + @override HitResult processEvent( Vec2D position, { @@ -825,59 +891,91 @@ class _HitShape extends _HitComponent { (hitEvent != ListenerType.up || !hasUpListener)) { return HitResult.none; } + var shape = component as Shape; - var isOver = false; - if (canHit) { - isOver = hitTest(position); - } - bool hoverChange = isHovered != isOver; - isHovered = isOver; - if (hoverChange && isHovered) { - previousPosition.x = position.x; - previousPosition.y = position.y; - } // iterate all events associated with this hit shape - for (final event in events) { + for (final listenerGroup in listenerGroups) { + if (listenerGroup.isConsumed()) { + continue; + } + final isGroupHovered = canHit && listenerGroup.isHovered(); + bool hoverChange = listenerGroup.prevHovered() != isGroupHovered; + // If hover has changes, it means that the element is hovered for the + // first time. Previous positions need to be reset to avoid jumps. + if (hoverChange && isGroupHovered) { + listenerGroup.previousPosition.x = position.x; + listenerGroup.previousPosition.y = position.y; + } + // Handle click gesture phases. A click gesture has two phases. + // First one attached to a pointer down actions, second one attached to a + // pointer up action. Both need to act on a shape of the listener group. + if (isGroupHovered) { + if (hitEvent == ListenerType.down) { + listenerGroup.clickPhase = GestureClickPhase.down; + } else if (hitEvent == ListenerType.up && + listenerGroup.clickPhase == GestureClickPhase.down) { + listenerGroup.clickPhase = GestureClickPhase.clicked; + } + } else { + if (hitEvent == ListenerType.down || hitEvent == ListenerType.up) { + listenerGroup.clickPhase = GestureClickPhase.out; + } + } // Always update hover states regardless of which specific event type // we're trying to trigger. - if (hoverChange) { - if (isOver && event.listenerType == ListenerType.enter) { - event.performChanges(controller, position, previousPosition); - controller.isActive = true; - } else if (!isOver && event.listenerType == ListenerType.exit) { - event.performChanges(controller, position, previousPosition); - controller.isActive = true; - } + // If hover has changed and: + // - it's hovering and the listener is of type enter + // - it's not hovering and the listener is of type exit + final listener = listenerGroup.listener; + if (hoverChange && + ((isGroupHovered && listener.listenerType == ListenerType.enter) || + (!isGroupHovered && + listener.listenerType == ListenerType.exit))) { + listener.performChanges( + controller, position, listenerGroup.previousPosition); + controller.isActive = true; + listenerGroup.consume(); } - if (isOver && hitEvent == event.listenerType) { - event.performChanges(controller, position, previousPosition); + // Perform changes if: + // - the click gesture is complete and the listener is of type click + // - the event type matches the listener type and it is hovering the group + if ((listenerGroup.clickPhase == GestureClickPhase.clicked && + listener.listenerType == ListenerType.click) || + (isGroupHovered && hitEvent == listener.listenerType)) { + listener.performChanges( + controller, position, listenerGroup.previousPosition); controller.isActive = true; + listenerGroup.consume(); } + listenerGroup.previousPosition.x = position.x; + listenerGroup.previousPosition.y = position.y; } - previousPosition.x = position.x; - previousPosition.y = position.y; - return isOver + return isHovered && canHit ? shape.isTargetOpaque ? HitResult.hitOpaque : HitResult.hit : HitResult.none; } - void addEvent(StateMachineListener event) { - final listenerType = event.listenerType; + void addListener(_ListenerGroup listenerGroup) { + final listener = listenerGroup.listener; + final listenerType = listener.listenerType; if (listenerType == ListenerType.enter || listenerType == ListenerType.exit || listenerType == ListenerType.move) { canEarlyOut = false; } else { - if (listenerType == ListenerType.down) { + if (listenerType == ListenerType.down || + listenerType == ListenerType.click) { hasDownListener = true; - } else if (listenerType == ListenerType.up) { + } + if (listenerType == ListenerType.up || + listenerType == ListenerType.click) { hasUpListener = true; } } - events.add(event); + listenerGroups.add(listenerGroup); } }