|
|
|
/*==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==*/
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// INCLUDES
|
|
|
|
//
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// singular
|
|
|
|
#include "plAGAnim.h"
|
|
|
|
|
|
|
|
// local
|
|
|
|
#include "plMatrixChannel.h"
|
|
|
|
|
|
|
|
// global
|
|
|
|
#include "hsResMgr.h"
|
|
|
|
|
|
|
|
// other
|
|
|
|
#include "../plMessage/plAnimCmdMsg.h"
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// STATICS
|
|
|
|
//
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
plAGAnim::plAnimMap plAGAnim::fAllAnims;
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// plAGAnim
|
|
|
|
//
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
// ctor ------------
|
|
|
|
// -----
|
|
|
|
plAGAnim::plAGAnim()
|
|
|
|
: plSynchedObject()
|
|
|
|
{
|
|
|
|
fName = nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ctor ------------------------------------------------------
|
|
|
|
// -----
|
|
|
|
plAGAnim::plAGAnim(const char *name, double start, double end)
|
|
|
|
: fStart((hsScalar)start),
|
|
|
|
fEnd((hsScalar)end)
|
|
|
|
{
|
|
|
|
if (name == nil)
|
|
|
|
name = "";
|
|
|
|
|
|
|
|
fName = TRACKED_NEW char[strlen(name) + 1];
|
|
|
|
strcpy(fName, name);
|
|
|
|
}
|
|
|
|
|
|
|
|
// dtor -------------
|
|
|
|
// -----
|
|
|
|
plAGAnim::~plAGAnim()
|
|
|
|
{
|
|
|
|
if (fName)
|
|
|
|
{
|
|
|
|
RemoveAnim(fName);
|
|
|
|
delete[] fName;
|
|
|
|
fName = nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
//int numChannels = fChannels.size();
|
|
|
|
int numApps = fApps.size();
|
|
|
|
|
|
|
|
for (int i = 0; i < numApps; i++)
|
|
|
|
{
|
|
|
|
plAGApplicator *app = fApps[i];
|
|
|
|
if (app)
|
|
|
|
{
|
|
|
|
plAGChannel *channel = app->GetChannel();
|
|
|
|
if(channel)
|
|
|
|
delete channel;
|
|
|
|
|
|
|
|
delete app;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetChannelCount ------------------
|
|
|
|
// ----------------
|
|
|
|
int plAGAnim::GetChannelCount() const
|
|
|
|
{
|
|
|
|
return fApps.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetChannel -------------------------------------
|
|
|
|
// -----------
|
|
|
|
plAGChannel * plAGAnim::GetChannel(int index) const
|
|
|
|
{
|
|
|
|
plAGApplicator *app = fApps[index];
|
|
|
|
return (app ? app->GetChannel() : nil);
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetChannel --------------------------------------------
|
|
|
|
// -----------
|
|
|
|
plAGChannel * plAGAnim::GetChannel(const char *name) const
|
|
|
|
{
|
|
|
|
int appCount = fApps.size();
|
|
|
|
|
|
|
|
for(int i = 0; i < appCount; i++)
|
|
|
|
{
|
|
|
|
plAGApplicator *app = fApps[i];
|
|
|
|
plAGChannel *channel = app->GetChannel();
|
|
|
|
const char *channelName = app->GetChannelName();
|
|
|
|
|
|
|
|
if(stricmp(name, channelName) == 0)
|
|
|
|
{
|
|
|
|
return channel;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetApplicatorCount ------------------
|
|
|
|
// -------------------
|
|
|
|
int plAGAnim::GetApplicatorCount() const
|
|
|
|
{
|
|
|
|
return fApps.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetApplicator -----------------------------------
|
|
|
|
// --------------
|
|
|
|
plAGApplicator *plAGAnim::GetApplicator(int i) const
|
|
|
|
{
|
|
|
|
return fApps[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
// AddApplicator -------------------------------
|
|
|
|
// --------------
|
|
|
|
int plAGAnim::AddApplicator(plAGApplicator *app)
|
|
|
|
{
|
|
|
|
hsAssert(app->GetChannel(), "Adding an applicator with no channel");
|
|
|
|
fApps.push_back(app);
|
|
|
|
|
|
|
|
// return the index of the channel
|
|
|
|
return(fApps.size() - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
// RemoveApplicator ------------------------
|
|
|
|
// -----------------
|
|
|
|
hsBool plAGAnim::RemoveApplicator(int index)
|
|
|
|
{
|
|
|
|
hsAssert(index < fApps.size(), "Out of range index for plAGAnim::RemoveApp()");
|
|
|
|
|
|
|
|
if(index < fApps.size())
|
|
|
|
{
|
|
|
|
fApps.erase(fApps.begin() + index);
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ExtendToLength ----------------------------
|
|
|
|
// ---------------
|
|
|
|
void plAGAnim::ExtendToLength(hsScalar length)
|
|
|
|
{
|
|
|
|
if (length > GetEnd())
|
|
|
|
SetEnd(length);
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetChannelName ------------------------------
|
|
|
|
// ---------------
|
|
|
|
const char * plAGAnim::GetChannelName(int index)
|
|
|
|
{
|
|
|
|
hsAssert(index < fApps.size(), "Out of range index for plAGAnim::GetChannelName()");
|
|
|
|
|
|
|
|
if(index < fApps.size())
|
|
|
|
{
|
|
|
|
return fApps[index]->GetChannel()->GetName();
|
|
|
|
} else {
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read --------------------------------------------
|
|
|
|
// -----
|
|
|
|
void plAGAnim::Read(hsStream *stream, hsResMgr *mgr)
|
|
|
|
{
|
|
|
|
plSynchedObject::Read(stream, mgr);
|
|
|
|
|
|
|
|
// read in the name of the animation itself
|
|
|
|
fName = stream->ReadSafeString();
|
|
|
|
|
|
|
|
fStart = stream->ReadSwapScalar();
|
|
|
|
fEnd = stream->ReadSwapScalar();
|
|
|
|
|
|
|
|
int numApps = stream->ReadSwap32();
|
|
|
|
|
|
|
|
fApps.reserve(numApps); // pre-allocate for performance
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < numApps; i++)
|
|
|
|
{
|
|
|
|
plAGApplicator * app = plAGApplicator::ConvertNoRef(mgr->ReadCreatable(stream));
|
|
|
|
app->SetChannel(plAGChannel::ConvertNoRef(mgr->ReadCreatable(stream)));
|
|
|
|
fApps.push_back(app);
|
|
|
|
}
|
|
|
|
plAGAnim::AddAnim(fName, this);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Write --------------------------------------------
|
|
|
|
// ------
|
|
|
|
void plAGAnim::Write(hsStream *stream, hsResMgr *mgr)
|
|
|
|
{
|
|
|
|
plSynchedObject::Write(stream, mgr);
|
|
|
|
|
|
|
|
stream->WriteSafeString(fName);
|
|
|
|
|
|
|
|
stream->WriteSwapScalar(fStart);
|
|
|
|
stream->WriteSwapScalar(fEnd);
|
|
|
|
|
|
|
|
int numApps = fApps.size();
|
|
|
|
|
|
|
|
stream->WriteSwap32(numApps);
|
|
|
|
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < numApps; i++)
|
|
|
|
{
|
|
|
|
plAGApplicator *app = fApps[i];
|
|
|
|
hsAssert(app, "Missing applicator during write.");
|
|
|
|
plAGChannel *channel = nil;
|
|
|
|
if (app)
|
|
|
|
channel = app->GetChannel();
|
|
|
|
|
|
|
|
hsAssert(channel, "Missing channel during write.");
|
|
|
|
mgr->WriteCreatable(stream, app);
|
|
|
|
mgr->WriteCreatable(stream, channel);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void plAGAnim::ClearAnimationRegistry()
|
|
|
|
{
|
|
|
|
fAllAnims.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
// AddAnim ----------------------------------------------
|
|
|
|
// --------
|
|
|
|
void plAGAnim::AddAnim(const char * name, plAGAnim *anim)
|
|
|
|
{
|
|
|
|
// Only register the animation if it's got a "real" name. Unnamed animations
|
|
|
|
// all get the same standard name.
|
|
|
|
if(strcmp(name, ENTIRE_ANIMATION_NAME) != 0)
|
|
|
|
{
|
|
|
|
hsAssert(anim, "registering nil anim");
|
|
|
|
fAllAnims[name] = anim;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// FindAnim -----------------------------------
|
|
|
|
// ---------
|
|
|
|
plAGAnim * plAGAnim::FindAnim(const char *name)
|
|
|
|
{
|
|
|
|
plAnimMap::iterator i = fAllAnims.find(name);
|
|
|
|
|
|
|
|
if(i != fAllAnims.end())
|
|
|
|
{
|
|
|
|
return (*i).second;
|
|
|
|
} else {
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// RemoveAnim -------------------------------
|
|
|
|
// -----------
|
|
|
|
hsBool plAGAnim::RemoveAnim(const char *name)
|
|
|
|
{
|
|
|
|
plAnimMap::iterator i = fAllAnims.find(name);
|
|
|
|
|
|
|
|
if(i != fAllAnims.end())
|
|
|
|
{
|
|
|
|
fAllAnims.erase(i);
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// DumpAnimationRegistry -------------
|
|
|
|
// ----------------------
|
|
|
|
void plAGAnim::DumpAnimationRegistry()
|
|
|
|
{
|
|
|
|
plAnimMap::iterator i = fAllAnims.begin();
|
|
|
|
int j = 0;
|
|
|
|
|
|
|
|
do {
|
|
|
|
plAGAnim *anim = (*i).second;
|
|
|
|
const char *name = anim->GetName();
|
|
|
|
hsStatusMessageF("GLOBAL ANIMS [%d]: <%s>", j++, name);
|
|
|
|
} while(++i != fAllAnims.end());
|
|
|
|
}
|
|
|
|
|
|
|
|
// SharesPinsWith -----------------------------------------
|
|
|
|
// ---------------
|
|
|
|
hsBool plAGAnim::SharesPinsWith(const plAGAnim *anim) const
|
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
for (i = 0; i < fApps.size(); i++)
|
|
|
|
{
|
|
|
|
for (j = 0; j < anim->fApps.size(); j++)
|
|
|
|
{
|
|
|
|
if (!strcmp(fApps[i]->GetChannelName(), anim->fApps[j]->GetChannelName()) &&
|
|
|
|
fApps[i]->CanBlend(anim->fApps[j]))
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// plATCAnim
|
|
|
|
//
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
// ctor --------------
|
|
|
|
// -----
|
|
|
|
plATCAnim::plATCAnim()
|
|
|
|
: plAGAnim()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
// ctor --------------------------------------------------------
|
|
|
|
// -----
|
|
|
|
plATCAnim::plATCAnim(const char *name, double start, double end)
|
|
|
|
: plAGAnim(name, start, end),
|
|
|
|
fInitial(-1),
|
|
|
|
fAutoStart(true),
|
|
|
|
fLoopStart((hsScalar)start),
|
|
|
|
fLoopEnd((hsScalar)end),
|
|
|
|
fLoop(false),
|
|
|
|
fEaseInType(plAnimEaseTypes::kNoEase),
|
|
|
|
fEaseOutType(plAnimEaseTypes::kNoEase),
|
|
|
|
fEaseInLength(0),
|
|
|
|
fEaseOutLength(0),
|
|
|
|
fEaseInMin(0.f),
|
|
|
|
fEaseInMax(0.f),
|
|
|
|
fEaseOutMin(0.f),
|
|
|
|
fEaseOutMax(0.f)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
// dtor ---------------
|
|
|
|
// -----
|
|
|
|
plATCAnim::~plATCAnim()
|
|
|
|
{
|
|
|
|
for (MarkerMap::iterator it = fMarkers.begin(); it != fMarkers.end(); it++)
|
|
|
|
delete [] (char*)it->first;
|
|
|
|
fMarkers.clear();
|
|
|
|
for( LoopMap::iterator it2 = fLoops.begin(); it2 != fLoops.end(); it2++ )
|
|
|
|
delete [] (char *)it2->first;
|
|
|
|
fLoops.clear();
|
|
|
|
fStopPoints.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read ---------------------------------------------
|
|
|
|
// -----
|
|
|
|
void plATCAnim::Read(hsStream *stream, hsResMgr *mgr)
|
|
|
|
{
|
|
|
|
plAGAnim::Read(stream, mgr);
|
|
|
|
|
|
|
|
fInitial = stream->ReadSwapScalar();
|
|
|
|
fAutoStart = stream->Readbool();
|
|
|
|
fLoopStart = stream->ReadSwapScalar();
|
|
|
|
fLoopEnd = stream->ReadSwapScalar();
|
|
|
|
fLoop = stream->Readbool();
|
|
|
|
|
|
|
|
fEaseInType = stream->ReadByte();
|
|
|
|
fEaseInMin = stream->ReadSwapScalar();
|
|
|
|
fEaseInMax = stream->ReadSwapScalar();
|
|
|
|
fEaseInLength = stream->ReadSwapScalar();
|
|
|
|
fEaseOutType = stream->ReadByte();
|
|
|
|
fEaseOutMin = stream->ReadSwapScalar();
|
|
|
|
fEaseOutMax = stream->ReadSwapScalar();
|
|
|
|
fEaseOutLength = stream->ReadSwapScalar();
|
|
|
|
|
|
|
|
int i;
|
|
|
|
int numMarkers = stream->ReadSwap32();
|
|
|
|
for (i = 0; i < numMarkers; i++)
|
|
|
|
{
|
|
|
|
char *name = stream->ReadSafeString();
|
|
|
|
float time = stream->ReadSwapFloat();
|
|
|
|
fMarkers[name] = time;
|
|
|
|
}
|
|
|
|
|
|
|
|
int numLoops = stream->ReadSwap32();
|
|
|
|
for (i = 0; i < numLoops; i++)
|
|
|
|
{
|
|
|
|
char *name = stream->ReadSafeString();
|
|
|
|
float begin = stream->ReadSwapScalar();
|
|
|
|
float end = stream->ReadSwapScalar();
|
|
|
|
fLoops[name] = std::pair<float,float>(begin,end);
|
|
|
|
}
|
|
|
|
|
|
|
|
int numStops = stream->ReadSwap32();
|
|
|
|
for (i = 0; i < numStops; i++)
|
|
|
|
fStopPoints.push_back(stream->ReadSwapScalar());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Write ---------------------------------------------
|
|
|
|
// ------
|
|
|
|
void plATCAnim::Write(hsStream *stream, hsResMgr *mgr)
|
|
|
|
{
|
|
|
|
plAGAnim::Write(stream, mgr);
|
|
|
|
|
|
|
|
stream->WriteSwapScalar(fInitial);
|
|
|
|
stream->Writebool(fAutoStart);
|
|
|
|
stream->WriteSwapScalar(fLoopStart);
|
|
|
|
stream->WriteSwapScalar(fLoopEnd);
|
|
|
|
stream->Writebool(fLoop);
|
|
|
|
|
|
|
|
stream->WriteByte(fEaseInType);
|
|
|
|
stream->WriteSwapScalar(fEaseInMin);
|
|
|
|
stream->WriteSwapScalar(fEaseInMax);
|
|
|
|
stream->WriteSwapScalar(fEaseInLength);
|
|
|
|
stream->WriteByte(fEaseOutType);
|
|
|
|
stream->WriteSwapScalar(fEaseOutMin);
|
|
|
|
stream->WriteSwapScalar(fEaseOutMax);
|
|
|
|
stream->WriteSwapScalar(fEaseOutLength);
|
|
|
|
|
|
|
|
stream->WriteSwap32(fMarkers.size());
|
|
|
|
for (MarkerMap::iterator it = fMarkers.begin(); it != fMarkers.end(); it++)
|
|
|
|
{
|
|
|
|
stream->WriteSafeString(it->first);
|
|
|
|
stream->WriteSwapFloat(it->second);
|
|
|
|
}
|
|
|
|
|
|
|
|
stream->WriteSwap32(fLoops.size());
|
|
|
|
for (LoopMap::iterator loopIt = fLoops.begin(); loopIt != fLoops.end(); loopIt++)
|
|
|
|
{
|
|
|
|
stream->WriteSafeString(loopIt->first);
|
|
|
|
std::pair<float,float>& loop = loopIt->second;
|
|
|
|
stream->WriteSwapFloat(loop.first);
|
|
|
|
stream->WriteSwapFloat(loop.second);
|
|
|
|
}
|
|
|
|
|
|
|
|
int i;
|
|
|
|
stream->WriteSwap32(fStopPoints.size());
|
|
|
|
for (i = 0; i < fStopPoints.size(); i++)
|
|
|
|
stream->WriteSwapScalar(fStopPoints[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
// CheckLoop --------------
|
|
|
|
// ----------
|
|
|
|
void plATCAnim::CheckLoop()
|
|
|
|
{
|
|
|
|
if (fLoopStart == fLoopEnd)
|
|
|
|
{
|
|
|
|
fLoopStart = fStart;
|
|
|
|
fLoopEnd = fEnd;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// AddLoop ------------------------------------------------------
|
|
|
|
// --------
|
|
|
|
void plATCAnim::AddLoop(const char *name, float start, float end)
|
|
|
|
{
|
|
|
|
char *nameCpy = hsStrcpy(name);
|
|
|
|
fLoops[nameCpy] = std::pair<float,float>(start, end);
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetLoop --------------------------------------------------------------
|
|
|
|
// --------
|
|
|
|
bool plATCAnim::GetLoop(const char *name, float &start, float &end) const
|
|
|
|
{
|
|
|
|
LoopMap::const_iterator it = fLoops.find(name);
|
|
|
|
if (it != fLoops.end())
|
|
|
|
{
|
|
|
|
const std::pair<float,float>& loop = (*it).second;
|
|
|
|
start = loop.first;
|
|
|
|
end = loop.second;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetLoop --------------------------------------------------------
|
|
|
|
// --------
|
|
|
|
bool plATCAnim::GetLoop(UInt32 num, float &start, float &end) const
|
|
|
|
{
|
|
|
|
if (num >= fLoops.size())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
LoopMap::const_iterator it = fLoops.begin();
|
|
|
|
|
|
|
|
while (num > 0)
|
|
|
|
{
|
|
|
|
it++;
|
|
|
|
num--;
|
|
|
|
}
|
|
|
|
const std::pair<float,float>& loop = (*it).second;
|
|
|
|
start = loop.first;
|
|
|
|
end = loop.second;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetNumLoops ----------------------
|
|
|
|
// ------------
|
|
|
|
UInt32 plATCAnim::GetNumLoops() const
|
|
|
|
{
|
|
|
|
return fLoops.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
// AddMarker ------------------------------------------
|
|
|
|
// ----------
|
|
|
|
void plATCAnim::AddMarker(const char *name, float time)
|
|
|
|
{
|
|
|
|
char *nameCpy = hsStrcpy(name);
|
|
|
|
fMarkers[nameCpy] = time;
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetMarker -------------------------------------
|
|
|
|
// ----------
|
|
|
|
float plATCAnim::GetMarker(const char *name) const
|
|
|
|
{
|
|
|
|
if (fMarkers.find(name) != fMarkers.end())
|
|
|
|
return (*fMarkers.find(name)).second;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// CopyMarkerNames -------------------------------------
|
|
|
|
// ----------------
|
|
|
|
void plATCAnim::CopyMarkerNames(std::vector<char*> &out)
|
|
|
|
{
|
|
|
|
MarkerMap::iterator it = fMarkers.begin();
|
|
|
|
|
|
|
|
for (; it != fMarkers.end(); it++)
|
|
|
|
{
|
|
|
|
out.push_back(hsStrcpy((*it).first));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// AddStopPoint ---------------------------
|
|
|
|
// -------------
|
|
|
|
void plATCAnim::AddStopPoint(hsScalar time)
|
|
|
|
{
|
|
|
|
fStopPoints.push_back(time);
|
|
|
|
}
|
|
|
|
|
|
|
|
// NumStopPoints ----------------
|
|
|
|
// --------------
|
|
|
|
UInt32 plATCAnim::NumStopPoints()
|
|
|
|
{
|
|
|
|
return fStopPoints.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetStopPoint --------------------------
|
|
|
|
// -------------
|
|
|
|
hsScalar plATCAnim::GetStopPoint(UInt32 i)
|
|
|
|
{
|
|
|
|
hsAssert(i < fStopPoints.size(), "Invalid index for GetStopPoint");
|
|
|
|
return fStopPoints[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// plEmoteAnim
|
|
|
|
//
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
// ctor ------------------
|
|
|
|
// -----
|
|
|
|
plEmoteAnim::plEmoteAnim()
|
|
|
|
: fBodyUsage(kBodyFull)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
// ctor ------------------------------------------------------------------------------
|
|
|
|
// -----
|
|
|
|
plEmoteAnim::plEmoteAnim(const char *animName, double begin, double end, float fadeIn,
|
|
|
|
float fadeOut, BodyUsage bodyUsage)
|
|
|
|
: plATCAnim(animName, begin, end),
|
|
|
|
fFadeIn(fadeIn),
|
|
|
|
fFadeOut(fadeOut),
|
|
|
|
fBodyUsage(bodyUsage)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read -----------------------------------------------
|
|
|
|
// -----
|
|
|
|
void plEmoteAnim::Read(hsStream *stream, hsResMgr *mgr)
|
|
|
|
{
|
|
|
|
plATCAnim::Read(stream, mgr);
|
|
|
|
|
|
|
|
// plAGAnim::RegisterEmote(fName, this);
|
|
|
|
fFadeIn = stream->ReadSwapScalar();
|
|
|
|
fFadeOut = stream->ReadSwapScalar();
|
|
|
|
fBodyUsage = static_cast<BodyUsage>(stream->ReadByte());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// Write -----------------------------------------------
|
|
|
|
// ------
|
|
|
|
void plEmoteAnim::Write(hsStream *stream, hsResMgr *mgr)
|
|
|
|
{
|
|
|
|
plATCAnim::Write(stream, mgr);
|
|
|
|
stream->WriteSwapScalar(fFadeIn);
|
|
|
|
stream->WriteSwapScalar(fFadeOut);
|
|
|
|
stream->WriteByte(static_cast<UInt8>(fBodyUsage));
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetBodyUsage ----------------------------------------
|
|
|
|
// -------------
|
|
|
|
plEmoteAnim::BodyUsage plEmoteAnim::GetBodyUsage() const
|
|
|
|
{
|
|
|
|
return fBodyUsage;
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetFadeIn -----------------------
|
|
|
|
// ----------
|
|
|
|
float plEmoteAnim::GetFadeIn() const
|
|
|
|
{
|
|
|
|
return fFadeIn;
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetFadeOut -----------------------
|
|
|
|
// -----------
|
|
|
|
float plEmoteAnim::GetFadeOut() const
|
|
|
|
{
|
|
|
|
return fFadeOut;
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// plAgeGlobalAnim
|
|
|
|
//
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
// ctor --------------------------
|
|
|
|
// -----
|
|
|
|
plAgeGlobalAnim::plAgeGlobalAnim()
|
|
|
|
: plAGAnim()
|
|
|
|
{
|
|
|
|
fGlobalVarName = nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ctor --------------------------------------------------------------------
|
|
|
|
// -----
|
|
|
|
plAgeGlobalAnim::plAgeGlobalAnim(const char *name, double start, double end)
|
|
|
|
: plAGAnim(name, start, end),
|
|
|
|
fGlobalVarName(nil)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
// dtor ---------------------------
|
|
|
|
// -----
|
|
|
|
plAgeGlobalAnim::~plAgeGlobalAnim()
|
|
|
|
{
|
|
|
|
delete [] fGlobalVarName;
|
|
|
|
}
|
|
|
|
|
|
|
|
void plAgeGlobalAnim::SetGlobalVarName(char *name)
|
|
|
|
{
|
|
|
|
delete [] fGlobalVarName;
|
|
|
|
fGlobalVarName = hsStrcpy(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Read ---------------------------------------------------
|
|
|
|
// -----
|
|
|
|
void plAgeGlobalAnim::Read(hsStream *stream, hsResMgr *mgr)
|
|
|
|
{
|
|
|
|
plAGAnim::Read(stream, mgr);
|
|
|
|
|
|
|
|
fGlobalVarName = stream->ReadSafeString();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Write ---------------------------------------------------
|
|
|
|
// ------
|
|
|
|
void plAgeGlobalAnim::Write(hsStream *stream, hsResMgr *mgr)
|
|
|
|
{
|
|
|
|
plAGAnim::Write(stream, mgr);
|
|
|
|
|
|
|
|
stream->WriteSafeString(fGlobalVarName);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// UTILITIES
|
|
|
|
//
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
// GetStartToEndTransform -----------------------------------------------
|
|
|
|
bool GetStartToEndTransform(const plAGAnim *anim, hsMatrix44 *startToEnd,
|
|
|
|
hsMatrix44 *endToStart, const char *channelName)
|
|
|
|
{
|
|
|
|
double start = 0.0f; // assumed
|
|
|
|
double end = anim->GetEnd();
|
|
|
|
|
|
|
|
GetRelativeTransform(anim, start, end, startToEnd, endToStart, channelName);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetRelativeTransform ---------------------------------------------------
|
|
|
|
bool GetRelativeTransform(const plAGAnim *anim, double timeA, double timeB,
|
|
|
|
hsMatrix44 *a2b, hsMatrix44 *b2a, const char *channelName)
|
|
|
|
{
|
|
|
|
bool result = false;
|
|
|
|
plAGChannel *maybeChannel = anim->GetChannel(channelName);
|
|
|
|
hsAssert(maybeChannel, "Couldn't find channel with given name.");
|
|
|
|
if(maybeChannel)
|
|
|
|
{
|
|
|
|
plMatrixChannel *channel = plMatrixChannel::ConvertNoRef(maybeChannel);
|
|
|
|
hsAssert(channel, "Found channel, but it's not a matrix channel.");
|
|
|
|
|
|
|
|
if(channel)
|
|
|
|
{
|
|
|
|
hsMatrix44 matA;
|
|
|
|
hsMatrix44 matB;
|
|
|
|
|
|
|
|
channel->Value(matA, timeA);
|
|
|
|
channel->Value(matB, timeB);
|
|
|
|
|
|
|
|
if(a2b) // requested a transform from point A to point B
|
|
|
|
{
|
|
|
|
hsMatrix44 invA;
|
|
|
|
matA.GetInverse(&invA);
|
|
|
|
*a2b = invA * matB;
|
|
|
|
}
|
|
|
|
if(b2a) // requested a transform from point B to point A
|
|
|
|
{
|
|
|
|
hsMatrix44 invB;
|
|
|
|
matB.GetInverse(&invB);
|
|
|
|
*b2a = invB * matA;
|
|
|
|
|
|
|
|
if(a2b)
|
|
|
|
{
|
|
|
|
hsMatrix44 invB2;
|
|
|
|
a2b->GetInverse(&invB2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|