New lua versions
[ryzomcore.git] / studio / src / plugins / object_viewer / scene / entity.cpp
blobf5a1b5094bbfd69b9db4b90a6a5506f1bd9169bf
1 /*
2 Object Viewer Qt
3 Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "stdpch.h"
21 #include "entity.h"
23 #include <QtCore/QString>
25 // NeL includes
26 #include <nel/misc/path.h>
27 #include <nel/3d/u_driver.h>
28 #include <nel/3d/u_scene.h>
29 #include <nel/3d/u_animation_set.h>
30 #include <nel/3d/u_animation.h>
31 #include <nel/3d/u_play_list_manager.h>
32 #include <nel/3d/u_play_list.h>
33 #include <nel/3d/u_track.h>
35 // Project includes
36 #include "modules.h"
38 using namespace NLMISC;
39 using namespace NL3D;
41 namespace NLQT
44 CSlotInfo::CSlotInfo()
45 : Animation("empty"),
46 Skeleton("empty"),
47 Offset(0),
48 StartTime(0),
49 EndTime(0),
50 StartBlend(1),
51 EndBlend (1),
52 Smoothness(1),
53 SpeedFactor(1),
54 ClampMode(0),
55 SkeletonInverted(false),
56 Enable(true)
60 CSlotInfo &CSlotInfo::operator=(const CSlotInfo &slotInfo)
62 if ( this != &slotInfo)
64 Animation = slotInfo.Animation;
65 ClampMode = slotInfo.ClampMode;
66 Enable = slotInfo.Enable;
67 EndBlend = slotInfo.EndBlend;
68 EndTime = slotInfo.EndTime;
69 Offset = slotInfo.Offset;
70 Skeleton = slotInfo.Skeleton;
71 SkeletonInverted = slotInfo.SkeletonInverted;
72 Smoothness = slotInfo.Smoothness;
73 SpeedFactor = slotInfo.SpeedFactor;
74 StartBlend = slotInfo.StartBlend;
75 StartTime = slotInfo.StartTime;
77 return *this;
80 CEntity::CEntity(void)
81 : _Name("<Unknown>"),
82 _FileNameShape(""),
83 _FileNameSkeleton(""),
84 _inPlace(false),
85 _incPos(false),
86 _Instance(NULL),
87 _Skeleton(NULL),
88 _PlayList(NULL),
89 _AnimationSet(NULL)
91 _CharacterScalePos = 1;
94 CEntity::~CEntity(void)
96 if (_PlayList != NULL)
98 _PlayList->resetAllChannels();
99 Modules::objView().getPlayListManager()->deletePlayList (_PlayList);
100 _PlayList = NULL;
102 if (_AnimationSet != NULL)
104 Modules::objView().getDriver()->deleteAnimationSet(_AnimationSet);
105 _AnimationSet = NULL;
107 if (!_Skeleton.empty())
109 _Skeleton.detachSkeletonSon(_Instance);
110 Modules::objView().getScene()->deleteSkeleton(_Skeleton);
111 _Skeleton = NULL;
113 if (!_Instance.empty())
115 Modules::objView().getScene()->deleteInstance(_Instance);
116 _Instance = NULL;
120 void CEntity::loadAnimation(const std::string &fileName)
122 uint id = _AnimationSet->addAnimation(fileName.c_str(),CFile::getFilenameWithoutExtension(fileName).c_str());
123 _AnimationList.push_back(_AnimationSet->getAnimationName(id));
124 _AnimationSet->build();
125 if (!_Skeleton.empty())
126 _PlayList->registerTransform(_Skeleton);
127 else
128 _PlayList->registerTransform(_Instance);
131 void CEntity::loadSWT(const std::string &fileName)
133 uint id = _AnimationSet->addSkeletonWeight(fileName.c_str(),CFile::getFilenameWithoutExtension(fileName).c_str());
134 _SWTList.push_back(_AnimationSet->getSkeletonWeightName(id));
137 void CEntity::addAnimToPlayList(const std::string &name)
139 _PlayListAnimation.push_back(name);
141 _AnimationStatus.EndAnim = this->getPlayListLength();
143 _Instance.start();
146 void CEntity::removeAnimToPlayList(uint row)
148 if (row < _PlayListAnimation.size())
149 _PlayListAnimation.erase(_PlayListAnimation.begin() + row);
151 _AnimationStatus.EndAnim = this->getPlayListLength();
154 void CEntity::swapAnimToPlayList(uint row1, uint row2)
156 if ((row1 < _PlayListAnimation.size()) && (row2 < _PlayListAnimation.size()))
157 std::swap(_PlayListAnimation[row1], _PlayListAnimation[row2]);
160 void CEntity::playbackAnim(bool play)
162 _AnimationStatus.PlayAnim = play;
164 if (play)
165 _Instance.start();
166 else
167 _Instance.freezeHRC();
170 void CEntity::reset()
172 _PlayListAnimation.clear();
173 _AnimationList.clear();
174 _SWTList.clear();
176 _PlayList->resetAllChannels();
179 float CEntity::getPlayListLength() const
181 // Accumul all the time
182 float time = 0;
183 for(size_t i = 0; i < _PlayListAnimation.size(); ++i)
184 time += getAnimLength(_PlayListAnimation[i]);
185 return time;
188 float CEntity::getAnimLength(const std::string &name) const
190 uint id = _AnimationSet->getAnimationIdByName(name.c_str());
191 NL3D::UAnimation *anim = _AnimationSet->getAnimation(id);
192 return anim->getEndTime() - anim->getBeginTime();
195 void CEntity::update(NL3D::TAnimationTime time)
197 this->resetChannel();
198 switch (_AnimationStatus.Mode)
200 case Mode::PlayList:
201 animatePlayList(time);
202 break;
203 case Mode::Mixer:
204 animateChannelMixer();
205 break;
210 void CEntity::resetChannel()
212 for(uint i = 0; i < NL3D::CChannelMixer::NumAnimationSlot; ++i)
213 _PlayList->setAnimation(i, UPlayList::empty);
216 void CEntity::addTransformation (CMatrix &current, UAnimation *anim, float begin, float end, UTrack *posTrack, UTrack *rotquatTrack,
217 UTrack *nextPosTrack, UTrack *nextRotquatTrack, bool removeLast)
219 // In place ?
220 if (_inPlace)
222 // Just identity
223 current.identity();
225 else
227 // Remove the start of the animation
228 CQuat rotEnd (0,0,0,1);
229 CVector posEnd (0,0,0);
230 if (rotquatTrack)
232 // Interpolate the rotation
233 rotquatTrack->interpolate (end, rotEnd);
235 if (posTrack)
237 // Interpolate the position
238 posTrack->interpolate (end, posEnd);
241 // Add the final rotation and position
242 CMatrix tmp;
243 tmp.identity ();
244 tmp.setRot (rotEnd);
245 tmp.setPos (posEnd);
247 // Incremental ?
248 if (_incPos)
249 current *= tmp;
250 else
251 current = tmp;
253 if (removeLast)
255 CQuat rotStart (0,0,0,1);
256 CVector posStart (0,0,0);
257 if (nextRotquatTrack)
259 // Interpolate the rotation
260 nextRotquatTrack->interpolate (begin, rotStart);
262 if (nextPosTrack)
264 // Interpolate the position
265 nextPosTrack->interpolate (begin, posStart);
267 // Remove the init rotation and position of the next animation
268 tmp.identity ();
269 tmp.setRot (rotStart);
270 tmp.setPos (posStart);
271 tmp.invert ();
272 current *= tmp;
274 // Normalize the mt
275 CVector I = current.getI ();
276 CVector J = current.getJ ();
277 I.z = 0;
278 J.z = 0;
279 J.normalize ();
280 CVector K = I^J;
281 K.normalize ();
282 I = J^K;
283 I.normalize ();
284 tmp.setRot (I, J, K);
285 tmp.setPos (current.getPos ());
286 current = tmp;
291 void CEntity::animatePlayList(NL3D::TAnimationTime time)
293 if (!_PlayListAnimation.empty())
295 // Animation index
296 uint id = _AnimationSet->getAnimationIdByName(_PlayListAnimation[0].c_str());
298 // Try channel AnimationSet
299 NL3D::UAnimation *anim = _AnimationSet->getAnimation(id);
301 bool there = false;
303 UTrack *posTrack = NULL;
304 UTrack *rotQuatTrack = NULL;
306 // Current matrix
307 CMatrix current;
308 current.identity();
310 // read an animation for init matrix
311 rotQuatTrack = anim->getTrackByName("rotquat");
312 posTrack = anim->getTrackByName("pos");
314 there = posTrack || rotQuatTrack;
316 // Accumul time
317 float startTime = 0;
318 float endTime = anim->getEndTime() - anim->getBeginTime();
320 uint index = 0;
321 while (time >= endTime)
323 index++;
324 if (index < _PlayListAnimation.size())
326 id = _AnimationSet->getAnimationIdByName(_PlayListAnimation[index].c_str());
327 NL3D::UAnimation *newAnim = _AnimationSet->getAnimation(id);
329 UTrack *newPosTrack = newAnim->getTrackByName ("pos");
330 UTrack *newRotquatTrack = newAnim->getTrackByName ("rotquat");
332 // Add the transformation
333 addTransformation (current, anim, newAnim->getBeginTime(), anim->getEndTime(), posTrack, rotQuatTrack, newPosTrack, newRotquatTrack, true);
336 anim = newAnim;
337 posTrack = newPosTrack;
338 rotQuatTrack = newRotquatTrack;
340 // Add start time
341 startTime = endTime;
342 endTime = startTime + (anim->getEndTime() - anim->getBeginTime());
344 else
346 // Add the transformation
347 addTransformation (current, anim, 0, anim->getEndTime(), posTrack, rotQuatTrack, NULL, NULL, false);
348 break;
352 // Time cropped ?
353 if (index >= _PlayListAnimation.size())
355 // Yes
356 index--;
357 id = _AnimationSet->getAnimationIdByName(_PlayListAnimation[index].c_str());
358 anim = _AnimationSet->getAnimation(id);
360 // End time for last anim
361 startTime = anim->getEndTime() - time;
363 else
365 // No
367 // Add the transformation
368 addTransformation (current, anim, 0, anim->getBeginTime() + time - startTime, posTrack, rotQuatTrack, NULL, NULL, false);
370 id = _AnimationSet->getAnimationIdByName(_PlayListAnimation[index].c_str());
371 anim = _AnimationSet->getAnimation(id);
373 // Final time
374 startTime -= anim->getBeginTime();
377 // Set the slot
378 _PlayList->setAnimation(0, id);
379 _PlayList->setTimeOrigin(0, startTime);
380 _PlayList->setSpeedFactor(0, 1.0f);
381 _PlayList->setWeightSmoothness(0, 1.0f);
382 _PlayList->setStartWeight(0, 1, 0);
383 _PlayList->setEndWeight(0, 1, 1);
384 _PlayList->setWrapMode(0, UPlayList::Clamp);
386 // Setup the pos and rot for this shape
387 if (there)
389 CVector pos = current.getPos();
391 // If a skeleton model
392 if(!_Skeleton.empty())
394 _Skeleton.setTransformMode(NL3D::UTransformable::RotQuat);
395 // scale animated pos value with the CFG scale
396 pos *= _CharacterScalePos;
397 _Skeleton.setPos(pos);
398 _Skeleton.setRotQuat(current.getRot());
400 else
402 _Instance.setTransformMode(NL3D::UTransformable::RotQuat);
403 _Instance.setPos(pos);
404 _Instance.setRotQuat(current.getRot());
410 void CEntity::animateChannelMixer()
412 for (uint i = 0; i < NL3D::CChannelMixer::NumAnimationSlot; ++i)
414 if (_SlotInfo[i].Enable)
416 // Set the animation
417 uint animId = _AnimationSet->getAnimationIdByName(_SlotInfo[i].Animation);
418 if (animId == UAnimationSet::NotFound)
419 _PlayList->setAnimation(i, UPlayList::empty);
420 else
421 _PlayList->setAnimation(i, animId);
423 // Set the skeleton weight
424 uint skelId = _AnimationSet->getSkeletonWeightIdByName(_SlotInfo[i].Skeleton);
425 if (skelId == UAnimationSet::NotFound)
426 _PlayList->setSkeletonWeight(i, UPlayList::empty, false);
427 else
428 _PlayList->setSkeletonWeight(i, skelId, _SlotInfo[i].SkeletonInverted);
430 // Set others values
431 _PlayList->setTimeOrigin(i, _SlotInfo[i].Offset);
432 _PlayList->setSpeedFactor(i, _SlotInfo[i].SpeedFactor);
433 _PlayList->setStartWeight(i, _SlotInfo[i].StartBlend, _SlotInfo[i].StartTime);
434 _PlayList->setEndWeight(i, _SlotInfo[i].EndBlend, _SlotInfo[i].EndTime);
435 _PlayList->setWeightSmoothness(i, _SlotInfo[i].Smoothness);
437 // Switch between wrap modes
438 switch (_SlotInfo[i].ClampMode)
440 case 0:
441 _PlayList->setWrapMode (i, UPlayList::Clamp);
442 break;
443 case 1:
444 _PlayList->setWrapMode (i, UPlayList::Repeat);
445 break;
446 case 2:
447 _PlayList->setWrapMode (i, UPlayList::Disable);
448 break;
454 } /* namespace NLQT */