mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-04 13:17:59 +02:00
more work on improved avatar UI adding model names and backward compatible support
This commit is contained in:
parent
aaf191b6dc
commit
1a463a0256
9 changed files with 115 additions and 55 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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).
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue