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.
430 lines
17 KiB
430 lines
17 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==*/ |
|
#ifndef PLAGANIM_INC |
|
#define PLAGANIM_INC |
|
|
|
/** \file plAGAnim.h |
|
\brief The animation class for the AniGraph animation system |
|
|
|
\ingroup Avatar |
|
\ingroup AniGraph |
|
*/ |
|
#pragma warning(disable: 4786) // don't care if mangled names are longer than 255 characters |
|
|
|
#include "../pnNetCommon/plSynchedObject.h" |
|
#include "hsStlUtils.h" |
|
#include "hsStlSortUtils.h" |
|
|
|
class plTMController; |
|
class hsAffineParts; |
|
class plAnimTimeConvert; |
|
struct hsMatrix44; |
|
class plEmoteAnim; |
|
class plAGApplicator; |
|
class plAGChannel; |
|
|
|
/** \class plAGAnim |
|
This class holds reusable animation data. A single plAGAnim can be instanced |
|
any number of times simultaneously. |
|
In order to use a plAGAnim, you need a plAGMasterMod, which is a special type of |
|
modifier which can be attached to multiple scene objects. A master mod is typically |
|
applied to the root of a scene branch, but there is no requirement that all the scene |
|
objects animated be children. |
|
Each plAGAnim has a number of channels, each of which can animate a single parameter |
|
of a single object. Channels are parametric, i.e. they can carry any data type. |
|
A plAGAnim carries a name for the animation, and each channel is named as well. |
|
Instancing a plAGAnim is done via a plAGAnimInstance. |
|
\sa plAGAnimInstance plAGMasterMod plAGModifier |
|
*/ |
|
class plAGAnim : public plSynchedObject |
|
{ |
|
public: |
|
/** How much of the body does this emote use? This is handy information for |
|
figuring out whether you can, say, wave while sitting down. */ |
|
enum BodyUsage { |
|
kBodyUnknown, |
|
kBodyUpper, |
|
kBodyFull, |
|
kBodyLower, |
|
kBodyMax, |
|
kForceSize = 0xff |
|
}; |
|
|
|
plAGAnim(); |
|
/** Construct with name, start time, and end time (within the max note track) |
|
*/ |
|
plAGAnim(const char *name, double begin, double end); |
|
/** Destruct, freeing the underlying animation data. */ |
|
virtual ~plAGAnim(); |
|
|
|
/** Return the total of number of channels supplied by this animation. |
|
An object being animated by this animation does not have to have this |
|
many channels; any which are not available will be ignored. |
|
This is syntactic sugar: GetApplicatorCount will return the exact |
|
same number, but some code is only interested in the channels and not |
|
the applicators. */ |
|
int GetChannelCount() const; |
|
|
|
/** Return the ith channel of the animation. Ordering is arbitrary but consistent. |
|
It's currently breadth first base on the export algorithm, but don't count on this |
|
remaining true. */ |
|
plAGChannel * GetChannel(int i) const; |
|
|
|
/** Get the name of the channel having the given index. Useful for talking to an |
|
an animation before it is applied and finding out what channels it's going to |
|
affect. */ |
|
virtual const char * GetChannelName(int index); |
|
|
|
/** Get channel by name. This corresponds to the name of the scene object this channel |
|
will be attached to when the animation is applied. |
|
This function is fairly slow and shouldn't be used often. */ |
|
plAGChannel * GetChannel(const char *name) const; |
|
|
|
/** Return the number of applicators held by this animation. An applicator is used |
|
to attach a channel to a sceneobject. */ |
|
int GetApplicatorCount() const; |
|
|
|
/** Return the ith applicator in the channel. |
|
Order is arbitrary but consistent, corresponding to processing order in the exporter. */ |
|
plAGApplicator * GetApplicator(int i) const; // get applicator by index |
|
|
|
/** Add an applicator -- which must have a channel behind it. |
|
Applicators are translator object which take the output of a |
|
channel and apply it to a scene object. */ |
|
int AddApplicator(plAGApplicator * app); |
|
|
|
/** Remove the ith applicator and its associated channel. Existing applicators |
|
will be renumbered. */ |
|
hsBool RemoveApplicator(int appNum); |
|
|
|
/** The name of the animation. This name is used in the avatar manager to reference |
|
animations. Animations are generally indexed by name when they are loaded |
|
by the avatar or from script, but most of the functions which take an animation |
|
name (such as AttachAnimation on the plAGMasterMod) will also take an pointer |
|
to a plAGAnim. */ |
|
virtual const char * GetName() const { return fName; } |
|
|
|
/** Return the length of the animation; end - start. */ |
|
virtual hsScalar GetLength() const { return fEnd - fStart; } |
|
|
|
/** Hacky function to extend the length of the animation to some minimum |
|
length. Does nothing if the animation is already longer than this. */ |
|
void ExtendToLength(hsScalar length); |
|
|
|
/** Return the start time for the beginning of the animation. The animation |
|
contains no data prior to this time. |
|
In practice, this always returns 0.0f and this function may be deprecated. */ |
|
virtual hsScalar GetStart() const { return fStart; } |
|
void SetStart(hsScalar start) { fStart = start; } |
|
|
|
/** Return the end time of the animation. Since start is typically 0, this usually |
|
serves as the length of the animation as well. */ |
|
virtual hsScalar GetEnd() const { return fEnd; } |
|
void SetEnd(hsScalar end) { fEnd = end; } |
|
|
|
|
|
/** Returns true if any applicator on the arg anim tries to use the |
|
same pin (on the same object) as we do. */ |
|
hsBool SharesPinsWith(const plAGAnim *anim) const; |
|
|
|
|
|
// PLASMA PROTOCOL |
|
// rtti |
|
CLASSNAME_REGISTER( plAGAnim ); |
|
GETINTERFACE_ANY( plAGAnim, plSynchedObject ); |
|
|
|
// *** temp hack to manage animation instances |
|
/** Add the animation by name to a global static registry. |
|
This functionality will possibly be added to the resource |
|
manager. */ |
|
static void AddAnim(const char * name, plAGAnim *anim); |
|
/** See if there is an animation with the given name in the |
|
global animation registry. */ |
|
static plAGAnim *FindAnim(const char *name); |
|
/** Remove the given animation from the registry. */ |
|
static hsBool RemoveAnim(const char *name); |
|
/** Clear the animation cache. Used when resetting the client |
|
to a vanilla state, as when clearing the scene while |
|
exporting. */ |
|
static void ClearAnimationRegistry(); |
|
/** Debugging utility. Prints out a list of all the animations |
|
in the registry */ |
|
static void DumpAnimationRegistry(); |
|
|
|
// persistance |
|
virtual void Read(hsStream* stream, hsResMgr* mgr); |
|
virtual void Write(hsStream* stream, hsResMgr* mgr); |
|
|
|
protected: |
|
typedef std::vector<plAGApplicator*> ApplicatorVec; |
|
ApplicatorVec fApps; /// our animation channels |
|
float fBlend; /// requested blend factor |
|
|
|
hsScalar fStart; /// the start time of the beginning of the animation (usually 0) |
|
hsScalar fEnd; /// the end time of the animation |
|
|
|
char *fName; /// the name of our animation |
|
|
|
// ??? Can this be moved to the resource manager? If it can manage an efficient |
|
// string-based namespace per class, we could get rid of this. |
|
typedef std::map<const char *, plAGAnim *, stringISorter> plAnimMap; // |
|
static plAnimMap fAllAnims; /// map of animation names to animations |
|
|
|
typedef std::map<const char *, plEmoteAnim *, stringISorter> plEmoteMap; |
|
static plEmoteMap fAllEmotes; |
|
}; |
|
|
|
/////////////// |
|
// PLATCANIM |
|
/////////////// |
|
|
|
/** \class plATCAnim |
|
The most common subclass of plAGAnim. |
|
Represents an animation with a standard AnimTimeConvert |
|
(i.e. stop/start/loop/etc animation) |
|
*/ |
|
class plATCAnim : public plAGAnim |
|
{ |
|
public: |
|
|
|
|
|
plATCAnim(); |
|
/** Construct with name, start time, and end time (within the max note track) |
|
Default is to start automatically, not loop, with no ease curves. */ |
|
plATCAnim(const char *name, double begin, double end); |
|
/** Destruct, freeing the underlying animation data. */ |
|
virtual ~plATCAnim(); |
|
|
|
/** Returns the initial position of the "playback head" for this animation. |
|
Animations are not required to start at their actual beginning but can, |
|
for instance, start in the middle, play to the end, and then loop to the |
|
beginning or to their loop start point. */ |
|
virtual hsScalar GetInitial() const { return fInitial; } |
|
void SetInitial(hsScalar initial) { fInitial = initial; } |
|
|
|
/** Does this animation start automatically when it's applied? */ |
|
virtual bool GetAutoStart() const { return fAutoStart; } |
|
void SetAutoStart(hsBool start) { fAutoStart = (start != 0); } |
|
|
|
/** If the animation loops, this is where it will restart the loop. Note that |
|
loops do not have to start at the beginning of the animation. */ |
|
virtual hsScalar GetLoopStart() const { return fLoopStart; } |
|
void SetLoopStart(hsScalar start) { fLoopStart = start; } |
|
|
|
/** If the animation loops, this is the end point of the loop. After passing |
|
this point, the animation will cycle around to GetLoopStart */ |
|
virtual hsScalar GetLoopEnd() const { return fLoopEnd; } |
|
void SetLoopEnd(hsScalar end) { fLoopEnd = end; } |
|
|
|
/** Does this animation loop?. Note that there may be multiple loop segments defined |
|
within a given animation. */ |
|
virtual bool GetLoop() const { return fLoop; } |
|
void SetLoop(hsBool loop) { fLoop = (loop != 0); } |
|
|
|
/** Set the curve type for easing in. Easing is an optional feature which allows you |
|
to make an animation slow down gradually when you stop it. |
|
The types are defined in plAnimEaseTypes.h |
|
*/ |
|
virtual UInt8 GetEaseInType() const { return fEaseInType; } |
|
void SetEaseInType(UInt8 type) { fEaseInType = type; } |
|
|
|
/** Set the length of time the ease-in should take. */ |
|
virtual hsScalar GetEaseInLength() const { return fEaseInLength; } |
|
/** Set the length of time the ease-in should take. */ |
|
void SetEaseInLength(hsScalar length) { fEaseInLength = length; } |
|
|
|
/** The minimum value used at the start of the ease in. */ |
|
virtual hsScalar GetEaseInMin() const { return fEaseInMin; } |
|
/** The minimum value used at the start of the ease in. */ |
|
void SetEaseInMin(hsScalar length) { fEaseInMin = length; } |
|
|
|
/** The maximum value reached at the end of the ease in. */ |
|
virtual hsScalar GetEaseInMax() const { return fEaseInMax; } |
|
/** The maximum value reached at the end of the ease in. */ |
|
void SetEaseInMax(hsScalar length) { fEaseInMax = length; } |
|
|
|
/** The curve type for the ease out. */ |
|
virtual UInt8 GetEaseOutType() const { return fEaseOutType; } |
|
/** The curve type for the ease out. */ |
|
void SetEaseOutType(UInt8 type) { fEaseOutType = type; } |
|
|
|
/** The length of time for the ease out. */ |
|
virtual hsScalar GetEaseOutLength() const { return fEaseOutLength; } |
|
/** The length of time for the ease out. */ |
|
void SetEaseOutLength(hsScalar length) { fEaseOutLength = length; } |
|
|
|
/** Minimum value reached in ease-out */ |
|
virtual hsScalar GetEaseOutMin() const { return fEaseOutMin; } |
|
/** Minimum value reached in ease-out */ |
|
void SetEaseOutMin(hsScalar length) { fEaseOutMin = length; } |
|
|
|
/** Maximum value reached in ease-in */ |
|
virtual hsScalar GetEaseOutMax() const { return fEaseOutMax; } |
|
/** Maximum value reached in ease-in */ |
|
void SetEaseOutMax(hsScalar length) { fEaseOutMax = length; } |
|
|
|
/** Animations can have multiple defined loop segments; these |
|
are selected using animation control messages. |
|
Each loop segment is named using markers in the notetrack. */ |
|
void AddLoop(const char *name, float start, float end); |
|
/** Get the loop having the given name. |
|
\param start will return the start time of the loop. |
|
\param end will hold the end time of the loop */ |
|
bool GetLoop(const char *name, float &start, float &end) const; |
|
/** Lets you get a loop by index instead of name. */ |
|
bool GetLoop(UInt32 num, float &start, float &end) const; |
|
/** Returns the number of loops defined on this anim. */ |
|
UInt32 GetNumLoops() const; |
|
|
|
/** Add a marker to the animation. Markers can be used |
|
for callbacks or for goto comands. A marker is a simple |
|
name/time tuple. */ |
|
void AddMarker(const char *name, float time); |
|
/** Returns the time value of the marker named by name. */ |
|
float GetMarker(const char *name) const; |
|
void CopyMarkerNames(std::vector<char*> &out); |
|
/** Add a stop point to the animation. A stop point is a |
|
"detent" for playback - if the animation is stopping |
|
near a stop point and fading out, the stop point will |
|
override the fade, so that the animation stops precisely |
|
at the defined time. */ |
|
void AddStopPoint(hsScalar time); |
|
/** Return the number of stop points defined for this animation. */ |
|
UInt32 NumStopPoints(); |
|
/** Get the time corresponding to the given stop point. Stop points |
|
are numbered in the order they were added. */ |
|
hsScalar GetStopPoint(UInt32 i); |
|
/** Function to check for a zero-length loop, and set it to |
|
the anim's start/end instead */ |
|
void CheckLoop(); |
|
|
|
// PLASMA PROTOCOL |
|
// rtti |
|
CLASSNAME_REGISTER( plATCAnim ); |
|
GETINTERFACE_ANY( plATCAnim, plAGAnim ); |
|
|
|
// persistance |
|
virtual void Read(hsStream* stream, hsResMgr* mgr); |
|
virtual void Write(hsStream* stream, hsResMgr* mgr); |
|
|
|
protected: |
|
hsScalar fInitial; /// the position of the playback head |
|
bool fAutoStart; /// does the animation start automatically? |
|
hsScalar fLoopStart; /// when wrapping a loop, start here |
|
hsScalar fLoopEnd; /// when you reach this point, loop back |
|
bool fLoop; /// do we loop? |
|
|
|
UInt8 fEaseInType; /// the type (none/linear/spline) of our ease-in curve, if any |
|
UInt8 fEaseOutType; /// the type (none/linear/spline) of our ease-out curve, if any |
|
hsScalar fEaseInLength; /// the length of time our ease-in curve takes |
|
hsScalar fEaseInMin; /// minimum (initial) value of our ease-in |
|
hsScalar fEaseInMax; /// maximum (final) value of our ease-in |
|
hsScalar fEaseOutLength; /// the length of time our ease-out curve takes |
|
hsScalar fEaseOutMin; /// minimum (final) value of our ease-out |
|
hsScalar fEaseOutMax; /// maximum (initial) value of our ease-out |
|
|
|
// a map from segment names to times |
|
typedef std::map<const char *, float, stringSorter> MarkerMap; |
|
MarkerMap fMarkers; |
|
|
|
typedef std::map<const char *, std::pair<float,float>, stringSorter> LoopMap; |
|
LoopMap fLoops; |
|
|
|
typedef std::vector<hsScalar> ScalarMap; |
|
ScalarMap fStopPoints; /// vector of stop points |
|
}; |
|
|
|
|
|
|
|
/** \class plEmoteAnim |
|
An animation to be used for emotes. |
|
Automatically registers so that it can be played from the chat field. |
|
*/ |
|
class plEmoteAnim : public plATCAnim |
|
{ |
|
public: |
|
|
|
plEmoteAnim(); |
|
plEmoteAnim(const char *animName, double begin, double end, float fadeIn, float fadeOut, BodyUsage bodyUsage); |
|
|
|
BodyUsage GetBodyUsage() const; |
|
hsScalar GetFadeIn() const; |
|
hsScalar GetFadeOut() const; |
|
|
|
CLASSNAME_REGISTER( plEmoteAnim ); |
|
GETINTERFACE_ANY( plEmoteAnim, plATCAnim ); |
|
|
|
virtual void Read(hsStream *stream, hsResMgr *mgr); |
|
virtual void Write(hsStream *stream, hsResMgr *mgr); |
|
|
|
protected: |
|
BodyUsage fBodyUsage; // how much of the body is used by this emote? |
|
hsScalar fFadeIn; // how fast to fade in the emote |
|
hsScalar fFadeOut; // how fast to fade out the emote |
|
}; |
|
|
|
////////////////// |
|
// PLAGEGLOBALANIM |
|
////////////////// |
|
|
|
/** \class plAgeGlobalAnim |
|
An animation that bases its current position on a variable that global to the age, |
|
like weather, time of day, etc. |
|
*/ |
|
|
|
class plAgeGlobalAnim : public plAGAnim |
|
{ |
|
public: |
|
plAgeGlobalAnim(); |
|
/** Construct with name, start time, and end time (within the max note track) |
|
*/ |
|
plAgeGlobalAnim(const char *name, double begin, double end); |
|
/** Destruct, freeing the underlying animation data. */ |
|
virtual ~plAgeGlobalAnim(); |
|
|
|
const char * GetGlobalVarName() const { return fGlobalVarName; } |
|
void SetGlobalVarName(char *name); |
|
|
|
// PLASMA PROTOCOL |
|
// rtti |
|
CLASSNAME_REGISTER( plAgeGlobalAnim ); |
|
GETINTERFACE_ANY( plAgeGlobalAnim, plAGAnim ); |
|
|
|
// persistance |
|
virtual void Read(hsStream* stream, hsResMgr* mgr); |
|
virtual void Write(hsStream* stream, hsResMgr* mgr); |
|
|
|
protected: |
|
char *fGlobalVarName; // Name of the SDL variable we animate on. |
|
}; |
|
|
|
// USEFUL HELPER FUNCTIONS |
|
bool GetStartToEndTransform(const plAGAnim *anim, hsMatrix44 *startToEnd, hsMatrix44 *endToStart, const char *channelName); |
|
bool GetRelativeTransform(const plAGAnim *anim, double timeA, double timeB, hsMatrix44 *a2b, hsMatrix44 *b2a, const char *channelName); |
|
|
|
|
|
|
|
#endif
|
|
|