Working on allowing attachment models to be uploaded.

This commit is contained in:
Andrzej Kapolka 2014-05-04 15:23:31 -07:00
parent adb301bfe3
commit e0400dbd9c
11 changed files with 79 additions and 57 deletions

View file

@ -63,11 +63,11 @@
#include <UUID.h>
#include <OctreeSceneStats.h>
#include <LocalVoxelsList.h>
#include <ModelUploader.h>
#include "Application.h"
#include "InterfaceVersion.h"
#include "Menu.h"
#include "ModelUploader.h"
#include "Util.h"
#include "devices/OculusManager.h"
#include "devices/TV3DManager.h"
@ -3090,6 +3090,16 @@ void Application::setMenuShortcutsEnabled(bool 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(){
QString buildVersion = " (build " + applicationVersion() + ")";
@ -3417,22 +3427,16 @@ void Application::toggleRunningScriptsWidget() {
}
}
void Application::uploadFST(bool isHead) {
ModelUploader* uploader = new ModelUploader(isHead);
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::uploadHead() {
uploadFST(true);
uploadModel(HEAD_MODEL);
}
void Application::uploadSkeleton() {
uploadFST(false);
uploadModel(SKELETON_MODEL);
}
void Application::uploadAttachment() {
uploadModel(ATTACHMENT_MODEL);
}
ScriptEngine* Application::loadScript(const QString& scriptName, bool loadScriptFromEditor) {

View file

@ -71,6 +71,7 @@
#include "scripting/ControllerScriptingInterface.h"
#include "ui/BandwidthDialog.h"
#include "ui/BandwidthMeter.h"
#include "ui/ModelsBrowser.h"
#include "ui/OctreeStatsDialog.h"
#include "ui/RearMirrorTools.h"
#include "ui/LodToolsDialog.h"
@ -295,9 +296,9 @@ public slots:
void reloadAllScripts();
void toggleRunningScriptsWidget();
void uploadFST(bool isHead);
void uploadHead();
void uploadSkeleton();
void uploadAttachment();
void bumpSettings() { ++_numChangedSettings; }
@ -375,13 +376,11 @@ private:
void setMenuShortcutsEnabled(bool enabled);
void uploadModel(ModelType modelType);
static void attachNewHeadToNode(Node *newNode);
static void* networkReceive(void* args); // network receive thread
void findAxisAlignment();
void displayRearMirrorTools();
MainWindow* _window;
GLCanvas* _glWidget; // our GLCanvas has a couple extra features

View file

@ -157,6 +157,8 @@ Menu::Menu() :
addDisabledActionAndSeparator(fileMenu, "Upload Avatar Model");
addActionToQMenuAndActionHash(fileMenu, MenuOption::UploadHead, 0, Application::getInstance(), SLOT(uploadHead()));
addActionToQMenuAndActionHash(fileMenu, MenuOption::UploadSkeleton, 0, Application::getInstance(), SLOT(uploadSkeleton()));
addActionToQMenuAndActionHash(fileMenu, MenuOption::UploadAttachment, 0,
Application::getInstance(), SLOT(uploadAttachment()));
addDisabledActionAndSeparator(fileMenu, "Settings");
addActionToQMenuAndActionHash(fileMenu, MenuOption::SettingsImport, 0, this, SLOT(importSettings()));
addActionToQMenuAndActionHash(fileMenu, MenuOption::SettingsExport, 0, this, SLOT(exportSettings()));

View file

@ -363,6 +363,7 @@ namespace MenuOption {
const QString TestPing = "Test Ping";
const QString TransmitterDrive = "Transmitter Drive";
const QString TurnWithHead = "Turn using Head";
const QString UploadAttachment = "Upload Attachment Model";
const QString UploadHead = "Upload Head Model";
const QString UploadSkeleton = "Upload Skeleton Model";
const QString Visage = "Visage";

View file

@ -59,11 +59,11 @@ static const int MAX_CHECK = 30;
static const int QCOMPRESS_HEADER_POSITION = 0;
static const int QCOMPRESS_HEADER_SIZE = 4;
ModelUploader::ModelUploader(bool isHead) :
ModelUploader::ModelUploader(ModelType modelType) :
_lodCount(-1),
_texturesCount(-1),
_totalSize(0),
_isHead(isHead),
_modelType(modelType),
_readyToSend(false),
_dataMultiPart(new QHttpMultiPart(QHttpMultiPart::FormDataType)),
_numberOfChecks(MAX_CHECK)
@ -190,7 +190,7 @@ bool ModelUploader::zip() {
}
// open the dialog to configure the rest
ModelPropertiesDialog properties(_isHead, mapping, basePath, geometry);
ModelPropertiesDialog properties(_modelType, mapping, basePath, geometry);
if (properties.exec() == QDialog::Rejected) {
return false;
}
@ -202,7 +202,7 @@ bool ModelUploader::zip() {
textPart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"model_name\"");
textPart.setBody(nameField);
_dataMultiPart->append(textPart);
_url = S3_URL + ((_isHead)? "/models/heads/" : "/models/skeletons/") + nameField + ".fst";
_url = S3_URL + "/models/" + MODEL_TYPE_NAMES[_modelType] + "/" + nameField + ".fst";
} else {
QMessageBox::warning(NULL,
QString("ModelUploader::zip()"),
@ -260,11 +260,7 @@ bool ModelUploader::zip() {
QHttpPart textPart;
textPart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data;"
" name=\"model_category\"");
if (_isHead) {
textPart.setBody("heads");
} else {
textPart.setBody("skeletons");
}
textPart.setBody(MODEL_TYPE_NAMES[_modelType]);
_dataMultiPart->append(textPart);
_readyToSend = true;
@ -510,9 +506,9 @@ bool ModelUploader::addPart(const QFile& file, const QByteArray& contents, const
return true;
}
ModelPropertiesDialog::ModelPropertiesDialog(bool isHead, const QVariantHash& originalMapping,
ModelPropertiesDialog::ModelPropertiesDialog(ModelType modelType, const QVariantHash& originalMapping,
const QString& basePath, const FBXGeometry& geometry) :
_isHead(isHead),
_modelType(modelType),
_originalMapping(originalMapping),
_basePath(basePath),
_geometry(geometry) {
@ -531,10 +527,12 @@ ModelPropertiesDialog::ModelPropertiesDialog(bool isHead, const QVariantHash& or
_scale->setMaximum(FLT_MAX);
_scale->setSingleStep(0.01);
form->addRow("Left Eye Joint:", _leftEyeJoint = createJointBox());
form->addRow("Right Eye Joint:", _rightEyeJoint = createJointBox());
form->addRow("Neck Joint:", _neckJoint = createJointBox());
if (!isHead) {
if (_modelType != ATTACHMENT_MODEL) {
form->addRow("Left Eye Joint:", _leftEyeJoint = createJointBox());
form->addRow("Right Eye Joint:", _rightEyeJoint = createJointBox());
form->addRow("Neck Joint:", _neckJoint = createJointBox());
}
if (_modelType == SKELETON_MODEL) {
form->addRow("Root Joint:", _rootJoint = createJointBox());
form->addRow("Lean Joint:", _leanJoint = createJointBox());
form->addRow("Head Joint:", _headJoint = createJointBox());
@ -573,10 +571,12 @@ QVariantHash ModelPropertiesDialog::getMapping() const {
mapping.insert(JOINT_INDEX_FIELD, jointIndices);
QVariantHash joints = mapping.value(JOINT_FIELD).toHash();
insertJointMapping(joints, "jointEyeLeft", _leftEyeJoint->currentText());
insertJointMapping(joints, "jointEyeRight", _rightEyeJoint->currentText());
insertJointMapping(joints, "jointNeck", _neckJoint->currentText());
if (!_isHead) {
if (_modelType != ATTACHMENT_MODEL) {
insertJointMapping(joints, "jointEyeLeft", _leftEyeJoint->currentText());
insertJointMapping(joints, "jointEyeRight", _rightEyeJoint->currentText());
insertJointMapping(joints, "jointNeck", _neckJoint->currentText());
}
if (_modelType == SKELETON_MODEL) {
insertJointMapping(joints, "jointRoot", _rootJoint->currentText());
insertJointMapping(joints, "jointLean", _leanJoint->currentText());
insertJointMapping(joints, "jointHead", _headJoint->currentText());
@ -604,10 +604,12 @@ void ModelPropertiesDialog::reset() {
_scale->setValue(_originalMapping.value(SCALE_FIELD).toDouble());
QVariantHash jointHash = _originalMapping.value(JOINT_FIELD).toHash();
setJointText(_leftEyeJoint, jointHash.value("jointEyeLeft").toString());
setJointText(_rightEyeJoint, jointHash.value("jointEyeRight").toString());
setJointText(_neckJoint, jointHash.value("jointNeck").toString());
if (!_isHead) {
if (_modelType != ATTACHMENT_MODEL) {
setJointText(_leftEyeJoint, jointHash.value("jointEyeLeft").toString());
setJointText(_rightEyeJoint, jointHash.value("jointEyeRight").toString());
setJointText(_neckJoint, jointHash.value("jointNeck").toString());
}
if (_modelType == SKELETON_MODEL) {
setJointText(_rootJoint, jointHash.value("jointRoot").toString());
setJointText(_leanJoint, jointHash.value("jointLean").toString());
setJointText(_headJoint, jointHash.value("jointHead").toString());

View file

@ -17,6 +17,8 @@
#include <FBXReader.h>
#include "ui/ModelsBrowser.h"
class QComboBox;
class QDoubleSpinBox;
class QFileInfo;
@ -30,7 +32,7 @@ class ModelUploader : public QObject {
Q_OBJECT
public:
ModelUploader(bool isHead);
ModelUploader(ModelType type);
~ModelUploader();
public slots:
@ -49,7 +51,7 @@ private:
int _lodCount;
int _texturesCount;
int _totalSize;
bool _isHead;
ModelType _modelType;
bool _readyToSend;
QHttpMultiPart* _dataMultiPart;
@ -73,7 +75,7 @@ class ModelPropertiesDialog : public QDialog {
Q_OBJECT
public:
ModelPropertiesDialog(bool isHead, const QVariantHash& originalMapping,
ModelPropertiesDialog(ModelType modelType, const QVariantHash& originalMapping,
const QString& basePath, const FBXGeometry& geometry);
QVariantHash getMapping() const;
@ -87,7 +89,7 @@ private:
QComboBox* createJointBox(bool withNone = true) const;
void insertJointMapping(QVariantHash& joints, const QString& joint, const QString& name) const;
bool _isHead;
ModelType _modelType;
QVariantHash _originalMapping;
QString _basePath;
FBXGeometry _geometry;

View file

@ -22,10 +22,11 @@
#include "ModelsBrowser.h"
const char* MODEL_TYPE_NAMES[] = { "heads", "skeletons", "attachments" };
static const QString S3_URL = "http://highfidelity-public.s3-us-west-1.amazonaws.com";
static const QString PUBLIC_URL = "http://public.highfidelity.io";
static const QString HEAD_MODELS_LOCATION = "models/heads";
static const QString SKELETON_MODELS_LOCATION = "models/skeletons/";
static const QString MODELS_LOCATION = "models/";
static const QString PREFIX_PARAMETER_NAME = "prefix";
static const QString MARKER_PARAMETER_NAME = "marker";
@ -243,11 +244,7 @@ void ModelHandler::queryNewFiles(QString marker) {
// Build query
QUrl url(S3_URL);
QUrlQuery query;
if (_type == Head) {
query.addQueryItem(PREFIX_PARAMETER_NAME, HEAD_MODELS_LOCATION);
} else if (_type == Skeleton) {
query.addQueryItem(PREFIX_PARAMETER_NAME, SKELETON_MODELS_LOCATION);
}
query.addQueryItem(PREFIX_PARAMETER_NAME, MODELS_LOCATION + MODEL_TYPE_NAMES[_type]);
if (!marker.isEmpty()) {
query.addQueryItem(MARKER_PARAMETER_NAME, marker);

View file

@ -16,12 +16,14 @@
#include <QStandardItemModel>
#include <QTreeView>
enum ModelType {
Head,
Skeleton
HEAD_MODEL,
SKELETON_MODEL,
ATTACHMENT_MODEL
};
extern const char* MODEL_TYPE_NAMES[];
class ModelHandler : public QObject {
Q_OBJECT
public:

View file

@ -48,7 +48,7 @@ void PreferencesDialog::openHeadModelBrowser() {
setWindowFlags(windowFlags() & ~Qt::WindowStaysOnTopHint);
show();
ModelsBrowser modelBrowser(Head);
ModelsBrowser modelBrowser(HEAD_MODEL);
connect(&modelBrowser, &ModelsBrowser::selected, this, &PreferencesDialog::setHeadUrl);
modelBrowser.browse();
@ -60,7 +60,7 @@ void PreferencesDialog::openBodyModelBrowser() {
setWindowFlags(windowFlags() & ~Qt::WindowStaysOnTopHint);
show();
ModelsBrowser modelBrowser(Skeleton);
ModelsBrowser modelBrowser(SKELETON_MODEL);
connect(&modelBrowser, &ModelsBrowser::selected, this, &PreferencesDialog::setSkeletonUrl);
modelBrowser.browse();

View file

@ -81,6 +81,7 @@ const glm::vec3 vec3Zero(0.0f);
class QNetworkAccessManager;
class AttachmentData;
class JointData;
class AvatarData : public QObject {
@ -275,6 +276,7 @@ protected:
QUrl _faceModelURL;
QUrl _skeletonModelURL;
QVector<AttachmentData> _attachmentData;
QString _displayName;
QRect _displayNameBoundingRect;
@ -309,4 +311,13 @@ public:
glm::quat rotation;
};
class AttachmentData {
public:
QUrl modelURL;
int jointIndex;
glm::vec3 translation;
glm::quat rotation;
float scale;
};
#endif // hifi_AvatarData_h

View file

@ -49,6 +49,8 @@ PacketVersion versionForPacketType(PacketType type) {
switch (type) {
case PacketTypeAvatarData:
return 3;
case PacketTypeAvatarIdentity:
return 1;
case PacketTypeEnvironmentData:
return 1;
case PacketTypeParticleData: