Show bonus/malus timer text if available
[ryzomcore.git] / nel / src / 3d / animation_set.cpp
blob462587b090e6ca51d5c72b2817426223e59f9035
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
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.
8 //
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/>.
17 #include "std3d.h"
19 #include "nel/3d/animation_set.h"
20 #include "nel/3d/driver.h"
21 #include "nel/3d/shape_bank.h"
22 #include "nel/misc/stream.h"
23 #include "nel/misc/path.h"
24 #include "nel/misc/file.h"
25 #include "nel/misc/algo.h"
29 using namespace std;
30 using namespace NLMISC;
32 #ifdef DEBUG_NEW
33 #define new DEBUG_NEW
34 #endif
36 namespace NL3D
39 // ***************************************************************************
40 CAnimationSet::CAnimationSet (bool headerOptim)
42 _SampleDivisor= 1;
43 _AnimHeaderOptimisation= headerOptim;
44 _Built= false;
47 // ***************************************************************************
48 CAnimationSet::~CAnimationSet ()
50 // Erase all animations.
51 for (uint a=0; a<_Animation.size(); a++)
52 delete _Animation[a];
53 for (uint s=0; s<_SkeletonWeight.size(); s++)
54 delete _SkeletonWeight[s];
57 // ***************************************************************************
58 uint CAnimationSet::getNumChannelId () const
60 return (uint)_ChannelIdByName.size ();
63 // ***************************************************************************
64 uint CAnimationSet::addAnimation (const char* name, CAnimation* animation)
66 // error to add an animation after a build() if the animation set is in HeaderCompress mode
67 nlassert(! (_Built && _AnimHeaderOptimisation) );
69 // if sampleDivisor, apply to the animation
70 if(_SampleDivisor>1)
71 animation->applySampleDivisor(_SampleDivisor);
73 // compress CTrackSampledQuat header
74 if(_AnimHeaderOptimisation)
75 animation->applyTrackQuatHeaderCompression();
77 // Add an animation
78 _Animation.push_back (animation);
79 _AnimationName.push_back (name);
81 // Add an entry name / animation
82 _AnimationIdByName.insert (std::map <std::string, uint32>::value_type (name, (uint32)_Animation.size()-1));
84 // Return animation id
85 return (uint)_Animation.size()-1;
88 // ***************************************************************************
89 uint CAnimationSet::addSkeletonWeight (const char* name, CSkeletonWeight* skeletonWeight)
91 // Add an animation
92 _SkeletonWeight.push_back (skeletonWeight);
93 _SkeletonWeightName.push_back (name);
95 // Add an entry name / animation
96 _SkeletonWeightIdByName.insert (std::map <std::string, uint32>::value_type (name, (uint32)_SkeletonWeight.size()-1));
98 // Return animation id
99 return (uint)_SkeletonWeight.size()-1;
102 // ***************************************************************************
103 void CAnimationSet::reset ()
105 _Animation.clear();
106 _SkeletonWeight.clear();
107 _ChannelName.clear();
108 _AnimationName.clear();
109 _SkeletonWeightName.clear();
110 _ChannelIdByName.clear();
111 _AnimationIdByName.clear();
112 _SkeletonWeightIdByName.clear();
113 _SSSShapes.clear();
116 // ***************************************************************************
117 void CAnimationSet::build ()
119 // error to rebuild in if already done while _AnimHeaderOptimisation,
120 // cause applyAnimHeaderCompression() won't work
121 if(_Built && _AnimHeaderOptimisation)
122 return;
123 _Built= true;
125 // Clear the channel map
126 _ChannelName.clear();
127 _ChannelIdByName.clear ();
129 // Set of names
130 std::set<std::string> channelNames;
132 // For each animation in the set
133 uint a;
134 for (a=0; a<_Animation.size(); a++)
136 // Fill the set of channel names
137 getAnimation (a)->getTrackNames (channelNames);
140 // Add this name in the map with there iD
141 uint id=0;
142 std::set<std::string>::iterator ite=channelNames.begin ();
143 while (ite!=channelNames.end ())
145 // Insert an entry
146 _ChannelIdByName.insert (std::map <std::string, uint32>::value_type (*ite, id++));
148 // Next entry
149 ite++;
152 // build ChannelName From Map
153 buildChannelNameFromMap();
155 // If the animation set is in HeaderOptim mode, reduce memory load by removing map<string, trackId>
156 if(_AnimHeaderOptimisation)
158 for (uint a=0; a<_Animation.size(); a++)
160 _Animation[a]->applyAnimHeaderCompression (this, _ChannelIdByName);
164 // Build the set of SSS Shapes from each animation
165 for (a=0; a<_Animation.size(); a++)
167 const std::vector<std::string> &shapes= _Animation[a]->getSSSShapes();
168 for(uint s=0;s<shapes.size();s++)
170 // insert (may be already done)
171 _SSSShapes.insert(shapes[s]);
176 // TestYoyo
177 /*nlinfo("ANIMYOYO: %d channels", _ChannelIdByName.size());
178 std::map <std::string, uint32>::iterator it;
179 for(it= _ChannelIdByName.begin();it!=_ChannelIdByName.end();it++)
181 nlinfo("ANIMYOYO: %3d: %s", it->second, it->first.c_str());
185 // ***************************************************************************
186 void CAnimationSet::serial (NLMISC::IStream& f)
188 // serial not possible if header optimisation enabled
189 nlassert(!_AnimHeaderOptimisation);
191 // Serial an header
192 f.serialCheck (NELID("_LEN"));
193 f.serialCheck (NELID("MINA"));
194 f.serialCheck (NELID("TES_"));
196 // Serial a version
197 uint ver= f.serialVersion (1);
199 // Serial the class
200 f.serialContPtr (_Animation);
201 f.serialContPtr (_SkeletonWeight);
202 f.serialCont (_AnimationName);
203 f.serialCont (_SkeletonWeightName);
204 f.serialCont(_ChannelIdByName);
205 f.serialCont(_AnimationIdByName);
206 f.serialCont(_SkeletonWeightIdByName);
207 if(ver>=1)
208 f.serialCont(_ChannelName);
209 else
210 buildChannelNameFromMap();
213 // ***************************************************************************
214 bool CAnimationSet::loadFromFiles(const std::string &path, bool recurse /* = true*/, const char *ext /*= "anim"*/, bool wantWarningMessage /*= true*/)
216 bool everythingOk = true;
217 std::vector<std::string> anims;
218 NLMISC::CPath::getPathContent(path, recurse, false, true, anims);
219 for (uint k = 0; k < anims.size(); ++k)
221 std::string fileExt = NLMISC::CFile::getExtension(anims[k]);
222 if (fileExt == ext) // an animation file ?
226 NLMISC::CIFile iFile;
227 iFile.open(anims[k]);
228 CUniquePtr<CAnimation> anim(new CAnimation);
229 anim->serial(iFile);
230 addAnimation(NLMISC::CFile::getFilenameWithoutExtension(anims[k]).c_str(), anim.release());
231 iFile.close();
234 catch (const NLMISC::EStream &e)
236 if (wantWarningMessage)
238 nlinfo("Unable to load an automatic animation : %s", e.what());
240 everythingOk = false;
244 build();
245 return everythingOk;
248 // ***************************************************************************
249 void CAnimationSet::setAnimationSampleDivisor(uint sampleDivisor)
251 _SampleDivisor= sampleDivisor;
252 // 0 is invalid
253 if(_SampleDivisor==0)
254 _SampleDivisor= 1;
257 // ***************************************************************************
258 uint CAnimationSet::getAnimationSampleDivisor() const
260 return _SampleDivisor;
263 // ***************************************************************************
264 void CAnimationSet::buildChannelNameFromMap()
266 contReset(_ChannelName);
267 _ChannelName.resize(_ChannelIdByName.size());
268 std::map <std::string, uint32>::iterator it;
269 for(it= _ChannelIdByName.begin();it!=_ChannelIdByName.end();it++)
271 _ChannelName[it->second]= it->first;
275 // ***************************************************************************
276 void CAnimationSet::preloadSSSShapes(IDriver &drv, CShapeBank &shapeBank)
278 const std::string shapeCacheName= "SSS_PreLoad";
280 // Create the Animation Set Shape cache if do not exist
281 if(!shapeBank.isShapeCache(shapeCacheName))
283 // allow "inifinite" number of preloaded shapes
284 shapeBank.addShapeCache(shapeCacheName);
285 shapeBank.setShapeCacheSize(shapeCacheName, 1000000);
288 // For all files
289 std::set<std::string>::iterator it;
290 for(it=_SSSShapes.begin();it!=_SSSShapes.end();it++)
292 string fileName= toLowerAscii(*it);
294 // link the shape to the shapeCache
295 shapeBank.linkShapeToShapeCache(fileName, shapeCacheName);
297 // If !present in the shapeBank
298 if( shapeBank.getPresentState(fileName)==CShapeBank::NotPresent )
300 // Don't load it if no more space in the cache
301 if( shapeBank.getShapeCacheFreeSpace(shapeCacheName)>0 )
303 // load it.
304 shapeBank.load(fileName);
306 // If success
307 if( shapeBank.getPresentState(fileName)==CShapeBank::Present )
309 // When a shape is first added to the bank, it is not in the cache.
310 // add it and release it to force it to be in the cache.
311 IShape *shp= shapeBank.addRef(fileName);
312 if(shp)
314 //nlinfo("Loading %s", CPath::lookup(fileName.c_str(), false, false).c_str());
315 shp->flushTextures(drv, 0);
316 shapeBank.release(shp);
325 } // NL3D