mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 04:57:58 +02:00
Network, Preferences and UI support for soft attachments
Added an isSoft field to the AttachmentData which is edited by the Attachment Dialog Menu, sent over the network via AvatarData identity packets and saved in the Interface.ini preferences. AvatarData and AvatarBulkData version number has been bumped. Changed Avatar attachment collections to use smart pointers to models instead of raw ones. Removed _unusedAttachmentModels. I don't think the caching was worth the added code complexity.
This commit is contained in:
parent
6b5b272cd7
commit
1618e0a92f
12 changed files with 132 additions and 54 deletions
|
@ -3017,8 +3017,7 @@ void Application::update(float deltaTime) {
|
||||||
getEntities()->update(); // update the models...
|
getEntities()->update(); // update the models...
|
||||||
}
|
}
|
||||||
|
|
||||||
myAvatar->harvestResultsFromPhysicsSimulation();
|
myAvatar->harvestResultsFromPhysicsSimulation(deltaTime);
|
||||||
myAvatar->simulateAttachments(deltaTime);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
#include "world.h"
|
#include "world.h"
|
||||||
#include "InterfaceLogging.h"
|
#include "InterfaceLogging.h"
|
||||||
|
#include "SoftAttachmentModel.h"
|
||||||
#include <Rig.h>
|
#include <Rig.h>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -108,9 +109,6 @@ Avatar::Avatar(RigPointer rig) :
|
||||||
|
|
||||||
Avatar::~Avatar() {
|
Avatar::~Avatar() {
|
||||||
assert(_motionState == nullptr);
|
assert(_motionState == nullptr);
|
||||||
for(auto attachment : _unusedAttachments) {
|
|
||||||
delete attachment;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const float BILLBOARD_LOD_DISTANCE = 40.0f;
|
const float BILLBOARD_LOD_DISTANCE = 40.0f;
|
||||||
|
@ -257,6 +255,8 @@ void Avatar::simulate(float deltaTime) {
|
||||||
// until velocity is included in AvatarData update message.
|
// until velocity is included in AvatarData update message.
|
||||||
//_position += _velocity * deltaTime;
|
//_position += _velocity * deltaTime;
|
||||||
measureMotionDerivatives(deltaTime);
|
measureMotionDerivatives(deltaTime);
|
||||||
|
|
||||||
|
simulateAttachments(deltaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Avatar::isLookingAtMe(AvatarSharedPointer avatar) const {
|
bool Avatar::isLookingAtMe(AvatarSharedPointer avatar) const {
|
||||||
|
@ -324,7 +324,7 @@ bool Avatar::addToScene(AvatarSharedPointer self, std::shared_ptr<render::Scene>
|
||||||
_skeletonModel.addToScene(scene, pendingChanges);
|
_skeletonModel.addToScene(scene, pendingChanges);
|
||||||
getHead()->getFaceModel().addToScene(scene, pendingChanges);
|
getHead()->getFaceModel().addToScene(scene, pendingChanges);
|
||||||
|
|
||||||
for (auto attachmentModel : _attachmentModels) {
|
for (auto& attachmentModel : _attachmentModels) {
|
||||||
attachmentModel->addToScene(scene, pendingChanges);
|
attachmentModel->addToScene(scene, pendingChanges);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,7 +335,7 @@ void Avatar::removeFromScene(AvatarSharedPointer self, std::shared_ptr<render::S
|
||||||
pendingChanges.removeItem(_renderItemID);
|
pendingChanges.removeItem(_renderItemID);
|
||||||
_skeletonModel.removeFromScene(scene, pendingChanges);
|
_skeletonModel.removeFromScene(scene, pendingChanges);
|
||||||
getHead()->getFaceModel().removeFromScene(scene, pendingChanges);
|
getHead()->getFaceModel().removeFromScene(scene, pendingChanges);
|
||||||
for (auto attachmentModel : _attachmentModels) {
|
for (auto& attachmentModel : _attachmentModels) {
|
||||||
attachmentModel->removeFromScene(scene, pendingChanges);
|
attachmentModel->removeFromScene(scene, pendingChanges);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -565,15 +565,14 @@ void Avatar::fixupModelsInScene() {
|
||||||
faceModel.removeFromScene(scene, pendingChanges);
|
faceModel.removeFromScene(scene, pendingChanges);
|
||||||
faceModel.addToScene(scene, pendingChanges);
|
faceModel.addToScene(scene, pendingChanges);
|
||||||
}
|
}
|
||||||
for (auto attachmentModel : _attachmentModels) {
|
for (auto& attachmentModel : _attachmentModels) {
|
||||||
if (attachmentModel->isRenderable() && attachmentModel->needsFixupInScene()) {
|
if (attachmentModel->isRenderable() && attachmentModel->needsFixupInScene()) {
|
||||||
attachmentModel->removeFromScene(scene, pendingChanges);
|
attachmentModel->removeFromScene(scene, pendingChanges);
|
||||||
attachmentModel->addToScene(scene, pendingChanges);
|
attachmentModel->addToScene(scene, pendingChanges);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (auto attachmentModelToRemove : _attachmentsToRemove) {
|
for (auto& attachmentModelToRemove : _attachmentsToRemove) {
|
||||||
attachmentModelToRemove->removeFromScene(scene, pendingChanges);
|
attachmentModelToRemove->removeFromScene(scene, pendingChanges);
|
||||||
_unusedAttachments << attachmentModelToRemove;
|
|
||||||
}
|
}
|
||||||
_attachmentsToRemove.clear();
|
_attachmentsToRemove.clear();
|
||||||
scene->enqueuePendingChanges(pendingChanges);
|
scene->enqueuePendingChanges(pendingChanges);
|
||||||
|
@ -603,13 +602,20 @@ bool Avatar::shouldRenderHead(const RenderArgs* renderArgs) const {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// virtual
|
||||||
void Avatar::simulateAttachments(float deltaTime) {
|
void Avatar::simulateAttachments(float deltaTime) {
|
||||||
for (int i = 0; i < _attachmentModels.size(); i++) {
|
for (int i = 0; i < _attachmentModels.size(); i++) {
|
||||||
const AttachmentData& attachment = _attachmentData.at(i);
|
const AttachmentData& attachment = _attachmentData.at(i);
|
||||||
Model* model = _attachmentModels.at(i);
|
auto& model = _attachmentModels.at(i);
|
||||||
int jointIndex = getJointIndex(attachment.jointName);
|
int jointIndex = getJointIndex(attachment.jointName);
|
||||||
glm::vec3 jointPosition;
|
glm::vec3 jointPosition;
|
||||||
glm::quat jointRotation;
|
glm::quat jointRotation;
|
||||||
|
if (attachment.isSoft) {
|
||||||
|
// soft attachments do not have transform offsets
|
||||||
|
model->setTranslation(getPosition());
|
||||||
|
model->setRotation(getOrientation() * Quaternions::Y_180);
|
||||||
|
model->simulate(deltaTime);
|
||||||
|
} else {
|
||||||
if (_skeletonModel.getJointPositionInWorldFrame(jointIndex, jointPosition) &&
|
if (_skeletonModel.getJointPositionInWorldFrame(jointIndex, jointPosition) &&
|
||||||
_skeletonModel.getJointRotationInWorldFrame(jointIndex, jointRotation)) {
|
_skeletonModel.getJointRotationInWorldFrame(jointIndex, jointRotation)) {
|
||||||
model->setTranslation(jointPosition + jointRotation * attachment.translation * getUniformScale());
|
model->setTranslation(jointPosition + jointRotation * attachment.translation * getUniformScale());
|
||||||
|
@ -620,6 +626,7 @@ void Avatar::simulateAttachments(float deltaTime) {
|
||||||
model->simulate(deltaTime);
|
model->simulate(deltaTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Avatar::updateJointMappings() {
|
void Avatar::updateJointMappings() {
|
||||||
|
@ -940,13 +947,48 @@ void Avatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
|
||||||
_skeletonModel.setURL(_skeletonModelURL);
|
_skeletonModel.setURL(_skeletonModelURL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// create new model, can return an instance of a SoftAttachmentModel rather then Model
|
||||||
|
static std::shared_ptr<Model> allocateAttachmentModel(bool isSoft, RigPointer rigOverride) {
|
||||||
|
if (isSoft) {
|
||||||
|
// cast to std::shared_ptr<Model>
|
||||||
|
return std::dynamic_pointer_cast<Model>(std::make_shared<SoftAttachmentModel>(std::make_shared<Rig>(), nullptr, rigOverride));
|
||||||
|
} else {
|
||||||
|
return std::make_shared<Model>(std::make_shared<Rig>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Avatar::setAttachmentData(const QVector<AttachmentData>& attachmentData) {
|
void Avatar::setAttachmentData(const QVector<AttachmentData>& attachmentData) {
|
||||||
AvatarData::setAttachmentData(attachmentData);
|
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QMetaObject::invokeMethod(this, "setAttachmentData", Qt::DirectConnection,
|
QMetaObject::invokeMethod(this, "setAttachmentData", Qt::DirectConnection,
|
||||||
Q_ARG(const QVector<AttachmentData>, attachmentData));
|
Q_ARG(const QVector<AttachmentData>, attachmentData));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto oldAttachmentData = _attachmentData;
|
||||||
|
AvatarData::setAttachmentData(attachmentData);
|
||||||
|
|
||||||
|
// if number of attachments has been reduced, remove excess models.
|
||||||
|
while (_attachmentModels.size() > attachmentData.size()) {
|
||||||
|
auto attachmentModel = _attachmentModels.back();
|
||||||
|
_attachmentModels.pop_back();
|
||||||
|
_attachmentsToRemove.push_back(attachmentModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < attachmentData.size(); i++) {
|
||||||
|
if (i == _attachmentModels.size()) {
|
||||||
|
// if number of attachments has been increased, we need to allocate a new model
|
||||||
|
_attachmentModels.push_back(allocateAttachmentModel(attachmentData[i].isSoft, _skeletonModel.getRig()));
|
||||||
|
}
|
||||||
|
else if (i < oldAttachmentData.size() && oldAttachmentData[i].isSoft != attachmentData[i].isSoft) {
|
||||||
|
// if the attachment has changed type, we need to re-allocate a new one.
|
||||||
|
_attachmentsToRemove.push_back(_attachmentModels[i]);
|
||||||
|
_attachmentModels[i] = allocateAttachmentModel(attachmentData[i].isSoft, _skeletonModel.getRig());
|
||||||
|
}
|
||||||
|
_attachmentModels[i]->setURL(attachmentData[i].modelURL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// AJT: TODO REMOVE
|
||||||
|
/*
|
||||||
// make sure we have as many models as attachments
|
// make sure we have as many models as attachments
|
||||||
while (_attachmentModels.size() < attachmentData.size()) {
|
while (_attachmentModels.size() < attachmentData.size()) {
|
||||||
Model* model = nullptr;
|
Model* model = nullptr;
|
||||||
|
@ -959,16 +1001,20 @@ void Avatar::setAttachmentData(const QVector<AttachmentData>& attachmentData) {
|
||||||
_attachmentModels.append(model);
|
_attachmentModels.append(model);
|
||||||
}
|
}
|
||||||
while (_attachmentModels.size() > attachmentData.size()) {
|
while (_attachmentModels.size() > attachmentData.size()) {
|
||||||
auto attachmentModel = _attachmentModels.takeLast();
|
auto attachmentModel = _attachmentModels.back();
|
||||||
_attachmentsToRemove << attachmentModel;
|
_attachmentModels.pop_back();
|
||||||
|
_attachmentsToRemove.push_back(attachmentModel);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
// update the urls
|
// update the urls
|
||||||
for (int i = 0; i < attachmentData.size(); i++) {
|
for (int i = 0; i < attachmentData.size(); i++) {
|
||||||
_attachmentModels[i]->setURL(attachmentData.at(i).modelURL);
|
_attachmentModels[i]->setURL(attachmentData.at(i).modelURL);
|
||||||
_attachmentModels[i]->setSnapModelToCenter(true);
|
_attachmentModels[i]->setSnapModelToCenter(true);
|
||||||
_attachmentModels[i]->setScaleToFit(true, getUniformScale() * _attachmentData.at(i).scale);
|
_attachmentModels[i]->setScaleToFit(true, getUniformScale() * _attachmentData.at(i).scale);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void Avatar::setBillboard(const QByteArray& billboard) {
|
void Avatar::setBillboard(const QByteArray& billboard) {
|
||||||
|
|
|
@ -68,7 +68,7 @@ public:
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
void simulate(float deltaTime);
|
void simulate(float deltaTime);
|
||||||
void simulateAttachments(float deltaTime);
|
virtual void simulateAttachments(float deltaTime);
|
||||||
|
|
||||||
virtual void render(RenderArgs* renderArgs, const glm::vec3& cameraPosition);
|
virtual void render(RenderArgs* renderArgs, const glm::vec3& cameraPosition);
|
||||||
|
|
||||||
|
@ -177,9 +177,9 @@ protected:
|
||||||
|
|
||||||
SkeletonModel _skeletonModel;
|
SkeletonModel _skeletonModel;
|
||||||
glm::vec3 _skeletonOffset;
|
glm::vec3 _skeletonOffset;
|
||||||
QVector<Model*> _attachmentModels;
|
std::vector<std::shared_ptr<Model>> _attachmentModels;
|
||||||
QVector<Model*> _attachmentsToRemove;
|
std::vector<std::shared_ptr<Model>> _attachmentsToRemove;
|
||||||
QVector<Model*> _unusedAttachments;
|
|
||||||
float _bodyYawDelta; // degrees/sec
|
float _bodyYawDelta; // degrees/sec
|
||||||
|
|
||||||
// These position histories and derivatives are in the world-frame.
|
// These position histories and derivatives are in the world-frame.
|
||||||
|
|
|
@ -201,6 +201,11 @@ MyAvatar::~MyAvatar() {
|
||||||
_lookAtTargetAvatar.reset();
|
_lookAtTargetAvatar.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// virtual
|
||||||
|
void MyAvatar::simulateAttachments(float deltaTime) {
|
||||||
|
// don't update attachments here, do it in harvestResultsFromPhysicsSimulation()
|
||||||
|
}
|
||||||
|
|
||||||
QByteArray MyAvatar::toByteArray(bool cullSmallChanges, bool sendAll) {
|
QByteArray MyAvatar::toByteArray(bool cullSmallChanges, bool sendAll) {
|
||||||
CameraMode mode = qApp->getCamera()->getMode();
|
CameraMode mode = qApp->getCamera()->getMode();
|
||||||
_globalPosition = getPosition();
|
_globalPosition = getPosition();
|
||||||
|
@ -621,6 +626,7 @@ void MyAvatar::saveData() {
|
||||||
settings.setValue("rotation_y", eulers.y);
|
settings.setValue("rotation_y", eulers.y);
|
||||||
settings.setValue("rotation_z", eulers.z);
|
settings.setValue("rotation_z", eulers.z);
|
||||||
settings.setValue("scale", attachment.scale);
|
settings.setValue("scale", attachment.scale);
|
||||||
|
settings.setValue("isSoft", attachment.isSoft);
|
||||||
}
|
}
|
||||||
settings.endArray();
|
settings.endArray();
|
||||||
|
|
||||||
|
@ -702,6 +708,7 @@ void MyAvatar::loadData() {
|
||||||
eulers.z = loadSetting(settings, "rotation_z", 0.0f);
|
eulers.z = loadSetting(settings, "rotation_z", 0.0f);
|
||||||
attachment.rotation = glm::quat(eulers);
|
attachment.rotation = glm::quat(eulers);
|
||||||
attachment.scale = loadSetting(settings, "scale", 1.0f);
|
attachment.scale = loadSetting(settings, "scale", 1.0f);
|
||||||
|
attachment.isSoft = settings.value("isSoft").toBool();
|
||||||
attachmentData.append(attachment);
|
attachmentData.append(attachment);
|
||||||
}
|
}
|
||||||
settings.endArray();
|
settings.endArray();
|
||||||
|
@ -1057,7 +1064,7 @@ void MyAvatar::prepareForPhysicsSimulation() {
|
||||||
_characterController.setFollowVelocity(_followVelocity);
|
_characterController.setFollowVelocity(_followVelocity);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::harvestResultsFromPhysicsSimulation() {
|
void MyAvatar::harvestResultsFromPhysicsSimulation(float deltaType) {
|
||||||
glm::vec3 position = getPosition();
|
glm::vec3 position = getPosition();
|
||||||
glm::quat orientation = getOrientation();
|
glm::quat orientation = getOrientation();
|
||||||
_characterController.getPositionAndOrientation(position, orientation);
|
_characterController.getPositionAndOrientation(position, orientation);
|
||||||
|
@ -1068,6 +1075,9 @@ void MyAvatar::harvestResultsFromPhysicsSimulation() {
|
||||||
} else {
|
} else {
|
||||||
setVelocity(_characterController.getLinearVelocity());
|
setVelocity(_characterController.getLinearVelocity());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// now that physics has adjusted our position, we can update attachements.
|
||||||
|
Avatar::simulateAttachments(deltaType);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::adjustSensorTransform() {
|
void MyAvatar::adjustSensorTransform() {
|
||||||
|
@ -1599,7 +1609,7 @@ void MyAvatar::maybeUpdateBillboard() {
|
||||||
if (_billboardValid || !(_skeletonModel.isLoadedWithTextures() && getHead()->getFaceModel().isLoadedWithTextures())) {
|
if (_billboardValid || !(_skeletonModel.isLoadedWithTextures() && getHead()->getFaceModel().isLoadedWithTextures())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
foreach (Model* model, _attachmentModels) {
|
for (auto& model : _attachmentModels) {
|
||||||
if (!model->isLoadedWithTextures()) {
|
if (!model->isLoadedWithTextures()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,6 +83,8 @@ public:
|
||||||
MyAvatar(RigPointer rig);
|
MyAvatar(RigPointer rig);
|
||||||
~MyAvatar();
|
~MyAvatar();
|
||||||
|
|
||||||
|
virtual void simulateAttachments(float deltaTime) override;
|
||||||
|
|
||||||
AudioListenerMode getAudioListenerModeHead() const { return FROM_HEAD; }
|
AudioListenerMode getAudioListenerModeHead() const { return FROM_HEAD; }
|
||||||
AudioListenerMode getAudioListenerModeCamera() const { return FROM_CAMERA; }
|
AudioListenerMode getAudioListenerModeCamera() const { return FROM_CAMERA; }
|
||||||
AudioListenerMode getAudioListenerModeCustom() const { return CUSTOM; }
|
AudioListenerMode getAudioListenerModeCustom() const { return CUSTOM; }
|
||||||
|
@ -204,7 +206,7 @@ public:
|
||||||
MyCharacterController* getCharacterController() { return &_characterController; }
|
MyCharacterController* getCharacterController() { return &_characterController; }
|
||||||
|
|
||||||
void prepareForPhysicsSimulation();
|
void prepareForPhysicsSimulation();
|
||||||
void harvestResultsFromPhysicsSimulation();
|
void harvestResultsFromPhysicsSimulation(float deltaTime);
|
||||||
void adjustSensorTransform();
|
void adjustSensorTransform();
|
||||||
|
|
||||||
const QString& getCollisionSoundURL() { return _collisionSoundURL; }
|
const QString& getCollisionSoundURL() { return _collisionSoundURL; }
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "SoftAttachmentModel.h"
|
#include "SoftAttachmentModel.h"
|
||||||
|
#include "InterfaceLogging.h"
|
||||||
|
|
||||||
SoftAttachmentModel::SoftAttachmentModel(RigPointer rig, QObject* parent, RigPointer rigOverride) :
|
SoftAttachmentModel::SoftAttachmentModel(RigPointer rig, QObject* parent, RigPointer rigOverride) :
|
||||||
Model(rig, parent),
|
Model(rig, parent),
|
||||||
|
@ -55,7 +56,7 @@ void SoftAttachmentModel::updateClusterMatrices(glm::vec3 modelPosition, glm::qu
|
||||||
// TODO: cache these look ups as an optimization
|
// TODO: cache these look ups as an optimization
|
||||||
int jointIndexOverride = getJointIndexOverride(cluster.jointIndex);
|
int jointIndexOverride = getJointIndexOverride(cluster.jointIndex);
|
||||||
glm::mat4 jointMatrix(glm::mat4::_null);
|
glm::mat4 jointMatrix(glm::mat4::_null);
|
||||||
if (jointIndexOverride >= 0 && jointIndexOverride < getJointStateCount()) {
|
if (jointIndexOverride >= 0 && jointIndexOverride < _rigOverride->getJointStateCount()) {
|
||||||
jointMatrix = _rigOverride->getJointTransform(jointIndexOverride);
|
jointMatrix = _rigOverride->getJointTransform(jointIndexOverride);
|
||||||
} else {
|
} else {
|
||||||
jointMatrix = _rig->getJointTransform(cluster.jointIndex);
|
jointMatrix = _rig->getJointTransform(cluster.jointIndex);
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QScrollArea>
|
#include <QScrollArea>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
#include <QCheckBox>
|
||||||
|
|
||||||
#include <avatar/AvatarManager.h>
|
#include <avatar/AvatarManager.h>
|
||||||
#include <avatar/MyAvatar.h>
|
#include <avatar/MyAvatar.h>
|
||||||
|
@ -147,6 +148,10 @@ AttachmentPanel::AttachmentPanel(AttachmentsDialog* dialog, const AttachmentData
|
||||||
_scale->setValue(data.scale);
|
_scale->setValue(data.scale);
|
||||||
connect(_scale, SIGNAL(valueChanged(double)), SLOT(updateAttachmentData()));
|
connect(_scale, SIGNAL(valueChanged(double)), SLOT(updateAttachmentData()));
|
||||||
|
|
||||||
|
layout->addRow("Is Soft:", _isSoft = new QCheckBox());
|
||||||
|
_isSoft->setChecked(data.isSoft);
|
||||||
|
connect(_isSoft, SIGNAL(stateChanged(int)), SLOT(updateAttachmentData()));
|
||||||
|
|
||||||
QPushButton* remove = new QPushButton("Delete");
|
QPushButton* remove = new QPushButton("Delete");
|
||||||
layout->addRow(remove);
|
layout->addRow(remove);
|
||||||
connect(remove, SIGNAL(clicked(bool)), SLOT(deleteLater()));
|
connect(remove, SIGNAL(clicked(bool)), SLOT(deleteLater()));
|
||||||
|
@ -160,6 +165,7 @@ AttachmentData AttachmentPanel::getAttachmentData() const {
|
||||||
data.translation = glm::vec3(_translationX->value(), _translationY->value(), _translationZ->value());
|
data.translation = glm::vec3(_translationX->value(), _translationY->value(), _translationZ->value());
|
||||||
data.rotation = glm::quat(glm::radians(glm::vec3(_rotationX->value(), _rotationY->value(), _rotationZ->value())));
|
data.rotation = glm::quat(glm::radians(glm::vec3(_rotationX->value(), _rotationY->value(), _rotationZ->value())));
|
||||||
data.scale = _scale->value();
|
data.scale = _scale->value();
|
||||||
|
data.isSoft = _isSoft->isChecked();
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,6 +233,7 @@ void AttachmentPanel::applyAttachmentData(const AttachmentData& attachment) {
|
||||||
_rotationY->setValue(eulers.y);
|
_rotationY->setValue(eulers.y);
|
||||||
_rotationZ->setValue(eulers.z);
|
_rotationZ->setValue(eulers.z);
|
||||||
_scale->setValue(attachment.scale);
|
_scale->setValue(attachment.scale);
|
||||||
|
_isSoft->setChecked(attachment.isSoft);
|
||||||
_applying = false;
|
_applying = false;
|
||||||
_dialog->updateAttachmentData();
|
_dialog->updateAttachmentData();
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,6 +77,7 @@ private:
|
||||||
QDoubleSpinBox* _rotationY;
|
QDoubleSpinBox* _rotationY;
|
||||||
QDoubleSpinBox* _rotationZ;
|
QDoubleSpinBox* _rotationZ;
|
||||||
QDoubleSpinBox* _scale;
|
QDoubleSpinBox* _scale;
|
||||||
|
QCheckBox* _isSoft;
|
||||||
bool _applying;
|
bool _applying;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1260,6 +1260,7 @@ void AvatarData::updateJointMappings() {
|
||||||
static const QString JSON_ATTACHMENT_URL = QStringLiteral("modelUrl");
|
static const QString JSON_ATTACHMENT_URL = QStringLiteral("modelUrl");
|
||||||
static const QString JSON_ATTACHMENT_JOINT_NAME = QStringLiteral("jointName");
|
static const QString JSON_ATTACHMENT_JOINT_NAME = QStringLiteral("jointName");
|
||||||
static const QString JSON_ATTACHMENT_TRANSFORM = QStringLiteral("transform");
|
static const QString JSON_ATTACHMENT_TRANSFORM = QStringLiteral("transform");
|
||||||
|
static const QString JSON_ATTACHMENT_IS_SOFT = QStringLiteral("isSoft");
|
||||||
|
|
||||||
QJsonObject AttachmentData::toJson() const {
|
QJsonObject AttachmentData::toJson() const {
|
||||||
QJsonObject result;
|
QJsonObject result;
|
||||||
|
@ -1278,6 +1279,7 @@ QJsonObject AttachmentData::toJson() const {
|
||||||
if (!transform.isIdentity()) {
|
if (!transform.isIdentity()) {
|
||||||
result[JSON_ATTACHMENT_TRANSFORM] = Transform::toJson(transform);
|
result[JSON_ATTACHMENT_TRANSFORM] = Transform::toJson(transform);
|
||||||
}
|
}
|
||||||
|
result[JSON_ATTACHMENT_IS_SOFT] = isSoft;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1302,6 +1304,10 @@ void AttachmentData::fromJson(const QJsonObject& json) {
|
||||||
rotation = transform.getRotation();
|
rotation = transform.getRotation();
|
||||||
scale = transform.getScale().x;
|
scale = transform.getScale().x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (json.contains(JSON_ATTACHMENT_IS_SOFT)) {
|
||||||
|
isSoft = json[JSON_ATTACHMENT_IS_SOFT].toBool();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AttachmentData::operator==(const AttachmentData& other) const {
|
bool AttachmentData::operator==(const AttachmentData& other) const {
|
||||||
|
@ -1311,12 +1317,12 @@ bool AttachmentData::operator==(const AttachmentData& other) const {
|
||||||
|
|
||||||
QDataStream& operator<<(QDataStream& out, const AttachmentData& attachment) {
|
QDataStream& operator<<(QDataStream& out, const AttachmentData& attachment) {
|
||||||
return out << attachment.modelURL << attachment.jointName <<
|
return out << attachment.modelURL << attachment.jointName <<
|
||||||
attachment.translation << attachment.rotation << attachment.scale;
|
attachment.translation << attachment.rotation << attachment.scale << attachment.isSoft;
|
||||||
}
|
}
|
||||||
|
|
||||||
QDataStream& operator>>(QDataStream& in, AttachmentData& attachment) {
|
QDataStream& operator>>(QDataStream& in, AttachmentData& attachment) {
|
||||||
return in >> attachment.modelURL >> attachment.jointName >>
|
return in >> attachment.modelURL >> attachment.jointName >>
|
||||||
attachment.translation >> attachment.rotation >> attachment.scale;
|
attachment.translation >> attachment.rotation >> attachment.scale >> attachment.isSoft;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AttachmentDataObject::setModelURL(const QString& modelURL) const {
|
void AttachmentDataObject::setModelURL(const QString& modelURL) const {
|
||||||
|
|
|
@ -437,6 +437,7 @@ public:
|
||||||
glm::vec3 translation;
|
glm::vec3 translation;
|
||||||
glm::quat rotation;
|
glm::quat rotation;
|
||||||
float scale { 1.0f };
|
float scale { 1.0f };
|
||||||
|
bool isSoft { false };
|
||||||
|
|
||||||
bool isValid() const { return modelURL.isValid(); }
|
bool isValid() const { return modelURL.isValid(); }
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
|
||||||
return VERSION_ENTITIES_REMOVED_START_AUTOMATICALLY_FROM_ANIMATION_PROPERTY_GROUP;
|
return VERSION_ENTITIES_REMOVED_START_AUTOMATICALLY_FROM_ANIMATION_PROPERTY_GROUP;
|
||||||
case PacketType::AvatarData:
|
case PacketType::AvatarData:
|
||||||
case PacketType::BulkAvatarData:
|
case PacketType::BulkAvatarData:
|
||||||
return 17;
|
return static_cast<PacketVersion>(AvatarMixerPacketVersion::SoftAttachmentSupport);
|
||||||
default:
|
default:
|
||||||
return 17;
|
return 17;
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,4 +163,9 @@ const PacketVersion VERSION_ENTITIES_POLYLINE_TEXTURE = 50;
|
||||||
const PacketVersion VERSION_ENTITIES_HAVE_PARENTS = 51;
|
const PacketVersion VERSION_ENTITIES_HAVE_PARENTS = 51;
|
||||||
const PacketVersion VERSION_ENTITIES_REMOVED_START_AUTOMATICALLY_FROM_ANIMATION_PROPERTY_GROUP = 52;
|
const PacketVersion VERSION_ENTITIES_REMOVED_START_AUTOMATICALLY_FROM_ANIMATION_PROPERTY_GROUP = 52;
|
||||||
|
|
||||||
|
enum class AvatarMixerPacketVersion : PacketVersion {
|
||||||
|
TranslationSupport = 17,
|
||||||
|
SoftAttachmentSupport
|
||||||
|
};
|
||||||
|
|
||||||
#endif // hifi_PacketHeaders_h
|
#endif // hifi_PacketHeaders_h
|
||||||
|
|
Loading…
Reference in a new issue