diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 24316f5088..7addc27b3b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -490,6 +490,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : connect(nodeList.data(), SIGNAL(dataReceived(const quint8, const int)), bandwidthRecorder.data(), SLOT(updateInboundData(const quint8, const int))); + connect(&_myAvatar->getSkeletonModel(), &SkeletonModel::skeletonLoaded, + this, &Application::checkSkeleton, Qt::QueuedConnection); + // check first run... if (_firstRun.get()) { qDebug() << "This is a first run..."; @@ -4044,3 +4047,19 @@ void Application::notifyPacketVersionMismatch() { msgBox.exec(); } } + +void Application::checkSkeleton() { + if (_myAvatar->getSkeletonModel().isActive() && !_myAvatar->getSkeletonModel().hasSkeleton()) { + qDebug() << "MyAvatar model has no skeleton"; + + QString message = "Your selected avatar body has no skeleton.\n\nThe default body will be loaded..."; + QMessageBox msgBox; + msgBox.setText(message); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setIcon(QMessageBox::Warning); + msgBox.exec(); + + _myAvatar->setSkeletonModelURL(DEFAULT_BODY_MODEL_URL); + _myAvatar->sendIdentityPacket(); + } +} diff --git a/interface/src/Application.h b/interface/src/Application.h index 73a3f1658b..ce4bae45b9 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -585,6 +585,8 @@ private: QTimer _settingsTimer; GLCanvas* _glWidget = new GLCanvas(); // our GLCanvas has a couple extra features + + void checkSkeleton(); }; #endif // hifi_Application_h diff --git a/interface/src/ModelUploader.cpp b/interface/src/ModelUploader.cpp index a2b729ad39..bd8540a892 100644 --- a/interface/src/ModelUploader.cpp +++ b/interface/src/ModelUploader.cpp @@ -177,6 +177,22 @@ bool ModelUploader::zip() { } QByteArray fbxContents = fbx.readAll(); FBXGeometry geometry = readFBX(fbxContents, QVariantHash()); + + // Make sure that a skeleton model has a skeleton + if (_modelType == SKELETON_MODEL) { + if (geometry.rootJointIndex == -1) { + + QString message = "Your selected skeleton model has no skeleton.\n\nThe upload will be canceled."; + QMessageBox msgBox; + msgBox.setWindowTitle("Model Upload"); + msgBox.setText(message); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setIcon(QMessageBox::Warning); + msgBox.exec(); + + return false; + } + } // make sure we have some basic mappings populateBasicMapping(mapping, filename, geometry); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 9c83942439..c2a957dc72 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -12,7 +12,6 @@ #include #include -#include #include #include @@ -195,6 +194,12 @@ void MyAvatar::simulate(float deltaTime) { PerformanceTimer perfTimer("skeleton"); _skeletonModel.simulate(deltaTime); } + + if (!_skeletonModel.hasSkeleton()) { + // All the simulation that can be done has been done + return; + } + { PerformanceTimer perfTimer("attachments"); simulateAttachments(deltaTime); diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index fa9846fd7d..fbb622b30a 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -81,6 +81,8 @@ void SkeletonModel::setJointStates(QVector states) { if (_enableShapes) { buildShapes(); } + + emit skeletonLoaded(); } const float PALM_PRIORITY = DEFAULT_PRIORITY; @@ -721,7 +723,8 @@ void SkeletonModel::buildShapes() { } const FBXGeometry& geometry = _geometry->getFBXGeometry(); - if (geometry.joints.isEmpty()) { + if (geometry.joints.isEmpty() || geometry.rootJointIndex == -1) { + // rootJointIndex == -1 if the avatar model has no skeleton return; } @@ -1006,3 +1009,6 @@ void SkeletonModel::renderJointCollisionShapes(float alpha) { glPopMatrix(); } +bool SkeletonModel::hasSkeleton() { + return isActive() ? _geometry->getFBXGeometry().rootJointIndex != -1 : false; +} diff --git a/interface/src/avatar/SkeletonModel.h b/interface/src/avatar/SkeletonModel.h index d28d1a8aef..74d0ed0324 100644 --- a/interface/src/avatar/SkeletonModel.h +++ b/interface/src/avatar/SkeletonModel.h @@ -123,7 +123,13 @@ public: void resetShapePositionsToDefaultPose(); // DEBUG method void renderRagdoll(); - + + bool hasSkeleton(); + +signals: + + void skeletonLoaded(); + protected: void buildShapes();