New Effects for Components and Graphics - Functional and Design Specification
Glossary
Animation: A change in value over time. Anyone reading this spec probably already knows this basic concept, but I wanted to call it out specifically because the whole tenet of the approach with this feature is to make our effects more generic, to have them animate 'properties' instead of calling specific functions in specifically-typed target objects.
Summary and Background
A more complete title for this spec might be "Effects for Arbitrary Objects, including the Gumbo Components and FXG Elements" as this feature solves a more general problem than just animating the new components. But it seemed a bit wordy for a spec title.
The current Effect classes in Halo are constrained to operate on UIComponent subclasses, through dependencies on certain properties, specific functions, and general concepts of how UIComponents behave.
In Gumbo, we are introducing the new FXG elements, which are not subclasses of UIComponent, and which therefore will not be able to be targets of the current Effect classes.
Our effects are essentially changing properties on their targets, so there is really nothing inherent in effects that must constrain them to operate solely on UIComponent objects. So why constrain them at all? Instead, let's create an effects structure such that any Effect can be applied generically to any object: old components, new components, our new FXG elements, or any arbitrary object written by us or our developers.
Usage Scenarios
These Effects will be used in all situations that effects are currently used: to change properties in target objects due to either specified settings ("Move from here to there") or implicit settings ("Transition from this state of the target to that state" and "Move the target based on the information in this MoveEvent").
Since the usage of these effects is broader than just new (and old) Flex components, they will also be used in broader situation, such as animating graphics objects and any other arbitrary objects that the user wants to affect.
Detailed Description
This feature is about introducing a new effects infrastructure where effects will subclass a variant of AnimateProperty. But where AnimateProperty animates a single named property on a target, the new FxAnimate base class animates an arbitrary number of properties. The new effects will set values in the targets by simply calling the setter (or setStyle, when the named property is a style instead) for each property.
Setting named properties in this way is what AnimateProperty does (for a single property), but not what the other previous effects do. Instead, they call known functions in the target. For instance, the Move effect calls target.move(x,y). Not only does the current approach require that the target object implement the specific function used by the effect, but it also means that effects are using a parallel system of setting these properties to the system used by other clients of that target.
The new approach will simply set properties on the target object in the usual way. For example, instead of move(x,y), Move will call target["x"] = x and target["y"] = y.
Many of the old effects will be ported over to this system, starting with the core effects considered most useful (such as Move, Resize, and Fade).
For now, we anticipate these effects being new classes; we are not proposing changing the old effects. These new effects should work on both old and new components, so developers will be encouraged to switch to the new effects in general. But in the interest of not breaking applications that still use the old effects, we are not proposing changing the behavior of those classes, but will just let them continue in their current mode while we develop parallel effects. Once we have a working system, we can come back to the question of whether to have new effects or port the behavior back to the old effect classes.
API Description
The new effects will go into the existing mx.effects package, although they will generally have the new "Fx" prefix to distinguish them from the old effects.
Note that triggers do not currently work on the new effects. We should come back to this later to determine whether to retrofit triggers onto these new classes or leave Triggers behind for older components and effects.
In the following classes:
- PropertyValuesHolder is a data structure that holds the multiple properties and from/to values animated by FxAnimate and its subclasses
- FxAnimate is the base class for all new effects. It can be used directly, just as AnimateProperty was before, or indirectly, by using one of the subclasses below.
- The remainder of the classes are the effects subclassing from FxAnimate. These effects specialize behavior and setup for known situations. For example, Move sets up the effect to animate x and y between appropriate values.
- I do not list the effect instance classes apart from FxAnimateInstance, as they are generally implementation details of the factory classes which the developer will usually deal directly with.
PropertyValuesHolder:
FxAnimate and FxAnimateInstance:
FxMove:
FxFade:
FxResize:
Note: The hideChildrenTargets functionality is currently disabled due to an unrelated change to remove the Panel object from the new components and should be re-thought in general
FxRotate:
FxAnimateColor:
This effect is the first (of those listed) to use the interpolator capability of Animation. It internally creates a ColorInterpolator object which it supplies to the underlying Animation so that the from/to colors are interpolated correctly.
CallAction:
All of the effects above subclass from the new FxAnimate class, as opposed to the TweenEffect class that the Halo effects subclass from. The Action effects of Halo subclass directly from Effect (they do not need the animation capabilities of TweenEffect). I am also adding one additional Action effect, CallAction, which also subclasses directly from Effect. The above discussions of FxAnimate do not apply here, but I include this new effect for completeness since it is also new in Gumbo.
Follow-on work from this feature will include other effects (ported over from the old effects or new), and would expose similar API. Examples of future effects include Bitmap effects that will use Pixel Bender shaders to transform before/after bitmaps.
B Features
1) Shorter syntax for triggering effects
It is worth exploring whether we can expose the 'trigger' functionality through a short-hand approach in MXML. The above method (in PropertyAnimator) would mean that callers must start event-based effects with something like this:
We may want to enable this functionality through a more terse syntax (much like the current "Triggers"), where the following MXML could be used in place of the code above:
Note: Triggers are not implemented yet in the new effects, as the syntax and functionality desired are not yet determined.
2) Motion along a path
This is probably a separate feature altogether, but I mention it here for completeness. With the structures described above for associating a property name with a list of values, it becomes possible to use that approach to define more complex motion paths. For example, we could also allow PropertyValuesHolder to have an item that specifies how to interpret the list of values, such as VALUES_CUBIC, and then derive a curved path that the object follows during the animation.
3) Keyframes
As with (2) above, we could allow the values list in PropertyValuesHolder to hold an arbitrary list of values and then supply a list of time values when those values hold true, thus providing a set of keyframes to the effect. I believe this is necessary and desirable functionality in a robust animation system, although it will probably not make this release.
Examples and Usage
Use of the FxMove and FxFade effects above are similar to how they are used today, both from ActionScript and MXML. For example, the FxMove effect could be started automatically by a transition through this MXML code, which automatically takes the from/to parameters from a combination of the state values and the current target location:
You could also specify specific parameters for the effect like this:
You could also have the button manually start the transition like this:
Note that the xFrom/yFrom/etc. attributes of Move (like attributes of other effects) are shorthands for setting the properties/values of the FxAnimate effect superclass directly. This improves the MXML code for these effects, as setting Arrays in MXML ends up in a lot of angle-brackets. Nevertheless, it is possible to do this in MXML for any effect. For example, here is how one would set up a Move-like effect in MXML by using the FxAnimate effect directly:
The FxAnimate class is a bit different than current effects because it allows specification of multiple values through its propertyValuesList property. In ActionScript code, this is what it would look like to animate several properties on a target object simultaneously:
It is generally expected that common effects, especially those instantiated in MXML, would be accessed through subclasses of FxAnimate and would (like FxMove, FxFade, and FxResize) have helper properties that are less verbose to set up than the propertyValuesList property of FxAnimate.
Additional Implementation Details
The trick with this feature is making the mechanisms of transitions and triggers work well with the new effects. So far, the transitions capabilities all work successfully in the new effects. In fact, the new effects handle transitions somewhat more easily than the old effects. For example, FxFade can now fade objects in or out automatically depending on states' alpha, visible, or parented properties; the old effects relied on helper effects such as RemoveChildAction to do this successfully.
Meanwhile, effect triggers do not work on the new effects. To some extent, the problem is made difficultby our more generic approach to setting properties on targets. Previously, we would call specific functions on the targets. These targets could, for example, avoid dispatching events when necessary, which avoided potential recursive situations like triggering a Move effect while changing x and y because of a Move effect. But also, we are considering not implementing triggers simply because there are already ways to achieve that functionality, via transitions and calling play() directly.
Prototype Work
The effects listed above in the "API Description" section are all working and checked in. Some prototype work has been done in the area of effect triggers, should we decide that we do want them to work on the new effects, but otherwise we are simply implementing new effects and functionality as we get to it.
Compiler Work
The B Feature item above, "Shorter syntax for triggering effects" may require some compiler work to turn the terse MXML syntax into the full ActionScript code required.
Web Tier Compiler Impact
None
Flex Feature Dependencies
This feature depends on the "Arbitrary Type Interpolation" feature, specifically to enable FxAnimateColor. That feature is complete and the code is checked in already.
Backwards Compatibility
Syntax changes
These effects will be new classes, so previous effects will not have any API implications. The API for these new effects will differ slightly from the old effects (such as "triggers" going away as a concept on Gumbo components), but again this is for new classes (effects and components), and should not cause a problem with the current APIs.
Warnings/Deprecation
None. "Triggers" will go away with the new effects, but will still work on UIComponent subclasses and the old effects.
Accessibility
N/A - we are just setting properties on accessible components (and other objects), not affecting how that accessibility works
Performance
As with other animation operations, we will need to ensure that performance is good enough to provide a smooth animation experience. This might mean updating the screen after processing Animation events, avoiding unnecessary overhead during animating, and otherwise ensuring lightweight animation.
Globalization
N/A
Localization
Compiler Features
N/A
Framework Features
There will be Errors thrown from bad parameters, but otherwise no use of Strings.
Issues and Recommendations
Trigger functionality: I have done enough prototyping to know how to enable trigger-like functionality for the simple effects of Move and Fade, but I don't know yet whether there are other, harder situations to account for in how these new effects are set up, run, and ended.
Note: Triggers, and whether we want them implemented for these effects, are TBD
I am currently adding these effects as new classes. We could, and maybe should, consider merging this functionality into the existing Effects classes, simply broadening their functionality to work as before and also with new components and arbitrary objects. This merge would involve changing their behavior and API (for example, the new system depends on Animation, not Tween, and the new system sets properties directly without calling functions), so it it's not an easy choice. The tradeoff here is increased and somewhat redundant API vs. potentially altered behavior for existing API.
Documentation
None, other than documenting the new classes and the new use of effects on arbitrary objects.
|
 |