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.
682 lines
19 KiB
682 lines
19 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/>.
|
||
|
|
||
13 years ago
|
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.
|
||
|
|
||
14 years ago
|
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==*/
|
||
|
/////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// INCLUDES
|
||
|
//
|
||
|
/////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
12 years ago
|
#include <algorithm>
|
||
|
|
||
14 years ago
|
// singular
|
||
|
#include "plAGAnimInstance.h"
|
||
|
|
||
|
// local
|
||
|
#include "plAGAnim.h"
|
||
|
#include "plAGModifier.h"
|
||
|
#include "plAGMasterMod.h"
|
||
|
|
||
|
// global
|
||
|
#include "hsTimer.h" // just when debugging for GetSysSeconds
|
||
|
|
||
|
// other
|
||
|
#include "pnNetCommon/plSDLTypes.h"
|
||
|
#include "plMessage/plAnimCmdMsg.h"
|
||
|
#include "plMessage/plOneShotCallbacks.h"
|
||
|
#include "plModifier/plSDLModifier.h"
|
||
|
#include "plSDL/plSDL.h"
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// FLAGS
|
||
|
//
|
||
|
/////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
// enable this to show blend trees before and after attaches and detaches
|
||
|
// #define SHOW_AG_CHANGES
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// STATIC
|
||
|
//
|
||
|
/////////////////////////////////////////////////////////////////////////////////////////
|
||
|
#ifdef TRACK_AG_ALLOCS
|
||
12 years ago
|
plString gGlobalAnimName;
|
||
|
plString gGlobalChannelName;
|
||
14 years ago
|
#endif // TRACK_AG_ALLOCS
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// plAGAnimInstance
|
||
|
//
|
||
|
/////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
// ctor -------------------------------------------------------------------
|
||
|
// -----
|
||
|
plAGAnimInstance::plAGAnimInstance(plAGAnim * anim, plAGMasterMod * master,
|
||
12 years ago
|
float blend, uint16_t blendPriority, bool cache,
|
||
14 years ago
|
bool useAmplitude)
|
||
|
: fAnimation(anim),
|
||
|
fMaster(master),
|
||
|
fBlend(blend),
|
||
|
fAmplitude(useAmplitude ? 1.0f : -1.0f)
|
||
|
{
|
||
|
int i;
|
||
|
fTimeConvert = nil;
|
||
|
plScalarChannel *timeChan = nil;
|
||
|
#ifdef TRACK_AG_ALLOCS
|
||
|
gGlobalAnimName = anim->GetName(); // for debug tracking...
|
||
|
#endif // TRACK_AG_ALLOCS
|
||
|
|
||
|
plATCAnim *atcAnim = plATCAnim::ConvertNoRef(anim);
|
||
|
if (atcAnim)
|
||
|
{
|
||
13 years ago
|
fTimeConvert = new plAnimTimeConvert();
|
||
10 years ago
|
IInitAnimTimeConvert(fTimeConvert, atcAnim, master);
|
||
|
//fTimeConvert->Init(atcAnim, this, master);
|
||
13 years ago
|
timeChan = new plATCChannel(fTimeConvert);
|
||
14 years ago
|
}
|
||
|
else
|
||
|
{
|
||
13 years ago
|
timeChan = new plScalarSDLChannel(anim->GetLength());
|
||
14 years ago
|
fSDLChannels.push_back((plScalarSDLChannel *)timeChan);
|
||
|
}
|
||
|
|
||
|
int nInChannels = anim->GetChannelCount();
|
||
|
|
||
|
fCleanupChannels.push_back(timeChan);
|
||
|
|
||
|
#ifdef SHOW_AG_CHANGES
|
||
13 years ago
|
hsStatusMessageF("\nAbout to Attach anim <%s>", GetName().c_str());
|
||
14 years ago
|
fMaster->DumpAniGraph("bone_pelvis", false, hsTimer::GetSysSeconds());
|
||
|
#endif
|
||
|
|
||
|
for (i = 0; i < nInChannels; i++)
|
||
|
{
|
||
|
plAGApplicator * app = fAnimation->GetApplicator(i);
|
||
|
plAGChannel * inChannel = app->GetChannel();
|
||
13 years ago
|
plString channelName = app->GetChannelName();
|
||
14 years ago
|
plAGModifier * channelMod = master->GetChannelMod(channelName);
|
||
|
|
||
|
if(channelMod) {
|
||
|
#ifdef TRACK_AG_ALLOCS
|
||
|
gGlobalChannelName = channelName;
|
||
|
#endif // TRACK_AG_ALLOCS
|
||
|
|
||
|
// we're going to be accumulating a chain of channels.
|
||
|
// curChannel will always point to the top one...
|
||
|
plAGChannel *topNode = inChannel;
|
||
|
|
||
|
if(cache)
|
||
|
{
|
||
|
topNode = topNode->MakeCacheChannel(fTimeConvert);
|
||
|
IRegisterDetach(channelName, topNode);
|
||
|
}
|
||
|
|
||
|
if(useAmplitude)
|
||
|
{
|
||
|
// amplitude is rarely used and expensive, so only alloc if asked
|
||
|
// first build a static copy of the incoming channel...
|
||
|
plAGChannel *zeroState = inChannel->MakeZeroState();
|
||
|
IRegisterDetach(channelName, zeroState);
|
||
|
|
||
|
// now make a blend node to blend the anim with its static copy
|
||
|
topNode = zeroState->MakeBlend(topNode, &fAmplitude, -1);
|
||
|
}
|
||
|
|
||
|
// make a time scaler to localize time for this instance
|
||
|
topNode = topNode->MakeTimeScale(timeChan);
|
||
|
IRegisterDetach(channelName, topNode);
|
||
|
|
||
|
channelMod->MergeChannel(app, topNode, &fBlend, this, blendPriority);
|
||
|
}
|
||
|
else
|
||
|
hsAssert(false, "Adding an animation with an invalid channel.");
|
||
|
}
|
||
|
fFadeBlend = fFadeAmp = false;
|
||
|
|
||
|
#ifdef TRACK_AG_ALLOCS
|
||
12 years ago
|
gGlobalAnimName = "";
|
||
14 years ago
|
#endif // TRACK_AG_ALLOCS
|
||
|
}
|
||
|
|
||
|
// dtor -----------------------------
|
||
|
// -----
|
||
|
plAGAnimInstance::~plAGAnimInstance()
|
||
|
{
|
||
|
delete fTimeConvert;
|
||
|
}
|
||
|
|
||
10 years ago
|
|
||
|
void plAGAnimInstance::IInitAnimTimeConvert(plAnimTimeConvert* atc, plATCAnim* anim, plAGMasterMod* master)
|
||
|
{
|
||
|
// Set up our eval callbacks
|
||
|
plAGInstanceCallbackMsg* instMsg;
|
||
|
|
||
|
instMsg = new plAGInstanceCallbackMsg(master->GetKey(), kStart);
|
||
|
instMsg->fInstance = this;
|
||
|
atc->AddCallback(instMsg);
|
||
|
hsRefCnt_SafeUnRef(instMsg);
|
||
|
|
||
|
instMsg = new plAGInstanceCallbackMsg(master->GetKey(), kStop);
|
||
|
instMsg->fInstance = this;
|
||
|
atc->AddCallback(instMsg);
|
||
|
hsRefCnt_SafeUnRef(instMsg);
|
||
|
|
||
|
instMsg = new plAGInstanceCallbackMsg(master->GetKey(), kSingleFrameAdjust);
|
||
|
instMsg->fInstance = this;
|
||
|
atc->AddCallback(instMsg);
|
||
|
hsRefCnt_SafeUnRef(instMsg);
|
||
|
|
||
|
atc->SetOwner(master);
|
||
|
atc->ClearFlags();
|
||
|
|
||
|
for (size_t i = 0; i < anim->NumStopPoints(); i++)
|
||
|
{
|
||
|
atc->GetStopPoints().Append(anim->GetStopPoint(i));
|
||
|
}
|
||
|
|
||
|
atc->SetBegin(anim->GetStart());
|
||
|
atc->SetEnd(anim->GetEnd());
|
||
|
atc->SetInitialBegin(atc->GetBegin());
|
||
|
atc->SetInitialEnd(atc->GetEnd());
|
||
|
|
||
|
if (anim->GetInitial() != -1)
|
||
|
{
|
||
|
atc->SetCurrentAnimTime(anim->GetInitial());
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
atc->SetCurrentAnimTime(anim->GetStart());
|
||
|
}
|
||
|
|
||
|
atc->SetLoopPoints(anim->GetLoopStart(), anim->GetLoopEnd());
|
||
|
atc->Loop(anim->GetLoop());
|
||
|
atc->SetSpeed(1.f);
|
||
|
|
||
|
atc->SetEase(true, anim->GetEaseInType(), anim->GetEaseInMin(),
|
||
|
anim->GetEaseInMax(), anim->GetEaseInLength());
|
||
|
|
||
|
atc->SetEase(false, anim->GetEaseOutType(), anim->GetEaseOutMin(),
|
||
|
anim->GetEaseOutMax(), anim->GetEaseOutLength());
|
||
|
|
||
|
|
||
|
// set up our time converter based on the animation's specs...
|
||
|
// ... after we've set all of its other state values.
|
||
|
if (anim->GetAutoStart())
|
||
|
{
|
||
|
plSynchEnabler ps(true); // enable dirty tracking so that autostart will send out a state update
|
||
|
atc->Start();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
atc->InitStop();
|
||
|
}
|
||
|
}
|
||
|
|
||
14 years ago
|
// SearchForGlobals ---------------------
|
||
|
// -----------------
|
||
|
void plAGAnimInstance::SearchForGlobals()
|
||
|
{
|
||
|
const plAgeGlobalAnim *ageAnim = plAgeGlobalAnim::ConvertNoRef(fAnimation);
|
||
|
if (ageAnim != nil && fSDLChannels.size() > 0)
|
||
|
{
|
||
|
extern const plSDLModifier *ExternFindAgeSDL();
|
||
|
const plSDLModifier *sdlMod = ExternFindAgeSDL();
|
||
|
if (!sdlMod)
|
||
|
return;
|
||
|
|
||
|
plSimpleStateVariable *var = sdlMod->GetStateCache()->FindVar(ageAnim->GetGlobalVarName());
|
||
|
if (!var)
|
||
|
return;
|
||
|
|
||
|
sdlMod->AddNotifyForVar(fMaster->GetKey(), ageAnim->GetGlobalVarName(), 0);
|
||
|
int i;
|
||
|
for (i = 0; i < fSDLChannels.size(); i++)
|
||
|
fSDLChannels[i]->SetVar(var);
|
||
|
}
|
||
|
}
|
||
|
|
||
13 years ago
|
void plAGAnimInstance::IRegisterDetach(const plString &channelName, plAGChannel *channel)
|
||
14 years ago
|
{
|
||
|
plDetachMap::value_type newPair(channelName, channel);
|
||
|
fManualDetachChannels.insert(newPair);
|
||
|
}
|
||
|
|
||
|
// SetCurrentTime ---------------------------------------------------------------
|
||
|
// ---------------
|
||
12 years ago
|
void plAGAnimInstance::SetCurrentTime(float localT, bool jump /* = false */)
|
||
14 years ago
|
{
|
||
|
if (fTimeConvert)
|
||
|
fTimeConvert->SetCurrentAnimTime(localT, jump);
|
||
|
}
|
||
|
|
||
|
// SeekRelative ------------------------------------
|
||
|
// -------------
|
||
12 years ago
|
void plAGAnimInstance::SeekRelative (float delta, bool jump)
|
||
14 years ago
|
{
|
||
|
if(fTimeConvert)
|
||
|
{
|
||
13 years ago
|
float now = fTimeConvert->CurrentAnimTime();
|
||
14 years ago
|
fTimeConvert->SetCurrentAnimTime (now + delta, jump);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Detach ---------------------
|
||
|
// -------
|
||
|
void plAGAnimInstance::Detach()
|
||
|
{
|
||
|
fMaster->DetachAnimation(this);
|
||
|
}
|
||
|
|
||
|
// DetachChannels ---------------------
|
||
|
// ---------------
|
||
|
void plAGAnimInstance::DetachChannels()
|
||
|
{
|
||
|
#ifdef SHOW_AG_CHANGES
|
||
13 years ago
|
hsStatusMessageF("\nAbout to DETACH anim <%s>", GetName().c_str());
|
||
14 years ago
|
fMaster->DumpAniGraph("bone_pelvis", false, hsTimer::GetSysSeconds());
|
||
|
#endif
|
||
|
plDetachMap::iterator i = fManualDetachChannels.begin();
|
||
|
|
||
|
while(i != fManualDetachChannels.end())
|
||
|
{
|
||
13 years ago
|
plString channelName = (*i).first;
|
||
14 years ago
|
plAGModifier *channelMod = fMaster->GetChannelMod(channelName, true);
|
||
|
|
||
|
if(channelMod)
|
||
|
{
|
||
|
do {
|
||
|
plAGChannel *channel = (*i).second;
|
||
|
channelMod->DetachChannel(channel);
|
||
|
} while (++i != fManualDetachChannels.end() && i->first == channelName);
|
||
|
} else {
|
||
|
do {
|
||
|
} while (++i != fManualDetachChannels.end() && i->first == channelName);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int cleanCount = fCleanupChannels.size();
|
||
|
hsAssert(cleanCount, "No time controls when deleting animation");
|
||
|
for (int j = 0; j < cleanCount; j++)
|
||
|
{
|
||
|
delete fCleanupChannels[j];
|
||
|
}
|
||
|
fCleanupChannels.clear();
|
||
|
|
||
|
#ifdef SHOW_AG_CHANGES
|
||
13 years ago
|
hsStatusMessageF("\nFinished DETACHING anim <%s>", GetName().c_str());
|
||
14 years ago
|
fMaster->DumpAniGraph("bone_pelvis", false, hsTimer::GetSysSeconds());
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
// SetBlend ---------------------------------------
|
||
|
// ---------
|
||
13 years ago
|
float plAGAnimInstance::SetBlend(float blend)
|
||
14 years ago
|
{
|
||
|
float oldBlend = fBlend.Value(0.0, true);
|
||
|
if(oldBlend != blend &&
|
||
|
(oldBlend == 0.0f ||
|
||
|
blend == 0.0f ||
|
||
|
oldBlend == 1.0f ||
|
||
|
blend == 1.0f))
|
||
|
{
|
||
|
fMaster->SetNeedCompile(true);
|
||
|
}
|
||
|
fBlend.Set(blend);
|
||
|
return blend;
|
||
|
}
|
||
|
|
||
|
// GetBlend -------------------------
|
||
|
// ---------
|
||
13 years ago
|
float plAGAnimInstance::GetBlend()
|
||
14 years ago
|
{
|
||
|
return fBlend.Value(0);
|
||
|
}
|
||
|
|
||
|
// SetAmplitude -------------------------------------
|
||
|
// -------------
|
||
13 years ago
|
float plAGAnimInstance::SetAmplitude(float amp)
|
||
14 years ago
|
{
|
||
|
if(fAmplitude.Get() != -1.0f)
|
||
|
{
|
||
|
fAmplitude.Set(amp);
|
||
|
}
|
||
|
return amp;
|
||
|
}
|
||
|
|
||
|
// GetAmplitude -------------------------
|
||
|
// -------------
|
||
13 years ago
|
float plAGAnimInstance::GetAmplitude()
|
||
14 years ago
|
{
|
||
|
return fAmplitude.Value(0);
|
||
|
}
|
||
|
|
||
|
// GetName -----------------------------
|
||
|
// --------
|
||
13 years ago
|
plString plAGAnimInstance::GetName()
|
||
14 years ago
|
{
|
||
|
if(fAnimation)
|
||
|
return fAnimation->GetName();
|
||
|
else
|
||
13 years ago
|
return plString::Null;
|
||
14 years ago
|
}
|
||
|
|
||
|
// SetLoop ----------------------------------
|
||
|
// --------
|
||
12 years ago
|
void plAGAnimInstance::SetLoop(bool status)
|
||
14 years ago
|
{
|
||
|
if (fTimeConvert)
|
||
|
fTimeConvert->Loop(status);
|
||
|
}
|
||
|
|
||
|
// HandleCmd ----------------------------------------
|
||
|
// ----------
|
||
12 years ago
|
bool plAGAnimInstance::HandleCmd(plAnimCmdMsg *msg)
|
||
14 years ago
|
{
|
||
|
if (fTimeConvert)
|
||
|
return fTimeConvert->HandleCmd(msg);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// IsFinished -----------------------
|
||
|
// -----------
|
||
12 years ago
|
bool plAGAnimInstance::IsFinished()
|
||
14 years ago
|
{
|
||
|
if (fTimeConvert)
|
||
|
return fTimeConvert->IsStopped();
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// IsAtEnd -----------------------
|
||
|
// --------
|
||
12 years ago
|
bool plAGAnimInstance::IsAtEnd()
|
||
14 years ago
|
{
|
||
|
if(fTimeConvert)
|
||
|
{
|
||
|
return fTimeConvert->CurrentAnimTime() == fTimeConvert->GetEnd();
|
||
|
}
|
||
|
else
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// Start -----------------------------------
|
||
|
// ------
|
||
|
void plAGAnimInstance::Start(double timeNow)
|
||
|
{
|
||
|
if (fTimeConvert)
|
||
|
{
|
||
|
if (timeNow < 0)
|
||
|
fTimeConvert->Start();
|
||
|
else
|
||
|
fTimeConvert->Start(timeNow);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Stop ---------------------
|
||
|
// -----
|
||
|
void plAGAnimInstance::Stop()
|
||
|
{
|
||
|
if (fTimeConvert)
|
||
|
fTimeConvert->Stop();
|
||
|
}
|
||
|
|
||
|
// AttachCallbacks --------------------------------------------------
|
||
|
// ----------------
|
||
|
void plAGAnimInstance::AttachCallbacks(plOneShotCallbacks *callbacks)
|
||
|
{
|
||
|
const plATCAnim *anim = plATCAnim::ConvertNoRef(fAnimation);
|
||
|
if (callbacks && anim)
|
||
|
{
|
||
|
plAnimCmdMsg animMsg;
|
||
|
animMsg.SetCmd(plAnimCmdMsg::kAddCallbacks);
|
||
|
|
||
|
for (int i = 0; i < callbacks->GetNumCallbacks(); i++)
|
||
|
{
|
||
|
plOneShotCallbacks::plOneShotCallback& cb = callbacks->GetCallback(i);
|
||
|
|
||
13 years ago
|
plEventCallbackMsg *eventMsg = new plEventCallbackMsg;
|
||
14 years ago
|
eventMsg->AddReceiver(cb.fReceiver);
|
||
|
eventMsg->fRepeats = 0;
|
||
|
eventMsg->fUser = cb.fUser;
|
||
|
|
||
13 years ago
|
if (!cb.fMarker.IsNull())
|
||
14 years ago
|
{
|
||
|
float marker = anim->GetMarker(cb.fMarker);
|
||
|
hsAssert(marker != -1, "Bad marker name");
|
||
|
eventMsg->fEventTime = marker;
|
||
|
eventMsg->fEvent = kTime;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
eventMsg->fEvent = kStop;
|
||
|
}
|
||
|
|
||
|
animMsg.AddCallback(eventMsg);
|
||
|
hsRefCnt_SafeUnRef(eventMsg);
|
||
|
}
|
||
|
|
||
|
fTimeConvert->HandleCmd(&animMsg);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// ProcessFade -------------------------------------
|
||
|
// ------------
|
||
13 years ago
|
void plAGAnimInstance::ProcessFade(float elapsed)
|
||
14 years ago
|
{
|
||
|
if (fFadeBlend) {
|
||
13 years ago
|
float newBlend = ICalcFade(fFadeBlend, GetBlend(), fFadeBlendGoal, fFadeBlendRate, elapsed);
|
||
14 years ago
|
SetBlend(newBlend);
|
||
|
if(fFadeDetach && (newBlend == fFadeBlendGoal) && (fFadeBlendGoal == 0.0f) )
|
||
|
{
|
||
|
fMaster->DetachAnimation(this);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (fFadeAmp && fAmplitude.Get() != -1.0f) {
|
||
13 years ago
|
float curAmp = GetAmplitude();
|
||
|
float newAmp = ICalcFade(fFadeAmp, curAmp, fFadeAmpGoal, fFadeAmpRate, elapsed);
|
||
14 years ago
|
SetAmplitude(newAmp);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// ICalcFade ---------------------------------------------------------------------
|
||
|
// ----------
|
||
12 years ago
|
float plAGAnimInstance::ICalcFade(bool &fade, float curVal, float goal,
|
||
13 years ago
|
float rate, float elapsed)
|
||
14 years ago
|
{
|
||
13 years ago
|
float newVal;
|
||
|
float curStep = rate * elapsed;
|
||
14 years ago
|
if(rate > 0) {
|
||
13 years ago
|
newVal = std::min(goal, curVal + curStep);
|
||
14 years ago
|
} else {
|
||
13 years ago
|
newVal = std::max(goal, curVal + curStep);
|
||
14 years ago
|
}
|
||
|
|
||
|
if(newVal == goal)
|
||
|
{
|
||
|
fade = false;
|
||
|
fMaster->DirtySynchState(kSDLAGMaster, 0); // send SDL state update to server
|
||
|
}
|
||
|
return newVal;
|
||
|
}
|
||
|
|
||
|
// FadeAndDetach -------------------------------------------------
|
||
|
// --------------
|
||
13 years ago
|
void plAGAnimInstance::FadeAndDetach(float goal, float rate)
|
||
14 years ago
|
{
|
||
|
ISetupFade(goal, rate, true, kFadeBlend);
|
||
|
}
|
||
|
|
||
|
// Fade --------------------------------------------------------------------------------
|
||
|
// -----
|
||
13 years ago
|
void plAGAnimInstance::Fade(float goal, float rate, uint8_t type /* = kFadeBlend */)
|
||
14 years ago
|
{
|
||
|
ISetupFade(goal, rate, false, type);
|
||
|
}
|
||
|
|
||
|
// ISetupFade --------------------------------------------------------------------------
|
||
|
// -----------
|
||
13 years ago
|
void plAGAnimInstance::ISetupFade(float goal, float rate, bool detach, uint8_t type)
|
||
14 years ago
|
{
|
||
|
if (rate == 0)
|
||
|
{
|
||
|
if (type == kFadeBlend)
|
||
|
{
|
||
|
SetBlend(goal);
|
||
|
fFadeBlend = false;
|
||
|
if(detach) {
|
||
|
fMaster->DetachAnimation(this);
|
||
|
}
|
||
|
}
|
||
|
else if (type == kFadeAmp)
|
||
|
{
|
||
|
SetAmplitude(goal);
|
||
|
fFadeAmp = false;
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
rate = (rate > 0 ? rate : -rate); // For old code that sends negative values
|
||
|
|
||
13 years ago
|
float curVal = 0;
|
||
14 years ago
|
switch (type)
|
||
|
{
|
||
|
case kFadeBlend:
|
||
|
curVal = GetBlend();
|
||
|
break;
|
||
|
case kFadeAmp:
|
||
|
curVal = GetAmplitude();
|
||
|
break;
|
||
|
}
|
||
|
if (curVal > goal)
|
||
|
rate = -rate;
|
||
|
|
||
|
switch (type)
|
||
|
{
|
||
|
case kFadeBlend:
|
||
|
fFadeBlend = true;
|
||
|
fFadeBlendGoal = goal;
|
||
|
fFadeBlendRate = rate;
|
||
|
fFadeDetach = detach;
|
||
|
break;
|
||
|
case kFadeAmp:
|
||
|
fFadeAmp = true;
|
||
|
fFadeAmpGoal = goal;
|
||
|
fFadeAmpRate = rate;
|
||
|
fFadeDetach = false; // only detach on blend fades, for the moment.
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class agAlloc
|
||
|
{
|
||
|
public:
|
||
13 years ago
|
agAlloc(plAGChannel *object, const char *chanName, const char *animName, uint16_t classIndex)
|
||
14 years ago
|
: fObject(object),
|
||
|
fClassIndex(classIndex)
|
||
|
{
|
||
|
fChannelName = hsStrcpy(chanName);
|
||
|
fAnimName = hsStrcpy(animName);
|
||
|
}
|
||
|
|
||
|
~agAlloc()
|
||
|
{
|
||
|
delete[] fChannelName;
|
||
|
delete[] fAnimName;
|
||
|
}
|
||
|
|
||
|
plAGChannel *fObject;
|
||
|
char *fChannelName;
|
||
|
char *fAnimName;
|
||
13 years ago
|
uint16_t fClassIndex;
|
||
14 years ago
|
};
|
||
|
|
||
|
typedef std::map<plAGChannel *, agAlloc *> agAllocMap;
|
||
|
static agAllocMap gAGAllocs;
|
||
|
|
||
13 years ago
|
void RegisterAGAlloc(plAGChannel *object, const char *chanName, const char *animName, uint16_t classIndex)
|
||
14 years ago
|
{
|
||
13 years ago
|
gAGAllocs[object] = new agAlloc(object, chanName, animName, classIndex);
|
||
14 years ago
|
}
|
||
|
|
||
|
void DumpAGAllocs()
|
||
|
{
|
||
|
agAllocMap::iterator i = gAGAllocs.begin();
|
||
|
agAllocMap::iterator theEnd = gAGAllocs.end();
|
||
|
|
||
|
hsStatusMessage("DUMPING AG ALLOCATIONS ================================================");
|
||
|
|
||
|
for ( ; i != theEnd; i++)
|
||
|
{
|
||
|
agAlloc * al = (*i).second;
|
||
|
|
||
13 years ago
|
uint16_t realClassIndex = al->fObject->ClassIndex();
|
||
14 years ago
|
|
||
|
hsStatusMessageF("agAlloc: an: %s ch: %s, cl: %s", al->fAnimName, al->fChannelName, plFactory::GetNameOfClass(realClassIndex));
|
||
|
|
||
|
}
|
||
|
// it's not fast but it's safe and simple..
|
||
|
i = gAGAllocs.begin();
|
||
|
while(i != gAGAllocs.end())
|
||
|
{
|
||
|
agAlloc * al = (*i).second;
|
||
|
delete al;
|
||
|
|
||
13 years ago
|
gAGAllocs.erase(i++);
|
||
14 years ago
|
}
|
||
|
hsStatusMessage("FINISHED DUMPING AG ALLOCATIONS *********************************************");
|
||
|
}
|
||
|
|
||
|
void UnRegisterAGAlloc(plAGChannel *object)
|
||
|
{
|
||
|
agAllocMap::iterator i = gAGAllocs.find(object);
|
||
|
if(i != gAGAllocs.end())
|
||
|
{
|
||
|
agAlloc * al = (*i).second;
|
||
|
|
||
|
gAGAllocs.erase(i);
|
||
|
delete al;
|
||
|
}
|
||
|
}
|