Menu

Effect Interruption and Reversal

SourceForge Editorial Staff

Gumbo Effect Interruption and Reversal - Functional and Design Specification


Glossary


Reversal: In the context of this spec, 'reversal' means the ability for transition effects to reverse and play backwards. This includes the capability of being able to declare a transition as being reversible (so that developers do not have to declare both directions explicitly) as well as the ability for a transition to stop and reverse on the fly, when running back to the state they were animating from.

Summary and Background


One of the more difficult aspects of using transitions in Flex is that interrupting transitions and going to different states can cause disruptive behavior. Because Flex cannot currently play multiple effects simultaneously (or, to be more specific and correct, cannot play multiple effects that operate on the same targets/properties without artifacts), the transition engine simply ends any currently-running transition effect before launching the new ones. The process of ending the previous transition effect causes the effect to snap the targets to their end locations, which causes sudden and disturbing movement before the new animation begins.

The purpose of this feature is to enable more functionality and API that enables transitions to smoothly move between different transition effects.

Usage Scenarios


Users could set properties on transitions that tell the system what behavior they should have at runtime. For example, a property of 'autoReverse' might be used to denote that a transition should reverse on the fly when its reverse transition interrupts it.

Detailed Description


In the case of reversing, or playing new transition effects that are returning to the state currently being animated from (a common occurrence), it should be possible to stop the current transition where it is and start the new, reversing transition from that point.

It should also be possible to move more smoothly between separate transitions, even if they are not reversals of each other. For example, if there is a transition playing between states A and B and a user action causes a change to state C, then instead of ending the first transition (which places it in state B), we could stop the transition effect where it is and start the transition to C from that point. This could be optional behavior, as determined by some code-settable property of the transition.

It should also be easier to declare a transition as being 'reversible', which would save code and effort from declaring multiple transitions that are simply inverses of each other. Currently, when you want to declare a transition (e.g., <fade>) from state A to B and the same/opposite transition from B to A, you have to declare two separate transitions, each with the same (or opposite) innards. The SDK should make it easier to declare a transition as being reversible, which would denote that when there is a state change in the opposite direction to that declared for the transition, then we would simply play this same transition in reverse.</fade>

API Description


Most of this feature is implemented under the hood: tracking the states being transitioned from/to, figuring how how much time has elapsed on current transitions and how to fast-forward to the appropriate place in the new transition, etc. All of the API necessary is to enable one of two things:

  • User-settable behavior: users should be able to opt in or out of the automatic reversing behavior that we are enabling, and the property on Transition allows them to do that
  • Timing data and functionality: In order to calculate how much time has elapsed in any given effect, it is necessary to get an accurate reading of how long the effect should run for and how long it has been running. Additionally, in order to tell an effect to start playing at a certain point, we need the ability to set the play time. some of the functions below are necessary to provide all of this functionality.

Addition to mx.states.Transition:

    /**
     *  Whether the transition should automatically reverse itself 
     *  when the opposite state transition begins playing.
     *
     *  <p>Flex does not currently play multiple transitions simultaneously.
     *  This means that when a new state transition occurs, if there
     *  is already one playing it is stopped by calling <code>end()</code>
     *  on it, which snaps it to its end values. The new transition
     *  then starts playing from that state.</p>
     * 
     *  <p>The <code>autoReverse</code> flag allows the developer to
     *  control whether the default snap-to-end behavior occurs, or whether,
     *  instead, the previous effect is stopped in place and the new
     *  effect is played from that intermediate state instead. Internally,
     *  the transition code calculates how much of the previous effect
     *  has been played and then plays the next effect for the inverse of that
     *  time.</p>
     * 
     *  <p>This flag is only checked when the new transition is going in the
     *  exact opposite direction of the currently playing one. That is, if
     *  a transition is playing between states A and B and then a transition
     *  to return to A is started, this flag will be checked. But if the
     *  application is going from state A to B and a transition to state C is
     *  started, then the default behavior of snapping to the end of the A->B
     *  transition, then playing the B->C transition will occur.</p>
     * 
     *  @default false 
     */
    public var autoReverse:Boolean = false;

