1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "nel/misc/path.h"
27 #include "nel/misc/debug.h"
28 #include "nel/misc/matrix.h"
30 #include "nel/3d/u_driver.h"
31 #include "nel/3d/u_scene.h"
32 #include "nel/3d/u_play_list.h"
33 #include "nel/3d/u_track.h"
34 #include "nel/3d/u_camera.h"
36 #include "scene_parser.h"
38 #include "entity_cl.h"
39 #include "animated_scene_object.h"
40 #include "ig_client.h"
41 #include "user_controls.h"
42 #include "time_client.h"
44 #include "game_share/entity.h"
50 using namespace NLMISC
;
58 extern UDriver
*Driver
;
60 extern UScene
*SceneRoot
;
66 const uint
CSceneParser::MAX_LINE_SIZE
= 500;
67 const char *CSceneParser::delimiter
= " \t";
69 //-----------------------------------------------
72 //-----------------------------------------------
73 CSceneParser::CSceneParser()
83 _ItScene
= _Scene
.end();
88 //-----------------------------------------------
90 // Load the file with the scene.
91 //-----------------------------------------------
92 void CSceneParser::load(const string
&filename
)
94 // Look for the file -> nlwarning and return if sceneFile is empty.
95 string sceneFile
= CPath::lookup(filename
, false);
98 nlwarning("CSceneParser::load : Can't find file \"%s\".", filename
.c_str());
103 ifstream
file(sceneFile
.c_str(), ios::in
);
106 // Load the capture speed.
107 ifstream
speedFile("capture_speed.txt", ios::in
);
108 if(speedFile
.is_open())
110 char tmpBuff
[MAX_LINE_SIZE
];
112 // Set the default fram rate (30fps).
118 // While the end of the file is not reached -> parse the script.
119 while(!speedFile
.eof())
121 // Get next valid line.
122 getNextValidLine(speedFile
, tmpBuff
);
124 char *ptr
= strtok(tmpBuff
, delimiter
);
126 NLMISC::fromString(ptr
, _FrameRate
);
129 // Close the speed file.
133 nlwarning("CSceneParser::load : 'capture_speed.txt' can't be open, default frame rate is %f.", _FrameRate
);
141 // Initialize Actors Position and rotation .
149 nlwarning("CSceneParser::load : File \"%s\" can't be open.", sceneFile
.c_str());
155 //-----------------------------------------------
158 //-----------------------------------------------
159 void CSceneParser::parse(ifstream
&file
)
161 char tmpBuff
[MAX_LINE_SIZE
];
163 // While the end of the file is not reached -> parse the script.
166 // Get next valid line.
167 getNextValidLine(file
, tmpBuff
);
169 char *ptr
= strtok(tmpBuff
, delimiter
);
173 if(strcmp(ptr
, "Time:") == 0)
176 // Filename of the File with all IG to load for the scene.
177 else if(strcmp(ptr
, "IG:") == 0)
178 parseIG(file
, tmpBuff
);
181 else if(strcmp(ptr
, "IG_Init:") == 0)
185 else if(strcmp(ptr
, "Particle:") == 0)
186 parseParticle(file
, tmpBuff
);
189 else if(strcmp(ptr
, "Actor:") == 0)
190 parseActor(file
, tmpBuff
);
193 else if(strcmp(ptr
, "Camera:") == 0)
194 parseCamAnims(file
, tmpBuff
);
197 else if(strcmp(ptr
, "Sequence:") == 0)
198 parseSequence(file
, tmpBuff
);
202 nlwarning("Unknown keyword '%s' at line %d.", ptr
, _Line
);
208 //-----------------------------------------------
209 // getNextValidLine :
210 // Skip empty lines and comment lines.
211 //-----------------------------------------------
212 void CSceneParser::getNextValidLine(ifstream
&file
, char *buff
)
217 file
.getline(buff
, MAX_LINE_SIZE
);
219 // Increase line nnumber.
225 // First char is not the beginning of a comment.
228 // Second char is not the end of a coment.
229 else if(buff
[1] != '/')
233 }// getNextValidLine //
236 //-----------------------------------------------
239 //-----------------------------------------------
240 void CSceneParser::parseTime()
242 char *ptr
= strtok(NULL
, delimiter
);
252 //-----------------------------------------------
254 // Parse the list of IG to load for the scene
255 //-----------------------------------------------
256 void CSceneParser::parseIG(ifstream
&file
, char *buff
)
260 // Get next valid line.
261 getNextValidLine(file
, buff
);
263 char *ptr
= strtok(buff
, delimiter
);
266 // End of the actor definition.
267 if(strcmp(ptr
, "End_IG") == 0)
276 //-----------------------------------------------
278 // Get the name of the IG to initialize entities.
279 //-----------------------------------------------
280 void CSceneParser::parseIGInit()
282 char *ptr
= strtok(NULL
, delimiter
);
290 //-----------------------------------------------
293 //-----------------------------------------------
294 void CSceneParser::parseParticle(ifstream
&file
, char *buff
)
296 // Reset the current particle.
297 _CurrentParticle
.reset();
301 // Get next valid line.
302 getNextValidLine(file
, buff
);
304 char *ptr
= strtok(buff
, delimiter
);
307 // End of the actor definition.
308 if(strcmp(ptr
, "End_Particle") == 0)
312 else if(strcmp(ptr
, "Id:") == 0)
316 else if(strcmp(ptr
, "IG:") == 0)
319 // Particle's Cluster
320 else if(strcmp(ptr
, "Cluster:") == 0)
321 parseParticleCluster();
323 // Actor father of the particle is there is one.
324 else if(strcmp(ptr
, "Actor:") == 0)
325 parseParticleActor();
328 else if(strcmp(ptr
, "Anims:") == 0)
329 parseParticleAnims(file
, buff
);
333 nlwarning("Unknown keyword '%s' at line %d.", ptr
, _Line
);
337 // If the current particle Id is Valid -> create the particle.
338 if(_CurrentParticle
.Id
>= 0)
340 map
<uint
, CParticle
>::iterator it
= _Particles
.find((uint
)_CurrentParticle
.Id
);
341 // Id already exists.
342 if(it
!= _Particles
.end())
343 nlwarning("Particle before line %d has the ID %d that already exists -> Particle Not Created.", _Line
, _CurrentParticle
.Id
);
344 // Insert the new Particle.
346 _Particles
.insert(make_pair((uint
)_CurrentParticle
.Id
, _CurrentParticle
));
349 nlwarning("Particle before line %d has no ID or a Bad one -> Particle Not Created.", _Line
);
352 //-----------------------------------------------
354 // Parse Particle's Id.
355 //-----------------------------------------------
356 void CSceneParser::parseParticleId()
358 char *ptr
= strtok(NULL
, delimiter
);
360 _CurrentParticle
.Id
= atoi(ptr
);
361 }// parseParticleId //
363 //-----------------------------------------------
365 // Parse Particle's IG.
366 //-----------------------------------------------
367 void CSceneParser::parseParticleIG()
369 char *ptr
= strtok(NULL
, delimiter
);
371 _CurrentParticle
.IG
= ptr
;
372 }// parseParticleIG //
374 //-----------------------------------------------
375 // parseParticleCluster :
376 // Parse Particle's Cluster.
377 //-----------------------------------------------
378 void CSceneParser::parseParticleCluster()
380 char *ptr
= strtok(NULL
, delimiter
);
382 _CurrentParticle
.Cluster
= ptr
;
383 }// parseParticleCluster //
385 //-----------------------------------------------
386 // parseParticleActor :
387 // Parse Particle's Actor.
388 //-----------------------------------------------
389 void CSceneParser::parseParticleActor()
391 char *ptr
= strtok(NULL
, delimiter
);
393 _CurrentParticle
.Actor
= atoi(ptr
);
394 }// parseParticleActor //
396 //-----------------------------------------------
397 // parseParticleAnims :
398 // Parse Particle's anims.
399 //-----------------------------------------------
400 void CSceneParser::parseParticleAnims(ifstream
&file
, char *buff
)
404 // Get next valid line.
405 getNextValidLine(file
, buff
);
407 char *ptr
= strtok(buff
, delimiter
);
410 // End of the actor definition.
411 if(strcmp(ptr
, "End_Anims") == 0)
415 _CurrentParticle
.Anims
.push_back(ptr
);
418 }// parseParticleAnims //
423 //-----------------------------------------------
426 //-----------------------------------------------
427 void CSceneParser::parseActor(ifstream
&file
, char *buff
)
429 // Reset the current actor.
430 _CurrentActor
.reset();
434 // Get next valid line.
435 getNextValidLine(file
, buff
);
437 char *ptr
= strtok(buff
, delimiter
);
440 // End of the actor definition.
441 if(strcmp(ptr
, "End_Actor") == 0)
445 else if(strcmp(ptr
, "Id:") == 0)
449 else if(strcmp(ptr
, "Name:") == 0)
452 // Is the Actor a flyer.
453 else if(strcmp(ptr
, "Fly:") == 0)
456 // Actor father of the particle is there is one.
457 else if(strcmp(ptr
, "Actor:") == 0)
461 else if(strcmp(ptr
, "Skel:") == 0)
465 else if(strcmp(ptr
, "Meshes:") == 0)
466 parseMeshes(file
, buff
);
469 else if(strcmp(ptr
, "Anims:") == 0)
470 parseAnims(file
, buff
);
474 nlwarning("Unknown keyword '%s' at line %d.", ptr
, _Line
);
478 // If the current actor Id is Valid -> create the actor.
479 if(_CurrentActor
.Id
>= 0)
481 map
<uint
, CActor
>::iterator it
= _Actors
.find((uint
)_CurrentActor
.Id
);
482 // Id already exists.
483 if(it
!= _Actors
.end())
484 nlwarning("Actor before line %d has the ID %d that already exists -> Actor Not Created.", _Line
, _CurrentActor
.Id
);
485 // Insert the new actor.
487 _Actors
.insert(make_pair((uint
)_CurrentActor
.Id
, _CurrentActor
));
490 nlwarning("Actor before line %d has no ID or a Bad one -> Actor Not Created.", _Line
);
493 //-----------------------------------------------
495 // Parse the current actor Id.
496 //-----------------------------------------------
497 void CSceneParser::parseId()
499 char *ptr
= strtok(NULL
, delimiter
);
501 _CurrentActor
.Id
= atoi(ptr
);
504 //-----------------------------------------------
506 // Parse the current actor Name.
507 //-----------------------------------------------
508 void CSceneParser::parseName()
510 char *ptr
= strtok(NULL
, delimiter
);
512 _CurrentActor
.Name
= ptr
;
515 //-----------------------------------------------
517 // Is the Actor a flyer.
518 //-----------------------------------------------
519 void CSceneParser::parseFly()
521 char *ptr
= strtok(NULL
, delimiter
);
525 _CurrentActor
.Fly
= true;
527 _CurrentActor
.Fly
= false;
531 //-----------------------------------------------
533 // Parse Actor's Actor.
534 //-----------------------------------------------
535 void CSceneParser::parseActorActor()
537 char *ptr
= strtok(NULL
, delimiter
);
540 _CurrentActor
.Actor
= atoi(ptr
);
541 nlwarning("Actor: %d Follow : %d", _CurrentActor
.Id
, _CurrentActor
.Actor
);
543 }// parseActorActor //
545 //-----------------------------------------------
547 // Parse the current actor Skeleton Name.
548 //-----------------------------------------------
549 void CSceneParser::parseSkel()
551 char *ptr
= strtok(NULL
, delimiter
);
553 _CurrentActor
.Skeleton
= ptr
;
556 //-----------------------------------------------
558 // Parse meshes used for the current actor.
559 //-----------------------------------------------
560 void CSceneParser::parseMeshes(ifstream
&file
, char *buff
)
564 // Get next valid line.
565 getNextValidLine(file
, buff
);
567 char *ptr
= strtok(buff
, delimiter
);
570 // End of the actor definition.
571 if(strcmp(ptr
, "End_Meshes") == 0)
575 _CurrentActor
.Meshes
.push_back(ptr
);
580 //-----------------------------------------------
582 // Parse anims used for the current actor.
583 //-----------------------------------------------
584 void CSceneParser::parseAnims(ifstream
&file
, char *buff
)
588 // Get next valid line.
589 getNextValidLine(file
, buff
);
591 char *ptr
= strtok(buff
, delimiter
);
594 // End of the actor definition.
595 if(strcmp(ptr
, "End_Anims") == 0)
599 _CurrentActor
.Anims
.push_back(ptr
);
607 //-----------------------------------------------
609 // Parse all anims used for the camera in all sequence.
610 //-----------------------------------------------
611 void CSceneParser::parseCamAnims(ifstream
&file
, char *buff
)
615 // Get next valid line.
616 getNextValidLine(file
, buff
);
618 char *ptr
= strtok(buff
, delimiter
);
621 // End of Anims for the camera.
622 if(strcmp(ptr
, "End_Camera") == 0)
626 _CamAnims
.push_back(ptr
);
634 //-----------------------------------------------
637 //-----------------------------------------------
638 void CSceneParser::parseSequence(ifstream
&file
, char *buff
)
640 // Reset the current sequence.
641 _CurrentSequence
.reset();
645 // Get next valid line.
646 getNextValidLine(file
, buff
);
648 char *ptr
= strtok(buff
, delimiter
);
651 // End of the actor definition.
652 if(strcmp(ptr
, "End_Sequence") == 0)
656 else if(strcmp(ptr
, "Id:") == 0)
659 // Particle for the sequence.
660 else if(strcmp(ptr
, "Particle:") == 0)
661 parseSeqParticle(file
, buff
);
663 // Actor for the sequence.
664 else if(strcmp(ptr
, "Actor:") == 0)
665 parseSeqActor(file
, buff
);
667 // Camera for the sequence.
668 else if(strcmp(ptr
, "Camera:") == 0)
669 parseSeqCam(file
, buff
);
673 nlwarning("Unknown keyword '%s' at line %d.", ptr
, _Line
);
677 // If the sequence Id is Valid -> create the sequence.
678 if(_CurrentSequence
.Id
>= 0)
680 map
<uint
, CSequence
>::iterator itSeq
= _Sequences
.find((uint
)_CurrentSequence
.Id
);
681 // Id already exists.
682 if(itSeq
!= _Sequences
.end())
683 nlwarning("Sequence before line %d has the ID %d that already exists -> Sequence Not Created.", _Line
, _CurrentSequence
.Id
);
684 // Insert the new actor.
686 _Sequences
.insert(make_pair((uint
)_CurrentSequence
.Id
, _CurrentSequence
));
689 nlwarning("Sequence before line %d has no ID or a Bad one -> Sequence Not Created.", _Line
);
692 //-----------------------------------------------
694 // Parse the current sequence Id.
695 //-----------------------------------------------
696 void CSceneParser::parseSeqId()
698 char *ptr
= strtok(NULL
, delimiter
);
700 _CurrentSequence
.Id
= atoi(ptr
);
703 //-----------------------------------------------
704 // parseSeqParticle :
705 // Parse particle in the sequence.
706 //-----------------------------------------------
707 void CSceneParser::parseSeqParticle(ifstream
&file
, char *buff
)
709 // Reset the current particle in the sequence.
710 _CurParticleSeq
.reset();
714 // Get next valid line.
715 getNextValidLine(file
, buff
);
717 char *ptr
= strtok(buff
, delimiter
);
720 // End of the actor definition.
721 if(strcmp(ptr
, "End_Particle") == 0)
724 // Actor in Sequence Id.
725 else if(strcmp(ptr
, "Id:") == 0)
726 parseSeqParticleId();
728 // Actor in Sequence anims.
729 else if(strcmp(ptr
, "Anims:") == 0)
730 parseSeqParticleAnims(file
, buff
);
734 nlwarning("Unknown keyword '%s' at line %d.", ptr
, _Line
);
738 // If the particle's Id in the sequence is Valid -> create the particleSeq.
739 if(_CurParticleSeq
.Id
>= 0)
741 map
<uint
, CParticleSeq
>::iterator itPartSeq
= _CurrentSequence
.ParticlesSeq
.find((uint
)_CurParticleSeq
.Id
);
742 // Id already exists.
743 if(itPartSeq
!= _CurrentSequence
.ParticlesSeq
.end())
744 nlwarning("Particle in Sequence before line %d has the ID %d that already exists -> Particle in the sequence Not Created.", _Line
, _CurParticleSeq
.Id
);
745 // Insert the new particle in the sequence.
747 _CurrentSequence
.ParticlesSeq
.insert(make_pair((uint
)_CurParticleSeq
.Id
, _CurParticleSeq
));
750 nlwarning("Particle in Sequence before line %d has no ID or a Bad one -> Particle in the sequence Not Created.", _Line
);
751 }// parseSeqParticle //
753 //-----------------------------------------------
754 // parseSeqParticleId :
755 // Parse the current particle's Id in the current sequence.
756 //-----------------------------------------------
757 void CSceneParser::parseSeqParticleId()
759 char *ptr
= strtok(NULL
, delimiter
);
761 _CurParticleSeq
.Id
= atoi(ptr
);
762 }// parseSeqParticleId //
764 //-----------------------------------------------
765 // parseSeqParticleAnims :
766 // Parse anims used for the current particle in the current sequence.
767 //-----------------------------------------------
768 void CSceneParser::parseSeqParticleAnims(ifstream
&file
, char *buff
)
772 // Get next valid line.
773 getNextValidLine(file
, buff
);
775 char *ptr
= strtok(buff
, delimiter
);
778 // End of the actor definition.
779 if(strcmp(ptr
, "End_Anims") == 0)
783 _CurParticleSeq
.Anims
.push_back(ptr
);
786 }// parseSeqParticleAnims //
788 //-----------------------------------------------
790 // Parse an actor in a sequence.
791 //-----------------------------------------------
792 void CSceneParser::parseSeqActor(ifstream
&file
, char *buff
)
794 // Reset the current sequence.
795 _CurrentActorSeq
.reset();
799 // Get next valid line.
800 getNextValidLine(file
, buff
);
802 char *ptr
= strtok(buff
, delimiter
);
805 // End of the actor definition.
806 if(strcmp(ptr
, "End_Actor") == 0)
809 // Actor in Sequence Id.
810 else if(strcmp(ptr
, "Id:") == 0)
813 // Actor in Sequence anims.
814 else if(strcmp(ptr
, "Anims:") == 0)
815 parseSeqActorAnims(file
, buff
);
819 nlwarning("Unknown keyword '%s' at line %d.", ptr
, _Line
);
823 // If the actor's Id in the sequence is Valid -> create the actorSeq.
824 if(_CurrentActorSeq
.Id
>= 0)
826 map
<uint
, CActorSeq
>::iterator itActSeq
= _CurrentSequence
.ActorsSeq
.find((uint
)_CurrentActorSeq
.Id
);
827 // Id already exists.
828 if(itActSeq
!= _CurrentSequence
.ActorsSeq
.end())
829 nlwarning("Actor in Sequence before line %d has the ID %d that already exists -> Actor in the sequence Not Created.", _Line
, _CurrentActorSeq
.Id
);
830 // Insert the new actor.
832 _CurrentSequence
.ActorsSeq
.insert(make_pair((uint
)_CurrentActorSeq
.Id
, _CurrentActorSeq
));
835 nlwarning("Actor in Sequence before line %d has no ID or a Bad one -> Actor in the sequence Not Created.", _Line
);
838 //-----------------------------------------------
840 // Parse the current actor's Id in the current sequence.
841 //-----------------------------------------------
842 void CSceneParser::parseSeqActorId()
844 char *ptr
= strtok(NULL
, delimiter
);
846 _CurrentActorSeq
.Id
= atoi(ptr
);
847 }// parseSeqActorId //
849 //-----------------------------------------------
850 // parseSeqActorAnims :
851 // Parse anims used for the current actor in the current sequence.
852 //-----------------------------------------------
853 void CSceneParser::parseSeqActorAnims(ifstream
&file
, char *buff
)
857 // Get next valid line.
858 getNextValidLine(file
, buff
);
860 char *ptr
= strtok(buff
, delimiter
);
863 // End of the actor definition.
864 if(strcmp(ptr
, "End_Anims") == 0)
868 _CurrentActorSeq
.Anims
.push_back(ptr
);
871 }// parseSeqActorAnims //
873 //-----------------------------------------------
875 // Parse camera in the sequence.
876 //-----------------------------------------------
877 void CSceneParser::parseSeqCam(ifstream
&file
, char *buff
)
881 // Get next valid line.
882 getNextValidLine(file
, buff
);
884 char *ptr
= strtok(buff
, delimiter
);
887 // End of the actor definition.
888 if(strcmp(ptr
, "End_Camera") == 0)
892 _CurrentSequence
.CamAnims
.push_back(ptr
);
900 //-----------------------------------------------
902 // Initialize Actors Position and rotation .
903 //-----------------------------------------------
904 void CSceneParser::initActors()
909 // Create the instance group with all start positions and rotations.
910 UInstanceGroup
*IGInit
= UInstanceGroup::createInstanceGroup(_IG_Init
);
913 int nbInst
= IGInit
->getNumInstance();
914 map
<uint
, CActor
>::iterator itActor
;
915 for(int i
= 0; i
< nbInst
; ++i
)
917 sint id
= atoi(IGInit
->getInstanceName(i
).c_str());
918 itActor
= _Actors
.find(id
);
919 if(itActor
!= _Actors
.end())
921 CActor
&actor
= (*itActor
).second
;
922 actor
.Pos
= IGInit
->getInstancePos(i
);
923 actor
.Rot
= IGInit
->getInstanceRot(i
);
926 nlwarning("CSceneParser::initActors : Actor %d is in the IG \"%s\" but is not in the script.", id
, _IG_Init
.c_str());
929 // Destroy the IG to initialize (all is already backup now).
934 nlwarning("CSceneParser::initActors : Can't create the Instance group to initialize actors.");
940 //-----------------------------------------------
942 // Initialize the scene with the parameters loaded from the script.
943 //-----------------------------------------------
944 void CSceneParser::apply()
946 // If the scene is already initialized -> reset the scene.
953 // Create a play list manager for the scene.
954 _PlayListManager
= Scene
->createPlayListManager();
956 // Initialize the Camera and reset it the second time.
959 // Initialize IG for the scenery (IG present from start to end like trees or torch.
962 // Initialize Particles.
965 // Initialize Actors.
968 // Scene already aplly now.
972 //-----------------------------------------------
975 //-----------------------------------------------
976 void CSceneParser::reset()
978 // Camera in scene mode.
979 UserControls
.mode(CUserControls::InterfaceMode
);
981 // Reset all particles.
988 //-----------------------------------------------
990 // Reset all particles.
991 //-----------------------------------------------
992 void CSceneParser::resetParticles()
994 map
<uint
, CParticle
>::iterator itPart
= _Particles
.begin();
995 for(itPart
= _Particles
.begin(); itPart
!= _Particles
.end(); ++itPart
)
997 // Get a reference on the particule.
998 CParticle
&particle
= (*itPart
).second
;
1000 // Check if the IG of particles is not already in the scene.
1001 if(particle
.IGPtr
&& _IGInScene
.find(particle
.IGPtr
) != _IGInScene
.end())
1003 // Reset the playlist.
1004 particle
.PlayList
->resetAllChannels();
1006 // Remove from the set with all particle in the scene.
1007 _IGInScene
.erase(particle
.IGPtr
);
1008 // Remove particles from scene.
1009 particle
.IGPtr
->removeFromScene(*Scene
);
1010 Scene
->deleteInstanceGroup (particle
.IGPtr
);
1012 // Load the IG of the particle.
1017 particle
.IGPtr
= UInstanceGroup::createInstanceGroup((*itPart
).second
.IG
);
1019 catch(Exception
&e
){nlwarning("CSceneParser::resetParticles : %s", e
.what());}
1022 }// resetParticles //
1024 //-----------------------------------------------
1026 // Reset all actors.
1027 //-----------------------------------------------
1028 void CSceneParser::resetActors()
1030 // Create new entities from actors
1031 map
<uint
, CActor
>::iterator itActor
;
1032 for(itActor
= _Actors
.begin(); itActor
!= _Actors
.end(); ++itActor
)
1034 // Get a reference on the actor.
1035 CActor
&actor
= (*itActor
).second
;
1038 Sid
entityId(Sid::npc
, (uint64
)actor
.Id
);
1041 CEntityCL
*entity
= getEntity(entityId
);
1044 // Position the entity.
1045 entity
->pacsPos(actor
.Pos
);
1047 // Position the skeleton at the same position as the entity.
1048 if(entity
->skeleton())
1050 entity
->skeleton()->setPos(actor
.Pos
);
1051 entity
->skeleton()->setRotQuat(actor
.Rot
);
1055 // Reset entity animations.
1056 resetAnimatedSceneObject(entityId
);
1061 //-----------------------------------------------
1063 // Initialize the scene with the parameters loaded from the script for particles.
1064 //-----------------------------------------------
1065 void CSceneParser::applyParticles()
1067 map
<uint
, CParticle
>::iterator itPart
= _Particles
.begin();
1068 for(itPart
= _Particles
.begin(); itPart
!= _Particles
.end(); ++itPart
)
1070 // Get a reference on the particule.
1071 CParticle
&particle
= (*itPart
).second
;
1073 // Create the animation set for the particule.
1074 particle
.AnimationSet
= Driver
->createAnimationSet();
1076 // Add animations to the animation set.
1077 list
<string
>::iterator itPartAnim
;
1078 for(itPartAnim
= particle
.Anims
.begin(); itPartAnim
!= particle
.Anims
.end(); ++itPartAnim
)
1080 uint idAnim
= UAnimationSet::NotFound
;
1083 idAnim
= particle
.AnimationSet
->addAnimation((*itPartAnim
+ string(".anim")).c_str(), (*itPartAnim
).c_str());
1085 catch(Exception
&e
) {nlwarning("%s", e
.what());}
1087 if(idAnim
!= UAnimationSet::NotFound
)
1089 particle
.AnimToId
.insert(make_pair((*itPartAnim
).c_str(), idAnim
));
1092 nlwarning("CSceneParser::applyParticles : Anim %s cannot be add in the animation set", (*itPartAnim
).c_str());
1095 // Build animation set
1096 particle
.AnimationSet
->build();
1099 particle
.PlayList
= _PlayListManager
->createPlayList(particle
.AnimationSet
);
1100 if(particle
.PlayList
)
1102 // Load the IG of the particle.
1106 particle
.IGPtr
= UInstanceGroup::createInstanceGroup((*itPart
).second
.IG
);
1108 catch(Exception
&e
) {nlwarning("%s", e
.what());}
1112 // Get the position of Instances in IG.
1113 for(uint i
= 0; i
< particle
.IGPtr
->getNumInstance(); ++i
)
1114 particle
.IGPos
.push_back(particle
.IGPtr
->getInstancePos(i
));
1118 }// applyParticles //
1120 //-----------------------------------------------
1122 // Initialize the Camera and reset it the second time.
1123 //-----------------------------------------------
1124 void CSceneParser::applyCamera()
1126 // Create the animation set for the camera if not already done.
1127 _AnimationSet
= Driver
->createAnimationSet();
1130 list
<string
>::iterator itCamAnims
;
1131 for(itCamAnims
= _CamAnims
.begin(); itCamAnims
!= _CamAnims
.end(); ++itCamAnims
)
1133 uint idAnim
= UAnimationSet::NotFound
;
1136 idAnim
= _AnimationSet
->addAnimation((*itCamAnims
+ string(".anim")).c_str(), (*itCamAnims
).c_str());
1138 catch(Exception
&e
) {nlwarning("%s", e
.what());}
1140 if(idAnim
!= UAnimationSet::NotFound
)
1141 _AnimCamToId
.insert(make_pair((*itCamAnims
).c_str(), idAnim
));
1143 nlwarning("CSceneParser::apply : Camera Anim %s cannot be add in the animation set", (*itCamAnims
).c_str());
1146 // Build animation set
1147 _AnimationSet
->build();
1150 _PlayList
= _PlayListManager
->createPlayList( _AnimationSet
);
1153 nlwarning("CSceneParser::apply : AnimationSet cannot be created.");
1156 //-----------------------------------------------
1158 // Initialize IG for the scenery (IG present from start to end like trees or torch.
1159 //-----------------------------------------------
1160 void CSceneParser::applyIG()
1162 // Load Instances Groups for the scene.
1163 for(list
<string
>::iterator itIG
= _IG
.begin(); itIG
!= _IG
.end(); ++itIG
)
1165 UInstanceGroup
*IGTemp
= 0;
1168 IGTemp
= UInstanceGroup::createInstanceGroup(*itIG
);
1170 catch(Exception
&e
) {nlwarning("CSceneParser::applyIG : %s", e
.what());}
1172 // Add Instance Group in the scene.
1174 IGTemp
->addToScene(*Scene
, Driver
);
1178 //-----------------------------------------------
1180 // Initialize actors.
1181 //-----------------------------------------------
1182 void CSceneParser::applyActors()
1184 // Create new entities from actors
1185 map
<uint
, CActor
>::iterator itActor
;
1186 for(itActor
= _Actors
.begin(); itActor
!= _Actors
.end(); ++itActor
)
1188 // Get a reference on the actor.
1189 CActor
&actor
= (*itActor
).second
;
1191 // Create the entity Sid.
1192 Sid
entityId(Sid::npc
, (uint64
)actor
.Id
);
1194 // Create the entity type.
1195 CTypeEntity typeEntity
;
1196 typeEntity
.TypeInfo
.TypeEntity
= CTypeEntity::npc
;
1197 typeEntity
.TypeInfo
.Kind
= CTypeEntity::zorai
;
1198 typeEntity
.TypeInfo
.Age
= CTypeEntity::adult
;
1199 typeEntity
.TypeInfo
.Sex
= CTypeEntity::male
;
1201 // Create the entity.
1202 CEntityCL
*entityTmp
= createEntity(entityId
, typeEntity
);
1205 // Get a reference on the entity.
1206 CEntityCL
&entity
= *entityTmp
;
1208 // True if the entity fly.
1209 entity
.flyer(actor
.Fly
);
1211 // Set the name of the entity
1212 entity
.name(actor
.Name
);
1213 // Time for the current frame.
1215 // Set the entity position.
1216 entity
.pacsPos(actor
.Pos
);
1220 m
.setRot(actor
.Rot
);
1221 entity
.front((m
* CVector::J
).normed());
1222 // Set the direction like the front.
1223 entity
.dir(entity
.front());
1224 // Set the vector UP.
1225 entity
.up(CVector(0.f
,0.f
,1.f
));
1227 // Assign a skeleton.
1228 entity
.skeleton(actor
.Skeleton
);
1230 // Position the entity.
1231 entity
.pacsPos(actor
.Pos
);
1233 // Position the skeleton at the same position as the entity.
1234 if(entity
.skeleton())
1236 entity
.skeleton()->setPos(actor
.Pos
);
1237 entity
.skeleton()->setRotQuat(actor
.Rot
);
1240 // Assign meshes used for the entity.
1242 list
<string
>::iterator itMeshes
;
1243 for(itMeshes
= actor
.Meshes
.begin(); itMeshes
!= actor
.Meshes
.end(); ++itMeshes
)
1245 // If there are too many meshes.
1246 if(count
>= (uint
)CEntityCL::NB_SLOT
)
1248 nlwarning("CSceneParser::applyActors : Too many meshes for Actor %d.", actor
.Id
);
1252 entity
.slot((CEntityCL::ESlots
)count
, *itMeshes
);
1256 // Create the playlist
1257 addEntityClAnimatedSceneObject(entityId
, actor
.Anims
);
1260 nlwarning("CSceneParser::applyActors : Entity %d Not created", actor
.Id
);
1265 //-----------------------------------------------
1267 // Play the sequence with the ID 'seq'.
1268 //-----------------------------------------------
1269 void CSceneParser::playSeq(uint seq
, double timeInSec
)
1271 // If the scene is not initialized -> return.
1275 // Camera in scene mode.
1276 UserControls
.mode(CUserControls::SceneMode
);
1278 _TimeStart
= timeInSec
;
1280 map
<uint
, CSequence
>::iterator itSeq
= _Sequences
.find(seq
);
1281 if(itSeq
!= _Sequences
.end())
1283 // Get a reference on the sequence.
1284 CSequence
&sequence
= (*itSeq
).second
;
1286 // Log the time used for the sequence.
1287 nlwarning("Sequence: %d, Time: %f", seq
, timeInSec
);
1289 // Camera in the sequence.
1290 if(!sequence
.CamAnims
.empty())
1294 map
<string
, uint
>::iterator itAnimCamId
;
1295 for(itAnimCamId
= _AnimCamToId
.begin(); itAnimCamId
!= _AnimCamToId
.end(); ++itAnimCamId
)
1297 _PlayList
->setTimeOrigin(0, timeInSec
);
1298 _PlayList
->setAnimation(0, (*itAnimCamId
).second
);
1303 // Particles in the sequence.
1304 map
<uint
, CParticleSeq
>::iterator itPartSeq
;
1305 for(itPartSeq
= sequence
.ParticlesSeq
.begin(); itPartSeq
!= sequence
.ParticlesSeq
.end(); ++itPartSeq
)
1307 CParticleSeq
&particleSeq
= (*itPartSeq
).second
;
1308 map
<uint
, CParticle
>::iterator itPart
= _Particles
.find(particleSeq
.Id
);
1309 if(itPart
!= _Particles
.end())
1311 // Get a reference on the particle.
1312 CParticle
&particle
= (*itPart
).second
;
1313 // Check if the IG has been created.
1316 // Check if the IG of particles is not already in the scene.
1317 if(_IGInScene
.find(particle
.IGPtr
) == _IGInScene
.end())
1319 // Insert IG in the set of IG in the scene.
1320 _IGInScene
.insert(particle
.IGPtr
);
1322 if(IGCity
.find(particle
.Cluster
) == IGCity
.end())
1323 Scene
->setToGlobalInstanceGroup(particle
.IGPtr
);
1325 particle
.IGPtr
->setClusterSystem(IGCity
[particle
.Cluster
]);
1326 // Add particles to the scene.
1327 particle
.IGPtr
->addToScene(*Scene
, Driver
);
1329 particle
.IGPtr
->unfreezeHRC();
1331 // Register all instances in the IG to a playlist.
1332 for(uint i
= 0; i
< particle
.IGPtr
->getNumInstance(); ++i
)
1334 std::string iName
= particle
.IGPtr
->getInstanceName( i
);
1335 UInstance instance
= particle
.IGPtr
->getByName( iName
);
1336 particle
.PlayList
->registerTransform(instance
);
1337 particle
.PlayList
->registerTransform(instance
, (iName
+ ".").c_str());
1341 // Start the particle animation.
1342 map
<string
, uint
>::iterator itAnimId
;
1343 for(itAnimId
= particle
.AnimToId
.begin(); itAnimId
!= particle
.AnimToId
.end(); ++itAnimId
)
1345 particle
.PlayList
->setTimeOrigin(0, timeInSec
);
1346 particle
.PlayList
->setAnimation(0, (*itAnimId
).second
);
1352 // Actors in the sequence.
1353 map
<uint
, CActorSeq
>::iterator itActSeq
;
1354 for(itActSeq
= sequence
.ActorsSeq
.begin(); itActSeq
!= sequence
.ActorsSeq
.end(); ++itActSeq
)
1356 CActorSeq
&actorSeq
= (*itActSeq
).second
;
1357 updateAnimationSequence(Sid(Sid::npc
, (uint64
)actorSeq
.Id
), actorSeq
.Anims
, 0 );
1363 //-----------------------------------------------
1365 // Update the scene.
1366 //-----------------------------------------------
1367 void CSceneParser::update(double timeInSec
)
1369 // Nothing to update if the scene is not applied.
1373 // Update the scene currently playing.
1374 updateScene(timeInSec
);
1376 // Update particles.
1377 updateParticles(timeInSec
);
1379 // Animate the camera.
1380 updateCamera(timeInSec
);
1382 // Update particle anims.
1383 if(_PlayListManager
)
1384 _PlayListManager
->animate(timeInSec
);
1386 // Update actor position (for actor on another actor).
1390 //-----------------------------------------------
1392 // Update the camera (position, target, roll, fov)
1393 //-----------------------------------------------
1394 void CSceneParser::updateCamera(double timeInSec
)
1396 // If there is a play list for the camera.
1399 // Get the Id of the animation in the slot 0.
1400 uint idAnim
= _PlayList
->getAnimation(0);
1401 if(idAnim
!= UPlayList::empty
)
1403 UAnimation
*animation
= _AnimationSet
->getAnimation(idAnim
);
1406 // Get Camera information from the animation (Pos, Target, Roll).
1407 UTrack
* trackRollCam
= animation
->getTrackByName("Camera.roll");
1408 UTrack
* trackFovCam
= animation
->getTrackByName("Camera.fov");
1409 UTrack
* trackPosCam
= animation
->getTrackByName("Camera.PathPos");
1410 UTrack
* trackPosTarget
= animation
->getTrackByName("Camera.Target.PathPos");
1411 if(trackPosCam
&& trackPosTarget
)
1413 float rollCam
= 0.f
;
1416 float difTime
= (float)(timeInSec
-_TimeStart
);
1419 trackRollCam
->interpolate(difTime
, rollCam
);
1420 trackPosCam
->interpolate(difTime
, posCam
);
1421 trackPosTarget
->interpolate(difTime
, posTarget
);
1423 // Update camera transformations.
1424 UCamera cam
= Scene
->getCam();
1427 cam
->setTransformMode(UTransformable::RotQuat
);
1428 cam
->lookAt(posCam
, posTarget
, rollCam
);
1432 trackFovCam
->interpolate(difTime
, fov
);
1433 CFrustum fr
= cam
->getFrustum();
1434 // change only the fov
1435 cam
->setPerspective(fov
, fr
.getAspectRatio(), fr
.Near
, fr
.Far
);
1439 // Update camera transformations for the Root.
1440 cam
= SceneRoot
->getCam();
1443 cam
->setTransformMode(UTransformable::RotQuat
);
1444 cam
->lookAt(posCam
, posTarget
, rollCam
);
1448 trackFovCam
->interpolate(difTime
, fov
);
1449 CFrustum fr
= cam
->getFrustum();
1450 // change only the fov
1451 cam
->setPerspective(fov
, fr
.getAspectRatio(), fr
.Near
, fr
.Far
);
1460 //-----------------------------------------------
1463 //-----------------------------------------------
1464 void CSceneParser::updateActors()
1466 // All actors in the scene.
1467 for(map
<uint
, CActor
>::iterator itActor
= _Actors
.begin(); itActor
!= _Actors
.end(); ++itActor
)
1469 // Get a reference on the actor.
1470 CActor
&actor
= (*itActor
).second
;
1472 // If there is no actor to follow -> next actor.
1476 // Get the entity pointer.
1477 CEntityCL
*entity
= getEntity(Sid(Sid::npc
, (uint64
)actor
.Id
));
1480 nlwarning("CSceneParser::updateActors : Cannot get the actor %d.", actor
.Id
);
1484 // Get the target entity pointer.
1485 CEntityCL
*entityTarget
= getEntity(Sid(Sid::npc
, (uint64
)actor
.Actor
));
1488 nlwarning("CSceneParser::updateActors : Cannot get the targeted actor %d.", actor
.Actor
);
1492 // Changes the entity position.
1493 entity
->pacsPos(entityTarget
->pos());
1497 //-----------------------------------------------
1498 // updateParticles :
1499 // Update particles.
1500 //-----------------------------------------------
1501 void CSceneParser::updateParticles(double timeInSec
)
1503 for(map
<uint
, CParticle
>::iterator itPart
= _Particles
.begin(); itPart
!= _Particles
.end(); ++itPart
)
1505 // Get a reference on the particule.
1506 CParticle
&particle
= (*itPart
).second
;
1508 // If the IG pointer is null -> Next particle.
1509 if(!(particle
.IGPtr
))
1512 // If the play list is NULL -> Next particle
1513 if(!(particle
.PlayList
))
1516 // Get the Id of the animation in the slot 0 -> if empty -> Next particle.
1517 uint idAnim
= particle
.PlayList
->getAnimation(0);
1518 if(idAnim
== UPlayList::empty
)
1521 // Get the animation pointer.
1522 UAnimation
*animation
= particle
.AnimationSet
->getAnimation(idAnim
);
1526 // Get the time difference.
1527 float difTime
= (float)(timeInSec
-_TimeStart
);
1529 // Particle do not follow anything.
1530 if(particle
.Actor
< 0)
1532 updateParticlesNoActor(difTime
, particle
, *animation
);
1534 // Particle follow an actor.
1537 updateParticlesActor(difTime
, particle
, *animation
);
1540 }// updateParticles //
1542 //-----------------------------------------------
1543 // updateParticlesNoActor :
1545 //-----------------------------------------------
1546 void CSceneParser::updateParticlesNoActor(float difTime
, CParticle
&particle
, UAnimation
&animation
)
1548 // Animate all instances.
1549 for(uint i
= 0; i
< particle
.IGPtr
->getNumInstance(); ++i
)
1551 std::string iName
= particle
.IGPtr
->getInstanceName(i
);
1552 UInstance instance
= particle
.IGPtr
->getByName(iName
);
1557 instance
->setTransformMode(UTransformable::RotQuat
);
1559 // If the animation has no track of position.
1560 UTrack
* trackPos
= animation
.getTrackByName("PathPos");
1562 trackPos
= animation
.getTrackByName(string(iName
+ "." + "PathPos").c_str());
1566 trackPos
->interpolate(difTime
, pos
);
1567 instance
->setPos(pos
);
1570 // If the animation has no track of rotation.
1571 UTrack
* trackRot
= animation
.getTrackByName("PathRotQuat");
1573 trackRot
= animation
.getTrackByName(string(iName
+ "." + "PathRotQuat").c_str());
1577 if(trackRot
->interpolate(difTime
, rot
))
1578 instance
->setRotQuat(rot
);
1580 nlwarning("CSceneParser::updateParticles : Not a Quat!");
1583 }// updateParticlesNoActor //
1586 //-----------------------------------------------
1587 // updateParticlesActor :
1589 //-----------------------------------------------
1590 void CSceneParser::updateParticlesActor(float difTime
, CParticle
&particle
, UAnimation
&animation
)
1592 // Get the entity pointer.
1593 CEntityCL
*entity
= getEntity(Sid(Sid::npc
, (uint64
)particle
.Actor
));
1596 nlwarning("CSceneParser::updateParticlesActor : cannot get the actor %d.", (uint64
)particle
.Actor
);
1600 // If the entity has no skeleton -> Next particle.
1601 if(!entity
->skeleton())
1603 nlwarning("The particle follow an entity %d without a skeleton.", (uint64
)particle
.Actor
);
1607 // Matrix 90 degrees
1610 m90
.rotateZ((float)(Pi
/2.0));
1612 // Matrix of the entity.
1613 CMatrix mChar
= entity
->skeleton()->getMatrix();
1614 mChar
.setPos(entity
->pos());
1616 // Animate all instances.
1617 for(uint i
= 0; i
< particle
.IGPtr
->getNumInstance(); ++i
)
1619 std::string iName
= particle
.IGPtr
->getInstanceName(i
);
1620 UInstance instance
= particle
.IGPtr
->getByName(iName
);
1625 instance
->setTransformMode(UTransformable::RotQuat
);
1629 // If the animation has no track of position.
1630 UTrack
* trackPos
= animation
.getTrackByName("PathPos");
1632 trackPos
= animation
.getTrackByName(string(iName
+ "." + "PathPos").c_str());
1636 trackPos
->interpolate(difTime
, pos
);
1640 // If the animation has no track of rotation.
1641 UTrack
* trackRot
= animation
.getTrackByName("PathRotQuat");
1643 trackRot
= animation
.getTrackByName(string(iName
+ "." + "PathRotQuat").c_str());
1647 trackPos
->interpolate(difTime
, rot
);
1651 CMatrix mFinal
= mChar
* m90
* mAnim
;
1652 instance
->setPos(mFinal
.getPos());
1653 instance
->setRotQuat(mFinal
.getRot());
1655 }// updateParticlesActor //
1658 //-----------------------------------------------
1660 // Load a scene from a file and put it in memory.
1661 // \param filename : filename for the file that contains the scene.
1662 // \warning This function clear the old scene.
1663 //-----------------------------------------------
1664 void CSceneParser::loadScene(const string
&filename
)
1666 // Look for the file -> nlwarning and return if sceneFile is empty.
1667 string sceneFile
= CPath::lookup(filename
, false);
1668 if(sceneFile
.empty())
1670 nlwarning("CSceneParser::loadScene : Can't find file \"%s\".", filename
.c_str());
1675 ifstream
file(sceneFile
.c_str(), ios::in
);
1679 char tmpBuff
[MAX_LINE_SIZE
];
1681 // While the end of the file is not reached -> parse the script.
1684 // Get next valid line.
1685 getNextValidLine(file
, tmpBuff
);
1687 pair
<sint
, double> seq
;
1689 char *ptr
= strtok(tmpBuff
, delimiter
);
1692 seq
.first
= atoi(ptr
);
1693 ptr
= strtok(NULL
, delimiter
);
1696 NLMISC::fromString(ptr
, seq
.second
);
1697 _Scene
.push_back(seq
);
1707 nlwarning("CSceneParser::loadScene : File \"%s\" can't be open.", sceneFile
.c_str());
1712 //-----------------------------------------------
1714 // Play a scene in memory.
1715 // \param timeInSec : current time in second.
1716 //-----------------------------------------------
1717 void CSceneParser::playScene(double timeInSec
)
1719 // Initialize the Iterator for the scene.
1720 _ItScene
= _Scene
.begin();
1721 // Initialize the time for the scene.
1722 _SceneStart
= timeInSec
;
1724 // Initialize or Reset the scene.
1727 // Play the first sequence to play for this scene.
1728 updateScene(timeInSec
);
1731 //-----------------------------------------------
1733 // Update the scene currently playing.
1734 // \param timeInSec : current time in second.
1735 //-----------------------------------------------
1736 void CSceneParser::updateScene(double timeInSec
)
1738 // If there are still sequences in the scene.
1739 if(_ItScene
!= _Scene
.end())
1741 double time
= timeInSec
-_SceneStart
;
1742 if((*_ItScene
).second
<= time
)
1744 // If the scene is finish -> Stop it.
1745 if((*_ItScene
).first
< 0)
1751 // Play the sequence.
1752 playSeq((*_ItScene
).first
, timeInSec
);
1761 //-----------------------------------------------
1763 // Stop the scene currently playing.
1764 //-----------------------------------------------
1765 void CSceneParser::stopScene()
1767 _ItScene
= _Scene
.end();
1771 //-----------------------------------------------
1772 // Function to know if there is a scene currently playing.
1773 // \return bool : 'true' if there is a scene currently playing.
1774 //-----------------------------------------------
1775 bool CSceneParser::isScenePlaying()
1777 return (_ItScene
!= _Scene
.end());
1778 }// isScenePlaying //