You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

183 lines
6.9 KiB

/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/** \file plAGChannel.h
\brief The animation class for the AniGraph animation system
WHAT'S AG STAND FOR?
AG stands for animation graph. It's a directed acyclic graph of animation data sources and operations.
WHAT'S A CHANNEL?
A channel is a stream of animation data.
A channel is a node in an animation graph.
Animation data can come from anything; keyframes, IK, physics, etc.
Channels are often grouped together using blending nodes.
Blending nodes are also a type of channel.
See where I'm going with this?
HOW IS THIS DIFFERENT FROM PLCONTROLLER?
It's very similar, but it's designed to be extremely lightweight; animation graphs are set up and torn down
quickly and with great frequency. They are not persistent, and their only state (besides cache)
is their interconnectedness.
HOW DO THEY GET SAVED?
Their client must recreate them at read/load time. Since they are stateless, all information necessary
to recreate them is necessarily held by the client.
ARE THEY REFERENCE COUNTED?
No. The entire graph is owned by the creator.
Deleting the top node of a graph deletes the entire graph.
If we decide we want to share subgraphs, we'll add reference counting -- easy since cycles are illegal
HOW DO THEY INTEGRATE WITH PLCONTROLLERS?
Once we decide the animation graph approach is workable and effective, we'll combine the plController
concept with the plAGChannel concept.
Until then, there will be a handful of channel types that adapt controllers into animation graphs.
WHAT DOES "COMBINE" MEAN?
Merging more than one types of animation data into a single output that preserves the value
of both.
WHAT DOES "BLEND" MEAN?
Merging two similar types of animation data using a weight to "fade" from one to the other
WHAT IS ZEROSTATE?
This is a static channel that always returns the value at time zero. It is used as a reference for animation
scaling (amplitude).
WHAT'S AN APPLICATOR?
In order to cut down on the number of derived channel classes for different Value() and Apply() behaviors,
applicators were created. At the end of each graph is an applicator, which specifies what should be done
with the result of a call to Value().
\ingroup Avatar
\ingroup AniGraph
*/
#ifndef PLAGCHANNEL_H
#define PLAGCHANNEL_H
/////////////////////////////////////////////////////////////////////////////////////////
//
// INCLUDES
//
/////////////////////////////////////////////////////////////////////////////////////////
#include "pnFactory/plCreatable.h"
/////////////////////////////////////////////////////////////////////////////////////////
//
// FORWARDS
//
/////////////////////////////////////////////////////////////////////////////////////////
class plAGModifier;
class plAnimTimeConvert;
class plAGChannel;
class plScalarChannel;
/////////////////////////////////////////////////////////////////////////////////////////
//
// DEFINITIONS
//
/////////////////////////////////////////////////////////////////////////////////////////
/** \class plAGChannel
An object that emits data of a specific type. Fundamental building
block of the animation graph. */
class plAGChannel : public plCreatable
{
public:
// -- methods --
/** Default constructor for the base class. */
plAGChannel();
/** Free an allocated name. Does not release any upstream nodes. */
virtual ~plAGChannel();
// AG PROTOCOL
/** Combine the given channel with this channel, allocating and returning
a new node which does the combination. It's up to the caller to
manage the lifetime of the new node. */
virtual plAGChannel * MakeCombine(plAGChannel * channelB);
/** Blend the given channel with this channel, using a third channel (which
must output a float/scalar value) to crossfade between the two.
As the blendChannel varies, the blend will vary. */
virtual plAGChannel * MakeBlend(plAGChannel * channelB, plScalarChannel * blendChannel, int blendPriority);
/** Create a "static clone" of this channel which always returns this channel's
value at time zero. */
virtual plAGChannel * MakeZeroState() = 0;
/** If we're potentially sharing this channel with other plAGMasterMods, we'll
want to insert a channel in the graph for cache info. This function returns
either the cache channel (replacing us) or ourself. */
virtual plAGChannel * MakeCacheChannel(plAnimTimeConvert *atc) { return this; }
/** Create a new channel which converts global time to local time
and attach it downstream from this channel. This allows you to
convert an animation from one timespace to another - critical for
blending.
local-time-animation <-- timescale <-- world-time-animation */
virtual plAGChannel * MakeTimeScale(plScalarChannel *timeSource) = 0;
/** Is the animation moving at the given world time? Takes into account
start/stop messages that haven't been applied yet, ease curves, etc. */
virtual hsBool IsStoppedAt(double wSecs) { return true; }
/** Detach the given channel from our graph. If this is the channel in
question, returns any upstream channels so they can be reattached.
If this is not the channel in question, passes the request upstream
and does any reattachment necessary. */
virtual plAGChannel * Detach(plAGChannel * channel);
/** Return the optimized version of this channel. May be a completely
different channel; will collapse out inactive subgraphs. */
virtual plAGChannel * Optimize(double time);
// \{
/** The name of the channel is used to dynamically attach to sub-parts of an
object. */
virtual const char * GetName() { return fName; };
virtual void SetName(char * name) { fName = name; };
// \}
// PLASMA PROTOCOL
// rtti
CLASSNAME_REGISTER( plAGChannel );
GETINTERFACE_ANY( plAGChannel, plCreatable );
// persistence
virtual void Write(hsStream *stream, hsResMgr *mgr);
virtual void Read(hsStream *s, hsResMgr *mgr);
protected:
const char * fName;
};
#endif PLAGCHANNEL_H