more work on improved avatar UI adding model names and backward compatible support

This commit is contained in:
ZappoMan 2015-04-03 17:03:22 -07:00
parent aaf191b6dc
commit 1a463a0256
9 changed files with 115 additions and 55 deletions

View file

@ -3689,17 +3689,7 @@ bool Application::askToSetAvatarUrl(const QString& url) {
}
// Download the FST file, to attempt to determine its model type
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkRequest networkRequest = QNetworkRequest(url);
networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
QNetworkReply* reply = networkAccessManager.get(networkRequest);
qDebug() << "Downloading avatar file at " << url;
QEventLoop loop;
QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
loop.exec();
QByteArray fstContents = reply->readAll();
delete reply;
QVariantHash fstMapping = FSTReader::readMapping(fstContents);
QVariantHash fstMapping = FSTReader::downloadMapping(url);
FSTReader::ModelType modelType = FSTReader::predictModelType(fstMapping);
@ -3710,26 +3700,27 @@ bool Application::askToSetAvatarUrl(const QString& url) {
QPushButton* bodyButton = NULL;
QPushButton* bodyAndHeadButton = NULL;
QString modelName = fstMapping["name"].toString();
QString message;
QString typeInfo;
switch (modelType) {
case FSTReader::HEAD_MODEL:
message = QString("Would you like to use '") + fstMapping["name"].toString() + QString("' for your avatar head?");
message = QString("Would you like to use '") + modelName + QString("' for your avatar head?");
headButton = msgBox.addButton(tr("Yes"), QMessageBox::ActionRole);
break;
case FSTReader::BODY_ONLY_MODEL:
message = QString("Would you like to use '") + fstMapping["name"].toString() + QString("' for your avatar body?");
message = QString("Would you like to use '") + modelName + QString("' for your avatar body?");
bodyButton = msgBox.addButton(tr("Yes"), QMessageBox::ActionRole);
break;
case FSTReader::HEAD_AND_BODY_MODEL:
message = QString("Would you like to use '") + fstMapping["name"].toString() + QString("' for your avatar?");
message = QString("Would you like to use '") + modelName + QString("' for your avatar?");
bodyAndHeadButton = msgBox.addButton(tr("Yes"), QMessageBox::ActionRole);
break;
default:
message = QString("Would you like to use '") + fstMapping["name"].toString() + QString("' for some part of your avatar head?");
message = QString("Would you like to use '") + modelName + QString("' for some part of your avatar head?");
headButton = msgBox.addButton(tr("Use for Head"), QMessageBox::ActionRole);
bodyButton = msgBox.addButton(tr("Use for Body"), QMessageBox::ActionRole);
bodyAndHeadButton = msgBox.addButton(tr("Use for Body and Head"), QMessageBox::ActionRole);
@ -3743,16 +3734,16 @@ bool Application::askToSetAvatarUrl(const QString& url) {
if (msgBox.clickedButton() == headButton) {
qDebug() << "Chose to use for head: " << url;
_myAvatar->useHeadURL(url);
emit headURLChanged(url);
_myAvatar->useHeadURL(url, modelName);
emit headURLChanged(url, modelName);
} else if (msgBox.clickedButton() == bodyButton) {
qDebug() << "Chose to use for body: " << url;
_myAvatar->useBodyURL(url);
emit bodyURLChanged(url);
_myAvatar->useBodyURL(url, modelName);
emit bodyURLChanged(url, modelName);
} else if (msgBox.clickedButton() == bodyAndHeadButton) {
qDebug() << "Chose to use for body + head: " << url;
_myAvatar->useFullAvatarURL(url);
emit fullAvatarURLChanged(url);
_myAvatar->useFullAvatarURL(url, modelName);
emit fullAvatarURLChanged(url, modelName);
} else {
qDebug() << "Declined to use the avatar: " << url;
}

View file

@ -335,9 +335,9 @@ signals:
void checkBackgroundDownloads();
void domainConnectionRefused(const QString& reason);
void headURLChanged(const QString& newValue);
void bodyURLChanged(const QString& newValue);
void fullAvatarURLChanged(const QString& newValue);
void headURLChanged(const QString& newValue, const QString& modelName);
void bodyURLChanged(const QString& newValue, const QString& modelName);
void fullAvatarURLChanged(const QString& newValue, const QString& modelName);
public slots:
void domainChanged(const QString& domainHostname);

View file

@ -610,7 +610,10 @@ void MyAvatar::saveData() {
settings.setValue("fullAvatarURL", _fullAvatarURLFromPreferences);
settings.setValue("faceModelURL", _headURLFromPreferences);
settings.setValue("skeletonModelURL", _skeletonURLFromPreferences);
settings.setValue("headModelName", _headModelName);
settings.setValue("bodyModelName", _bodyModelName);
settings.setValue("fullAvatarModelName", _fullAvatarModelName);
settings.beginWriteArray("attachmentData");
for (int i = 0; i < _attachmentData.size(); i++) {
settings.setArrayIndex(i);
@ -675,20 +678,48 @@ void MyAvatar::loadData() {
// The old preferences only stored the face and skeleton URLs, we didn't track if the user wanted to use 1 or 2 urls
// for their avatar, So we need to attempt to detect this old case and set our new preferences accordingly. If
// the head URL is empty, then we will assume they are using a full url...
_headURLFromPreferences = settings.value("faceModelURL", DEFAULT_HEAD_MODEL_URL).toUrl();
bool assumeFullAvatar = _headURLFromPreferences.isEmpty();
bool isOldSettings = !(settings.contains("useFullAvatar") || settings.contains("fullAvatarURL"));
_useFullAvatar = settings.value("useFullAvatar", assumeFullAvatar).toBool();
_useFullAvatar = settings.value("useFullAvatar").toBool();
_headURLFromPreferences = settings.value("faceModelURL", DEFAULT_HEAD_MODEL_URL).toUrl();
_fullAvatarURLFromPreferences = settings.value("fullAvatarURL").toUrl();
_skeletonURLFromPreferences = settings.value("skeletonModelURL").toUrl();
_headModelName = settings.value("headModelName").toString();
_bodyModelName = settings.value("bodyModelName").toString();
_fullAvatarModelName = settings.value("fullAvatarModelName").toString();;
if (isOldSettings) {
bool assumeFullAvatar = _headURLFromPreferences.isEmpty();
_useFullAvatar = assumeFullAvatar;
if (_useFullAvatar) {
_fullAvatarURLFromPreferences = settings.value("skeletonModelURL").toUrl();
_headURLFromPreferences = DEFAULT_HEAD_MODEL_URL;
_skeletonURLFromPreferences = DEFAULT_BODY_MODEL_URL;
QVariantHash fullAvatarFST = FSTReader::downloadMapping(_fullAvatarURLFromPreferences.toString());
_headModelName = "Default";
_bodyModelName = "Default";
_fullAvatarModelName = fullAvatarFST["name"].toString();
} else {
_fullAvatarURLFromPreferences = DEFAULT_FULL_AVATAR_MODEL_URL;
_skeletonURLFromPreferences = settings.value("skeletonModelURL").toUrl();
QVariantHash headFST = FSTReader::downloadMapping(_headURLFromPreferences.toString());
QVariantHash bodyFST = FSTReader::downloadMapping(_skeletonURLFromPreferences.toString());
_headModelName = headFST["name"].toString();
_bodyModelName = bodyFST["name"].toString();
_fullAvatarModelName = "Default";
}
}
if (_useFullAvatar) {
setFaceModelURL(QUrl());
setSkeletonModelURL(_fullAvatarURLFromPreferences);
useFullAvatarURL(_fullAvatarURLFromPreferences, _fullAvatarModelName);
} else {
setFaceModelURL(_headURLFromPreferences);
setSkeletonModelURL(_skeletonURLFromPreferences);
useHeadAndBodyURLs(_headURLFromPreferences, _skeletonURLFromPreferences, _headModelName, _bodyModelName);
}
QVector<AttachmentData> attachmentData;
@ -922,9 +953,10 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
_billboardValid = false;
}
void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL) {
void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelName) {
_useFullAvatar = true;
_fullAvatarURLFromPreferences = fullAvatarURL;
_fullAvatarModelName = modelName;
if (!getFaceModelURLString().isEmpty()) {
setFaceModelURL(QString());
@ -937,18 +969,20 @@ void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL) {
sendIdentityPacket();
}
void MyAvatar::useHeadURL(const QUrl& headURL) {
useHeadAndBodyURLs(headURL, _skeletonURLFromPreferences);
void MyAvatar::useHeadURL(const QUrl& headURL, const QString& modelName) {
useHeadAndBodyURLs(headURL, _skeletonURLFromPreferences, modelName, _bodyModelName);
}
void MyAvatar::useBodyURL(const QUrl& bodyURL) {
useHeadAndBodyURLs(_headURLFromPreferences, bodyURL);
void MyAvatar::useBodyURL(const QUrl& bodyURL, const QString& modelName) {
useHeadAndBodyURLs(_headURLFromPreferences, bodyURL, _headModelName, modelName);
}
void MyAvatar::useHeadAndBodyURLs(const QUrl& headURL, const QUrl& bodyURL) {
void MyAvatar::useHeadAndBodyURLs(const QUrl& headURL, const QUrl& bodyURL, const QString& headName, const QString& bodyName) {
_useFullAvatar = false;
_headURLFromPreferences = headURL;
_skeletonURLFromPreferences = bodyURL;
_headModelName = headName;
_bodyModelName = bodyName;
if (headURL != getFaceModelURL()) {
setFaceModelURL(headURL);

View file

@ -117,16 +117,20 @@ public:
virtual void clearJointData(int index);
virtual void clearJointsData();
void useFullAvatarURL(const QUrl& fullAvatarURL);
void useHeadURL(const QUrl& headURL);
void useBodyURL(const QUrl& bodyURL);
void useHeadAndBodyURLs(const QUrl& headURL, const QUrl& bodyURL);
void useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelName = QString());
void useHeadURL(const QUrl& headURL, const QString& modelName = QString());
void useBodyURL(const QUrl& bodyURL, const QString& modelName = QString());
void useHeadAndBodyURLs(const QUrl& headURL, const QUrl& bodyURL, const QString& headName = QString(), const QString& bodyName = QString());
bool getUseFullAvatar() const { return _useFullAvatar; }
const QUrl& getFullAvatarURLFromPreferences() const { return _fullAvatarURLFromPreferences; }
const QUrl& getHeadURLFromPreferences() const { return _headURLFromPreferences; }
const QUrl& getBodyURLFromPreferences() const { return _skeletonURLFromPreferences; }
const QString& getHeadModelName() const { return _headModelName; }
const QString& getBodyModelName() const { return _bodyModelName; }
const QString& getFullAvartarModelName() const { return _fullAvatarModelName; }
virtual void setAttachmentData(const QVector<AttachmentData>& attachmentData);
virtual glm::vec3 getSkeletonPosition() const;
@ -249,6 +253,10 @@ private:
QUrl _fullAvatarURLFromPreferences;
QUrl _headURLFromPreferences;
QUrl _skeletonURLFromPreferences;
QString _headModelName;
QString _bodyModelName;
QString _fullAvatarModelName;
};
#endif // hifi_MyAvatar_h

View file

@ -61,11 +61,11 @@ PreferencesDialog::PreferencesDialog(QWidget* parent) :
move(parentWidget()->geometry().topLeft());
setFixedHeight(parentWidget()->size().height() - PREFERENCES_HEIGHT_PADDING);
ui.bodyNameLabel->setText("Body - name of model here");
ui.headNameLabel->setText("Head - name of model here");
ui.fullAvatarNameLabel->setText("Full Avatar - name of model here");
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
ui.bodyNameLabel->setText("Body - " + myAvatar->getBodyModelName());
ui.headNameLabel->setText("Head - " + myAvatar->getHeadModelName());
ui.fullAvatarNameLabel->setText("Full Avatar - " + myAvatar->getFullAvartarModelName());
UIUtil::scaleWidgetFontSizes(this);
}
@ -95,19 +95,22 @@ void PreferencesDialog::setUseFullAvatar(bool useFullAvatar) {
ui.useSeparateBodyAndHead->setChecked(!_useFullAvatar);
}
void PreferencesDialog::headURLChanged(const QString& newValue) {
void PreferencesDialog::headURLChanged(const QString& newValue, const QString& modelName) {
ui.faceURLEdit->setText(newValue);
setUseFullAvatar(false);
ui.headNameLabel->setText("Head - " + modelName);
}
void PreferencesDialog::bodyURLChanged(const QString& newValue) {
void PreferencesDialog::bodyURLChanged(const QString& newValue, const QString& modelName) {
ui.skeletonURLEdit->setText(newValue);
setUseFullAvatar(false);
ui.bodyNameLabel->setText("Body - " + modelName);
}
void PreferencesDialog::fullAvatarURLChanged(const QString& newValue) {
void PreferencesDialog::fullAvatarURLChanged(const QString& newValue, const QString& modelName) {
ui.fullAvatarURLEdit->setText(newValue);
setUseFullAvatar(true);
ui.fullAvatarNameLabel->setText("Full Avatar - " + modelName);
}
void PreferencesDialog::accept() {

View file

@ -54,9 +54,9 @@ private slots:
void setSkeletonUrl(QString modelUrl);
void openSnapshotLocationBrowser();
void openScriptsLocationBrowser();
void headURLChanged(const QString& newValue);
void bodyURLChanged(const QString& newValue);
void fullAvatarURLChanged(const QString& newValue);
void headURLChanged(const QString& newValue, const QString& modelName);
void bodyURLChanged(const QString& newValue, const QString& modelName);
void fullAvatarURLChanged(const QString& newValue, const QString& modelName);
void useSeparateBodyAndHead(bool checked);
void useFullAvatar(bool checked);

View file

@ -103,6 +103,8 @@ const int AVATAR_BILLBOARD_PACKET_SEND_INTERVAL_MSECS = 5000;
const QUrl DEFAULT_HEAD_MODEL_URL = QUrl("http://public.highfidelity.io/models/heads/defaultAvatar_head.fst");
const QUrl DEFAULT_BODY_MODEL_URL = QUrl("http://public.highfidelity.io/models/skeletons/defaultAvatar_body.fst");
const QUrl DEFAULT_FULL_AVATAR_MODEL_URL = QUrl("http://public.highfidelity.io/marketplace/contents/029db3d4-da2c-4cb2-9c08-b9612ba576f5/02949063e7c4aed42ad9d1a58461f56d.fst");
// Where one's own Avatar begins in the world (will be overwritten if avatar data file is found).
// This is the start location in the Sandbox (xyz: 6270, 211, 6000).

View file

@ -10,6 +10,13 @@
//
#include <QBuffer>
#include <QEventLoop>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <NetworkAccessManager.h>
#include <NetworkingConstants.h>
#include <SharedUtil.h>
#include "FSTReader.h"
@ -169,3 +176,17 @@ FSTReader::ModelType FSTReader::predictModelType(const QVariantHash& mapping) {
return ENTITY_MODEL;
}
QVariantHash FSTReader::downloadMapping(const QString& url) {
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkRequest networkRequest = QNetworkRequest(url);
networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
QNetworkReply* reply = networkAccessManager.get(networkRequest);
qDebug() << "Downloading avatar file at " << url;
QEventLoop loop;
QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
loop.exec();
QByteArray fstContents = reply->readAll();
delete reply;
return FSTReader::readMapping(fstContents);
}

View file

@ -51,6 +51,7 @@ public:
static QString getNameFromType(ModelType modelType);
static FSTReader::ModelType getTypeFromName(const QString& name);
static QVariantHash downloadMapping(const QString& url);
private:
static void writeVariant(QBuffer& buffer, QVariantHash::const_iterator& it);