Merge pull request #4004 from Atlante45/modeluploader_scripting_interface

Entity upload
This commit is contained in:
Philip Rosedale 2014-12-23 16:58:52 -08:00
commit 0ef26b1446
7 changed files with 245 additions and 201 deletions

View file

@ -3626,16 +3626,6 @@ void Application::setMenuShortcutsEnabled(bool enabled) {
setShortcutsEnabled(_window->menuBar(), enabled); setShortcutsEnabled(_window->menuBar(), enabled);
} }
void Application::uploadModel(ModelType modelType) {
ModelUploader* uploader = new ModelUploader(modelType);
QThread* thread = new QThread();
thread->connect(uploader, SIGNAL(destroyed()), SLOT(quit()));
thread->connect(thread, SIGNAL(finished()), SLOT(deleteLater()));
uploader->connect(thread, SIGNAL(started()), SLOT(send()));
thread->start();
}
void Application::updateWindowTitle(){ void Application::updateWindowTitle(){
QString buildVersion = " (build " + applicationVersion() + ")"; QString buildVersion = " (build " + applicationVersion() + ")";
@ -4191,15 +4181,19 @@ void Application::toggleRunningScriptsWidget() {
} }
void Application::uploadHead() { void Application::uploadHead() {
uploadModel(HEAD_MODEL); ModelUploader::uploadHead();
} }
void Application::uploadSkeleton() { void Application::uploadSkeleton() {
uploadModel(SKELETON_MODEL); ModelUploader::uploadSkeleton();
} }
void Application::uploadAttachment() { void Application::uploadAttachment() {
uploadModel(ATTACHMENT_MODEL); ModelUploader::uploadAttachment();
}
void Application::uploadEntity() {
ModelUploader::uploadEntity();
} }
void Application::openUrl(const QUrl& url) { void Application::openUrl(const QUrl& url) {

View file

@ -374,6 +374,7 @@ public slots:
void uploadHead(); void uploadHead();
void uploadSkeleton(); void uploadSkeleton();
void uploadAttachment(); void uploadAttachment();
void uploadEntity();
void openUrl(const QUrl& url); void openUrl(const QUrl& url);
@ -459,8 +460,6 @@ private:
void setMenuShortcutsEnabled(bool enabled); void setMenuShortcutsEnabled(bool enabled);
void uploadModel(ModelType modelType);
static void attachNewHeadToNode(Node *newNode); static void attachNewHeadToNode(Node *newNode);
static void* networkReceive(void* args); // network receive thread static void* networkReceive(void* args); // network receive thread

View file

@ -189,10 +189,14 @@ Menu::Menu() :
SLOT(toggleAddressBar())); SLOT(toggleAddressBar()));
addDisabledActionAndSeparator(fileMenu, "Upload Avatar Model"); addDisabledActionAndSeparator(fileMenu, "Upload Avatar Model");
addActionToQMenuAndActionHash(fileMenu, MenuOption::UploadHead, 0, Application::getInstance(), SLOT(uploadHead())); addActionToQMenuAndActionHash(fileMenu, MenuOption::UploadHead, 0,
addActionToQMenuAndActionHash(fileMenu, MenuOption::UploadSkeleton, 0, Application::getInstance(), SLOT(uploadSkeleton())); Application::getInstance(), SLOT(uploadHead()));
addActionToQMenuAndActionHash(fileMenu, MenuOption::UploadSkeleton, 0,
Application::getInstance(), SLOT(uploadSkeleton()));
addActionToQMenuAndActionHash(fileMenu, MenuOption::UploadAttachment, 0, addActionToQMenuAndActionHash(fileMenu, MenuOption::UploadAttachment, 0,
Application::getInstance(), SLOT(uploadAttachment())); Application::getInstance(), SLOT(uploadAttachment()));
addActionToQMenuAndActionHash(fileMenu, MenuOption::UploadEntity, 0,
Application::getInstance(), SLOT(uploadEntity()));
addDisabledActionAndSeparator(fileMenu, "Settings"); addDisabledActionAndSeparator(fileMenu, "Settings");
addActionToQMenuAndActionHash(fileMenu, MenuOption::SettingsImport, 0, this, SLOT(importSettings())); addActionToQMenuAndActionHash(fileMenu, MenuOption::SettingsImport, 0, this, SLOT(importSettings()));
addActionToQMenuAndActionHash(fileMenu, MenuOption::SettingsExport, 0, this, SLOT(exportSettings())); addActionToQMenuAndActionHash(fileMenu, MenuOption::SettingsExport, 0, this, SLOT(exportSettings()));

View file

@ -482,6 +482,7 @@ namespace MenuOption {
const QString TransmitterDrive = "Transmitter Drive"; const QString TransmitterDrive = "Transmitter Drive";
const QString TurnWithHead = "Turn using Head"; const QString TurnWithHead = "Turn using Head";
const QString UploadAttachment = "Upload Attachment Model"; const QString UploadAttachment = "Upload Attachment Model";
const QString UploadEntity = "Upload Entity Model";
const QString UploadHead = "Upload Head Model"; const QString UploadHead = "Upload Head Model";
const QString UploadSkeleton = "Upload Skeleton Model"; const QString UploadSkeleton = "Upload Skeleton Model";
const QString UserInterface = "User Interface"; const QString UserInterface = "User Interface";

View file

@ -55,7 +55,8 @@ static const QString MODEL_URL = "/api/v1/models";
static const QString SETTING_NAME = "LastModelUploadLocation"; static const QString SETTING_NAME = "LastModelUploadLocation";
static const int MAX_SIZE = 10 * 1024 * 1024; // 10 MB static const int BYTES_PER_MEGABYTES = 1024 * 1024;
static const unsigned long MAX_SIZE = 50 * 1024 * BYTES_PER_MEGABYTES; // 50 GB (Virtually remove limit)
static const int MAX_TEXTURE_SIZE = 1024; static const int MAX_TEXTURE_SIZE = 1024;
static const int TIMEOUT = 1000; static const int TIMEOUT = 1000;
static const int MAX_CHECK = 30; static const int MAX_CHECK = 30;
@ -63,6 +64,32 @@ static const int MAX_CHECK = 30;
static const int QCOMPRESS_HEADER_POSITION = 0; static const int QCOMPRESS_HEADER_POSITION = 0;
static const int QCOMPRESS_HEADER_SIZE = 4; static const int QCOMPRESS_HEADER_SIZE = 4;
void ModelUploader::uploadModel(ModelType modelType) {
ModelUploader* uploader = new ModelUploader(modelType);
QThread* thread = new QThread();
thread->connect(uploader, SIGNAL(destroyed()), SLOT(quit()));
thread->connect(thread, SIGNAL(finished()), SLOT(deleteLater()));
uploader->connect(thread, SIGNAL(started()), SLOT(send()));
thread->start();
}
void ModelUploader::uploadHead() {
uploadModel(HEAD_MODEL);
}
void ModelUploader::uploadSkeleton() {
uploadModel(SKELETON_MODEL);
}
void ModelUploader::uploadAttachment() {
uploadModel(ATTACHMENT_MODEL);
}
void ModelUploader::uploadEntity() {
uploadModel(ENTITY_MODEL);
}
ModelUploader::ModelUploader(ModelType modelType) : ModelUploader::ModelUploader(ModelType modelType) :
_lodCount(-1), _lodCount(-1),
_texturesCount(-1), _texturesCount(-1),
@ -148,6 +175,91 @@ bool ModelUploader::zip() {
FBXGeometry geometry = readFBX(fbxContents, QVariantHash()); FBXGeometry geometry = readFBX(fbxContents, QVariantHash());
// make sure we have some basic mappings // make sure we have some basic mappings
populateBasicMapping(mapping, filename, geometry);
// open the dialog to configure the rest
ModelPropertiesDialog properties(_modelType, mapping, basePath, geometry);
if (properties.exec() == QDialog::Rejected) {
return false;
}
mapping = properties.getMapping();
QByteArray nameField = mapping.value(NAME_FIELD).toByteArray();
QString urlBase;
if (!nameField.isEmpty()) {
QHttpPart textPart;
textPart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"model_name\"");
textPart.setBody(nameField);
_dataMultiPart->append(textPart);
urlBase = S3_URL + "/models/" + MODEL_TYPE_NAMES[_modelType] + "/" + nameField;
_url = urlBase + ".fst";
} else {
QMessageBox::warning(NULL,
QString("ModelUploader::zip()"),
QString("Model name is missing in the .fst file."),
QMessageBox::Ok);
qDebug() << "[Warning] " << QString("Model name is missing in the .fst file.");
return false;
}
QByteArray texdirField = mapping.value(TEXDIR_FIELD).toByteArray();
QString texDir;
_textureBase = urlBase + "/textures/";
if (!texdirField.isEmpty()) {
texDir = basePath + "/" + texdirField;
QFileInfo texInfo(texDir);
if (!texInfo.exists() || !texInfo.isDir()) {
QMessageBox::warning(NULL,
QString("ModelUploader::zip()"),
QString("Texture directory could not be found."),
QMessageBox::Ok);
qDebug() << "[Warning] " << QString("Texture directory could not be found.");
return false;
}
}
QVariantHash lodField = mapping.value(LOD_FIELD).toHash();
for (QVariantHash::const_iterator it = lodField.constBegin(); it != lodField.constEnd(); it++) {
QFileInfo lod(basePath + "/" + it.key());
if (!lod.exists() || !lod.isFile()) { // Check existence
QMessageBox::warning(NULL,
QString("ModelUploader::zip()"),
QString("LOD file %1 could not be found.").arg(lod.fileName()),
QMessageBox::Ok);
qDebug() << "[Warning] " << QString("FBX file %1 could not be found.").arg(lod.fileName());
}
// Compress and copy
if (!addPart(lod.filePath(), QString("lod%1").arg(++_lodCount))) {
return false;
}
}
// Write out, compress and copy the fst
if (!addPart(*fst, writeMapping(mapping), QString("fst"))) {
return false;
}
// Compress and copy the fbx
if (!addPart(fbx, fbxContents, "fbx")) {
return false;
}
if (!addTextures(texDir, geometry)) {
return false;
}
QHttpPart textPart;
textPart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data;"
" name=\"model_category\"");
textPart.setBody(MODEL_TYPE_NAMES[_modelType]);
_dataMultiPart->append(textPart);
_readyToSend = true;
return true;
}
void ModelUploader::populateBasicMapping(QVariantHash& mapping, QString filename, FBXGeometry geometry) {
if (!mapping.contains(NAME_FIELD)) { if (!mapping.contains(NAME_FIELD)) {
mapping.insert(NAME_FIELD, QFileInfo(filename).baseName()); mapping.insert(NAME_FIELD, QFileInfo(filename).baseName());
} }
@ -162,11 +274,11 @@ bool ModelUploader::zip() {
QVariantHash joints = mapping.value(JOINT_FIELD).toHash(); QVariantHash joints = mapping.value(JOINT_FIELD).toHash();
if (!joints.contains("jointEyeLeft")) { if (!joints.contains("jointEyeLeft")) {
joints.insert("jointEyeLeft", geometry.jointIndices.contains("jointEyeLeft") ? "jointEyeLeft" : joints.insert("jointEyeLeft", geometry.jointIndices.contains("jointEyeLeft") ? "jointEyeLeft" :
(geometry.jointIndices.contains("EyeLeft") ? "EyeLeft" : "LeftEye")); (geometry.jointIndices.contains("EyeLeft") ? "EyeLeft" : "LeftEye"));
} }
if (!joints.contains("jointEyeRight")) { if (!joints.contains("jointEyeRight")) {
joints.insert("jointEyeRight", geometry.jointIndices.contains("jointEyeRight") ? "jointEyeRight" : joints.insert("jointEyeRight", geometry.jointIndices.contains("jointEyeRight") ? "jointEyeRight" :
geometry.jointIndices.contains("EyeRight") ? "EyeRight" : "RightEye"); geometry.jointIndices.contains("EyeRight") ? "EyeRight" : "RightEye");
} }
if (!joints.contains("jointNeck")) { if (!joints.contains("jointNeck")) {
joints.insert("jointNeck", geometry.jointIndices.contains("jointNeck") ? "jointNeck" : "Neck"); joints.insert("jointNeck", geometry.jointIndices.contains("jointNeck") ? "jointNeck" : "Neck");
@ -250,87 +362,6 @@ bool ModelUploader::zip() {
blendshapes.insertMulti("Sneer", QVariantList() << "Squint_Right" << 0.5); blendshapes.insertMulti("Sneer", QVariantList() << "Squint_Right" << 0.5);
mapping.insert(BLENDSHAPE_FIELD, blendshapes); mapping.insert(BLENDSHAPE_FIELD, blendshapes);
} }
// open the dialog to configure the rest
ModelPropertiesDialog properties(_modelType, mapping, basePath, geometry);
if (properties.exec() == QDialog::Rejected) {
return false;
}
mapping = properties.getMapping();
QByteArray nameField = mapping.value(NAME_FIELD).toByteArray();
QString urlBase;
if (!nameField.isEmpty()) {
QHttpPart textPart;
textPart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"model_name\"");
textPart.setBody(nameField);
_dataMultiPart->append(textPart);
urlBase = S3_URL + "/models/" + MODEL_TYPE_NAMES[_modelType] + "/" + nameField;
_url = urlBase + ".fst";
} else {
QMessageBox::warning(NULL,
QString("ModelUploader::zip()"),
QString("Model name is missing in the .fst file."),
QMessageBox::Ok);
qDebug() << "[Warning] " << QString("Model name is missing in the .fst file.");
return false;
}
QByteArray texdirField = mapping.value(TEXDIR_FIELD).toByteArray();
QString texDir;
_textureBase = urlBase + "/textures/";
if (!texdirField.isEmpty()) {
texDir = basePath + "/" + texdirField;
QFileInfo texInfo(texDir);
if (!texInfo.exists() || !texInfo.isDir()) {
QMessageBox::warning(NULL,
QString("ModelUploader::zip()"),
QString("Texture directory could not be found."),
QMessageBox::Ok);
qDebug() << "[Warning] " << QString("Texture directory could not be found.");
return false;
}
}
QVariantHash lodField = mapping.value(LOD_FIELD).toHash();
for (QVariantHash::const_iterator it = lodField.constBegin(); it != lodField.constEnd(); it++) {
QFileInfo lod(basePath + "/" + it.key());
if (!lod.exists() || !lod.isFile()) { // Check existence
QMessageBox::warning(NULL,
QString("ModelUploader::zip()"),
QString("LOD file %1 could not be found.").arg(lod.fileName()),
QMessageBox::Ok);
qDebug() << "[Warning] " << QString("FBX file %1 could not be found.").arg(lod.fileName());
}
// Compress and copy
if (!addPart(lod.filePath(), QString("lod%1").arg(++_lodCount))) {
return false;
}
}
// Write out, compress and copy the fst
if (!addPart(*fst, writeMapping(mapping), QString("fst"))) {
return false;
}
// Compress and copy the fbx
if (!addPart(fbx, fbxContents, "fbx")) {
return false;
}
if (!addTextures(texDir, geometry)) {
return false;
}
QHttpPart textPart;
textPart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data;"
" name=\"model_category\"");
textPart.setBody(MODEL_TYPE_NAMES[_modelType]);
_dataMultiPart->append(textPart);
_readyToSend = true;
return true;
} }
void ModelUploader::send() { void ModelUploader::send() {
@ -590,9 +621,9 @@ bool ModelUploader::addPart(const QFile& file, const QByteArray& contents, const
if (_totalSize > MAX_SIZE) { if (_totalSize > MAX_SIZE) {
QMessageBox::warning(NULL, QMessageBox::warning(NULL,
QString("ModelUploader::zip()"), QString("ModelUploader::zip()"),
QString("Model too big, over %1 Bytes.").arg(MAX_SIZE), QString("Model too big, over %1 MB.").arg(MAX_SIZE / BYTES_PER_MEGABYTES),
QMessageBox::Ok); QMessageBox::Ok);
qDebug() << "[Warning] " << QString("Model too big, over %1 Bytes.").arg(MAX_SIZE); qDebug() << "[Warning] " << QString("Model too big, over %1 MB.").arg(MAX_SIZE / BYTES_PER_MEGABYTES);
return false; return false;
} }
qDebug() << "Current model size: " << _totalSize; qDebug() << "Current model size: " << _totalSize;
@ -613,8 +644,8 @@ ModelPropertiesDialog::ModelPropertiesDialog(ModelType modelType, const QVariant
_modelType(modelType), _modelType(modelType),
_originalMapping(originalMapping), _originalMapping(originalMapping),
_basePath(basePath), _basePath(basePath),
_geometry(geometry) { _geometry(geometry)
{
setWindowTitle("Set Model Properties"); setWindowTitle("Set Model Properties");
QFormLayout* form = new QFormLayout(); QFormLayout* form = new QFormLayout();
@ -629,33 +660,35 @@ ModelPropertiesDialog::ModelPropertiesDialog(ModelType modelType, const QVariant
_scale->setMaximum(FLT_MAX); _scale->setMaximum(FLT_MAX);
_scale->setSingleStep(0.01); _scale->setSingleStep(0.01);
if (_modelType == ATTACHMENT_MODEL) { if (_modelType != ENTITY_MODEL) {
QHBoxLayout* translation = new QHBoxLayout(); if (_modelType == ATTACHMENT_MODEL) {
form->addRow("Translation:", translation); QHBoxLayout* translation = new QHBoxLayout();
translation->addWidget(_translationX = createTranslationBox()); form->addRow("Translation:", translation);
translation->addWidget(_translationY = createTranslationBox()); translation->addWidget(_translationX = createTranslationBox());
translation->addWidget(_translationZ = createTranslationBox()); translation->addWidget(_translationY = createTranslationBox());
form->addRow("Pivot About Center:", _pivotAboutCenter = new QCheckBox()); translation->addWidget(_translationZ = createTranslationBox());
form->addRow("Pivot Joint:", _pivotJoint = createJointBox()); form->addRow("Pivot About Center:", _pivotAboutCenter = new QCheckBox());
connect(_pivotAboutCenter, SIGNAL(toggled(bool)), SLOT(updatePivotJoint())); form->addRow("Pivot Joint:", _pivotJoint = createJointBox());
_pivotAboutCenter->setChecked(true); connect(_pivotAboutCenter, SIGNAL(toggled(bool)), SLOT(updatePivotJoint()));
_pivotAboutCenter->setChecked(true);
} else {
form->addRow("Left Eye Joint:", _leftEyeJoint = createJointBox()); } else {
form->addRow("Right Eye Joint:", _rightEyeJoint = createJointBox()); form->addRow("Left Eye Joint:", _leftEyeJoint = createJointBox());
form->addRow("Neck Joint:", _neckJoint = createJointBox()); form->addRow("Right Eye Joint:", _rightEyeJoint = createJointBox());
} form->addRow("Neck Joint:", _neckJoint = createJointBox());
if (_modelType == SKELETON_MODEL) { }
form->addRow("Root Joint:", _rootJoint = createJointBox()); if (_modelType == SKELETON_MODEL) {
form->addRow("Lean Joint:", _leanJoint = createJointBox()); form->addRow("Root Joint:", _rootJoint = createJointBox());
form->addRow("Head Joint:", _headJoint = createJointBox()); form->addRow("Lean Joint:", _leanJoint = createJointBox());
form->addRow("Left Hand Joint:", _leftHandJoint = createJointBox()); form->addRow("Head Joint:", _headJoint = createJointBox());
form->addRow("Right Hand Joint:", _rightHandJoint = createJointBox()); form->addRow("Left Hand Joint:", _leftHandJoint = createJointBox());
form->addRow("Right Hand Joint:", _rightHandJoint = createJointBox());
form->addRow("Free Joints:", _freeJoints = new QVBoxLayout());
QPushButton* newFreeJoint = new QPushButton("New Free Joint"); form->addRow("Free Joints:", _freeJoints = new QVBoxLayout());
_freeJoints->addWidget(newFreeJoint); QPushButton* newFreeJoint = new QPushButton("New Free Joint");
connect(newFreeJoint, SIGNAL(clicked(bool)), SLOT(createNewFreeJoint())); _freeJoints->addWidget(newFreeJoint);
connect(newFreeJoint, SIGNAL(clicked(bool)), SLOT(createNewFreeJoint()));
}
} }
QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok |
@ -683,38 +716,40 @@ QVariantHash ModelPropertiesDialog::getMapping() const {
} }
mapping.insert(JOINT_INDEX_FIELD, jointIndices); mapping.insert(JOINT_INDEX_FIELD, jointIndices);
QVariantHash joints = mapping.value(JOINT_FIELD).toHash(); if (_modelType != ENTITY_MODEL) {
if (_modelType == ATTACHMENT_MODEL) { QVariantHash joints = mapping.value(JOINT_FIELD).toHash();
glm::vec3 pivot; if (_modelType == ATTACHMENT_MODEL) {
if (_pivotAboutCenter->isChecked()) { glm::vec3 pivot;
pivot = (_geometry.meshExtents.minimum + _geometry.meshExtents.maximum) * 0.5f; if (_pivotAboutCenter->isChecked()) {
pivot = (_geometry.meshExtents.minimum + _geometry.meshExtents.maximum) * 0.5f;
} else if (_pivotJoint->currentIndex() != 0) {
pivot = extractTranslation(_geometry.joints.at(_pivotJoint->currentIndex() - 1).transform); } else if (_pivotJoint->currentIndex() != 0) {
pivot = extractTranslation(_geometry.joints.at(_pivotJoint->currentIndex() - 1).transform);
}
mapping.insert(TRANSLATION_X_FIELD, -pivot.x * _scale->value() + _translationX->value());
mapping.insert(TRANSLATION_Y_FIELD, -pivot.y * _scale->value() + _translationY->value());
mapping.insert(TRANSLATION_Z_FIELD, -pivot.z * _scale->value() + _translationZ->value());
} else {
insertJointMapping(joints, "jointEyeLeft", _leftEyeJoint->currentText());
insertJointMapping(joints, "jointEyeRight", _rightEyeJoint->currentText());
insertJointMapping(joints, "jointNeck", _neckJoint->currentText());
} }
mapping.insert(TRANSLATION_X_FIELD, -pivot.x * _scale->value() + _translationX->value()); if (_modelType == SKELETON_MODEL) {
mapping.insert(TRANSLATION_Y_FIELD, -pivot.y * _scale->value() + _translationY->value()); insertJointMapping(joints, "jointRoot", _rootJoint->currentText());
mapping.insert(TRANSLATION_Z_FIELD, -pivot.z * _scale->value() + _translationZ->value()); insertJointMapping(joints, "jointLean", _leanJoint->currentText());
insertJointMapping(joints, "jointHead", _headJoint->currentText());
} else { insertJointMapping(joints, "jointLeftHand", _leftHandJoint->currentText());
insertJointMapping(joints, "jointEyeLeft", _leftEyeJoint->currentText()); insertJointMapping(joints, "jointRightHand", _rightHandJoint->currentText());
insertJointMapping(joints, "jointEyeRight", _rightEyeJoint->currentText());
insertJointMapping(joints, "jointNeck", _neckJoint->currentText()); mapping.remove(FREE_JOINT_FIELD);
} for (int i = 0; i < _freeJoints->count() - 1; i++) {
if (_modelType == SKELETON_MODEL) { QComboBox* box = static_cast<QComboBox*>(_freeJoints->itemAt(i)->widget()->layout()->itemAt(0)->widget());
insertJointMapping(joints, "jointRoot", _rootJoint->currentText()); mapping.insertMulti(FREE_JOINT_FIELD, box->currentText());
insertJointMapping(joints, "jointLean", _leanJoint->currentText()); }
insertJointMapping(joints, "jointHead", _headJoint->currentText());
insertJointMapping(joints, "jointLeftHand", _leftHandJoint->currentText());
insertJointMapping(joints, "jointRightHand", _rightHandJoint->currentText());
mapping.remove(FREE_JOINT_FIELD);
for (int i = 0; i < _freeJoints->count() - 1; i++) {
QComboBox* box = static_cast<QComboBox*>(_freeJoints->itemAt(i)->widget()->layout()->itemAt(0)->widget());
mapping.insertMulti(FREE_JOINT_FIELD, box->currentText());
} }
mapping.insert(JOINT_FIELD, joints);
} }
mapping.insert(JOINT_FIELD, joints);
return mapping; return mapping;
} }
@ -729,32 +764,35 @@ void ModelPropertiesDialog::reset() {
_scale->setValue(_originalMapping.value(SCALE_FIELD).toDouble()); _scale->setValue(_originalMapping.value(SCALE_FIELD).toDouble());
QVariantHash jointHash = _originalMapping.value(JOINT_FIELD).toHash(); QVariantHash jointHash = _originalMapping.value(JOINT_FIELD).toHash();
if (_modelType == ATTACHMENT_MODEL) {
_translationX->setValue(_originalMapping.value(TRANSLATION_X_FIELD).toDouble()); if (_modelType != ENTITY_MODEL) {
_translationY->setValue(_originalMapping.value(TRANSLATION_Y_FIELD).toDouble()); if (_modelType == ATTACHMENT_MODEL) {
_translationZ->setValue(_originalMapping.value(TRANSLATION_Z_FIELD).toDouble()); _translationX->setValue(_originalMapping.value(TRANSLATION_X_FIELD).toDouble());
_pivotAboutCenter->setChecked(true); _translationY->setValue(_originalMapping.value(TRANSLATION_Y_FIELD).toDouble());
_pivotJoint->setCurrentIndex(0); _translationZ->setValue(_originalMapping.value(TRANSLATION_Z_FIELD).toDouble());
_pivotAboutCenter->setChecked(true);
} else { _pivotJoint->setCurrentIndex(0);
setJointText(_leftEyeJoint, jointHash.value("jointEyeLeft").toString());
setJointText(_rightEyeJoint, jointHash.value("jointEyeRight").toString()); } else {
setJointText(_neckJoint, jointHash.value("jointNeck").toString()); setJointText(_leftEyeJoint, jointHash.value("jointEyeLeft").toString());
} setJointText(_rightEyeJoint, jointHash.value("jointEyeRight").toString());
if (_modelType == SKELETON_MODEL) { setJointText(_neckJoint, jointHash.value("jointNeck").toString());
setJointText(_rootJoint, jointHash.value("jointRoot").toString());
setJointText(_leanJoint, jointHash.value("jointLean").toString());
setJointText(_headJoint, jointHash.value("jointHead").toString());
setJointText(_leftHandJoint, jointHash.value("jointLeftHand").toString());
setJointText(_rightHandJoint, jointHash.value("jointRightHand").toString());
while (_freeJoints->count() > 1) {
delete _freeJoints->itemAt(0)->widget();
} }
foreach (const QVariant& joint, _originalMapping.values(FREE_JOINT_FIELD)) { if (_modelType == SKELETON_MODEL) {
QString jointName = joint.toString(); setJointText(_rootJoint, jointHash.value("jointRoot").toString());
if (_geometry.jointIndices.contains(jointName)) { setJointText(_leanJoint, jointHash.value("jointLean").toString());
createNewFreeJoint(jointName); setJointText(_headJoint, jointHash.value("jointHead").toString());
setJointText(_leftHandJoint, jointHash.value("jointLeftHand").toString());
setJointText(_rightHandJoint, jointHash.value("jointRightHand").toString());
while (_freeJoints->count() > 1) {
delete _freeJoints->itemAt(0)->widget();
}
foreach (const QVariant& joint, _originalMapping.values(FREE_JOINT_FIELD)) {
QString jointName = joint.toString();
if (_geometry.jointIndices.contains(jointName)) {
createNewFreeJoint(jointName);
}
} }
} }
} }

View file

@ -33,13 +33,15 @@ class ModelUploader : public QObject {
Q_OBJECT Q_OBJECT
public: public:
ModelUploader(ModelType type); static void uploadModel(ModelType modelType);
~ModelUploader();
public slots: static void uploadHead();
void send(); static void uploadSkeleton();
static void uploadAttachment();
static void uploadEntity();
private slots: private slots:
void send();
void checkJSON(QNetworkReply& requestReply); void checkJSON(QNetworkReply& requestReply);
void uploadUpdate(qint64 bytesSent, qint64 bytesTotal); void uploadUpdate(qint64 bytesSent, qint64 bytesTotal);
void uploadSuccess(QNetworkReply& requestReply); void uploadSuccess(QNetworkReply& requestReply);
@ -48,12 +50,21 @@ private slots:
void processCheck(); void processCheck();
private: private:
ModelUploader(ModelType type);
~ModelUploader();
void populateBasicMapping(QVariantHash& mapping, QString filename, FBXGeometry geometry);
bool zip();
bool addTextures(const QString& texdir, const FBXGeometry& geometry);
bool addPart(const QString& path, const QString& name, bool isTexture = false);
bool addPart(const QFile& file, const QByteArray& contents, const QString& name, bool isTexture = false);
QString _url; QString _url;
QString _textureBase; QString _textureBase;
QSet<QByteArray> _textureFilenames; QSet<QByteArray> _textureFilenames;
int _lodCount; int _lodCount;
int _texturesCount; int _texturesCount;
int _totalSize; unsigned long _totalSize;
ModelType _modelType; ModelType _modelType;
bool _readyToSend; bool _readyToSend;
@ -64,12 +75,6 @@ private:
QDialog* _progressDialog; QDialog* _progressDialog;
QProgressBar* _progressBar; QProgressBar* _progressBar;
bool zip();
bool addTextures(const QString& texdir, const FBXGeometry& geometry);
bool addPart(const QString& path, const QString& name, bool isTexture = false);
bool addPart(const QFile& file, const QByteArray& contents, const QString& name, bool isTexture = false);
}; };
/// A dialog that allows customization of various model properties. /// A dialog that allows customization of various model properties.

View file

@ -12,16 +12,19 @@
#include <QDialog> #include <QDialog>
#include <QDialogButtonBox> #include <QDialogButtonBox>
#include <QGridLayout> #include <QGridLayout>
#include <QFileInfo>
#include <QHeaderView> #include <QHeaderView>
#include <QLineEdit>
#include <QMessageBox> #include <QMessageBox>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QThread>
#include <QUrl> #include <QUrl>
#include <qurlquery.h> #include <QUrlQuery>
#include <QXmlStreamReader> #include <QXmlStreamReader>
#include <NetworkAccessManager.h> #include <NetworkAccessManager.h>
#include "Application.h"
#include "ModelsBrowser.h" #include "ModelsBrowser.h"
const char* MODEL_TYPE_NAMES[] = { "entities", "heads", "skeletons", "attachments" }; const char* MODEL_TYPE_NAMES[] = { "entities", "heads", "skeletons", "attachments" };