An Action is composed of 1) an Action type, which can be something like
movement, resizing, change in color, etc., and 2) a sequence of dx,
dy offsets that we call a path. Just think of a path as a sequence
of steps in the
-
space.
In a movement Action, the control points or offsets in the associated path define where the AnimObject should next be located. Think of a control point in a path like a frame in a motion picture. In subsequent frames, images have changed location by some small increment. If we iterate the frames in this series, the object appears to move along this path. The length of an Action is the number of offsets its path contains.
Paths are not only used for movement, however. Every Action utilizes its path component to define its exact changes to an object.
Below is the class definition for an Action:
class Action {
public:
Action();
Action(const char *);
Action(const char *, int, double [], double []);
Action(const char *, int);
Action(const char *, MOTION);
Action(const char *, const char *);
Action(const char *, Loc *, Loc *, MOTION);
Action(const char *, Loc *, Loc *, int);
Action(const char *, Loc *, Loc *, double);
~Action();
int Length();
double Deltax();
double Deltay();
Action *Copy();
Action *ChangeType(const char *);
Action *Reverse();
Action *Smooth();
Action *Rotate(int);
Action *Scale(double, double);
Action *Extend(double, double);
Action *Interpolate(double);
Action *Example(Loc *, Loc *);
Action *Iterate(int);
Action *Concatenate(Action *);
Action *Compose(Action *);
};
Quite imposing, isn't it? Well, not really, once you play with it a little.
Basically, there are just lots of different member functions that allow
you to make paths in lots of different ways. When you want a path for movement,
certain functions are especially useful. When you want one for a color
change, others may be helpful. Just remember that down underneath is simply
a type (which is just a character string) and a list of relative offsets.
In all the constructors below (except first), the initial argument
identifies the Action type. This is simply a character string. The types
that we have predefined and designated how AnimObjects will react to them
are ``MOVE,'' ``RESIZE,'' ``VIS,'' ``COLOR,'' ``FILL,'' ``RAISE,'' ``LOWER,''
``ALTER_LL,'' ``ALTER_UR'' and others. Simply designate this string when
you create an Action. Below we described how each of these affects the
different AnimObjects.
MOVE - move the AnimObject along the given path. The first movement of the AnimObject corresponds to the first relative offset in the path. All these relative offsets are with respect to the AnimObject's previous position on the screen.
VIS - switch the visibility of the AnimObject for each offset in the given path. At each offset in the path, if the AnimObject is visible, it will become invisible, and vice-versa.
COLOR - change the AnimObject to the color indicated by the path.
ALTER - change the string shown for a Text AnimObject.
FILL - change the "fill" component of the AnimObject. This works differently for different types of AnimObjects. For rectangles, circles, ellipses, polygons, and pies, this transition alters the AnimObject's fill style value by the x value of the offsets in the path. The x value is simply added in. If the AnimObject's fill value goes below 0.0, it is automatically set back to 0.0. If it goes above 1.0, it is set back to 1.0. Actually, the full range of values between 0.0 and 1.0 is not available. We currently implement 40 different fills that range between the two extremes. For lines, polylines, and splines, the x value of each offset is added to the line's width parameter value, and the y value is added to the line's style parameter value (see AnimObject constructors for information on width and styles). Extreme values are reset to 0.0 and 1.0 as in rectangles and circles.
RESIZE - resize the AnimObject along the path. The various types of AnimObjects each have a ``method'' in which they are resized. Since lines can have positive or negative sizes, they are resized by altering the line's size for each offset in the path. Rectangles can have only positive sizes, so resizing a rectangle corresponds to ``dragging'' the upper right corner of the rectangle along the given path. If one of the rectangle's dimensions would become negative, it is set to 0. Circles are resized by modifying the circle's radius by the amount given in the x component of each offset in the path. On an ellipse, the resize transition adds the x value to the ellipse's x radius and the y value to the y radius. Pies work similarly. For polylines, polygons, and splines the transitions RESIZE1-RESIZE7 modify relative positions of the respective vertex number, plus all others after it in numerical order, by the relative offsets of the path. These are useful, for example, with a forward arrow polyline that has many of its edges compressed down to start. They can subsequently be grown out in all different directions, one at a time. Currently, resizing has no affect on text.
GRAB - the GRAB actions modify polylines, polygons, and splines by altering
the relative position of a particular vertex on the AnimObject (except
the one denoting the AnimObject's position) by the relative offsets of
the path. As opposed to RESIZE, the transitions GRAB1-GRAB7 alter only
one particular vertex in the AnimObject's definition. Think of grabbing
that vertex and swinging it around while all the other points stay anchored.
With a Pie object, the
component modifies the beginning angle of the pie (0.0->1.0 corresponds
to a complete circle) and the
component modifies the delta angle. GRABs have no effect on other AnimObjects.
RAISE - bring the AnimObject to the viewing plane closest to the viewer. The AnimObject's position is not changed, only its relative ordering (top to bottom) with respect to other AnimObjects.
LOWER - push the given AnimObject to the viewing plane farthest from the viewer. The AnimObject's position is not changed, only its relative ordering (top to bottom) with respect to other AnimObjects. It will possibly be obscured by every other AnimObject.
ALTER_LL - this modifies the coordinate value of the lower left corner
of the View by adding the
and
offset values of the Action to it. The AnimObject provided is totally ignored
(but just don't use a Set because the coordinate will be modified for every
member of the Set). This Action is useful to pan and zoom the View window
in synchronization with the animation loop.
ALTER_UR - this modifies the coordinate value of the upper right corner
of the View. Using both the ALTER_LL and ALTER_UR together on the same
path at the same time allows you to pan the View around.
Below is a further explanation of the different Action types and the number of offsets in the path of an Action:
Action(char *type) [0 offsets]NOTE: By itself, this action will do nothing because it has no offsets. You must use AddHead() or AddTail() to add offsets. In fact, if you specify 0 offsets in any other constructor, you get an error message stating that the action is useless.
Action(char *type, char *attribute) [1 offset]Sets the color attribute of any object (COLOR) or the string attribute of a text object (ALTER).
Action(char *type, int offsets)If offsets == 0, see the note at the top.
If offsets
1 with the RAISE or LOWER actions, this action will raise the object to
the front or lower the object to the back.
If offsets
1 with the VIS action, this will cause the visibility of the object to
alternate between visible and invisible. If offsets is even, the object
will end up with the same visibility status it started with. If odd, the
object's visibility status will end up opposite that which it started with.
This constructor can also be used with the MOVE, FILL, RESIZE, GRAB, ALTER_LL, and ALTER_UR actions, but since all the offsets will be null, an action constructed this way won't do anything.
Action(char *type, Loc *from, Loc *to, int offsets) Action(char *type, Loc *from, Loc *to, double distance) [>= 1 offset] Action(char *type, MOTION motion) [20 offsets] Action(char *type, Loc *from, Loc *to, MOTION motion) [20 offsets] Action(char *type, int offsets, double dx[], double dy[])If offsets == 0, see the note at the top.
The first two constructors always create offsets in a straight line. Note that these constructors can also be used with the FILL action.
The next two constructors can produce offsets in a line or a clockwise or counterclockwise pattern, depending on whether motion is STRAIGHT, CLOCKWISE, or COUNTERCLOCKWISE.
The last constructor can have any offsets you provide. Note that it is easier to use one of the other constructors if you want action in a straight line or want the fill pattern to change linearly.
These constructors can also be used with the RAISE, LOWER, and VIS actions,
but since the values of the offsets will be ignored, it's easier to use
the simpler constructor designed for those actions.