diff --git a/lib/src/core/core.dart b/lib/src/core/core.dart index 6d58162..8b297fa 100644 --- a/lib/src/core/core.dart +++ b/lib/src/core/core.dart @@ -11,6 +11,9 @@ export 'package:rive/src/core/importers/linear_animation_importer.dart'; export 'package:rive/src/core/importers/keyed_object_importer.dart'; export 'package:rive/src/core/importers/keyed_property_importer.dart'; export 'package:rive/src/core/importers/state_machine_importer.dart'; +export 'package:rive/src/core/importers/state_machine_layer_importer.dart'; +export 'package:rive/src/core/importers/layer_state_importer.dart'; +export 'package:rive/src/core/importers/state_transition_importer.dart'; typedef PropertyChangeCallback = void Function(dynamic from, dynamic to); typedef BatchAddCallback = void Function(); diff --git a/lib/src/core/importers/layer_state_importer.dart b/lib/src/core/importers/layer_state_importer.dart new file mode 100644 index 0000000..55f52cc --- /dev/null +++ b/lib/src/core/importers/layer_state_importer.dart @@ -0,0 +1,16 @@ +import 'package:rive/src/core/core.dart'; +import 'package:rive/src/rive_core/animation/layer_state.dart'; +import 'package:rive/src/rive_core/animation/state_transition.dart'; + +class LayerStateImporter extends ImportStackObject { + final LayerState state; + LayerStateImporter(this.state); + + void addTransition(StateTransition transition) { + state.context.addObject(transition); + transition.stateFrom = state; + } + + @override + void resolve() {} +} diff --git a/lib/src/core/importers/state_machine_layer_importer.dart b/lib/src/core/importers/state_machine_layer_importer.dart new file mode 100644 index 0000000..27b440e --- /dev/null +++ b/lib/src/core/importers/state_machine_layer_importer.dart @@ -0,0 +1,38 @@ +import 'package:rive/src/core/core.dart'; +import 'package:rive/src/rive_core/animation/layer_state.dart'; +import 'package:rive/src/rive_core/animation/state_machine_layer.dart'; + +class StateMachineLayerImporter extends ImportStackObject { + final StateMachineLayer layer; + StateMachineLayerImporter(this.layer); + + final List importedStates = []; + + void addState(LayerState state) { + importedStates.add(state); + // Here the state gets assigned a core (artboard) id. + layer.context.addObject(state); + layer.internalAddState(state); + } + + @override + void resolve() { + for (final state in importedStates) { + for (final transition in state.transitions) { + // At import time the stateToId is an index relative to the entire layer + // (which state in this layer). We can use that to find the matching + // importedState and assign back the core id that will resolve after the + // entire artboard imports. + assert(transition.stateToId >= 0 && + transition.stateToId < importedStates.length); + transition.stateToId = importedStates[transition.stateToId].id; + + // As an alternative way to do this, in the future we could consider + // just short-circuiting the reference here. We're avoiding this for now + // to keep shared code between the editor and runtime more consistent. + + // transition.stateTo = importedStates[transition.stateToId]; + } + } + } +} diff --git a/lib/src/core/importers/state_transition_importer.dart b/lib/src/core/importers/state_transition_importer.dart new file mode 100644 index 0000000..60ebde3 --- /dev/null +++ b/lib/src/core/importers/state_transition_importer.dart @@ -0,0 +1,15 @@ +import 'package:rive/src/core/core.dart'; +import 'package:rive/src/rive_core/animation/state_transition.dart'; +import 'package:rive/src/rive_core/animation/transition_condition.dart'; + +class StateTransitionImporter extends ImportStackObject { + final StateTransition transition; + StateTransitionImporter(this.transition); + + void addCondition(TransitionCondition condition) { + transition.internalAddCondition(condition); + } + + @override + void resolve() {} +} diff --git a/lib/src/rive_core/animation/layer_state.dart b/lib/src/rive_core/animation/layer_state.dart index 6c521f6..8705fe1 100644 --- a/lib/src/rive_core/animation/layer_state.dart +++ b/lib/src/rive_core/animation/layer_state.dart @@ -1,3 +1,5 @@ +import 'package:rive/src/core/core.dart'; +import 'package:rive/src/rive_core/animation/state_machine_layer.dart'; import 'package:rive/src/rive_core/animation/state_transition.dart'; import 'package:rive/src/generated/animation/layer_state_base.dart'; export 'package:rive/src/generated/animation/layer_state_base.dart'; @@ -23,4 +25,15 @@ abstract class LayerState extends LayerStateBase { void onRemoved() { super.onRemoved(); } + + @override + bool import(ImportStack stack) { + var importer = + stack.latest(StateMachineLayerBase.typeKey); + if (importer == null) { + return false; + } + importer.addState(this); + return super.import(stack); + } } diff --git a/lib/src/rive_core/animation/state_machine_component.dart b/lib/src/rive_core/animation/state_machine_component.dart index c7db867..9741300 100644 --- a/lib/src/rive_core/animation/state_machine_component.dart +++ b/lib/src/rive_core/animation/state_machine_component.dart @@ -1,4 +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/generated/animation/state_machine_component_base.dart'; export 'package:rive/src/generated/animation/state_machine_component_base.dart'; @@ -38,4 +39,15 @@ abstract class StateMachineComponent extends StateMachineComponentBase { machineComponentList(stateMachine).remove(this); } } + + @override + bool import(ImportStack importStack) { + var importer = + importStack.latest(StateMachineBase.typeKey); + if (importer == null) { + return false; + } + importer.addMachineComponent(this); + return super.import(importStack); + } } diff --git a/lib/src/rive_core/animation/state_machine_layer.dart b/lib/src/rive_core/animation/state_machine_layer.dart index 5c5d24f..10830a7 100644 --- a/lib/src/rive_core/animation/state_machine_layer.dart +++ b/lib/src/rive_core/animation/state_machine_layer.dart @@ -1,7 +1,11 @@ import 'dart:collection'; +import 'package:rive/src/rive_core/animation/any_state.dart'; +import 'package:rive/src/rive_core/animation/entry_state.dart'; +import 'package:rive/src/rive_core/animation/exit_state.dart'; import 'package:rive/src/rive_core/animation/layer_state.dart'; import 'package:rive/src/rive_core/animation/state_machine.dart'; import 'package:rive/src/rive_core/animation/state_machine_component.dart'; +import 'package:rive/src/generated/animation/any_state_base.dart'; import 'package:rive/src/generated/animation/state_machine_layer_base.dart'; export 'package:rive/src/generated/animation/state_machine_layer_base.dart'; @@ -17,4 +21,19 @@ class StateMachineLayer extends StateMachineLayerBase { machine?.layers; @override void onAdded() {} + bool internalAddState(LayerState state) { + assert(state != null); + switch (state.coreType) { + case AnyStateBase.typeKey: + _anyState = state; + break; + case ExitStateBase.typeKey: + _exitState = state; + break; + case EntryStateBase.typeKey: + _entryState = state; + break; + } + return true; + } } diff --git a/lib/src/rive_core/animation/state_transition.dart b/lib/src/rive_core/animation/state_transition.dart index 1fb424a..0a17ed5 100644 --- a/lib/src/rive_core/animation/state_transition.dart +++ b/lib/src/rive_core/animation/state_transition.dart @@ -8,6 +8,7 @@ export 'package:rive/src/generated/animation/state_transition_base.dart'; class StateTransition extends StateTransitionBase { final StateTransitionConditions conditions = StateTransitionConditions(); LayerState stateTo; + LayerState stateFrom; @override void onAdded() {} @override @@ -23,6 +24,17 @@ class StateTransition extends StateTransitionBase { } bool get isDisabled => (flags & StateTransitionFlags.disabled) != 0; + @override + bool import(ImportStack importStack) { + var importer = + importStack.latest(LayerStateBase.typeKey); + if (importer == null) { + return false; + } + importer.addTransition(this); + return super.import(importStack); + } + bool internalAddCondition(TransitionCondition condition) { if (conditions.contains(condition)) { return false; diff --git a/lib/src/rive_core/animation/transition_condition.dart b/lib/src/rive_core/animation/transition_condition.dart index 9230b66..19875e5 100644 --- a/lib/src/rive_core/animation/transition_condition.dart +++ b/lib/src/rive_core/animation/transition_condition.dart @@ -1,4 +1,6 @@ +import 'package:rive/src/core/core.dart'; import 'package:rive/src/rive_core/animation/state_machine_input.dart'; +import 'package:rive/src/rive_core/animation/state_transition.dart'; import 'package:rive/src/generated/animation/transition_condition_base.dart'; export 'package:rive/src/generated/animation/transition_condition_base.dart'; @@ -33,4 +35,15 @@ abstract class TransitionCondition extends TransitionConditionBase { void onAddedDirty() { input = inputId == null ? null : context.resolve(inputId); } + + @override + bool import(ImportStack importStack) { + var importer = importStack + .latest(StateTransitionBase.typeKey); + if (importer == null) { + return false; + } + importer.addCondition(this); + return super.import(importStack); + } } diff --git a/lib/src/rive_file.dart b/lib/src/rive_file.dart index 618f1d0..60560d4 100644 --- a/lib/src/rive_file.dart +++ b/lib/src/rive_file.dart @@ -2,9 +2,14 @@ import 'dart:collection'; import 'dart:typed_data'; import 'package:rive/src/core/field_types/core_field_type.dart'; +import 'package:rive/src/generated/animation/animation_state_base.dart'; +import 'package:rive/src/generated/animation/any_state_base.dart'; +import 'package:rive/src/generated/animation/entry_state_base.dart'; +import 'package:rive/src/generated/animation/exit_state_base.dart'; import 'package:rive/src/generated/animation/keyed_property_base.dart'; import 'package:rive/src/generated/animation/state_machine_base.dart'; import 'package:rive/src/rive_core/animation/keyed_property.dart'; +import 'package:rive/src/rive_core/animation/layer_state.dart'; import 'package:rive/src/rive_core/animation/state_machine.dart'; import 'package:rive/src/rive_core/component.dart'; import 'package:rive/src/rive_core/runtime/runtime_header.dart'; @@ -72,6 +77,7 @@ class RiveFile { } ImportStackObject stackObject; + var stackType = object.coreType; switch (object.coreType) { case ArtboardBase.typeKey: stackObject = ArtboardImporter(object as RuntimeArtboard); @@ -96,9 +102,14 @@ class RiveFile { break; } case StateMachineBase.typeKey: - stackObject = StateMachineImporter(object as StateMachine); - // stackObject = _LinearAnimationStackObject(object as - // LinearAnimation); helper = _AnimationImportHelper(); + stackObject = StateMachineImporter(object as StateMachine); + break; + case EntryStateBase.typeKey: + case AnyStateBase.typeKey: + case ExitStateBase.typeKey: + case AnimationStateBase.typeKey: + stackObject = LayerStateImporter(object as LayerState); + stackType = LayerStateBase.typeKey; break; default: if (object is Component) { @@ -107,7 +118,7 @@ class RiveFile { break; } - importStack.makeLatest(object.coreType, stackObject); + importStack.makeLatest(stackType, stackObject); if (object?.import(importStack) ?? true) { switch (object.coreType) {