Developer Documentation

SkeletalAnimationPlugin.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4 * Copyright (c) 2001-2015, RWTH-Aachen University *
5 * Department of Computer Graphics and Multimedia *
6 * All rights reserved. *
7 * www.openflipper.org *
8 * *
9 *---------------------------------------------------------------------------*
10 * This file is part of OpenFlipper. *
11 *---------------------------------------------------------------------------*
12 * *
13 * Redistribution and use in source and binary forms, with or without *
14 * modification, are permitted provided that the following conditions *
15 * are met: *
16 * *
17 * 1. Redistributions of source code must retain the above copyright notice, *
18 * this list of conditions and the following disclaimer. *
19 * *
20 * 2. Redistributions in binary form must reproduce the above copyright *
21 * notice, this list of conditions and the following disclaimer in the *
22 * documentation and/or other materials provided with the distribution. *
23 * *
24 * 3. Neither the name of the copyright holder nor the names of its *
25 * contributors may be used to endorse or promote products derived from *
26 * this software without specific prior written permission. *
27 * *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41
42
43 #include "SkeletalAnimationPlugin.hh"
44
45 #include <ObjectTypes/Skeleton/Skeleton.hh>
46 #include <ObjectTypes/Skeleton/SkeletonObjectData.hh>
47 #include <ObjectTypes/Skeleton/SkinT.hh>
48
49
50 #include <QInputDialog>
51 #include <QMessageBox>
52
53 #include "dialogs/AnimationToolbox.hh"
54 #include "dialogs/AddAnimationDialog.hh"
55
56 using namespace std;
57
58 //------------------------------------------------------------------------------
59
63 SkeletalAnimationPlugin::SkeletalAnimationPlugin() :
64 pToolbox_(0),
65 toolIcon_(0),
66 bGuiUpdating_(false),
67 animationOffset_(0)
68 {
69 }
70
71 //------------------------------------------------------------------------------
72
76 QString SkeletalAnimationPlugin::name()
77 {
78 return "SkeletalAnimation";
79 }
80
81 //------------------------------------------------------------------------------
82
86 QString SkeletalAnimationPlugin::description()
87 {
88 return "Plugin to control skeletal animations";
89 }
90
91 //------------------------------------------------------------------------------
92
96 void SkeletalAnimationPlugin::initializePlugin()
97 {
98 bGuiUpdating_ = false;
99
100 pToolbox_ = new AnimationToolboxWidget();
101 QSize size(300, 300);
102 pToolbox_->resize(size);
103
104 connect( pToolbox_->pbAttachSkin, SIGNAL(clicked()), this, SLOT(slotAttachSkin()) );
105 connect( pToolbox_->pbClearSkins, SIGNAL(clicked()), this, SLOT(slotClearSkins()) );
106
107 connect( pToolbox_->cbAnimation, SIGNAL(currentIndexChanged(int)), this, SLOT(slotAnimationIndexChanged(int)) );
108 connect( pToolbox_->hsFrame, SIGNAL(valueChanged(int)), this, SLOT(slotFrameChanged(int)) );
109 connect( pToolbox_->pbPlay, SIGNAL(clicked()), this, SLOT( playAnimation() ) );
110 connect( pToolbox_->pbStop, SIGNAL(clicked()), this, SLOT( stopAnimation() ) );
111 connect( pToolbox_->pbPrevFrame, SIGNAL(clicked()), this, SLOT( prevFrame() ) );
112 connect( pToolbox_->pbNextFrame, SIGNAL(clicked()), this, SLOT( nextFrame() ) );
113 connect( pToolbox_->sbFPS, SIGNAL(valueChanged ( int )), this, SLOT( changeFPS(int) ) );
114 connect( pToolbox_->cbSkipFrames, SIGNAL(stateChanged(int)), this, SLOT(slotSkipFramesChanged(int)) );
115 connect( pToolbox_->pbAddAnimation, SIGNAL(clicked()), this, SLOT(slotAddAnimation()) );
116 connect( pToolbox_->pbDeleteAnimation, SIGNAL(clicked()), this, SLOT(slotDeleteAnimation()) );
117
118 connect( pToolbox_->pbEditAnimation, SIGNAL(clicked()), this, SLOT(slotAnimationNameChanged()));
119
120 pToolbox_->pbAddAnimation->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"addAnimation.png") );
121 pToolbox_->pbDeleteAnimation->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"deleteAnimation.png") );
122 pToolbox_->pbEditAnimation->setIcon(QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"editAnimation.png") );
123
124 pToolbox_->cbMethod->addItem("Linear Blend Skinning");
125 pToolbox_->cbMethod->addItem("Dual Quaternion Blend Skinning");
126
127 pToolbox_->cbMethod->setCurrentIndex(0);
128 connect( pToolbox_->cbMethod, SIGNAL(currentIndexChanged(int)), this, SLOT(slotMethodChanged(int)) );
129 method_ = Blending::M_LBS;
130
131 toolIcon_ = new QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"skeletalAnimation.png");
132 emit addToolbox( tr("Skeletal Animation") , pToolbox_, toolIcon_ );
133 }
134
135 //------------------------------------------------------------------------------
136
140 void SkeletalAnimationPlugin::pluginsInitialized()
141 {
142 emit setDescriptions();
143 }
144
145 //------------------------------------------------------------------------------
146
150 void SkeletalAnimationPlugin::exit()
151 {
152 }
153
154 //------------------------------------------------------------------------------
155
159 void SkeletalAnimationPlugin::slotAllCleared()
160 {
161 activeSkeletons_.clear();
162
163 slotAnimationIndexChanged(0);
164 }
165
166 //------------------------------------------------------------------------------
167
171 void SkeletalAnimationPlugin::slotObjectSelectionChanged(int _id)
172 {
173 checkObjectSelection(_id);
174 }
175
176 //------------------------------------------------------------------------------
177
181 void SkeletalAnimationPlugin::fileOpened( int _id) {
182 checkObjectSelection(_id);
183 }
184
185 //------------------------------------------------------------------------------
186
190 void SkeletalAnimationPlugin::addedEmptyObject(int _id) {
191
192 checkObjectSelection(_id);
193 }
194
195 //------------------------------------------------------------------------------
196
200 void SkeletalAnimationPlugin::objectDeleted(int _id) {
201
202 checkObjectSelection(_id);
203
204 // Check for skin that is to be cleared
205 BaseObjectData* bod = 0;
206 if (!PluginFunctions::getObject(_id, bod)) {
207 return;
208 }
209
210 if (bod->hasObjectData(OBJECTDATA_SKIN)) {
211
212 BaseSkin* baseSkin = 0;
213
214 if (bod->dataType(DATA_TRIANGLE_MESH))
215 baseSkin = dynamic_cast<BaseSkin*> (bod->objectData(OBJECTDATA_SKIN));
216 else if (bod->dataType(DATA_POLY_MESH))
217 baseSkin = dynamic_cast<BaseSkin*> (bod->objectData(OBJECTDATA_SKIN));
218
219 if (baseSkin) {
220 BaseObjectData* skeletonObj = PluginFunctions::skeletonObject(baseSkin->skeletonId());
221
222 if(skeletonObj) {
223 // Detach skin from skeleton
224 detachSkin(bod, skeletonObj);
225 }
226 }
227 }
228 }
229
230 //------------------------------------------------------------------------------
231
235 void SkeletalAnimationPlugin::checkObjectSelection(const int _objectId){
236
237 BaseObject* object;
238 PluginFunctions::getObject(_objectId,object);
239
240 if ( !object ) {
241 std::cerr << "SkeletalAnimationPlugin::checkObjectSelection : unable to get object! " << std::endl;
242 return;
243 }
244
245 if ( object->dataType() == DataType(DATA_SKELETON) ) {
246 activeSkeletons_.clear();
247
248 // get target skeletons
249 for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS, DataType(DATA_SKELETON)) ; o_it != PluginFunctions::objectsEnd(); ++o_it)
250 activeSkeletons_.push_back( o_it->id() );
251
252 // if no target skeleton there check if there is only one skeleton
253 if ( activeSkeletons_.empty() ){
254 for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::ALL_OBJECTS, DataType(DATA_SKELETON)) ; o_it != PluginFunctions::objectsEnd(); ++o_it)
255 activeSkeletons_.push_back( o_it->id() );
256
257 if (activeSkeletons_.size() != 1)
258 activeSkeletons_.clear();
259 }
260
261 }
262
263 UpdateUI();
264 }
265
266 //------------------------------------------------------------------------------
267
268 void SkeletalAnimationPlugin::slotAnimationNameChanged() {
269
270 if(pToolbox_->cbAnimation->currentText() == "Reference Pose") {
271
272 QMessageBox::warning(0, "Not editable!", "You cannot change the reference pose's name!");
273 return;
274 }
275
276 QString newName = QInputDialog::getText(0, tr("Change Animation's Name"), tr("New Name:"),
277 QLineEdit::Normal, pToolbox_->cbAnimation->currentText());
278
279 // Set animation's name
280 for (unsigned int i=0; i < activeSkeletons_.size(); i++){
281
282 // Get active skeleton
283 BaseObjectData* baseObject = 0;
284 PluginFunctions::getObject(activeSkeletons_[i], baseObject);
285
286 if ( baseObject == 0 )
287 continue;
288
289 SkeletonObject* skeletonObject = dynamic_cast<SkeletonObject*>(baseObject);
290 if(!skeletonObject) continue;
291 Skeleton* skeleton = PluginFunctions::skeleton(skeletonObject);
292 if(!skeleton) continue;
293
294 AnimationHandle h = skeleton->animationHandle(pToolbox_->cbAnimation->currentText().toStdString());
295 if(skeleton != 0 && h.isValid()) {
296 skeleton->animation(h)->setName(newName.toStdString());
297 skeleton->replaceAnimationName(pToolbox_->cbAnimation->currentText().toStdString(), newName.toStdString());
298 } else {
299 return;
300 }
301 }
302
303 pToolbox_->cbAnimation->setItemText(pToolbox_->cbAnimation->currentIndex(), newName);
304 }
305
306 //------------------------------------------------------------------------------
307
311 int SkeletalAnimationPlugin::getNumberOfFrames()
312 {
313
314 for (unsigned int i=0; i < activeSkeletons_.size(); i++){
315
316 //get active skeleton
317 BaseObjectData* baseObject = 0;
318 PluginFunctions::getObject(activeSkeletons_[i], baseObject);
319
320 if ( baseObject == 0 )
321 continue;
322
323 SkeletonObject* skeletonObject = dynamic_cast<SkeletonObject*>(baseObject);
324 Skeleton* skeleton = PluginFunctions::skeleton(skeletonObject);
325
326 if(skeleton != 0 && skeleton->animation( currentAnimationHandle() ) != 0)
327 return skeleton->animation( currentAnimationHandle() )->frameCount();
328 }
329
330 return 0;
331 }
332
333 //------------------------------------------------------------------------------
334
338 void SkeletalAnimationPlugin::setFrame(int _iFrame)
339 {
340 pToolbox_->hsFrame->setValue(_iFrame);
341 }
342
343 //------------------------------------------------------------------------------
344
348 int SkeletalAnimationPlugin::getFrame() {
349 return pToolbox_->hsFrame->value();
350 }
351
352 //------------------------------------------------------------------------------
353
357 void SkeletalAnimationPlugin::changeFPS(int _fps) {
358 pToolbox_->sbFPS->blockSignals(true);
359 pToolbox_->sbFPS->setValue(_fps);
360 pToolbox_->sbFPS->blockSignals(false);
361
362 animationTimer_.setInterval(1000/_fps);
363 }
364
365 //------------------------------------------------------------------------------
366
373 void SkeletalAnimationPlugin::UpdateSkins(BaseObjectData *_skeletonObject, AnimationHandle &_hAni)
374 {
375
376 if( !_skeletonObject->hasObjectData(OBJECTDATA_SKELETON) )
377 return;
378
379 SkeletonObjectData* skeletonData = dynamic_cast< SkeletonObjectData* >( _skeletonObject->objectData(OBJECTDATA_SKELETON) );
380
381 for (unsigned int i=0; i < skeletonData->skinCount(); i++){
382
383 // deform all attached skin meshes
384 int meshId = skeletonData->skin(i);
385
386 BaseObjectData* object = 0;
387 PluginFunctions::getObject(meshId, object);
388
389 if (object == 0)
390 continue;
391
392 if ( !object->hasObjectData(OBJECTDATA_SKIN) ){
393 emit log(LOGERR, tr("Error: Attached skin mesh has no skin-object-data."));
394 continue;
395 }
396
397 BaseSkin* skin = dynamic_cast< BaseSkin* > ( object->objectData(OBJECTDATA_SKIN) );
398 skin->deformSkin(_hAni, method_ );
399
400 emit updatedObject(object->id(), UPDATE_GEOMETRY);
401 }
402 }
403
404 //------------------------------------------------------------------------------
405
409 void SkeletalAnimationPlugin::slotObjectUpdated( int _id, const UpdateType& /*_type*/ )
410 {
411 // do nothing during animation
412 if ( animationTimer_.isActive() )
413 return;
414
415 BaseObjectData* obj = 0;
416
417 PluginFunctions::getObject(_id, obj);
418
419 if ( (obj != 0) && (obj->dataType(DATA_SKELETON)) ){
420
421 SkeletonObject* sObj = PluginFunctions::skeletonObject(obj);
422
423 //check if pose changed
424 if ( sObj->activePose() != currentAnimationHandle() ){
425
426 AnimationHandle newHandle = sObj->activePose();
427
428 if ( !newHandle.isValid() ) //refPose
429 pToolbox_->cbAnimation->setCurrentIndex( 0 );
430 else
431 setComboBoxPosition(newHandle.animationIndex());
432 }
433
434 //check if animationCount changed
435 if ( (int)PluginFunctions::skeleton(sObj)->animationCount() != pToolbox_->cbAnimation->count()-1 )
436 UpdateUI();
437 }
438 }
439
440 //------------------------------------------------------------------------------
441
445 void SkeletalAnimationPlugin::slotAnimationIndexChanged(int /*_index*/)
446 {
447 if(bGuiUpdating_) // do not update while the gui is updating
448 return;
449
450 if ( activeSkeletons_.empty() ){
451 pToolbox_->hsFrame->setRange( 0, 0 );
452 pToolbox_->hsFrame->setTickInterval(1);
453 pToolbox_->hsFrame->setValue(0);
454
455 pToolbox_->cbAnimation->clear();
456
457 } else {
458
459 //get first active skeleton
460 BaseObjectData* skelObject = 0;
461 PluginFunctions::getObject(activeSkeletons_[0], skelObject);
462
463 if ( skelObject == 0 )
464 return;
465
466 Skeleton* skeleton = PluginFunctions::skeleton(skelObject);
467
468 // equip the frame slider with the new range
469 AnimationT<ACG::Vec3d> *pAnimation = skeleton->animation(currentAnimationHandle());
470 if(pAnimation != 0){
471 pToolbox_->hsFrame->setRange( 0, pAnimation->frameCount() - 1 );
472 changeFPS( pAnimation->fps() );
473 }else
474 pToolbox_->hsFrame->setRange( 0, 0 );
475
476 pToolbox_->hsFrame->setTickInterval(1);
477 pToolbox_->hsFrame->setValue(0);
478
479 // pass the current frame
480 AnimationHandle hAni = currentAnimationHandle();
481 dynamic_cast<SkeletonObject*>(skelObject)->setActivePose(hAni);
482
483 emit updatedObject(skelObject->id(), UPDATE_GEOMETRY);
484
485 // update skins if available
486 UpdateSkins(skelObject, hAni);
487
488 slotFrameChanged(0);
489 }
490 }
491
492 //------------------------------------------------------------------------------
493
497 void SkeletalAnimationPlugin::slotFrameChanged(int /*_index*/)
498 {
499 // do not update while the gui is updating
500 if(bGuiUpdating_)
501 return;
502
503 for (unsigned int i=0; i < activeSkeletons_.size(); i++){
504
505 //get active skeleton
506 BaseObjectData* skelObject = 0;
507 PluginFunctions::getObject(activeSkeletons_[i], skelObject);
508
509 if ( skelObject == 0 )
510 return;
511
512 // pass the current frame
513 AnimationHandle hAni = currentAnimationHandle();
514 PluginFunctions::skeletonObject(skelObject)->setActivePose(hAni);
515
516 // and update the skin if available
517 UpdateSkins(skelObject, hAni);
518
519 emit updatedObject(skelObject->id(), UPDATE_GEOMETRY);
520 }
521 }
522
523 //------------------------------------------------------------------------------
524
528 void SkeletalAnimationPlugin::playAnimation() {
529 disconnect(&animationTimer_, 0, 0, 0);
530 animationTimer_.stop();
531 animationTimer_.setSingleShot(false);
532 animationTimer_.setInterval(1000 / pToolbox_->sbFPS->value());
533 connect(&animationTimer_,SIGNAL(timeout()),this,SLOT(animate()));
534 animationTimer_.start();
535 animationTime_.start();
536 animationOffset_ = pToolbox_->hsFrame->value();
537
538 //The Play button will just toggle between play and pause mode
539 connect( pToolbox_->pbPlay, SIGNAL(clicked()), this, SLOT( pauseAnimation() ) );
540 }
541
542 //------------------------------------------------------------------------------
543
547 void SkeletalAnimationPlugin::pauseAnimation() {
548 animationTimer_.stop();
549 disconnect(&animationTimer_, 0, 0, 0);
550
551 connect( pToolbox_->pbPlay, SIGNAL(clicked()), this, SLOT( playAnimation() ) );
552 }
553
554 //------------------------------------------------------------------------------
555
559 void SkeletalAnimationPlugin::stopAnimation() {
560 pauseAnimation();
561 pToolbox_->hsFrame->setSliderPosition(0); //Reset the playback
562 }
563
564 //------------------------------------------------------------------------------
565
569 void SkeletalAnimationPlugin::prevFrame() {
570 pauseAnimation();
571 pToolbox_->hsFrame->setSliderPosition(pToolbox_->hsFrame->sliderPosition() - 1);
572 }
573
574 //------------------------------------------------------------------------------
575
579 void SkeletalAnimationPlugin::nextFrame() {
580 pauseAnimation();
581 pToolbox_->hsFrame->setSliderPosition(pToolbox_->hsFrame->sliderPosition() + 1);
582 }
583
584 //------------------------------------------------------------------------------
585
592 void SkeletalAnimationPlugin::animate()
593 {
594 unsigned long frameCount = getNumberOfFrames();
595 if(frameCount <= 1) // 0: invalid animation, 1: just a pose
596 {
597 setFrame(0);
598 stopAnimation();
599 return;
600 }
601 --frameCount;
602
603 if(pToolbox_->cbSkipFrames->isChecked())
604 {
605 int fps = pToolbox_->sbFPS->value();
606 unsigned long currentFrame = animationOffset_ + (unsigned long)floor(double(animationTime_.elapsed()) / 1000.0 * fps);
607 setFrame(currentFrame % frameCount);
608 }else{
609 setFrame((getFrame() + 1) % frameCount);
610 }
611 }
612
613 //------------------------------------------------------------------------------
614
620 void SkeletalAnimationPlugin::slotSkipFramesChanged(int _state)
621 {
622 if(_state == Qt::Checked)
623 {
624 // changing to skip frames as necessary
625 animationTime_.start();
626 animationOffset_ = pToolbox_->hsFrame->value();
627 }else{
628 // changing to display all frames
629 }
630 }
631
632 //------------------------------------------------------------------------------
633
639 void SkeletalAnimationPlugin::slotMethodChanged(int _index)
640 {
641 // change the method
642 switch(_index)
643 {
644 case 0:
645 method_ = Blending::M_LBS;
646 break;
647 default:
648 case 1:
649 method_ = Blending::M_DBS;
650 break;
651 }
652
653 // deform the skin(s) using the new method
654 for (unsigned int i=0; i < activeSkeletons_.size(); i++){
655
656 //get active skeleton
657 BaseObjectData* baseObject = 0;
658 PluginFunctions::getObject(activeSkeletons_[i], baseObject);
659
660 if ( baseObject == 0 )
661 return;
662
663 SkeletonObject* skeletonObject = dynamic_cast<SkeletonObject*>(baseObject);
664 AnimationHandle hAni = skeletonObject->skeletonNode()->activePose();
665
666 // and update the skin
667 UpdateSkins(skeletonObject, hAni);
668 }
669
670 emit updateView();
671 }
672
673 //------------------------------------------------------------------------------
674
679 class GuiUpdatingScopeGuard
680 {
681 bool& v_;
682 public:
683 explicit GuiUpdatingScopeGuard(bool &_in):v_(_in){v_ = true;}
684 ~GuiUpdatingScopeGuard(){v_ = false;}
685 };
686
690 void SkeletalAnimationPlugin::UpdateUI()
691 {
692 if(bGuiUpdating_) // gui updates object -> object is updated so gui gets updated -> loop forever
693 return;
694
695 GuiUpdatingScopeGuard guard(bGuiUpdating_);
696
697 if( ! activeSkeletons_.empty() )
698 {
699 //get first active skeleton
700 BaseObjectData* baseObject = 0;
701 PluginFunctions::getObject(activeSkeletons_[0], baseObject);
702
703 if ( baseObject == 0 )
704 return;
705
706 SkeletonObject* skeletonObj = PluginFunctions::skeletonObject(baseObject);
707 Skeleton* skeleton = PluginFunctions::skeleton(baseObject);
708
709 // update the rigging and skinning group
710 // enable UI
711 if(skeletonObj->objectData(OBJECTDATA_SKELETON) == 0)
712 {
713 pToolbox_->pbAttachSkin->setEnabled(true);
714 pToolbox_->pbClearSkins->setEnabled(false);
715 pToolbox_->skinningBox->setTitle(tr("Attached Skins"));
716 }else{
717 pToolbox_->pbAttachSkin->setEnabled(true);
718 pToolbox_->pbClearSkins->setEnabled(true);
719
720 SkeletonObjectData* skelData = dynamic_cast<SkeletonObjectData*>( skeletonObj->objectData(OBJECTDATA_SKELETON) );
721 pToolbox_->skinningBox->setTitle(tr("Attached Skins (Currently: %1)").arg(skelData->skinCount()) );
722 }
723
724 // update the Skeleton group
725 AnimationHandle hAni = skeletonObj->skeletonNode()->activePose();
726
727 pToolbox_->pbAddAnimation->setEnabled(true);
728 pToolbox_->cbAnimation->setEnabled(true);
729 pToolbox_->cbAnimation->clear();
730
731 // create the reference pose
732 pToolbox_->cbAnimation->addItem("Reference Pose");
733
734 Skeleton::AnimationIterator animations = skeleton->animationsBegin();
735
736 while ( animations ) {
737 AnimationHandle anim = *animations;
738 pToolbox_->cbAnimation->addItem(skeleton->animationName(anim.animationIndex()).c_str(),QVariant::fromValue(anim.animationIndex()));
739 ++animations;
740 }
741
742 setComboBoxPosition(hAni.animationIndex());
743
744 // get the number of frames in the animation
745 pToolbox_->hsFrame->setEnabled(true);
746 if(skeleton->animation(hAni) != 0)
747 pToolbox_->hsFrame->setRange( 0, skeleton->animation(hAni)->frameCount() - 1 );
748 pToolbox_->hsFrame->setTickInterval(1);
749 pToolbox_->hsFrame->setValue(hAni.frame());
750
751 }else{
752 // disable UI
753 pToolbox_->pbAddAnimation->setEnabled(false);
754 pToolbox_->cbAnimation->setEnabled(false);
755 pToolbox_->cbAnimation->clear();
756 pToolbox_->hsFrame->setEnabled(false);
757 pToolbox_->hsFrame->setRange(0, 0);
758 pToolbox_->hsFrame->setTickInterval(1);
759
760 pToolbox_->pbAttachSkin->setEnabled(false);
761 pToolbox_->pbClearSkins->setEnabled(false);
762 pToolbox_->skinningBox->setTitle(tr("Attached Skins"));
763 }
764 }
765
766 //------------------------------------------------------------------------------
767
771 void SkeletalAnimationPlugin::slotAttachSkin()
772 {
773
774 if( activeSkeletons_.size() != 1 ){
775 emit log(LOGERR, tr("Cannot bind mesh. Please select only one skeleton."));
776 return;
777 }
778
779 int meshCount = 0;
780
781 for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS, DataType(DATA_TRIANGLE_MESH|DATA_POLY_MESH)) ; o_it != PluginFunctions::objectsEnd(); ++o_it)
782 {
783 attachSkin(activeSkeletons_[0], o_it->id());
784 meshCount++;
785 }
786
787 if (meshCount == 0){
788 emit log(LOGERR, tr("Cannot bind mesh. Please select at least one mesh as target."));
789 return;
790 }
791 }
792
793 //------------------------------------------------------------------------------
794
795 void SkeletalAnimationPlugin::attachSkin(BaseObjectData* _skin, BaseObjectData* _skeletonObj) {
796
797 // get the skeleton and make it prepare the mesh
798 Skeleton* skeleton = dynamic_cast<SkeletonObject*>(_skeletonObj)->skeleton();
799
800 //check if mesh is already a skin
801 if (_skin->hasObjectData(OBJECTDATA_SKIN) ){
802 emit log(LOGERR, tr("Cannot bind mesh as skin. Mesh is already a skin."));
803 return;
804 }
805
806 // prepare the skin template class used to deform the skin
807 SkeletonObjectData* skelData = 0;
808
809 if ( _skeletonObj->hasObjectData(OBJECTDATA_SKELETON) )
810 skelData = dynamic_cast< SkeletonObjectData* >(_skeletonObj->objectData(OBJECTDATA_SKELETON));
811 else {
812 skelData = new SkeletonObjectData();
813 _skeletonObj->setObjectData(OBJECTDATA_SKELETON, skelData);
814 }
815
816 skelData->addSkin( _skin->id() );
817
818 BaseSkin* baseSkin = 0;
819
820 OpenMesh::VPropHandleT<BaseSkin::SkinWeights> propWeights;
821 bool hasSkinWeights = true;
822
823 if(_skin->dataType(DATA_TRIANGLE_MESH)){
824 hasSkinWeights = PluginFunctions::triMesh(_skin)->get_property_handle(propWeights, SKIN_WEIGHTS_PROP);
825 baseSkin = dynamic_cast<BaseSkin*>( new TriMeshSkin(skeleton, PluginFunctions::triMesh(_skin),_skeletonObj->id()) );
826 }else if(_skin->dataType(DATA_POLY_MESH)){
827 hasSkinWeights = PluginFunctions::polyMesh(_skin)->get_property_handle(propWeights, SKIN_WEIGHTS_PROP);
828 baseSkin = dynamic_cast<BaseSkin*>( new PolyMeshSkin(skeleton, PluginFunctions::polyMesh(_skin) ,_skeletonObj->id() ));
829 }
830
831 baseSkin->attachSkin();
832
833 if (hasSkinWeights)
834 baseSkin->deformSkin(currentAnimationHandle(), method_);
835
836 emit updatedObject(_skin->id(), UPDATE_GEOMETRY);
837 _skin->setObjectData(OBJECTDATA_SKIN, baseSkin);
838
839 _skeletonObj->target(true);
840 _skeletonObj->source(false);
841
842 if( !hasSkinWeights ){
843 //ask if they should be computed automatically
844 bool canCompute;
845 emit pluginExists("skinningplugin", canCompute);
846
847 if (canCompute){
848 QMessageBox msgBox;
849 msgBox.setText("The mesh is not equipped with skin weights.");
850 msgBox.setInformativeText("Do you want to compute them automatically?");
851 msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
852 msgBox.setDefaultButton(QMessageBox::Yes);
853 int ret = msgBox.exec();
854
855 if (ret == QMessageBox::Yes)
856 RPC::callFunction("skinningplugin", "computeSkinWeights");
857 }
858 }
859
860 UpdateUI();
861 }
862
863 //------------------------------------------------------------------------------
864
868 void SkeletalAnimationPlugin::slotClearSkins()
869 {
870 for (unsigned int i=0; i < activeSkeletons_.size(); i++)
871 clearSkins( activeSkeletons_[i] );
872 }
873
874 //------------------------------------------------------------------------------
875
876 void SkeletalAnimationPlugin::clearSkins(BaseObjectData* _skeletonObj) {
877
878 // prepare the skin template class used to deform the skin
879 SkeletonObjectData* skelData = 0;
880
881 if ( !_skeletonObj->hasObjectData(OBJECTDATA_SKELETON) )
882 return;
883
884 skelData = dynamic_cast< SkeletonObjectData* >(_skeletonObj->objectData(OBJECTDATA_SKELETON));
885
886 for (int i=skelData->skinCount()-1; i >= 0; i--){
887 //deform all attached skin meshes
888 int meshId = skelData->skin(i);
889
890 BaseObjectData* object = 0;
891 PluginFunctions::getObject(meshId, object);
892
893 if (object == 0)
894 continue;
895
896 detachSkin(object, _skeletonObj);
897 }
898 }
899
900 //------------------------------------------------------------------------------
901
902 void SkeletalAnimationPlugin::detachSkin(BaseObjectData* _skin, BaseObjectData* _skeletonObj) {
903
904 // get the skeleton and make it prepare the mesh
905 Skeleton* skeleton = dynamic_cast<SkeletonObject*>(_skeletonObj)->skeleton();
906
907 if ( !_skeletonObj->hasObjectData(OBJECTDATA_SKELETON) ){
908 emit log(LOGERR, tr("Cannot detach skin. Skeleton has no object data."));
909 return;
910 }
911
912 //first try to remove the skin from the mesh
913 if (_skin->hasObjectData(OBJECTDATA_SKIN) ){
914
915 BaseSkin* baseSkin = 0;
916
917 if(_skin->dataType(DATA_TRIANGLE_MESH))
918 baseSkin = dynamic_cast<BaseSkin*>( new TriMeshSkin(skeleton, PluginFunctions::triMesh(_skin) ,_skeletonObj->id()));
919 else if(_skin->dataType(DATA_POLY_MESH))
920 baseSkin = dynamic_cast<BaseSkin*>( new PolyMeshSkin(skeleton, PluginFunctions::polyMesh(_skin) ,_skeletonObj->id()));
921
922 baseSkin->releaseSkin();
923 _skin->clearObjectData(OBJECTDATA_SKIN);
924 delete baseSkin;
925
926 emit updatedObject(_skin->id(), UPDATE_GEOMETRY);
927 }
928
929 // then remove the skin from the skeleton data
930 SkeletonObjectData* skelData = dynamic_cast< SkeletonObjectData* >(_skeletonObj->objectData(OBJECTDATA_SKELETON));
931
932 skelData->removeSkin( _skin->id() );
933
934 //remove the objectData if all skins are removed
935 if ( skelData->skinCount() == 0 ){
936 _skeletonObj->clearObjectData(OBJECTDATA_SKELETON);
937 delete skelData;
938 }
939
940 UpdateUI();
941 }
942
943 //------------------------------------------------------------------------------
944
945 void SkeletalAnimationPlugin::slotAddAnimation()
946 {
947
948 if( activeSkeletons_.size() != 1 ){
949 emit log(LOGERR, tr("Cannot add animation. Please select only one skeleton."));
950 return;
951 }
952
953 AddAnimationDialog dialog;
954 dialog.animationName->selectAll();
955 dialog.animationName->setFocus();
956
957 if ( dialog.exec() == QDialog::Accepted ){
958 if ( dialog.animationName->text() == "" ){
959 emit log(LOGERR, tr("Cannot add animation with empty name"));
960 return;
961 }
962
963 BaseObjectData* obj = 0;
964
965 PluginFunctions::getObject(activeSkeletons_[0], obj);
966
967 if (obj == 0){
968 emit log(LOGERR, tr("Unable to get object"));
969 return;
970 }
971
972 SkeletonObject* skeletonObj = PluginFunctions::skeletonObject(obj);
973
974 if (skeletonObj == 0){
975 emit log(LOGERR, tr("Unable to get skeletonObject"));
976 return;
977 }
978
979 Skeleton* skeleton = PluginFunctions::skeleton(obj);
980
981 std::string stdName = dialog.animationName->text().toStdString();
982
983 if ( skeleton->animation(stdName) != 0 ){
984 emit log(LOGERR, tr("Animation with this name already exists"));
985 return;
986 }
987
988 FrameAnimationT<ACG::Vec3d>* animation = new FrameAnimationT<ACG::Vec3d>(skeleton, dialog.frames->value());
989 AnimationHandle handle = skeleton->addAnimation(stdName, animation);
990
991 //init pose to refPose
992 for (unsigned int i=0; i < skeleton->animation(handle)->frameCount(); i++){
993 handle.setFrame(i);
994 Skeleton::Pose* pose = skeleton->pose(handle);
995
996 for (unsigned int j=0; j < skeleton->jointCount(); j++)
997 pose->setGlobalMatrix(j, skeleton->referencePose()->globalMatrix(j) );
998 }
999
1000 emit updatedObject(activeSkeletons_[0], UPDATE_ALL);
1001
1002 //select the new animation
1003 setComboBoxPosition(handle.animationIndex());
1004 }
1005 }
1006
1007 //------------------------------------------------------------------------------
1008
1009 void SkeletalAnimationPlugin::slotDeleteAnimation()
1010 {
1011 int iAnimation = pToolbox_->cbAnimation->currentIndex();
1012 unsigned int animationIndex = pToolbox_->cbAnimation->itemData(iAnimation).toUInt();
1013
1014 if ( iAnimation == 0 ) {
1015 emit log(LOGERR,"Reference pose could never be removed!");
1016 } else {
1017 pToolbox_->cbAnimation->removeItem(iAnimation);
1018
1019 for ( PluginFunctions::ObjectIterator o_it(PluginFunctions::TARGET_OBJECTS, DataType(DATA_SKELETON)) ; o_it != PluginFunctions::objectsEnd(); ++o_it) {
1020
1021 SkeletonObject* skeletonObject = dynamic_cast<SkeletonObject*>(*o_it);
1022 Skeleton* skeleton = PluginFunctions::skeleton(skeletonObject);
1023
1024 skeleton->removeAnimation(AnimationHandle(animationIndex));
1025
1026 }
1027
1028 UpdateUI();
1029 }
1030 }
1031
1032 //------------------------------------------------------------------------------
1033
1039 AnimationHandle SkeletalAnimationPlugin::currentAnimationHandle()
1040 {
1041 int iAnimation = pToolbox_->cbAnimation->currentIndex();
1042 unsigned int animationId = pToolbox_->cbAnimation->itemData(iAnimation).toUInt();
1043
1044 if(iAnimation == 0)
1045 return AnimationHandle(); //This will be the reference pose, i.e. an empty animation
1046 else if(iAnimation > 0)
1047 return AnimationHandle(animationId, pToolbox_->hsFrame->value());
1048 return AnimationHandle(); // should not happen
1049 }
1050
1051 //------------------------------------------------------------------------------
1052
1057 void SkeletalAnimationPlugin::setComboBoxPosition(unsigned int _animationIndex)
1058 {
1059 for ( int i = 0 ; i < pToolbox_->cbAnimation->count(); ++i ) {
1060 unsigned int animationId = pToolbox_->cbAnimation->itemData(i).toUInt();
1061
1062 if ( animationId == _animationIndex ) {
1063 pToolbox_->cbAnimation->setCurrentIndex(i);
1064 return;
1065 }
1066
1067 }
1068
1069 }
1070
1071 //------------------------------------------------------------------------------
1072
1073
1074
LOGERR
Definition: LoggingInterface.hh:96
BaseObject::clearObjectData
void clearObjectData(QString _dataName)
Clear the object data pointer ( this will not delete the object!! )
Definition: BaseObject.cc:787
FrameAnimationT::frameCount
unsigned int frameCount()
Returns the number of frames stored in this pose.
Definition: FrameAnimationT_impl.hh:155
SkeletalAnimationPlugin::slotFrameChanged
void slotFrameChanged(int)
Called by the framework when a different frame was selected.
Definition: SkeletalAnimationPlugin.cc:497
SkeletalAnimationPlugin::slotMethodChanged
void slotMethodChanged(int _index)
Called as the skin deformation method changed.
Definition: SkeletalAnimationPlugin.cc:639
AnimationHandle::animationIndex
size_t animationIndex() const
Returns the animation index (zero based)
Definition: AnimationHandle.hh:57
OpenMesh::VPropHandleT
Definition: Property.hh:484
PluginFunctions::skeletonObject
SkeletonObject * skeletonObject(BaseObjectData *_object)
Cast an BaseObject to a SkeletonObject if possible.
Definition: PluginFunctionsSkeleton.cc:99
SkeletalAnimationPlugin::changeFPS
void changeFPS(int _fps)
Change the frames per second (FPS)
Definition: SkeletalAnimationPlugin.cc:357
UPDATE_GEOMETRY
const UpdateType UPDATE_GEOMETRY(UpdateTypeSet(1)<< 2)
Geometry updated.
BaseSkin
Abstract base class for the skin template, wrapping all template versions of the skin.
Definition: BaseSkin.hh:62
DATA_TRIANGLE_MESH
#define DATA_TRIANGLE_MESH
Definition: TriangleMesh.hh:60
BaseObject::source
bool source()
Definition: BaseObject.cc:291
SkeletalAnimationPlugin::addedEmptyObject
void addedEmptyObject(int _id)
Update ui when the object is added.
Definition: SkeletalAnimationPlugin.cc:190
PoseT::setGlobalMatrix
void setGlobalMatrix(unsigned int _joint, const Matrix &_global, bool _keepGlobalChildPositions=true)
Sets the global coordinate system.
Definition: PoseT_impl.hh:211
DATA_POLY_MESH
#define DATA_POLY_MESH
Definition: PolyMesh.hh:59
SkeletonObjectData
Data object attached to the skeleton.
Definition: SkeletonObjectData.hh:57
UPDATE_ALL
const UpdateType UPDATE_ALL(UpdateTypeSet(1))
Identifier for all updates.
BaseObject::setObjectData
void setObjectData(QString _dataName, PerObjectData *_data)
Definition: BaseObject.cc:781
SkeletalAnimationPlugin::setComboBoxPosition
void setComboBoxPosition(unsigned int _animationIndex)
Sets the animations combo box to the right entry.
Definition: SkeletalAnimationPlugin.cc:1057
PluginFunctions::polyMesh
PolyMesh * polyMesh(BaseObjectData *_object)
Get a poly mesh from an object.
Definition: PluginFunctionsPolyMesh.cc:128
SkeletalAnimationPlugin::objectDeleted
void objectDeleted(int _id)
Update ui when the object is deleted.
Definition: SkeletalAnimationPlugin.cc:200
SkeletalAnimationPlugin::pToolbox_
AnimationToolboxWidget * pToolbox_
A pointer to the toolbox widget.
Definition: SkeletalAnimationPlugin.hh:170
RPC::callFunction
QScriptValue callFunction(QString _plugin, QString _functionName, std::vector< QScriptValue > _parameters)
Call a function provided by a plugin getting multiple parameters.
Definition: RPCWrappers.cc:55
SkeletonObject::skeletonNode
ACG::SceneGraph::SkeletonNodeT< Skeleton > * skeletonNode()
Returns the skeleton scenegraph node.
Definition: SkeletonObject.cc:215
BaseObject
Definition: BaseObject.hh:82
SkeletonT::replaceAnimationName
void replaceAnimationName(const std::string &_strOld, const std::string &_strNew)
Returns a pointer to the pose with the given animation handle.
Definition: SkeletonT.hh:190
PluginFunctions::getObject
bool getObject(const int _identifier, BaseObject *&_object)
Get the object which has the given identifier.
Definition: PluginFunctions.cc:296
FrameAnimationT
Definition: FrameAnimationT.hh:47
SkeletalAnimationPlugin::pauseAnimation
void pauseAnimation()
Called by the ui and stops the current animation.
Definition: SkeletalAnimationPlugin.cc:547
std
STL namespace.
DATA_SKELETON
#define DATA_SKELETON
Definition: Skeleton.hh:64
SkeletalAnimationPlugin::slotSkipFramesChanged
void slotSkipFramesChanged(int _state)
Called as the skip frames check box changes state.
Definition: SkeletalAnimationPlugin.cc:620
SkeletonT::animationsBegin
AnimationIterator animationsBegin()
Iterator over the animations.
Definition: SkeletonT_impl.hh:939
SkeletalAnimationPlugin::getNumberOfFrames
int getNumberOfFrames()
Returns the number of frames in the currently active animation.
Definition: SkeletalAnimationPlugin.cc:311
SkeletalAnimationPlugin::animationTime_
QTime animationTime_
Time since the animation was started, used to meet the given fps.
Definition: SkeletalAnimationPlugin.hh:178
BaseObject::target
bool target()
Definition: BaseObject.cc:273
PluginFunctions::triMesh
TriMesh * triMesh(BaseObjectData *_object)
Get a triangle mesh from an object.
Definition: PluginFunctionsTriangleMesh.cc:134
PluginFunctions::ALL_OBJECTS
const QStringList ALL_OBJECTS
Iterable object range.
Definition: PluginFunctions.hh:430
AnimationT< ACG::Vec3d >
PoseT
A general pose, used to store the frames of the animation.
Definition: PoseT.hh:58
FrameAnimationT::pose
Pose * pose(unsigned int _iFrame)
Returns a pointer to the pose stored in the given frame.
Definition: FrameAnimationT_impl.hh:145
SkeletalAnimationPlugin::animationOffset_
int animationOffset_
This frame was selected as the animation was started.
Definition: SkeletalAnimationPlugin.hh:179
GuiUpdatingScopeGuard
Helper Class for UpdateUI. assigns a bool value and set it to "true". after leaving the scope...
Definition: SkeletalAnimationPlugin.cc:679
SkeletalAnimationPlugin::description
QString description()
returns a plugin description
Definition: SkeletalAnimationPlugin.cc:86
AnimationHandle::frame
size_t frame() const
Returns the selected frame (zero based)
Definition: AnimationHandle.hh:60
DataType
Predefined datatypes.
Definition: DataTypes.hh:83
SkeletalAnimationPlugin::exit
void exit()
Plugin gets closed.
Definition: SkeletalAnimationPlugin.cc:150
AnimationHandle::isValid
bool isValid() const
Returns true if the handle is valid.
Definition: AnimationHandle.hh:55
BaseObject::id
int id() const
Definition: BaseObject.cc:190
AnimationToolboxWidget
Definition: AnimationToolbox.hh:47
SkeletalAnimationPlugin::slotObjectUpdated
void slotObjectUpdated(int _id, const UpdateType &_type)
Check activePose if a skeleton was updated.
Definition: SkeletalAnimationPlugin.cc:409
SkeletonObjectData::addSkin
void addSkin(int _objectId)
Add a skin to the skeleton.
Definition: SkeletonObjectData.hh:98
SkeletalAnimationPlugin::UpdateUI
void UpdateUI()
Called when the active object changes and the interface needs to be updated.
Definition: SkeletalAnimationPlugin.cc:690
BaseObject::dataType
bool dataType(DataType _type) const
Definition: BaseObject.cc:221
SkeletalAnimationPlugin::animate
void animate()
Iterates the animation.
Definition: SkeletalAnimationPlugin.cc:592
SkeletalAnimationPlugin::currentAnimationHandle
AnimationHandle currentAnimationHandle()
Returns a handle describing the current frame in the active animation.
Definition: SkeletalAnimationPlugin.cc:1039
SkeletalAnimationPlugin::playAnimation
void playAnimation()
Called by the ui and starts an automatic animation.
Definition: SkeletalAnimationPlugin.cc:528
SkeletonObjectData::skinCount
unsigned int skinCount()
Get the number of associated skins.
Definition: SkeletonObjectData.hh:91
SkeletonT::removeAnimation
void removeAnimation(std::string _name)
Removes an animation from the list.
Definition: SkeletonT_impl.hh:880
PluginFunctions::objectsEnd
DLLEXPORT ObjectIterator objectsEnd()
Return Iterator to Object End.
Definition: PluginFunctionsIterator.cc:177
SkeletalAnimationPlugin::slotObjectSelectionChanged
void slotObjectSelectionChanged(int _id)
Update ui when the object selection changes.
Definition: SkeletalAnimationPlugin.cc:171
SkeletonObject
Definition: SkeletonObject.hh:72
SkeletonObjectData::skin
int skin(unsigned int _index)
Get the skin with given index (0 <= _index < skinCount())
Definition: SkeletonObjectData.hh:82
SkeletalAnimationPlugin::fileOpened
void fileOpened(int _id)
Update ui when the object is loaded.
Definition: SkeletalAnimationPlugin.cc:181
SkeletalAnimationPlugin::SkeletalAnimationPlugin
SkeletalAnimationPlugin()
Constructor.
Definition: SkeletalAnimationPlugin.cc:63
SkeletalAnimationPlugin::checkObjectSelection
void checkObjectSelection(const int _objectId)
Check source/target selection of objects.
Definition: SkeletalAnimationPlugin.cc:235
PluginFunctions::ObjectIterator
Core Data Iterator.
Definition: PluginFunctions.hh:441
PluginFunctions::skeleton
Skeleton * skeleton(BaseObjectData *_object)
Get a skeleton from an object.
Definition: PluginFunctionsSkeleton.cc:80
SkeletalAnimationPlugin::initializePlugin
void initializePlugin()
initialize the plugin
Definition: SkeletalAnimationPlugin.cc:96
SkeletonT::animationName
const std::string & animationName(size_t _index)
Returns the name of the animation with the given index.
Definition: SkeletonT_impl.hh:978
SkeletalAnimationPlugin::method_
Blending::Method method_
The current blending method for the skin.
Definition: SkeletalAnimationPlugin.hh:174
SkeletalAnimationPlugin::clearSkins
bool clearSkins(int skeletonId)
Returns the number of frames in the currently active animation.
Definition: SkeletalAnimationScripting.cc:100
SkeletalAnimationPlugin::bGuiUpdating_
bool bGuiUpdating_
Used to drop a few messages while the gui is being updated.
Definition: SkeletalAnimationPlugin.hh:176
BaseObjectData
Definition: BaseObjectData.hh:102
SkeletonT::AnimationIterator
Iterator class for the animations attached to a skeleton.
Definition: SkeletonT.hh:114
UpdateType
Update type class.
Definition: UpdateType.hh:60
SkeletalAnimationPlugin::name
QString name()
returns the plugin name
Definition: SkeletalAnimationPlugin.cc:76
Skeleton.hh
PluginFunctions::TARGET_OBJECTS
const QStringList TARGET_OBJECTS("target")
Iterable object range.
SkeletalAnimationPlugin::setFrame
void setFrame(int _iFrame)
Displays the given frame from the current animation and updates the view.
Definition: SkeletalAnimationPlugin.cc:338
SkeletalAnimationPlugin::slotAttachSkin
void slotAttachSkin()
Called by Qt as the user is trying to connect a mesh to a skeleton.
Definition: SkeletalAnimationPlugin.cc:771
SkeletalAnimationPlugin::pluginsInitialized
void pluginsInitialized()
final initializations
Definition: SkeletalAnimationPlugin.cc:140
SkeletonObject::setActivePose
void setActivePose(const AnimationHandle &_hAni)
Call this to set the active pose.
Definition: SkeletonObject.cc:285
SkeletalAnimationPlugin::prevFrame
void prevFrame()
Called by the ui and goes to previous frame of the current animation.
Definition: SkeletalAnimationPlugin.cc:569
SkeletonT::animation
Animation * animation(std::string _name)
Returns a pointer to the animation to the given name.
Definition: SkeletonT_impl.hh:852
SkeletalAnimationPlugin::UpdateSkins
void UpdateSkins(BaseObjectData *_pSkeletonObject, AnimationHandle &_hAni)
Changes the mesh&#39;s pose to represent the frame given by the animation handle.
Definition: SkeletalAnimationPlugin.cc:373
SkeletalAnimationPlugin::detachSkin
bool detachSkin(int skeletonId, int skinId)
Returns the number of frames in the currently active animation.
Definition: SkeletalAnimationScripting.cc:81
SkeletonT::animationCount
size_t animationCount()
Returns the number of animations stored in this skeleton.
Definition: SkeletonT_impl.hh:965
SkeletalAnimationPlugin::stopAnimation
void stopAnimation()
Called by the ui and stops the current animation.
Definition: SkeletalAnimationPlugin.cc:559
SkeletalAnimationPlugin::slotAnimationIndexChanged
void slotAnimationIndexChanged(int)
Called by the framework when the animation index changed.
Definition: SkeletalAnimationPlugin.cc:445
BaseObject::objectData
PerObjectData * objectData(QString _dataName)
Returns the object data pointer.
Definition: BaseObject.cc:803
SkeletalAnimationPlugin::attachSkin
bool attachSkin(int skeletonId, int skinId)
Returns the number of frames in the currently active animation.
Definition: SkeletalAnimationScripting.cc:63
SkeletalAnimationPlugin::getFrame
int getFrame()
Gets the current frame number.
Definition: SkeletalAnimationPlugin.cc:348
SkeletonT
Definition: JointT.hh:50
SkeletonObjectData::removeSkin
void removeSkin(int _objectId)
Remove a skin from the skeleton.
Definition: SkeletonObjectData.hh:110
SkeletalAnimationPlugin::slotClearSkins
void slotClearSkins()
Called by Qt as the user is trying to unbind a mesh from as a skeleton.
Definition: SkeletalAnimationPlugin.cc:868
SkeletonT::animationHandle
AnimationHandle animationHandle(std::string _name)
Get an AnimationHandle to the animation with the given name.
Definition: SkeletonT_impl.hh:837
SkeletalAnimationPlugin::nextFrame
void nextFrame()
Called by the ui and goes to next frame of the current animation.
Definition: SkeletalAnimationPlugin.cc:579
BaseObject::hasObjectData
bool hasObjectData(QString _dataName)
Checks if object data with given name is available.
Definition: BaseObject.cc:795
SkeletalAnimationPlugin::slotAllCleared
void slotAllCleared()
clear all occurred
Definition: SkeletalAnimationPlugin.cc:159
AddAnimationDialog
Definition: AddAnimationDialog.hh:47
AnimationHandle
A handle used to refer to an animation or to a specific frame in an animation.
Definition: AnimationHandle.hh:47
SkinT
General skin class, used to bind skeleton and mesh and deform the mesh.
Definition: SkinT.hh:14
SkeletalAnimationPlugin::animationTimer_
QTimer animationTimer_
Timer used to control animations.
Definition: SkeletalAnimationPlugin.hh:177