You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ryzom-core/code/ryzom/client/src/animation.cpp

243 lines
6.6 KiB
C++

// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "stdpch.h"
/////////////
// INCLUDE //
/////////////
// misc
#include "nel/misc/debug.h"
// Georges
#include "nel/georges/u_form_elm.h"
#include "nel/georges/u_form.h"
#include "nel/georges/u_form_loader.h"
// client
#include "animation.h"
#include "animation_misc.h"
#include "debug_client.h"
#include "client_cfg.h"
#include "entity_animation_manager.h" // \todo GUIGUI : added to recompile animations at loading (to do better ?).
///////////
// USING //
///////////
using namespace NLGEORGES;
using namespace NLSOUND;
using namespace std;
////////////
// METHOD //
////////////
// STATIC
std::set<std::string> CAnimation::MissingAnim;
//-----------------------------------------------
// CAnimation :
// Constructor.
//-----------------------------------------------
CAnimation::CAnimation()
{
_SoundAnim = -1;
_Animation = UnknownAnim;
_Rot = 0.0;
_Sheet = NULL;
}// CAnimation //
//-----------------------------------------------
// Destructor
//-----------------------------------------------
CAnimation::~CAnimation()
{
}// ~CAnimation //
//-----------------------------------------------
// init
//-----------------------------------------------
void CAnimation::init(CAnimationSheet *sheet, NL3D::UAnimationSet *animationSet)
{
_Sheet = sheet;
_FXSet.init(&sheet->FXSet, animationSet);
string animName = _Sheet->AnimNames.get(_Sheet->IdAnim);
computeAnimation(animationSet, animName);
}// init //
//-----------------------------------------------
// computeAnimation :
//-----------------------------------------------
void CAnimation::computeAnimation(NL3D::UAnimationSet *animationSet, const std::string &animName)
{
// Check animationSet.
if(animationSet == 0)
{
nlwarning("CAnimation:computeAnimation: Animation Set is NULL.");
return;
}
// ...
uint id = animationSet->getAnimationIdByName(animName);
if(id == NL3D::UAnimationSet::NotFound)
{
_Animation = animationSet->addAnimation(animName.c_str(), animName.c_str(), ClientCfg.DisplayMissingAnimFile);
if(_Animation == NL3D::UAnimationSet::NotFound)
{
// Up to 100 missing animation kept.
if(MissingAnim.size() < 100)
{
std::pair<std::set<std::string>::iterator, bool> result = MissingAnim.insert(animName);
if(result.second)
nlwarning("CAnimation::computeAnimation: Animation '%s' NOT FOUND.", animName.c_str());
}
}
else
{
if(CAnimationMisc::getAnimationLength(animationSet, _Animation) == 0.0)
nlwarning("CAnimation::computeAnimation: Animation '%s' LENGTH IS 0.", animName.c_str());
// Must store name for reload (or if the sound is not currently enabled)
_SoundAnimName= animName;
// Sound Process.
CSoundAnimManager *sndMngr = CSoundAnimManager::instance();
if(sndMngr)
{
std::string animNameNotConst = animName;
_SoundAnim = sndMngr->loadAnimation(animNameNotConst);
}
}
}
else
{
_Animation = id;
// Must store name for reload (or if the sound is not currently enabled)
_SoundAnimName= animName;
// Sound Process.
CSoundAnimManager *sndMngr = CSoundAnimManager::instance();
if(sndMngr)
{
std::string animNameNotConst = animName;
_SoundAnim = sndMngr->getAnimationFromName(animNameNotConst);
}
}
// Get the rotation in the animation.
_Rot = CAnimationMisc::getAnimationRotation(animationSet, _Animation);
}// computeAnimation //
//-----------------------------------------------
// Return the next animation to play or -1
//-----------------------------------------------
sint8 CAnimation::getNextAnim(const vector<bool> &animFilterStates) const
{
if(_Sheet)
{
if(_Sheet->Next.empty())
return -1;
else
{
static vector<sint8> filteredNextAnim;
static vector<uint16> filteredNextWeight;
filteredNextAnim.clear();
filteredNextWeight.clear();
// compute the filtered weight sum, and filtered next anim list
uint32 weightSum = 0;
uint i;
for( i=0; i<_Sheet->NextWeight.size(); ++i)
{
sint8 nextAnim= _Sheet->Next[i];
if(nextAnim<(sint)animFilterStates.size() && animFilterStates[nextAnim])
{
uint16 nw= _Sheet->NextWeight[i];
weightSum += nw;
filteredNextAnim.push_back(nextAnim);
filteredNextWeight.push_back(nw);
}
}
// if no filter match, abort
if(filteredNextAnim.empty())
return -1;
// choose a random number between 1 and weightsum
uint32 randWeight = rand()%weightSum + 1;
// "concatenate" weights of each index, when the random value is reached we'll have the index to use
uint32 w = 0;
for( i=0; i<filteredNextWeight.size(); ++i)
{
w += filteredNextWeight[i];
if( randWeight <= w )
{
return filteredNextAnim[i];
}
}
nlwarning("<CAnimation::getNextAnim> can't choose next anim, rand=%d weigthSum=%d weightCount=%d",randWeight,weightSum,_Sheet->NextWeight.size());
}
}
return -1;
}// getNextAnim //
//-----------------------------------------------
// resetSoundAnim
//-----------------------------------------------
void CAnimation::resetSoundAnim()
{
_SoundAnim=CSoundAnimationNoId;
}
//-----------------------------------------------
// reloadAnimation() with stored name
//-----------------------------------------------
void CAnimation::reloadSoundAnim()
{
CSoundAnimManager *sndMngr = CSoundAnimManager::instance();
// don't need to reload if already loaded
if(sndMngr && _SoundAnim==CSoundAnimationNoId)
{
// If some sound anim bound
if(!_SoundAnimName.empty())
{
std::string animNameNotConst = _SoundAnimName;
// if already exist, take
_SoundAnim = sndMngr->getAnimationFromName(animNameNotConst);
// else create
if(_SoundAnim==CSoundAnimationNoId)
_SoundAnim = sndMngr->loadAnimation(animNameNotConst);
}
}
}
//-----------------------------------------------
// getNextAnimList
//-----------------------------------------------
const std::vector<sint8> &CAnimation::getNextAnimList() const
{
static std::vector<sint8> emptyList;
if(_Sheet)
return _Sheet->Next;
else
return emptyList;
}