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
183 lines
6.9 KiB
14 years ago
|
/*==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
|