mirror of
https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git
synced 2025-07-19 19:59:09 +00:00
Hoist MOULOpenSourceClientPlugin/Plasma20/* to top level
to match H'uru layout and make patching/cherry-picking easier.
This commit is contained in:
822
Sources/Plasma/PubUtilLib/plAvatar/plAGMasterMod.cpp
Normal file
822
Sources/Plasma/PubUtilLib/plAvatar/plAGMasterMod.cpp
Normal file
@ -0,0 +1,822 @@
|
||||
/*==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==*/
|
||||
// singular
|
||||
#include "plAGMasterMod.h"
|
||||
|
||||
// local
|
||||
#include "plAGAnim.h"
|
||||
#include "plAGAnimInstance.h"
|
||||
#include "plAGModifier.h"
|
||||
// #include "plAvatarAnim.h"
|
||||
#include "plAGMasterSDLModifier.h"
|
||||
#include "plMatrixChannel.h"
|
||||
|
||||
// global
|
||||
#include "hsResMgr.h"
|
||||
#include "plgDispatch.h"
|
||||
|
||||
// other
|
||||
// #include "../pnMessage/plRefMsg.h"
|
||||
#include "../plMessage/plAnimCmdMsg.h"
|
||||
#include "../pnMessage/plSDLModifierMsg.h"
|
||||
#include "../pnMessage/plSDLNotificationMsg.h"
|
||||
#include "../pnMessage/plTimeMsg.h"
|
||||
#include "../pnSceneObject/plSceneObject.h"
|
||||
#include "../pnSceneObject/plCoordinateInterface.h"
|
||||
|
||||
////////////////
|
||||
// PLAGMASTERMOD
|
||||
////////////////
|
||||
// Coordinates the activities of a bunch of plAGModifiers
|
||||
// std::map<char *, plAGMasterMod *, stringISorter> plAGMasterMod::fInstances;
|
||||
|
||||
// CTOR
|
||||
plAGMasterMod::plAGMasterMod()
|
||||
: fTarget(nil),
|
||||
fNeedEval(false),
|
||||
fFirstEval(true),
|
||||
fAGMasterSDLMod(nil),
|
||||
fNeedCompile(false),
|
||||
fIsGrouped(false),
|
||||
fIsGroupMaster(false),
|
||||
fMsgForwarder(nil)
|
||||
{
|
||||
}
|
||||
|
||||
// DTOR
|
||||
plAGMasterMod::~plAGMasterMod()
|
||||
{
|
||||
}
|
||||
|
||||
void plAGMasterMod::Write(hsStream *stream, hsResMgr *mgr)
|
||||
{
|
||||
plModifier::Write(stream, mgr);
|
||||
|
||||
int length = 0;
|
||||
stream->WriteSwap32(length); // backwards compatability. Nuke on next format change.
|
||||
stream->WriteSwap32(fPrivateAnims.size());
|
||||
int i;
|
||||
for (i = 0; i < fPrivateAnims.size(); i++)
|
||||
{
|
||||
mgr->WriteKey(stream, fPrivateAnims[i]->GetKey());
|
||||
}
|
||||
stream->Writebool(fIsGrouped);
|
||||
stream->Writebool(fIsGroupMaster);
|
||||
if (fIsGroupMaster)
|
||||
mgr->WriteKey(stream, fMsgForwarder->GetKey());
|
||||
|
||||
// maybe later... WriteCachedMessages(stream, mgr);
|
||||
}
|
||||
|
||||
void plAGMasterMod::Read(hsStream * stream, hsResMgr *mgr)
|
||||
{
|
||||
plModifier::Read(stream, mgr);
|
||||
|
||||
//////////////////////////////////////////
|
||||
int nameLength = stream->ReadSwap32(); // Unused. Nuke next format change.
|
||||
char *junk = TRACKED_NEW char[nameLength+1]; //
|
||||
stream->Read(nameLength, junk); //
|
||||
junk[nameLength] = 0; //
|
||||
delete [] junk; //
|
||||
//////////////////////////////////////////
|
||||
|
||||
int numPrivateAnims = stream->ReadSwap32();
|
||||
fPrivateAnims.reserve(numPrivateAnims); // pre-allocate for performance
|
||||
int i;
|
||||
for (i = 0; i < numPrivateAnims; i++)
|
||||
{
|
||||
plGenRefMsg* msg = TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kPrivateAnim);
|
||||
mgr->ReadKeyNotifyMe(stream, msg, plRefFlags::kActiveRef);
|
||||
}
|
||||
fIsGrouped = stream->Readbool();
|
||||
fIsGroupMaster = stream->Readbool();
|
||||
if (fIsGroupMaster)
|
||||
{
|
||||
plGenRefMsg* msg = TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, 0);
|
||||
mgr->ReadKeyNotifyMe(stream, msg, plRefFlags::kActiveRef);
|
||||
}
|
||||
|
||||
// maybe later... ReadCachedMessages(stream, mgr);
|
||||
}
|
||||
|
||||
// ADDTARGET
|
||||
// Collect all the plAGModifiers from our children and attach private anims.
|
||||
void plAGMasterMod::AddTarget(plSceneObject * object)
|
||||
{
|
||||
plSynchEnabler p(false); // turn off dirty tracking while in this function
|
||||
|
||||
fTarget = object;
|
||||
int autoIdx = -1;
|
||||
int initialIdx = -1;
|
||||
int timeIdx = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < fPrivateAnims.size(); i++)
|
||||
{
|
||||
plATCAnim *atcAnim = plATCAnim::ConvertNoRef(fPrivateAnims[i]);
|
||||
if (!atcAnim)
|
||||
continue;
|
||||
|
||||
if (atcAnim->GetAutoStart())
|
||||
autoIdx = i;
|
||||
if (atcAnim->GetInitial() != -1)
|
||||
initialIdx = i;
|
||||
if (atcAnim->GetStart() < fPrivateAnims[timeIdx]->GetStart())
|
||||
timeIdx = i;
|
||||
}
|
||||
|
||||
int masterIdx;
|
||||
if (autoIdx != -1)
|
||||
masterIdx = autoIdx; // If something autostarts, it wins.
|
||||
else if (initialIdx != -1)
|
||||
masterIdx = initialIdx; // Otherwise, the fellow with the @initial point wins
|
||||
else
|
||||
masterIdx = timeIdx; // Default case: the earliest anim wins
|
||||
|
||||
for (i = 0; i < fPrivateAnims.size(); i++)
|
||||
{
|
||||
AttachAnimationBlended(fPrivateAnims[i], i == masterIdx ? 1.f : 0.f);
|
||||
}
|
||||
|
||||
// Force one eval after we init
|
||||
plgDispatch::Dispatch()->RegisterForExactType(plEvalMsg::Index(), GetKey());
|
||||
|
||||
if (!fIsGrouped || fIsGroupMaster)
|
||||
{
|
||||
// add sdl modifier
|
||||
delete fAGMasterSDLMod;
|
||||
fAGMasterSDLMod = TRACKED_NEW plAGMasterSDLModifier;
|
||||
object->AddModifier(fAGMasterSDLMod);
|
||||
}
|
||||
}
|
||||
|
||||
void plAGMasterMod::RemoveTarget(plSceneObject* o)
|
||||
{
|
||||
hsAssert(o == fTarget, "Removing target I don't have");
|
||||
|
||||
DetachAllAnimations();
|
||||
|
||||
// remove sdl modifier
|
||||
if (o)
|
||||
{
|
||||
if (fAGMasterSDLMod)
|
||||
o->RemoveModifier(fAGMasterSDLMod);
|
||||
}
|
||||
delete fAGMasterSDLMod;
|
||||
fAGMasterSDLMod=nil;
|
||||
|
||||
fTarget = nil;
|
||||
}
|
||||
|
||||
#include "plProfile.h"
|
||||
|
||||
plProfile_CreateTimer("ApplyAnimation", "Animation", ApplyAnimation);
|
||||
plProfile_CreateTimer(" AffineValue", "Animation", AffineValue);
|
||||
plProfile_CreateTimer(" AffineInterp", "Animation", AffineInterp);
|
||||
plProfile_CreateTimer(" AffineBlend", "Animation", AffineBlend);
|
||||
plProfile_CreateTimer(" AffineCompose", "Animation", AffineCompose);
|
||||
plProfile_CreateTimer(" AffineApplicator", "Animation", MatrixApplicator);
|
||||
plProfile_CreateTimer("AnimatingPhysicals", "Animation", AnimatingPhysicals);
|
||||
plProfile_CreateTimer("StoppedAnimPhysicals", "Animation", StoppedAnimPhysicals);
|
||||
|
||||
// IEVAL
|
||||
hsBool plAGMasterMod::IEval(double secs, hsScalar del, UInt32 dirty)
|
||||
{
|
||||
if (fFirstEval)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < fAnimInstances.size(); i++)
|
||||
fAnimInstances[i]->SearchForGlobals();
|
||||
|
||||
fFirstEval = false;
|
||||
}
|
||||
ApplyAnimations(secs, del);
|
||||
|
||||
// We might get registered for just a single eval. If we don't need to eval anymore, unregister
|
||||
if (!fNeedEval)
|
||||
plgDispatch::Dispatch()->UnRegisterForExactType(plEvalMsg::Index(), GetKey());
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// APPLYANIMATIONS
|
||||
void plAGMasterMod::ApplyAnimations(double time, hsScalar elapsed)
|
||||
{
|
||||
plProfile_BeginLap(ApplyAnimation, this->GetKey()->GetUoid().GetObjectName());
|
||||
|
||||
// update any fades
|
||||
for (int i = 0; i < fAnimInstances.size(); i++)
|
||||
{
|
||||
fAnimInstances[i]->ProcessFade(elapsed);
|
||||
}
|
||||
|
||||
AdvanceAnimsToTime(time);
|
||||
|
||||
plProfile_EndLap(ApplyAnimation,this->GetKey()->GetUoid().GetObjectName());
|
||||
}
|
||||
|
||||
void plAGMasterMod::AdvanceAnimsToTime(double time)
|
||||
{
|
||||
if(fNeedCompile)
|
||||
Compile(time);
|
||||
|
||||
for(plChannelModMap::iterator j = fChannelMods.begin(); j != fChannelMods.end(); j++)
|
||||
{
|
||||
plAGModifier *mod = (*j).second;
|
||||
mod->Apply(time);
|
||||
}
|
||||
}
|
||||
|
||||
void plAGMasterMod::SetNeedCompile(bool needCompile)
|
||||
{
|
||||
fNeedCompile = true;
|
||||
}
|
||||
|
||||
void plAGMasterMod::Compile(double time)
|
||||
{
|
||||
plChannelModMap::iterator end = fChannelMods.end();
|
||||
fNeedCompile = false;
|
||||
|
||||
for(plChannelModMap::iterator j = fChannelMods.begin(); j != end; j++)
|
||||
{
|
||||
plAGModifier *mod = (*j).second;
|
||||
plAGApplicator *app = mod->GetApplicator(kAGPinTransform);
|
||||
|
||||
if(app) {
|
||||
plAGChannel *channel = app->GetChannel();
|
||||
if(channel)
|
||||
{
|
||||
plMatrixChannel *topChannel = plMatrixChannel::ConvertNoRef(channel);
|
||||
if(topChannel)
|
||||
topChannel->Optimize(time);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void plAGMasterMod::DumpAniGraph(const char *justThisChannel, bool optimized, double time)
|
||||
{
|
||||
plChannelModMap::iterator end = fChannelMods.end();
|
||||
fNeedCompile = false;
|
||||
|
||||
for(plChannelModMap::iterator j = fChannelMods.begin(); j != end; j++)
|
||||
{
|
||||
plAGModifier *mod = (*j).second;
|
||||
if(!justThisChannel || stricmp(justThisChannel, mod->GetChannelName()) == 0)
|
||||
{
|
||||
plAGApplicator *app = mod->GetApplicator(kAGPinTransform);
|
||||
|
||||
if(app) {
|
||||
plAGChannel *channel = app->GetChannel();
|
||||
if(channel)
|
||||
{
|
||||
plMatrixChannel *topChannel = plMatrixChannel::ConvertNoRef(channel);
|
||||
if(topChannel)
|
||||
{
|
||||
hsStatusMessageF("AGModifier: <%s>", mod->GetChannelName());
|
||||
topChannel->Dump(1, optimized, time);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(justThisChannel)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GETCHANNELMOD(name)
|
||||
// Get the modifier that controls the channel with the given name
|
||||
plAGModifier * plAGMasterMod::GetChannelMod(const char * name, hsBool dontCache ) const
|
||||
{
|
||||
plAGModifier * result = nil;
|
||||
std::map<const char *, plAGModifier *, stringSorter>::const_iterator i = fChannelMods.find(name);
|
||||
|
||||
if (i != fChannelMods.end()) {
|
||||
result = (*i).second;
|
||||
} else {
|
||||
plSceneObject *SO = GetTarget(0);
|
||||
if(SO) {
|
||||
result = IFindChannelMod(SO, name);
|
||||
if(result && !dontCache) {
|
||||
ICacheChannelMod(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// CACHECHANNELMOD
|
||||
plAGModifier * plAGMasterMod::ICacheChannelMod(plAGModifier *mod) const
|
||||
{
|
||||
plGenRefMsg* msg = TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, 0);
|
||||
hsgResMgr::ResMgr()->SendRef(mod, msg, plRefFlags::kActiveRef);
|
||||
|
||||
return mod;
|
||||
}
|
||||
|
||||
// IFINDAGMOD (sceneObject)
|
||||
// See if there's an ag modifier on this sceneobject.
|
||||
// Doesn't check for multiples; just returns the first one.
|
||||
plAGModifier * plAGMasterMod::IFindChannelMod(const plSceneObject *SO, const char *name) const
|
||||
{
|
||||
const plCoordinateInterface * CI = SO->GetCoordinateInterface();
|
||||
|
||||
const plAGModifier * constMod = static_cast<const plAGModifier *>(FindModifierByClass(SO, plAGModifier::Index()));
|
||||
plAGModifier * mod = const_cast<plAGModifier *>(constMod);
|
||||
|
||||
if(mod)
|
||||
{
|
||||
const char *modName = mod->GetChannelName();
|
||||
if(stricmp(name, modName) == 0)
|
||||
return mod;
|
||||
}
|
||||
|
||||
if(CI)
|
||||
{
|
||||
int childCount = CI->GetNumChildren();
|
||||
for (int i = 0; i < childCount; i++)
|
||||
{
|
||||
const plSceneObject * subChild = CI->GetChild(i)->GetOwner();
|
||||
plAGModifier * mod = IFindChannelMod(subChild, name);
|
||||
|
||||
if(mod)
|
||||
return mod;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
// ATTACHANIMATIONBLENDED(anim, blend)
|
||||
plAGAnimInstance * plAGMasterMod::AttachAnimationBlended(plAGAnim *anim,
|
||||
hsScalar blendFactor /* = 0 */,
|
||||
UInt16 blendPriority /* plAGMedBlendPriority */,
|
||||
hsBool cache /* = false */)
|
||||
{
|
||||
plAGAnimInstance *instance = nil;
|
||||
plAnimVector::iterator i;
|
||||
if(anim)
|
||||
{
|
||||
fNeedCompile = true; // need to recompile the graph since we're editing it...
|
||||
for (i = fPrivateAnims.begin(); i != fPrivateAnims.end(); i++)
|
||||
{
|
||||
if (*i == anim)
|
||||
break;
|
||||
}
|
||||
if (i == fPrivateAnims.end()) // Didn't find it. Ref it!
|
||||
{
|
||||
plGenRefMsg* msg = TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kPublicAnim);
|
||||
hsgResMgr::ResMgr()->SendRef(anim, msg, plRefFlags::kActiveRef);
|
||||
}
|
||||
instance = TRACKED_NEW plAGAnimInstance(anim, this, blendFactor, blendPriority, cache, false);
|
||||
fAnimInstances.push_back(instance);
|
||||
|
||||
plATCAnim *atcAnim = plATCAnim::ConvertNoRef(anim);
|
||||
if (atcAnim)
|
||||
{
|
||||
fATCAnimInstances.push_back(instance);
|
||||
ISetupMarkerCallbacks(atcAnim, instance->GetTimeConvert());
|
||||
}
|
||||
IRegForEval(HasRunningAnims());
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
// ATTACHANIMATIONBLENDED(name, blend)
|
||||
plAGAnimInstance * plAGMasterMod::AttachAnimationBlended(const char *name, hsScalar blendFactor /* = 0 */, UInt16 blendPriority, hsBool cache /* = false */)
|
||||
{
|
||||
plAGAnimInstance *instance = nil;
|
||||
plAGAnim *anim = plAGAnim::FindAnim(name);
|
||||
|
||||
if(anim)
|
||||
{
|
||||
instance = AttachAnimationBlended(anim, blendFactor, blendPriority, cache);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
void plAGMasterMod::PlaySimpleAnim(const char *name)
|
||||
{
|
||||
plATCAnim *anim = plATCAnim::ConvertNoRef(plAGAnim::FindAnim(name));
|
||||
plAGAnimInstance *instance = nil;
|
||||
if (anim)
|
||||
{
|
||||
if (FindAnimInstance(name))
|
||||
return;
|
||||
|
||||
instance = AttachAnimationBlended(anim, 1.f, (UInt16)kAGMaxBlendPriority, false);
|
||||
}
|
||||
|
||||
if (instance)
|
||||
{
|
||||
instance->SetLoop(false);
|
||||
instance->Start();
|
||||
|
||||
plAGDetachCallbackMsg *msg = TRACKED_NEW plAGDetachCallbackMsg(GetKey(), kStop);
|
||||
msg->SetAnimName(name);
|
||||
instance->GetTimeConvert()->AddCallback(msg);
|
||||
hsRefCnt_SafeUnRef(msg);
|
||||
}
|
||||
}
|
||||
|
||||
// FINDANIMINSTANCE
|
||||
// Look for an animation instance of the given name on the modifier.
|
||||
// If we need this to be fast, should make it a map rather than a vector
|
||||
plAGAnimInstance * plAGMasterMod::FindAnimInstance(const char *name)
|
||||
{
|
||||
plAGAnimInstance *result = nil;
|
||||
|
||||
if (name)
|
||||
{
|
||||
for (int i = 0; i < fAnimInstances.size(); i++)
|
||||
{
|
||||
plAGAnimInstance *act = fAnimInstances[i];
|
||||
const char *eachName = act->GetName();
|
||||
|
||||
if( stricmp(eachName, name) == 0)
|
||||
{
|
||||
result = act;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// FINDORATTACHINSTANCE
|
||||
plAGAnimInstance * plAGMasterMod::FindOrAttachInstance(const char *name, hsScalar blendFactor)
|
||||
{
|
||||
plAGAnimInstance *result = FindAnimInstance(name);
|
||||
if(result)
|
||||
{
|
||||
// if it's already attached, we need to set the blend
|
||||
result->SetBlend(blendFactor);
|
||||
} else {
|
||||
result = AttachAnimationBlended(name, blendFactor);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// GETANIMINSTANCE
|
||||
plAGAnimInstance * plAGMasterMod::GetAnimInstance(int i)
|
||||
{
|
||||
return fAnimInstances[i];
|
||||
}
|
||||
|
||||
// GETNUMANIMATIONS
|
||||
int plAGMasterMod::GetNumAnimations()
|
||||
{
|
||||
return fAnimInstances.size();
|
||||
}
|
||||
|
||||
// GETNUMPRIVATEANIMATIONS
|
||||
int plAGMasterMod::GetNumPrivateAnimations()
|
||||
{
|
||||
return fPrivateAnims.size();
|
||||
}
|
||||
|
||||
int plAGMasterMod::GetNumATCAnimations()
|
||||
{
|
||||
return fATCAnimInstances.size();
|
||||
}
|
||||
|
||||
plAGAnimInstance *plAGMasterMod::GetATCAnimInstance(int i)
|
||||
{
|
||||
return fATCAnimInstances[i];
|
||||
}
|
||||
|
||||
void plAGMasterMod::DetachAllAnimations()
|
||||
{
|
||||
int nInstances = fAnimInstances.size();
|
||||
|
||||
for (int i = nInstances - 1; i >= 0; i--)
|
||||
{
|
||||
plAGAnimInstance * instance = fAnimInstances[i];
|
||||
if(instance)
|
||||
{
|
||||
DetachAnimation(instance);
|
||||
// delete instance;
|
||||
}
|
||||
}
|
||||
fAnimInstances.clear();
|
||||
fPrivateAnims.clear();
|
||||
fATCAnimInstances.clear();
|
||||
}
|
||||
|
||||
// DETACHANIMATION(plAGAnimInstance *)
|
||||
void plAGMasterMod::DetachAnimation(plAGAnimInstance *anim)
|
||||
{
|
||||
plInstanceVector::iterator i;
|
||||
plAnimVector::iterator j;
|
||||
|
||||
fNeedCompile = true; // need to recompile the graph since we're editing it...
|
||||
|
||||
for ( i = fAnimInstances.begin(); i != fAnimInstances.end(); i++)
|
||||
{
|
||||
plAGAnimInstance *instance = *i;
|
||||
|
||||
if(instance == anim)
|
||||
{
|
||||
// DetachAnimation(instance);
|
||||
instance->DetachChannels();
|
||||
|
||||
// Need to release it if it's not a private anim
|
||||
const plAGAnim *agAnim = instance->GetAnimation();
|
||||
for (j = fPrivateAnims.begin(); j != fPrivateAnims.end(); j++)
|
||||
{
|
||||
if (*j == agAnim)
|
||||
break;
|
||||
}
|
||||
if (j == fPrivateAnims.end()) // We didn't find it
|
||||
GetKey()->Release(agAnim->GetKey());
|
||||
|
||||
delete instance;
|
||||
i = fAnimInstances.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for ( i = fATCAnimInstances.begin(); i != fATCAnimInstances.end(); i++)
|
||||
{
|
||||
plAGAnimInstance *instance = *i;
|
||||
|
||||
if(instance == anim)
|
||||
{
|
||||
i = fATCAnimInstances.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DETACHANIMATION(name)
|
||||
void plAGMasterMod::DetachAnimation(const char *name)
|
||||
{
|
||||
plAGAnimInstance *anim = FindAnimInstance(name);
|
||||
if(anim) {
|
||||
DetachAnimation(anim);
|
||||
}
|
||||
}
|
||||
|
||||
void plAGMasterMod::DumpCurrentAnims(const char *header)
|
||||
{
|
||||
if(header)
|
||||
hsStatusMessageF("Dumping Armature Anim Stack: %s", header);
|
||||
int nAnims = fAnimInstances.size();
|
||||
for(int i = nAnims - 1; i >= 0; i--)
|
||||
{
|
||||
plAGAnimInstance *inst = fAnimInstances[i];
|
||||
const char *name = inst->GetName();
|
||||
float blend = inst->GetBlend();
|
||||
|
||||
hsStatusMessageF("%d: %s with blend of %f\n", i, name, blend);
|
||||
}
|
||||
}
|
||||
|
||||
// MSGRECEIVE
|
||||
// receive trigger messages
|
||||
hsBool plAGMasterMod::MsgReceive(plMessage* msg)
|
||||
{
|
||||
plAnimCmdMsg* cmdMsg;
|
||||
plAGCmdMsg* agMsg;
|
||||
int i;
|
||||
|
||||
plSDLNotificationMsg* nMsg = plSDLNotificationMsg::ConvertNoRef(msg);
|
||||
if (nMsg)
|
||||
{
|
||||
// Force a single eval
|
||||
plgDispatch::Dispatch()->RegisterForExactType(plEvalMsg::Index(), GetKey());
|
||||
return true;
|
||||
}
|
||||
|
||||
if (cmdMsg = plAnimCmdMsg::ConvertNoRef(msg))
|
||||
{
|
||||
const char *targetName = cmdMsg->GetAnimName();
|
||||
|
||||
if (!targetName)
|
||||
targetName = ENTIRE_ANIMATION_NAME;
|
||||
|
||||
plAGAnimInstance *inst = FindAnimInstance(targetName);
|
||||
if (inst != nil)
|
||||
{
|
||||
if (cmdMsg->CmdChangesAnimTime())
|
||||
{
|
||||
for (i = 0; i < GetNumAnimations(); i++)
|
||||
{
|
||||
plAGAnimInstance *currInst = GetAnimInstance(i);
|
||||
if (currInst != inst && currInst->GetAnimation()->SharesPinsWith(inst->GetAnimation()))
|
||||
currInst->SetBlend(0);
|
||||
}
|
||||
inst->SetBlend(1);
|
||||
}
|
||||
|
||||
inst->HandleCmd(cmdMsg);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (agMsg = plAGCmdMsg::ConvertNoRef(msg))
|
||||
{
|
||||
if (agMsg->Cmd(plAGCmdMsg::kSetAnimTime))
|
||||
{
|
||||
for (int i = 0; i < fAnimInstances.size(); i++)
|
||||
{
|
||||
plAGAnimInstance *inst = fAnimInstances[i];
|
||||
inst->SetCurrentTime(agMsg->fAnimTime, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
plAGAnimInstance *inst = FindAnimInstance(agMsg->GetAnimName());
|
||||
if (inst != nil)
|
||||
{
|
||||
if (agMsg->Cmd(plAGCmdMsg::kSetBlend))
|
||||
inst->Fade(agMsg->fBlend, agMsg->fBlendRate, plAGAnimInstance::kFadeBlend);
|
||||
if (agMsg->Cmd(plAGCmdMsg::kSetAmp))
|
||||
inst->Fade(agMsg->fAmp, agMsg->fAmpRate, plAGAnimInstance::kFadeAmp);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
plAGInstanceCallbackMsg *agicMsg = plAGInstanceCallbackMsg::ConvertNoRef(msg);
|
||||
if (agicMsg != nil)
|
||||
{
|
||||
if (agicMsg->fEvent == kStart)
|
||||
{
|
||||
IRegForEval(true);
|
||||
}
|
||||
else if (agicMsg->fEvent == kStop)
|
||||
{
|
||||
if (!HasRunningAnims())
|
||||
IRegForEval(false);
|
||||
}
|
||||
else // Just force a single eval
|
||||
{
|
||||
plgDispatch::Dispatch()->RegisterForExactType(plEvalMsg::Index(), GetKey());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
plAGDetachCallbackMsg *detachMsg = plAGDetachCallbackMsg::ConvertNoRef(msg);
|
||||
if (detachMsg != nil)
|
||||
{
|
||||
DetachAnimation(detachMsg->GetAnimName());
|
||||
}
|
||||
|
||||
plGenRefMsg *genRefMsg;
|
||||
if (genRefMsg = plGenRefMsg::ConvertNoRef(msg))
|
||||
{
|
||||
plAGAnim *anim;
|
||||
if (anim = plAGAnim::ConvertNoRef(genRefMsg->GetRef()))
|
||||
{
|
||||
if (genRefMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest))
|
||||
{
|
||||
if (genRefMsg->fType == kPrivateAnim)
|
||||
fPrivateAnims.push_back(anim);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (genRefMsg->fType == kPrivateAnim)
|
||||
{
|
||||
plAnimVector::iterator i = fPrivateAnims.begin();
|
||||
for (i; i != fPrivateAnims.end(); i++)
|
||||
{
|
||||
plAGAnim *currAnim = *i;
|
||||
|
||||
if(currAnim == anim)
|
||||
{
|
||||
i = fPrivateAnims.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
plAGModifier *agmod;
|
||||
if (agmod = plAGModifier::ConvertNoRef(genRefMsg->GetRef()))
|
||||
{
|
||||
if (genRefMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest))
|
||||
fChannelMods[agmod->GetChannelName()] = agmod;
|
||||
else
|
||||
fChannelMods.erase(agmod->GetChannelName());
|
||||
|
||||
return true;
|
||||
}
|
||||
plMsgForwarder *msgfwd;
|
||||
if (msgfwd = plMsgForwarder::ConvertNoRef(genRefMsg->GetRef()))
|
||||
{
|
||||
if (genRefMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest))
|
||||
fMsgForwarder = msgfwd;
|
||||
else
|
||||
fMsgForwarder = nil;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
plRefMsg* refMsg = plRefMsg::ConvertNoRef(msg);
|
||||
if( refMsg )
|
||||
{
|
||||
if( refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace) )
|
||||
AddTarget(plSceneObject::ConvertNoRef(refMsg->GetRef()));
|
||||
else
|
||||
RemoveTarget(plSceneObject::ConvertNoRef(refMsg->GetRef()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return plModifier::MsgReceive(msg);
|
||||
}
|
||||
|
||||
void plAGMasterMod::IRegForEval(hsBool val)
|
||||
{
|
||||
if (fNeedEval == val)
|
||||
return;
|
||||
|
||||
fNeedEval = val;
|
||||
if (val)
|
||||
plgDispatch::Dispatch()->RegisterForExactType(plEvalMsg::Index(), GetKey());
|
||||
else
|
||||
plgDispatch::Dispatch()->UnRegisterForExactType(plEvalMsg::Index(), GetKey());
|
||||
}
|
||||
|
||||
hsBool plAGMasterMod::HasRunningAnims()
|
||||
{
|
||||
int i;
|
||||
hsBool needEval = false;
|
||||
for (i = 0; i < fAnimInstances.size(); i++)
|
||||
{
|
||||
if (!fAnimInstances[i]->IsFinished())
|
||||
{
|
||||
needEval = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return needEval;
|
||||
}
|
||||
|
||||
//
|
||||
// Send SDL sendState msg to object's plAGMasterSDLModifier
|
||||
//
|
||||
hsBool plAGMasterMod::DirtySynchState(const char* SDLStateName, UInt32 synchFlags)
|
||||
{
|
||||
if(GetNumTargets() > 0 && (!fIsGrouped || fIsGroupMaster))
|
||||
{
|
||||
plSceneObject *sObj = GetTarget(0);
|
||||
if(sObj)
|
||||
return sObj->DirtySynchState(SDLStateName, synchFlags);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void plAGMasterMod::SetIsGroupMaster(bool master, plMsgForwarder* msgForwarder)
|
||||
{
|
||||
fIsGroupMaster = master;
|
||||
fMsgForwarder = msgForwarder;
|
||||
}
|
||||
|
||||
void plAGMasterMod::SetIsGrouped(bool grouped)
|
||||
{
|
||||
fIsGrouped = true;
|
||||
}
|
Reference in New Issue
Block a user