// Ryzom - MMORPG Framework
// 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 .
/////////////
// INCLUDE //
/////////////
#include "stdpch.h" // First include for pre-compiled headers.
// misc
#include "nel/misc/path.h"
// Client
#include "animation_set.h"
#include "animation_misc.h"
#include "debug_client.h"
#include "client_cfg.h"
// Georges
#include "nel/georges/u_form.h"
#include "nel/georges/u_form_elm.h"
#include "nel/georges/u_form_loader.h"
///////////
// USING //
///////////
using namespace NLMISC;
using namespace NLGEORGES;
using namespace std;
////////////
// METHOD //
////////////
//-----------------------------------------------
// CAnimationSet :
// Constructor.
//-----------------------------------------------
CAnimationSet::CAnimationSet()
{
_MaxDist = 0.001;
_Angle = Pi/2.0;
_AboutFaceAngle = 3.0*Pi/4.0;
_SpeedToWalk = 4.0;
_SpeedToRun = 4.0;
_WalkDist = 0.0;
_RunDist = 0.0;
_WalkLength = 0.0;
_RunLength = 0.0;
_Sheet = NULL;
}// CAnimationSet //
//-----------------------------------------------
// init
//-----------------------------------------------
void CAnimationSet::init(CAnimationSetSheet *sheet, NL3D::UAnimationSet *animationSet)
{
_Sheet = sheet;
_AnimationStates.resize(_Sheet->AnimationStates.size());
for (uint32 i = 0; i < _AnimationStates.size(); ++i)
{
_AnimationStates[i].init(&_Sheet->AnimationStates[i], animationSet);
}
const CAnimationState *animState = getAnimationState (CAnimationStateSheet::Walk);
if (animState)
{
// Compute the distance to break the idle (done according to the walk state).
CAnimation::TAnimId walkId = animState->chooseAnim(0, EGSPD::CPeople::Unknown, GSGENDER::male);
// Check the animation Id.
if(walkId != CAnimation::UnknownAnim)
{
// Get the animation
const CAnimation *walkAnim = animState->getAnimation(walkId);
// Compute the dist made by the walk animation.
CVector mov;
if(CAnimationMisc::getAnimationMove(animationSet, walkAnim->id(), mov))
{
_WalkDist = fabs(mov.y);
_MaxDist = ClientCfg.MinDistFactor*_WalkDist;
}
_WalkLength = CAnimationMisc::getAnimationLength(animationSet, walkAnim->id());
animState = getAnimationState (CAnimationStateSheet::Run);
if (animState)
{
// Get the run animation ID.
CAnimation::TAnimId runId = animState->chooseAnim(0, EGSPD::CPeople::Unknown, GSGENDER::male);
if(runId != CAnimation::UnknownAnim)
{
// Get the animation
const CAnimation *runAnim = animState->getAnimation(runId);
CVector mov;
if(CAnimationMisc::getAnimationMove(animationSet, runAnim->id(), mov))
_RunDist = fabs(mov.y);
_RunLength = CAnimationMisc::getAnimationLength(animationSet, runAnim->id());
// Get the walk average speed.
double aveWalk = CAnimationMisc::getAnimationAverageSpeed(animationSet, walkAnim->id());
// Get the run average speed.
double aveRun = CAnimationMisc::getAnimationAverageSpeed(animationSet, runAnim->id());
pushInfoStr(NLMISC::toString("Walk speed(%f).", aveWalk));
pushInfoStr(NLMISC::toString("Run speed(%f).", aveRun));
// Check animations average speed for walk and run.
if(aveRun Run speed(%f) !", aveWalk, aveRun));
// Average Speed.
double ave = (aveWalk+aveRun)/2.0;
// Compute the min speed to run when walking.
_SpeedToRun = (ave + aveRun)/2.0;
// Compute the max speed to walk when running.
_SpeedToWalk = (ave + aveWalk)/2.0;
}
// No animation found to run.
else
if(_Sheet->IsRunEssential)
pushDebugStr("No animation found to run: speedToRun and speedToWalk will return the default value.");
}
}
// No animation found to walk.
else
if(_Sheet->IsWalkEssential)
pushDebugStr("No animation found to walk: maxDist, speedToRun and speedToWalk will return the default value.");
}
// Compute the angle after the one the character should turn (left/or right).
animState = getAnimationState (CAnimationStateSheet::TurnLeft);
if (animState)
{
CAnimation::TAnimId turnLeftId = animState->chooseAnim(0, EGSPD::CPeople::Unknown, GSGENDER::male);
// Check the animation Id.
if(turnLeftId != CAnimation::UnknownAnim)
{
// Get the animation
const CAnimation *anim = animState->getAnimation(turnLeftId);
if (anim)
{
CQuat currentAnimRotStart, currentAnimRotEnd;
if(CAnimationMisc::interpolate(animationSet, anim->id(), 0.0, currentAnimRotStart))
{
double animLength = CAnimationMisc::getAnimationLength(animationSet, turnLeftId);
if(CAnimationMisc::interpolate(animationSet, anim->id(), animLength, currentAnimRotEnd))
{
currentAnimRotStart.invert();
CQuat currentAnimRot = currentAnimRotStart * currentAnimRotEnd;
_Angle = 0.75 * fabs(currentAnimRot.getAngle());
}
}
}
}
}
}// init //
//-----------------------------------------------
// getAnimationStateByIndex
//-----------------------------------------------
CAnimationState *CAnimationSet::getAnimationStateByIndex(uint index)
{
if (index >= _AnimationStates.size()) return NULL;
return &_AnimationStates[index];
}// getAnimationStateByIndex //