1778 lines
46 KiB
C++
1778 lines
46 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/path.h"
|
|
#include "nel/misc/debug.h"
|
|
#include "nel/misc/matrix.h"
|
|
// 3D Interface.
|
|
#include "nel/3d/u_driver.h"
|
|
#include "nel/3d/u_scene.h"
|
|
#include "nel/3d/u_play_list.h"
|
|
#include "nel/3d/u_track.h"
|
|
#include "nel/3d/u_camera.h"
|
|
// Client.
|
|
#include "scene_parser.h"
|
|
#include "entities.h"
|
|
#include "entity_cl.h"
|
|
#include "animated_scene_object.h"
|
|
#include "ig_client.h"
|
|
#include "user_controls.h"
|
|
#include "time_client.h"
|
|
// Game Share
|
|
#include "game_share/entity.h"
|
|
|
|
|
|
///////////
|
|
// USING //
|
|
///////////
|
|
using namespace NLMISC;
|
|
using namespace NL3D;
|
|
using namespace std;
|
|
|
|
|
|
////////////
|
|
// EXTERN //
|
|
////////////
|
|
extern UDriver *Driver;
|
|
extern UScene *Scene;
|
|
extern UScene *SceneRoot;
|
|
|
|
|
|
/////////////
|
|
// METHODS //
|
|
/////////////
|
|
const uint CSceneParser::MAX_LINE_SIZE = 500;
|
|
const char *CSceneParser::delimiter = " \t";
|
|
|
|
//-----------------------------------------------
|
|
// CSceneParser :
|
|
// Constructor.
|
|
//-----------------------------------------------
|
|
CSceneParser::CSceneParser()
|
|
{
|
|
_FrameRate = 30.0;
|
|
_Line = 0;
|
|
_AnimationSet = 0;
|
|
_TimeStart = -1;
|
|
_AnimationSet = 0;
|
|
_Apply = false;
|
|
_Day = true;
|
|
|
|
_ItScene = _Scene.end();
|
|
_SceneStart = -1.f;
|
|
}// CSceneParser //
|
|
|
|
|
|
//-----------------------------------------------
|
|
// load :
|
|
// Load the file with the scene.
|
|
//-----------------------------------------------
|
|
void CSceneParser::load(const string &filename)
|
|
{
|
|
// Look for the file -> nlwarning and return if sceneFile is empty.
|
|
string sceneFile = CPath::lookup(filename, false);
|
|
if(sceneFile.empty())
|
|
{
|
|
nlwarning("CSceneParser::load : Can't find file \"%s\".", filename.c_str());
|
|
return;
|
|
}
|
|
|
|
// Open the file.
|
|
ifstream file(sceneFile.c_str(), ios::in);
|
|
if(file.is_open())
|
|
{
|
|
// Load the capture speed.
|
|
ifstream speedFile("capture_speed.txt", ios::in);
|
|
if(speedFile.is_open())
|
|
{
|
|
char tmpBuff[MAX_LINE_SIZE];
|
|
|
|
// Set the default fram rate (30fps).
|
|
_FrameRate = 30.0;
|
|
|
|
// Init Lines.
|
|
_Line = 0;
|
|
|
|
// While the end of the file is not reached -> parse the script.
|
|
while(!speedFile.eof())
|
|
{
|
|
// Get next valid line.
|
|
getNextValidLine(speedFile, tmpBuff);
|
|
|
|
char *ptr = strtok(tmpBuff, delimiter);
|
|
if(ptr != NULL)
|
|
NLMISC::fromString(ptr, _FrameRate);
|
|
}
|
|
|
|
// Close the speed file.
|
|
speedFile.close();
|
|
}
|
|
else
|
|
nlwarning("CSceneParser::load : 'capture_speed.txt' can't be open, default frame rate is %f.", _FrameRate);
|
|
|
|
// Init Lines.
|
|
_Line = 0;
|
|
|
|
// Parse the File.
|
|
parse(file);
|
|
|
|
// Initialize Actors Position and rotation .
|
|
initActors();
|
|
|
|
// Close the File.
|
|
file.close();
|
|
}
|
|
else
|
|
{
|
|
nlwarning("CSceneParser::load : File \"%s\" can't be open.", sceneFile.c_str());
|
|
return;
|
|
}
|
|
}// load //
|
|
|
|
|
|
//-----------------------------------------------
|
|
// parse :
|
|
// Parse the file.
|
|
//-----------------------------------------------
|
|
void CSceneParser::parse(ifstream &file)
|
|
{
|
|
char tmpBuff[MAX_LINE_SIZE];
|
|
|
|
// While the end of the file is not reached -> parse the script.
|
|
while(!file.eof())
|
|
{
|
|
// Get next valid line.
|
|
getNextValidLine(file, tmpBuff);
|
|
|
|
char *ptr = strtok(tmpBuff, delimiter);
|
|
if(ptr != NULL)
|
|
{
|
|
// Time (Day/Night)
|
|
if(strcmp(ptr, "Time:") == 0)
|
|
parseTime();
|
|
|
|
// Filename of the File with all IG to load for the scene.
|
|
else if(strcmp(ptr, "IG:") == 0)
|
|
parseIG(file, tmpBuff);
|
|
|
|
// Ig for the init.
|
|
else if(strcmp(ptr, "IG_Init:") == 0)
|
|
parseIGInit();
|
|
|
|
// Particle.
|
|
else if(strcmp(ptr, "Particle:") == 0)
|
|
parseParticle(file, tmpBuff);
|
|
|
|
// Actor.
|
|
else if(strcmp(ptr, "Actor:") == 0)
|
|
parseActor(file, tmpBuff);
|
|
|
|
// Camera.
|
|
else if(strcmp(ptr, "Camera:") == 0)
|
|
parseCamAnims(file, tmpBuff);
|
|
|
|
// Action.
|
|
else if(strcmp(ptr, "Sequence:") == 0)
|
|
parseSequence(file, tmpBuff);
|
|
|
|
// Bad Keyword
|
|
else
|
|
nlwarning("Unknown keyword '%s' at line %d.", ptr, _Line);
|
|
}
|
|
}
|
|
}// parse //
|
|
|
|
|
|
//-----------------------------------------------
|
|
// getNextValidLine :
|
|
// Skip empty lines and comment lines.
|
|
//-----------------------------------------------
|
|
void CSceneParser::getNextValidLine(ifstream &file, char *buff)
|
|
{
|
|
while(!file.eof())
|
|
{
|
|
// Get the line.
|
|
file.getline(buff, MAX_LINE_SIZE);
|
|
|
|
// Increase line nnumber.
|
|
_Line++;
|
|
|
|
// Skip comments.
|
|
if(buff[0] != 0)
|
|
{
|
|
// First char is not the beginning of a comment.
|
|
if(buff[0] != '/')
|
|
break;
|
|
// Second char is not the end of a coment.
|
|
else if(buff[1] != '/')
|
|
break;
|
|
}
|
|
}
|
|
}// getNextValidLine //
|
|
|
|
|
|
//-----------------------------------------------
|
|
// parseTime :
|
|
// Day or Night.
|
|
//-----------------------------------------------
|
|
void CSceneParser::parseTime()
|
|
{
|
|
char *ptr = strtok(NULL, delimiter);
|
|
if(ptr != NULL)
|
|
{
|
|
if(atoi(ptr))
|
|
_Day = true;
|
|
else
|
|
_Day = false;
|
|
}
|
|
}// parseTime //
|
|
|
|
//-----------------------------------------------
|
|
// parseIG :
|
|
// Parse the list of IG to load for the scene
|
|
//-----------------------------------------------
|
|
void CSceneParser::parseIG(ifstream &file, char *buff)
|
|
{
|
|
while(!file.eof())
|
|
{
|
|
// Get next valid line.
|
|
getNextValidLine(file, buff);
|
|
|
|
char *ptr = strtok(buff, delimiter);
|
|
if(ptr != NULL)
|
|
{
|
|
// End of the actor definition.
|
|
if(strcmp(ptr, "End_IG") == 0)
|
|
break;
|
|
// IG Name.
|
|
else
|
|
_IG.push_back(ptr);
|
|
}
|
|
}
|
|
}// parseIG //
|
|
|
|
//-----------------------------------------------
|
|
// parseIGInit :
|
|
// Get the name of the IG to initialize entities.
|
|
//-----------------------------------------------
|
|
void CSceneParser::parseIGInit()
|
|
{
|
|
char *ptr = strtok(NULL, delimiter);
|
|
if(ptr != NULL)
|
|
_IG_Init = ptr;
|
|
}// parseIGInit //
|
|
|
|
|
|
///////////////
|
|
// PARTICLES //
|
|
//-----------------------------------------------
|
|
// parseParticle :
|
|
// Parse Particle.
|
|
//-----------------------------------------------
|
|
void CSceneParser::parseParticle(ifstream &file, char *buff)
|
|
{
|
|
// Reset the current particle.
|
|
_CurrentParticle.reset();
|
|
|
|
while(!file.eof())
|
|
{
|
|
// Get next valid line.
|
|
getNextValidLine(file, buff);
|
|
|
|
char *ptr = strtok(buff, delimiter);
|
|
if(ptr != NULL)
|
|
{
|
|
// End of the actor definition.
|
|
if(strcmp(ptr, "End_Particle") == 0)
|
|
break;
|
|
|
|
// Particle's Id
|
|
else if(strcmp(ptr, "Id:") == 0)
|
|
parseParticleId();
|
|
|
|
// Particle's IG
|
|
else if(strcmp(ptr, "IG:") == 0)
|
|
parseParticleIG();
|
|
|
|
// Particle's Cluster
|
|
else if(strcmp(ptr, "Cluster:") == 0)
|
|
parseParticleCluster();
|
|
|
|
// Actor father of the particle is there is one.
|
|
else if(strcmp(ptr, "Actor:") == 0)
|
|
parseParticleActor();
|
|
|
|
// Particle's Anims
|
|
else if(strcmp(ptr, "Anims:") == 0)
|
|
parseParticleAnims(file, buff);
|
|
|
|
// Bad Keyword
|
|
else
|
|
nlwarning("Unknown keyword '%s' at line %d.", ptr, _Line);
|
|
}
|
|
}
|
|
|
|
// If the current particle Id is Valid -> create the particle.
|
|
if(_CurrentParticle.Id >= 0)
|
|
{
|
|
map<uint, CParticle>::iterator it = _Particles.find((uint)_CurrentParticle.Id);
|
|
// Id already exists.
|
|
if(it != _Particles.end())
|
|
nlwarning("Particle before line %d has the ID %d that already exists -> Particle Not Created.", _Line, _CurrentParticle.Id);
|
|
// Insert the new Particle.
|
|
else
|
|
_Particles.insert(make_pair((uint)_CurrentParticle.Id, _CurrentParticle));
|
|
}
|
|
else
|
|
nlwarning("Particle before line %d has no ID or a Bad one -> Particle Not Created.", _Line);
|
|
}// parseParticle //
|
|
|
|
//-----------------------------------------------
|
|
// parseParticleId :
|
|
// Parse Particle's Id.
|
|
//-----------------------------------------------
|
|
void CSceneParser::parseParticleId()
|
|
{
|
|
char *ptr = strtok(NULL, delimiter);
|
|
if(ptr != NULL)
|
|
_CurrentParticle.Id = atoi(ptr);
|
|
}// parseParticleId //
|
|
|
|
//-----------------------------------------------
|
|
// parseParticleIG :
|
|
// Parse Particle's IG.
|
|
//-----------------------------------------------
|
|
void CSceneParser::parseParticleIG()
|
|
{
|
|
char *ptr = strtok(NULL, delimiter);
|
|
if(ptr != NULL)
|
|
_CurrentParticle.IG = ptr;
|
|
}// parseParticleIG //
|
|
|
|
//-----------------------------------------------
|
|
// parseParticleCluster :
|
|
// Parse Particle's Cluster.
|
|
//-----------------------------------------------
|
|
void CSceneParser::parseParticleCluster()
|
|
{
|
|
char *ptr = strtok(NULL, delimiter);
|
|
if(ptr != NULL)
|
|
_CurrentParticle.Cluster = ptr;
|
|
}// parseParticleCluster //
|
|
|
|
//-----------------------------------------------
|
|
// parseParticleActor :
|
|
// Parse Particle's Actor.
|
|
//-----------------------------------------------
|
|
void CSceneParser::parseParticleActor()
|
|
{
|
|
char *ptr = strtok(NULL, delimiter);
|
|
if(ptr != NULL)
|
|
_CurrentParticle.Actor = atoi(ptr);
|
|
}// parseParticleActor //
|
|
|
|
//-----------------------------------------------
|
|
// parseParticleAnims :
|
|
// Parse Particle's anims.
|
|
//-----------------------------------------------
|
|
void CSceneParser::parseParticleAnims(ifstream &file, char *buff)
|
|
{
|
|
while(!file.eof())
|
|
{
|
|
// Get next valid line.
|
|
getNextValidLine(file, buff);
|
|
|
|
char *ptr = strtok(buff, delimiter);
|
|
if(ptr != NULL)
|
|
{
|
|
// End of the actor definition.
|
|
if(strcmp(ptr, "End_Anims") == 0)
|
|
break;
|
|
// Meshes Name.
|
|
else
|
|
_CurrentParticle.Anims.push_back(ptr);
|
|
}
|
|
}
|
|
}// parseParticleAnims //
|
|
|
|
|
|
////////////
|
|
// ACTORS //
|
|
//-----------------------------------------------
|
|
// parseActor :
|
|
// Parse an actor.
|
|
//-----------------------------------------------
|
|
void CSceneParser::parseActor(ifstream &file, char *buff)
|
|
{
|
|
// Reset the current actor.
|
|
_CurrentActor.reset();
|
|
|
|
while(!file.eof())
|
|
{
|
|
// Get next valid line.
|
|
getNextValidLine(file, buff);
|
|
|
|
char *ptr = strtok(buff, delimiter);
|
|
if(ptr != NULL)
|
|
{
|
|
// End of the actor definition.
|
|
if(strcmp(ptr, "End_Actor") == 0)
|
|
break;
|
|
|
|
// Actor's Id
|
|
else if(strcmp(ptr, "Id:") == 0)
|
|
parseId();
|
|
|
|
// Actor's Name
|
|
else if(strcmp(ptr, "Name:") == 0)
|
|
parseName();
|
|
|
|
// Is the Actor a flyer.
|
|
else if(strcmp(ptr, "Fly:") == 0)
|
|
parseFly();
|
|
|
|
// Actor father of the particle is there is one.
|
|
else if(strcmp(ptr, "Actor:") == 0)
|
|
parseActorActor();
|
|
|
|
// Actor's Skeleton
|
|
else if(strcmp(ptr, "Skel:") == 0)
|
|
parseSkel();
|
|
|
|
// Actor's Meshes
|
|
else if(strcmp(ptr, "Meshes:") == 0)
|
|
parseMeshes(file, buff);
|
|
|
|
// Actor's Anims
|
|
else if(strcmp(ptr, "Anims:") == 0)
|
|
parseAnims(file, buff);
|
|
|
|
// Bad Keyword
|
|
else
|
|
nlwarning("Unknown keyword '%s' at line %d.", ptr, _Line);
|
|
}
|
|
}
|
|
|
|
// If the current actor Id is Valid -> create the actor.
|
|
if(_CurrentActor.Id >= 0)
|
|
{
|
|
map<uint, CActor>::iterator it = _Actors.find((uint)_CurrentActor.Id);
|
|
// Id already exists.
|
|
if(it != _Actors.end())
|
|
nlwarning("Actor before line %d has the ID %d that already exists -> Actor Not Created.", _Line, _CurrentActor.Id);
|
|
// Insert the new actor.
|
|
else
|
|
_Actors.insert(make_pair((uint)_CurrentActor.Id, _CurrentActor));
|
|
}
|
|
else
|
|
nlwarning("Actor before line %d has no ID or a Bad one -> Actor Not Created.", _Line);
|
|
}// parseActor //
|
|
|
|
//-----------------------------------------------
|
|
// parseId :
|
|
// Parse the current actor Id.
|
|
//-----------------------------------------------
|
|
void CSceneParser::parseId()
|
|
{
|
|
char *ptr = strtok(NULL, delimiter);
|
|
if(ptr != NULL)
|
|
_CurrentActor.Id = atoi(ptr);
|
|
}// parseId //
|
|
|
|
//-----------------------------------------------
|
|
// parseName :
|
|
// Parse the current actor Name.
|
|
//-----------------------------------------------
|
|
void CSceneParser::parseName()
|
|
{
|
|
char *ptr = strtok(NULL, delimiter);
|
|
if(ptr != NULL)
|
|
_CurrentActor.Name = ptr;
|
|
}// parseName //
|
|
|
|
//-----------------------------------------------
|
|
// parseFly :
|
|
// Is the Actor a flyer.
|
|
//-----------------------------------------------
|
|
void CSceneParser::parseFly()
|
|
{
|
|
char *ptr = strtok(NULL, delimiter);
|
|
if(ptr != NULL)
|
|
{
|
|
if(atoi(ptr))
|
|
_CurrentActor.Fly = true;
|
|
else
|
|
_CurrentActor.Fly = false;
|
|
}
|
|
}// parseFly //
|
|
|
|
//-----------------------------------------------
|
|
// parseActorActor :
|
|
// Parse Actor's Actor.
|
|
//-----------------------------------------------
|
|
void CSceneParser::parseActorActor()
|
|
{
|
|
char *ptr = strtok(NULL, delimiter);
|
|
if(ptr != NULL)
|
|
{
|
|
_CurrentActor.Actor = atoi(ptr);
|
|
nlwarning("Actor: %d Follow : %d", _CurrentActor.Id, _CurrentActor.Actor);
|
|
}
|
|
}// parseActorActor //
|
|
|
|
//-----------------------------------------------
|
|
// parseSkel :
|
|
// Parse the current actor Skeleton Name.
|
|
//-----------------------------------------------
|
|
void CSceneParser::parseSkel()
|
|
{
|
|
char *ptr = strtok(NULL, delimiter);
|
|
if(ptr != NULL)
|
|
_CurrentActor.Skeleton = ptr;
|
|
}// parseSkel //
|
|
|
|
//-----------------------------------------------
|
|
// parseMeshes :
|
|
// Parse meshes used for the current actor.
|
|
//-----------------------------------------------
|
|
void CSceneParser::parseMeshes(ifstream &file, char *buff)
|
|
{
|
|
while(!file.eof())
|
|
{
|
|
// Get next valid line.
|
|
getNextValidLine(file, buff);
|
|
|
|
char *ptr = strtok(buff, delimiter);
|
|
if(ptr != NULL)
|
|
{
|
|
// End of the actor definition.
|
|
if(strcmp(ptr, "End_Meshes") == 0)
|
|
break;
|
|
// Meshes Name.
|
|
else
|
|
_CurrentActor.Meshes.push_back(ptr);
|
|
}
|
|
}
|
|
}// parseMeshes //
|
|
|
|
//-----------------------------------------------
|
|
// parseAnims :
|
|
// Parse anims used for the current actor.
|
|
//-----------------------------------------------
|
|
void CSceneParser::parseAnims(ifstream &file, char *buff)
|
|
{
|
|
while(!file.eof())
|
|
{
|
|
// Get next valid line.
|
|
getNextValidLine(file, buff);
|
|
|
|
char *ptr = strtok(buff, delimiter);
|
|
if(ptr != NULL)
|
|
{
|
|
// End of the actor definition.
|
|
if(strcmp(ptr, "End_Anims") == 0)
|
|
break;
|
|
// Meshes Name.
|
|
else
|
|
_CurrentActor.Anims.push_back(ptr);
|
|
}
|
|
}
|
|
}// parseAnims //
|
|
|
|
|
|
////////////
|
|
// CAMERA //
|
|
//-----------------------------------------------
|
|
// parseCamAnims :
|
|
// Parse all anims used for the camera in all sequence.
|
|
//-----------------------------------------------
|
|
void CSceneParser::parseCamAnims(ifstream &file, char *buff)
|
|
{
|
|
while(!file.eof())
|
|
{
|
|
// Get next valid line.
|
|
getNextValidLine(file, buff);
|
|
|
|
char *ptr = strtok(buff, delimiter);
|
|
if(ptr != NULL)
|
|
{
|
|
// End of Anims for the camera.
|
|
if(strcmp(ptr, "End_Camera") == 0)
|
|
break;
|
|
// Meshes Name.
|
|
else
|
|
_CamAnims.push_back(ptr);
|
|
}
|
|
}
|
|
}// parseCamAnims //
|
|
|
|
|
|
///////////////
|
|
// SEQUENCES //
|
|
//-----------------------------------------------
|
|
// parseSequence :
|
|
// Parse a sequence.
|
|
//-----------------------------------------------
|
|
void CSceneParser::parseSequence(ifstream &file, char *buff)
|
|
{
|
|
// Reset the current sequence.
|
|
_CurrentSequence.reset();
|
|
|
|
while(!file.eof())
|
|
{
|
|
// Get next valid line.
|
|
getNextValidLine(file, buff);
|
|
|
|
char *ptr = strtok(buff, delimiter);
|
|
if(ptr != NULL)
|
|
{
|
|
// End of the actor definition.
|
|
if(strcmp(ptr, "End_Sequence") == 0)
|
|
break;
|
|
|
|
// Sequence Id.
|
|
else if(strcmp(ptr, "Id:") == 0)
|
|
parseSeqId();
|
|
|
|
// Particle for the sequence.
|
|
else if(strcmp(ptr, "Particle:") == 0)
|
|
parseSeqParticle(file, buff);
|
|
|
|
// Actor for the sequence.
|
|
else if(strcmp(ptr, "Actor:") == 0)
|
|
parseSeqActor(file, buff);
|
|
|
|
// Camera for the sequence.
|
|
else if(strcmp(ptr, "Camera:") == 0)
|
|
parseSeqCam(file, buff);
|
|
|
|
// Bad Keyword
|
|
else
|
|
nlwarning("Unknown keyword '%s' at line %d.", ptr, _Line);
|
|
}
|
|
}
|
|
|
|
// If the sequence Id is Valid -> create the sequence.
|
|
if(_CurrentSequence.Id >= 0)
|
|
{
|
|
map<uint, CSequence>::iterator itSeq = _Sequences.find((uint)_CurrentSequence.Id);
|
|
// Id already exists.
|
|
if(itSeq != _Sequences.end())
|
|
nlwarning("Sequence before line %d has the ID %d that already exists -> Sequence Not Created.", _Line, _CurrentSequence.Id);
|
|
// Insert the new actor.
|
|
else
|
|
_Sequences.insert(make_pair((uint)_CurrentSequence.Id, _CurrentSequence));
|
|
}
|
|
else
|
|
nlwarning("Sequence before line %d has no ID or a Bad one -> Sequence Not Created.", _Line);
|
|
}// parseSequence //
|
|
|
|
//-----------------------------------------------
|
|
// parseSeqId :
|
|
// Parse the current sequence Id.
|
|
//-----------------------------------------------
|
|
void CSceneParser::parseSeqId()
|
|
{
|
|
char *ptr = strtok(NULL, delimiter);
|
|
if(ptr != NULL)
|
|
_CurrentSequence.Id = atoi(ptr);
|
|
}// parseSeqId //
|
|
|
|
//-----------------------------------------------
|
|
// parseSeqParticle :
|
|
// Parse particle in the sequence.
|
|
//-----------------------------------------------
|
|
void CSceneParser::parseSeqParticle(ifstream &file, char *buff)
|
|
{
|
|
// Reset the current particle in the sequence.
|
|
_CurParticleSeq.reset();
|
|
|
|
while(!file.eof())
|
|
{
|
|
// Get next valid line.
|
|
getNextValidLine(file, buff);
|
|
|
|
char *ptr = strtok(buff, delimiter);
|
|
if(ptr != NULL)
|
|
{
|
|
// End of the actor definition.
|
|
if(strcmp(ptr, "End_Particle") == 0)
|
|
break;
|
|
|
|
// Actor in Sequence Id.
|
|
else if(strcmp(ptr, "Id:") == 0)
|
|
parseSeqParticleId();
|
|
|
|
// Actor in Sequence anims.
|
|
else if(strcmp(ptr, "Anims:") == 0)
|
|
parseSeqParticleAnims(file, buff);
|
|
|
|
// Bad Keyword
|
|
else
|
|
nlwarning("Unknown keyword '%s' at line %d.", ptr, _Line);
|
|
}
|
|
}
|
|
|
|
// If the particle's Id in the sequence is Valid -> create the particleSeq.
|
|
if(_CurParticleSeq.Id >= 0)
|
|
{
|
|
map<uint, CParticleSeq>::iterator itPartSeq = _CurrentSequence.ParticlesSeq.find((uint)_CurParticleSeq.Id);
|
|
// Id already exists.
|
|
if(itPartSeq != _CurrentSequence.ParticlesSeq.end())
|
|
nlwarning("Particle in Sequence before line %d has the ID %d that already exists -> Particle in the sequence Not Created.", _Line, _CurParticleSeq.Id);
|
|
// Insert the new particle in the sequence.
|
|
else
|
|
_CurrentSequence.ParticlesSeq.insert(make_pair((uint)_CurParticleSeq.Id, _CurParticleSeq));
|
|
}
|
|
else
|
|
nlwarning("Particle in Sequence before line %d has no ID or a Bad one -> Particle in the sequence Not Created.", _Line);
|
|
}// parseSeqParticle //
|
|
|
|
//-----------------------------------------------
|
|
// parseSeqParticleId :
|
|
// Parse the current particle's Id in the current sequence.
|
|
//-----------------------------------------------
|
|
void CSceneParser::parseSeqParticleId()
|
|
{
|
|
char *ptr = strtok(NULL, delimiter);
|
|
if(ptr != NULL)
|
|
_CurParticleSeq.Id = atoi(ptr);
|
|
}// parseSeqParticleId //
|
|
|
|
//-----------------------------------------------
|
|
// parseSeqParticleAnims :
|
|
// Parse anims used for the current particle in the current sequence.
|
|
//-----------------------------------------------
|
|
void CSceneParser::parseSeqParticleAnims(ifstream &file, char *buff)
|
|
{
|
|
while(!file.eof())
|
|
{
|
|
// Get next valid line.
|
|
getNextValidLine(file, buff);
|
|
|
|
char *ptr = strtok(buff, delimiter);
|
|
if(ptr != NULL)
|
|
{
|
|
// End of the actor definition.
|
|
if(strcmp(ptr, "End_Anims") == 0)
|
|
break;
|
|
// Meshes Name.
|
|
else
|
|
_CurParticleSeq.Anims.push_back(ptr);
|
|
}
|
|
}
|
|
}// parseSeqParticleAnims //
|
|
|
|
//-----------------------------------------------
|
|
// parseSeqActor :
|
|
// Parse an actor in a sequence.
|
|
//-----------------------------------------------
|
|
void CSceneParser::parseSeqActor(ifstream &file, char *buff)
|
|
{
|
|
// Reset the current sequence.
|
|
_CurrentActorSeq.reset();
|
|
|
|
while(!file.eof())
|
|
{
|
|
// Get next valid line.
|
|
getNextValidLine(file, buff);
|
|
|
|
char *ptr = strtok(buff, delimiter);
|
|
if(ptr != NULL)
|
|
{
|
|
// End of the actor definition.
|
|
if(strcmp(ptr, "End_Actor") == 0)
|
|
break;
|
|
|
|
// Actor in Sequence Id.
|
|
else if(strcmp(ptr, "Id:") == 0)
|
|
parseSeqActorId();
|
|
|
|
// Actor in Sequence anims.
|
|
else if(strcmp(ptr, "Anims:") == 0)
|
|
parseSeqActorAnims(file, buff);
|
|
|
|
// Bad Keyword
|
|
else
|
|
nlwarning("Unknown keyword '%s' at line %d.", ptr, _Line);
|
|
}
|
|
}
|
|
|
|
// If the actor's Id in the sequence is Valid -> create the actorSeq.
|
|
if(_CurrentActorSeq.Id >= 0)
|
|
{
|
|
map<uint, CActorSeq>::iterator itActSeq = _CurrentSequence.ActorsSeq.find((uint)_CurrentActorSeq.Id);
|
|
// Id already exists.
|
|
if(itActSeq != _CurrentSequence.ActorsSeq.end())
|
|
nlwarning("Actor in Sequence before line %d has the ID %d that already exists -> Actor in the sequence Not Created.", _Line, _CurrentActorSeq.Id);
|
|
// Insert the new actor.
|
|
else
|
|
_CurrentSequence.ActorsSeq.insert(make_pair((uint)_CurrentActorSeq.Id, _CurrentActorSeq));
|
|
}
|
|
else
|
|
nlwarning("Actor in Sequence before line %d has no ID or a Bad one -> Actor in the sequence Not Created.", _Line);
|
|
}// parseSeqActor //
|
|
|
|
//-----------------------------------------------
|
|
// parseSeqActorId :
|
|
// Parse the current actor's Id in the current sequence.
|
|
//-----------------------------------------------
|
|
void CSceneParser::parseSeqActorId()
|
|
{
|
|
char *ptr = strtok(NULL, delimiter);
|
|
if(ptr != NULL)
|
|
_CurrentActorSeq.Id = atoi(ptr);
|
|
}// parseSeqActorId //
|
|
|
|
//-----------------------------------------------
|
|
// parseSeqActorAnims :
|
|
// Parse anims used for the current actor in the current sequence.
|
|
//-----------------------------------------------
|
|
void CSceneParser::parseSeqActorAnims(ifstream &file, char *buff)
|
|
{
|
|
while(!file.eof())
|
|
{
|
|
// Get next valid line.
|
|
getNextValidLine(file, buff);
|
|
|
|
char *ptr = strtok(buff, delimiter);
|
|
if(ptr != NULL)
|
|
{
|
|
// End of the actor definition.
|
|
if(strcmp(ptr, "End_Anims") == 0)
|
|
break;
|
|
// Meshes Name.
|
|
else
|
|
_CurrentActorSeq.Anims.push_back(ptr);
|
|
}
|
|
}
|
|
}// parseSeqActorAnims //
|
|
|
|
//-----------------------------------------------
|
|
// parseSeqCam :
|
|
// Parse camera in the sequence.
|
|
//-----------------------------------------------
|
|
void CSceneParser::parseSeqCam(ifstream &file, char *buff)
|
|
{
|
|
while(!file.eof())
|
|
{
|
|
// Get next valid line.
|
|
getNextValidLine(file, buff);
|
|
|
|
char *ptr = strtok(buff, delimiter);
|
|
if(ptr != NULL)
|
|
{
|
|
// End of the actor definition.
|
|
if(strcmp(ptr, "End_Camera") == 0)
|
|
break;
|
|
// Meshes Name.
|
|
else
|
|
_CurrentSequence.CamAnims.push_back(ptr);
|
|
}
|
|
}
|
|
}// parseSeqCam //
|
|
|
|
|
|
////////////////
|
|
// INIT AFTER //
|
|
//-----------------------------------------------
|
|
// initActors :
|
|
// Initialize Actors Position and rotation .
|
|
//-----------------------------------------------
|
|
void CSceneParser::initActors()
|
|
{
|
|
if(_IG_Init.empty())
|
|
return;
|
|
|
|
// Create the instance group with all start positions and rotations.
|
|
UInstanceGroup *IGInit = UInstanceGroup::createInstanceGroup(_IG_Init);
|
|
if(IGInit)
|
|
{
|
|
int nbInst = IGInit->getNumInstance();
|
|
map<uint, CActor>::iterator itActor;
|
|
for(int i = 0; i < nbInst; ++i )
|
|
{
|
|
sint id = atoi(IGInit->getInstanceName(i).c_str());
|
|
itActor = _Actors.find(id);
|
|
if(itActor != _Actors.end())
|
|
{
|
|
CActor &actor = (*itActor).second;
|
|
actor.Pos = IGInit->getInstancePos(i);
|
|
actor.Rot = IGInit->getInstanceRot(i);
|
|
}
|
|
else
|
|
nlwarning("CSceneParser::initActors : Actor %d is in the IG \"%s\" but is not in the script.", id, _IG_Init.c_str());
|
|
}
|
|
|
|
// Destroy the IG to initialize (all is already backup now).
|
|
delete IGInit;
|
|
IGInit = 0;
|
|
}
|
|
else
|
|
nlwarning("CSceneParser::initActors : Can't create the Instance group to initialize actors.");
|
|
}// initActors ///
|
|
|
|
|
|
//////////////
|
|
// PLAY SEQ //
|
|
//-----------------------------------------------
|
|
// apply :
|
|
// Initialize the scene with the parameters loaded from the script.
|
|
//-----------------------------------------------
|
|
void CSceneParser::apply()
|
|
{
|
|
// If the scene is already initialized -> reset the scene.
|
|
if(_Apply)
|
|
{
|
|
reset();
|
|
return;
|
|
}
|
|
|
|
// Create a play list manager for the scene.
|
|
_PlayListManager = Scene->createPlayListManager();
|
|
|
|
// Initialize the Camera and reset it the second time.
|
|
applyCamera();
|
|
|
|
// Initialize IG for the scenery (IG present from start to end like trees or torch.
|
|
applyIG();
|
|
|
|
// Initialize Particles.
|
|
applyParticles();
|
|
|
|
// Initialize Actors.
|
|
applyActors();
|
|
|
|
// Scene already aplly now.
|
|
_Apply = true;
|
|
}// apply //
|
|
|
|
//-----------------------------------------------
|
|
// reset :
|
|
// Reset the scene.
|
|
//-----------------------------------------------
|
|
void CSceneParser::reset()
|
|
{
|
|
// Camera in scene mode.
|
|
UserControls.mode(CUserControls::InterfaceMode);
|
|
|
|
// Reset all particles.
|
|
resetParticles();
|
|
|
|
// Reset all actors.
|
|
resetActors();
|
|
}// reset //
|
|
|
|
//-----------------------------------------------
|
|
// resetParticles :
|
|
// Reset all particles.
|
|
//-----------------------------------------------
|
|
void CSceneParser::resetParticles()
|
|
{
|
|
map<uint, CParticle>::iterator itPart = _Particles.begin();
|
|
for(itPart = _Particles.begin(); itPart != _Particles.end(); ++itPart)
|
|
{
|
|
// Get a reference on the particule.
|
|
CParticle &particle = (*itPart).second;
|
|
|
|
// Check if the IG of particles is not already in the scene.
|
|
if(particle.IGPtr && _IGInScene.find(particle.IGPtr) != _IGInScene.end())
|
|
{
|
|
// Reset the playlist.
|
|
particle.PlayList->resetAllChannels();
|
|
|
|
// Remove from the set with all particle in the scene.
|
|
_IGInScene.erase(particle.IGPtr);
|
|
// Remove particles from scene.
|
|
particle.IGPtr->removeFromScene(*Scene);
|
|
Scene->deleteInstanceGroup (particle.IGPtr);
|
|
|
|
// Load the IG of the particle.
|
|
particle.IGPtr = 0;
|
|
|
|
try
|
|
{
|
|
particle.IGPtr = UInstanceGroup::createInstanceGroup((*itPart).second.IG);
|
|
}
|
|
catch(Exception &e){nlwarning("CSceneParser::resetParticles : %s", e.what());}
|
|
}
|
|
}
|
|
}// resetParticles //
|
|
|
|
//-----------------------------------------------
|
|
// resetActors :
|
|
// Reset all actors.
|
|
//-----------------------------------------------
|
|
void CSceneParser::resetActors()
|
|
{
|
|
// Create new entities from actors
|
|
map<uint, CActor>::iterator itActor;
|
|
for(itActor = _Actors.begin(); itActor != _Actors.end(); ++itActor)
|
|
{
|
|
// Get a reference on the actor.
|
|
CActor &actor = (*itActor).second;
|
|
|
|
// Get the Sid.
|
|
Sid entityId(Sid::npc, (uint64)actor.Id);
|
|
|
|
// Find the actor.
|
|
CEntityCL *entity = getEntity(entityId);
|
|
if(entity)
|
|
{
|
|
// Position the entity.
|
|
entity->pacsPos(actor.Pos);
|
|
|
|
// Position the skeleton at the same position as the entity.
|
|
if(entity->skeleton())
|
|
{
|
|
entity->skeleton()->setPos(actor.Pos);
|
|
entity->skeleton()->setRotQuat(actor.Rot);
|
|
}
|
|
}
|
|
|
|
// Reset entity animations.
|
|
resetAnimatedSceneObject(entityId);
|
|
}
|
|
}// resetActors //
|
|
|
|
|
|
//-----------------------------------------------
|
|
// applyParticles :
|
|
// Initialize the scene with the parameters loaded from the script for particles.
|
|
//-----------------------------------------------
|
|
void CSceneParser::applyParticles()
|
|
{
|
|
map<uint, CParticle>::iterator itPart = _Particles.begin();
|
|
for(itPart = _Particles.begin(); itPart != _Particles.end(); ++itPart)
|
|
{
|
|
// Get a reference on the particule.
|
|
CParticle &particle = (*itPart).second;
|
|
|
|
// Create the animation set for the particule.
|
|
particle.AnimationSet = Driver->createAnimationSet();
|
|
|
|
// Add animations to the animation set.
|
|
list<string>::iterator itPartAnim;
|
|
for(itPartAnim = particle.Anims.begin(); itPartAnim != particle.Anims.end(); ++itPartAnim)
|
|
{
|
|
uint idAnim = UAnimationSet::NotFound;
|
|
try
|
|
{
|
|
idAnim = particle.AnimationSet->addAnimation((*itPartAnim + string(".anim")).c_str(), (*itPartAnim).c_str());
|
|
}
|
|
catch(Exception &e) {nlwarning("%s", e.what());}
|
|
|
|
if(idAnim != UAnimationSet::NotFound)
|
|
{
|
|
particle.AnimToId.insert(make_pair((*itPartAnim).c_str(), idAnim));
|
|
}
|
|
else
|
|
nlwarning("CSceneParser::applyParticles : Anim %s cannot be add in the animation set", (*itPartAnim).c_str());
|
|
}
|
|
|
|
// Build animation set
|
|
particle.AnimationSet->build();
|
|
|
|
// Create playlist.
|
|
particle.PlayList = _PlayListManager->createPlayList(particle.AnimationSet);
|
|
if(particle.PlayList)
|
|
{
|
|
// Load the IG of the particle.
|
|
particle.IGPtr = 0;
|
|
try
|
|
{
|
|
particle.IGPtr = UInstanceGroup::createInstanceGroup((*itPart).second.IG);
|
|
}
|
|
catch(Exception &e) {nlwarning("%s", e.what());}
|
|
|
|
if(particle.IGPtr)
|
|
{
|
|
// Get the position of Instances in IG.
|
|
for(uint i = 0; i < particle.IGPtr->getNumInstance(); ++i )
|
|
particle.IGPos.push_back(particle.IGPtr->getInstancePos(i));
|
|
}
|
|
}
|
|
}
|
|
}// applyParticles //
|
|
|
|
//-----------------------------------------------
|
|
// applyCamera :
|
|
// Initialize the Camera and reset it the second time.
|
|
//-----------------------------------------------
|
|
void CSceneParser::applyCamera()
|
|
{
|
|
// Create the animation set for the camera if not already done.
|
|
_AnimationSet = Driver->createAnimationSet();
|
|
if(_AnimationSet)
|
|
{
|
|
list<string>::iterator itCamAnims;
|
|
for(itCamAnims = _CamAnims.begin(); itCamAnims != _CamAnims.end(); ++itCamAnims)
|
|
{
|
|
uint idAnim = UAnimationSet::NotFound;
|
|
try
|
|
{
|
|
idAnim = _AnimationSet->addAnimation((*itCamAnims + string(".anim")).c_str(), (*itCamAnims).c_str());
|
|
}
|
|
catch(Exception &e) {nlwarning("%s", e.what());}
|
|
|
|
if(idAnim != UAnimationSet::NotFound)
|
|
_AnimCamToId.insert(make_pair((*itCamAnims).c_str(), idAnim));
|
|
else
|
|
nlwarning("CSceneParser::apply : Camera Anim %s cannot be add in the animation set", (*itCamAnims).c_str());
|
|
}
|
|
|
|
// Build animation set
|
|
_AnimationSet->build();
|
|
|
|
// create playlist
|
|
_PlayList = _PlayListManager->createPlayList( _AnimationSet );
|
|
}
|
|
else
|
|
nlwarning("CSceneParser::apply : AnimationSet cannot be created.");
|
|
}// applyCamera //
|
|
|
|
//-----------------------------------------------
|
|
// applyIG :
|
|
// Initialize IG for the scenery (IG present from start to end like trees or torch.
|
|
//-----------------------------------------------
|
|
void CSceneParser::applyIG()
|
|
{
|
|
// Load Instances Groups for the scene.
|
|
for(list<string>::iterator itIG = _IG.begin(); itIG != _IG.end(); ++itIG)
|
|
{
|
|
UInstanceGroup *IGTemp = 0;
|
|
try
|
|
{
|
|
IGTemp = UInstanceGroup::createInstanceGroup(*itIG);
|
|
}
|
|
catch(Exception &e) {nlwarning("CSceneParser::applyIG : %s", e.what());}
|
|
|
|
// Add Instance Group in the scene.
|
|
if(IGTemp)
|
|
IGTemp->addToScene(*Scene, Driver);
|
|
}
|
|
}// applyIG //
|
|
|
|
//-----------------------------------------------
|
|
// applyActors :
|
|
// Initialize actors.
|
|
//-----------------------------------------------
|
|
void CSceneParser::applyActors()
|
|
{
|
|
// Create new entities from actors
|
|
map<uint, CActor>::iterator itActor;
|
|
for(itActor = _Actors.begin(); itActor != _Actors.end(); ++itActor)
|
|
{
|
|
// Get a reference on the actor.
|
|
CActor &actor = (*itActor).second;
|
|
|
|
// Create the entity Sid.
|
|
Sid entityId(Sid::npc, (uint64)actor.Id);
|
|
|
|
// Create the entity type.
|
|
CTypeEntity typeEntity;
|
|
typeEntity.TypeInfo.TypeEntity = CTypeEntity::npc;
|
|
typeEntity.TypeInfo.Kind = CTypeEntity::zorai;
|
|
typeEntity.TypeInfo.Age = CTypeEntity::adult;
|
|
typeEntity.TypeInfo.Sex = CTypeEntity::male;
|
|
|
|
// Create the entity.
|
|
CEntityCL *entityTmp = createEntity(entityId, typeEntity);
|
|
if(entityTmp)
|
|
{
|
|
// Get a reference on the entity.
|
|
CEntityCL &entity = *entityTmp;
|
|
|
|
// True if the entity fly.
|
|
entity.flyer(actor.Fly);
|
|
|
|
// Set the name of the entity
|
|
entity.name(actor.Name);
|
|
// Time for the current frame.
|
|
entity.time(T1);
|
|
// Set the entity position.
|
|
entity.pacsPos(actor.Pos);
|
|
// Set the Front.
|
|
CMatrix m;
|
|
m.identity();
|
|
m.setRot(actor.Rot);
|
|
entity.front((m * CVector::J).normed());
|
|
// Set the direction like the front.
|
|
entity.dir(entity.front());
|
|
// Set the vector UP.
|
|
entity.up(CVector(0.f,0.f,1.f));
|
|
|
|
// Assign a skeleton.
|
|
entity.skeleton(actor.Skeleton);
|
|
|
|
// Position the entity.
|
|
entity.pacsPos(actor.Pos);
|
|
|
|
// Position the skeleton at the same position as the entity.
|
|
if(entity.skeleton())
|
|
{
|
|
entity.skeleton()->setPos(actor.Pos);
|
|
entity.skeleton()->setRotQuat(actor.Rot);
|
|
}
|
|
|
|
// Assign meshes used for the entity.
|
|
uint count = 0;
|
|
list<string>::iterator itMeshes;
|
|
for(itMeshes = actor.Meshes.begin(); itMeshes != actor.Meshes.end(); ++itMeshes)
|
|
{
|
|
// If there are too many meshes.
|
|
if(count >= (uint)CEntityCL::NB_SLOT)
|
|
{
|
|
nlwarning("CSceneParser::applyActors : Too many meshes for Actor %d.", actor.Id);
|
|
break;
|
|
}
|
|
|
|
entity.slot((CEntityCL::ESlots)count, *itMeshes);
|
|
++count;
|
|
}
|
|
|
|
// Create the playlist
|
|
addEntityClAnimatedSceneObject(entityId, actor.Anims);
|
|
}
|
|
else
|
|
nlwarning("CSceneParser::applyActors : Entity %d Not created", actor.Id);
|
|
}
|
|
}// applyActors //
|
|
|
|
|
|
//-----------------------------------------------
|
|
// playSeq :
|
|
// Play the sequence with the ID 'seq'.
|
|
//-----------------------------------------------
|
|
void CSceneParser::playSeq(uint seq, double timeInSec)
|
|
{
|
|
// If the scene is not initialized -> return.
|
|
if(!_Apply)
|
|
return;
|
|
|
|
// Camera in scene mode.
|
|
UserControls.mode(CUserControls::SceneMode);
|
|
|
|
_TimeStart = timeInSec;
|
|
|
|
map<uint, CSequence>::iterator itSeq = _Sequences.find(seq);
|
|
if(itSeq != _Sequences.end())
|
|
{
|
|
// Get a reference on the sequence.
|
|
CSequence &sequence = (*itSeq).second;
|
|
|
|
// Log the time used for the sequence.
|
|
nlwarning("Sequence: %d, Time: %f", seq, timeInSec);
|
|
|
|
// Camera in the sequence.
|
|
if(!sequence.CamAnims.empty())
|
|
{
|
|
if(_PlayList)
|
|
{
|
|
map<string, uint>::iterator itAnimCamId;
|
|
for(itAnimCamId = _AnimCamToId.begin(); itAnimCamId != _AnimCamToId.end(); ++itAnimCamId)
|
|
{
|
|
_PlayList->setTimeOrigin(0, timeInSec);
|
|
_PlayList->setAnimation(0, (*itAnimCamId).second);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Particles in the sequence.
|
|
map<uint, CParticleSeq>::iterator itPartSeq;
|
|
for(itPartSeq = sequence.ParticlesSeq.begin(); itPartSeq != sequence.ParticlesSeq.end(); ++itPartSeq)
|
|
{
|
|
CParticleSeq &particleSeq = (*itPartSeq).second;
|
|
map<uint, CParticle>::iterator itPart = _Particles.find(particleSeq.Id);
|
|
if(itPart != _Particles.end())
|
|
{
|
|
// Get a reference on the particle.
|
|
CParticle &particle = (*itPart).second;
|
|
// Check if the IG has been created.
|
|
if(particle.IGPtr)
|
|
{
|
|
// Check if the IG of particles is not already in the scene.
|
|
if(_IGInScene.find(particle.IGPtr) == _IGInScene.end())
|
|
{
|
|
// Insert IG in the set of IG in the scene.
|
|
_IGInScene.insert(particle.IGPtr);
|
|
// Cluster.
|
|
if(IGCity.find(particle.Cluster) == IGCity.end())
|
|
Scene->setToGlobalInstanceGroup(particle.IGPtr);
|
|
else
|
|
particle.IGPtr->setClusterSystem(IGCity[particle.Cluster]);
|
|
// Add particles to the scene.
|
|
particle.IGPtr->addToScene(*Scene, Driver);
|
|
// Unfreeze the IG.
|
|
particle.IGPtr->unfreezeHRC();
|
|
|
|
// Register all instances in the IG to a playlist.
|
|
for(uint i = 0; i < particle.IGPtr->getNumInstance(); ++i )
|
|
{
|
|
std::string iName = particle.IGPtr->getInstanceName( i );
|
|
UInstance instance = particle.IGPtr->getByName( iName );
|
|
particle.PlayList->registerTransform(instance);
|
|
particle.PlayList->registerTransform(instance, (iName + ".").c_str());
|
|
}
|
|
}
|
|
|
|
// Start the particle animation.
|
|
map<string, uint>::iterator itAnimId;
|
|
for(itAnimId = particle.AnimToId.begin(); itAnimId != particle.AnimToId.end(); ++itAnimId)
|
|
{
|
|
particle.PlayList->setTimeOrigin(0, timeInSec);
|
|
particle.PlayList->setAnimation(0, (*itAnimId).second);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Actors in the sequence.
|
|
map<uint, CActorSeq>::iterator itActSeq;
|
|
for(itActSeq = sequence.ActorsSeq.begin(); itActSeq != sequence.ActorsSeq.end(); ++itActSeq)
|
|
{
|
|
CActorSeq &actorSeq = (*itActSeq).second;
|
|
updateAnimationSequence(Sid(Sid::npc, (uint64)actorSeq.Id), actorSeq.Anims, 0 );
|
|
}
|
|
}
|
|
}// playSeq //
|
|
|
|
|
|
//-----------------------------------------------
|
|
// update :
|
|
// Update the scene.
|
|
//-----------------------------------------------
|
|
void CSceneParser::update(double timeInSec)
|
|
{
|
|
// Nothing to update if the scene is not applied.
|
|
if(!_Apply)
|
|
return;
|
|
|
|
// Update the scene currently playing.
|
|
updateScene(timeInSec);
|
|
|
|
// Update particles.
|
|
updateParticles(timeInSec);
|
|
|
|
// Animate the camera.
|
|
updateCamera(timeInSec);
|
|
|
|
// Update particle anims.
|
|
if(_PlayListManager)
|
|
_PlayListManager->animate(timeInSec);
|
|
|
|
// Update actor position (for actor on another actor).
|
|
updateActors();
|
|
}// update //
|
|
|
|
//-----------------------------------------------
|
|
// updateCamera :
|
|
// Update the camera (position, target, roll, fov)
|
|
//-----------------------------------------------
|
|
void CSceneParser::updateCamera(double timeInSec)
|
|
{
|
|
// If there is a play list for the camera.
|
|
if(_PlayList)
|
|
{
|
|
// Get the Id of the animation in the slot 0.
|
|
uint idAnim = _PlayList->getAnimation(0);
|
|
if(idAnim != UPlayList::empty)
|
|
{
|
|
UAnimation *animation = _AnimationSet->getAnimation(idAnim);
|
|
if(animation)
|
|
{
|
|
// Get Camera information from the animation (Pos, Target, Roll).
|
|
UTrack* trackRollCam = animation->getTrackByName("Camera.roll");
|
|
UTrack* trackFovCam = animation->getTrackByName("Camera.fov");
|
|
UTrack* trackPosCam = animation->getTrackByName("Camera.PathPos");
|
|
UTrack* trackPosTarget = animation->getTrackByName("Camera.Target.PathPos");
|
|
if(trackPosCam && trackPosTarget)
|
|
{
|
|
float rollCam = 0.f;
|
|
CVector posCam;
|
|
CVector posTarget;
|
|
float difTime = (float)(timeInSec-_TimeStart);
|
|
|
|
if(trackRollCam)
|
|
trackRollCam->interpolate(difTime, rollCam);
|
|
trackPosCam->interpolate(difTime, posCam);
|
|
trackPosTarget->interpolate(difTime, posTarget);
|
|
|
|
// Update camera transformations.
|
|
UCamera cam = Scene->getCam();
|
|
if(cam)
|
|
{
|
|
cam->setTransformMode(UTransformable::RotQuat);
|
|
cam->lookAt(posCam, posTarget, rollCam);
|
|
if(trackFovCam)
|
|
{
|
|
float fov;
|
|
trackFovCam->interpolate(difTime, fov);
|
|
CFrustum fr= cam->getFrustum();
|
|
// change only the fov
|
|
cam->setPerspective(fov, fr.getAspectRatio(), fr.Near, fr.Far);
|
|
}
|
|
}
|
|
|
|
// Update camera transformations for the Root.
|
|
cam = SceneRoot->getCam();
|
|
if(cam)
|
|
{
|
|
cam->setTransformMode(UTransformable::RotQuat);
|
|
cam->lookAt(posCam, posTarget, rollCam);
|
|
if(trackFovCam)
|
|
{
|
|
float fov;
|
|
trackFovCam->interpolate(difTime, fov);
|
|
CFrustum fr= cam->getFrustum();
|
|
// change only the fov
|
|
cam->setPerspective(fov, fr.getAspectRatio(), fr.Near, fr.Far);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}// updateCamera //
|
|
|
|
//-----------------------------------------------
|
|
// updateActors :
|
|
// Update Actors.
|
|
//-----------------------------------------------
|
|
void CSceneParser::updateActors()
|
|
{
|
|
// All actors in the scene.
|
|
for(map<uint, CActor>::iterator itActor = _Actors.begin(); itActor != _Actors.end(); ++itActor)
|
|
{
|
|
// Get a reference on the actor.
|
|
CActor &actor = (*itActor).second;
|
|
|
|
// If there is no actor to follow -> next actor.
|
|
if(actor.Actor < 0)
|
|
continue;
|
|
|
|
// Get the entity pointer.
|
|
CEntityCL *entity = getEntity(Sid(Sid::npc, (uint64)actor.Id));
|
|
if(!entity)
|
|
{
|
|
nlwarning("CSceneParser::updateActors : Cannot get the actor %d.", actor.Id);
|
|
continue;
|
|
}
|
|
|
|
// Get the target entity pointer.
|
|
CEntityCL *entityTarget = getEntity(Sid(Sid::npc, (uint64)actor.Actor));
|
|
if(!entityTarget)
|
|
{
|
|
nlwarning("CSceneParser::updateActors : Cannot get the targeted actor %d.", actor.Actor);
|
|
continue;
|
|
}
|
|
|
|
// Changes the entity position.
|
|
entity->pacsPos(entityTarget->pos());
|
|
}
|
|
}// updateActors //
|
|
|
|
//-----------------------------------------------
|
|
// updateParticles :
|
|
// Update particles.
|
|
//-----------------------------------------------
|
|
void CSceneParser::updateParticles(double timeInSec)
|
|
{
|
|
for(map<uint, CParticle>::iterator itPart = _Particles.begin(); itPart != _Particles.end(); ++itPart)
|
|
{
|
|
// Get a reference on the particule.
|
|
CParticle &particle = (*itPart).second;
|
|
|
|
// If the IG pointer is null -> Next particle.
|
|
if(!(particle.IGPtr))
|
|
continue;
|
|
|
|
// If the play list is NULL -> Next particle
|
|
if(!(particle.PlayList))
|
|
continue;
|
|
|
|
// Get the Id of the animation in the slot 0 -> if empty -> Next particle.
|
|
uint idAnim = particle.PlayList->getAnimation(0);
|
|
if(idAnim == UPlayList::empty)
|
|
continue;
|
|
|
|
// Get the animation pointer.
|
|
UAnimation *animation = particle.AnimationSet->getAnimation(idAnim);
|
|
if(!animation)
|
|
continue;
|
|
|
|
// Get the time difference.
|
|
float difTime = (float)(timeInSec-_TimeStart);
|
|
|
|
// Particle do not follow anything.
|
|
if(particle.Actor < 0)
|
|
{
|
|
updateParticlesNoActor(difTime, particle, *animation);
|
|
}
|
|
// Particle follow an actor.
|
|
else
|
|
{
|
|
updateParticlesActor(difTime, particle, *animation);
|
|
}
|
|
}
|
|
}// updateParticles //
|
|
|
|
//-----------------------------------------------
|
|
// updateParticlesNoActor :
|
|
//
|
|
//-----------------------------------------------
|
|
void CSceneParser::updateParticlesNoActor(float difTime, CParticle &particle, UAnimation &animation)
|
|
{
|
|
// Animate all instances.
|
|
for(uint i = 0; i < particle.IGPtr->getNumInstance(); ++i )
|
|
{
|
|
std::string iName = particle.IGPtr->getInstanceName(i);
|
|
UInstance instance = particle.IGPtr->getByName(iName);
|
|
|
|
if(!instance)
|
|
continue;
|
|
|
|
instance->setTransformMode(UTransformable::RotQuat);
|
|
|
|
// If the animation has no track of position.
|
|
UTrack* trackPos = animation.getTrackByName("PathPos");
|
|
if(!trackPos)
|
|
trackPos = animation.getTrackByName(string(iName + "." + "PathPos").c_str());
|
|
if(trackPos)
|
|
{
|
|
CVector pos;
|
|
trackPos->interpolate(difTime, pos);
|
|
instance->setPos(pos);
|
|
}
|
|
|
|
// If the animation has no track of rotation.
|
|
UTrack* trackRot = animation.getTrackByName("PathRotQuat");
|
|
if(!trackRot)
|
|
trackRot = animation.getTrackByName(string(iName + "." + "PathRotQuat").c_str());
|
|
if(trackRot)
|
|
{
|
|
CQuat rot;
|
|
if(trackRot->interpolate(difTime, rot))
|
|
instance->setRotQuat(rot);
|
|
else
|
|
nlwarning("CSceneParser::updateParticles : Not a Quat!");
|
|
}
|
|
}
|
|
}// updateParticlesNoActor //
|
|
|
|
|
|
//-----------------------------------------------
|
|
// updateParticlesActor :
|
|
//
|
|
//-----------------------------------------------
|
|
void CSceneParser::updateParticlesActor(float difTime, CParticle &particle, UAnimation &animation)
|
|
{
|
|
// Get the entity pointer.
|
|
CEntityCL *entity = getEntity(Sid(Sid::npc, (uint64)particle.Actor));
|
|
if(!entity)
|
|
{
|
|
nlwarning("CSceneParser::updateParticlesActor : cannot get the actor %d.", (uint64)particle.Actor);
|
|
return;
|
|
}
|
|
|
|
// If the entity has no skeleton -> Next particle.
|
|
if(!entity->skeleton())
|
|
{
|
|
nlwarning("The particle follow an entity %d without a skeleton.", (uint64)particle.Actor);
|
|
return;
|
|
}
|
|
|
|
// Matrix 90 degrees
|
|
CMatrix m90;
|
|
m90.identity();
|
|
m90.rotateZ((float)(Pi/2.0));
|
|
|
|
// Matrix of the entity.
|
|
CMatrix mChar = entity->skeleton()->getMatrix();
|
|
mChar.setPos(entity->pos());
|
|
|
|
// Animate all instances.
|
|
for(uint i = 0; i < particle.IGPtr->getNumInstance(); ++i )
|
|
{
|
|
std::string iName = particle.IGPtr->getInstanceName(i);
|
|
UInstance instance = particle.IGPtr->getByName(iName);
|
|
|
|
if(!instance)
|
|
continue;
|
|
|
|
instance->setTransformMode(UTransformable::RotQuat);
|
|
|
|
CMatrix mAnim;
|
|
mAnim.identity();
|
|
// If the animation has no track of position.
|
|
UTrack* trackPos = animation.getTrackByName("PathPos");
|
|
if(!trackPos)
|
|
trackPos = animation.getTrackByName(string(iName + "." + "PathPos").c_str());
|
|
if(trackPos)
|
|
{
|
|
CVector pos;
|
|
trackPos->interpolate(difTime, pos);
|
|
mAnim.setPos(pos);
|
|
}
|
|
|
|
// If the animation has no track of rotation.
|
|
UTrack* trackRot = animation.getTrackByName("PathRotQuat");
|
|
if(!trackRot)
|
|
trackRot = animation.getTrackByName(string(iName + "." + "PathRotQuat").c_str());
|
|
if(trackRot)
|
|
{
|
|
CQuat rot;
|
|
trackPos->interpolate(difTime, rot);
|
|
mAnim.setRot(rot);
|
|
}
|
|
|
|
CMatrix mFinal = mChar * m90 * mAnim;
|
|
instance->setPos(mFinal.getPos());
|
|
instance->setRotQuat(mFinal.getRot());
|
|
}
|
|
}// updateParticlesActor //
|
|
|
|
|
|
//-----------------------------------------------
|
|
// loadScene :
|
|
// Load a scene from a file and put it in memory.
|
|
// \param filename : filename for the file that contains the scene.
|
|
// \warning This function clear the old scene.
|
|
//-----------------------------------------------
|
|
void CSceneParser::loadScene(const string &filename)
|
|
{
|
|
// Look for the file -> nlwarning and return if sceneFile is empty.
|
|
string sceneFile = CPath::lookup(filename, false);
|
|
if(sceneFile.empty())
|
|
{
|
|
nlwarning("CSceneParser::loadScene : Can't find file \"%s\".", filename.c_str());
|
|
return;
|
|
}
|
|
|
|
// Open the file.
|
|
ifstream file(sceneFile.c_str(), ios::in);
|
|
if(file.is_open())
|
|
{
|
|
// ...
|
|
char tmpBuff[MAX_LINE_SIZE];
|
|
|
|
// While the end of the file is not reached -> parse the script.
|
|
while(!file.eof())
|
|
{
|
|
// Get next valid line.
|
|
getNextValidLine(file, tmpBuff);
|
|
|
|
pair<sint, double> seq;
|
|
// ...
|
|
char *ptr = strtok(tmpBuff, delimiter);
|
|
if(ptr != NULL)
|
|
{
|
|
seq.first = atoi(ptr);
|
|
ptr = strtok(NULL, delimiter);
|
|
if(ptr != NULL)
|
|
{
|
|
NLMISC::fromString(ptr, seq.second);
|
|
_Scene.push_back(seq);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Close the File.
|
|
file.close();
|
|
}
|
|
else
|
|
{
|
|
nlwarning("CSceneParser::loadScene : File \"%s\" can't be open.", sceneFile.c_str());
|
|
return;
|
|
}
|
|
}// loadScene //
|
|
|
|
//-----------------------------------------------
|
|
// playScene :
|
|
// Play a scene in memory.
|
|
// \param timeInSec : current time in second.
|
|
//-----------------------------------------------
|
|
void CSceneParser::playScene(double timeInSec)
|
|
{
|
|
// Initialize the Iterator for the scene.
|
|
_ItScene = _Scene.begin();
|
|
// Initialize the time for the scene.
|
|
_SceneStart = timeInSec;
|
|
|
|
// Initialize or Reset the scene.
|
|
apply();
|
|
|
|
// Play the first sequence to play for this scene.
|
|
updateScene(timeInSec);
|
|
}// playScene //
|
|
|
|
//-----------------------------------------------
|
|
// updateScene :
|
|
// Update the scene currently playing.
|
|
// \param timeInSec : current time in second.
|
|
//-----------------------------------------------
|
|
void CSceneParser::updateScene(double timeInSec)
|
|
{
|
|
// If there are still sequences in the scene.
|
|
if(_ItScene != _Scene.end())
|
|
{
|
|
double time = timeInSec-_SceneStart;
|
|
if((*_ItScene).second <= time)
|
|
{
|
|
// If the scene is finish -> Stop it.
|
|
if((*_ItScene).first < 0)
|
|
{
|
|
stopScene();
|
|
}
|
|
else
|
|
{
|
|
// Play the sequence.
|
|
playSeq((*_ItScene).first, timeInSec);
|
|
|
|
// Next sequence.
|
|
_ItScene++;
|
|
}
|
|
}
|
|
}
|
|
}// updateScene //
|
|
|
|
//-----------------------------------------------
|
|
// stopScene :
|
|
// Stop the scene currently playing.
|
|
//-----------------------------------------------
|
|
void CSceneParser::stopScene()
|
|
{
|
|
_ItScene = _Scene.end();
|
|
_SceneStart = -1.f;
|
|
}// stopScene //
|
|
|
|
//-----------------------------------------------
|
|
// Function to know if there is a scene currently playing.
|
|
// \return bool : 'true' if there is a scene currently playing.
|
|
//-----------------------------------------------
|
|
bool CSceneParser::isScenePlaying()
|
|
{
|
|
return (_ItScene != _Scene.end());
|
|
}// isScenePlaying //
|