diff --git a/.gitignore b/.gitignore index 2491f4c6..19b56216 100644 --- a/.gitignore +++ b/.gitignore @@ -90,3 +90,19 @@ shared_lib/dependencies shared_lib/bin *.make Makefile + +# https://dart.dev/guides/libraries/private-files + +.dart_tool/ +build/ + +doc/api/ + +# IntelliJ +*.iml +*.ipr +*.iws +.idea/ + +# Mac +.DS_Store \ No newline at end of file diff --git a/analysis_options.yaml b/analysis_options.yaml index 63fe01d8..05150c1e 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1,6 +1,7 @@ analyzer: errors: unused_import: error + prefer_is_empty: ignore exclude: - ios - macos @@ -51,7 +52,8 @@ linter: - join_return_with_assignment - library_names - library_prefixes - - lines_longer_than_80_chars + # STOKANAL-FORK-EDIT +# - lines_longer_than_80_chars # - literal_only_boolean_expressions # too many false positives: https://github.com/dart-lang/sdk/issues/34181 - no_adjacent_strings_in_list - no_duplicate_case_values @@ -76,7 +78,7 @@ linter: - prefer_contains - prefer_final_fields - prefer_final_in_for_each - - prefer_foreach +# - prefer_foreach - prefer_function_declarations_over_variables - prefer_initializing_formals - prefer_is_empty diff --git a/example/macos/Flutter/GeneratedPluginRegistrant.swift b/example/macos/Flutter/GeneratedPluginRegistrant.swift new file mode 100644 index 00000000..0aa3a062 --- /dev/null +++ b/example/macos/Flutter/GeneratedPluginRegistrant.swift @@ -0,0 +1,32 @@ +// +// Generated file. Do not edit. +// + +import FlutterMacOS +import Foundation + +import audio_session +import device_info_plus +import flutter_udid +import in_app_purchase_storekit +import just_audio +import package_info_plus +import path_provider_foundation +import rive_common +import shared_preferences_foundation +import url_launcher_macos +import wakelock_plus + +func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + AudioSessionPlugin.register(with: registry.registrar(forPlugin: "AudioSessionPlugin")) + DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) + FlutterUdidPlugin.register(with: registry.registrar(forPlugin: "FlutterUdidPlugin")) + InAppPurchasePlugin.register(with: registry.registrar(forPlugin: "InAppPurchasePlugin")) + JustAudioPlugin.register(with: registry.registrar(forPlugin: "JustAudioPlugin")) + FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) + PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) + RivePlugin.register(with: registry.registrar(forPlugin: "RivePlugin")) + SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) + UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) + WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin")) +} diff --git a/example/windows/flutter/generated_plugin_registrant.cc b/example/windows/flutter/generated_plugin_registrant.cc new file mode 100644 index 00000000..bd19e8f5 --- /dev/null +++ b/example/windows/flutter/generated_plugin_registrant.cc @@ -0,0 +1,20 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + +#include +#include +#include + +void RegisterPlugins(flutter::PluginRegistry* registry) { + FlutterUdidPluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FlutterUdidPluginCApi")); + RivePluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("RivePlugin")); + UrlLauncherWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("UrlLauncherWindows")); +} diff --git a/example/windows/flutter/generated_plugin_registrant.h b/example/windows/flutter/generated_plugin_registrant.h new file mode 100644 index 00000000..dc139d85 --- /dev/null +++ b/example/windows/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void RegisterPlugins(flutter::PluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/example/windows/flutter/generated_plugins.cmake b/example/windows/flutter/generated_plugins.cmake new file mode 100644 index 00000000..974401b2 --- /dev/null +++ b/example/windows/flutter/generated_plugins.cmake @@ -0,0 +1,26 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + flutter_udid + rive_common + url_launcher_windows +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/lib/src/controllers/linear_animation_controller.dart b/lib/src/controllers/linear_animation_controller.dart index f4c5f99b..f4675900 100644 --- a/lib/src/controllers/linear_animation_controller.dart +++ b/lib/src/controllers/linear_animation_controller.dart @@ -1,3 +1,5 @@ +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/linear_animation_instance.dart' @@ -10,7 +12,7 @@ export 'package:rive/src/runtime_mounted_artboard.dart'; /// the inputs of the StateMachine. class LinearAnimationInstance extends core.LinearAnimationInstance with RuntimeEventReporter, KeyedCallbackReporter { - final _runtimeEventListeners = {}; + final _runtimeEventListeners = HashSet(); // {}; late CoreContext? context; LinearAnimationInstance(animation, @@ -27,9 +29,12 @@ class LinearAnimationInstance extends core.LinearAnimationInstance @override void reportEvent(Event event) { - _runtimeEventListeners.toList().forEach((callback) { - callback(event); - }); + for (final t in _runtimeEventListeners) { + t(event); + } + // _runtimeEventListeners.toList().forEach((callback) { + // callback(event); + // }); } @override diff --git a/lib/src/controllers/state_machine_controller.dart b/lib/src/controllers/state_machine_controller.dart index 1448515b..1e9262d7 100644 --- a/lib/src/controllers/state_machine_controller.dart +++ b/lib/src/controllers/state_machine_controller.dart @@ -1,3 +1,5 @@ +import 'dart:collection'; + 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_bool.dart'; @@ -119,7 +121,7 @@ class StateMachineController extends core.StateMachineController /// A list of inputs available in the StateMachine. Iterable get inputs => _inputs; - final _runtimeEventListeners = {}; + final _runtimeEventListeners = HashSet();//{}; StateMachineController( StateMachine stateMachine, { @@ -224,8 +226,13 @@ class StateMachineController extends core.StateMachineController @override void applyEvents() { - var events = reportedEvents.toList(growable: false); + // var events = reportedEvents.toList(growable: false); super.applyEvents(); - _runtimeEventListeners.toList().forEach(events.forEach); + + // _runtimeEventListeners.toList().forEach(events.forEach); + for (final t in _runtimeEventListeners) { + reportedEvents.forEach(t); + } + // _runtimeEventListeners.toList().forEach(reportedEvents.forEach); } } diff --git a/lib/src/core/core.dart b/lib/src/core/core.dart index 1f0b8495..87443f98 100644 --- a/lib/src/core/core.dart +++ b/lib/src/core/core.dart @@ -93,7 +93,7 @@ abstract class CoreContext { // ignore: one_member_abstracts abstract class ImportStackObject { - final _resolveBefore = {}; + final _resolveBefore = HashSet();//{}; bool _resolved = false; bool initStack(ImportStack stack) { diff --git a/lib/src/core/field_types/core_field_type.dart b/lib/src/core/field_types/core_field_type.dart index 0caf2741..f966d6c5 100644 --- a/lib/src/core/field_types/core_field_type.dart +++ b/lib/src/core/field_types/core_field_type.dart @@ -4,4 +4,6 @@ import 'package:rive_common/utilities.dart'; abstract class CoreFieldType { T deserialize(BinaryReader reader); void skip(BinaryReader reader) => deserialize(reader); + + // const CoreFieldType(); } diff --git a/lib/src/core/importers/artboard_importer.dart b/lib/src/core/importers/artboard_importer.dart index 25d5de64..dd6df72f 100644 --- a/lib/src/core/importers/artboard_importer.dart +++ b/lib/src/core/importers/artboard_importer.dart @@ -31,7 +31,7 @@ class ArtboardImporter extends ImportStackObject { } assert(!artboard.children.contains(artboard), 'artboard should never contain itself as a child'); - for (final object in artboard.objects.toList(growable: false)) { + for (final object in artboard.objects) {//.toList(growable: false)) { if (object == null) { continue; } diff --git a/lib/src/core/importers/backboard_importer.dart b/lib/src/core/importers/backboard_importer.dart index f8eb0907..067eb539 100644 --- a/lib/src/core/importers/backboard_importer.dart +++ b/lib/src/core/importers/backboard_importer.dart @@ -11,9 +11,9 @@ class BackboardImporter extends ImportStackObject { final Backboard backboard; final HashMap artboardLookup; - final Set nestedArtboards = {}; + final Set nestedArtboards = HashSet();//{}; final List fileAssets = []; - final Set fileAssetReferencers = {}; + final Set fileAssetReferencers = HashSet();//{}; BackboardImporter(this.artboardLookup, this.backboard); void addArtboard(Artboard object) {} diff --git a/lib/src/generated/animation/keyed_object_base.dart b/lib/src/generated/animation/keyed_object_base.dart index 5c1e6498..e03789dc 100644 --- a/lib/src/generated/animation/keyed_object_base.dart +++ b/lib/src/generated/animation/keyed_object_base.dart @@ -6,6 +6,7 @@ import 'package:rive/src/core/core.dart'; abstract class KeyedObjectBase extends Core { static const int typeKey = 25; + @override int get coreType => KeyedObjectBase.typeKey; @override diff --git a/lib/src/generated/animation/keyed_property_base.dart b/lib/src/generated/animation/keyed_property_base.dart index 515dcf97..c0837be6 100644 --- a/lib/src/generated/animation/keyed_property_base.dart +++ b/lib/src/generated/animation/keyed_property_base.dart @@ -15,20 +15,22 @@ abstract class KeyedPropertyBase extends Core { /// PropertyKey field with key 53. static const int propertyKeyPropertyKey = 53; static const int propertyKeyInitialValue = CoreContext.invalidPropertyKey; - int _propertyKey = propertyKeyInitialValue; + + /// STOKANAL-FORK-EDIT: exposing + int propertyKey_ = propertyKeyInitialValue; /// The property type that is keyed. - int get propertyKey => _propertyKey; + int get propertyKey => propertyKey_; - /// Change the [_propertyKey] field value. + /// Change the [propertyKey_] field value. /// [propertyKeyChanged] will be invoked only if the field's value has /// changed. set propertyKey(int value) { - if (_propertyKey == value) { + if (propertyKey_ == value) { return; } - int from = _propertyKey; - _propertyKey = value; + int from = propertyKey_; + propertyKey_ = value; if (hasValidated) { propertyKeyChanged(from, value); } @@ -40,7 +42,7 @@ abstract class KeyedPropertyBase extends Core { void copy(Core source) { super.copy(source); if (source is KeyedPropertyBase) { - _propertyKey = source._propertyKey; + propertyKey_ = source.propertyKey_; } } } diff --git a/lib/src/generated/animation/keyframe_double_base.dart b/lib/src/generated/animation/keyframe_double_base.dart index 6f2eb19e..ddc42ad0 100644 --- a/lib/src/generated/animation/keyframe_double_base.dart +++ b/lib/src/generated/animation/keyframe_double_base.dart @@ -21,17 +21,20 @@ abstract class KeyFrameDoubleBase extends InterpolatingKeyFrame { /// Value field with key 70. static const int valuePropertyKey = 70; static const double valueInitialValue = 0; - double _value = valueInitialValue; - double get value => _value; - /// Change the [_value] field value. + /// STOKANAL-FORK-EDIT: exposing + double value_ = valueInitialValue; + + 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) { + if (value_ == value) { return; } - double from = _value; - _value = value; + double from = value_; + value_ = value; if (hasValidated) { valueChanged(from, value); } @@ -43,7 +46,7 @@ abstract class KeyFrameDoubleBase extends InterpolatingKeyFrame { void copy(Core source) { super.copy(source); if (source is KeyFrameDoubleBase) { - _value = source._value; + value_ = source.value_; } } } diff --git a/lib/src/generated/rive_core_context.dart b/lib/src/generated/rive_core_context.dart index ac4d68e8..41c353d7 100644 --- a/lib/src/generated/rive_core_context.dart +++ b/lib/src/generated/rive_core_context.dart @@ -190,7 +190,35 @@ import 'package:rive/src/rive_core/viewmodel/viewmodel_property_viewmodel.dart'; // ignore: avoid_classes_with_only_static_members class RiveCoreContext { + + // static final _counter = HashMap(); + + /// STOKANAL-FORK-EDIT static Core? makeCoreInstance(int typeKey) { + + switch (typeKey) { + case KeyFrameDoubleBase.typeKey: return KeyFrameDouble(); + case KeyedPropertyBase.typeKey: return KeyedProperty(); + case KeyedObjectBase.typeKey: return KeyedObject(); + case KeyFrameIdBase.typeKey: return KeyFrameId(); + case TransitionNumberConditionBase.typeKey: return TransitionNumberCondition(); + case TransitionBoolConditionBase.typeKey: return TransitionBoolCondition(); + case CubicEaseInterpolatorBase.typeKey: return CubicEaseInterpolator(); + case CubicDetachedVertexBase.typeKey: return CubicDetachedVertex(); + case StateTransitionBase.typeKey: return StateTransition(); + case CubicValueInterpolatorBase.typeKey: return CubicValueInterpolator(); + case StraightVertexBase.typeKey: return StraightVertex(); + case AnimationStateBase.typeKey: return AnimationState(); + case ImageBase.typeKey: return Image(); + case NodeBase.typeKey: return Node(); + case LinearAnimationBase.typeKey: return LinearAnimation(); + } + + // _counter.putIfAbsent(typeKey, IntCapsule.new).increment(); + // if (Randoms().hit(0.001)) { + // info('makeCoreInstance > ${_counter.entries.sorted((e1, e2) => e2.value.value - e1.value.value).map((e) => '${e.key}:${e.value}').join(',')}'); + // } + switch (typeKey) { case ViewModelInstanceListItemBase.typeKey: return ViewModelInstanceListItem(); @@ -252,8 +280,6 @@ class RiveCoreContext { return ScaleConstraint(); case RotationConstraintBase.typeKey: return RotationConstraint(); - case NodeBase.typeKey: - return Node(); case NestedArtboardBase.typeKey: return NestedArtboard(); case SoloBase.typeKey: @@ -266,40 +292,26 @@ class RiveCoreContext { return KeyFrameUint(); case AnimationBase.typeKey: return Animation(); - case LinearAnimationBase.typeKey: - return LinearAnimation(); case NestedSimpleAnimationBase.typeKey: return NestedSimpleAnimation(); - case AnimationStateBase.typeKey: - return AnimationState(); case NestedTriggerBase.typeKey: return NestedTrigger(); - case KeyedObjectBase.typeKey: - return KeyedObject(); case BlendAnimationDirectBase.typeKey: return BlendAnimationDirect(); case StateMachineNumberBase.typeKey: return StateMachineNumber(); - case CubicValueInterpolatorBase.typeKey: - return CubicValueInterpolator(); case TransitionTriggerConditionBase.typeKey: return TransitionTriggerCondition(); - case KeyedPropertyBase.typeKey: - return KeyedProperty(); case StateMachineListenerBase.typeKey: return StateMachineListener(); case TransitionPropertyViewModelComparatorBase.typeKey: return TransitionPropertyViewModelComparator(); - case KeyFrameIdBase.typeKey: - return KeyFrameId(); case KeyFrameBoolBase.typeKey: return KeyFrameBool(); case ListenerBoolChangeBase.typeKey: return ListenerBoolChange(); case ListenerAlignTargetBase.typeKey: return ListenerAlignTarget(); - case TransitionNumberConditionBase.typeKey: - return TransitionNumberCondition(); case TransitionValueBooleanComparatorBase.typeKey: return TransitionValueBooleanComparator(); case AnyStateBase.typeKey: @@ -314,14 +326,8 @@ class RiveCoreContext { return ListenerNumberChange(); case TransitionViewModelConditionBase.typeKey: return TransitionViewModelCondition(); - case CubicEaseInterpolatorBase.typeKey: - return CubicEaseInterpolator(); - case StateTransitionBase.typeKey: - return StateTransition(); case NestedBoolBase.typeKey: return NestedBool(); - case KeyFrameDoubleBase.typeKey: - return KeyFrameDouble(); case KeyFrameColorBase.typeKey: return KeyFrameColor(); case StateMachineBase.typeKey: @@ -362,8 +368,6 @@ class RiveCoreContext { return TransitionValueStringComparator(); case NestedRemapAnimationBase.typeKey: return NestedRemapAnimation(); - case TransitionBoolConditionBase.typeKey: - return TransitionBoolCondition(); case BlendStateTransitionBase.typeKey: return BlendStateTransition(); case StateMachineBoolBase.typeKey: @@ -388,8 +392,6 @@ class RiveCoreContext { return Shape(); case WeightBase.typeKey: return Weight(); - case StraightVertexBase.typeKey: - return StraightVertex(); case CubicWeightBase.typeKey: return CubicWeight(); case CubicAsymmetricVertexBase.typeKey: @@ -414,10 +416,6 @@ class RiveCoreContext { return Polygon(); case StarBase.typeKey: return Star(); - case ImageBase.typeKey: - return Image(); - case CubicDetachedVertexBase.typeKey: - return CubicDetachedVertex(); case EventBase.typeKey: return Event(); case DrawRulesBase.typeKey: @@ -491,7 +489,72 @@ class RiveCoreContext { } } + /// STOKANAL-FORK-EDIT static void setObjectProperty(Core object, int propertyKey, Object value) { + + switch (propertyKey) { + case InterpolatingKeyFrameBase.interpolationTypePropertyKey: + (object as InterpolatingKeyFrameBase).interpolationType = value as int; + // if (object is InterpolatingKeyFrameBase && value is int) { + // object.interpolationType = value; + // } + return; + + case KeyFrameDoubleBase.valuePropertyKey: + (object as KeyFrameDoubleBase).value =value as double; + // if (object is KeyFrameDoubleBase && value is double) { + // object.value = value; + // } + return; + + case KeyedPropertyBase.propertyKeyPropertyKey: + (object as KeyedPropertyBase).propertyKey = value as int; + // if (object is KeyedPropertyBase && value is int) { + // object.propertyKey = value; + // } + return; + + case InterpolatingKeyFrameBase.interpolatorIdPropertyKey: + (object as InterpolatingKeyFrameBase).interpolatorId = value as int; + // if (object is InterpolatingKeyFrameBase && value is int) { + // object.interpolatorId = value; + // } + return; + + case KeyFrameBase.framePropertyKey: + (object as KeyFrameBase).frame = value as int; + // if (object is KeyFrameBase && value is int) { + // object.frame = value; + // } + return; + + case KeyedObjectBase.objectIdPropertyKey: + (object as KeyedObjectBase).objectId = value as int; + // if (object is KeyedObjectBase && value is int) { + // object.objectId = value; + // } + return; + + case ComponentBase.parentIdPropertyKey: + (object as ComponentBase).parentId = value as int; + // if (object is ComponentBase && value is int) { + // object.parentId = value; + // } + return; + + case LayoutComponentStyleBase.interpolatorIdPropertyKey: + (object as LayoutComponentStyleBase).interpolatorId = value as int; + // if (object is LayoutComponentStyleBase && value is int) { + // object.interpolatorId = value; + // } + return; + } + + // _counter.putIfAbsent(propertyKey, IntCapsule.new).increment(); + // if (Randoms().hit(0.001)) { + // info('setObjectProperty > ${_counter.entries.sorted((e1, e2) => e2.value.value - e1.value.value).map((e) => '${e.key}:${e.value}').join(',')}'); + // } + switch (propertyKey) { case ViewModelInstanceListItemBase.useLinkedArtboardPropertyKey: if (object is ViewModelInstanceListItemBase && value is bool) { @@ -553,11 +616,6 @@ class RiveCoreContext { object.name = value; } break; - case ComponentBase.parentIdPropertyKey: - if (object is ComponentBase && value is int) { - object.parentId = value; - } - break; case ViewModelInstanceBase.viewModelIdPropertyKey: if (object is ViewModelInstanceBase && value is int) { object.viewModelId = value; @@ -968,11 +1026,6 @@ class RiveCoreContext { object.interpolationType = value; } break; - case LayoutComponentStyleBase.interpolatorIdPropertyKey: - if (object is LayoutComponentStyleBase && value is int) { - object.interpolatorId = value; - } - break; case LayoutComponentStyleBase.interpolationTimePropertyKey: if (object is LayoutComponentStyleBase && value is double) { object.interpolationTime = value; @@ -1163,21 +1216,6 @@ class RiveCoreContext { object.flags = value; } break; - case KeyFrameBase.framePropertyKey: - if (object is KeyFrameBase && value is int) { - object.frame = value; - } - break; - case InterpolatingKeyFrameBase.interpolationTypePropertyKey: - if (object is InterpolatingKeyFrameBase && value is int) { - object.interpolationType = value; - } - break; - case InterpolatingKeyFrameBase.interpolatorIdPropertyKey: - if (object is InterpolatingKeyFrameBase && value is int) { - object.interpolatorId = value; - } - break; case KeyFrameUintBase.valuePropertyKey: if (object is KeyFrameUintBase && value is int) { object.value = value; @@ -1268,11 +1306,6 @@ class RiveCoreContext { object.inputId = value; } break; - case KeyedObjectBase.objectIdPropertyKey: - if (object is KeyedObjectBase && value is int) { - object.objectId = value; - } - break; case BlendAnimationBase.animationIdPropertyKey: if (object is BlendAnimationBase && value is int) { object.animationId = value; @@ -1328,11 +1361,6 @@ class RiveCoreContext { object.inputId = value; } break; - case KeyedPropertyBase.propertyKeyPropertyKey: - if (object is KeyedPropertyBase && value is int) { - object.propertyKey = value; - } - break; case StateMachineListenerBase.targetIdPropertyKey: if (object is StateMachineListenerBase && value is int) { object.targetId = value; @@ -1473,11 +1501,6 @@ class RiveCoreContext { object.nestedValue = value; } break; - case KeyFrameDoubleBase.valuePropertyKey: - if (object is KeyFrameDoubleBase && value is double) { - object.value = value; - } - break; case KeyFrameColorBase.valuePropertyKey: if (object is KeyFrameColorBase && value is int) { object.value = value; @@ -2393,8 +2416,33 @@ class RiveCoreContext { static CoreFieldType doubleType = CoreDoubleType(); static CoreFieldType bytesType = CoreBytesType(); static CoreFieldType callbackType = CoreCallbackType(); + + /// STOKANAL-FORK-EDIT static CoreFieldType? coreType(int propertyKey) { + + switch (propertyKey) { + + case InterpolatingKeyFrameBase.interpolationTypePropertyKey: + case KeyedPropertyBase.propertyKeyPropertyKey: + case InterpolatingKeyFrameBase.interpolatorIdPropertyKey: + case KeyFrameBase.framePropertyKey: + case KeyedObjectBase.objectIdPropertyKey: + case ComponentBase.parentIdPropertyKey: + return uintType; + + case KeyFrameDoubleBase.valuePropertyKey: + case NodeBase.xPropertyKey: + case NodeBase.yPropertyKey: + return doubleType; + } + + // _counter.putIfAbsent(propertyKey, IntCapsule.new).increment(); + // if (Randoms().hit(0.001)) { + // info('coreType > ${_counter.entries.sorted((e1, e2) => e2.value.value - e1.value.value).map((e) => '${e.key}:${e.value}').join(',')}'); + // } + switch (propertyKey) { + case ViewModelInstanceListItemBase.useLinkedArtboardPropertyKey: case ViewModelInstanceBooleanBase.propertyValuePropertyKey: case TransformComponentConstraintBase.offsetPropertyKey: @@ -2434,7 +2482,6 @@ class RiveCoreContext { case ViewModelInstanceEnumBase.propertyValuePropertyKey: case ViewModelBase.defaultInstanceIdPropertyKey: case ViewModelPropertyViewModelBase.viewModelReferenceIdPropertyKey: - case ComponentBase.parentIdPropertyKey: case ViewModelInstanceBase.viewModelIdPropertyKey: case ViewModelPropertyEnumBase.enumIdPropertyKey: case ViewModelInstanceViewModelBase.propertyValuePropertyKey: @@ -2456,7 +2503,6 @@ class RiveCoreContext { case LayoutComponentStyleBase.scaleTypePropertyKey: case LayoutComponentStyleBase.layoutAlignmentTypePropertyKey: case LayoutComponentStyleBase.animationStyleTypePropertyKey: - case LayoutComponentStyleBase.interpolationTypePropertyKey: case LayoutComponentStyleBase.interpolatorIdPropertyKey: case LayoutComponentStyleBase.displayValuePropertyKey: case LayoutComponentStyleBase.positionTypeValuePropertyKey: @@ -2494,9 +2540,6 @@ class RiveCoreContext { case LayoutComponentStyleBase.maxHeightUnitsValuePropertyKey: case ListenerFireEventBase.eventIdPropertyKey: case LayerStateBase.flagsPropertyKey: - case KeyFrameBase.framePropertyKey: - case InterpolatingKeyFrameBase.interpolationTypePropertyKey: - case InterpolatingKeyFrameBase.interpolatorIdPropertyKey: case KeyFrameUintBase.valuePropertyKey: case LinearAnimationBase.fpsPropertyKey: case LinearAnimationBase.durationPropertyKey: @@ -2507,12 +2550,10 @@ class RiveCoreContext { case ListenerInputChangeBase.nestedInputIdPropertyKey: case AnimationStateBase.animationIdPropertyKey: case NestedInputBase.inputIdPropertyKey: - case KeyedObjectBase.objectIdPropertyKey: case BlendAnimationBase.animationIdPropertyKey: case BlendAnimationDirectBase.inputIdPropertyKey: case BlendAnimationDirectBase.blendSourcePropertyKey: case TransitionInputConditionBase.inputIdPropertyKey: - case KeyedPropertyBase.propertyKeyPropertyKey: case StateMachineListenerBase.targetIdPropertyKey: case StateMachineListenerBase.listenerTypeValuePropertyKey: case StateMachineListenerBase.eventIdPropertyKey: @@ -2584,6 +2625,7 @@ class RiveCoreContext { case TextValueRunBase.styleIdPropertyKey: case FileAssetBase.assetIdPropertyKey: case AudioEventBase.assetIdPropertyKey: + case LayoutComponentStyleBase.interpolationTypePropertyKey: return uintType; case ViewModelInstanceColorBase.propertyValuePropertyKey: case KeyFrameColorBase.valuePropertyKey: @@ -2626,8 +2668,6 @@ class RiveCoreContext { case TransformComponentBase.rotationPropertyKey: case TransformComponentBase.scaleXPropertyKey: case TransformComponentBase.scaleYPropertyKey: - case NodeBase.xPropertyKey: - case NodeBase.yPropertyKey: case LayoutComponentStyleBase.gapHorizontalPropertyKey: case LayoutComponentStyleBase.gapVerticalPropertyKey: case LayoutComponentStyleBase.maxWidthPropertyKey: @@ -2672,7 +2712,6 @@ class RiveCoreContext { case CubicInterpolatorComponentBase.x2PropertyKey: case CubicInterpolatorComponentBase.y2PropertyKey: case ListenerNumberChangeBase.valuePropertyKey: - case KeyFrameDoubleBase.valuePropertyKey: case TransitionValueNumberComparatorBase.valuePropertyKey: case ElasticInterpolatorBase.amplitudePropertyKey: case ElasticInterpolatorBase.periodPropertyKey: @@ -2866,6 +2905,7 @@ class RiveCoreContext { } static int getUint(Core object, int propertyKey) { + switch (propertyKey) { case ViewModelInstanceListItemBase.viewModelIdPropertyKey: return (object as ViewModelInstanceListItemBase).viewModelId; @@ -3186,6 +3226,7 @@ class RiveCoreContext { } static int getColor(Core object, int propertyKey) { + switch (propertyKey) { case ViewModelInstanceColorBase.propertyValuePropertyKey: return (object as ViewModelInstanceColorBase).propertyValue; @@ -3204,6 +3245,7 @@ class RiveCoreContext { } static String getString(Core object, int propertyKey) { + switch (propertyKey) { case ViewModelComponentBase.namePropertyKey: return (object as ViewModelComponentBase).name; @@ -3241,8 +3283,16 @@ class RiveCoreContext { return ''; } + /// STOKANAL-FORK-EDIT static double getDouble(Core object, int propertyKey) { + switch (propertyKey) { + + case NodeBase.xPropertyKey: + return (object as NodeBase).x; + case NodeBase.yPropertyKey: + return (object as NodeBase).y; + case ViewModelInstanceNumberBase.propertyValuePropertyKey: return (object as ViewModelInstanceNumberBase).propertyValue; case CustomPropertyNumberBase.propertyValuePropertyKey: @@ -3277,10 +3327,6 @@ class RiveCoreContext { return (object as TransformComponentBase).scaleX; case TransformComponentBase.scaleYPropertyKey: return (object as TransformComponentBase).scaleY; - case NodeBase.xPropertyKey: - return (object as NodeBase).x; - case NodeBase.yPropertyKey: - return (object as NodeBase).y; case LayoutComponentStyleBase.gapHorizontalPropertyKey: return (object as LayoutComponentStyleBase).gapHorizontal; case LayoutComponentStyleBase.gapVerticalPropertyKey: @@ -3370,7 +3416,7 @@ class RiveCoreContext { case ListenerNumberChangeBase.valuePropertyKey: return (object as ListenerNumberChangeBase).value; case KeyFrameDoubleBase.valuePropertyKey: - return (object as KeyFrameDoubleBase).value; + return (object as KeyFrameDoubleBase).value_; case TransitionValueNumberComparatorBase.valuePropertyKey: return (object as TransitionValueNumberComparatorBase).value; case ElasticInterpolatorBase.amplitudePropertyKey: @@ -3574,6 +3620,7 @@ class RiveCoreContext { } static Uint8List getBytes(Core object, int propertyKey) { + switch (propertyKey) { case NestedArtboardBase.dataBindPathIdsPropertyKey: return (object as NestedArtboardBase).dataBindPathIds; @@ -3589,8 +3636,18 @@ class RiveCoreContext { return Uint8List(0); } + /// STOKANAL-FORK-EDIT static void setBool(Core object, int propertyKey, bool value) { + switch (propertyKey) { + + case NestedSimpleAnimationBase.isPlayingPropertyKey: + (object as NestedSimpleAnimationBase).isPlaying = value; + // if (object is NestedSimpleAnimationBase) { + // object.isPlaying = value; + // } + break; + case ViewModelInstanceListItemBase.useLinkedArtboardPropertyKey: if (object is ViewModelInstanceListItemBase) { object.useLinkedArtboard = value; @@ -3666,11 +3723,6 @@ class RiveCoreContext { object.quantize = value; } break; - case NestedSimpleAnimationBase.isPlayingPropertyKey: - if (object is NestedSimpleAnimationBase) { - object.isPlaying = value; - } - break; case KeyFrameBoolBase.valuePropertyKey: if (object is KeyFrameBoolBase) { object.value = value; @@ -3749,8 +3801,25 @@ class RiveCoreContext { } } + /// STOKANAL-FORK-EDIT static void setUint(Core object, int propertyKey, int value) { + switch (propertyKey) { + + case SoloBase.activeComponentIdPropertyKey: + (object as SoloBase).activeComponentId = value; + // if (object is SoloBase) { + // object.activeComponentId = value; + // } + return; + + case DrawRulesBase.drawTargetIdPropertyKey: + (object as DrawRulesBase).drawTargetId = value; + // if (object is DrawRulesBase) { + // object.drawTargetId = value; + // } + return; + case ViewModelInstanceListItemBase.viewModelIdPropertyKey: if (object is ViewModelInstanceListItemBase) { object.viewModelId = value; @@ -3876,11 +3945,6 @@ class RiveCoreContext { object.animationId = value; } break; - case SoloBase.activeComponentIdPropertyKey: - if (object is SoloBase) { - object.activeComponentId = value; - } - break; case LayoutComponentStyleBase.scaleTypePropertyKey: if (object is LayoutComponentStyleBase) { object.scaleType = value; @@ -4371,11 +4435,6 @@ class RiveCoreContext { object.assetId = value; } break; - case DrawRulesBase.drawTargetIdPropertyKey: - if (object is DrawRulesBase) { - object.drawTargetId = value; - } - break; case LayoutComponentBase.styleIdPropertyKey: if (object is LayoutComponentBase) { object.styleId = value; @@ -4539,8 +4598,29 @@ class RiveCoreContext { } } + /// STOKANAL-FORK-EDIT static void setColor(Core object, int propertyKey, int value) { + + // _counter.putIfAbsent(propertyKey, IntCapsule.new).increment(); + // if (Randoms().hit(0.001)) { + // info('setColor > ${_counter.entries.sorted((e1, e2) => e2.value.value - e1.value.value).map((e) => '${e.key}:${e.value}').join(',')}'); + // } + + // reordered switch (propertyKey) { + case SolidColorBase.colorValuePropertyKey: + (object as SolidColorBase).colorValue = value; + // if (object is SolidColorBase) { + // object.colorValue = value; + // } + return; + case GradientStopBase.colorValuePropertyKey: + (object as GradientStopBase).colorValue = value; + // if (object is GradientStopBase) { + // object.colorValue = value; + // } + return; + case ViewModelInstanceColorBase.propertyValuePropertyKey: if (object is ViewModelInstanceColorBase) { object.propertyValue = value; @@ -4556,16 +4636,6 @@ class RiveCoreContext { object.value = value; } break; - case SolidColorBase.colorValuePropertyKey: - if (object is SolidColorBase) { - object.colorValue = value; - } - break; - case GradientStopBase.colorValuePropertyKey: - if (object is GradientStopBase) { - object.colorValue = value; - } - break; case BindablePropertyColorBase.propertyValuePropertyKey: if (object is BindablePropertyColorBase) { object.propertyValue = value; @@ -4575,6 +4645,7 @@ class RiveCoreContext { } static void setString(Core object, int propertyKey, String value) { + switch (propertyKey) { case ViewModelComponentBase.namePropertyKey: if (object is ViewModelComponentBase) { @@ -4659,8 +4730,129 @@ class RiveCoreContext { } } + /// STOKANAL-FORK-EDIT static void setDouble(Core object, int propertyKey, double value) { + + // reordered switch to allow for more frequent in the beginning switch (propertyKey) { + case VertexBase.xPropertyKey: + (object as VertexBase).x = value; + // if (object is VertexBase) { + // object.x = value; + // } + return; + case VertexBase.yPropertyKey: + (object as VertexBase).y = value; + // if (object is VertexBase) { + // object.y = value; + // } + return; + case CubicDetachedVertexBase.outRotationPropertyKey: + (object as CubicDetachedVertexBase).outRotation = value; + // if (object is CubicDetachedVertexBase) { + // object.outRotation = value; + // } + return; + case CubicDetachedVertexBase.outDistancePropertyKey: + (object as CubicDetachedVertexBase).outDistance = value; + // if (object is CubicDetachedVertexBase) { + // object.outDistance = value; + // } + return; + case CubicDetachedVertexBase.inRotationPropertyKey: + (object as CubicDetachedVertexBase).inRotation = value; + // if (object is CubicDetachedVertexBase) { + // object.inRotation = value; + // } + return; + case CubicAsymmetricVertexBase.inDistancePropertyKey: + (object as CubicAsymmetricVertexBase).inDistance = value; + // if (object is CubicAsymmetricVertexBase) { + // object.inDistance = value; + // } + return; + case NodeBase.xPropertyKey: + (object as NodeBase).x = value; + // if (object is NodeBase) { + // object.x = value; + // } + return; + case NodeBase.yPropertyKey: + (object as NodeBase).y = value; + // if (object is NodeBase) { + // object.y = value; + // } + return; + case CubicDetachedVertexBase.inDistancePropertyKey: + if (object is CubicDetachedVertexBase) { + object.inDistance = value; + } + return; + case TransformComponentBase.scaleXPropertyKey: + if (object is TransformComponentBase) { + object.scaleX = value; + } + return; + case TransformComponentBase.scaleYPropertyKey: + if (object is TransformComponentBase) { + object.scaleY = value; + } + return; + case TransformComponentBase.rotationPropertyKey: + if (object is TransformComponentBase) { + object.rotation = value; + } + return; + case DistanceConstraintBase.distancePropertyKey: + if (object is DistanceConstraintBase) { + object.distance = value; + } + return; + case WorldTransformComponentBase.opacityPropertyKey: + if (object is WorldTransformComponentBase) { + object.opacity = value; + } + return; + case CubicAsymmetricVertexBase.rotationPropertyKey: + if (object is CubicAsymmetricVertexBase) { + object.rotation = value; + } + return; + case CubicMirroredVertexBase.rotationPropertyKey: + if (object is CubicMirroredVertexBase) { + object.rotation = value; + } + return; + case CubicMirroredVertexBase.distancePropertyKey: + if (object is CubicMirroredVertexBase) { + object.distance = value; + } + return; + case CubicAsymmetricVertexBase.outDistancePropertyKey: + if (object is CubicAsymmetricVertexBase) { + object.outDistance = value; + } + return; + case GradientStopBase.positionPropertyKey: + if (object is GradientStopBase) { + object.position = value; + } + return; + case StrokeBase.thicknessPropertyKey: + if (object is StrokeBase) { + object.thickness = value; + } + return; + + // } + // + // _counter.putIfAbsent(propertyKey, IntCapsule.new).increment(); + // if (Randoms().hit(0.001)) { + // info('setDouble > ${_counter.entries.sorted((e1, e2) => e2.value.value - e1.value.value).map((e) => '${e.key}:${e.value}').join(',')}'); + // } + // + // switch (propertyKey) { + case ViewModelInstanceNumberBase.propertyValuePropertyKey: if (object is ViewModelInstanceNumberBase) { object.propertyValue = value; @@ -4676,11 +4868,6 @@ class RiveCoreContext { object.strength = value; } break; - case DistanceConstraintBase.distancePropertyKey: - if (object is DistanceConstraintBase) { - object.distance = value; - } - break; case TransformComponentConstraintBase.copyFactorPropertyKey: if (object is TransformComponentConstraintBase) { object.copyFactor = value; @@ -4726,36 +4913,6 @@ class RiveCoreContext { object.originY = value; } break; - case WorldTransformComponentBase.opacityPropertyKey: - if (object is WorldTransformComponentBase) { - object.opacity = value; - } - break; - case TransformComponentBase.rotationPropertyKey: - if (object is TransformComponentBase) { - object.rotation = value; - } - break; - case TransformComponentBase.scaleXPropertyKey: - if (object is TransformComponentBase) { - object.scaleX = value; - } - break; - case TransformComponentBase.scaleYPropertyKey: - if (object is TransformComponentBase) { - object.scaleY = value; - } - break; - case NodeBase.xPropertyKey: - if (object is NodeBase) { - object.x = value; - } - break; - case NodeBase.yPropertyKey: - if (object is NodeBase) { - object.y = value; - } - break; case LayoutComponentStyleBase.gapHorizontalPropertyKey: if (object is LayoutComponentStyleBase) { object.gapHorizontal = value; @@ -5036,16 +5193,6 @@ class RiveCoreContext { object.opacity = value; } break; - case StrokeBase.thicknessPropertyKey: - if (object is StrokeBase) { - object.thickness = value; - } - break; - case GradientStopBase.positionPropertyKey: - if (object is GradientStopBase) { - object.position = value; - } - break; case TrimPathBase.startPropertyKey: if (object is TrimPathBase) { object.start = value; @@ -5061,16 +5208,6 @@ class RiveCoreContext { object.offset = value; } break; - case VertexBase.xPropertyKey: - if (object is VertexBase) { - object.x = value; - } - break; - case VertexBase.yPropertyKey: - if (object is VertexBase) { - object.y = value; - } - break; case MeshVertexBase.uPropertyKey: if (object is MeshVertexBase) { object.u = value; @@ -5086,21 +5223,6 @@ class RiveCoreContext { object.radius = value; } break; - case CubicAsymmetricVertexBase.rotationPropertyKey: - if (object is CubicAsymmetricVertexBase) { - object.rotation = value; - } - break; - case CubicAsymmetricVertexBase.inDistancePropertyKey: - if (object is CubicAsymmetricVertexBase) { - object.inDistance = value; - } - break; - case CubicAsymmetricVertexBase.outDistancePropertyKey: - if (object is CubicAsymmetricVertexBase) { - object.outDistance = value; - } - break; case ParametricPathBase.widthPropertyKey: if (object is ParametricPathBase) { object.width = value; @@ -5141,16 +5263,6 @@ class RiveCoreContext { object.cornerRadiusBR = value; } break; - case CubicMirroredVertexBase.rotationPropertyKey: - if (object is CubicMirroredVertexBase) { - object.rotation = value; - } - break; - case CubicMirroredVertexBase.distancePropertyKey: - if (object is CubicMirroredVertexBase) { - object.distance = value; - } - break; case PolygonBase.cornerRadiusPropertyKey: if (object is PolygonBase) { object.cornerRadius = value; @@ -5171,26 +5283,6 @@ class RiveCoreContext { object.originY = value; } break; - case CubicDetachedVertexBase.inRotationPropertyKey: - if (object is CubicDetachedVertexBase) { - object.inRotation = value; - } - break; - case CubicDetachedVertexBase.inDistancePropertyKey: - if (object is CubicDetachedVertexBase) { - object.inDistance = value; - } - break; - case CubicDetachedVertexBase.outRotationPropertyKey: - if (object is CubicDetachedVertexBase) { - object.outRotation = value; - } - break; - case CubicDetachedVertexBase.outDistancePropertyKey: - if (object is CubicDetachedVertexBase) { - object.outDistance = value; - } - break; case LayoutComponentBase.widthPropertyKey: if (object is LayoutComponentBase) { object.width = value; diff --git a/lib/src/generated/shapes/vertex_base.dart b/lib/src/generated/shapes/vertex_base.dart index 58fb3278..f0185db3 100644 --- a/lib/src/generated/shapes/vertex_base.dart +++ b/lib/src/generated/shapes/vertex_base.dart @@ -20,6 +20,7 @@ abstract class VertexBase extends ContainerComponent { /// X field with key 24. static const int xPropertyKey = 24; static const double xInitialValue = 0; + double _x = xInitialValue; /// X value for the translation of the vertex. @@ -44,6 +45,7 @@ abstract class VertexBase extends ContainerComponent { /// Y field with key 25. static const int yPropertyKey = 25; static const double yInitialValue = 0; + double _y = yInitialValue; /// Y value for the translation of the vertex. diff --git a/lib/src/rive_core/animation/animation_reset_factory.dart b/lib/src/rive_core/animation/animation_reset_factory.dart index 7840cade..3274e02b 100644 --- a/lib/src/rive_core/animation/animation_reset_factory.dart +++ b/lib/src/rive_core/animation/animation_reset_factory.dart @@ -1,3 +1,5 @@ +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/blend_state.dart'; @@ -120,10 +122,10 @@ class _KeyedProperty { class _KeyedObject { final List<_KeyedProperty> properties = []; final KeyedObject data; - final Set visitedProperties = {}; + final Set visitedProperties = HashSet();//{}; _KeyedObject(this.data); void addProperties( - List props, Core object, bool storeAsBaseline) { + Iterable props, Core object, bool storeAsBaseline) { for (final property in props) { if (!visitedProperties.contains(property.propertyKey)) { visitedProperties.add(property.propertyKey); @@ -151,12 +153,14 @@ class _AnimationsData { int size = 0; List<_KeyedObject> keyedObjects = []; - Map visitedObjects = {}; - _AnimationsData(List animations, CoreContext core, + Map visitedObjects = HashMap();//{}; + + _AnimationsData(Iterable animations, CoreContext core, bool useFirstAsBaseline) { bool isFirstAnimation = useFirstAsBaseline; for (final animation in animations) { - animation.keyedObjects.forEach((keyedObject) { + // animation.keyedObjects.forEach((keyedObject) { + for (final keyedObject in animation.keyedObjects) { final objectIntId = resolveId(keyedObject.objectId); final object = core.resolve(keyedObject.objectId); if (!visitedObjects.containsKey(objectIntId)) { @@ -164,8 +168,8 @@ class _AnimationsData { keyedObjects.add(visitedObjects[objectIntId]!); } visitedObjects[objectIntId]!.addProperties( - keyedObject.keyedProperties.toList(), object!, isFirstAnimation); - }); + keyedObject.keyedProperties, object!, isFirstAnimation); // .toList() + }//); isFirstAnimation = false; } for (final object in keyedObjects) { @@ -178,7 +182,9 @@ class _AnimationsData { } void writeObjects(AnimationReset animationReset, CoreContext core) { - keyedObjects.forEach((keyedObject) { + + // keyedObjects.forEach((keyedObject) { + for (final keyedObject in keyedObjects) { // We might have added keyed objects but no properties need resetting if (keyedObject.properties.isNotEmpty) { int objectIntId = resolveId(keyedObject.data.objectId); @@ -202,7 +208,7 @@ class _AnimationsData { animationReset.writePropertyKey(property.propertyKey); if (property.isBaseline) { animationReset.writeDouble( - (property.property.keyframes.first as KeyFrameDouble).value); + (property.property.keyframes.first as KeyFrameDouble).value_); } else { animationReset.writeDouble(RiveCoreContext.getDouble( core.resolve(keyedObject.data.objectId), @@ -211,14 +217,14 @@ class _AnimationsData { } } } - }); + }//); animationReset.createReader(); } } List _pool = []; -AnimationReset fromAnimations(List animations, +AnimationReset fromAnimations(Iterable animations, CoreContext core, bool useFirstAsBaseline) { final animationData = _AnimationsData(animations, core, useFirstAsBaseline); AnimationReset? animationReset; @@ -247,13 +253,15 @@ List _fromState( if (state is AnimationState && state.animation != null) { animations.add(state.animation!); } else if (state is BlendState) { - state.animations.forEach((blend1DAnimation) { + + // state.animations.forEach((blend1DAnimation) { + for (final blend1DAnimation in state.animations) { final animation = core.resolve(blend1DAnimation.animationId); if (animation != null) { animations.add(animation); } - }); + }//); } } return animations; diff --git a/lib/src/rive_core/animation/blend_state_1d_instance.dart b/lib/src/rive_core/animation/blend_state_1d_instance.dart index 5016852d..9732e6bc 100644 --- a/lib/src/rive_core/animation/blend_state_1d_instance.dart +++ b/lib/src/rive_core/animation/blend_state_1d_instance.dart @@ -20,8 +20,8 @@ class BlendState1DInstance ? animation_reset_factory.fromAnimations( animationInstances .map((animationInstance) => - animationInstance.animationInstance.animation) - .toList(growable: false), + animationInstance.animationInstance.animation), + // .toList(growable: false), state.context, true) : null; diff --git a/lib/src/rive_core/animation/keyed_object.dart b/lib/src/rive_core/animation/keyed_object.dart index 114871cf..14658642 100644 --- a/lib/src/rive_core/animation/keyed_object.dart +++ b/lib/src/rive_core/animation/keyed_object.dart @@ -1,5 +1,6 @@ import 'dart:collection'; +import 'package:collection/collection.dart'; import 'package:rive/src/core/core.dart'; import 'package:rive/src/generated/animation/keyed_object_base.dart'; import 'package:rive/src/rive_core/animation/keyed_property.dart'; @@ -15,10 +16,21 @@ abstract class KeyedCallbackReporter { } class KeyedObject extends KeyedObjectBase { - final HashMap _keyedProperties = - HashMap(); - Iterable get keyedProperties => _keyedProperties.values; + final Map _keyedProperties = HashMap(); + + /// STOKANAL-FORK-EDIT: Keeping a copy of values lazily + List? _props; + Iterable get keyedProperties => + _props ??= _keyedProperties.values.toList(); + + List? _propsNonCallback; + Iterable get propsNonCallback => + _propsNonCallback ??= keyedProperties.whereNot((p) => p.isCallback).toList(); + + /// STOKANAL-FORK-EDIT: Reuse this object for every animation + @override + K? clone() => this as K; @override void onAddedDirty() {} @@ -48,6 +60,7 @@ class KeyedObject extends KeyedObjectBase { return false; } _keyedProperties[property.propertyKey] = property; + _propsNonCallback = _props = null; return true; } @@ -56,6 +69,7 @@ class KeyedObject extends KeyedObjectBase { /// be @internal when it's supported. bool internalRemoveKeyedProperty(KeyedProperty property) { var removed = _keyedProperties.remove(property.propertyKey); + _propsNonCallback = _props = null; if (_keyedProperties.isEmpty) { // Remove this keyed property. @@ -73,8 +87,12 @@ class KeyedObject extends KeyedObjectBase { required KeyedCallbackReporter reporter, bool isAtStartFrame = false, }) { - for (final keyedProperty - in _keyedProperties.values.where((property) => property.isCallback)) { + for (final keyedProperty in keyedProperties) { + + if (!keyedProperty.isCallback) { + continue; + } + keyedProperty.reportKeyedCallbacks( objectId, secondsFrom, @@ -94,10 +112,7 @@ class KeyedObject extends KeyedObjectBase { if (object == null) { return; } - for (final keyedProperty in _keyedProperties.values) { - if (keyedProperty.isCallback) { - continue; - } + for (final keyedProperty in propsNonCallback) { keyedProperty.apply(time, mix, object); } } diff --git a/lib/src/rive_core/animation/keyed_property.dart b/lib/src/rive_core/animation/keyed_property.dart index afb97eb6..1fc7786e 100644 --- a/lib/src/rive_core/animation/keyed_property.dart +++ b/lib/src/rive_core/animation/keyed_property.dart @@ -57,6 +57,11 @@ class KeyFrameList { class KeyedProperty extends KeyedPropertyBase with KeyFrameList { + + /// STOKANAL-FORK-EDIT: Reuse this object for every animation + @override + K? clone() => this as K; + @override void onAdded() {} @@ -117,9 +122,6 @@ class KeyedProperty extends KeyedPropertyBase int closestFrameIndex(double seconds, {int exactOffset = 0}) { // Binary find the keyframe index (use timeInSeconds here as opposed to the // finder above which operates in frames). - int mid = 0; - double closestSeconds = 0; - int start = 0; int end = _keyframes.length - 1; // If it's the last keyframe, we skip the binary search @@ -127,6 +129,10 @@ class KeyedProperty extends KeyedPropertyBase return end + 1; } + int mid = 0; + int start = 0; + double closestSeconds = 0; + while (start <= end) { mid = (start + end) >> 1; closestSeconds = _keyframes[mid].seconds; @@ -141,7 +147,7 @@ class KeyedProperty extends KeyedPropertyBase return start; } - bool get isCallback => RiveCoreContext.isCallback(propertyKey); + bool get isCallback => RiveCoreContext.isCallback(propertyKey_); /// Report any keyframes that occured between secondsFrom and secondsTo. void reportKeyedCallbacks( @@ -186,7 +192,7 @@ class KeyedProperty extends KeyedPropertyBase /// Apply keyframe values at a given time expressed in [seconds]. void apply(double seconds, double mix, Core object) { - if (_keyframes.isEmpty) { + if (_keyframes.length == 0) { return; } diff --git a/lib/src/rive_core/animation/keyframe_double.dart b/lib/src/rive_core/animation/keyframe_double.dart index 39d55448..bcde08e1 100644 --- a/lib/src/rive_core/animation/keyframe_double.dart +++ b/lib/src/rive_core/animation/keyframe_double.dart @@ -14,17 +14,22 @@ void _apply( } class KeyFrameDouble extends KeyFrameDoubleBase { + + /// STOKANAL-FORK-EDIT: Reuse this object for every animation + @override + K? clone() => this as K; + @override void apply(Core object, int propertyKey, double mix) => - _apply(object, propertyKey, mix, value); + _apply(object, propertyKey, mix, value_); @override void applyInterpolation(Core object, int propertyKey, double currentTime, KeyFrameDouble nextFrame, double mix) { var f = (currentTime - seconds) / (nextFrame.seconds - seconds); - var frameValue = interpolator?.transformValue(value, nextFrame.value, f) ?? - value + (nextFrame.value - value) * f; + var frameValue = interpolator?.transformValue(value_, nextFrame.value_, f) ?? + value_ + (nextFrame.value_ - value_) * f; _apply(object, propertyKey, mix, frameValue); } diff --git a/lib/src/rive_core/animation/linear_animation.dart b/lib/src/rive_core/animation/linear_animation.dart index b6b5212c..c7f8fae3 100644 --- a/lib/src/rive_core/animation/linear_animation.dart +++ b/lib/src/rive_core/animation/linear_animation.dart @@ -14,6 +14,28 @@ class LinearAnimation extends LinearAnimationBase { /// object is keyed in this animation. final _keyedObjects = HashMap(); + // static int _objectCount = 0; + // static final List _all = []; + // static void dump() { + // log('DUMPING LINEAR ANIMATIONS all=${_all.length} keyed=${_all.where((a) => a._keyedObjects.isNotEmpty).length} keys=${_all.map((a) => a._keyedObjects.length).sum}'); + // // log(_all.where((a) => a._keyedObjects.isNotEmpty).map((a) => a.toString()).join('\n')); + // } + // + // final int count = ++_objectCount; + // late final bool logging = count < 4500 && count % 500 == 0; + // + // @override + // String toString() => 'LinearAnimation[$name, $count, ${_keyedObjects.length}]'; + // + // LinearAnimation() { + // + // _all.add(this); + // if (logging) { + // log('CONSTRUCTED >> $this'); + // debugPrintStack(); + // } + // } + /// The metadata for the objects that are keyed in this animation. Iterable get keyedObjects => _keyedObjects.values; @@ -22,6 +44,12 @@ class LinearAnimation extends LinearAnimationBase { bool internalAddKeyedObject(KeyedObject object) { if (internalCheckAddKeyedObject(object)) { _keyedObjects[object.objectId] = object; + + // if (logging) {// && _keyedObjects.length % 1 == 0) { + // log('ADDING KEY-OBJECT >> $this'); + // debugPrintStack(); + // } + return true; } return false; @@ -42,14 +70,16 @@ class LinearAnimation extends LinearAnimationBase { objects.any((element) => _keyedObjects.containsKey(element.id)); 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()) { + for (final kf in kp.keyframes){//.toList()) { kf.remove(); found = true; } @@ -73,6 +103,9 @@ class LinearAnimation extends LinearAnimationBase { /// Returns the start time of the animation in seconds, considering speed double get startTime => (speed >= 0) ? startSeconds : endSeconds; + /// STOKANAL-FORK-EDIT: iterate properties with a list rather than with a map + late final List _objects = _keyedObjects.values.toList(growable: false); + void reportKeyedCallbacks( double secondsFrom, double secondsTo, { @@ -88,7 +121,9 @@ class LinearAnimation extends LinearAnimationBase { // Do not report a callback twice if it comes from the "pong" part of a // "ping pong" loop if (!isAtStartFrame || !fromPong) { - for (final keyedObject in _keyedObjects.values) { + // for (final keyedObject in _keyedObjects.values) { + /// STOKANAL-FORK-EDIT: iterate properties with a list rather than with a map + for (final keyedObject in _objects) { keyedObject.reportKeyedCallbacks( secondsFrom, secondsTo, @@ -110,7 +145,9 @@ class LinearAnimation extends LinearAnimationBase { // ignore: parameter_assignments time = (time * fps).floor() / fps; } - for (final keyedObject in _keyedObjects.values) { + // for (final keyedObject in _keyedObjects.values) { + /// STOKANAL-FORK-EDIT: iterate properties with a list rather than with a map + for (final keyedObject in _objects) { keyedObject.apply(time, mix, coreContext); } } diff --git a/lib/src/rive_core/animation/nested_state_machine.dart b/lib/src/rive_core/animation/nested_state_machine.dart index 403871e5..b73c3806 100644 --- a/lib/src/rive_core/animation/nested_state_machine.dart +++ b/lib/src/rive_core/animation/nested_state_machine.dart @@ -1,3 +1,5 @@ +import 'dart:collection'; + import 'package:flutter/foundation.dart'; import 'package:flutter/gestures.dart'; import 'package:rive/src/core/core.dart'; @@ -41,7 +43,7 @@ class NestedStateMachine extends NestedStateMachineBase { @override bool get isEnabled => _stateMachineInstance?.isActive ?? false; - final Set _nestedInputs = {}; + final Set _nestedInputs = HashSet();//{}; Set get nestedInputs => _nestedInputs; NestedStateMachineInstance? _stateMachineInstance; diff --git a/lib/src/rive_core/artboard.dart b/lib/src/rive_core/artboard.dart index 74a598b7..8132dd5d 100644 --- a/lib/src/rive_core/artboard.dart +++ b/lib/src/rive_core/artboard.dart @@ -106,7 +106,7 @@ class Artboard extends ArtboardBase with ShapePaintContainer { final List _rules = []; List _sortedDrawRules = []; - final Set _components = {}; + final Set _components = HashSet();//{}; List get drawables => _drawables; @@ -133,8 +133,9 @@ class Artboard extends ArtboardBase with ShapePaintContainer { int _dirtDepth = 0; /// Iterate each component and call callback for it. - void forEachComponent(void Function(Component) callback) => - _components.forEach(callback); + void forEachComponent(void Function(Component) callback) { + _components.forEach(callback); + } /// Find a component of a specific type with a specific name. T? component(String name) { @@ -205,7 +206,7 @@ class Artboard extends ArtboardBase with ShapePaintContainer { return didUpdate; } - final Set _activeNestedArtboards = {}; + final Set _activeNestedArtboards = HashSet();//{}; Iterable get activeNestedArtboards => _activeNestedArtboards; final List _joysticks = []; @@ -215,7 +216,7 @@ class Artboard extends ArtboardBase with ShapePaintContainer { Iterable get dataBinds => _dataBinds; bool canPreApplyJoysticks() { - if (_joysticks.isEmpty) { + if (_joysticks.length == 0) { return false; } if (_joysticks.any((joystick) => joystick.isComplex)) { @@ -311,8 +312,8 @@ class Artboard extends ArtboardBase with ShapePaintContainer { } if (nested) { - var active = _activeNestedArtboards.toList(growable: false); - for (final activeNestedArtboard in active) { + // var active = _activeNestedArtboards.toList(growable: false); + for (final activeNestedArtboard in _activeNestedArtboards){//.toList(growable: false)) { if (activeNestedArtboard.advance(elapsedSeconds)) { didUpdate = true; } @@ -573,7 +574,7 @@ class Artboard extends ArtboardBase with ShapePaintContainer { /// The animation controllers that are called back whenever the artboard /// advances. - final Set _animationControllers = {}; + final Set _animationControllers = HashSet();//{}; /// Access a read-only iterator of currently applied animation controllers. Iterable get animationControllers => @@ -665,9 +666,7 @@ class Artboard extends ArtboardBase with ShapePaintContainer { } void populateDataBinds(List globalDataBinds) { - dataBinds.forEach((dataBind) { - globalDataBinds.add(dataBind); - }); + dataBinds.forEach(globalDataBinds.add); for (final nestedArtboard in _activeNestedArtboards) { final mountedArtboard = nestedArtboard.mountedArtboard; diff --git a/lib/src/rive_core/assets/font_asset.dart b/lib/src/rive_core/assets/font_asset.dart index 3b9739d7..99e40f05 100644 --- a/lib/src/rive_core/assets/font_asset.dart +++ b/lib/src/rive_core/assets/font_asset.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:collection'; import 'package:flutter/foundation.dart'; import 'package:rive/src/generated/assets/font_asset_base.dart'; @@ -9,7 +10,7 @@ import 'package:rive_common/rive_text.dart'; export 'package:rive/src/generated/assets/font_asset_base.dart'; class FontAsset extends FontAssetBase { - final Set _callbacks = {}; + final Set _callbacks = HashSet();//{}; /// Call [callback] when the font is ready. Set [notifyAlreadySet] to /// specify if you want to be called if the font is already set. diff --git a/lib/src/rive_core/audio_player.dart b/lib/src/rive_core/audio_player.dart index 258121c6..007fa0c3 100644 --- a/lib/src/rive_core/audio_player.dart +++ b/lib/src/rive_core/audio_player.dart @@ -95,7 +95,7 @@ class AudioPlayer { return; } - var completed = _sounds.where((sound) => sound.completed).toList(); + var completed = _sounds.where((sound) => sound.completed);//.toList(); _sounds.removeWhere((sound) => sound.completed); for (final sound in completed) { diff --git a/lib/src/rive_core/bones/bone.dart b/lib/src/rive_core/bones/bone.dart index d83e6c48..41b149d8 100644 --- a/lib/src/rive_core/bones/bone.dart +++ b/lib/src/rive_core/bones/bone.dart @@ -1,3 +1,5 @@ +import 'dart:collection'; + import 'package:rive/src/generated/bones/bone_base.dart'; import 'package:rive/src/rive_core/constraints/constraint.dart'; import 'package:rive_common/math.dart'; @@ -9,7 +11,7 @@ typedef bool BoneCallback(Bone bone); class Bone extends BoneBase { /// Child constraints applied to some child of this bone which also affect /// this bone. - final Set _peerConstraints = {}; + final Set _peerConstraints = HashSet();//{}; Iterable get peerConstraints => _peerConstraints; bool addPeerConstraint(Constraint child) => _peerConstraints.add(child); diff --git a/lib/src/rive_core/component.dart b/lib/src/rive_core/component.dart index 5f57567e..dc3764f2 100644 --- a/lib/src/rive_core/component.dart +++ b/lib/src/rive_core/component.dart @@ -1,3 +1,5 @@ +import 'dart:collection'; + import 'package:rive/src/generated/component_base.dart'; import 'package:rive/src/rive_core/artboard.dart'; import 'package:rive/src/rive_core/component_dirt.dart'; @@ -163,13 +165,13 @@ abstract class Component extends ComponentBase } /// Components that this component depends on. - final Set _dependsOn = {}; + final Set _dependsOn = HashSet();//{}; @override Set get dependents => _dependencyHelper.dependents; Set get dependencies { - Set components = {}; + Set components = HashSet();//{}; allDependencies(components); return components; } diff --git a/lib/src/rive_core/constraints/follow_path_constraint.dart b/lib/src/rive_core/constraints/follow_path_constraint.dart index eda76937..4ec5f4cf 100644 --- a/lib/src/rive_core/constraints/follow_path_constraint.dart +++ b/lib/src/rive_core/constraints/follow_path_constraint.dart @@ -19,7 +19,8 @@ class FollowPathConstraint extends FollowPathConstraintBase { Mat2D get targetTransform { if (target is Shape || target is Path) { - var metrics = _worldPath.computeMetrics().toList(growable: false); + // var metrics = _worldPath.computeMetrics().toList(growable: false); + var metrics = _worldPath.computeMetrics(); if (metrics.isEmpty) { return Mat2D(); } diff --git a/lib/src/rive_core/constraints/ik_constraint.dart b/lib/src/rive_core/constraints/ik_constraint.dart index 2cacc486..40700245 100644 --- a/lib/src/rive_core/constraints/ik_constraint.dart +++ b/lib/src/rive_core/constraints/ik_constraint.dart @@ -96,7 +96,7 @@ class IKConstraint extends IKConstraintBase { // tip (constrainedComponent). var tip = parent as Bone; - var bones = _fkChain.reversed.map((link) => link.bone).toSet(); + var bones = _fkChain.reversed.map((link) => link.bone).toSet(); // to set to preserve order for (final bone in bones.skip(1)) { for (final child in bone.children) { if (child is TransformComponent && !bones.contains(child)) { diff --git a/lib/src/rive_core/dependency_helper.dart b/lib/src/rive_core/dependency_helper.dart index fb0383be..1d56188a 100644 --- a/lib/src/rive_core/dependency_helper.dart +++ b/lib/src/rive_core/dependency_helper.dart @@ -1,20 +1,33 @@ + + class DependencyHelper { - Set dependents = {}; + + final dependents = {}; // set should stay ordered T? dependencyRoot; DependencyHelper(); bool addDependent(U value) { - if (!dependents.contains(value)) { - dependents.add(value); + + // if (!dependents.contains(value)) { + // dependents.add(value); + + /// STOKANAL-FORK-EDIT: use add directly + if (dependents.add(value)) { return true; } return false; } void addDirt(int dirt, {bool recurse = false}) { - dependents - .forEach((dependent) => dependent.addDirt(dirt, recurse: recurse)); + + /// STOKANAL-FORK-EDIT: do not use forEach + for (final dependent in dependents) { + dependent.addDirt(dirt, recurse: recurse); + } + + // dependents + // .forEach((dependent) => dependent.addDirt(dirt, recurse: recurse)); } void onComponentDirty(U component) { diff --git a/lib/src/rive_core/drawable.dart b/lib/src/rive_core/drawable.dart index d42aa3f7..fd39fb71 100644 --- a/lib/src/rive_core/drawable.dart +++ b/lib/src/rive_core/drawable.dart @@ -43,7 +43,7 @@ abstract class Drawable extends DrawableBase { List _clippingShapes = []; bool clip(Canvas canvas) { - if (_clippingShapes.isEmpty) { + if (_clippingShapes.length == 0) { return false; } canvas.save(); diff --git a/lib/src/rive_core/event.dart b/lib/src/rive_core/event.dart index 38e0ce4f..53effd61 100644 --- a/lib/src/rive_core/event.dart +++ b/lib/src/rive_core/event.dart @@ -26,7 +26,7 @@ class Event extends EventBase { } void _syncCustomProperties() { - var nextCustomProperties = children.whereType().toSet(); + var nextCustomProperties = children.whereType().toSet();//.toSet(); if (!iterableEquals(customProperties, nextCustomProperties)) { customProperties.clear(); customProperties.addAll(nextCustomProperties); 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 5baf13b3..01dd2af2 100644 --- a/lib/src/rive_core/shapes/paint/trim_path_drawing.dart +++ b/lib/src/rive_core/shapes/paint/trim_path_drawing.dart @@ -78,7 +78,7 @@ void _appendPathSegmentSync( void _trimPathSequential( Path path, Path result, double startT, double stopT, bool complement) { // Measure length of all the contours. - var metrics = path.computeMetrics().toList(growable: false); + var metrics = path.computeMetrics();//.toList(growable: false); double totalLength = 0.0; for (final metric in metrics) { totalLength += metric.length; @@ -114,7 +114,7 @@ void _trimPathSequential( void _trimPathSync( Path path, Path result, double startT, double stopT, bool complement) { - final metrics = path.computeMetrics().toList(growable: false); + final metrics = path.computeMetrics();//.toList(growable: false); for (final metric in metrics) { double length = metric.length; double trimStart = length * startT; diff --git a/lib/src/rive_core/shapes/shape.dart b/lib/src/rive_core/shapes/shape.dart index 35729995..86a18ad5 100644 --- a/lib/src/rive_core/shapes/shape.dart +++ b/lib/src/rive_core/shapes/shape.dart @@ -1,3 +1,4 @@ +import 'dart:collection'; import 'dart:ui' as ui; import 'package:collection/collection.dart'; @@ -14,7 +15,7 @@ import 'package:rive_common/math.dart'; export 'package:rive/src/generated/shapes/shape_base.dart'; class Shape extends ShapeBase with ShapePaintContainer { - final Set paths = {}; + final Set paths = HashSet();//{}; bool _wantWorldPath = false; bool _wantLocalPath = false; diff --git a/lib/src/rive_core/shapes/shape_paint_container.dart b/lib/src/rive_core/shapes/shape_paint_container.dart index d7935d64..54525f83 100644 --- a/lib/src/rive_core/shapes/shape_paint_container.dart +++ b/lib/src/rive_core/shapes/shape_paint_container.dart @@ -1,3 +1,5 @@ +import 'dart:collection'; + import 'package:meta/meta.dart'; import 'package:rive/src/rive_core/component.dart'; import 'package:rive/src/rive_core/container_component.dart'; @@ -9,9 +11,9 @@ import 'package:rive_common/math.dart'; /// An abstraction to give a common interface to any component that can contain /// fills and strokes. abstract class ShapePaintContainer { - final Set fills = {}; + final Set fills = HashSet();//{}; - final Set strokes = {}; + final Set strokes = HashSet();//{}; /// Called whenever a new paint mutator is added/removed from the shape paints /// (for example a linear gradient is added to a stroke). diff --git a/lib/src/rive_core/state_machine_controller.dart b/lib/src/rive_core/state_machine_controller.dart index 1e5ef31a..8192f35b 100644 --- a/lib/src/rive_core/state_machine_controller.dart +++ b/lib/src/rive_core/state_machine_controller.dart @@ -364,7 +364,7 @@ class StateMachineController extends RiveAnimationController final _reportedEvents = []; // Keep a seperate list of nested events because we also need to store // the source of the nested event in order to compare to listener target - final Map> _reportedNestedEvents = {}; + final Map> _reportedNestedEvents = HashMap>();//{}; /// Optional callback for state changes final OnStateChange? onStateChange; @@ -372,7 +372,7 @@ class StateMachineController extends RiveAnimationController /// Optional callback for input value changes OnInputValueChange? onInputValueChange; - final _eventListeners = {}; + final _eventListeners = HashSet();//{}; AudioPlayer? _audioPlayer; AudioPlayer get audioPlayer => (_audioPlayer ??= AudioPlayer.make())!; @@ -512,7 +512,9 @@ class StateMachineController extends RiveAnimationController }); } } - hitShapeLookup.values.toList().forEach(hitComponents.add); + + // hitShapeLookup.values.toList().forEach(hitComponents.add); + hitShapeLookup.values.forEach(hitComponents.add); _artboard = core as RuntimeArtboard; @@ -609,31 +611,34 @@ class StateMachineController extends RiveAnimationController _reportedEvents.clear(); _reportedNestedEvents.clear(); - var listeners = stateMachine.listeners.whereType(); - listeners.forEach((listener) { + // var listeners = stateMachine.listeners.whereType(); + // stateMachine.listeners.whereType().forEach((listener) { + for (final listener in stateMachine.listeners.whereType()) { var listenerTarget = artboard?.context.resolve(listener.targetId); if (listener.listenerType == ListenerType.event) { // Handle events from this artboard if it is the target if (listenerTarget == artboard) { - events.forEach((event) { + // events.forEach((event) { + for (final event in events) { if (listener.eventId == event.id) { listener.performChanges(this, Vec2D(), Vec2D()); } - }); + }//); } else { // Handle events from nested artboards nestedEvents.forEach((targetId, eventList) { if (listener.targetId == targetId) { - eventList.forEach((nestedEvent) { + // eventList.forEach((nestedEvent) { + for (final nestedEvent in eventList) { if (listener.eventId == nestedEvent.id) { listener.performChanges(this, Vec2D(), Vec2D()); } - }); + }//); } }); } } - }); + }//); var riveEvents = []; @@ -643,9 +648,10 @@ class StateMachineController extends RiveAnimationController } riveEvents.add(RiveEvent.fromCoreEvent(event)); } - _eventListeners.toList().forEach((listener) { + // _eventListeners.toList().forEach((listener) { + for (final listener in _eventListeners) { riveEvents.forEach(listener); - }); + }//); } } diff --git a/lib/src/rive_core/text/text.dart b/lib/src/rive_core/text/text.dart index a5f1771b..ea95ed85 100644 --- a/lib/src/rive_core/text/text.dart +++ b/lib/src/rive_core/text/text.dart @@ -1,4 +1,4 @@ -import 'dart:math'; +import 'dart:math' hide log; import 'dart:ui'; import 'package:rive/src/generated/text/text_base.dart'; @@ -76,7 +76,9 @@ class Text extends TextBase with TextStyleContainer implements Sizable { // Shapes that should be cleaned before next shaping call. final List _cleanupShapes = []; BreakLinesResult? _lines; - // TextShapeResult? get shape => _shape; + + /// STOKANAL-FORK-EDIT: exposing + TextShapeResult? get shape => _shape; BreakLinesResult? get lines => _lines; // Used by text effectors. @@ -263,8 +265,13 @@ class Text extends TextBase with TextStyleContainer implements Sizable { } final List _renderStyles = []; + + /// STOKANAL-FORK-EDIT: exposing + List get renderStyles => _renderStyles; + Size _measuredSizeMax = Size.zero; Size _measuredSize = Size.zero; + Size _measure(Size maxSize) { if (_measuredSizeMax == maxSize) { return _measuredSize; @@ -364,6 +371,9 @@ class Text extends TextBase with TextStyleContainer implements Sizable { min(maxSize.height, bounds.height.ceilToDouble())); } + /// STOKANAL-FORK-EDIT: expose method + void buildRenderStyles() => _buildRenderStyles(); + void _buildRenderStyles() { var lines = _lines; var shape = _shape; @@ -669,6 +679,13 @@ class Text extends TextBase with TextStyleContainer implements Sizable { return; } + /// STOKANAL-FORK-EDIT: logging + // if (text == 'F' && Random().nextDouble() < 0.01) { + // log('TEXT DRAW F > ${hashCode} lines=${_lines?.length} shape=${_shape!=null} styles=${_renderStyles.length} runs=${runs.map((r) => '${r.name}=${r.text}').join(",")}'); + // } else if (text == 'C' && Random().nextDouble() < 0.01) { + // log('TEXT DRAW C > ${hashCode} lines=${_lines?.length} shape=${_shape!=null} styles=${_renderStyles.length} runs=${runs.map((r) => '${r.name}=${r.text}').join(",")}'); + // } + if (!clip(canvas)) { canvas.save(); } diff --git a/lib/src/rive_core/text/text_style.dart b/lib/src/rive_core/text/text_style.dart index d47d64da..e58eef8f 100644 --- a/lib/src/rive_core/text/text_style.dart +++ b/lib/src/rive_core/text/text_style.dart @@ -56,10 +56,10 @@ class TextVariationHelper extends Component { class TextStyle extends TextStyleBase with ShapePaintContainer, FileAssetReferencer { - final Set _referencers = {}; + final Set _referencers = HashSet();//{}; Text? get text => parent as Text?; - final Set _variations = {}; - final Set _features = {}; + final Set _variations = HashSet();//{}; + final Set _features = HashSet();//{}; Iterable get variations => _variations; Iterable get features => _features; @@ -133,7 +133,8 @@ class TextStyle extends TextStyleBase _variationHelper?.buildDependencies(); } - void removeVariations() => _variations.toSet().forEach(context.removeObject); + // void removeVariations() => _variations.toSet().forEach(context.removeObject); + void removeVariations() => _variations.forEach(context.removeObject); @override set asset(FontAsset? value) { diff --git a/lib/src/rive_core/text/text_style_container.dart b/lib/src/rive_core/text/text_style_container.dart index b60336ab..838f6ff0 100644 --- a/lib/src/rive_core/text/text_style_container.dart +++ b/lib/src/rive_core/text/text_style_container.dart @@ -10,7 +10,7 @@ import 'package:rive_common/utilities.dart'; /// file-wide styles by making them owned by an [Artboard] or [Backboard]. abstract class TextStyleContainer { int _nextShaperId = 0; - final Set styles = {}; + final Set styles = {}; // preserve order final HashMap _styleLookup = HashMap(); // TextStyle? styleFromShaperId(int id) => _styleLookup[id]; diff --git a/lib/src/rive_core/transform_component.dart b/lib/src/rive_core/transform_component.dart index a4873389..aa51ad9e 100644 --- a/lib/src/rive_core/transform_component.dart +++ b/lib/src/rive_core/transform_component.dart @@ -91,7 +91,7 @@ abstract class TransformComponent extends TransformComponentBase { Mat2D.copy(worldTransform, transform); } - if (_constraints.isNotEmpty) { + if (_constraints.length > 0) { for (final constraint in _constraints) { constraint.constrain(this); } @@ -225,11 +225,12 @@ abstract class TransformComponent extends TransformComponentBase { } // In the runtime, we have to iterate the dependents - dependents.forEach((element) { + // dependents.forEach((element) { + for (final element in dependents) { if (element is TransformComponent) { element.markDirtyIfConstrained(); } - }); + }//); return true; } diff --git a/lib/src/rive_file.dart b/lib/src/rive_file.dart index fbd879dc..a2abea70 100644 --- a/lib/src/rive_file.dart +++ b/lib/src/rive_file.dart @@ -355,9 +355,8 @@ class RiveFile { // TODO: in the next major version add an assert here to make this a // requirement if (!_initializedText) { - debugPrint('''Rive: RiveFile.import called before RiveFile.initialize() - -Consider calling `await RiveFile.initialize()` before using `RiveFile.import`'''); + /// STOKANAL-FORK-EDIT + // debugPrint('''Rive: RiveFile.import called before RiveFile.initialize(). Consider calling `await RiveFile.initialize()` before using `RiveFile.import`'''); } var reader = BinaryReader(bytes); diff --git a/lib/src/runtime_artboard.dart b/lib/src/runtime_artboard.dart index ca9594a3..bc0760d5 100644 --- a/lib/src/runtime_artboard.dart +++ b/lib/src/runtime_artboard.dart @@ -1,3 +1,7 @@ +import 'dart:collection'; +import 'dart:developer'; + +import 'package:collection/collection.dart'; import 'package:flutter/scheduler.dart'; import 'package:rive/rive.dart'; import 'package:rive/src/core/core.dart'; @@ -99,9 +103,9 @@ class RuntimeArtboard extends Artboard implements CoreContext { final List _objects = []; Iterable get objects => _objects; - final Set _needDependenciesBuilt = {}; + final Set _needDependenciesBuilt = HashSet();//{}; - // Indicates if this artboard is playing or paused + /// Indicates if this artboard is playing or paused bool _isPlaying = true; @override @@ -109,6 +113,13 @@ class RuntimeArtboard extends Artboard implements CoreContext { object?.context = this; object?.id = _objects.length; + // if (object is LinearAnimation && object.logging) { + // log('ADD LINEAR-ANIMATION > $object'); + // } + // if (object is KeyedObject && object.logging) { + // log('ADD KEYED-OBJECT > $object'); + // } + _objects.add(object); return object; } @@ -214,8 +225,13 @@ class RuntimeArtboard extends Artboard implements CoreContext { } object?.onAddedDirty(); } - animations.forEach(artboard.animations.add); - for (final object in artboard.objects.toList(growable: false)) { + + // animations.forEach(artboard.animations.add); + for (var a in animations) { + artboard.animations.add(a); + } + + for (final object in artboard.objects) { //.toList(growable: false)) { if (object == null) { continue; } @@ -223,10 +239,33 @@ class RuntimeArtboard extends Artboard implements CoreContext { InternalCoreHelper.markValid(object); } artboard.clean(); + + // dump(); + return artboard; } + /// STOKANAL-FORK-EDIT: Reuse this object for every animation + void dump() { + log(toString()); + log(objects + .map((o) => o.runtimeType) + .groupListsBy((o) => o) + .entries + .sorted((e1, e2) => e2.value.length - e1.value.length) + .map((e) => '${e.key}: ${e.value.length}') + .join('\n')); + } + + /// STOKANAL-FORK-EDIT: Reuse this object for every animation + @override + String toString() { + // LinearAnimation.dump(); // uncomment to dump animations + return 'RuntimeArtboard[$name ${objects.length}]'; + } + void addNestedEventListener(StateMachineController controller) { + activeNestedArtboards.forEach((artboard) { if (artboard.mountedArtboard is RuntimeMountedArtboard) { (artboard.mountedArtboard as RuntimeMountedArtboard).eventCallback = diff --git a/lib/src/runtime_event.dart b/lib/src/runtime_event.dart index 113c6322..ab9593ad 100644 --- a/lib/src/runtime_event.dart +++ b/lib/src/runtime_event.dart @@ -1,3 +1,5 @@ +import 'dart:collection'; + import 'package:flutter/widgets.dart'; import 'package:rive/src/rive_core/custom_property_boolean.dart'; import 'package:rive/src/rive_core/custom_property_number.dart'; @@ -28,7 +30,7 @@ class RiveEvent { }); factory RiveEvent.fromCoreEvent(Event event) { - final Map properties = {}; + final Map properties = HashMap();//{}; for (final property in event.customProperties) { dynamic value; switch (property.coreType) { diff --git a/lib/src/runtime_mounted_artboard.dart b/lib/src/runtime_mounted_artboard.dart index 7553fdf5..36937414 100644 --- a/lib/src/runtime_mounted_artboard.dart +++ b/lib/src/runtime_mounted_artboard.dart @@ -1,3 +1,5 @@ +import 'dart:collection'; + import 'package:flutter/rendering.dart'; import 'package:rive/src/controllers/state_machine_controller.dart'; import 'package:rive/src/core/core.dart'; @@ -19,11 +21,11 @@ abstract class RuntimeEventReporter { class RuntimeMountedArtboard extends MountedArtboard { NestedArtboard nestedArtboard; final RuntimeArtboard artboardInstance; - final Set _runtimeEventListeners = {}; + final Set _runtimeEventListeners = HashSet();//{}; Size originalArtboardInstanceSize = const Size(0, 0); Set get controllers => - _runtimeEventListeners.whereType().toSet(); + HashSet.of(_runtimeEventListeners.whereType()); // The callback used for bubbling events up from nested artboards Function(Event, NestedArtboard)? eventCallback; diff --git a/lib/src/widgets/rive_animation.dart b/lib/src/widgets/rive_animation.dart index c8d61775..90f0a2c2 100644 --- a/lib/src/widgets/rive_animation.dart +++ b/lib/src/widgets/rive_animation.dart @@ -233,6 +233,21 @@ class RiveAnimationState extends State { _init(await _loadRiveFile()); } + /// STOKANAL-FORK-EDIT: start + /// This is a workaround to allow for embedded Rive animations. It hacks the Flutter State flow. + // @override + // RiveAnimation get widget => _widget??super.widget; + // RiveAnimation? _widget; + // @override + // bool get mounted => (_widget != null) ? true : super.mounted; + // @override + // void setState(VoidCallback fn) => (_widget != null) ? fn() : super.setState(fn); + // Future init(RiveAnimation widget) async { + // _widget = widget; + // initState(); + // } + /// STOKANAL-FORK-EDIT: end + /// Loads the correct Rive file depending on [widget.src] Future _loadRiveFile() { switch (widget.src) { @@ -296,9 +311,10 @@ class RiveAnimationState extends State { } // Clear current local controllers. - _controllers.forEach((c) { + // _controllers.forEach((c) { + for (final c in _controllers) { c.dispose(); - }); + }//); _controllers.clear(); final artboard = (widget.artboard != null diff --git a/pubspec.yaml b/pubspec.yaml index df07780c..3e47ccf0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,15 +3,20 @@ version: 0.13.20 homepage: https://rive.app description: Rive 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 + +publish_to: none # STOKANAL-FORK-EDIT: added to include stokanal path dependency + topics: - animation - ui - effects - widgets - widget + - environment: sdk: ">=2.17.0 <4.0.0" flutter: ">=2.5.0" + dependencies: collection: ^1.15.0 flutter: @@ -22,8 +27,15 @@ dependencies: meta: ^1.3.0 plugin_platform_interface: ^2.0.2 rive_common: 0.4.15 + + # STOKANAL-FORK-EDIT: added stokanal + stokanal: + path: ../stokanal-flutter/ + dev_dependencies: flutter_test: sdk: flutter mocktail: - path: ^1.8.3 \ No newline at end of file + path: ^1.8.3 + +# see STOKANAL-FORK-EDIT for edits against the fork \ No newline at end of file diff --git a/test/rive_animation_test.dart b/test/rive_animation_test.dart index 7d523995..b871acf4 100644 --- a/test/rive_animation_test.dart +++ b/test/rive_animation_test.dart @@ -1,3 +1,5 @@ +import 'dart:collection'; + import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; @@ -269,7 +271,7 @@ void main() { riveFile.mainArtboard, 'State Machine 1'); expect(controller, isNotNull); - Set receivedEvents = {}; + Set receivedEvents = HashSet();//{}; controller!.addEventListener((event) { receivedEvents.add(event.name); }); @@ -316,7 +318,7 @@ void main() { riveFile.mainArtboard, 'State Machine 1'); expect(controller, isNotNull); - Set receivedEvents = {}; + Set receivedEvents = HashSet();//{}; controller!.addEventListener((event) { receivedEvents.add(event.name); });