mirror of
https://github.com/overte-org/overte.git
synced 2025-07-24 23:55:14 +02:00
Merge pull request #4384 from ctrlaltdavid/20369
CR for Job #20369 - Uploaded avatars without skeletons crash Interface
This commit is contained in:
commit
e2a367607a
6 changed files with 57 additions and 3 deletions
|
@ -490,6 +490,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
||||||
connect(nodeList.data(), SIGNAL(dataReceived(const quint8, const int)),
|
connect(nodeList.data(), SIGNAL(dataReceived(const quint8, const int)),
|
||||||
bandwidthRecorder.data(), SLOT(updateInboundData(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...
|
// check first run...
|
||||||
if (_firstRun.get()) {
|
if (_firstRun.get()) {
|
||||||
qDebug() << "This is a first run...";
|
qDebug() << "This is a first run...";
|
||||||
|
@ -4044,3 +4047,19 @@ void Application::notifyPacketVersionMismatch() {
|
||||||
msgBox.exec();
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -585,6 +585,8 @@ private:
|
||||||
QTimer _settingsTimer;
|
QTimer _settingsTimer;
|
||||||
|
|
||||||
GLCanvas* _glWidget = new GLCanvas(); // our GLCanvas has a couple extra features
|
GLCanvas* _glWidget = new GLCanvas(); // our GLCanvas has a couple extra features
|
||||||
|
|
||||||
|
void checkSkeleton();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_Application_h
|
#endif // hifi_Application_h
|
||||||
|
|
|
@ -177,6 +177,22 @@ bool ModelUploader::zip() {
|
||||||
}
|
}
|
||||||
QByteArray fbxContents = fbx.readAll();
|
QByteArray fbxContents = fbx.readAll();
|
||||||
FBXGeometry geometry = readFBX(fbxContents, QVariantHash());
|
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
|
// make sure we have some basic mappings
|
||||||
populateBasicMapping(mapping, filename, geometry);
|
populateBasicMapping(mapping, filename, geometry);
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QBuffer>
|
#include <QBuffer>
|
||||||
|
|
||||||
#include <glm/gtx/norm.hpp>
|
#include <glm/gtx/norm.hpp>
|
||||||
|
@ -195,6 +194,12 @@ void MyAvatar::simulate(float deltaTime) {
|
||||||
PerformanceTimer perfTimer("skeleton");
|
PerformanceTimer perfTimer("skeleton");
|
||||||
_skeletonModel.simulate(deltaTime);
|
_skeletonModel.simulate(deltaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!_skeletonModel.hasSkeleton()) {
|
||||||
|
// All the simulation that can be done has been done
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("attachments");
|
PerformanceTimer perfTimer("attachments");
|
||||||
simulateAttachments(deltaTime);
|
simulateAttachments(deltaTime);
|
||||||
|
|
|
@ -81,6 +81,8 @@ void SkeletonModel::setJointStates(QVector<JointState> states) {
|
||||||
if (_enableShapes) {
|
if (_enableShapes) {
|
||||||
buildShapes();
|
buildShapes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emit skeletonLoaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
const float PALM_PRIORITY = DEFAULT_PRIORITY;
|
const float PALM_PRIORITY = DEFAULT_PRIORITY;
|
||||||
|
@ -721,7 +723,8 @@ void SkeletonModel::buildShapes() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1006,3 +1009,6 @@ void SkeletonModel::renderJointCollisionShapes(float alpha) {
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SkeletonModel::hasSkeleton() {
|
||||||
|
return isActive() ? _geometry->getFBXGeometry().rootJointIndex != -1 : false;
|
||||||
|
}
|
||||||
|
|
|
@ -123,7 +123,13 @@ public:
|
||||||
void resetShapePositionsToDefaultPose(); // DEBUG method
|
void resetShapePositionsToDefaultPose(); // DEBUG method
|
||||||
|
|
||||||
void renderRagdoll();
|
void renderRagdoll();
|
||||||
|
|
||||||
|
bool hasSkeleton();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
void skeletonLoaded();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void buildShapes();
|
void buildShapes();
|
||||||
|
|
Loading…
Reference in a new issue