Save attachment data for attachment model/skeleton model combinations, let

scripts use those saved parameters so that you can tweak the location of
(for example) the gun and have it saved appropriately.
This commit is contained in:
Andrzej Kapolka 2014-05-08 18:00:41 -07:00
parent acab09b89a
commit c424f6ce69
6 changed files with 120 additions and 18 deletions

View file

@ -513,6 +513,55 @@ void MyAvatar::loadData(QSettings* settings) {
settings->endGroup();
}
void MyAvatar::saveAttachmentData(const AttachmentData& attachment) const {
QSettings* settings = Application::getInstance()->lockSettings();
settings->beginGroup("savedAttachmentData");
settings->beginGroup(_skeletonModel.getURL().toString());
settings->beginGroup(attachment.modelURL.toString());
settings->setValue("jointName", attachment.jointName);
settings->setValue("translation_x", attachment.translation.x);
settings->setValue("translation_y", attachment.translation.y);
settings->setValue("translation_z", attachment.translation.z);
glm::vec3 eulers = safeEulerAngles(attachment.rotation);
settings->setValue("rotation_x", eulers.x);
settings->setValue("rotation_y", eulers.y);
settings->setValue("rotation_z", eulers.z);
settings->setValue("scale", attachment.scale);
settings->endGroup();
settings->endGroup();
settings->endGroup();
Application::getInstance()->unlockSettings();
}
AttachmentData MyAvatar::loadAttachmentData(const QUrl& modelURL) const {
QSettings* settings = Application::getInstance()->lockSettings();
settings->beginGroup("savedAttachmentData");
settings->beginGroup(_skeletonModel.getURL().toString());
settings->beginGroup(modelURL.toString());
AttachmentData attachment;
attachment.modelURL = modelURL;
attachment.jointName = settings->value("jointName").toString();
attachment.translation.x = loadSetting(settings, "translation_x", 0.0f);
attachment.translation.y = loadSetting(settings, "translation_y", 0.0f);
attachment.translation.z = loadSetting(settings, "translation_z", 0.0f);
glm::vec3 eulers;
eulers.x = loadSetting(settings, "rotation_x", 0.0f);
eulers.y = loadSetting(settings, "rotation_y", 0.0f);
eulers.z = loadSetting(settings, "rotation_z", 0.0f);
attachment.rotation = glm::quat(eulers);
attachment.scale = loadSetting(settings, "scale", 1.0f);
settings->endGroup();
settings->endGroup();
settings->endGroup();
Application::getInstance()->unlockSettings();
return attachment;
}
int MyAvatar::parseDataAtOffset(const QByteArray& packet, int offset) {
qDebug() << "Error: ignoring update packet for MyAvatar"
<< " packetLength = " << packet.size()
@ -592,6 +641,23 @@ void MyAvatar::setAttachmentData(const QVector<AttachmentData>& attachmentData)
_billboardValid = false;
}
void MyAvatar::attach(const QString& modelURL, const QString& jointName, const glm::vec3& translation,
const glm::quat& rotation, float scale, bool allowDuplicates, bool useSaved) {
if (QThread::currentThread() != thread()) {
Avatar::attach(modelURL, jointName, translation, rotation, scale, allowDuplicates, useSaved);
return;
}
if (useSaved) {
AttachmentData attachment = loadAttachmentData(modelURL);
if (!attachment.jointName.isEmpty()) {
Avatar::attach(modelURL, attachment.jointName, attachment.translation,
attachment.rotation, attachment.scale, allowDuplicates, useSaved);
return;
}
}
Avatar::attach(modelURL, jointName, translation, rotation, scale, allowDuplicates, useSaved);
}
void MyAvatar::renderBody(RenderMode renderMode, float glowLevel) {
if (!(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) {
return; // wait until both models are loaded

View file

@ -66,6 +66,9 @@ public:
void saveData(QSettings* settings);
void loadData(QSettings* settings);
void saveAttachmentData(const AttachmentData& attachment) const;
AttachmentData loadAttachmentData(const QUrl& modelURL) const;
// Set what driving keys are being pressed to control thrust levels
void setDriveKeys(int key, float val) { _driveKeys[key] = val; };
bool getDriveKeys(int key) { return _driveKeys[key] != 0.f; };
@ -88,6 +91,10 @@ public:
virtual void setSkeletonModelURL(const QUrl& skeletonModelURL);
virtual void setAttachmentData(const QVector<AttachmentData>& attachmentData);
virtual void attach(const QString& modelURL, const QString& jointName = QString(),
const glm::vec3& translation = glm::vec3(), const glm::quat& rotation = glm::quat(), float scale = 1.0f,
bool allowDuplicates = false, bool useSaved = true);
virtual void setCollisionGroups(quint32 collisionGroups);
void setMotionBehaviorsByScript(quint32 flags);

View file

@ -76,27 +76,28 @@ void AttachmentsDialog::addAttachment(const AttachmentData& data) {
_attachments->insertWidget(_attachments->count() - 1, new AttachmentPanel(this, data));
}
static QDoubleSpinBox* createTranslationBox(AttachmentsDialog* dialog, float value) {
static QDoubleSpinBox* createTranslationBox(AttachmentPanel* panel, float value) {
QDoubleSpinBox* box = new QDoubleSpinBox();
box->setSingleStep(0.01);
box->setMinimum(-FLT_MAX);
box->setMaximum(FLT_MAX);
box->setValue(value);
dialog->connect(box, SIGNAL(valueChanged(double)), SLOT(updateAttachmentData()));
panel->connect(box, SIGNAL(valueChanged(double)), SLOT(updateAttachmentData()));
return box;
}
static QDoubleSpinBox* createRotationBox(AttachmentsDialog* dialog, float value) {
static QDoubleSpinBox* createRotationBox(AttachmentPanel* panel, float value) {
QDoubleSpinBox* box = new QDoubleSpinBox();
box->setMinimum(-180.0);
box->setMaximum(180.0);
box->setWrapping(true);
box->setValue(value);
dialog->connect(box, SIGNAL(valueChanged(double)), SLOT(updateAttachmentData()));
panel->connect(box, SIGNAL(valueChanged(double)), SLOT(updateAttachmentData()));
return box;
}
AttachmentPanel::AttachmentPanel(AttachmentsDialog* dialog, const AttachmentData& data) {
AttachmentPanel::AttachmentPanel(AttachmentsDialog* dialog, const AttachmentData& data) :
_dialog(dialog) {
setFrameStyle(QFrame::StyledPanel);
QFormLayout* layout = new QFormLayout();
@ -107,7 +108,7 @@ AttachmentPanel::AttachmentPanel(AttachmentsDialog* dialog, const AttachmentData
layout->addRow("Model URL:", urlBox);
urlBox->addWidget(_modelURL = new QLineEdit(data.modelURL.toString()), 1);
_modelURL->setText(data.modelURL.toString());
dialog->connect(_modelURL, SIGNAL(returnPressed()), SLOT(updateAttachmentData()));
connect(_modelURL, SIGNAL(returnPressed()), SLOT(modelURLChanged()));
QPushButton* chooseURL = new QPushButton("Choose");
urlBox->addWidget(chooseURL);
connect(chooseURL, SIGNAL(clicked(bool)), SLOT(chooseModelURL()));
@ -120,26 +121,26 @@ AttachmentPanel::AttachmentPanel(AttachmentsDialog* dialog, const AttachmentData
}
}
_jointName->setCurrentText(data.jointName);
dialog->connect(_jointName, SIGNAL(currentIndexChanged(int)), SLOT(updateAttachmentData()));
connect(_jointName, SIGNAL(currentIndexChanged(int)), SLOT(updateAttachmentData()));
QHBoxLayout* translationBox = new QHBoxLayout();
translationBox->addWidget(_translationX = createTranslationBox(dialog, data.translation.x));
translationBox->addWidget(_translationY = createTranslationBox(dialog, data.translation.y));
translationBox->addWidget(_translationZ = createTranslationBox(dialog, data.translation.z));
translationBox->addWidget(_translationX = createTranslationBox(this, data.translation.x));
translationBox->addWidget(_translationY = createTranslationBox(this, data.translation.y));
translationBox->addWidget(_translationZ = createTranslationBox(this, data.translation.z));
layout->addRow("Translation:", translationBox);
QHBoxLayout* rotationBox = new QHBoxLayout();
glm::vec3 eulers = glm::degrees(safeEulerAngles(data.rotation));
rotationBox->addWidget(_rotationX = createRotationBox(dialog, eulers.x));
rotationBox->addWidget(_rotationY = createRotationBox(dialog, eulers.y));
rotationBox->addWidget(_rotationZ = createRotationBox(dialog, eulers.z));
rotationBox->addWidget(_rotationX = createRotationBox(this, eulers.x));
rotationBox->addWidget(_rotationY = createRotationBox(this, eulers.y));
rotationBox->addWidget(_rotationZ = createRotationBox(this, eulers.z));
layout->addRow("Rotation:", rotationBox);
layout->addRow("Scale:", _scale = new QDoubleSpinBox());
_scale->setSingleStep(0.01);
_scale->setMaximum(FLT_MAX);
_scale->setValue(data.scale);
dialog->connect(_scale, SIGNAL(valueChanged(double)), SLOT(updateAttachmentData()));
connect(_scale, SIGNAL(valueChanged(double)), SLOT(updateAttachmentData()));
QPushButton* remove = new QPushButton("Delete");
layout->addRow(remove);
@ -165,5 +166,30 @@ void AttachmentPanel::chooseModelURL() {
void AttachmentPanel::setModelURL(const QString& url) {
_modelURL->setText(url);
emit _modelURL->returnPressed();
modelURLChanged();
}
void AttachmentPanel::modelURLChanged() {
// check for saved attachment data
AttachmentData attachment = Application::getInstance()->getAvatar()->loadAttachmentData(_modelURL->text());
if (!attachment.jointName.isEmpty()) {
_jointName->setCurrentText(attachment.jointName);
_translationX->setValue(attachment.translation.x);
_translationY->setValue(attachment.translation.y);
_translationZ->setValue(attachment.translation.z);
glm::vec3 eulers = glm::degrees(safeEulerAngles(attachment.rotation));
_rotationX->setValue(eulers.x);
_rotationY->setValue(eulers.y);
_rotationZ->setValue(eulers.z);
_scale->setValue(attachment.scale);
}
_dialog->updateAttachmentData();
}
void AttachmentPanel::updateAttachmentData() {
// save the attachment data under the model URL (if any)
if (!_modelURL->text().isEmpty()) {
Application::getInstance()->getAvatar()->saveAttachmentData(getAttachmentData());
}
_dialog->updateAttachmentData();
}

View file

@ -60,9 +60,12 @@ private slots:
void chooseModelURL();
void setModelURL(const QString& url);
void modelURLChanged();
void updateAttachmentData();
private:
AttachmentsDialog* _dialog;
QLineEdit* _modelURL;
QComboBox* _jointName;
QDoubleSpinBox* _translationX;

View file

@ -686,11 +686,11 @@ void AvatarData::setAttachmentData(const QVector<AttachmentData>& attachmentData
}
void AvatarData::attach(const QString& modelURL, const QString& jointName, const glm::vec3& translation,
const glm::quat& rotation, float scale, bool allowDuplicates) {
const glm::quat& rotation, float scale, bool allowDuplicates, bool useSaved) {
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "attach", Q_ARG(const QString&, modelURL), Q_ARG(const QString&, jointName),
Q_ARG(const glm::vec3&, translation), Q_ARG(const glm::quat&, rotation),
Q_ARG(float, scale), Q_ARG(bool, allowDuplicates));
Q_ARG(float, scale), Q_ARG(bool, allowDuplicates), Q_ARG(bool, useSaved));
return;
}
QVector<AttachmentData> attachmentData = getAttachmentData();

View file

@ -242,7 +242,7 @@ public:
Q_INVOKABLE virtual void attach(const QString& modelURL, const QString& jointName = QString(),
const glm::vec3& translation = glm::vec3(), const glm::quat& rotation = glm::quat(), float scale = 1.0f,
bool allowDuplicates = false);
bool allowDuplicates = false, bool useSaved = true);
Q_INVOKABLE void detachOne(const QString& modelURL, const QString& jointName = QString());
Q_INVOKABLE void detachAll(const QString& modelURL, const QString& jointName = QString());