43 #include "SkeletalAnimationPlugin.hh" 46 #include <ObjectTypes/Skeleton/SkeletonObjectData.hh> 47 #include <ObjectTypes/Skeleton/SkinT.hh> 50 #include <QInputDialog> 51 #include <QMessageBox> 53 #include "dialogs/AnimationToolbox.hh" 54 #include "dialogs/AddAnimationDialog.hh" 78 return "SkeletalAnimation";
88 return "Plugin to control skeletal animations";
101 QSize size(300, 300);
113 connect(
pToolbox_->sbFPS, SIGNAL(valueChanged (
int )),
this, SLOT(
changeFPS(
int) ) );
115 connect(
pToolbox_->pbAddAnimation, SIGNAL(clicked()),
this, SLOT(slotAddAnimation()) );
116 connect(
pToolbox_->pbDeleteAnimation, SIGNAL(clicked()),
this, SLOT(slotDeleteAnimation()) );
118 connect(
pToolbox_->pbEditAnimation, SIGNAL(clicked()),
this, SLOT(slotAnimationNameChanged()));
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") );
124 pToolbox_->cbMethod->addItem(
"Linear Blend Skinning");
125 pToolbox_->cbMethod->addItem(
"Dual Quaternion Blend Skinning");
131 toolIcon_ =
new QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+
"skeletalAnimation.png");
132 emit addToolbox( tr(
"Skeletal Animation") ,
pToolbox_, toolIcon_ );
142 emit setDescriptions();
161 activeSkeletons_.clear();
215 baseSkin = dynamic_cast<BaseSkin*> (bod->
objectData(OBJECTDATA_SKIN));
217 baseSkin = dynamic_cast<BaseSkin*> (bod->
objectData(OBJECTDATA_SKIN));
241 std::cerr <<
"SkeletalAnimationPlugin::checkObjectSelection : unable to get object! " << std::endl;
246 activeSkeletons_.clear();
250 activeSkeletons_.push_back( o_it->id() );
253 if ( activeSkeletons_.empty() ){
255 activeSkeletons_.push_back( o_it->id() );
257 if (activeSkeletons_.size() != 1)
258 activeSkeletons_.clear();
268 void SkeletalAnimationPlugin::slotAnimationNameChanged() {
270 if(
pToolbox_->cbAnimation->currentText() ==
"Reference Pose") {
272 QMessageBox::warning(0,
"Not editable!",
"You cannot change the reference pose's name!");
276 QString newName = QInputDialog::getText(0, tr(
"Change Animation's Name"), tr(
"New Name:"),
277 QLineEdit::Normal,
pToolbox_->cbAnimation->currentText());
280 for (
unsigned int i=0; i < activeSkeletons_.size(); i++){
286 if ( baseObject == 0 )
290 if(!skeletonObject)
continue;
292 if(!skeleton)
continue;
295 if(skeleton != 0 && h.
isValid()) {
296 skeleton->
animation(h)->setName(newName.toStdString());
314 for (
unsigned int i=0; i < activeSkeletons_.size(); i++){
320 if ( baseObject == 0 )
381 for (
unsigned int i=0; i < skeletonData->
skinCount(); i++){
384 int meshId = skeletonData->
skin(i);
393 emit log(
LOGERR, tr(
"Error: Attached skin mesh has no skin-object-data."));
397 BaseSkin* skin =
dynamic_cast< BaseSkin*
> (
object->objectData(OBJECTDATA_SKIN) );
398 skin->deformSkin(_hAni,
method_ );
429 pToolbox_->cbAnimation->setCurrentIndex( 0 );
450 if ( activeSkeletons_.empty() ){
463 if ( skelObject == 0 )
471 pToolbox_->hsFrame->setRange( 0, pAnimation->frameCount() - 1 );
503 for (
unsigned int i=0; i < activeSkeletons_.size(); i++){
509 if ( skelObject == 0 )
561 pToolbox_->hsFrame->setSliderPosition(0);
607 setFrame(currentFrame % frameCount);
622 if(_state == Qt::Checked)
654 for (
unsigned int i=0; i < activeSkeletons_.size(); i++){
660 if ( baseObject == 0 )
697 if( ! activeSkeletons_.empty() )
703 if ( baseObject == 0 )
711 if(skeletonObj->
objectData(OBJECTDATA_SKELETON) == 0)
713 pToolbox_->pbAttachSkin->setEnabled(
true);
714 pToolbox_->pbClearSkins->setEnabled(
false);
715 pToolbox_->skinningBox->setTitle(tr(
"Attached Skins"));
717 pToolbox_->pbAttachSkin->setEnabled(
true);
718 pToolbox_->pbClearSkins->setEnabled(
true);
721 pToolbox_->skinningBox->setTitle(tr(
"Attached Skins (Currently: %1)").arg(skelData->
skinCount()) );
727 pToolbox_->pbAddAnimation->setEnabled(
true);
728 pToolbox_->cbAnimation->setEnabled(
true);
732 pToolbox_->cbAnimation->addItem(
"Reference Pose");
736 while ( animations ) {
753 pToolbox_->pbAddAnimation->setEnabled(
false);
754 pToolbox_->cbAnimation->setEnabled(
false);
760 pToolbox_->pbAttachSkin->setEnabled(
false);
761 pToolbox_->pbClearSkins->setEnabled(
false);
762 pToolbox_->skinningBox->setTitle(tr(
"Attached Skins"));
774 if( activeSkeletons_.size() != 1 ){
775 emit log(
LOGERR, tr(
"Cannot bind mesh. Please select only one skeleton."));
788 emit log(
LOGERR, tr(
"Cannot bind mesh. Please select at least one mesh as target."));
802 emit log(
LOGERR, tr(
"Cannot bind mesh as skin. Mesh is already a skin."));
810 skelData = dynamic_cast< SkeletonObjectData* >(_skeletonObj->
objectData(OBJECTDATA_SKELETON));
821 bool hasSkinWeights =
true;
831 baseSkin->attachSkin();
839 _skeletonObj->
target(
true);
840 _skeletonObj->
source(
false);
842 if( !hasSkinWeights ){
845 emit pluginExists(
"skinningplugin", canCompute);
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();
855 if (ret == QMessageBox::Yes)
870 for (
unsigned int i=0; i < activeSkeletons_.size(); i++)
886 for (
int i=skelData->
skinCount()-1; i >= 0; i--){
888 int meshId = skelData->
skin(i);
908 emit log(
LOGERR, tr(
"Cannot detach skin. Skeleton has no object data."));
922 baseSkin->releaseSkin();
935 if ( skelData->skinCount() == 0 ){
945 void SkeletalAnimationPlugin::slotAddAnimation()
948 if( activeSkeletons_.size() != 1 ){
949 emit log(
LOGERR, tr(
"Cannot add animation. Please select only one skeleton."));
954 dialog.animationName->selectAll();
955 dialog.animationName->setFocus();
957 if ( dialog.exec() == QDialog::Accepted ){
958 if ( dialog.animationName->text() ==
"" ){
959 emit log(
LOGERR, tr(
"Cannot add animation with empty name"));
968 emit log(
LOGERR, tr(
"Unable to get object"));
974 if (skeletonObj == 0){
975 emit log(
LOGERR, tr(
"Unable to get skeletonObject"));
981 std::string stdName = dialog.animationName->text().toStdString();
983 if ( skeleton->
animation(stdName) != 0 ){
984 emit log(
LOGERR, tr(
"Animation with this name already exists"));
992 for (
unsigned int i=0; i < skeleton->animation(handle)->
frameCount(); i++){
996 for (
unsigned int j=0; j < skeleton->jointCount(); j++)
1000 emit updatedObject(activeSkeletons_[0],
UPDATE_ALL);
1009 void SkeletalAnimationPlugin::slotDeleteAnimation()
1011 int iAnimation =
pToolbox_->cbAnimation->currentIndex();
1012 unsigned int animationIndex =
pToolbox_->cbAnimation->itemData(iAnimation).toUInt();
1014 if ( iAnimation == 0 ) {
1015 emit log(
LOGERR,
"Reference pose could never be removed!");
1017 pToolbox_->cbAnimation->removeItem(iAnimation);
1041 int iAnimation =
pToolbox_->cbAnimation->currentIndex();
1042 unsigned int animationId =
pToolbox_->cbAnimation->itemData(iAnimation).toUInt();
1046 else if(iAnimation > 0)
1059 for (
int i = 0 ; i <
pToolbox_->cbAnimation->count(); ++i ) {
1060 unsigned int animationId =
pToolbox_->cbAnimation->itemData(i).toUInt();
1062 if ( animationId == _animationIndex ) {
1063 pToolbox_->cbAnimation->setCurrentIndex(i);
Abstract base class for the skin template, wrapping all template versions of the skin.
void pluginsInitialized()
final initializations
void addedEmptyObject(int _id)
Update ui when the object is added.
Pose * pose(unsigned int _iFrame)
Returns a pointer to the pose stored in the given frame.
void playAnimation()
Called by the ui and starts an automatic animation.
ACG::SceneGraph::SkeletonNodeT< Skeleton > * skeletonNode()
Returns the skeleton scenegraph node.
size_t animationIndex() const
Returns the animation index (zero based)
const UpdateType UPDATE_ALL(UpdateTypeSet(1))
Identifier for all updates.
unsigned int frameCount()
Returns the number of frames stored in this pose.
AnimationIterator animationsBegin()
Iterator over the animations.
void slotClearSkins()
Called by Qt as the user is trying to unbind a mesh from as a skeleton.
void objectDeleted(int _id)
Update ui when the object is deleted.
SkeletalAnimationPlugin()
Constructor.
void UpdateUI()
Called when the active object changes and the interface needs to be updated.
int animationOffset_
This frame was selected as the animation was started.
int skin(unsigned int _index)
Get the skin with given index (0 <= _index < skinCount())
void addSkin(int _objectId)
Add a skin to the skeleton.
void nextFrame()
Called by the ui and goes to next frame of the current animation.
void setGlobalMatrix(unsigned int _joint, const Matrix &_global, bool _keepGlobalChildPositions=true)
Sets the global coordinate system.
Skeleton * skeleton(BaseObjectData *_object)
Get a skeleton from an object.
void UpdateSkins(BaseObjectData *_pSkeletonObject, AnimationHandle &_hAni)
Changes the mesh's pose to represent the frame given by the animation handle.
void slotMethodChanged(int _index)
Called as the skin deformation method changed.
void checkObjectSelection(const int _objectId)
Check source/target selection of objects.
QString description()
returns a plugin description
bool dataType(DataType _type) const
size_t frame() const
Returns the selected frame (zero based)
const QStringList TARGET_OBJECTS("target")
Iterable object range.
Blending::Method method_
The current blending method for the skin.
void stopAnimation()
Called by the ui and stops the current animation.
SkeletonObject * skeletonObject(BaseObjectData *_object)
Cast an BaseObject to a SkeletonObject if possible.
A general pose, used to store the frames of the animation.
unsigned int skinCount()
Get the number of associated skins.
Helper Class for UpdateUI. assigns a bool value and set it to "true". after leaving the scope...
void slotObjectSelectionChanged(int _id)
Update ui when the object selection changes.
QScriptValue callFunction(QString _plugin, QString _functionName, std::vector< QScriptValue > _parameters)
Call a function provided by a plugin getting multiple parameters.
void initializePlugin()
initialize the plugin
TriMesh * triMesh(BaseObjectData *_object)
Get a triangle mesh from an object.
const QStringList ALL_OBJECTS
Iterable object range.
size_t animationCount()
Returns the number of animations stored in this skeleton.
const std::string & animationName(size_t _index)
Returns the name of the animation with the given index.
QTimer animationTimer_
Timer used to control animations.
void clearObjectData(QString _dataName)
Clear the object data pointer ( this will not delete the object!! )
bool getObject(const int _identifier, BaseObject *&_object)
Get the object which has the given identifier.
int getNumberOfFrames()
Returns the number of frames in the currently active animation.
A handle used to refer to an animation or to a specific frame in an animation.
General skin class, used to bind skeleton and mesh and deform the mesh.
void slotAllCleared()
clear all occurred
const UpdateType UPDATE_GEOMETRY(UpdateTypeSet(1)<< 2)
Geometry updated.
AnimationHandle currentAnimationHandle()
Returns a handle describing the current frame in the active animation.
void removeSkin(int _objectId)
Remove a skin from the skeleton.
void slotObjectUpdated(int _id, const UpdateType &_type)
Check activePose if a skeleton was updated.
void pauseAnimation()
Called by the ui and stops the current animation.
AnimationToolboxWidget * pToolbox_
A pointer to the toolbox widget.
void replaceAnimationName(const std::string &_strOld, const std::string &_strNew)
Returns a pointer to the pose with the given animation handle.
void setActivePose(const AnimationHandle &_hAni)
Call this to set the active pose.
void setObjectData(QString _dataName, PerObjectData *_data)
bool attachSkin(int skeletonId, int skinId)
Returns the number of frames in the currently active animation.
void prevFrame()
Called by the ui and goes to previous frame of the current animation.
bool clearSkins(int skeletonId)
Returns the number of frames in the currently active animation.
void fileOpened(int _id)
Update ui when the object is loaded.
Data object attached to the skeleton.
void removeAnimation(std::string _name)
Removes an animation from the list.
DLLEXPORT ObjectIterator objectsEnd()
Return Iterator to Object End.
void slotAnimationIndexChanged(int)
Called by the framework when the animation index changed.
AnimationHandle animationHandle(std::string _name)
Get an AnimationHandle to the animation with the given name.
bool hasObjectData(QString _dataName)
Checks if object data with given name is available.
PolyMesh * polyMesh(BaseObjectData *_object)
Get a poly mesh from an object.
Animation * animation(std::string _name)
Returns a pointer to the animation to the given name.
Iterator class for the animations attached to a skeleton.
PerObjectData * objectData(QString _dataName)
Returns the object data pointer.
bool bGuiUpdating_
Used to drop a few messages while the gui is being updated.
void animate()
Iterates the animation.
bool detachSkin(int skeletonId, int skinId)
Returns the number of frames in the currently active animation.
bool isValid() const
Returns true if the handle is valid.
void setFrame(int _iFrame)
Displays the given frame from the current animation and updates the view.
#define DATA_TRIANGLE_MESH
void exit()
Plugin gets closed.
void slotSkipFramesChanged(int _state)
Called as the skip frames check box changes state.
void changeFPS(int _fps)
Change the frames per second (FPS)
QTime animationTime_
Time since the animation was started, used to meet the given fps.
void setComboBoxPosition(unsigned int _animationIndex)
Sets the animations combo box to the right entry.
QString name()
returns the plugin name
void slotAttachSkin()
Called by Qt as the user is trying to connect a mesh to a skeleton.
void slotFrameChanged(int)
Called by the framework when a different frame was selected.
int getFrame()
Gets the current frame number.