// 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 "stdpch.h"
#include
#include "nel/3d/animation_time.h"
#include "nel/3d/u_animation.h"
#include "nel/3d/u_track.h"
#include "nel/3d/u_bone.h"
#include "nel/misc/command.h"
#include "game_share/draw_section.h"
#include "animated_scene_object.h"
#include "user_entity.h"
#include "view.h"
#include "entities.h"
using namespace std;
using namespace NLMISC;
using namespace NL3D;
using namespace NLNET;
// some extern of client
extern CUserEntity *UserEntity;
extern UScene *Scene;
// map of anilated scene object
TMapCAnimatedSceneObject AnimatedSceneObject;
// Constructor for moving object, create entity (mesh, skeleton) and build animation on it
CAnimatedSceneObject::CAnimatedSceneObject( const string& ObjectName, const string& ClusterIG, const string& MeshName, const string& SkeletonName, const list < string >& Animations, const CVector& Position, const CQuat& Rotation, float Distance )
{
_ObjectName = ObjectName;
_ClusterIG = ClusterIG;
_MeshName = MeshName;
_SkeletonName = SkeletonName;
_Position = Position;
_Rotation = Rotation;
_Distance = Distance * Distance; //square distance for optimize distance calculation
// create play list manager and animation set
_PlayListManager = Scene->createPlayListManager();
_AnimationSet = Driver->createAnimationSet();
//fill animation set
for( list< string >::const_iterator it = Animations.begin(); it != Animations.end(); ++it )
{
uint idAnim;
try
{
idAnim = _AnimationSet->addAnimation( ( *it + string(".anim")).c_str(), (*it).c_str() );
}
catch(Exception &)
{
idAnim = UAnimationSet::NotFound;
if( idAnim == UAnimationSet::NotFound)
{
nlwarning( "CAnimatedSceneObject::CAnimatedSceneObject Animation %s not found for object %s", (*it).c_str(), _ObjectName.c_str() );
continue;
}
}
_MapAnimation.insert( make_pair( *it, idAnim ) );
}
// build animation set
_AnimationSet->build();
// create playlist
_PlayList = _PlayListManager->createPlayList( _AnimationSet );
_Status = SAnimationStatus();
_Status.RandomAnim = 1;
_Status.ApplyDisplacement = 0;
// load instance and bind to skeleton
_Instance = Scene->createInstance( _MeshName );
if( _Instance == NULL )
{
nlerror("CAnimatedSceneObject::CAnimatedSceneObject createInstance %s returned 0 -> no shape.", _MeshName.c_str() );
}
else
{
_Transform = _Instance;
}
// load skeleton, bind mesh and init position, rotation, cluster
if(_SkeletonName != "" )
{
_Skeleton = Scene->createSkeleton(_SkeletonName);
if( _Skeleton == NULL )
{
nlerror("CAnimatedSceneObject::CAnimatedSceneObject createSkeleton %s returned 0 -> no skeleton.", _SkeletonName.c_str() );
}
_Transform = _Skeleton;
_Skeleton->bindSkin( _Instance );
// Enable Shadow
if(ClientCfg.Shadows)
{
_Skeleton->enableCastShadowMap(true);
}
}
// register skeleton in playlist
_PlayList->registerTransform( _Transform );
// Initialise squeleton initial state
if( _MapAnimation.begin() != _MapAnimation.end() )
{
_PlayList->setAnimation( 0, (*_MapAnimation.begin()).second );
_PlayList->setTimeOrigin(0, 0 );
_PlayList->setSpeedFactor( 0, 1 );
_PlayListManager->animate( 0 );
}
_Transform->setClusterSystem( IGCity[_ClusterIG] );
_Transform->setPos( _Position );
_Transform->setRotQuat( _Rotation );
_IdAnimationPlayed = -1;
}
// Constructor for moving object, it not create entity (mesh, skeleton) but build animation on pre-exist entity
CAnimatedSceneObject::CAnimatedSceneObject( const CEntityId& Id, const list < std::string >& Animations )
{
_Id = Id;
_ObjectName = "";
_ClusterIG = "";
_MeshName = "";
_SkeletonName = "";
_Distance = 0;
_Skeleton = NULL;
_Instance = NULL;
CEntityCL *entity = getEntity(Id);
if(entity)
{
_Skeleton = *entity->skeleton();
_Transform = _Skeleton;
_Position = _Skeleton->getPos();
_Rotation = _Skeleton->getRotQuat();
// create play list manager and animation set
_PlayListManager = Scene->createPlayListManager();
_AnimationSet = Driver->createAnimationSet();
//fill animation set
for( list< string >::const_iterator its = Animations.begin(); its != Animations.end(); ++its )
{
uint idAnim;
try
{
idAnim = _AnimationSet->addAnimation( ( *its + string(".anim") ).c_str(), (*its).c_str() );
}
catch(Exception &)
{
idAnim = UAnimationSet::NotFound;
if( idAnim == UAnimationSet::NotFound)
{
nlwarning( "CAnimatedSceneObject::CAnimatedSceneObject Animation %s not found for entity CEntityId(%u,%f)", (*its).c_str(), Id.Type, (double)(sint64)Id.Id );
continue;
}
}
_MapAnimation.insert( make_pair( *its, idAnim ) );
}
// build animation set
_AnimationSet->build();
// create playlist
_PlayList = _PlayListManager->createPlayList( _AnimationSet );
_Status = SAnimationStatus();
_Status.SequenceAnim = 1;
_Status.ApplyDisplacement = 1;
// register skeleton in playlist
_PlayList->registerTransform( *entity->skeleton() );
// Snap to ground(the snap check if it's a flyer).
entity->pacsPos(_Position);
entity->snapToGround();
_Position = entity->pos();
CMatrix current;
current.identity ();
current.setRot (_Rotation);
// Rotation 90°
CMatrix rot90;
rot90.identity ();
rot90.rotateZ (-(float)Pi/2);
current *= rot90;
_Transform->unfreezeHRC();
_Transform->setPos(_Position);
_Transform->setRotQuat(current.getRot());
_Transform->freezeHRC();
_IdAnimationPlayed = -1;
if( _Id.Type == RYZOMID::npc )
{
sendEndSequenceMessage( _Id, 1 );
}
}
else
{
_PlayList = NULL;
_AnimationSet = NULL;
_PlayListManager = NULL;
}
}
// Constructor for moving object, init by UTransform
CAnimatedSceneObject::CAnimatedSceneObject( const CEntityId& Id, UTransform *Transform, const list < std::string >& Animations, bool displacement )
{
_Id = Id;
_ObjectName = "";
_ClusterIG = "";
_MeshName = "";
_SkeletonName = "";
_Distance = 0;
_Transform = Transform;
_Instance = NULL;
_Skeleton = NULL;
_PlayList = NULL;
_Position = _Transform->getPos();
_Rotation = _Transform->getRotQuat();
// create play list manager and animation set
_PlayListManager = Scene->createPlayListManager();
_AnimationSet = Driver->createAnimationSet();
//fill animation set
for( list< string >::const_iterator its = Animations.begin(); its != Animations.end(); ++its )
{
uint idAnim;
try
{
idAnim = _AnimationSet->addAnimation( ( *its + string(".anim") ).c_str(), (*its).c_str() );
}
catch(Exception &)
{
idAnim = UAnimationSet::NotFound;
if( idAnim == UAnimationSet::NotFound)
{
nlwarning( "CAnimatedSceneObject::CAnimatedSceneObject Animation %s not found for entity CEntityId(%u,%f)", (*its).c_str(), Id.Type, (double)(sint64)Id.Id );
continue:
}
}
_MapAnimation.insert( make_pair( *its, idAnim ) );
}
_Status = SAnimationStatus();
_Status.SequenceAnim = 1;
_Status.ApplyDisplacement = displacement;
if( Animations.begin() != Animations.end() )
{
// build animation set
_AnimationSet->build();
// create playlist
_PlayList = _PlayListManager->createPlayList( _AnimationSet );
// register skeleton in playlist
_PlayList->registerTransform( _Transform );
_IdAnimationPlayed = -1;
}
}
// Reset intial pos and rot matrix
void CAnimatedSceneObject::resetInitialPos( void )
{
_IdAnimationPlayed = -1;
// Current Matrix
_Position = _Transform->getPos();
_Rotation = _Transform->getRotQuat();
CEntityCL *entity = getEntity(_Id);
if(entity)
{
// Snap to ground(the snap check if it's a flyer).
entity->pacsPos(_Position);
entity->snapToGround();
_Position = entity->pos();
}
CMatrix current;
current.identity ();
current.setRot (_Rotation);
// Rotation 90°
CMatrix rot90;
rot90.identity ();
rot90.rotateZ (-(float)Pi/2);
current *= rot90;
_Transform->unfreezeHRC();
_Transform->setPos(_Position);
_Transform->setRotQuat(current.getRot());
_Transform->freezeHRC();
}
// Destructor
CAnimatedSceneObject::~CAnimatedSceneObject()
{
if( _Instance != NULL && _MeshName != "" )
{
Scene->deleteInstance( _Instance );
}
if( _Skeleton != NULL && _SkeletonName != "" )
{
Scene->deleteSkeleton( _Skeleton );
}
if( _PlayListManager != NULL )
{
if( _PlayList != NULL )
{
_PlayListManager->deletePlayList( _PlayList );
}
if( _AnimationSet != NULL )
{
Driver->deleteAnimationSet( _AnimationSet );
}
Scene->deletePlayListManager( _PlayListManager );
}
_MapAnimation.clear();
_SequenceAnimation.clear();
}
// Start an animation, if object have more than one animation, it choose one randomly
void CAnimatedSceneObject::StartRandomAnimation( double time, float speedFactor )
{
if( _Transform != NULL )
{
_Transform->unfreezeHRC();
}
uint numAnimation = _MapAnimation.size();
numAnimation = ( rand() * numAnimation ) / RAND_MAX;
map< string, uint >::iterator it = _MapAnimation.begin();
for(uint i = 0; i < numAnimation; ++i ) ++it;
numAnimation = (*it).second;
_PlayList->setAnimation( 0, numAnimation );
_IdAnimationPlayed = numAnimation;
_StartAnimationTime = time;
_OldAnimationTime = _StartAnimationTime;
_PlayList->setTimeOrigin(0, _StartAnimationTime );
_PlayList->setSpeedFactor( 0, speedFactor );
if( _Transform != NULL )
{
_Position = _Transform->getPos();
_Rotation = _Transform->getRotQuat();
CEntityCL *entity = getEntity(_Id);
if(entity)
{
// Snap to ground(the snap check if it's a flyer).
entity->pacsPos(_Position);
entity->snapToGround();
_Position = entity->pos();
}
// Read start animation rotation and position
_PreviousRotation = CQuat::Identity;
_PreviousTranslation = CVector::Null;
// read an animation for init matrix
UTrack* Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "PathRotQuat" );
if( Track == NULL )
{
Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "Bip01.PathRotQuat" );
}
if( Track == NULL )
{
Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "rotquat" );
}
if( Track != NULL )
{
Track->interpolate( 0, _PreviousRotation );
}
Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "PathPos" );
if( Track == NULL )
{
Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "Bip01.PathPos" );
}
if( Track == NULL )
{
Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "pathpos" );
}
if( Track != NULL )
{
Track->interpolate( 0, _PreviousTranslation );
}
// Animation Matrix
CMatrix animation;
animation.identity();
animation.setPos (_PreviousTranslation);
animation.setRot (_PreviousRotation);
// reset orientation of skeleton
CMatrix current;
current.identity();
current.setRot( _Rotation );
CVector I, J, K;
I = current.getJ();
I.z=0;
I.normalize ();
K.set (0,0,1);
J=K^I;
current.setRot (I, J, K);
current.setPos (_Position);
_AnimTransformation = current;
if(entity)
{
if(!entity->flyer())
{
_AnimTransformation.setPos( _AnimTransformation.getPos() - CVectorD( 0, 0, entity->pos().z ) );
}
}
}
}
// Start next animation
void CAnimatedSceneObject::StartNextAnimation( double time, float speedFactor )
{
if( _SequenceAnimation.begin() != _SequenceAnimation.end() )
{
if( _Transform != NULL )
{
_Transform->unfreezeHRC();
}
string animName = *_SequenceAnimation.begin();
_SequenceAnimation.pop_front();
map< string, uint >::iterator it = _MapAnimation.find( animName );
if( it != _MapAnimation.end() )
{
uint idAnim = (*it).second;
_PlayList->setAnimation( 0, idAnim );
_IdAnimationPlayed = idAnim;
_StartAnimationTime = time;
_OldAnimationTime = _StartAnimationTime;
_PlayList->setTimeOrigin(0, _StartAnimationTime );
_PlayList->setSpeedFactor( 0, speedFactor );
if( _Transform != NULL )
{
_Position = _Transform->getPos();
_Rotation = _Transform->getRotQuat();
CEntityCL *entity = getEntity(_Id);
if(entity)
{
// Snap to ground(the snap check if it's a flyer).
entity->pacsPos(_Position);
entity->snapToGround();
_Position = entity->pos();
}
// Read start animation rotation and position
_PreviousRotation = CQuat::Identity;
_PreviousTranslation = CVector::Null;
// read an animation for init matrix
UTrack* Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "PathRotQuat" );
if( Track == NULL )
{
Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "Bip01.PathRotQuat" );
}
if( Track == NULL )
{
Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "rotquat" );
}
if( Track != NULL )
{
Track->interpolate( 0, _PreviousRotation );
}
Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "PathPos" );
if( Track == NULL )
{
Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "Bip01.PathPos" );
}
if( Track == NULL )
{
Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "pathpos" );
}
if( Track != NULL )
{
Track->interpolate( 0, _PreviousTranslation );
}
// Animation Matrix
CMatrix animation;
animation.identity();
animation.setPos (_PreviousTranslation);
animation.setRot (_PreviousRotation);
// reset orientation of skeleton
CMatrix current;
current.identity();
current.setRot( _Rotation );
CVector I, J, K;
I = current.getJ();
I.z=0;
I.normalize ();
K.set (0,0,1);
J=K^I;
current.setRot (I, J, K);
current.setPos (_Position);
_AnimTransformation = current;
if(entity)
{
if(!entity->flyer() )
{
_AnimTransformation.setPos( _AnimTransformation.getPos() - CVectorD( 0, 0, entity->pos().z ) );
}
}
}
}
if( _SequenceAnimation.size() == 1 )
{
sendEndSequenceMessage( _Id, idSequence() );
}
}
else
{
//StartAnimation( string("FY_HOM_idlecycle") );
}
}
// Start animation cooresponding to numAnim
void CAnimatedSceneObject::StartAnimation( string& nameAnim, double time, float speedFactor )
{
if( _Transform != NULL )
{
_Transform->unfreezeHRC();
}
map< string, uint >::iterator it = _MapAnimation.find( nameAnim );
if( it != _MapAnimation.end() )
{
uint numAnimation = (*it).second;
_PlayList->setAnimation( 0, numAnimation );
_IdAnimationPlayed = numAnimation;
_StartAnimationTime = time;
_OldAnimationTime = _StartAnimationTime;
_PlayList->setTimeOrigin(0, _StartAnimationTime );
_PlayList->setSpeedFactor( 0, speedFactor );
if( _Transform != NULL )
{
_Position = _Transform->getPos();
_Rotation = _Transform->getRotQuat();
CEntityCL *entity = getEntity(_Id);
if(entity)
{
// Snap to ground(the snap check if it's a flyer).
entity->pacsPos(_Position);
entity->snapToGround();
_Position = entity->pos();
}
// Read start animation rotation and position
_PreviousRotation = CQuat::Identity;
_PreviousTranslation = CVector::Null;
// read an animation for init matrix
UTrack* Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "PathRotQuat" );
if( Track == NULL )
{
Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "Bip01.PathRotQuat" );
}
if( Track == NULL )
{
Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "rotquat" );
}
if( Track != NULL )
{
Track->interpolate( 0, _PreviousRotation );
}
Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "PathPos" );
if( Track == NULL )
{
Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "Bip01.PathPos" );
}
if( Track == NULL )
{
Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "pathpos" );
}
if( Track != NULL )
{
Track->interpolate( 0, _PreviousTranslation );
}
// Animation Matrix
CMatrix animation;
animation.identity();
animation.setPos (_PreviousTranslation);
animation.setRot (_PreviousRotation);
// reset orientation of skeleton
CMatrix current;
current.identity();
current.setRot( _Rotation );
CVector I, J, K;
I = current.getJ();
I.z=0;
I.normalize ();
K.set (0,0,1);
J=K^I;
current.setRot (I, J, K);
current.setPos (_Position);
_AnimTransformation = current;
if(entity)
{
if( !entity->flyer() )
{
_AnimTransformation.setPos( _AnimTransformation.getPos() - CVectorD( 0, 0, entity->pos().z ) );
}
}
}
}
}
// remove the initial animation offset
void CAnimatedSceneObject::removeOffsetAnimation ()
{
// Read start animation rotation and position
_PreviousRotation = CQuat::Identity;
_PreviousTranslation = CVector::Null;
// read an animation for init matrix
UTrack* Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "PathRotQuat" );
if( Track == NULL )
{
Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "Bip01.PathRotQuat" );
}
if( Track == NULL )
{
Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "rotquat" );
}
if( Track != NULL )
{
Track->interpolate( 0, _PreviousRotation );
}
Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "PathPos" );
if( Track == NULL )
{
Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "Bip01.PathPos" );
}
if( Track == NULL )
{
Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "pathpos" );
}
if( Track != NULL )
{
Track->interpolate( 0, _PreviousTranslation );
}
// Remove first frame animation from transform
CVector position = _Transform->getPos ();
CQuat rotation = _Transform->getRotQuat ();
// Build current matrix
CMatrix current;
current.identity ();
current.setPos (position);
current.setRot (rotation);
// Build invert first frame matrix
CMatrix firstFrame;
firstFrame.identity ();
firstFrame.setPos (_PreviousTranslation);
firstFrame.setRot (_PreviousRotation);
firstFrame.invert ();
// Remove the first frame animation
current *= firstFrame;
// Rotation 90°
CMatrix rot90;
rot90.identity ();
rot90.rotateZ (-(float)Pi/2);
current *= rot90;
// Set transform
_Transform->setPos (current.getPos());
_Transform->setRotQuat (current.getRot());
}
// update (add to end list) Animation sequence with sequence
void CAnimatedSceneObject::updateAnimationSequence( const list< string >& sequence )
{
for( list< string >::const_iterator it = sequence.begin(); it != sequence.end(); ++it )
{
_SequenceAnimation.push_back( (*it) );
}
}
// Process logic and displacement and setup visual animation
void CAnimatedSceneObject::applyObjectAnimationTimeslice( double time )
{
_PlayListManager->animate( time );
// Apply displacement if mode set and displacement animation exist
if( _Status.ApplyDisplacement == 1 )
{
CQuat rot = CQuat::Identity;
CVector translation = CVector::Null;
// Read position and rotation in appropriate UTrack
UTrack* Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "PathRotQuat" );
if( Track == NULL )
{
Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "Bip01.PathRotQuat" );
}
if( Track == NULL )
{
Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "rotquat" );
}
if( Track != NULL )
{
Track->interpolate( (float)(time - _StartAnimationTime) * _PlayList->getSpeedFactor( 0 ), rot );
}
Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "PathPos" );
if( Track == NULL )
{
Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "Bip01.PathPos" );
}
if( Track == NULL )
{
Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "pathpos" );
}
if( Track != NULL )
{
Track->interpolate( (float)(time - _StartAnimationTime) * _PlayList->getSpeedFactor( 0 ), translation );
}
applyDeltaRotationAndPosition( rot, translation);
}
processLogicTemp( (_OldAnimationTime - _StartAnimationTime) * _PlayList->getSpeedFactor( 0 ), (time - _StartAnimationTime) * _PlayList->getSpeedFactor( 0 ) );
_OldAnimationTime = time;
}
// manage object animation
// TODO: manage other type animation than trigger distance and sequence list
void CAnimatedSceneObject::manageObjectAnimation( double Time, CVector userPos )
{
double overLoop = 0;
if( _IdAnimationPlayed != -1 )
{
if( Time > ( _StartAnimationTime + (double) _AnimationSet->getAnimation( _IdAnimationPlayed )->getEndTime() / _PlayList->getSpeedFactor( 0 ) ) )
{
overLoop = Time - _StartAnimationTime - (double) _AnimationSet->getAnimation( _IdAnimationPlayed )->getEndTime() / _PlayList->getSpeedFactor( 0 );
/* nlinfo("overLoop %f Time %f Start %f getEndTime() %f speedFactor() %f",
overLoop,
Time,
_StartAnimationTime,
_AnimationSet->getAnimation( _IdAnimationPlayed )->getEndTime(),
_PlayList->getSpeedFactor( 0 ));
*/
nlassert( overLoop >= 0 );
// play through logic and movement of end of last animation before animation change
nlassert( Time-overLoop >= _StartAnimationTime );
applyObjectAnimationTimeslice(Time-overLoop);
nlassert( Time >= _StartAnimationTime );
if( _Status.LoopAnim )
{
if( _StartAnimationTime == 0 )
{
overLoop = 0;
}
_StartAnimationTime = Time - overLoop;
nlassert( Time >= _StartAnimationTime );
_PlayList->setTimeOrigin( 0, _StartAnimationTime );
}
else
{
removeOffsetAnimation ();
if( _Transform != NULL )
{
_Transform->freezeHRC();
}
_IdAnimationPlayed = -1;
}
}
}
if( _IdAnimationPlayed == -1 )
{
if( _Status.CodeAnim != 1 )
{
if( ( _Distance == 0 ) || ( ( userPos - _Position ).sqrnorm() < _Distance ) )
{
if( _Status.RandomAnim == 1 )
{
StartRandomAnimation( Time - overLoop );
}
else if ( _Status.SequenceAnim == 1 )
{
StartNextAnimation( Time - overLoop );
}
}
}
else
{
float angle = (float)((((uint32)Time * 1000)%(uint32)(1000*2*Pi))*0.001);
CMatrix rot;
rot.identity();
rot.rotateZ(angle);
/*
CQuat rot = CQuat (CVector (0, 0, 1), angle) * _Transform->getRotQuat();
rot.normalize();
*/
_Transform->setRotQuat( rot.getRot() );
}
}
if( _IdAnimationPlayed != -1 )
{
// play through anim visuals and logic and movement for the timeslice
applyObjectAnimationTimeslice(Time);
}
}
// Apply animation rotation and translation
void CAnimatedSceneObject::applyDeltaRotationAndPosition( CQuat& rot, CVector& trans )
{
if( _Transform != NULL )
{
// Animation Matrix
CMatrix animation;
animation.identity();
animation.setPos (trans);
animation.setRot (rot);
// Compose matrix
CMatrix composed;
composed = _AnimTransformation * animation;
_Rotation = composed.getRot();
_Position = composed.getPos();
CEntityCL *entity = getEntity(_Id);
if(entity)
{
// \todo GUIGUI : TO CHECK
#if 1
if( !entity->flyer() )
_Position.z += entity->pos().z;
entity->pacsPos(_Position);
entity->snapToGround();
if( !entity->flyer() )
_Position.z = entity->pos().z + composed.getPos().z;
// Old version
#else
if( !entity->flyer() )
{
_Position.z += entity->pos().z;
entity->pacsPos(_Position);
entity->snapToGround();
_Position.z = entity->pos().z + composed.getPos().z;
}
else
{
entity->pos(_Position);
}
#endif
}
_Transform->setRotQuat(_Rotation);
_Transform->setPos(_Position);
}
}
// Instanciate an object and add it to map
void addAnimatedSceneObject( const string& AnimatedSceneObjectName, const string& ClusterIG, const string& MeshName, const string& SkeletonName, const list & Animations, const CVector& Position, const CQuat& Rotation, float Distance )
{
if( AnimatedSceneObject.find( AnimatedSceneObjectName ) == AnimatedSceneObject.end() )
{
CAnimatedSceneObject * o = new CAnimatedSceneObject( AnimatedSceneObjectName, ClusterIG, MeshName, SkeletonName, Animations, Position, Rotation, Distance );
if( o != NULL )
{
AnimatedSceneObject.insert( make_pair( AnimatedSceneObjectName, o) );
}
}
}
void addEntityClAnimatedSceneObject( const CEntityId& Id, const list < string >& Animations)
{
string test = string( "CEntityId") + toString( Id.Type) + toString( Id.Id);
if( AnimatedSceneObject.find( string( "CEntityId") + toString( Id.Type) + toString( Id.Id) ) == AnimatedSceneObject.end() )
{
CAnimatedSceneObject * o = new CAnimatedSceneObject( Id, Animations );
if( o != NULL )
{
AnimatedSceneObject.insert( make_pair( string( "CEntityId") + toString( Id.Type) + toString( Id.Id), o) );
}
}
}
void addUknowTypeSceneObject( const CEntityId& Id, NL3D::UTransform *Transform, const std::list < std::string >& Animations, bool displacement )
{
if( AnimatedSceneObject.find( string( "CEntityId") + toString( Id.Type) + toString( Id.Id) ) == AnimatedSceneObject.end() )
{
CAnimatedSceneObject * o = new CAnimatedSceneObject( Id, Transform, Animations, displacement );
if( o != NULL )
{
AnimatedSceneObject.insert( make_pair( string( "CEntityId") + toString( Id.Type) + toString( Id.Id), o) );
}
}
}
// manage animated object
void manageAnimatedSceneObject( double Time )
{
for( TMapCAnimatedSceneObject::iterator it = AnimatedSceneObject.begin(); it != AnimatedSceneObject.end(); ++it )
{
(*it).second->manageObjectAnimation( Time, View.viewPos() );
}
}
// delete
void deleteAnimatedSceneObject( const string& AnimatedSceneObjectName )
{
TMapCAnimatedSceneObject::iterator it = AnimatedSceneObject.find( AnimatedSceneObjectName );
if( it != AnimatedSceneObject.end() )
{
delete (*it).second;
AnimatedSceneObject.erase( it );
}
}
// update sequence animation
void updateAnimationSequence( const CEntityId& id, const list< string >& sequence, uint32 idSequence )
{
TMapCAnimatedSceneObject::iterator it;
for( it = AnimatedSceneObject.begin(); it != AnimatedSceneObject.end(); ++it )
{
if( (*it).second->getId() == id )
{
break;
}
}
if( it != AnimatedSceneObject.end() )
{
(*it).second->updateAnimationSequence( sequence );
(*it).second->idSequence( idSequence );
}
}
// Reset animation for the entity and break the current one.
void resetAnimatedSceneObject(const CEntityId& id)
{
for(TMapCAnimatedSceneObject::iterator it = AnimatedSceneObject.begin(); it != AnimatedSceneObject.end(); ++it )
{
if((*it).second->getId() == id)
{
(*it).second->breakCurrentAnimation();
(*it).second->resetSequence();
(*it).second->resetInitialPos();
break;
}
}
}
void sendEndSequenceMessage( const CEntityId& id, uint32 idSequence )
{
SEND_MSG_MACRO
(
"ANIME_BAR_MAN_END",
SAnimeBarManEnd end;
end.Id = id;
end.SlotNumber = idSequence;
msg.serial(end);,
;,
;
)
}
//---------------------------------------------------
// processLogic :
//
//---------------------------------------------------
void CAnimatedSceneObject::processLogicTemp( double startOffset, double endOffset )
{
static uint32 previousSoundIndex = 0;
// get the logical animation data across the current anim segment
UTrack * soundTrack = NULL;
vector result;
// EAM->processLogic( _AnimationsGlobalId[MOVING], startOffset, endOffset, soundTrack, result);
// get infos about the anim
char *soundTrackName = "NoteTrack";
soundTrack = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( soundTrackName );
if( soundTrack != NULL )
{
UTrackKeyframer * soundTrackKF = dynamic_cast(soundTrack);
if( soundTrackKF == NULL )
{
nlerror("The track %s is not a key framer track",soundTrackName);
}
soundTrackKF->getKeysInRange((float)startOffset, (float)endOffset, result);
}
// process sounds
if( SoundMngr )
{
if( soundTrack )
{
vector::iterator itResult;
for( itResult = result.begin(); itResult != result.end(); ++itResult )
{
string soundName;
double keyTime = *itResult;
nlinfo("keyTime = %f result size : %d",*itResult,result.size());
if( !soundTrack->interpolate( *itResult, soundName) )
{
nlwarning("The key at offset %f is not a string",*itResult);
}
else
{
/* // if there are step sounds
if( soundName == "step" )
{
// get the material
UGlobalPosition globalPos;
getPrimitive()->getGlobalPosition(globalPos, dynamicWI);
uint32 material = GR->getMaterial( globalPos );
// choose the sound type soft/hard
bool soft;
if( Type.TypeInfo.Sex == CTypeEntity::male )
soft = false;
if( Type.TypeInfo.Sex == CTypeEntity::female )
soft = true;
vector sounds;
uint32 soundSourceId;
// choose the sound for the move type
if( _AnimationsStateKey[MOVING] == "walk" )
{
if( SoundMngr->getSounds( material, WALK, soft, sounds ) )
{
string name = chooseRandom(sounds,previousSoundIndex );
SoundMngr->spawnSound( name , pos ());
}
else
{
nlwarning(" : there is no walk step sound for the material %d",material);
SoundMngr->spawnSource( "Fwrks_Clac_1", pos() );
}
}
_SoundSourcesId.push_back( soundSourceId );
}
else*/ if (soundName.find ("snd_") != string::npos)
{
// need to spawn a sound linked to the anim
SoundMngr->spawnSource( soundName, _Position );
nlwarning ("launching sound for anim event from notetrack '%s'", soundName.c_str());
}
else
{
nlwarning ("unknown notetrack event: '%s'", soundName.c_str());
}
}
}
}
}
} // processAnimSounds //