|
|
|
/*==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/>.
|
|
|
|
|
|
|
|
Additional permissions under GNU GPL version 3 section 7
|
|
|
|
|
|
|
|
If you modify this Program, or any covered work, by linking or
|
|
|
|
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
|
|
|
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
|
|
|
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
|
|
|
(or a modified version of those libraries),
|
|
|
|
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
|
|
|
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
|
|
|
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
|
|
|
licensors of this Program grant you additional
|
|
|
|
permission to convey the resulting work. Corresponding Source for a
|
|
|
|
non-source form of such a combination shall include the source code for
|
|
|
|
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
|
|
|
work.
|
|
|
|
|
|
|
|
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 plAGAnimInstance.h
|
|
|
|
\brief The animation class for the AniGraph animation system
|
|
|
|
|
|
|
|
\ingroup Avatar
|
|
|
|
\ingroup AniGraph
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef PLAGANIMINSTANCE_INC
|
|
|
|
#define PLAGANIMINSTANCE_INC
|
|
|
|
|
|
|
|
// disable warning C4503: dcorated name length exceeded, name was truncated
|
|
|
|
// disable warning C4786: symbol greater than 255 characters,
|
|
|
|
#pragma warning(disable: 4503 4786)
|
|
|
|
|
|
|
|
// templates
|
|
|
|
#include "hsStlUtils.h"
|
|
|
|
#include "hsStlSortUtils.h"
|
|
|
|
|
|
|
|
// local
|
|
|
|
#include "plScalarChannel.h"
|
|
|
|
|
|
|
|
// other
|
|
|
|
#include "../plInterp/plAnimTimeConvert.h"
|
|
|
|
|
|
|
|
// declarations
|
|
|
|
class plAGChannel;
|
|
|
|
class plAGAnim;
|
|
|
|
class plAGMasterMod;
|
|
|
|
class plAGChannelApplicator;
|
|
|
|
class plOneShotCallbacks;
|
|
|
|
|
|
|
|
/////////////////
|
|
|
|
// PLAGANIMINSTANCE
|
|
|
|
/////////////////
|
|
|
|
/** \class plAGAnimInstance
|
|
|
|
Whenever we attach an animation to a scene object hierarchy, we
|
|
|
|
create an activation record -- a plAGAnimInstance -- that remembers
|
|
|
|
all the ephemeral state associated with animation
|
|
|
|
Since animations have many channels and may involve blend operations,
|
|
|
|
one of the primary responsibilities of this class is to keep track of
|
|
|
|
all the animation node graphs that were created by the invocation of
|
|
|
|
this animation.
|
|
|
|
*/
|
|
|
|
class plAGAnimInstance {
|
|
|
|
public:
|
|
|
|
/** Used for the fade commands to select what to fade. */
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
kFadeBlend, /// Fade the blend strength
|
|
|
|
kFadeAmp, /// Fade the amplitude
|
|
|
|
} FadeType;
|
|
|
|
|
|
|
|
/** Default constructor. */
|
|
|
|
plAGAnimInstance();
|
|
|
|
|
|
|
|
/** Construct from an animation and a master modifier.
|
|
|
|
This attaches the animation channels to the channels of
|
|
|
|
the master modifier and creates all the bookkeeping structures
|
|
|
|
necessary to undo it later. */
|
|
|
|
plAGAnimInstance(plAGAnim * anim, plAGMasterMod * master, hsScalar blend, UInt16 blendPriority, hsBool cache, bool useAmplitude);
|
|
|
|
|
|
|
|
/** Destructor. Removes the animation from the scene objects it's attached to. */
|
|
|
|
virtual ~plAGAnimInstance();
|
|
|
|
|
|
|
|
/** Returns the animation that this instance mediates. */
|
|
|
|
const plAGAnim * GetAnimation() { return fAnimation; };
|
|
|
|
|
|
|
|
/** Returns the timeconvert object that controls the progress of time
|
|
|
|
in this animation. */
|
|
|
|
plAnimTimeConvert *GetTimeConvert() { return fTimeConvert; }
|
|
|
|
|
|
|
|
/** Set the speed of the animation. This is expressed as a fraction of
|
|
|
|
the speed with which the animation was defined. */
|
|
|
|
void SetSpeed(hsScalar speed) { if (fTimeConvert) fTimeConvert->SetSpeed(speed); };
|
|
|
|
|
|
|
|
// \{
|
|
|
|
/**
|
|
|
|
The current blend factor of the animation. This indicates the
|
|
|
|
priority of this animation as opposed to other animations which
|
|
|
|
were attached before it. Conceptually it may help to think of this
|
|
|
|
as a layer in an stack of animations, where the blend value is the
|
|
|
|
'opacity' of this animation relative to the ones below it.
|
|
|
|
1.0 represents full strength.
|
|
|
|
You may use values higher than 1.0, but this has not
|
|
|
|
yet been seen to have any practical utility whatsoever. Note that
|
|
|
|
even if an animation has a blend strength of 1.0, it may have another
|
|
|
|
animation on top/downstream from it that is masking it completely. */
|
|
|
|
hsScalar SetBlend(hsScalar blend);
|
|
|
|
hsScalar GetBlend();
|
|
|
|
// \}
|
|
|
|
|
|
|
|
/** Set the strength of the animation with respect to its 0th frame.
|
|
|
|
This can be used to dampen the motion of the animation.
|
|
|
|
Animations must be designed to use this: frame 0 of the animation
|
|
|
|
must be a reasonable "default pose" as it will be blended with the
|
|
|
|
current frame of the animation to produce the result. */
|
|
|
|
hsScalar SetAmplitude(hsScalar amp);
|
|
|
|
/** Get the current strength of the animation. */
|
|
|
|
hsScalar GetAmplitude();
|
|
|
|
|
|
|
|
/** Make this animation loop (or not.) Note that the instance can loop
|
|
|
|
or not without regard to whether the plAGAnim it is based on loops. */
|
|
|
|
void SetLoop(hsBool status);
|
|
|
|
|
|
|
|
/** Interpret and respond to an animation command message. /sa plAnimCmdMsg */
|
|
|
|
hsBool HandleCmd(plAnimCmdMsg *msg);
|
|
|
|
|
|
|
|
/** Start playback of the animation. You may optionally provide the a world
|
|
|
|
time, which is needed for synchronizing the animation's timeline
|
|
|
|
with the global timeline. If timeNow is -1 (the default,) the system
|
|
|
|
time will be polled */
|
|
|
|
void Start(double worldTimeNow = -1);
|
|
|
|
|
|
|
|
/** Stop playback of the animation. */
|
|
|
|
void Stop();
|
|
|
|
|
|
|
|
/** Move the playback head of the animation to a specific time.
|
|
|
|
Note that this time is in animation local time, not global time.
|
|
|
|
The "jump" parameter specifies whether or not to fire callbacks
|
|
|
|
that occur between the current time and the target time. */
|
|
|
|
void SetCurrentTime(hsScalar newLocalTime, hsBool jump = false);
|
|
|
|
|
|
|
|
/** Move the playback head by the specified relative amount within
|
|
|
|
the animation. This may cause looping. If the beginning or end
|
|
|
|
of the animation is reached an looping is not on, the movement
|
|
|
|
will pin.
|
|
|
|
\param jump if true, don't look for callbacks between old time and TRACKED_NEW */
|
|
|
|
void SeekRelative(hsScalar delta, hsBool jump);
|
|
|
|
|
|
|
|
/** Gradually fade the blend strength or amplitude of the animation.
|
|
|
|
\param goal is the desired blend strength
|
|
|
|
\param rate is in blend units per second
|
|
|
|
\type is either kFadeBlend or kFadeAmp */
|
|
|
|
void Fade(hsScalar goal, hsScalar rate, UInt8 type = kFadeBlend);
|
|
|
|
|
|
|
|
/** Fade the animation and detach it after the fade is complete.
|
|
|
|
Extremely useful for situations where the controlling logic
|
|
|
|
is terminating immediately but you want the animation to fade
|
|
|
|
out gradually.
|
|
|
|
\deprecated
|
|
|
|
*/
|
|
|
|
void FadeAndDetach(hsScalar goal, hsScalar rate);
|
|
|
|
|
|
|
|
/** Has the animation terminated of natural causes?
|
|
|
|
Primarily used to see if an animation has played all the
|
|
|
|
way to the end, but will also return true if the animation
|
|
|
|
was stopped with a stop command */
|
|
|
|
hsBool IsFinished();
|
|
|
|
|
|
|
|
/** Is the animation playback head positioned at the end. */
|
|
|
|
hsBool IsAtEnd();
|
|
|
|
|
|
|
|
/** Get the name of the underlying animation. */
|
|
|
|
const char * GetName();
|
|
|
|
|
|
|
|
/** Remove all channels from the master mode and remove us from
|
|
|
|
our master modifier.
|
|
|
|
Destructs the object! */
|
|
|
|
void Detach();
|
|
|
|
|
|
|
|
/** Remove all the instance's channels from the modifiers they're attached to.
|
|
|
|
Typically called by the master mod prior to destructing the instance. */
|
|
|
|
void DetachChannels();
|
|
|
|
|
|
|
|
/** Prune any unused branches out of the animation graph; add any
|
|
|
|
newly active branches back in. */
|
|
|
|
void Optimize();
|
|
|
|
|
|
|
|
/** Convert the given world time to local animation time.
|
|
|
|
May include the effects of looping or wraparound.
|
|
|
|
If the local time passes the end of the animation, the returned
|
|
|
|
time will be pinned appropriately. */
|
|
|
|
double WorldToAnimTime(double foo) { return (fTimeConvert ? fTimeConvert->WorldToAnimTimeNoUpdate(foo) : 0); };
|
|
|
|
|
|
|
|
/** Attach a sequence of callback messages to the animation instance.
|
|
|
|
Messages are each associated with a specific (local) time
|
|
|
|
in the animation and will be sent when playback passes that time. */
|
|
|
|
void AttachCallbacks(plOneShotCallbacks *callbacks);
|
|
|
|
|
|
|
|
void ProcessFade(hsScalar elapsed); // process any outstanding fades
|
|
|
|
void SearchForGlobals(); // Util function to setup SDL channels
|
|
|
|
protected:
|
|
|
|
/** Set up bookkeeping for a fade. */
|
|
|
|
void ISetupFade(hsScalar goal, hsScalar rate, bool detach, UInt8 type);
|
|
|
|
|
|
|
|
void IRegisterDetach(const char *channelName, plAGChannel *channel);
|
|
|
|
|
|
|
|
const plAGAnim * fAnimation;
|
|
|
|
plAGMasterMod * fMaster;
|
|
|
|
|
|
|
|
std::map<char *, plAGChannelApplicator *, stringISorter> fChannels;
|
|
|
|
|
|
|
|
typedef std::multimap<const char *, plAGChannel *> plDetachMap;
|
|
|
|
plDetachMap fManualDetachChannels;
|
|
|
|
|
|
|
|
std::vector<plAGChannel*> fCleanupChannels;
|
|
|
|
std::vector<plScalarSDLChannel*> fSDLChannels;
|
|
|
|
|
|
|
|
plScalarConstant fBlend; // blend factor vs. previous animations
|
|
|
|
plScalarConstant fAmplitude; // for animation scaling
|
|
|
|
|
|
|
|
// Each activation gets its own timeline.
|
|
|
|
plAnimTimeConvert *fTimeConvert;
|
|
|
|
|
|
|
|
hsBool fFadeBlend; /// we are fading the blend
|
|
|
|
hsScalar fFadeBlendGoal; /// what blend level we're trying to reach
|
|
|
|
hsScalar fFadeBlendRate; /// how fast are we fading in blend units per second (1 blend unit = full)
|
|
|
|
hsBool fFadeDetach; /// detach after fade is finished? (only used for blend fades)
|
|
|
|
|
|
|
|
hsBool fFadeAmp; /// we are fading the amplitude
|
|
|
|
hsScalar fFadeAmpGoal; /// amplitude we're trying to reach
|
|
|
|
hsScalar fFadeAmpRate; /// how faster we're fading in blend units per second
|
|
|
|
|
|
|
|
hsScalar ICalcFade(hsBool &fade, hsScalar curVal, hsScalar goal, hsScalar rate, hsScalar elapsed);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
//#ifdef _DEBUG
|
|
|
|
//#define TRACK_AG_ALLOCS // for now, automatically track AG allocations in debug
|
|
|
|
//#endif
|
|
|
|
#ifdef TRACK_AG_ALLOCS
|
|
|
|
|
|
|
|
extern const char *gGlobalAnimName;
|
|
|
|
extern const char *gGlobalChannelName;
|
|
|
|
|
|
|
|
void RegisterAGAlloc(plAGChannel *object, const char *chanName, const char *animName, UInt16 classIndex);
|
|
|
|
void UnRegisterAGAlloc(plAGChannel *object);
|
|
|
|
void DumpAGAllocs();
|
|
|
|
|
|
|
|
#endif // TRACK_AG_ALLOCS
|
|
|
|
|
|
|
|
#endif // PLAGANIMINSTANCE_INC
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|