Merge pull request #5566 from howard-stearns/recapitate

Get rid of separate head/body avatar
This commit is contained in:
Seth Alves 2015-08-19 10:46:05 -07:00
commit 537b690d60
17 changed files with 79 additions and 1065 deletions

View file

@ -4097,23 +4097,12 @@ bool Application::askToSetAvatarUrl(const QString& url) {
QMessageBox msgBox;
msgBox.setIcon(QMessageBox::Question);
msgBox.setWindowTitle("Set Avatar");
QPushButton* headButton = NULL;
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 '") + 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 '") + 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 '") + modelName + QString("' for your avatar?");
@ -4121,10 +4110,7 @@ bool Application::askToSetAvatarUrl(const QString& url) {
break;
default:
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);
message = QString(modelName + QString("Does not support a head and body as required."));
break;
}
@ -4133,14 +4119,7 @@ bool Application::askToSetAvatarUrl(const QString& url) {
msgBox.exec();
if (msgBox.clickedButton() == headButton) {
_myAvatar->useHeadURL(url, modelName);
emit headURLChanged(url, modelName);
} else if (msgBox.clickedButton() == bodyButton) {
_myAvatar->useBodyURL(url, modelName);
emit bodyURLChanged(url, modelName);
} else if (msgBox.clickedButton() == bodyAndHeadButton) {
_myAvatar->useFullAvatarURL(url, modelName);
if (msgBox.clickedButton() == bodyAndHeadButton) {
emit fullAvatarURLChanged(url, modelName);
} else {
qCDebug(interfaceapp) << "Declined to use the avatar: " << url;
@ -4627,7 +4606,7 @@ void Application::checkSkeleton() {
msgBox.setIcon(QMessageBox::Warning);
msgBox.exec();
_myAvatar->useBodyURL(DEFAULT_BODY_MODEL_URL, "Default");
_myAvatar->useFullAvatarURL(AvatarData::defaultFullAvatarModelUrl(), DEFAULT_FULL_AVATAR_MODEL_NAME);
} else {
_physicsEngine.setCharacterController(_myAvatar->getCharacterController());
}

View file

@ -26,7 +26,6 @@
#include <NodeList.h>
#include <NumericalConstants.h>
#include <udt/PacketHeaders.h>
#include <PathUtils.h>
#include <PerfStat.h>
#include <SharedUtil.h>
#include <TextRenderer3D.h>
@ -979,20 +978,12 @@ void Avatar::scaleVectorRelativeToPosition(glm::vec3 &positionToScale) const {
void Avatar::setFaceModelURL(const QUrl& faceModelURL) {
AvatarData::setFaceModelURL(faceModelURL);
const QUrl DEFAULT_FACE_MODEL_URL = QUrl::fromLocalFile(PathUtils::resourcesPath() + "meshes/defaultAvatar_head.fst");
getHead()->getFaceModel().setURL(_faceModelURL, DEFAULT_FACE_MODEL_URL, true, !isMyAvatar());
getHead()->getFaceModel().setURL(_faceModelURL, AvatarData::defaultFullAvatarModelUrl(), true, !isMyAvatar());
}
void Avatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
AvatarData::setSkeletonModelURL(skeletonModelURL);
const QUrl DEFAULT_FULL_MODEL_URL = QUrl::fromLocalFile(PathUtils::resourcesPath() + "meshes/defaultAvatar_full.fst");
const QUrl DEFAULT_SKELETON_MODEL_URL = QUrl::fromLocalFile(PathUtils::resourcesPath() + "meshes/defaultAvatar_body.fst");
if (isMyAvatar()) {
_skeletonModel.setURL(_skeletonModelURL,
getUseFullAvatar() ? DEFAULT_FULL_MODEL_URL : DEFAULT_SKELETON_MODEL_URL, true, !isMyAvatar());
} else {
_skeletonModel.setURL(_skeletonModelURL, DEFAULT_SKELETON_MODEL_URL, true, !isMyAvatar());
}
_skeletonModel.setURL(_skeletonModelURL, AvatarData::defaultFullAvatarModelUrl(), true, !isMyAvatar());
}
void Avatar::setAttachmentData(const QVector<AttachmentData>& attachmentData) {

View file

@ -150,8 +150,6 @@ public:
Q_INVOKABLE glm::vec3 getAcceleration() const { return _acceleration; }
Q_INVOKABLE glm::vec3 getAngularVelocity() const { return _angularVelocity; }
Q_INVOKABLE glm::vec3 getAngularAcceleration() const { return _angularAcceleration; }
virtual bool getUseFullAvatar() const { return false; }
/// Scales a world space position vector relative to the avatar position and scale
/// \param vector position to be scaled. Will store the result

View file

@ -47,66 +47,10 @@ void FaceModel::simulate(float deltaTime, bool fullUpdate) {
if (isActive()) {
setOffset(-_geometry->getFBXGeometry().neckPivot);
for (int i = 0; i < _rig->getJointStateCount(); i++) {
maybeUpdateNeckAndEyeRotation(i);
}
Model::simulateInternal(deltaTime);
}
}
void FaceModel::maybeUpdateNeckRotation(const JointState& parentState, const JointState& state, int index) {
// get the rotation axes in joint space and use them to adjust the rotation
glm::mat3 axes = glm::mat3_cast(glm::quat());
glm::mat3 inverse = glm::mat3(glm::inverse(parentState.getTransform() *
glm::translate(_rig->getJointDefaultTranslationInConstrainedFrame(index)) *
state.getPreTransform() * glm::mat4_cast(state.getPreRotation())));
glm::vec3 pitchYawRoll = safeEulerAngles(_owningHead->getFinalOrientationInLocalFrame());
glm::vec3 lean = glm::radians(glm::vec3(_owningHead->getFinalLeanForward(),
_owningHead->getTorsoTwist(),
_owningHead->getFinalLeanSideways()));
pitchYawRoll -= lean;
_rig->setJointRotationInConstrainedFrame(index,
glm::angleAxis(-pitchYawRoll.z, glm::normalize(inverse * axes[2]))
* glm::angleAxis(pitchYawRoll.y, glm::normalize(inverse * axes[1]))
* glm::angleAxis(-pitchYawRoll.x, glm::normalize(inverse * axes[0]))
* state.getDefaultRotation(), DEFAULT_PRIORITY);
}
void FaceModel::maybeUpdateEyeRotation(Model* model, const JointState& parentState, const JointState& state, int index) {
// likewise with the eye joints
// NOTE: at the moment we do the math in the world-frame, hence the inverse transform is more complex than usual.
glm::mat4 inverse = glm::inverse(glm::mat4_cast(model->getRotation()) * parentState.getTransform() *
glm::translate(_rig->getJointDefaultTranslationInConstrainedFrame(index)) *
state.getPreTransform() * glm::mat4_cast(state.getPreRotation() * state.getDefaultRotation()));
glm::vec3 front = glm::vec3(inverse * glm::vec4(_owningHead->getFinalOrientationInWorldFrame() * IDENTITY_FRONT, 0.0f));
glm::vec3 lookAtDelta = _owningHead->getCorrectedLookAtPosition() - model->getTranslation();
glm::vec3 lookAt = glm::vec3(inverse * glm::vec4(lookAtDelta + glm::length(lookAtDelta) * _owningHead->getSaccade(), 1.0f));
glm::quat between = rotationBetween(front, lookAt);
const float MAX_ANGLE = 30.0f * RADIANS_PER_DEGREE;
_rig->setJointRotationInConstrainedFrame(index, glm::angleAxis(glm::clamp(glm::angle(between),
-MAX_ANGLE, MAX_ANGLE), glm::axis(between)) *
state.getDefaultRotation(), DEFAULT_PRIORITY);
}
void FaceModel::maybeUpdateNeckAndEyeRotation(int index) {
const JointState& state = _rig->getJointState(index);
const FBXGeometry& geometry = _geometry->getFBXGeometry();
const int parentIndex = state.getParentIndex();
// guard against out-of-bounds access to _jointStates
if (parentIndex != -1 && parentIndex >= 0 && parentIndex < _rig->getJointStateCount()) {
const JointState& parentState = _rig->getJointState(parentIndex);
if (index == geometry.neckJointIndex) {
maybeUpdateNeckRotation(parentState, state, index);
} else if (index == geometry.leftEyeJointIndex || index == geometry.rightEyeJointIndex) {
maybeUpdateEyeRotation(this, parentState, state, index);
}
}
}
bool FaceModel::getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const {
if (!isActive()) {
return false;

View file

@ -26,10 +26,6 @@ public:
virtual void simulate(float deltaTime, bool fullUpdate = true);
void maybeUpdateNeckRotation(const JointState& parentState, const JointState& state, int index);
void maybeUpdateEyeRotation(Model* model, const JointState& parentState, const JointState& state, int index);
void maybeUpdateNeckAndEyeRotation(int index);
/// Retrieve the positions of up to two eye meshes.
/// \return whether or not both eye meshes were found
bool getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const;

View file

@ -652,12 +652,7 @@ void MyAvatar::saveData() {
settings.setValue("leanScale", _leanScale);
settings.setValue("scale", _targetScale);
settings.setValue("useFullAvatar", _useFullAvatar);
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");
@ -727,61 +722,10 @@ void MyAvatar::loadData() {
_targetScale = loadSetting(settings, "scale", 1.0f);
setScale(_scale);
// 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...
bool isOldSettings = !(settings.contains("useFullAvatar") || settings.contains("fullAvatarURL"));
_useFullAvatar = settings.value("useFullAvatar").toBool();
_headURLFromPreferences = settings.value("faceModelURL", DEFAULT_HEAD_MODEL_URL).toUrl();
_fullAvatarURLFromPreferences = settings.value("fullAvatarURL", DEFAULT_FULL_AVATAR_MODEL_URL).toUrl();
_skeletonURLFromPreferences = settings.value("skeletonModelURL", DEFAULT_BODY_MODEL_URL).toUrl();
_headModelName = settings.value("headModelName", DEFAULT_HEAD_MODEL_NAME).toString();
_bodyModelName = settings.value("bodyModelName", DEFAULT_BODY_MODEL_NAME).toString();
_fullAvatarURLFromPreferences = settings.value("fullAvatarURL", AvatarData::defaultFullAvatarModelUrl()).toUrl();
_fullAvatarModelName = settings.value("fullAvatarModelName", DEFAULT_FULL_AVATAR_MODEL_NAME).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", DEFAULT_BODY_MODEL_URL).toUrl();
if (_skeletonURLFromPreferences == DEFAULT_BODY_MODEL_URL) {
_bodyModelName = DEFAULT_BODY_MODEL_NAME;
} else {
QVariantHash bodyFST = FSTReader::downloadMapping(_skeletonURLFromPreferences.toString());
_bodyModelName = bodyFST["name"].toString();
}
if (_headURLFromPreferences == DEFAULT_HEAD_MODEL_URL) {
_headModelName = DEFAULT_HEAD_MODEL_NAME;
} else {
QVariantHash headFST = FSTReader::downloadMapping(_headURLFromPreferences.toString());
_headModelName = headFST["name"].toString();
}
_fullAvatarModelName = "Default";
}
}
if (_useFullAvatar) {
useFullAvatarURL(_fullAvatarURLFromPreferences, _fullAvatarModelName);
} else {
useHeadAndBodyURLs(_headURLFromPreferences, _skeletonURLFromPreferences, _headModelName, _bodyModelName);
}
useFullAvatarURL(_fullAvatarURLFromPreferences, _fullAvatarModelName);
QVector<AttachmentData> attachmentData;
int attachmentCount = settings.beginReadArray("attachmentData");
@ -1012,29 +956,6 @@ void MyAvatar::clearJointAnimationPriorities() {
}
}
QString MyAvatar::getModelDescription() const {
QString result;
if (_useFullAvatar) {
if (!getFullAvartarModelName().isEmpty()) {
result = "Full Avatar \"" + getFullAvartarModelName() + "\"";
} else {
result = "Full Avatar \"" + _fullAvatarURLFromPreferences.fileName() + "\"";
}
} else {
if (!getHeadModelName().isEmpty()) {
result = "Head \"" + getHeadModelName() + "\"";
} else {
result = "Head \"" + _headURLFromPreferences.fileName() + "\"";
}
if (!getBodyModelName().isEmpty()) {
result += " and Body \"" + getBodyModelName() + "\"";
} else {
result += " and Body \"" + _skeletonURLFromPreferences.fileName() + "\"";
}
}
return result;
}
void MyAvatar::setFaceModelURL(const QUrl& faceModelURL) {
Avatar::setFaceModelURL(faceModelURL);
@ -1061,8 +982,6 @@ void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelN
return;
}
_useFullAvatar = true;
if (_fullAvatarURLFromPreferences != fullAvatarURL) {
_fullAvatarURLFromPreferences = fullAvatarURL;
if (modelName.isEmpty()) {
@ -1077,66 +996,14 @@ void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelN
setFaceModelURL(QString());
}
if (fullAvatarURL != getSkeletonModelURL()) {
const QString& urlString = fullAvatarURL.toString();
if (urlString.isEmpty() || (fullAvatarURL != getSkeletonModelURL())) {
setSkeletonModelURL(fullAvatarURL);
UserActivityLogger::getInstance().changedModel("skeleton", fullAvatarURL.toString());
UserActivityLogger::getInstance().changedModel("skeleton", urlString);
}
sendIdentityPacket();
}
void MyAvatar::useHeadURL(const QUrl& headURL, const QString& modelName) {
useHeadAndBodyURLs(headURL, _skeletonURLFromPreferences, modelName, _bodyModelName);
}
void MyAvatar::useBodyURL(const QUrl& bodyURL, const QString& modelName) {
useHeadAndBodyURLs(_headURLFromPreferences, bodyURL, _headModelName, modelName);
}
void MyAvatar::useHeadAndBodyURLs(const QUrl& headURL, const QUrl& bodyURL, const QString& headName, const QString& bodyName) {
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "useFullAvatarURL", Qt::BlockingQueuedConnection,
Q_ARG(const QUrl&, headURL),
Q_ARG(const QUrl&, bodyURL),
Q_ARG(const QString&, headName),
Q_ARG(const QString&, bodyName));
return;
}
_useFullAvatar = false;
if (_headURLFromPreferences != headURL) {
_headURLFromPreferences = headURL;
if (headName.isEmpty()) {
QVariantHash headFST = FSTReader::downloadMapping(_headURLFromPreferences.toString());
_headModelName = headFST["name"].toString();
} else {
_headModelName = headName;
}
}
if (_skeletonURLFromPreferences != bodyURL) {
_skeletonURLFromPreferences = bodyURL;
if (bodyName.isEmpty()) {
QVariantHash bodyFST = FSTReader::downloadMapping(_skeletonURLFromPreferences.toString());
_bodyModelName = bodyFST["name"].toString();
} else {
_bodyModelName = bodyName;
}
}
if (headURL != getFaceModelURL()) {
setFaceModelURL(headURL);
UserActivityLogger::getInstance().changedModel("head", headURL.toString());
}
if (bodyURL != getSkeletonModelURL()) {
setSkeletonModelURL(bodyURL);
UserActivityLogger::getInstance().changedModel("skeleton", bodyURL.toString());
}
sendIdentityPacket();
}
void MyAvatar::setAttachmentData(const QVector<AttachmentData>& attachmentData) {
Avatar::setAttachmentData(attachmentData);
if (QThread::currentThread() != thread()) {
@ -1310,11 +1177,7 @@ void MyAvatar::preRender(RenderArgs* renderArgs) {
}
if (shouldDrawHead != _prevShouldDrawHead) {
if (_useFullAvatar) {
_skeletonModel.setCauterizeBones(!shouldDrawHead);
} else {
getHead()->getFaceModel().setVisibleInScene(shouldDrawHead, scene);
}
_skeletonModel.setCauterizeBones(!shouldDrawHead);
}
_prevShouldDrawHead = shouldDrawHead;
}

View file

@ -126,21 +126,8 @@ public:
virtual void clearJointsData();
Q_INVOKABLE void useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelName = QString());
Q_INVOKABLE void useHeadURL(const QUrl& headURL, const QString& modelName = QString());
Q_INVOKABLE void useBodyURL(const QUrl& bodyURL, const QString& modelName = QString());
Q_INVOKABLE void useHeadAndBodyURLs(const QUrl& headURL, const QUrl& bodyURL,
const QString& headName = QString(), const QString& bodyName = QString());
Q_INVOKABLE virtual bool getUseFullAvatar() const { return _useFullAvatar; }
Q_INVOKABLE const QUrl& getFullAvatarURLFromPreferences() const { return _fullAvatarURLFromPreferences; }
Q_INVOKABLE const QUrl& getHeadURLFromPreferences() const { return _headURLFromPreferences; }
Q_INVOKABLE const QUrl& getBodyURLFromPreferences() const { return _skeletonURLFromPreferences; }
Q_INVOKABLE const QString& getHeadModelName() const { return _headModelName; }
Q_INVOKABLE const QString& getBodyModelName() const { return _bodyModelName; }
Q_INVOKABLE const QString& getFullAvartarModelName() const { return _fullAvatarModelName; }
Q_INVOKABLE QString getModelDescription() const;
Q_INVOKABLE const QString& getFullAvatarModelName() const { return _fullAvatarModelName; }
virtual void setAttachmentData(const QVector<AttachmentData>& attachmentData);
@ -298,18 +285,9 @@ private:
void initHeadBones();
// Avatar Preferences
bool _useFullAvatar = false;
QUrl _fullAvatarURLFromPreferences;
QUrl _headURLFromPreferences;
QUrl _skeletonURLFromPreferences;
QString _headModelName;
QString _bodyModelName;
QString _fullAvatarModelName;
RigPointer _rig;
bool _prevShouldDrawHead;
// cache of the current HMD sensor position and orientation
// in sensor space.
glm::mat4 _hmdSensorMatrix;
@ -330,6 +308,8 @@ private:
glm::quat _goToOrientation;
std::unordered_set<int> _headBoneSet;
RigPointer _rig;
bool _prevShouldDrawHead;
};
#endif // hifi_MyAvatar_h

View file

@ -1,215 +0,0 @@
//
// AvatarAppearanceDialog.cpp
// interface/src/ui
//
// Created by Stojce Slavkovski on 2/20/14.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <QFileDialog>
#include <QFont>
#include <AudioClient.h>
#include <avatar/AvatarManager.h>
#include <devices/Faceshift.h>
#include <NetworkingConstants.h>
#include "Application.h"
#include "MainWindow.h"
#include "LODManager.h"
#include "Menu.h"
#include "AvatarAppearanceDialog.h"
#include "Snapshot.h"
#include "UserActivityLogger.h"
#include "UIUtil.h"
#include "ui/DialogsManager.h"
#include "ui/PreferencesDialog.h"
AvatarAppearanceDialog::AvatarAppearanceDialog(QWidget* parent) :
QDialog(parent) {
setAttribute(Qt::WA_DeleteOnClose);
ui.setupUi(this);
loadAvatarAppearance();
connect(ui.defaultButton, &QPushButton::clicked, this, &AvatarAppearanceDialog::accept);
connect(ui.buttonBrowseHead, &QPushButton::clicked, this, &AvatarAppearanceDialog::openHeadModelBrowser);
connect(ui.buttonBrowseBody, &QPushButton::clicked, this, &AvatarAppearanceDialog::openBodyModelBrowser);
connect(ui.buttonBrowseFullAvatar, &QPushButton::clicked, this, &AvatarAppearanceDialog::openFullAvatarModelBrowser);
connect(ui.useSeparateBodyAndHead, &QRadioButton::clicked, this, &AvatarAppearanceDialog::useSeparateBodyAndHead);
connect(ui.useFullAvatar, &QRadioButton::clicked, this, &AvatarAppearanceDialog::useFullAvatar);
connect(Application::getInstance(), &Application::headURLChanged, this, &AvatarAppearanceDialog::headURLChanged);
connect(Application::getInstance(), &Application::bodyURLChanged, this, &AvatarAppearanceDialog::bodyURLChanged);
connect(Application::getInstance(), &Application::fullAvatarURLChanged, this, &AvatarAppearanceDialog::fullAvatarURLChanged);
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);
}
void AvatarAppearanceDialog::useSeparateBodyAndHead(bool checked) {
QUrl headURL(ui.faceURLEdit->text());
QUrl bodyURL(ui.skeletonURLEdit->text());
DependencyManager::get<AvatarManager>()->getMyAvatar()->useHeadAndBodyURLs(headURL, bodyURL);
setUseFullAvatar(!checked);
}
void AvatarAppearanceDialog::useFullAvatar(bool checked) {
QUrl fullAvatarURL(ui.fullAvatarURLEdit->text());
DependencyManager::get<AvatarManager>()->getMyAvatar()->useFullAvatarURL(fullAvatarURL);
setUseFullAvatar(checked);
}
void AvatarAppearanceDialog::setUseFullAvatar(bool useFullAvatar) {
_useFullAvatar = useFullAvatar;
ui.faceURLEdit->setEnabled(!_useFullAvatar);
ui.skeletonURLEdit->setEnabled(!_useFullAvatar);
ui.fullAvatarURLEdit->setEnabled(_useFullAvatar);
ui.useFullAvatar->setChecked(_useFullAvatar);
ui.useSeparateBodyAndHead->setChecked(!_useFullAvatar);
QPointer<PreferencesDialog> prefs = DependencyManager::get<DialogsManager>()->getPreferencesDialog();
if (prefs) { // Preferences dialog may have been closed
prefs->avatarDescriptionChanged();
}
}
void AvatarAppearanceDialog::headURLChanged(const QString& newValue, const QString& modelName) {
ui.faceURLEdit->setText(newValue);
setUseFullAvatar(false);
ui.headNameLabel->setText("Head - " + modelName);
}
void AvatarAppearanceDialog::bodyURLChanged(const QString& newValue, const QString& modelName) {
ui.skeletonURLEdit->setText(newValue);
setUseFullAvatar(false);
ui.bodyNameLabel->setText("Body - " + modelName);
}
void AvatarAppearanceDialog::fullAvatarURLChanged(const QString& newValue, const QString& modelName) {
ui.fullAvatarURLEdit->setText(newValue);
setUseFullAvatar(true);
ui.fullAvatarNameLabel->setText("Full Avatar - " + modelName);
}
void AvatarAppearanceDialog::accept() {
saveAvatarAppearance();
QPointer<PreferencesDialog> prefs = DependencyManager::get<DialogsManager>()->getPreferencesDialog();
if (prefs) { // Preferences dialog may have been closed
prefs->avatarDescriptionChanged();
}
close();
delete _marketplaceWindow;
_marketplaceWindow = NULL;
}
void AvatarAppearanceDialog::setHeadUrl(QString modelUrl) {
ui.faceURLEdit->setText(modelUrl);
}
void AvatarAppearanceDialog::setSkeletonUrl(QString modelUrl) {
ui.skeletonURLEdit->setText(modelUrl);
}
void AvatarAppearanceDialog::openFullAvatarModelBrowser() {
auto MARKETPLACE_URL = NetworkingConstants::METAVERSE_SERVER_URL.toString() + "/marketplace?category=avatars";
auto WIDTH = 900;
auto HEIGHT = 700;
if (!_marketplaceWindow) {
_marketplaceWindow = new WebWindowClass("Marketplace", MARKETPLACE_URL, WIDTH, HEIGHT, false);
}
_marketplaceWindow->setVisible(true);
}
void AvatarAppearanceDialog::openHeadModelBrowser() {
auto MARKETPLACE_URL = NetworkingConstants::METAVERSE_SERVER_URL.toString() + "/marketplace?category=avatars";
auto WIDTH = 900;
auto HEIGHT = 700;
if (!_marketplaceWindow) {
_marketplaceWindow = new WebWindowClass("Marketplace", MARKETPLACE_URL, WIDTH, HEIGHT, false);
}
_marketplaceWindow->setVisible(true);
}
void AvatarAppearanceDialog::openBodyModelBrowser() {
auto MARKETPLACE_URL = NetworkingConstants::METAVERSE_SERVER_URL.toString() + "/marketplace?category=avatars";
auto WIDTH = 900;
auto HEIGHT = 700;
if (!_marketplaceWindow) {
_marketplaceWindow = new WebWindowClass("Marketplace", MARKETPLACE_URL, WIDTH, HEIGHT, false);
}
_marketplaceWindow->setVisible(true);
}
void AvatarAppearanceDialog::resizeEvent(QResizeEvent *resizeEvent) {
// keep buttons panel at the bottom
ui.buttonsPanel->setGeometry(0,
size().height() - ui.buttonsPanel->height(),
size().width(),
ui.buttonsPanel->height());
// set width and height of srcollarea to match bottom panel and width
ui.scrollArea->setGeometry(ui.scrollArea->geometry().x(), ui.scrollArea->geometry().y(),
size().width(),
size().height() - ui.buttonsPanel->height() - ui.scrollArea->geometry().y());
}
void AvatarAppearanceDialog::loadAvatarAppearance() {
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
_useFullAvatar = myAvatar->getUseFullAvatar();
_fullAvatarURLString = myAvatar->getFullAvatarURLFromPreferences().toString();
_headURLString = myAvatar->getHeadURLFromPreferences().toString();
_bodyURLString = myAvatar->getBodyURLFromPreferences().toString();
ui.fullAvatarURLEdit->setText(_fullAvatarURLString);
ui.faceURLEdit->setText(_headURLString);
ui.skeletonURLEdit->setText(_bodyURLString);
setUseFullAvatar(_useFullAvatar);
}
void AvatarAppearanceDialog::saveAvatarAppearance() {
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
QUrl headURL(ui.faceURLEdit->text());
QString headURLString = headURL.toString();
QUrl bodyURL(ui.skeletonURLEdit->text());
QString bodyURLString = bodyURL.toString();
QUrl fullAvatarURL(ui.fullAvatarURLEdit->text());
QString fullAvatarURLString = fullAvatarURL.toString();
bool somethingChanged =
_useFullAvatar != myAvatar->getUseFullAvatar() ||
fullAvatarURLString != myAvatar->getFullAvatarURLFromPreferences().toString() ||
headURLString != myAvatar->getHeadURLFromPreferences().toString() ||
bodyURLString != myAvatar->getBodyURLFromPreferences().toString();
if (somethingChanged) {
if (_useFullAvatar) {
myAvatar->useFullAvatarURL(fullAvatarURL);
} else {
myAvatar->useHeadAndBodyURLs(headURL, bodyURL);
}
}
}

View file

@ -1,64 +0,0 @@
//
// AvatarAppearanceDialog.h
// interface/src/ui
//
// Created by Stojce Slavkovski on 2/20/14.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_AvatarAppearanceDialog_h
#define hifi_AvatarAppearanceDialog_h
#include "ui_avatarAppearance.h"
#include <QDialog>
#include <QString>
#include "scripting/WebWindowClass.h"
class AvatarAppearanceDialog : public QDialog {
Q_OBJECT
public:
AvatarAppearanceDialog(QWidget* parent = nullptr);
protected:
void resizeEvent(QResizeEvent* resizeEvent);
private:
void loadAvatarAppearance();
void saveAvatarAppearance();
void openHeadModelBrowser();
void openBodyModelBrowser();
void openFullAvatarModelBrowser();
void setUseFullAvatar(bool useFullAvatar);
Ui_AvatarAppearanceDialog ui;
bool _useFullAvatar;
QString _headURLString;
QString _bodyURLString;
QString _fullAvatarURLString;
QString _displayNameString;
WebWindowClass* _marketplaceWindow = NULL;
private slots:
void accept();
void setHeadUrl(QString modelUrl);
void setSkeletonUrl(QString modelUrl);
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);
};
#endif // hifi_AvatarAppearanceDialog_h

View file

@ -20,7 +20,6 @@
#include "AddressBarDialog.h"
#include "AnimationsDialog.h"
#include "AttachmentsDialog.h"
#include "AvatarAppearanceDialog.h"
#include "BandwidthDialog.h"
#include "CachesSizeDialog.h"
#include "DiskCacheEditor.h"
@ -88,15 +87,6 @@ void DialogsManager::editPreferences() {
}
}
void DialogsManager::changeAvatarAppearance() {
if (!_avatarAppearanceDialog) {
maybeCreateDialog(_avatarAppearanceDialog);
_avatarAppearanceDialog->show();
} else {
_avatarAppearanceDialog->close();
}
}
void DialogsManager::editAttachments() {
if (!_attachmentsDialog) {
maybeCreateDialog(_attachmentsDialog);

View file

@ -34,7 +34,6 @@ class OctreeStatsDialog;
class PreferencesDialog;
class ScriptEditorWindow;
class QMessageBox;
class AvatarAppearanceDialog;
class DomainConnectionDialog;
class UpdateDialog;
@ -66,7 +65,6 @@ public slots:
void hmdTools(bool showTools);
void showScriptEditor();
void showIRCLink();
void changeAvatarAppearance();
void showDomainConnectionDialog();
// Application Update
@ -110,7 +108,6 @@ private:
QPointer<OctreeStatsDialog> _octreeStatsDialog;
QPointer<PreferencesDialog> _preferencesDialog;
QPointer<ScriptEditorWindow> _scriptEditor;
QPointer<AvatarAppearanceDialog> _avatarAppearanceDialog;
QPointer<DomainConnectionDialog> _domainConnectionDialog;
QPointer<UpdateDialog> _updateDialog;
};

View file

@ -47,45 +47,45 @@ PreferencesDialog::PreferencesDialog(QWidget* parent) :
connect(ui.buttonBrowseScriptsLocation, &QPushButton::clicked, this, &PreferencesDialog::openScriptsLocationBrowser);
connect(ui.buttonReloadDefaultScripts, &QPushButton::clicked, Application::getInstance(), &Application::loadDefaultScripts);
DialogsManager* dialogsManager = DependencyManager::get<DialogsManager>().data();
connect(ui.buttonChangeApperance, &QPushButton::clicked, dialogsManager, &DialogsManager::changeAvatarAppearance);
connect(Application::getInstance(), &Application::headURLChanged, this, &PreferencesDialog::headURLChanged);
connect(Application::getInstance(), &Application::bodyURLChanged, this, &PreferencesDialog::bodyURLChanged);
connect(ui.buttonChangeAppearance, &QPushButton::clicked, this, &PreferencesDialog::openFullAvatarModelBrowser);
connect(ui.appearanceDescription, &QLineEdit::textChanged, this, [this](const QString& url) {
this->fullAvatarURLChanged(url, "");
});
connect(Application::getInstance(), &Application::fullAvatarURLChanged, this, &PreferencesDialog::fullAvatarURLChanged);
// move dialog to left side
move(parentWidget()->geometry().topLeft());
setFixedHeight(parentWidget()->size().height() - PREFERENCES_HEIGHT_PADDING);
ui.apperanceDescription->setText(DependencyManager::get<AvatarManager>()->getMyAvatar()->getModelDescription());
UIUtil::scaleWidgetFontSizes(this);
}
void PreferencesDialog::avatarDescriptionChanged() {
ui.apperanceDescription->setText(DependencyManager::get<AvatarManager>()->getMyAvatar()->getModelDescription());
}
void PreferencesDialog::headURLChanged(const QString& newValue, const QString& modelName) {
ui.apperanceDescription->setText(DependencyManager::get<AvatarManager>()->getMyAvatar()->getModelDescription());
}
void PreferencesDialog::bodyURLChanged(const QString& newValue, const QString& modelName) {
ui.apperanceDescription->setText(DependencyManager::get<AvatarManager>()->getMyAvatar()->getModelDescription());
}
void PreferencesDialog::fullAvatarURLChanged(const QString& newValue, const QString& modelName) {
ui.apperanceDescription->setText(DependencyManager::get<AvatarManager>()->getMyAvatar()->getModelDescription());
ui.appearanceDescription->setText(newValue);
const QString APPEARANCE_LABEL_TEXT("Appearance: ");
ui.appearanceLabel->setText(APPEARANCE_LABEL_TEXT + modelName);
DependencyManager::get<AvatarManager>()->getMyAvatar()->useFullAvatarURL(newValue, modelName);
}
void PreferencesDialog::accept() {
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
_lastGoodAvatarURL = myAvatar->getFullAvatarURLFromPreferences();
_lastGoodAvatarName = myAvatar->getFullAvatarModelName();
savePreferences();
close();
delete _marketplaceWindow;
_marketplaceWindow = NULL;
}
void PreferencesDialog::restoreLastGoodAvatar() {
fullAvatarURLChanged(_lastGoodAvatarURL.toString(), _lastGoodAvatarName);
}
void PreferencesDialog::reject() {
restoreLastGoodAvatar();
QDialog::reject();
}
void PreferencesDialog::openSnapshotLocationBrowser() {
QString dir = QFileDialog::getExistingDirectory(this, tr("Snapshots Location"),
QStandardPaths::writableLocation(QStandardPaths::DesktopLocation),
@ -103,6 +103,16 @@ void PreferencesDialog::openScriptsLocationBrowser() {
ui.scriptsLocationEdit->setText(dir);
}
}
void PreferencesDialog::openFullAvatarModelBrowser() {
const auto MARKETPLACE_URL = NetworkingConstants::METAVERSE_SERVER_URL.toString() + "/marketplace?category=avatars";
const auto WIDTH = 900;
const auto HEIGHT = 700;
if (!_marketplaceWindow) {
_marketplaceWindow = new WebWindowClass("Marketplace", MARKETPLACE_URL, WIDTH, HEIGHT, false);
}
_marketplaceWindow->setVisible(true);
}
void PreferencesDialog::resizeEvent(QResizeEvent *resizeEvent) {
@ -129,6 +139,10 @@ void PreferencesDialog::loadPreferences() {
ui.collisionSoundURLEdit->setText(myAvatar->getCollisionSoundURL());
_lastGoodAvatarURL = myAvatar->getFullAvatarURLFromPreferences();
_lastGoodAvatarName = myAvatar->getFullAvatarModelName();
fullAvatarURLChanged(_lastGoodAvatarURL.toString(), _lastGoodAvatarName);
ui.sendDataCheckBox->setChecked(!menuInstance->isOptionChecked(MenuOption::DisableActivityLogger));
ui.snapshotLocationEdit->setText(Snapshot::snapshotsLocation.get());
@ -211,6 +225,11 @@ void PreferencesDialog::savePreferences() {
myAvatar->setCollisionSoundURL(ui.collisionSoundURLEdit->text());
// MyAvatar persists its own data. If it doesn't agree with what the user has explicitly accepted, set it back to old values.
if (_lastGoodAvatarURL != myAvatar->getFullAvatarURLFromPreferences()) {
restoreLastGoodAvatar();
}
if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableActivityLogger)
!= ui.sendDataCheckBox->isChecked()) {
Menu::getInstance()->triggerOption(MenuOption::DisableActivityLogger);

View file

@ -33,6 +33,9 @@ protected:
private:
void loadPreferences();
void savePreferences();
QUrl _lastGoodAvatarURL;
QString _lastGoodAvatarName;
void restoreLastGoodAvatar();
Ui_PreferencesDialog ui;
@ -42,10 +45,10 @@ private:
private slots:
void accept();
void reject();
void openFullAvatarModelBrowser();
void openSnapshotLocationBrowser();
void openScriptsLocationBrowser();
void headURLChanged(const QString& newValue, const QString& modelName);
void bodyURLChanged(const QString& newValue, const QString& modelName);
void fullAvatarURLChanged(const QString& newValue, const QString& modelName);
};

View file

@ -1,471 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AvatarAppearanceDialog</class>
<widget class="QDialog" name="AvatarAppearanceDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>500</width>
<height>350</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>500</width>
<height>350</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>500</width>
<height>16777215</height>
</size>
</property>
<property name="font">
<font>
<pointsize>13</pointsize>
</font>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QScrollArea" name="scrollArea">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>-107</y>
<width>485</width>
<height>1550</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>30</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>30</number>
</property>
<property name="bottomMargin">
<number>10</number>
</property>
<item>
<layout class="QVBoxLayout" name="verticalLayout_4">
<property name="spacing">
<number>0</number>
</property>
<property name="topMargin">
<number>7</number>
</property>
<property name="bottomMargin">
<number>7</number>
</property>
<item>
<widget class="QRadioButton" name="useFullAvatar">
<property name="font">
<font>
<family>Arial</family>
</font>
</property>
<property name="text">
<string>Use single avatar with Body and Head</string>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_fullAvatar">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>10</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="fullAvatarNameLabel">
<property name="font">
<font>
<family>Arial</family>
</font>
</property>
<property name="text">
<string>Full Avatar</string>
</property>
<property name="alignment">
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
<property name="buddy">
<cstring>fullAvatarURLEdit</cstring>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_fullAvatar">
<item>
<widget class="QLineEdit" name="fullAvatarURLEdit">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_fullAvatar">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>5</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="buttonBrowseFullAvatar">
<property name="font">
<font>
<family>Arial</family>
</font>
</property>
<property name="text">
<string>Browse</string>
</property>
<property name="iconSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="QRadioButton" name="useSeparateBodyAndHead">
<property name="font">
<font>
<family>Arial</family>
</font>
</property>
<property name="text">
<string>Use separate Body and Head avatar files</string>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_separateParts_head">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>10</number>
</property>
<property name="topMargin">
<number>7</number>
</property>
<property name="bottomMargin">
<number>7</number>
</property>
<item>
<widget class="QLabel" name="headNameLabel">
<property name="font">
<font>
<family>Arial</family>
</font>
</property>
<property name="text">
<string>Head</string>
</property>
<property name="alignment">
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QLineEdit" name="faceURLEdit"/>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>5</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="buttonBrowseHead">
<property name="font">
<font>
<family>Arial</family>
</font>
</property>
<property name="text">
<string>Browse</string>
</property>
<property name="iconSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_separateParts_body">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>10</number>
</property>
<property name="topMargin">
<number>7</number>
</property>
<property name="bottomMargin">
<number>7</number>
</property>
<item>
<widget class="QLabel" name="bodyNameLabel">
<property name="font">
<font>
<family>Arial</family>
</font>
</property>
<property name="text">
<string>Body</string>
</property>
<property name="alignment">
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
<property name="buddy">
<cstring>skeletonURLEdit</cstring>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_skeletonURL">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QLineEdit" name="skeletonURLEdit">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_10">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>5</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="buttonBrowseBody">
<property name="font">
<font>
<family>Arial</family>
</font>
</property>
<property name="text">
<string>Browse</string>
</property>
<property name="iconSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<widget class="QFrame" name="buttonsPanel">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_12">
<item>
<layout class="QHBoxLayout" name="buttonsHBox_2">
<item>
<spacer name="horizontalSpacer_14">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="defaultButton">
<property name="font">
<font>
<family>Arial</family>
</font>
</property>
<property name="text">
<string>Close</string>
</property>
<property name="default">
<bool>true</bool>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
</ui>

View file

@ -275,7 +275,7 @@
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
<property name="buddy">
<cstring>apperanceDescription</cstring>
<cstring>appearanceDescription</cstring>
</property>
</widget>
</item>
@ -283,26 +283,21 @@
<item>
<layout class="QHBoxLayout" name="horizontalLayout_1_apperanceDescription">
<layout class="QHBoxLayout" name="horizontalLayout_1_appearanceDescription">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QLineEdit" name="apperanceDescription">
<widget class="QLineEdit" name="appearanceDescription">
<property name="font">
<font>
<family>Arial</family>
</font>
</property>
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_1_apperanceDescription">
<spacer name="horizontalSpacer_1_appearanceDescription">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
@ -318,7 +313,7 @@
</spacer>
</item>
<item>
<widget class="QPushButton" name="buttonChangeApperance">
<widget class="QPushButton" name="buttonChangeAppearance">
<property name="font">
<font>
<family>Arial</family>

View file

@ -70,6 +70,16 @@ AvatarData::~AvatarData() {
delete _referential;
}
// We cannot have a file-level variable (const or otherwise) in the header if it uses PathUtils, because that references Application, which will not yet initialized.
// Thus we have a static class getter, referencing a static class var.
QUrl AvatarData::_defaultFullAvatarModelUrl = {}; // In C++, if this initialization were in the header, every file would have it's own copy, even for class vars.
const QUrl AvatarData::defaultFullAvatarModelUrl() {
if (_defaultFullAvatarModelUrl.isEmpty()) {
_defaultFullAvatarModelUrl = QUrl::fromLocalFile(PathUtils::resourcesPath() + "meshes/defaultAvatar_full.fst");
}
return _defaultFullAvatarModelUrl;
}
const glm::vec3& AvatarData::getPosition() const {
if (_referential) {
_referential->update();
@ -899,7 +909,7 @@ void AvatarData::setFaceModelURL(const QUrl& faceModelURL) {
}
void AvatarData::setSkeletonModelURL(const QUrl& skeletonModelURL) {
_skeletonModelURL = skeletonModelURL.isEmpty() ? DEFAULT_BODY_MODEL_URL : skeletonModelURL;
_skeletonModelURL = skeletonModelURL.isEmpty() ? AvatarData::defaultFullAvatarModelUrl() : skeletonModelURL;
qCDebug(avatars) << "Changing skeleton model for avatar to" << _skeletonModelURL.toString();

View file

@ -54,6 +54,7 @@ typedef unsigned long long quint64;
#include "AABox.h"
#include "HandData.h"
#include "HeadData.h"
#include "PathUtils.h"
#include "Player.h"
#include "Recorder.h"
#include "Referential.h"
@ -107,12 +108,7 @@ const float MAX_AUDIO_LOUDNESS = 1000.0; // close enough for mouth animation
const int AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS = 1000;
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");
const QString DEFAULT_HEAD_MODEL_NAME = QString("Robot");
const QString DEFAULT_BODY_MODEL_NAME = QString("Robot");
// See also static AvatarData::defaultFullAvatarModelUrl().
const QString DEFAULT_FULL_AVATAR_MODEL_NAME = QString("Default");
@ -163,6 +159,8 @@ public:
AvatarData();
virtual ~AvatarData();
static const QUrl defaultFullAvatarModelUrl();
virtual bool isMyAvatar() const { return false; }
const QUuid& getSessionUUID() const { return _sessionUUID; }
@ -401,6 +399,7 @@ protected:
SimpleMovingAverage _averageBytesReceived;
private:
static QUrl _defaultFullAvatarModelUrl;
// privatize the copy constructor and assignment operator so they cannot be called
AvatarData(const AvatarData&);
AvatarData& operator= (const AvatarData&);