Additions to Effect and EffectInstance:

    /**
     * Sets the current time of an effect. Seek may be used to
     * fast-forward or reverse to a particular point in time in an effect.
     * 
     * @param seekTime Number of milliseconds that the effect should
     * play at. This number should be between 0 and the duration of the
     * effect.
     * 
     * @see #duration
     */
    function seek(seekTime:Number):void;

    /**
     *  Current position in time of the effect.
     *  This property has a value between 0 and the actual duration 
     *  (which includes the value of the <code>startDelay</code>, 
     *  <code>repeatCount</code>, and <code>repeatDelay</code> properties).
     */
    function get playheadTime():Number;

In CompositeEffect (and overridden in Parallel and Sequence):

    /**
     * Returns the duration of this effect as defined by the duration of
     * all child effects. This takes into account the startDelay and repetition
     * info for all child effects, along with their durations, and returns the
     * appropriate result.
     */
    public function get compositeDuration():Number{}

B Features


Interruption behavior

Although 'interruption' is part of this feature, the most important part at first is being able to reverse animations on the fly. Figuring out what to do to interrupt one transition and then start another one is more complicated, and involves more options. This puts it on the B list for me: I'd like to get to it, but there are probably more pressing features for Flex that I need to handle first.

Were I to tackle interruption in general, I would probably provide various options, selectable by a property on the transition. For example, in discussion with Ely, here are some options that have come up: - The current behavior (jump to the end of the previous transition, play the new one from there) - Stop&play (stop at the current point of the previous transition and play the new one from there) - autoReverse (the A feature described above, specific to cases where the new transition is the reverse of the previous one) - forceComplete (finish the previous transition, then possibly play the next transition from that point, unless another transition occurred in the meantime)

Note to self: One of the hold-ups on implementing this B feature is the interaction of transitions and state values. Currently, states without explicit values for properties will derive those values on the fly from whatever the property value is. This means that if we short-circuit a transition, such as stopping it in place to take on one of the behaviors above, then we will essentially clobber the values of properties that have no explicit declaration for that state. If there is a simple workaround for this situation, that would simplify this part of the feature.

Reversible transitions

Currently, a user must declare reverse transitions explicitly. If they want a <move> when going from state1 to state2 and the same effect when going from state2 to state1, they must supply two transitions that look exactly the same except for the fromtState/toState properties on Transition. For more complicated effects, like a Parallel effect with many effect children, they must figure out the reverse order for the effects and create a reversed transition appropriately.</move>

The SDK could figure this out for the user, making it necessary for them to only declare one direction and then, through the use of some transition flag presumably (e.g., <transition reversible="true">), tell us to calculate the inverse transition for them. Then, when we encounter a state-state transition that is the reverse of one declared, we will use this calculated inverse automatically.</transition>

Although it is possible for the SDK to do this, it is not a simple task, thus this is a B Feature as there are probably more pressing feature to implement (at least there is a workaround for this feature; developers continue to explicitly declare the reverse transitions they require). Note, for example, that it is not as simple as just playing a transition in reverse: you still want each atomic effect to play from/to the states in question, and not to play in reverse from the "to" state to the 'from" state. This complicates the implementation since we can't just play stuff backwards; we have to take different approaches in different situations.

It is worth noting some of the elements that would have to be addressed in implementing this feature:

  • An atomic effect (not Parallel or Sequence) would:
    • ignore its startDelay (more on this later, in composite effects)
    • switch the start/end values for any hard-coded values
    • grab any other values as usual from states or from the target
  • A Parallel effect would:
    • insert new startDelay for any child effect whose total duration did not equal the compositeDuration of the Parallel effect (note that the real startDelay of the effects will be ignored. Either create a new effect with this new startDelay (or none), or find some other way to delay launching the child effect)
    • play each child effect in reverse, according to the rules here (not playReversed(), but reversing only hardcoded values and child start orders/times)
  • A Sequence effect would:
    • Play its childSet in reverse order
    • startDelays would be ignored, except that these would become startDelays on the previous/next child effects, to put the same buffer between them in reverse that they had going forward

Examples and Usage


An example of two Parallel transition effects which reverse on the fly when opposite state changes occur mid-transition:

        <Transition fromState="State1" toState="State2" autoReverse="true">
            <Parallel>
                <FxResize adjustConstraints="true" targets="{<a href="rect4">rect4</a>}" duration="1000"/>
                <FxFade target="{rect5}" duration="300" startDelay="1000"/>
                <FxFade target="{rect6}" duration="300" startDelay="1300"/>
                <FxFade target="{rect7}" duration="300" startDelay="1600"/>
                <FxFade target="{rect8}" duration="300" startDelay="1900"/>
            </Parallel>
        </Transition>

        <Transition fromState="State2" toState="State1" autoReverse="true">
            <Parallel>
                <FxFade target="{rect8}" duration="300"/>
                <FxFade target="{rect7}" duration="300" startDelay="300"/>
                <FxFade target="{rect6}" duration="300" startDelay="600"/>
                <FxFade target="{rect5}" duration="300" startDelay="900"/>
                <FxResize adjustConstraints="true" targets="{<a href="rect4">rect4</a>}" duration="1000" startDelay="1200"/>
            </Parallel>
        </Transition>

Similarly, a Sequence effect that has the same behavior:

        <Transition fromState="State1" toState="State4" autoReverse="true">
            <Sequence>
                <FxResize adjustConstraints="true" targets="{<a href="sequenceRect">sequenceRect</a>}" duration="1000"/>
                <AddAction target="{rect5s}"/>
                <FxFade target="{rect5s}" duration="300"/>
                <AddAction target="{rect6s}"/>
                <FxFade target="{rect6s}" duration="300"/>
                <AddAction target="{rect7s}"/>
                <FxFade target="{rect7s}" duration="300"/>
                <AddAction target="{rect8s}"/>
                <FxFade target="{rect8s}" duration="300"/>
            </Sequence>
        </Transition>
        <Transition fromState="State4" toState="State1" autoReverse="true">
            <Sequence>
                <FxFade target="{rect8s}" duration="300"/>
                <RemoveAction target="{rect8s}" effectEnd="removeEndHandler()"/>
                <FxFade target="{rect7s}" duration="300"/>
                <RemoveAction target="{rect7s}"/>
                <FxFade target="{rect6s}" duration="300"/>
                <RemoveAction target="{rect6s}"/>
                <FxFade target="{rect5s}" duration="300"/>
                <RemoveAction target="{rect5s}"/>
                <FxResize adjustConstraints="true" targets="{<a href="sequenceRect">sequenceRect</a>}" duration="1000"/>
            </Sequence>
        </Transition>

Additional Implementation Details


This initial work on the feature is expected to hit the high points and fix the critical problems in this area. It is possible that later work may be required to round out the feature or add other nice-to-haves. For example, seeking behavior on composite animations is expected to work to the extent necessary for this feature, although there may be bugs in the general functionality of seeking that may not be fixed at this time.

Prototype Work


The basic behavior and API around auto-reversing simple and complex animations is mostly done at this time. The functionality of auto-reversing Parallel animations was done for the alpha release. This exposed some API that has since changed and there were various implementation details that also changed. The new work in i9 includes this capability for Paralle effects, but adds the capability of reversing Sequence animations as well.

The additional work of interrupting effects and playing different transitions (not simple reverses) is not yet prototyped. Some initial work in stopping animations was done, but this approach does not work well with states, so there should probably be a different implementation for robust behavior. Also, the API around interrupting and starting new transitions requires more thought.

Compiler Work


None

Web Tier Compiler Impact


None

Flex Feature Dependencies


None

Backwards Compatibility


Syntax changes

None

Behavior

Action effects need to have zero duration to make composite effect duration calculation correct. This is a behavior change (these effects previously had the default duration), but it is doubtful that anyone ever set or queried this property on the Action effects, since the property was ignored in these Effect subclasses.

Warnings/Deprecation

None

Accessibility


None

Performance


None

Globalization


None

Localization


Compiler Features

None

Framework Features

None

Issues and Recommendations


None

Documentation


None

QA


Capabilities should be tested with both complex (Parallel and Sequence) and simple (non-composite) effects. Ensure that reversing animations start from the same place (or close to it) that the previous transition ended. Note that this feature requires that reversing transitions be of the same overall duration, and be functionally reversals of each other, otherwise the effects may be undesirable.


Related

Wiki: Flex 4

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.