mirror of
https://github.com/overte-org/overte.git
synced 2025-07-23 13:24:02 +02:00
remove attachments
This commit is contained in:
parent
54d70a5679
commit
55907acd70
30 changed files with 19 additions and 1313 deletions
|
@ -67,8 +67,6 @@
|
||||||
* @property {boolean} lookAtSnappingEnabled=true - <code>true</code> if the avatar's eyes snap to look at another avatar's
|
* @property {boolean} lookAtSnappingEnabled=true - <code>true</code> if the avatar's eyes snap to look at another avatar's
|
||||||
* eyes when the other avatar is in the line of sight and also has <code>lookAtSnappingEnabled == true</code>.
|
* eyes when the other avatar is in the line of sight and also has <code>lookAtSnappingEnabled == true</code>.
|
||||||
* @property {string} skeletonModelURL - The avatar's FST file.
|
* @property {string} skeletonModelURL - The avatar's FST file.
|
||||||
* @property {AttachmentData[]} attachmentData - Information on the avatar's attachments.
|
|
||||||
* <p class="important">Deprecated: This property is deprecated and will be removed. Use avatar entities instead.</p>
|
|
||||||
* @property {string[]} jointNames - The list of joints in the current avatar model. <em>Read-only.</em>
|
* @property {string[]} jointNames - The list of joints in the current avatar model. <em>Read-only.</em>
|
||||||
* @property {Uuid} sessionUUID - Unique ID of the avatar in the domain. <em>Read-only.</em>
|
* @property {Uuid} sessionUUID - Unique ID of the avatar in the domain. <em>Read-only.</em>
|
||||||
* @property {Mat4} sensorToWorldMatrix - The scale, rotation, and translation transform from the user's real world to the
|
* @property {Mat4} sensorToWorldMatrix - The scale, rotation, and translation transform from the user's real world to the
|
||||||
|
|
|
@ -316,7 +316,6 @@ static const QString JS_EXTENSION = ".js";
|
||||||
static const QString FST_EXTENSION = ".fst";
|
static const QString FST_EXTENSION = ".fst";
|
||||||
static const QString FBX_EXTENSION = ".fbx";
|
static const QString FBX_EXTENSION = ".fbx";
|
||||||
static const QString OBJ_EXTENSION = ".obj";
|
static const QString OBJ_EXTENSION = ".obj";
|
||||||
static const QString AVA_JSON_EXTENSION = ".ava.json";
|
|
||||||
static const QString WEB_VIEW_TAG = "noDownload=true";
|
static const QString WEB_VIEW_TAG = "noDownload=true";
|
||||||
static const QString ZIP_EXTENSION = ".zip";
|
static const QString ZIP_EXTENSION = ".zip";
|
||||||
static const QString CONTENT_ZIP_EXTENSION = ".content.zip";
|
static const QString CONTENT_ZIP_EXTENSION = ".content.zip";
|
||||||
|
@ -365,7 +364,6 @@ static const QString TESTER_FILE = "/sdcard/_hifi_test_device.txt";
|
||||||
const std::vector<std::pair<QString, Application::AcceptURLMethod>> Application::_acceptedExtensions {
|
const std::vector<std::pair<QString, Application::AcceptURLMethod>> Application::_acceptedExtensions {
|
||||||
{ SVO_EXTENSION, &Application::importSVOFromURL },
|
{ SVO_EXTENSION, &Application::importSVOFromURL },
|
||||||
{ SVO_JSON_EXTENSION, &Application::importSVOFromURL },
|
{ SVO_JSON_EXTENSION, &Application::importSVOFromURL },
|
||||||
{ AVA_JSON_EXTENSION, &Application::askToWearAvatarAttachmentUrl },
|
|
||||||
{ JSON_EXTENSION, &Application::importJSONFromURL },
|
{ JSON_EXTENSION, &Application::importJSONFromURL },
|
||||||
{ JS_EXTENSION, &Application::askToLoadScript },
|
{ JS_EXTENSION, &Application::askToLoadScript },
|
||||||
{ FST_EXTENSION, &Application::askToSetAvatarUrl },
|
{ FST_EXTENSION, &Application::askToSetAvatarUrl },
|
||||||
|
@ -7838,74 +7836,6 @@ bool Application::askToLoadScript(const QString& scriptFilenameOrURL) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Application::askToWearAvatarAttachmentUrl(const QString& url) {
|
|
||||||
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
|
|
||||||
QNetworkRequest networkRequest = QNetworkRequest(url);
|
|
||||||
networkRequest.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy);
|
|
||||||
networkRequest.setHeader(QNetworkRequest::UserAgentHeader, NetworkingConstants::OVERTE_USER_AGENT);
|
|
||||||
QNetworkReply* reply = networkAccessManager.get(networkRequest);
|
|
||||||
int requestNumber = ++_avatarAttachmentRequest;
|
|
||||||
connect(reply, &QNetworkReply::finished, [this, reply, url, requestNumber]() {
|
|
||||||
|
|
||||||
if (requestNumber != _avatarAttachmentRequest) {
|
|
||||||
// this request has been superseded by another more recent request
|
|
||||||
reply->deleteLater();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QNetworkReply::NetworkError networkError = reply->error();
|
|
||||||
if (networkError == QNetworkReply::NoError) {
|
|
||||||
// download success
|
|
||||||
QByteArray contents = reply->readAll();
|
|
||||||
|
|
||||||
QJsonParseError jsonError;
|
|
||||||
auto doc = QJsonDocument::fromJson(contents, &jsonError);
|
|
||||||
if (jsonError.error == QJsonParseError::NoError) {
|
|
||||||
|
|
||||||
auto jsonObject = doc.object();
|
|
||||||
|
|
||||||
// retrieve optional name field from JSON
|
|
||||||
QString name = tr("Unnamed Attachment");
|
|
||||||
auto nameValue = jsonObject.value("name");
|
|
||||||
if (nameValue.isString()) {
|
|
||||||
name = nameValue.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto avatarAttachmentConfirmationTitle = tr("Avatar Attachment Confirmation");
|
|
||||||
auto avatarAttachmentConfirmationMessage = tr("Would you like to wear '%1' on your avatar?").arg(name);
|
|
||||||
ModalDialogListener* dlg = OffscreenUi::asyncQuestion(avatarAttachmentConfirmationTitle,
|
|
||||||
avatarAttachmentConfirmationMessage,
|
|
||||||
QMessageBox::Ok | QMessageBox::Cancel);
|
|
||||||
QObject::connect(dlg, &ModalDialogListener::response, this, [=] (QVariant answer) {
|
|
||||||
QObject::disconnect(dlg, &ModalDialogListener::response, this, nullptr);
|
|
||||||
if (static_cast<QMessageBox::StandardButton>(answer.toInt()) == QMessageBox::Yes) {
|
|
||||||
// add attachment to avatar
|
|
||||||
auto myAvatar = getMyAvatar();
|
|
||||||
assert(myAvatar);
|
|
||||||
auto attachmentDataVec = myAvatar->getAttachmentData();
|
|
||||||
AttachmentData attachmentData;
|
|
||||||
attachmentData.fromJson(jsonObject);
|
|
||||||
attachmentDataVec.push_back(attachmentData);
|
|
||||||
myAvatar->setAttachmentData(attachmentDataVec);
|
|
||||||
} else {
|
|
||||||
qCDebug(interfaceapp) << "User declined to wear the avatar attachment";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// json parse error
|
|
||||||
auto avatarAttachmentParseErrorString = tr("Error parsing attachment JSON from url: \"%1\"");
|
|
||||||
displayAvatarAttachmentWarning(avatarAttachmentParseErrorString.arg(url));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// download failure
|
|
||||||
auto avatarAttachmentDownloadErrorString = tr("Error downloading attachment JSON from url: \"%1\"");
|
|
||||||
displayAvatarAttachmentWarning(avatarAttachmentDownloadErrorString.arg(url));
|
|
||||||
}
|
|
||||||
reply->deleteLater();
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const QString CONTENT_SET_NAME_QUERY_PARAM = "name";
|
static const QString CONTENT_SET_NAME_QUERY_PARAM = "name";
|
||||||
|
|
||||||
void Application::replaceDomainContent(const QString& url, const QString& itemName) {
|
void Application::replaceDomainContent(const QString& url, const QString& itemName) {
|
||||||
|
@ -7984,11 +7914,6 @@ bool Application::askToReplaceDomainContent(const QString& url) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::displayAvatarAttachmentWarning(const QString& message) const {
|
|
||||||
auto avatarAttachmentWarningTitle = tr("Avatar Attachment Failure");
|
|
||||||
OffscreenUi::asyncWarning(avatarAttachmentWarningTitle, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Application::showDialog(const QUrl& widgetUrl, const QUrl& tabletUrl, const QString& name) const {
|
void Application::showDialog(const QUrl& widgetUrl, const QUrl& tabletUrl, const QString& name) const {
|
||||||
auto tablet = DependencyManager::get<TabletScriptingInterface>()->getTablet(SYSTEM_TABLET);
|
auto tablet = DependencyManager::get<TabletScriptingInterface>()->getTablet(SYSTEM_TABLET);
|
||||||
auto hmd = DependencyManager::get<HMDScriptingInterface>();
|
auto hmd = DependencyManager::get<HMDScriptingInterface>();
|
||||||
|
|
|
@ -546,9 +546,6 @@ private slots:
|
||||||
bool askToSetAvatarUrl(const QString& url);
|
bool askToSetAvatarUrl(const QString& url);
|
||||||
bool askToLoadScript(const QString& scriptFilenameOrURL);
|
bool askToLoadScript(const QString& scriptFilenameOrURL);
|
||||||
|
|
||||||
bool askToWearAvatarAttachmentUrl(const QString& url);
|
|
||||||
void displayAvatarAttachmentWarning(const QString& message) const;
|
|
||||||
|
|
||||||
bool askToReplaceDomainContent(const QString& url);
|
bool askToReplaceDomainContent(const QString& url);
|
||||||
|
|
||||||
void setSessionUUID(const QUuid& sessionUUID) const;
|
void setSessionUUID(const QUuid& sessionUUID) const;
|
||||||
|
@ -800,8 +797,6 @@ private:
|
||||||
bool _reticleClickPressed { false };
|
bool _reticleClickPressed { false };
|
||||||
bool _keyboardFocusWaitingOnRenderable { false };
|
bool _keyboardFocusWaitingOnRenderable { false };
|
||||||
|
|
||||||
int _avatarAttachmentRequest = 0;
|
|
||||||
|
|
||||||
bool _settingsLoaded { false };
|
bool _settingsLoaded { false };
|
||||||
|
|
||||||
bool _captureMouse { false };
|
bool _captureMouse { false };
|
||||||
|
|
|
@ -222,8 +222,6 @@ void AvatarBookmarks::updateAvatarEntities(const QVariantList &avatarEntities) {
|
||||||
* @property {number} avatarScale - The target scale of the avatar.
|
* @property {number} avatarScale - The target scale of the avatar.
|
||||||
* @property {Array<Object<"properties",Entities.EntityProperties>>} [avatarEntites] - The avatar entities included with the
|
* @property {Array<Object<"properties",Entities.EntityProperties>>} [avatarEntites] - The avatar entities included with the
|
||||||
* bookmark.
|
* bookmark.
|
||||||
* @property {AttachmentData[]} [attachments] - The attachments included with the bookmark.
|
|
||||||
* <p class="important">Deprecated: Use avatar entities instead.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void AvatarBookmarks::loadBookmark(const QString& bookmarkName) {
|
void AvatarBookmarks::loadBookmark(const QString& bookmarkName) {
|
||||||
|
@ -266,8 +264,6 @@ void AvatarBookmarks::loadBookmarkInternal(const QString& bookmarkName) {
|
||||||
myAvatar->clearWornAvatarEntities();
|
myAvatar->clearWornAvatarEntities();
|
||||||
const float& qScale = bookmark.value(ENTRY_AVATAR_SCALE, 1.0f).toFloat();
|
const float& qScale = bookmark.value(ENTRY_AVATAR_SCALE, 1.0f).toFloat();
|
||||||
myAvatar->setAvatarScale(qScale);
|
myAvatar->setAvatarScale(qScale);
|
||||||
QList<QVariant> attachments = bookmark.value(ENTRY_AVATAR_ATTACHMENTS, QList<QVariant>()).toList();
|
|
||||||
myAvatar->setAttachmentsVariant(attachments);
|
|
||||||
QVariantList avatarEntities = bookmark.value(ENTRY_AVATAR_ENTITIES, QVariantList()).toList();
|
QVariantList avatarEntities = bookmark.value(ENTRY_AVATAR_ENTITIES, QVariantList()).toList();
|
||||||
addAvatarEntities(avatarEntities);
|
addAvatarEntities(avatarEntities);
|
||||||
emit bookmarkLoaded(bookmarkName);
|
emit bookmarkLoaded(bookmarkName);
|
||||||
|
@ -335,7 +331,6 @@ QVariantMap AvatarBookmarks::getAvatarDataToBookmark() {
|
||||||
const QString& avatarIcon = QString("");
|
const QString& avatarIcon = QString("");
|
||||||
const QVariant& avatarScale = myAvatar->getAvatarScale();
|
const QVariant& avatarScale = myAvatar->getAvatarScale();
|
||||||
|
|
||||||
// If Avatar attachments ever change, this is where to update them, when saving remember to also append to AVATAR_BOOKMARK_VERSION
|
|
||||||
QVariantMap bookmark;
|
QVariantMap bookmark;
|
||||||
bookmark.insert(ENTRY_VERSION, AVATAR_BOOKMARK_VERSION);
|
bookmark.insert(ENTRY_VERSION, AVATAR_BOOKMARK_VERSION);
|
||||||
bookmark.insert(ENTRY_AVATAR_URL, avatarUrl);
|
bookmark.insert(ENTRY_AVATAR_URL, avatarUrl);
|
||||||
|
|
|
@ -66,8 +66,7 @@ public slots:
|
||||||
void saveBookmark(const QString& bookmarkName);
|
void saveBookmark(const QString& bookmarkName);
|
||||||
|
|
||||||
/*@jsdoc
|
/*@jsdoc
|
||||||
* Loads an avatar bookmark, setting your avatar model, scale, and avatar entities (or attachments if an old bookmark) to
|
* Loads an avatar bookmark, setting your avatar model, scale, and avatar entities to those in the bookmark.
|
||||||
* those in the bookmark.
|
|
||||||
* @function AvatarBookmarks.loadBookmark
|
* @function AvatarBookmarks.loadBookmark
|
||||||
* @param {string} bookmarkName - The name of the avatar bookmark to load (case sensitive).
|
* @param {string} bookmarkName - The name of the avatar bookmark to load (case sensitive).
|
||||||
*/
|
*/
|
||||||
|
@ -104,8 +103,7 @@ public slots:
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
/*@jsdoc
|
/*@jsdoc
|
||||||
* Triggered when an avatar bookmark is loaded, setting your avatar model, scale, and avatar entities (or attachments if an
|
* Triggered when an avatar bookmark is loaded, setting your avatar model, scale, and avatar entities to those in the bookmark.
|
||||||
* old bookmark) to those in the bookmark.
|
|
||||||
* @function AvatarBookmarks.bookmarkLoaded
|
* @function AvatarBookmarks.bookmarkLoaded
|
||||||
* @param {string} bookmarkName - The name of the avatar bookmark loaded.
|
* @param {string} bookmarkName - The name of the avatar bookmark loaded.
|
||||||
* @returns {Signal}
|
* @returns {Signal}
|
||||||
|
@ -155,7 +153,6 @@ private:
|
||||||
const QString AVATARBOOKMARKS_FILENAME = "avatarbookmarks.json";
|
const QString AVATARBOOKMARKS_FILENAME = "avatarbookmarks.json";
|
||||||
const QString ENTRY_AVATAR_URL = "avatarUrl";
|
const QString ENTRY_AVATAR_URL = "avatarUrl";
|
||||||
const QString ENTRY_AVATAR_ICON = "avatarIcon";
|
const QString ENTRY_AVATAR_ICON = "avatarIcon";
|
||||||
const QString ENTRY_AVATAR_ATTACHMENTS = "attachments";
|
|
||||||
const QString ENTRY_AVATAR_ENTITIES = "avatarEntites";
|
const QString ENTRY_AVATAR_ENTITIES = "avatarEntites";
|
||||||
const QString ENTRY_AVATAR_SCALE = "avatarScale";
|
const QString ENTRY_AVATAR_SCALE = "avatarScale";
|
||||||
const QString ENTRY_VERSION = "version";
|
const QString ENTRY_VERSION = "version";
|
||||||
|
|
|
@ -272,12 +272,6 @@ MyAvatar::MyAvatar(QThread* thread) :
|
||||||
auto hfmModel = getSkeletonModel()->getHFMModel();
|
auto hfmModel = getSkeletonModel()->getHFMModel();
|
||||||
qApp->loadAvatarScripts(hfmModel.scripts);
|
qApp->loadAvatarScripts(hfmModel.scripts);
|
||||||
_shouldLoadScripts = false;
|
_shouldLoadScripts = false;
|
||||||
}
|
|
||||||
// Load and convert old attachments to avatar entities
|
|
||||||
if (_oldAttachmentData.size() > 0) {
|
|
||||||
setAttachmentData(_oldAttachmentData);
|
|
||||||
_oldAttachmentData.clear();
|
|
||||||
_attachmentData.clear();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
connect(_skeletonModel.get(), &Model::rigReady, this, &Avatar::rigReady);
|
connect(_skeletonModel.get(), &Model::rigReady, this, &Avatar::rigReady);
|
||||||
|
@ -371,10 +365,6 @@ MyAvatar::MyAvatar(QThread* thread) :
|
||||||
setWorldPosition(dummyAvatar.getWorldPosition());
|
setWorldPosition(dummyAvatar.getWorldPosition());
|
||||||
setWorldOrientation(dummyAvatar.getWorldOrientation());
|
setWorldOrientation(dummyAvatar.getWorldOrientation());
|
||||||
|
|
||||||
if (!dummyAvatar.getAttachmentData().isEmpty()) {
|
|
||||||
setAttachmentData(dummyAvatar.getAttachmentData());
|
|
||||||
}
|
|
||||||
|
|
||||||
auto headData = dummyAvatar.getHeadData();
|
auto headData = dummyAvatar.getHeadData();
|
||||||
if (headData && _headData) {
|
if (headData && _headData) {
|
||||||
// blendshapes
|
// blendshapes
|
||||||
|
@ -501,11 +491,6 @@ glm::quat MyAvatar::getOrientationOutbound() const {
|
||||||
return (slerp(_smoothOrientationInitial, _smoothOrientationTarget, interp));
|
return (slerp(_smoothOrientationInitial, _smoothOrientationTarget, interp));
|
||||||
}
|
}
|
||||||
|
|
||||||
// virtual
|
|
||||||
void MyAvatar::simulateAttachments(float deltaTime) {
|
|
||||||
// don't update attachments here, do it in harvestResultsFromPhysicsSimulation()
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray MyAvatar::toByteArrayStateful(AvatarDataDetail dataDetail, bool dropFaceTracking) {
|
QByteArray MyAvatar::toByteArrayStateful(AvatarDataDetail dataDetail, bool dropFaceTracking) {
|
||||||
CameraMode mode = qApp->getCamera().getMode();
|
CameraMode mode = qApp->getCamera().getMode();
|
||||||
_globalPosition = getWorldPosition();
|
_globalPosition = getWorldPosition();
|
||||||
|
@ -982,8 +967,7 @@ void MyAvatar::simulate(float deltaTime, bool inView) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// we've achived our final adjusted position and rotation for the avatar
|
// we've achived our final adjusted position and rotation for the avatar
|
||||||
// and all of its joints, now update our attachements.
|
// and all of its joints, now update our children.
|
||||||
Avatar::simulateAttachments(deltaTime);
|
|
||||||
relayJointDataToChildren();
|
relayJointDataToChildren();
|
||||||
if (applyGrabChanges()) {
|
if (applyGrabChanges()) {
|
||||||
_cauterizationNeedsUpdate = true;
|
_cauterizationNeedsUpdate = true;
|
||||||
|
@ -2175,65 +2159,6 @@ void MyAvatar::loadAvatarEntityDataFromSettings() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::saveAttachmentData(const AttachmentData& attachment) const {
|
|
||||||
Settings settings;
|
|
||||||
settings.beginGroup("savedAttachmentData");
|
|
||||||
settings.beginGroup(_skeletonModel->getURL().toString());
|
|
||||||
settings.beginGroup(attachment.modelURL.toString());
|
|
||||||
settings.setValue("jointName", attachment.jointName);
|
|
||||||
|
|
||||||
settings.beginGroup(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();
|
|
||||||
settings.endGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
AttachmentData MyAvatar::loadAttachmentData(const QUrl& modelURL, const QString& jointName) const {
|
|
||||||
Settings settings;
|
|
||||||
settings.beginGroup("savedAttachmentData");
|
|
||||||
settings.beginGroup(_skeletonModel->getURL().toString());
|
|
||||||
settings.beginGroup(modelURL.toString());
|
|
||||||
|
|
||||||
AttachmentData attachment;
|
|
||||||
attachment.modelURL = modelURL;
|
|
||||||
if (jointName.isEmpty()) {
|
|
||||||
attachment.jointName = settings.value("jointName").toString();
|
|
||||||
} else {
|
|
||||||
attachment.jointName = jointName;
|
|
||||||
}
|
|
||||||
settings.beginGroup(attachment.jointName);
|
|
||||||
if (settings.contains("translation_x")) {
|
|
||||||
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);
|
|
||||||
} else {
|
|
||||||
attachment = AttachmentData();
|
|
||||||
}
|
|
||||||
|
|
||||||
settings.endGroup();
|
|
||||||
settings.endGroup();
|
|
||||||
settings.endGroup();
|
|
||||||
settings.endGroup();
|
|
||||||
|
|
||||||
return attachment;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MyAvatar::isMyAvatarURLProtected() const {
|
bool MyAvatar::isMyAvatarURLProtected() const {
|
||||||
return !ScriptPermissions::isCurrentScriptAllowed(ScriptPermissions::Permission::SCRIPT_PERMISSION_GET_AVATAR_URL);
|
return !ScriptPermissions::isCurrentScriptAllowed(ScriptPermissions::Permission::SCRIPT_PERMISSION_GET_AVATAR_URL);
|
||||||
}
|
}
|
||||||
|
@ -2994,171 +2919,6 @@ SharedSoundPointer MyAvatar::getCollisionSound() {
|
||||||
return _collisionSound;
|
return _collisionSound;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::attach(const QString& modelURL, const QString& jointName,
|
|
||||||
const glm::vec3& translation, const glm::quat& rotation,
|
|
||||||
float scale, bool isSoft,
|
|
||||||
bool allowDuplicates, bool useSaved) {
|
|
||||||
if (QThread::currentThread() != thread()) {
|
|
||||||
BLOCKING_INVOKE_METHOD(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, isSoft),
|
|
||||||
Q_ARG(bool, allowDuplicates),
|
|
||||||
Q_ARG(bool, useSaved)
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!DependencyManager::get<NodeList>()->getThisNodeCanRezAvatarEntities()) {
|
|
||||||
qCDebug(interfaceapp) << "Ignoring attach() because don't have canRezAvatarEntities permission on domain";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
AttachmentData data;
|
|
||||||
data.modelURL = modelURL;
|
|
||||||
data.jointName = jointName;
|
|
||||||
data.translation = translation;
|
|
||||||
data.rotation = rotation;
|
|
||||||
data.scale = scale;
|
|
||||||
data.isSoft = isSoft;
|
|
||||||
EntityItemProperties properties;
|
|
||||||
attachmentDataToEntityProperties(data, properties);
|
|
||||||
DependencyManager::get<EntityScriptingInterface>()->addEntity(properties, true);
|
|
||||||
emit attachmentsChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyAvatar::detachOne(const QString& modelURL, const QString& jointName) {
|
|
||||||
if (QThread::currentThread() != thread()) {
|
|
||||||
BLOCKING_INVOKE_METHOD(this, "detachOne",
|
|
||||||
Q_ARG(const QString&, modelURL),
|
|
||||||
Q_ARG(const QString&, jointName)
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!DependencyManager::get<NodeList>()->getThisNodeCanRezAvatarEntities()) {
|
|
||||||
qCDebug(interfaceapp) << "Ignoring detachOne() because don't have canRezAvatarEntities permission on domain";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QUuid entityID;
|
|
||||||
if (findAvatarEntity(modelURL, jointName, entityID)) {
|
|
||||||
DependencyManager::get<EntityScriptingInterface>()->deleteEntity(entityID);
|
|
||||||
}
|
|
||||||
emit attachmentsChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyAvatar::detachAll(const QString& modelURL, const QString& jointName) {
|
|
||||||
if (QThread::currentThread() != thread()) {
|
|
||||||
BLOCKING_INVOKE_METHOD(this, "detachAll",
|
|
||||||
Q_ARG(const QString&, modelURL),
|
|
||||||
Q_ARG(const QString&, jointName)
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!DependencyManager::get<NodeList>()->getThisNodeCanRezAvatarEntities()) {
|
|
||||||
qCDebug(interfaceapp) << "Ignoring detachAll() because don't have canRezAvatarEntities permission on domain";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QUuid entityID;
|
|
||||||
while (findAvatarEntity(modelURL, jointName, entityID)) {
|
|
||||||
DependencyManager::get<EntityScriptingInterface>()->deleteEntity(entityID);
|
|
||||||
}
|
|
||||||
emit attachmentsChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyAvatar::setAttachmentData(const QVector<AttachmentData>& attachmentData) {
|
|
||||||
if (QThread::currentThread() != thread()) {
|
|
||||||
BLOCKING_INVOKE_METHOD(this, "setAttachmentData",
|
|
||||||
Q_ARG(const QVector<AttachmentData>&, attachmentData));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!DependencyManager::get<NodeList>()->getThisNodeCanRezAvatarEntities()) {
|
|
||||||
qCDebug(interfaceapp) << "Ignoring setAttachmentData() because don't have canRezAvatarEntities permission on domain";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<EntityItemProperties> newEntitiesProperties;
|
|
||||||
for (auto& data : attachmentData) {
|
|
||||||
QUuid entityID;
|
|
||||||
EntityItemProperties properties;
|
|
||||||
if (findAvatarEntity(data.modelURL.toString(), data.jointName, entityID)) {
|
|
||||||
properties = DependencyManager::get<EntityScriptingInterface>()->getEntityProperties(entityID);
|
|
||||||
}
|
|
||||||
attachmentDataToEntityProperties(data, properties);
|
|
||||||
newEntitiesProperties.push_back(properties);
|
|
||||||
}
|
|
||||||
|
|
||||||
// clear any existing wearables
|
|
||||||
clearWornAvatarEntities();
|
|
||||||
|
|
||||||
for (auto& properties : newEntitiesProperties) {
|
|
||||||
DependencyManager::get<EntityScriptingInterface>()->addEntity(properties, true);
|
|
||||||
}
|
|
||||||
emit attachmentsChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
QVector<AttachmentData> MyAvatar::getAttachmentData() const {
|
|
||||||
QVector<AttachmentData> attachmentData;
|
|
||||||
|
|
||||||
if (!DependencyManager::get<NodeList>()->getThisNodeCanRezAvatarEntities()) {
|
|
||||||
qCDebug(interfaceapp) << "Ignoring getAttachmentData() because don't have canRezAvatarEntities permission on domain";
|
|
||||||
return attachmentData;
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<QUuid> avatarEntityIDs;
|
|
||||||
_avatarEntitiesLock.withReadLock([&] {
|
|
||||||
avatarEntityIDs = _packedAvatarEntityData.keys();
|
|
||||||
});
|
|
||||||
for (const auto& entityID : avatarEntityIDs) {
|
|
||||||
auto properties = DependencyManager::get<EntityScriptingInterface>()->getEntityProperties(entityID);
|
|
||||||
AttachmentData data = entityPropertiesToAttachmentData(properties);
|
|
||||||
attachmentData.append(data);
|
|
||||||
}
|
|
||||||
return attachmentData;
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariantList MyAvatar::getAttachmentsVariant() const {
|
|
||||||
QVariantList result;
|
|
||||||
|
|
||||||
if (!DependencyManager::get<NodeList>()->getThisNodeCanRezAvatarEntities()) {
|
|
||||||
qCDebug(interfaceapp)
|
|
||||||
<< "Ignoring getAttachmentsVariant() because don't have canRezAvatarEntities permission on domain";
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto& attachment : getAttachmentData()) {
|
|
||||||
result.append(attachment.toVariant());
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyAvatar::setAttachmentsVariant(const QVariantList& variant) {
|
|
||||||
if (QThread::currentThread() != thread()) {
|
|
||||||
BLOCKING_INVOKE_METHOD(this, "setAttachmentsVariant",
|
|
||||||
Q_ARG(const QVariantList&, variant));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!DependencyManager::get<NodeList>()->getThisNodeCanRezAvatarEntities()) {
|
|
||||||
qCDebug(interfaceapp)
|
|
||||||
<< "Ignoring setAttachmentsVariant() because don't have canRezAvatarEntities permission on domain";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QVector<AttachmentData> newAttachments;
|
|
||||||
newAttachments.reserve(variant.size());
|
|
||||||
for (const auto& attachmentVar : variant) {
|
|
||||||
AttachmentData attachment;
|
|
||||||
if (attachment.fromVariant(attachmentVar)) {
|
|
||||||
newAttachments.append(attachment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setAttachmentData(newAttachments);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MyAvatar::findAvatarEntity(const QString& modelURL, const QString& jointName, QUuid& entityID) {
|
bool MyAvatar::findAvatarEntity(const QString& modelURL, const QString& jointName, QUuid& entityID) {
|
||||||
QList<QUuid> avatarEntityIDs;
|
QList<QUuid> avatarEntityIDs;
|
||||||
_avatarEntitiesLock.withReadLock([&] {
|
_avatarEntitiesLock.withReadLock([&] {
|
||||||
|
@ -3174,34 +2934,6 @@ bool MyAvatar::findAvatarEntity(const QString& modelURL, const QString& jointNam
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
AttachmentData MyAvatar::entityPropertiesToAttachmentData(const EntityItemProperties& properties) const {
|
|
||||||
AttachmentData data;
|
|
||||||
data.modelURL = properties.getModelURL();
|
|
||||||
data.translation = properties.getLocalPosition();
|
|
||||||
data.rotation = properties.getLocalRotation();
|
|
||||||
data.isSoft = properties.getRelayParentJoints();
|
|
||||||
int jointIndex = (int)properties.getParentJointIndex();
|
|
||||||
if (jointIndex > -1 && jointIndex < getJointNames().size()) {
|
|
||||||
data.jointName = getJointNames()[jointIndex];
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyAvatar::attachmentDataToEntityProperties(const AttachmentData& data, EntityItemProperties& properties) {
|
|
||||||
QString url = data.modelURL.toString();
|
|
||||||
properties.setName(QFileInfo(url).baseName());
|
|
||||||
properties.setType(EntityTypes::Model);
|
|
||||||
properties.setParentID(AVATAR_SELF_ID);
|
|
||||||
properties.setLocalPosition(data.translation);
|
|
||||||
properties.setLocalRotation(data.rotation);
|
|
||||||
if (!data.isSoft) {
|
|
||||||
properties.setParentJointIndex(getJointIndex(data.jointName));
|
|
||||||
} else {
|
|
||||||
properties.setRelayParentJoints(true);
|
|
||||||
}
|
|
||||||
properties.setModelURL(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyAvatar::initHeadBones() {
|
void MyAvatar::initHeadBones() {
|
||||||
int neckJointIndex = -1;
|
int neckJointIndex = -1;
|
||||||
if (_skeletonModel->isLoaded()) {
|
if (_skeletonModel->isLoaded()) {
|
||||||
|
@ -3444,22 +3176,6 @@ void MyAvatar::preDisplaySide(const RenderArgs* renderArgs) {
|
||||||
if (shouldDrawHead != _prevShouldDrawHead) {
|
if (shouldDrawHead != _prevShouldDrawHead) {
|
||||||
_cauterizationNeedsUpdate = true;
|
_cauterizationNeedsUpdate = true;
|
||||||
_skeletonModel->setEnableCauterization(!shouldDrawHead);
|
_skeletonModel->setEnableCauterization(!shouldDrawHead);
|
||||||
|
|
||||||
for (int i = 0; i < _attachmentData.size(); i++) {
|
|
||||||
if (_attachmentData[i].jointName.compare("Head", Qt::CaseInsensitive) == 0 ||
|
|
||||||
_attachmentData[i].jointName.compare("Neck", Qt::CaseInsensitive) == 0 ||
|
|
||||||
_attachmentData[i].jointName.compare("LeftEye", Qt::CaseInsensitive) == 0 ||
|
|
||||||
_attachmentData[i].jointName.compare("RightEye", Qt::CaseInsensitive) == 0 ||
|
|
||||||
_attachmentData[i].jointName.compare("HeadTop_End", Qt::CaseInsensitive) == 0 ||
|
|
||||||
_attachmentData[i].jointName.compare("Face", Qt::CaseInsensitive) == 0) {
|
|
||||||
uint8_t modelRenderTagBits = shouldDrawHead ? render::hifi::TAG_ALL_VIEWS : render::hifi::TAG_SECONDARY_VIEW;
|
|
||||||
|
|
||||||
_attachmentModels[i]->setTagMask(modelRenderTagBits);
|
|
||||||
_attachmentModels[i]->setGroupCulled(false);
|
|
||||||
_attachmentModels[i]->setCanCastShadow(true);
|
|
||||||
_attachmentModels[i]->setVisibleInScene(true, qApp->getMain3DScene());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_prevShouldDrawHead = shouldDrawHead;
|
_prevShouldDrawHead = shouldDrawHead;
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,8 +141,6 @@ class MyAvatar : public Avatar {
|
||||||
* @property {boolean} lookAtSnappingEnabled=true - <code>true</code> if the avatar's eyes snap to look at another avatar's
|
* @property {boolean} lookAtSnappingEnabled=true - <code>true</code> if the avatar's eyes snap to look at another avatar's
|
||||||
* eyes when the other avatar is in the line of sight and also has <code>lookAtSnappingEnabled == true</code>.
|
* eyes when the other avatar is in the line of sight and also has <code>lookAtSnappingEnabled == true</code>.
|
||||||
* @property {string} skeletonModelURL - The avatar's FST file.
|
* @property {string} skeletonModelURL - The avatar's FST file.
|
||||||
* @property {AttachmentData[]} attachmentData - Information on the avatar's attachments.
|
|
||||||
* <p class="important">Deprecated: This property is deprecated and will be removed. Use avatar entities instead.</p>
|
|
||||||
* @property {string[]} jointNames - The list of joints in the current avatar model. <em>Read-only.</em>
|
* @property {string[]} jointNames - The list of joints in the current avatar model. <em>Read-only.</em>
|
||||||
* @property {Uuid} sessionUUID - Unique ID of the avatar in the domain. <em>Read-only.</em>
|
* @property {Uuid} sessionUUID - Unique ID of the avatar in the domain. <em>Read-only.</em>
|
||||||
* @property {Mat4} sensorToWorldMatrix - The scale, rotation, and translation transform from the user's real world to the
|
* @property {Mat4} sensorToWorldMatrix - The scale, rotation, and translation transform from the user's real world to the
|
||||||
|
@ -326,17 +324,10 @@ class MyAvatar : public Avatar {
|
||||||
* @borrows Avatar.getJointIndex as getJointIndex
|
* @borrows Avatar.getJointIndex as getJointIndex
|
||||||
* @borrows Avatar.getJointNames as getJointNames
|
* @borrows Avatar.getJointNames as getJointNames
|
||||||
* @borrows Avatar.setBlendshape as setBlendshape
|
* @borrows Avatar.setBlendshape as setBlendshape
|
||||||
* @borrows Avatar.getAttachmentsVariant as getAttachmentsVariant
|
|
||||||
* @borrows Avatar.setAttachmentsVariant as setAttachmentsVariant
|
|
||||||
* @borrows Avatar.updateAvatarEntity as updateAvatarEntity
|
* @borrows Avatar.updateAvatarEntity as updateAvatarEntity
|
||||||
* @borrows Avatar.clearAvatarEntity as clearAvatarEntity
|
* @borrows Avatar.clearAvatarEntity as clearAvatarEntity
|
||||||
* @borrows Avatar.setForceFaceTrackerConnected as setForceFaceTrackerConnected
|
* @borrows Avatar.setForceFaceTrackerConnected as setForceFaceTrackerConnected
|
||||||
* @borrows Avatar.setSkeletonModelURL as setSkeletonModelURL
|
* @borrows Avatar.setSkeletonModelURL as setSkeletonModelURL
|
||||||
* @borrows Avatar.getAttachmentData as getAttachmentData
|
|
||||||
* @borrows Avatar.setAttachmentData as setAttachmentData
|
|
||||||
* @borrows Avatar.attach as attach
|
|
||||||
* @borrows Avatar.detachOne as detachOne
|
|
||||||
* @borrows Avatar.detachAll as detachAll
|
|
||||||
* @comment Avatar.getAvatarEntityData as getAvatarEntityData - Don't borrow because implementation is different.
|
* @comment Avatar.getAvatarEntityData as getAvatarEntityData - Don't borrow because implementation is different.
|
||||||
* @comment Avatar.setAvatarEntityData as setAvatarEntityData - Don't borrow because implementation is different.
|
* @comment Avatar.setAvatarEntityData as setAvatarEntityData - Don't borrow because implementation is different.
|
||||||
* @borrows Avatar.getSensorToWorldMatrix as getSensorToWorldMatrix
|
* @borrows Avatar.getSensorToWorldMatrix as getSensorToWorldMatrix
|
||||||
|
@ -590,8 +581,6 @@ public:
|
||||||
static void registerMetaTypes(ScriptEnginePointer engine);
|
static void registerMetaTypes(ScriptEnginePointer engine);
|
||||||
void registerProperties(ScriptEnginePointer engine);
|
void registerProperties(ScriptEnginePointer engine);
|
||||||
|
|
||||||
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; }
|
||||||
|
@ -1073,9 +1062,6 @@ public:
|
||||||
void loadData();
|
void loadData();
|
||||||
void loadAvatarEntityDataFromSettings();
|
void loadAvatarEntityDataFromSettings();
|
||||||
|
|
||||||
void saveAttachmentData(const AttachmentData& attachment) const;
|
|
||||||
AttachmentData loadAttachmentData(const QUrl& modelURL, const QString& jointName = QString()) const;
|
|
||||||
|
|
||||||
// Set what driving keys are being pressed to control thrust levels
|
// Set what driving keys are being pressed to control thrust levels
|
||||||
void clearDriveKeys();
|
void clearDriveKeys();
|
||||||
void setDriveKey(DriveKeys key, float val);
|
void setDriveKey(DriveKeys key, float val);
|
||||||
|
@ -1822,12 +1808,6 @@ public:
|
||||||
float computeStandingHeightMode(const controller::Pose& head);
|
float computeStandingHeightMode(const controller::Pose& head);
|
||||||
glm::quat computeAverageHeadRotation(const controller::Pose& head);
|
glm::quat computeAverageHeadRotation(const controller::Pose& head);
|
||||||
|
|
||||||
virtual void setAttachmentData(const QVector<AttachmentData>& attachmentData) override;
|
|
||||||
virtual QVector<AttachmentData> getAttachmentData() const override;
|
|
||||||
|
|
||||||
virtual QVariantList getAttachmentsVariant() const override;
|
|
||||||
virtual void setAttachmentsVariant(const QVariantList& variant) override;
|
|
||||||
|
|
||||||
glm::vec3 getNextPosition() { return _goToPending ? _goToPosition : getWorldPosition(); }
|
glm::vec3 getNextPosition() { return _goToPending ? _goToPosition : getWorldPosition(); }
|
||||||
void prepareAvatarEntityDataForReload();
|
void prepareAvatarEntityDataForReload();
|
||||||
|
|
||||||
|
@ -2610,16 +2590,6 @@ signals:
|
||||||
*/
|
*/
|
||||||
void sensorToWorldScaleChanged(float sensorToWorldScale);
|
void sensorToWorldScaleChanged(float sensorToWorldScale);
|
||||||
|
|
||||||
/*@jsdoc
|
|
||||||
* Triggered when the a model is attached to or detached from one of the avatar's joints using one of
|
|
||||||
* {@link MyAvatar.attach|attach}, {@link MyAvatar.detachOne|detachOne}, {@link MyAvatar.detachAll|detachAll}, or
|
|
||||||
* {@link MyAvatar.setAttachmentData|setAttachmentData}.
|
|
||||||
* @function MyAvatar.attachmentsChanged
|
|
||||||
* @returns {Signal}
|
|
||||||
* @deprecated This signal is deprecated and will be removed. Use avatar entities instead.
|
|
||||||
*/
|
|
||||||
void attachmentsChanged();
|
|
||||||
|
|
||||||
/*@jsdoc
|
/*@jsdoc
|
||||||
* Triggered when the avatar's size changes. This can be due to the user changing the size of their avatar or the domain
|
* Triggered when the avatar's size changes. This can be due to the user changing the size of their avatar or the domain
|
||||||
* limiting the size of their avatar.
|
* limiting the size of their avatar.
|
||||||
|
@ -2701,18 +2671,7 @@ private:
|
||||||
void setScriptedMotorFrame(QString frame);
|
void setScriptedMotorFrame(QString frame);
|
||||||
void setScriptedMotorMode(QString mode);
|
void setScriptedMotorMode(QString mode);
|
||||||
|
|
||||||
// Attachments
|
// Avatar Entities
|
||||||
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 isSoft = false,
|
|
||||||
bool allowDuplicates = false, bool useSaved = true) override;
|
|
||||||
|
|
||||||
virtual void detachOne(const QString& modelURL, const QString& jointName = QString()) override;
|
|
||||||
virtual void detachAll(const QString& modelURL, const QString& jointName = QString()) override;
|
|
||||||
|
|
||||||
// Attachments/Avatar Entity
|
|
||||||
void attachmentDataToEntityProperties(const AttachmentData& data, EntityItemProperties& properties);
|
|
||||||
AttachmentData entityPropertiesToAttachmentData(const EntityItemProperties& properties) const;
|
|
||||||
bool findAvatarEntity(const QString& modelURL, const QString& jointName, QUuid& entityID);
|
bool findAvatarEntity(const QString& modelURL, const QString& jointName, QUuid& entityID);
|
||||||
void addAvatarEntitiesToTree();
|
void addAvatarEntitiesToTree();
|
||||||
|
|
||||||
|
|
|
@ -316,7 +316,6 @@ void OtherAvatar::simulate(float deltaTime, bool inView) {
|
||||||
{
|
{
|
||||||
PROFILE_RANGE(simulation, "misc");
|
PROFILE_RANGE(simulation, "misc");
|
||||||
measureMotionDerivatives(deltaTime);
|
measureMotionDerivatives(deltaTime);
|
||||||
simulateAttachments(deltaTime);
|
|
||||||
updatePalms();
|
updatePalms();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
@ -384,7 +383,7 @@ void OtherAvatar::debugJointData() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OtherAvatar::handleChangedAvatarEntityData() {
|
void OtherAvatar::handleChangedAvatarEntityData() {
|
||||||
PerformanceTimer perfTimer("attachments");
|
PerformanceTimer perfTimer("avatarEntities");
|
||||||
|
|
||||||
// AVATAR ENTITY UPDATE FLOW
|
// AVATAR ENTITY UPDATE FLOW
|
||||||
// - if queueEditEntityMessage() sees "AvatarEntity" HostType it calls _myAvatar->storeAvatarEntityDataPayload()
|
// - if queueEditEntityMessage() sees "AvatarEntity" HostType it calls _myAvatar->storeAvatarEntityDataPayload()
|
||||||
|
|
|
@ -20,14 +20,10 @@
|
||||||
#include "HMDToolsDialog.h"
|
#include "HMDToolsDialog.h"
|
||||||
#include "TestingDialog.h"
|
#include "TestingDialog.h"
|
||||||
|
|
||||||
class AnimationsDialog;
|
|
||||||
class AttachmentsDialog;
|
|
||||||
class CachesSizeDialog;
|
|
||||||
class LodToolsDialog;
|
class LodToolsDialog;
|
||||||
class OctreeStatsDialog;
|
class OctreeStatsDialog;
|
||||||
class ScriptEditorWindow;
|
class ScriptEditorWindow;
|
||||||
class TestingDialog;
|
class TestingDialog;
|
||||||
class QMessageBox;
|
|
||||||
class DomainConnectionDialog;
|
class DomainConnectionDialog;
|
||||||
|
|
||||||
class DialogsManager : public QObject, public Dependency {
|
class DialogsManager : public QObject, public Dependency {
|
||||||
|
@ -77,10 +73,6 @@ private:
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void maybeCreateDialog(QPointer<T>& member);
|
void maybeCreateDialog(QPointer<T>& member);
|
||||||
|
|
||||||
QPointer<AnimationsDialog> _animationsDialog;
|
|
||||||
QPointer<AttachmentsDialog> _attachmentsDialog;
|
|
||||||
QPointer<CachesSizeDialog> _cachesSizeDialog;
|
|
||||||
QPointer<QMessageBox> _ircInfoBox;
|
|
||||||
QPointer<HMDToolsDialog> _hmdToolsDialog;
|
QPointer<HMDToolsDialog> _hmdToolsDialog;
|
||||||
QPointer<LodToolsDialog> _lodToolsDialog;
|
QPointer<LodToolsDialog> _lodToolsDialog;
|
||||||
QPointer<OctreeStatsDialog> _octreeStatsDialog;
|
QPointer<OctreeStatsDialog> _octreeStatsDialog;
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
#include <NetworkingConstants.h>
|
#include <NetworkingConstants.h>
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
|
|
||||||
const char* MODEL_TYPE_NAMES[] = { "entities", "heads", "skeletons", "skeletons", "attachments" };
|
const char* MODEL_TYPE_NAMES[] = { "entities", "heads", "skeletons", "skeletons" };
|
||||||
|
|
||||||
static const QString S3_URL = NetworkingConstants::HF_PUBLIC_CDN_URL;
|
static const QString S3_URL = NetworkingConstants::HF_PUBLIC_CDN_URL;
|
||||||
static const QString PUBLIC_URL = "http://public.overte.org"; // Changed to Overte but not entirely sure what to do with this yet.
|
static const QString PUBLIC_URL = "http://public.overte.org"; // Changed to Overte but not entirely sure what to do with this yet.
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
#include <VariantMapToScriptValue.h>
|
#include <VariantMapToScriptValue.h>
|
||||||
#include <DebugDraw.h>
|
#include <DebugDraw.h>
|
||||||
#include <shared/Camera.h>
|
#include <shared/Camera.h>
|
||||||
#include <SoftAttachmentModel.h>
|
|
||||||
#include <render/TransitionStage.h>
|
#include <render/TransitionStage.h>
|
||||||
#include <GLMHelpers.h>
|
#include <GLMHelpers.h>
|
||||||
#include "ModelEntityItem.h"
|
#include "ModelEntityItem.h"
|
||||||
|
@ -52,7 +51,6 @@ const float DISPLAYNAME_BACKGROUND_ALPHA = 0.4f;
|
||||||
const glm::vec3 HAND_TO_PALM_OFFSET(0.0f, 0.12f, 0.08f);
|
const glm::vec3 HAND_TO_PALM_OFFSET(0.0f, 0.12f, 0.08f);
|
||||||
const float Avatar::MYAVATAR_LOADING_PRIORITY = (float)M_PI; // Entity priority is computed as atan2(maxDim, distance) which is <= PI / 2
|
const float Avatar::MYAVATAR_LOADING_PRIORITY = (float)M_PI; // Entity priority is computed as atan2(maxDim, distance) which is <= PI / 2
|
||||||
const float Avatar::OTHERAVATAR_LOADING_PRIORITY = MYAVATAR_LOADING_PRIORITY - EPSILON;
|
const float Avatar::OTHERAVATAR_LOADING_PRIORITY = MYAVATAR_LOADING_PRIORITY - EPSILON;
|
||||||
const float Avatar::ATTACHMENT_LOADING_PRIORITY = OTHERAVATAR_LOADING_PRIORITY - EPSILON;
|
|
||||||
|
|
||||||
namespace render {
|
namespace render {
|
||||||
template <> const ItemKey payloadGetKey(const AvatarSharedPointer& avatar) {
|
template <> const ItemKey payloadGetKey(const AvatarSharedPointer& avatar) {
|
||||||
|
@ -651,19 +649,6 @@ void Avatar::addToScene(AvatarSharedPointer self, const render::ScenePointer& sc
|
||||||
_skeletonModel->setVisibleInScene(_isMeshVisible, scene);
|
_skeletonModel->setVisibleInScene(_isMeshVisible, scene);
|
||||||
|
|
||||||
processMaterials();
|
processMaterials();
|
||||||
bool attachmentRenderingNeedsUpdate = false;
|
|
||||||
for (auto& attachmentModel : _attachmentModels) {
|
|
||||||
attachmentModel->addToScene(scene, transaction);
|
|
||||||
attachmentModel->setTagMask(render::hifi::TAG_ALL_VIEWS);
|
|
||||||
attachmentModel->setGroupCulled(true);
|
|
||||||
attachmentModel->setCanCastShadow(true);
|
|
||||||
attachmentModel->setVisibleInScene(_isMeshVisible, scene);
|
|
||||||
attachmentRenderingNeedsUpdate = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attachmentRenderingNeedsUpdate) {
|
|
||||||
updateAttachmentRenderIDs();
|
|
||||||
}
|
|
||||||
|
|
||||||
_mustFadeIn = true;
|
_mustFadeIn = true;
|
||||||
emit DependencyManager::get<scriptable::ModelProviderFactory>()->modelAddedToScene(getSessionUUID(), NestableType::Avatar, _skeletonModel);
|
emit DependencyManager::get<scriptable::ModelProviderFactory>()->modelAddedToScene(getSessionUUID(), NestableType::Avatar, _skeletonModel);
|
||||||
|
@ -688,11 +673,6 @@ void Avatar::fadeOut(render::Transaction& transaction, KillAvatarReason reason)
|
||||||
|
|
||||||
void Avatar::fade(render::Transaction& transaction, render::Transition::Type type) {
|
void Avatar::fade(render::Transaction& transaction, render::Transition::Type type) {
|
||||||
transaction.resetTransitionOnItem(_renderItemID, type);
|
transaction.resetTransitionOnItem(_renderItemID, type);
|
||||||
for (auto& attachmentModel : _attachmentModels) {
|
|
||||||
for (auto itemId : attachmentModel->fetchRenderItemIDs()) {
|
|
||||||
transaction.resetTransitionOnItem(itemId, type, _renderItemID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_lastFadeRequested = type;
|
_lastFadeRequested = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -704,9 +684,6 @@ void Avatar::removeFromScene(AvatarSharedPointer self, const render::ScenePointe
|
||||||
transaction.removeItem(_renderItemID);
|
transaction.removeItem(_renderItemID);
|
||||||
render::Item::clearID(_renderItemID);
|
render::Item::clearID(_renderItemID);
|
||||||
_skeletonModel->removeFromScene(scene, transaction);
|
_skeletonModel->removeFromScene(scene, transaction);
|
||||||
for (auto& attachmentModel : _attachmentModels) {
|
|
||||||
attachmentModel->removeFromScene(scene, transaction);
|
|
||||||
}
|
|
||||||
emit DependencyManager::get<scriptable::ModelProviderFactory>()->modelRemovedFromScene(getSessionUUID(), NestableType::Avatar, _skeletonModel);
|
emit DependencyManager::get<scriptable::ModelProviderFactory>()->modelRemovedFromScene(getSessionUUID(), NestableType::Avatar, _skeletonModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -866,8 +843,6 @@ bool Avatar::getEnableMeshVisible() const {
|
||||||
void Avatar::fixupModelsInScene(const render::ScenePointer& scene) {
|
void Avatar::fixupModelsInScene(const render::ScenePointer& scene) {
|
||||||
bool canTryFade{ false };
|
bool canTryFade{ false };
|
||||||
|
|
||||||
_attachmentsToDelete.clear();
|
|
||||||
|
|
||||||
// check to see if when we added our models to the scene they were ready, if they were not ready, then
|
// check to see if when we added our models to the scene they were ready, if they were not ready, then
|
||||||
// fix them up in the scene
|
// fix them up in the scene
|
||||||
render::Transaction transaction;
|
render::Transaction transaction;
|
||||||
|
@ -885,27 +860,9 @@ void Avatar::fixupModelsInScene(const render::ScenePointer& scene) {
|
||||||
canTryFade = true;
|
canTryFade = true;
|
||||||
_isAnimatingScale = true;
|
_isAnimatingScale = true;
|
||||||
}
|
}
|
||||||
bool attachmentRenderingNeedsUpdate = false;
|
|
||||||
for (auto attachmentModel : _attachmentModels) {
|
|
||||||
if (attachmentModel->isRenderable() && attachmentModel->needsFixupInScene()) {
|
|
||||||
attachmentModel->removeFromScene(scene, transaction);
|
|
||||||
attachmentModel->addToScene(scene, transaction);
|
|
||||||
|
|
||||||
attachmentModel->setTagMask(render::hifi::TAG_ALL_VIEWS);
|
|
||||||
attachmentModel->setGroupCulled(true);
|
|
||||||
attachmentModel->setCanCastShadow(true);
|
|
||||||
attachmentModel->setVisibleInScene(_isMeshVisible, scene);
|
|
||||||
attachmentRenderingNeedsUpdate = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_needMeshVisibleSwitch) {
|
if (_needMeshVisibleSwitch) {
|
||||||
_skeletonModel->setVisibleInScene(_isMeshVisible, scene);
|
_skeletonModel->setVisibleInScene(_isMeshVisible, scene);
|
||||||
for (auto attachmentModel : _attachmentModels) {
|
|
||||||
if (attachmentModel->isRenderable()) {
|
|
||||||
attachmentModel->setVisibleInScene(_isMeshVisible, scene);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
updateRenderItem(transaction);
|
updateRenderItem(transaction);
|
||||||
_needMeshVisibleSwitch = false;
|
_needMeshVisibleSwitch = false;
|
||||||
}
|
}
|
||||||
|
@ -916,17 +873,6 @@ void Avatar::fixupModelsInScene(const render::ScenePointer& scene) {
|
||||||
_mustFadeIn = false;
|
_mustFadeIn = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto attachmentModelToRemove : _attachmentsToRemove) {
|
|
||||||
attachmentModelToRemove->removeFromScene(scene, transaction);
|
|
||||||
attachmentRenderingNeedsUpdate = true;
|
|
||||||
}
|
|
||||||
_attachmentsToDelete.insert(_attachmentsToDelete.end(), _attachmentsToRemove.begin(), _attachmentsToRemove.end());
|
|
||||||
_attachmentsToRemove.clear();
|
|
||||||
|
|
||||||
if (attachmentRenderingNeedsUpdate) {
|
|
||||||
updateAttachmentRenderIDs();
|
|
||||||
}
|
|
||||||
|
|
||||||
scene->enqueueTransaction(transaction);
|
scene->enqueueTransaction(transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -934,48 +880,6 @@ bool Avatar::shouldRenderHead(const RenderArgs* renderArgs) const {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Avatar::simulateAttachments(float deltaTime) {
|
|
||||||
assert(_attachmentModels.size() == _attachmentModelsTexturesLoaded.size());
|
|
||||||
PerformanceTimer perfTimer("attachments");
|
|
||||||
for (int i = 0; i < (int)_attachmentModels.size(); i++) {
|
|
||||||
const AttachmentData& attachment = _attachmentData.at(i);
|
|
||||||
auto& model = _attachmentModels.at(i);
|
|
||||||
bool texturesLoaded = _attachmentModelsTexturesLoaded.at(i);
|
|
||||||
|
|
||||||
// Watch for texture loading
|
|
||||||
if (!texturesLoaded && model->getGeometry() && model->getGeometry()->areTexturesLoaded()) {
|
|
||||||
_attachmentModelsTexturesLoaded[i] = true;
|
|
||||||
model->updateRenderItems();
|
|
||||||
}
|
|
||||||
|
|
||||||
int jointIndex = getJointIndex(attachment.jointName);
|
|
||||||
glm::vec3 jointPosition;
|
|
||||||
glm::quat jointRotation;
|
|
||||||
if (attachment.isSoft) {
|
|
||||||
// soft attachments do not have transform offsets
|
|
||||||
model->setTransformNoUpdateRenderItems(Transform(getWorldOrientation() * Quaternions::Y_180, glm::vec3(1.0), getWorldPosition()));
|
|
||||||
model->simulate(deltaTime);
|
|
||||||
model->updateRenderItems();
|
|
||||||
} else {
|
|
||||||
if (_skeletonModel->getJointPositionInWorldFrame(jointIndex, jointPosition) &&
|
|
||||||
_skeletonModel->getJointRotationInWorldFrame(jointIndex, jointRotation)) {
|
|
||||||
model->setTransformNoUpdateRenderItems(Transform(jointRotation * attachment.rotation, glm::vec3(1.0), jointPosition + jointRotation * attachment.translation * getModelScale()));
|
|
||||||
float scale = getModelScale() * attachment.scale;
|
|
||||||
model->setScaleToFit(true, model->getNaturalDimensions() * scale, true); // hack to force rescale
|
|
||||||
model->setSnapModelToCenter(false); // hack to force resnap
|
|
||||||
model->setSnapModelToCenter(true);
|
|
||||||
model->simulate(deltaTime);
|
|
||||||
model->updateRenderItems();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_ancestorChainRenderableVersion != _lastAncestorChainRenderableVersion) {
|
|
||||||
_lastAncestorChainRenderableVersion = _ancestorChainRenderableVersion;
|
|
||||||
updateDescendantRenderIDs();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float Avatar::getBoundingRadius() const {
|
float Avatar::getBoundingRadius() const {
|
||||||
return getBounds().getLargestDimension() / 2.0f;
|
return getBounds().getLargestDimension() / 2.0f;
|
||||||
}
|
}
|
||||||
|
@ -1631,58 +1535,6 @@ void Avatar::updateFitBoundingBox() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// create new model, can return an instance of a SoftAttachmentModel rather then Model
|
|
||||||
static std::shared_ptr<Model> allocateAttachmentModel(bool isSoft, const Rig& rigOverride, bool isCauterized) {
|
|
||||||
if (isSoft) {
|
|
||||||
// cast to std::shared_ptr<Model>
|
|
||||||
std::shared_ptr<SoftAttachmentModel> softModel = std::make_shared<SoftAttachmentModel>(nullptr, rigOverride);
|
|
||||||
if (isCauterized) {
|
|
||||||
softModel->flagAsCauterized();
|
|
||||||
}
|
|
||||||
return std::dynamic_pointer_cast<Model>(softModel);
|
|
||||||
} else {
|
|
||||||
return std::make_shared<Model>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Avatar::setAttachmentData(const QVector<AttachmentData>& attachmentData) {
|
|
||||||
if (QThread::currentThread() != thread()) {
|
|
||||||
BLOCKING_INVOKE_METHOD(this, "setAttachmentData",
|
|
||||||
Q_ARG(const QVector<AttachmentData>, attachmentData));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto oldAttachmentData = _attachmentData;
|
|
||||||
AvatarData::setAttachmentData(attachmentData);
|
|
||||||
|
|
||||||
// if number of attachments has been reduced, remove excess models.
|
|
||||||
while ((int)_attachmentModels.size() > attachmentData.size()) {
|
|
||||||
auto attachmentModel = _attachmentModels.back();
|
|
||||||
_attachmentModels.pop_back();
|
|
||||||
_attachmentModelsTexturesLoaded.pop_back();
|
|
||||||
_attachmentsToRemove.push_back(attachmentModel);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < attachmentData.size(); i++) {
|
|
||||||
if (i == (int)_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(), isMyAvatar()));
|
|
||||||
_attachmentModelsTexturesLoaded.push_back(false);
|
|
||||||
} 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(), isMyAvatar());
|
|
||||||
_attachmentModelsTexturesLoaded[i] = false;
|
|
||||||
}
|
|
||||||
// If the model URL has changd, we need to wait for the textures to load
|
|
||||||
if (_attachmentModels[i]->getURL() != attachmentData[i].modelURL) {
|
|
||||||
_attachmentModelsTexturesLoaded[i] = false;
|
|
||||||
}
|
|
||||||
_attachmentModels[i]->setLoadingPriority(ATTACHMENT_LOADING_PRIORITY);
|
|
||||||
_attachmentModels[i]->setURL(attachmentData[i].modelURL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int Avatar::parseDataFromBuffer(const QByteArray& buffer) {
|
int Avatar::parseDataFromBuffer(const QByteArray& buffer) {
|
||||||
PerformanceTimer perfTimer("unpack");
|
PerformanceTimer perfTimer("unpack");
|
||||||
if (!_initialized) {
|
if (!_initialized) {
|
||||||
|
@ -2102,11 +1954,6 @@ uint32_t Avatar::appendSubMetaItems(render::ItemIDs& subItems) {
|
||||||
return _subItemLock.resultWithReadLock<uint32_t>([&] {
|
return _subItemLock.resultWithReadLock<uint32_t>([&] {
|
||||||
uint32_t total = 0;
|
uint32_t total = 0;
|
||||||
|
|
||||||
if (_attachmentRenderIDs.size() > 0) {
|
|
||||||
subItems.insert(subItems.end(), _attachmentRenderIDs.begin(), _attachmentRenderIDs.end());
|
|
||||||
total += (uint32_t)_attachmentRenderIDs.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_descendantRenderIDs.size() > 0) {
|
if (_descendantRenderIDs.size() > 0) {
|
||||||
subItems.insert(subItems.end(), _descendantRenderIDs.begin(), _descendantRenderIDs.end());
|
subItems.insert(subItems.end(), _descendantRenderIDs.begin(), _descendantRenderIDs.end());
|
||||||
total += (uint32_t)_descendantRenderIDs.size();
|
total += (uint32_t)_descendantRenderIDs.size();
|
||||||
|
@ -2116,18 +1963,6 @@ uint32_t Avatar::appendSubMetaItems(render::ItemIDs& subItems) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Avatar::updateAttachmentRenderIDs() {
|
|
||||||
_subItemLock.withWriteLock([&] {
|
|
||||||
_attachmentRenderIDs.clear();
|
|
||||||
for (auto& attachmentModel : _attachmentModels) {
|
|
||||||
if (attachmentModel && attachmentModel->isRenderable()) {
|
|
||||||
auto& metaSubItems = attachmentModel->fetchRenderItemIDs();
|
|
||||||
_attachmentRenderIDs.insert(_attachmentRenderIDs.end(), metaSubItems.begin(), metaSubItems.end());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void Avatar::updateDescendantRenderIDs() {
|
void Avatar::updateDescendantRenderIDs() {
|
||||||
_subItemLock.withWriteLock([&] {
|
_subItemLock.withWriteLock([&] {
|
||||||
auto oldRenderingDescendantEntityIDs = _renderingDescendantEntityIDs;
|
auto oldRenderingDescendantEntityIDs = _renderingDescendantEntityIDs;
|
||||||
|
|
|
@ -157,7 +157,6 @@ public:
|
||||||
void init();
|
void init();
|
||||||
void removeAvatarEntitiesFromTree();
|
void removeAvatarEntitiesFromTree();
|
||||||
virtual void simulate(float deltaTime, bool inView) = 0;
|
virtual void simulate(float deltaTime, bool inView) = 0;
|
||||||
virtual void simulateAttachments(float deltaTime);
|
|
||||||
|
|
||||||
virtual void render(RenderArgs* renderArgs);
|
virtual void render(RenderArgs* renderArgs);
|
||||||
|
|
||||||
|
@ -344,7 +343,6 @@ public:
|
||||||
Q_INVOKABLE glm::quat jointToWorldRotation(const glm::quat& rotation, const int jointIndex = -1) const;
|
Q_INVOKABLE glm::quat jointToWorldRotation(const glm::quat& rotation, const int jointIndex = -1) const;
|
||||||
|
|
||||||
Q_INVOKABLE virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override;
|
Q_INVOKABLE virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override;
|
||||||
virtual void setAttachmentData(const QVector<AttachmentData>& attachmentData) override;
|
|
||||||
|
|
||||||
void updateDisplayNameAlpha(bool showDisplayName);
|
void updateDisplayNameAlpha(bool showDisplayName);
|
||||||
virtual void setSessionDisplayName(const QString& sessionDisplayName) override { }; // no-op
|
virtual void setSessionDisplayName(const QString& sessionDisplayName) override { }; // no-op
|
||||||
|
@ -650,10 +648,6 @@ protected:
|
||||||
mutable bool _modelJointsCached { false };
|
mutable bool _modelJointsCached { false };
|
||||||
|
|
||||||
glm::vec3 _skeletonOffset;
|
glm::vec3 _skeletonOffset;
|
||||||
std::vector<std::shared_ptr<Model>> _attachmentModels;
|
|
||||||
std::vector<bool> _attachmentModelsTexturesLoaded;
|
|
||||||
std::vector<std::shared_ptr<Model>> _attachmentsToRemove;
|
|
||||||
std::vector<std::shared_ptr<Model>> _attachmentsToDelete;
|
|
||||||
|
|
||||||
float _bodyYawDelta { 0.0f }; // degrees/sec
|
float _bodyYawDelta { 0.0f }; // degrees/sec
|
||||||
float _seatedBodyYawDelta{ 0.0f }; // degrees/renderframe
|
float _seatedBodyYawDelta{ 0.0f }; // degrees/renderframe
|
||||||
|
@ -753,7 +747,6 @@ protected:
|
||||||
|
|
||||||
static const float MYAVATAR_LOADING_PRIORITY;
|
static const float MYAVATAR_LOADING_PRIORITY;
|
||||||
static const float OTHERAVATAR_LOADING_PRIORITY;
|
static const float OTHERAVATAR_LOADING_PRIORITY;
|
||||||
static const float ATTACHMENT_LOADING_PRIORITY;
|
|
||||||
|
|
||||||
LoadingStatus _loadingStatus { LoadingStatus::NoModel };
|
LoadingStatus _loadingStatus { LoadingStatus::NoModel };
|
||||||
|
|
||||||
|
@ -773,12 +766,9 @@ protected:
|
||||||
VectorOfIDs _grabsToDelete; // deleted grab IDs -- changes needed to entities or physics
|
VectorOfIDs _grabsToDelete; // deleted grab IDs -- changes needed to entities or physics
|
||||||
|
|
||||||
ReadWriteLockable _subItemLock;
|
ReadWriteLockable _subItemLock;
|
||||||
void updateAttachmentRenderIDs();
|
|
||||||
render::ItemIDs _attachmentRenderIDs;
|
|
||||||
void updateDescendantRenderIDs();
|
void updateDescendantRenderIDs();
|
||||||
render::ItemIDs _descendantRenderIDs;
|
render::ItemIDs _descendantRenderIDs;
|
||||||
std::unordered_set<EntityItemID> _renderingDescendantEntityIDs;
|
std::unordered_set<EntityItemID> _renderingDescendantEntityIDs;
|
||||||
uint32_t _lastAncestorChainRenderableVersion { 0 };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_Avatar_h
|
#endif // hifi_Avatar_h
|
||||||
|
|
|
@ -58,8 +58,6 @@
|
||||||
* when the other avatar is in the line of sight and also has <code>lookAtSnappingEnabled == true</code>.
|
* when the other avatar is in the line of sight and also has <code>lookAtSnappingEnabled == true</code>.
|
||||||
*
|
*
|
||||||
* @property {string} skeletonModelURL - The avatar's FST file.
|
* @property {string} skeletonModelURL - The avatar's FST file.
|
||||||
* @property {AttachmentData[]} attachmentData - Information on the avatar's attachments.
|
|
||||||
* <p class="important">Deprecated: This property is deprecated and will be removed. Use avatar entities instead.</p>
|
|
||||||
* @property {string[]} jointNames - The list of joints in the avatar model.
|
* @property {string[]} jointNames - The list of joints in the avatar model.
|
||||||
*
|
*
|
||||||
* @property {number} audioLoudness - The instantaneous loudness of the audio input that the avatar is injecting into the
|
* @property {number} audioLoudness - The instantaneous loudness of the audio input that the avatar is injecting into the
|
||||||
|
|
|
@ -73,17 +73,10 @@ static const float DEFAULT_AVATAR_DENSITY = 1000.0f; // density of water
|
||||||
STATIC_SCRIPT_TYPES_INITIALIZER((+[](ScriptManager* manager) {
|
STATIC_SCRIPT_TYPES_INITIALIZER((+[](ScriptManager* manager) {
|
||||||
auto scriptEngine = manager->engine().get();
|
auto scriptEngine = manager->engine().get();
|
||||||
|
|
||||||
registerAvatarTypes(scriptEngine);
|
|
||||||
scriptRegisterMetaType<RayToAvatarIntersectionResult, RayToAvatarIntersectionResultToScriptValue, RayToAvatarIntersectionResultFromScriptValue>(scriptEngine);
|
scriptRegisterMetaType<RayToAvatarIntersectionResult, RayToAvatarIntersectionResultToScriptValue, RayToAvatarIntersectionResultFromScriptValue>(scriptEngine);
|
||||||
scriptRegisterMetaType<AvatarEntityMap, AvatarEntityMapToScriptValue, AvatarEntityMapFromScriptValue>(scriptEngine);
|
scriptRegisterMetaType<AvatarEntityMap, AvatarEntityMapToScriptValue, AvatarEntityMapFromScriptValue>(scriptEngine);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
STATIC_SCRIPT_INITIALIZER(+[](ScriptManager* manager) {
|
|
||||||
auto scriptEngine = manager->engine().get();
|
|
||||||
|
|
||||||
registerAvatarPrototypes(scriptEngine);
|
|
||||||
});
|
|
||||||
|
|
||||||
size_t AvatarDataPacket::maxFaceTrackerInfoSize(size_t numBlendshapeCoefficients) {
|
size_t AvatarDataPacket::maxFaceTrackerInfoSize(size_t numBlendshapeCoefficients) {
|
||||||
return FACE_TRACKER_INFO_SIZE + numBlendshapeCoefficients * sizeof(float);
|
return FACE_TRACKER_INFO_SIZE + numBlendshapeCoefficients * sizeof(float);
|
||||||
}
|
}
|
||||||
|
@ -2027,7 +2020,6 @@ void AvatarData::processAvatarIdentity(QDataStream& packetStream, bool& identity
|
||||||
Identity identity;
|
Identity identity;
|
||||||
|
|
||||||
packetStream
|
packetStream
|
||||||
>> identity.attachmentData
|
|
||||||
>> identity.displayName
|
>> identity.displayName
|
||||||
>> identity.sessionDisplayName
|
>> identity.sessionDisplayName
|
||||||
>> identity.identityFlags
|
>> identity.identityFlags
|
||||||
|
@ -2068,11 +2060,6 @@ void AvatarData::processAvatarIdentity(QDataStream& packetStream, bool& identity
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (identity.attachmentData != _attachmentData) {
|
|
||||||
setAttachmentData(identity.attachmentData);
|
|
||||||
identityChanged = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef WANT_DEBUG
|
#ifdef WANT_DEBUG
|
||||||
qCDebug(avatars) << __FUNCTION__
|
qCDebug(avatars) << __FUNCTION__
|
||||||
<< "identity.uuid:" << identity.uuid
|
<< "identity.uuid:" << identity.uuid
|
||||||
|
@ -2319,7 +2306,6 @@ QByteArray AvatarData::identityByteArray(bool setIsReplicated) const {
|
||||||
|
|
||||||
identityStream << getSessionUUID()
|
identityStream << getSessionUUID()
|
||||||
<< (udt::SequenceNumber::Type) _identitySequenceNumber
|
<< (udt::SequenceNumber::Type) _identitySequenceNumber
|
||||||
<< _attachmentData
|
|
||||||
<< _displayName
|
<< _displayName
|
||||||
<< getSessionDisplayNameForTransport() // depends on _sessionDisplayName
|
<< getSessionDisplayNameForTransport() // depends on _sessionDisplayName
|
||||||
<< identityFlags;
|
<< identityFlags;
|
||||||
|
@ -2353,86 +2339,6 @@ void AvatarData::setDisplayName(const QString& displayName) {
|
||||||
markIdentityDataChanged();
|
markIdentityDataChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<AttachmentData> AvatarData::getAttachmentData() const {
|
|
||||||
if (QThread::currentThread() != thread()) {
|
|
||||||
QVector<AttachmentData> result;
|
|
||||||
BLOCKING_INVOKE_METHOD(const_cast<AvatarData*>(this), "getAttachmentData",
|
|
||||||
Q_RETURN_ARG(QVector<AttachmentData>, result));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return _attachmentData;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AvatarData::setAttachmentData(const QVector<AttachmentData>& attachmentData) {
|
|
||||||
if (QThread::currentThread() != thread()) {
|
|
||||||
QMetaObject::invokeMethod(this, "setAttachmentData", Q_ARG(const QVector<AttachmentData>&, attachmentData));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_attachmentData = attachmentData;
|
|
||||||
markIdentityDataChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AvatarData::attach(const QString& modelURL, const QString& jointName,
|
|
||||||
const glm::vec3& translation, const glm::quat& rotation,
|
|
||||||
float scale, bool isSoft,
|
|
||||||
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, isSoft),
|
|
||||||
Q_ARG(bool, allowDuplicates), Q_ARG(bool, useSaved));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
QVector<AttachmentData> attachmentData = getAttachmentData();
|
|
||||||
if (!allowDuplicates) {
|
|
||||||
foreach (const AttachmentData& data, attachmentData) {
|
|
||||||
if (data.modelURL == modelURL && (jointName.isEmpty() || data.jointName == jointName)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AttachmentData data;
|
|
||||||
data.modelURL = modelURL;
|
|
||||||
data.jointName = jointName;
|
|
||||||
data.translation = translation;
|
|
||||||
data.rotation = rotation;
|
|
||||||
data.scale = scale;
|
|
||||||
data.isSoft = isSoft;
|
|
||||||
attachmentData.append(data);
|
|
||||||
setAttachmentData(attachmentData);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AvatarData::detachOne(const QString& modelURL, const QString& jointName) {
|
|
||||||
if (QThread::currentThread() != thread()) {
|
|
||||||
QMetaObject::invokeMethod(this, "detachOne", Q_ARG(const QString&, modelURL), Q_ARG(const QString&, jointName));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
QVector<AttachmentData> attachmentData = getAttachmentData();
|
|
||||||
for (QVector<AttachmentData>::iterator it = attachmentData.begin(); it != attachmentData.end(); ++it) {
|
|
||||||
if (it->modelURL == modelURL && (jointName.isEmpty() || it->jointName == jointName)) {
|
|
||||||
attachmentData.erase(it);
|
|
||||||
setAttachmentData(attachmentData);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AvatarData::detachAll(const QString& modelURL, const QString& jointName) {
|
|
||||||
if (QThread::currentThread() != thread()) {
|
|
||||||
QMetaObject::invokeMethod(this, "detachAll", Q_ARG(const QString&, modelURL), Q_ARG(const QString&, jointName));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
QVector<AttachmentData> attachmentData = getAttachmentData();
|
|
||||||
for (QVector<AttachmentData>::iterator it = attachmentData.begin(); it != attachmentData.end(); ) {
|
|
||||||
if (it->modelURL == modelURL && (jointName.isEmpty() || it->jointName == jointName)) {
|
|
||||||
it = attachmentData.erase(it);
|
|
||||||
} else {
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setAttachmentData(attachmentData);
|
|
||||||
}
|
|
||||||
|
|
||||||
int AvatarData::sendAvatarDataPacket(bool sendAll) {
|
int AvatarData::sendAvatarDataPacket(bool sendAll) {
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
|
|
||||||
|
@ -2495,149 +2401,6 @@ int AvatarData::sendIdentityPacket() {
|
||||||
return identityData.size();
|
return identityData.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
static const QString JSON_ATTACHMENT_URL = QStringLiteral("modelUrl");
|
|
||||||
static const QString JSON_ATTACHMENT_JOINT_NAME = QStringLiteral("jointName");
|
|
||||||
static const QString JSON_ATTACHMENT_TRANSFORM = QStringLiteral("transform");
|
|
||||||
static const QString JSON_ATTACHMENT_IS_SOFT = QStringLiteral("isSoft");
|
|
||||||
|
|
||||||
QJsonObject AttachmentData::toJson() const {
|
|
||||||
QJsonObject result;
|
|
||||||
if (modelURL.isValid() && !modelURL.isEmpty()) {
|
|
||||||
result[JSON_ATTACHMENT_URL] = modelURL.toString();
|
|
||||||
}
|
|
||||||
if (!jointName.isEmpty()) {
|
|
||||||
result[JSON_ATTACHMENT_JOINT_NAME] = jointName;
|
|
||||||
}
|
|
||||||
// FIXME the transform constructor that takes rot/scale/translation
|
|
||||||
// doesn't return the correct value for isIdentity()
|
|
||||||
Transform transform;
|
|
||||||
transform.setRotation(rotation);
|
|
||||||
transform.setScale(scale);
|
|
||||||
transform.setTranslation(translation);
|
|
||||||
if (!transform.isIdentity()) {
|
|
||||||
result[JSON_ATTACHMENT_TRANSFORM] = Transform::toJson(transform);
|
|
||||||
}
|
|
||||||
result[JSON_ATTACHMENT_IS_SOFT] = isSoft;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AttachmentData::fromJson(const QJsonObject& json) {
|
|
||||||
if (json.contains(JSON_ATTACHMENT_URL)) {
|
|
||||||
const QString modelURLTemp = json[JSON_ATTACHMENT_URL].toString();
|
|
||||||
if (modelURLTemp != modelURL.toString()) {
|
|
||||||
modelURL = modelURLTemp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (json.contains(JSON_ATTACHMENT_JOINT_NAME)) {
|
|
||||||
const QString jointNameTemp = json[JSON_ATTACHMENT_JOINT_NAME].toString();
|
|
||||||
if (jointNameTemp != jointName) {
|
|
||||||
jointName = jointNameTemp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (json.contains(JSON_ATTACHMENT_TRANSFORM)) {
|
|
||||||
Transform transform = Transform::fromJson(json[JSON_ATTACHMENT_TRANSFORM]);
|
|
||||||
translation = transform.getTranslation();
|
|
||||||
rotation = transform.getRotation();
|
|
||||||
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 {
|
|
||||||
return modelURL == other.modelURL && jointName == other.jointName && translation == other.translation &&
|
|
||||||
rotation == other.rotation && scale == other.scale && isSoft == other.isSoft;
|
|
||||||
}
|
|
||||||
|
|
||||||
QDataStream& operator<<(QDataStream& out, const AttachmentData& attachment) {
|
|
||||||
return out << attachment.modelURL << attachment.jointName <<
|
|
||||||
attachment.translation << attachment.rotation << attachment.scale << attachment.isSoft;
|
|
||||||
}
|
|
||||||
|
|
||||||
QDataStream& operator>>(QDataStream& in, AttachmentData& attachment) {
|
|
||||||
return in >> attachment.modelURL >> attachment.jointName >>
|
|
||||||
attachment.translation >> attachment.rotation >> attachment.scale >> attachment.isSoft;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AttachmentDataObject::setModelURL(const QString& modelURL) {
|
|
||||||
AttachmentData data = scriptvalue_cast<AttachmentData>(thisObject());
|
|
||||||
data.modelURL = modelURL;
|
|
||||||
Q_ASSERT(engine());
|
|
||||||
thisObject() = engine()->toScriptValue(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString AttachmentDataObject::getModelURL() const {
|
|
||||||
return scriptvalue_cast<AttachmentData>(thisObject()).modelURL.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AttachmentDataObject::setJointName(const QString& jointName) {
|
|
||||||
AttachmentData data = scriptvalue_cast<AttachmentData>(thisObject());
|
|
||||||
data.jointName = jointName;
|
|
||||||
Q_ASSERT(engine());
|
|
||||||
thisObject() = engine()->toScriptValue(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString AttachmentDataObject::getJointName() const {
|
|
||||||
return scriptvalue_cast<AttachmentData>(thisObject()).jointName;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AttachmentDataObject::setTranslation(const glm::vec3& translation) {
|
|
||||||
AttachmentData data = scriptvalue_cast<AttachmentData>(thisObject());
|
|
||||||
data.translation = translation;
|
|
||||||
Q_ASSERT(engine());
|
|
||||||
thisObject() = engine()->toScriptValue(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::vec3 AttachmentDataObject::getTranslation() const {
|
|
||||||
return scriptvalue_cast<AttachmentData>(thisObject()).translation;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AttachmentDataObject::setRotation(const glm::quat& rotation) {
|
|
||||||
AttachmentData data = scriptvalue_cast<AttachmentData>(thisObject());
|
|
||||||
data.rotation = rotation;
|
|
||||||
Q_ASSERT(engine());
|
|
||||||
thisObject() = engine()->toScriptValue(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::quat AttachmentDataObject::getRotation() const {
|
|
||||||
return scriptvalue_cast<AttachmentData>(thisObject()).rotation;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AttachmentDataObject::setScale(float scale) {
|
|
||||||
AttachmentData data = scriptvalue_cast<AttachmentData>(thisObject());
|
|
||||||
data.scale = scale;
|
|
||||||
Q_ASSERT(engine());
|
|
||||||
thisObject() = engine()->toScriptValue(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
float AttachmentDataObject::getScale() const {
|
|
||||||
return scriptvalue_cast<AttachmentData>(thisObject()).scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AttachmentDataObject::setIsSoft(bool isSoft) {
|
|
||||||
AttachmentData data = scriptvalue_cast<AttachmentData>(thisObject());
|
|
||||||
data.isSoft = isSoft;
|
|
||||||
Q_ASSERT(engine());
|
|
||||||
thisObject() = engine()->toScriptValue(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AttachmentDataObject::getIsSoft() const {
|
|
||||||
return scriptvalue_cast<AttachmentData>(thisObject()).isSoft;
|
|
||||||
}
|
|
||||||
|
|
||||||
void registerAvatarTypes(ScriptEngine* engine) {
|
|
||||||
scriptRegisterSequenceMetaType<QVector<AttachmentData> >(engine);
|
|
||||||
}
|
|
||||||
|
|
||||||
void registerAvatarPrototypes(ScriptEngine* engine) {
|
|
||||||
engine->setDefaultPrototype(qMetaTypeId<AttachmentData>(), engine->newQObject(
|
|
||||||
new AttachmentDataObject(), ScriptEngine::ScriptOwnership));
|
|
||||||
}
|
|
||||||
|
|
||||||
void AvatarData::setRecordingBasis(std::shared_ptr<Transform> recordingBasis) {
|
void AvatarData::setRecordingBasis(std::shared_ptr<Transform> recordingBasis) {
|
||||||
if (!recordingBasis) {
|
if (!recordingBasis) {
|
||||||
recordingBasis = std::make_shared<Transform>();
|
recordingBasis = std::make_shared<Transform>();
|
||||||
|
@ -2670,7 +2433,6 @@ static const QString JSON_AVATAR_HEAD_MODEL = QStringLiteral("headModel");
|
||||||
static const QString JSON_AVATAR_BODY_MODEL = QStringLiteral("bodyModel");
|
static const QString JSON_AVATAR_BODY_MODEL = QStringLiteral("bodyModel");
|
||||||
static const QString JSON_AVATAR_DISPLAY_NAME = QStringLiteral("displayName");
|
static const QString JSON_AVATAR_DISPLAY_NAME = QStringLiteral("displayName");
|
||||||
// It isn't meaningful to persist sessionDisplayName.
|
// It isn't meaningful to persist sessionDisplayName.
|
||||||
static const QString JSON_AVATAR_ATTACHMENTS = QStringLiteral("attachments");
|
|
||||||
static const QString JSON_AVATAR_ENTITIES = QStringLiteral("attachedEntities");
|
static const QString JSON_AVATAR_ENTITIES = QStringLiteral("attachedEntities");
|
||||||
static const QString JSON_AVATAR_SCALE = QStringLiteral("scale");
|
static const QString JSON_AVATAR_SCALE = QStringLiteral("scale");
|
||||||
static const QString JSON_AVATAR_VERSION = QStringLiteral("version");
|
static const QString JSON_AVATAR_VERSION = QStringLiteral("version");
|
||||||
|
@ -2838,24 +2600,11 @@ void AvatarData::fromJson(const QJsonObject& json, bool useFrameSkeleton) {
|
||||||
setTargetScale((float)json[JSON_AVATAR_SCALE].toDouble());
|
setTargetScale((float)json[JSON_AVATAR_SCALE].toDouble());
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<AttachmentData> attachments;
|
|
||||||
if (json.contains(JSON_AVATAR_ATTACHMENTS) && json[JSON_AVATAR_ATTACHMENTS].isArray()) {
|
|
||||||
QJsonArray attachmentsJson = json[JSON_AVATAR_ATTACHMENTS].toArray();
|
|
||||||
for (auto attachmentJson : attachmentsJson) {
|
|
||||||
AttachmentData attachment;
|
|
||||||
attachment.fromJson(attachmentJson.toObject());
|
|
||||||
attachments.push_back(attachment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (attachments != getAttachmentData()) {
|
|
||||||
setAttachmentData(attachments);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (json.contains(JSON_AVATAR_ENTITIES) && json[JSON_AVATAR_ENTITIES].isArray()) {
|
if (json.contains(JSON_AVATAR_ENTITIES) && json[JSON_AVATAR_ENTITIES].isArray()) {
|
||||||
QJsonArray attachmentsJson = json[JSON_AVATAR_ENTITIES].toArray();
|
QJsonArray avatarEntitiesJSON = json[JSON_AVATAR_ENTITIES].toArray();
|
||||||
for (auto attachmentJson : attachmentsJson) {
|
for (auto avatarEntityJSON : avatarEntitiesJSON) {
|
||||||
if (attachmentJson.isObject()) {
|
if (avatarEntityJSON.isObject()) {
|
||||||
QVariantMap entityData = attachmentJson.toObject().toVariantMap();
|
QVariantMap entityData = avatarEntityJSON.toObject().toVariantMap();
|
||||||
QUuid id = entityData.value("id").toUuid();
|
QUuid id = entityData.value("id").toUuid();
|
||||||
QByteArray data = QByteArray::fromBase64(entityData.value("properties").toByteArray());
|
QByteArray data = QByteArray::fromBase64(entityData.value("properties").toByteArray());
|
||||||
updateAvatarEntity(id, data);
|
updateAvatarEntity(id, data);
|
||||||
|
@ -2970,30 +2719,6 @@ glm::vec3 AvatarData::getAbsoluteJointTranslationInObjectFrame(int index) const
|
||||||
return glm::vec3();
|
return glm::vec3();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*@jsdoc
|
|
||||||
* Information on an attachment worn by the avatar.
|
|
||||||
* @typedef {object} AttachmentData
|
|
||||||
* @property {string} modelUrl - The URL of the glTF, FBX, or OBJ model file. glTF models may be in JSON or binary format
|
|
||||||
* (".gltf" or ".glb" URLs respectively).
|
|
||||||
* @property {string} jointName - The name of the joint that the attachment is parented to.
|
|
||||||
* @property {Vec3} translation - The offset from the joint that the attachment is positioned at.
|
|
||||||
* @property {Vec3} rotation - The rotation applied to the model relative to the joint orientation.
|
|
||||||
* @property {number} scale - The scale applied to the attachment model.
|
|
||||||
* @property {boolean} soft - If <code>true</code> and the model has a skeleton, the bones of the attached model's skeleton are
|
|
||||||
* rotated to fit the avatar's current pose. If <code>true</code>, the <code>translation</code>, <code>rotation</code>, and
|
|
||||||
* <code>scale</code> parameters are ignored.
|
|
||||||
*/
|
|
||||||
QVariant AttachmentData::toVariant() const {
|
|
||||||
QVariantMap result;
|
|
||||||
result["modelUrl"] = modelURL;
|
|
||||||
result["jointName"] = jointName;
|
|
||||||
result["translation"] = vec3ToQMap(translation);
|
|
||||||
result["rotation"] = vec3ToQMap(glm::degrees(safeEulerAngles(rotation)));
|
|
||||||
result["scale"] = scale;
|
|
||||||
result["soft"] = isSoft;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::vec3 variantToVec3(const QVariant& var) {
|
glm::vec3 variantToVec3(const QVariant& var) {
|
||||||
auto map = var.toMap();
|
auto map = var.toMap();
|
||||||
glm::vec3 result;
|
glm::vec3 result;
|
||||||
|
@ -3003,52 +2728,6 @@ glm::vec3 variantToVec3(const QVariant& var) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AttachmentData::fromVariant(const QVariant& variant) {
|
|
||||||
bool isValid = false;
|
|
||||||
auto map = variant.toMap();
|
|
||||||
if (map.contains("modelUrl")) {
|
|
||||||
auto urlString = map["modelUrl"].toString();
|
|
||||||
modelURL = urlString;
|
|
||||||
isValid = true;
|
|
||||||
}
|
|
||||||
if (map.contains("jointName")) {
|
|
||||||
jointName = map["jointName"].toString();
|
|
||||||
}
|
|
||||||
if (map.contains("translation")) {
|
|
||||||
translation = variantToVec3(map["translation"]);
|
|
||||||
}
|
|
||||||
if (map.contains("rotation")) {
|
|
||||||
rotation = glm::quat(glm::radians(variantToVec3(map["rotation"])));
|
|
||||||
}
|
|
||||||
if (map.contains("scale")) {
|
|
||||||
scale = map["scale"].toFloat();
|
|
||||||
}
|
|
||||||
if (map.contains("soft")) {
|
|
||||||
isSoft = map["soft"].toBool();
|
|
||||||
}
|
|
||||||
return isValid;
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariantList AvatarData::getAttachmentsVariant() const {
|
|
||||||
QVariantList result;
|
|
||||||
for (const auto& attachment : getAttachmentData()) {
|
|
||||||
result.append(attachment.toVariant());
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AvatarData::setAttachmentsVariant(const QVariantList& variant) {
|
|
||||||
QVector<AttachmentData> newAttachments;
|
|
||||||
newAttachments.reserve(variant.size());
|
|
||||||
for (const auto& attachmentVar : variant) {
|
|
||||||
AttachmentData attachment;
|
|
||||||
if (attachment.fromVariant(attachmentVar)) {
|
|
||||||
newAttachments.append(attachment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setAttachmentData(newAttachments);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AvatarData::storeAvatarEntityDataPayload(const QUuid& entityID, const QByteArray& data) {
|
void AvatarData::storeAvatarEntityDataPayload(const QUuid& entityID, const QByteArray& data) {
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
_avatarEntitiesLock.withWriteLock([&] {
|
_avatarEntitiesLock.withWriteLock([&] {
|
||||||
|
|
|
@ -451,7 +451,6 @@ Q_DECLARE_METATYPE(KillAvatarReason);
|
||||||
|
|
||||||
class QDataStream;
|
class QDataStream;
|
||||||
|
|
||||||
class AttachmentData;
|
|
||||||
class Transform;
|
class Transform;
|
||||||
using TransformPointer = std::shared_ptr<Transform>;
|
using TransformPointer = std::shared_ptr<Transform>;
|
||||||
|
|
||||||
|
@ -523,8 +522,6 @@ class AvatarData : public QObject, public SpatiallyNestable {
|
||||||
* @property {boolean} lookAtSnappingEnabled=true - <code>true</code> if the avatar's eyes snap to look at another avatar's
|
* @property {boolean} lookAtSnappingEnabled=true - <code>true</code> if the avatar's eyes snap to look at another avatar's
|
||||||
* eyes when the other avatar is in the line of sight and also has <code>lookAtSnappingEnabled == true</code>.
|
* eyes when the other avatar is in the line of sight and also has <code>lookAtSnappingEnabled == true</code>.
|
||||||
* @property {string} skeletonModelURL - The avatar's FST file.
|
* @property {string} skeletonModelURL - The avatar's FST file.
|
||||||
* @property {AttachmentData[]} attachmentData - Information on the avatar's attachments.
|
|
||||||
* <p class="important">Deprecated: This property is deprecated and will be removed. Use avatar entities instead.</p>
|
|
||||||
* @property {string[]} jointNames - The list of joints in the current avatar model. <em>Read-only.</em>
|
* @property {string[]} jointNames - The list of joints in the current avatar model. <em>Read-only.</em>
|
||||||
* @property {Uuid} sessionUUID - Unique ID of the avatar in the domain. <em>Read-only.</em>
|
* @property {Uuid} sessionUUID - Unique ID of the avatar in the domain. <em>Read-only.</em>
|
||||||
* @property {Mat4} sensorToWorldMatrix - The scale, rotation, and translation transform from the user's real world to the
|
* @property {Mat4} sensorToWorldMatrix - The scale, rotation, and translation transform from the user's real world to the
|
||||||
|
@ -580,7 +577,6 @@ class AvatarData : public QObject, public SpatiallyNestable {
|
||||||
Q_PROPERTY(QString sessionDisplayName READ getSessionDisplayName WRITE setSessionDisplayName NOTIFY sessionDisplayNameChanged)
|
Q_PROPERTY(QString sessionDisplayName READ getSessionDisplayName WRITE setSessionDisplayName NOTIFY sessionDisplayNameChanged)
|
||||||
Q_PROPERTY(bool lookAtSnappingEnabled MEMBER _lookAtSnappingEnabled NOTIFY lookAtSnappingChanged)
|
Q_PROPERTY(bool lookAtSnappingEnabled MEMBER _lookAtSnappingEnabled NOTIFY lookAtSnappingChanged)
|
||||||
Q_PROPERTY(QString skeletonModelURL READ getSkeletonModelURLFromScript WRITE setSkeletonModelURLFromScript NOTIFY skeletonModelURLChanged)
|
Q_PROPERTY(QString skeletonModelURL READ getSkeletonModelURLFromScript WRITE setSkeletonModelURLFromScript NOTIFY skeletonModelURLChanged)
|
||||||
Q_PROPERTY(QVector<AttachmentData> attachmentData READ getAttachmentData WRITE setAttachmentData)
|
|
||||||
|
|
||||||
Q_PROPERTY(QStringList jointNames READ getJointNames)
|
Q_PROPERTY(QStringList jointNames READ getJointNames)
|
||||||
|
|
||||||
|
@ -1145,27 +1141,6 @@ public:
|
||||||
*/
|
*/
|
||||||
Q_INVOKABLE void setBlendshape(QString name, float val) { _headData->setBlendshape(name, val); }
|
Q_INVOKABLE void setBlendshape(QString name, float val) { _headData->setBlendshape(name, val); }
|
||||||
|
|
||||||
|
|
||||||
/*@jsdoc
|
|
||||||
* Gets information about the models currently attached to your avatar.
|
|
||||||
* @function Avatar.getAttachmentsVariant
|
|
||||||
* @returns {AttachmentData[]} Information about all models attached to your avatar.
|
|
||||||
* @deprecated This function is deprecated and will be removed. Use avatar entities instead.
|
|
||||||
*/
|
|
||||||
// FIXME: Can this name be improved? Can it be deprecated?
|
|
||||||
Q_INVOKABLE virtual QVariantList getAttachmentsVariant() const;
|
|
||||||
|
|
||||||
/*@jsdoc
|
|
||||||
* Sets all models currently attached to your avatar. For example, if you retrieve attachment data using
|
|
||||||
* {@link MyAvatar.getAttachmentsVariant} or {@link Avatar.getAttachmentsVariant}, make changes to it, and then want to
|
|
||||||
* update your avatar's attachments per the changed data.
|
|
||||||
* @function Avatar.setAttachmentsVariant
|
|
||||||
* @param {AttachmentData[]} variant - The attachment data defining the models to have attached to your avatar.
|
|
||||||
* @deprecated This function is deprecated and will be removed. Use avatar entities instead.
|
|
||||||
*/
|
|
||||||
// FIXME: Can this name be improved? Can it be deprecated?
|
|
||||||
Q_INVOKABLE virtual void setAttachmentsVariant(const QVariantList& variant);
|
|
||||||
|
|
||||||
virtual void storeAvatarEntityDataPayload(const QUuid& entityID, const QByteArray& payload);
|
virtual void storeAvatarEntityDataPayload(const QUuid& entityID, const QByteArray& payload);
|
||||||
|
|
||||||
/*@jsdoc
|
/*@jsdoc
|
||||||
|
@ -1209,7 +1184,6 @@ public:
|
||||||
const HeadData* getHeadData() const { return _headData; }
|
const HeadData* getHeadData() const { return _headData; }
|
||||||
|
|
||||||
struct Identity {
|
struct Identity {
|
||||||
QVector<AttachmentData> attachmentData;
|
|
||||||
QString displayName;
|
QString displayName;
|
||||||
QString sessionDisplayName;
|
QString sessionDisplayName;
|
||||||
bool isReplicated;
|
bool isReplicated;
|
||||||
|
@ -1254,109 +1228,6 @@ public:
|
||||||
}
|
}
|
||||||
virtual bool isCertifyFailed() const { return _verificationFailed; }
|
virtual bool isCertifyFailed() const { return _verificationFailed; }
|
||||||
|
|
||||||
/*@jsdoc
|
|
||||||
* Gets information about the models currently attached to your avatar.
|
|
||||||
* @function Avatar.getAttachmentData
|
|
||||||
* @returns {AttachmentData[]} Information about all models attached to your avatar.
|
|
||||||
* @deprecated This function is deprecated and will be removed. Use avatar entities instead.
|
|
||||||
* @example <caption>Report the URLs of all current attachments.</caption>
|
|
||||||
* var attachments = MyAvatar.getaAttachmentData();
|
|
||||||
* for (var i = 0; i < attachments.length; i++) {
|
|
||||||
* print(attachments[i].modelURL);
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* // Note: If using from the Avatar API, replace "MyAvatar" with "Avatar".
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE virtual QVector<AttachmentData> getAttachmentData() const;
|
|
||||||
|
|
||||||
/*@jsdoc
|
|
||||||
* Sets all models currently attached to your avatar. For example, if you retrieve attachment data using
|
|
||||||
* {@link MyAvatar.getAttachmentData} or {@link Avatar.getAttachmentData}, make changes to it, and then want to update your avatar's attachments per the
|
|
||||||
* changed data. You can also remove all attachments by using setting <code>attachmentData</code> to <code>null</code>.
|
|
||||||
* @function Avatar.setAttachmentData
|
|
||||||
* @param {AttachmentData[]} attachmentData - The attachment data defining the models to have attached to your avatar. Use
|
|
||||||
* <code>null</code> to remove all attachments.
|
|
||||||
* @deprecated This function is deprecated and will be removed. Use avatar entities instead.
|
|
||||||
* @example <caption>Remove a hat attachment if your avatar is wearing it.</caption>
|
|
||||||
* var hatURL = "https://apidocs.overte.org/examples/cowboy-hat.fbx";
|
|
||||||
* var attachments = MyAvatar.getAttachmentData();
|
|
||||||
*
|
|
||||||
* for (var i = 0; i < attachments.length; i++) {
|
|
||||||
* if (attachments[i].modelURL === hatURL) {
|
|
||||||
* attachments.splice(i, 1);
|
|
||||||
* MyAvatar.setAttachmentData(attachments);
|
|
||||||
* break;
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* // Note: If using from the Avatar API, replace all occurrences of "MyAvatar" with "Avatar".
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE virtual void setAttachmentData(const QVector<AttachmentData>& attachmentData);
|
|
||||||
|
|
||||||
/*@jsdoc
|
|
||||||
* Attaches a model to your avatar. For example, you can give your avatar a hat to wear, a guitar to hold, or a surfboard to
|
|
||||||
* stand on.
|
|
||||||
* @function Avatar.attach
|
|
||||||
* @param {string} modelURL - The URL of the glTF, FBX, or OBJ model to attach. glTF models may be in JSON or binary format
|
|
||||||
* (".gltf" or ".glb" URLs respectively).
|
|
||||||
* @param {string} [jointName=""] - The name of the avatar joint (see {@link MyAvatar.getJointNames} or
|
|
||||||
* {@link Avatar.getJointNames}) to attach the model to.
|
|
||||||
* @param {Vec3} [translation=Vec3.ZERO] - The offset to apply to the model relative to the joint position.
|
|
||||||
* @param {Quat} [rotation=Quat.IDENTITY] - The rotation to apply to the model relative to the joint orientation.
|
|
||||||
* @param {number} [scale=1.0] - The scale to apply to the model.
|
|
||||||
* @param {boolean} [isSoft=false] - If the model has a skeleton, set this to <code>true</code> so that the bones of the
|
|
||||||
* attached model's skeleton are rotated to fit the avatar's current pose. <code>isSoft</code> is used, for example,
|
|
||||||
* to have clothing that moves with the avatar.
|
|
||||||
* <p>If <code>true</code>, the <code>translation</code>, <code>rotation</code>, and <code>scale</code> parameters are
|
|
||||||
* ignored.</p>
|
|
||||||
* @param {boolean} [allowDuplicates=false] - If <code>true</code> then more than one copy of any particular model may be
|
|
||||||
* attached to the same joint; if <code>false</code> then the same model cannot be attached to the same joint.
|
|
||||||
* @param {boolean} [useSaved=true] - <em>Not used.</em>
|
|
||||||
* @deprecated This function is deprecated and will be removed. Use avatar entities instead.
|
|
||||||
* @example <caption>Attach a cowboy hat to your avatar's head.</caption>
|
|
||||||
* var attachment = {
|
|
||||||
* modelURL: "https://apidocs.overte.org/examples/cowboy-hat.fbx",
|
|
||||||
* jointName: "Head",
|
|
||||||
* translation: {"x": 0, "y": 0.25, "z": 0},
|
|
||||||
* rotation: {"x": 0, "y": 0, "z": 0, "w": 1},
|
|
||||||
* scale: 0.01,
|
|
||||||
* isSoft: false
|
|
||||||
* };
|
|
||||||
*
|
|
||||||
* MyAvatar.attach(attachment.modelURL,
|
|
||||||
* attachment.jointName,
|
|
||||||
* attachment.translation,
|
|
||||||
* attachment.rotation,
|
|
||||||
* attachment.scale,
|
|
||||||
* attachment.isSoft);
|
|
||||||
*
|
|
||||||
* // Note: If using from the Avatar API, replace "MyAvatar" with "Avatar".
|
|
||||||
*/
|
|
||||||
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 isSoft = false,
|
|
||||||
bool allowDuplicates = false, bool useSaved = true);
|
|
||||||
|
|
||||||
/*@jsdoc
|
|
||||||
* Detaches the most recently attached instance of a particular model from either a specific joint or any joint.
|
|
||||||
* @function Avatar.detachOne
|
|
||||||
* @param {string} modelURL - The URL of the model to detach.
|
|
||||||
* @param {string} [jointName=""] - The name of the joint to detach the model from. If <code>""</code>, then the most
|
|
||||||
* recently attached model is removed from which ever joint it was attached to.
|
|
||||||
* @deprecated This function is deprecated and will be removed. Use avatar entities instead.
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE virtual void detachOne(const QString& modelURL, const QString& jointName = QString());
|
|
||||||
|
|
||||||
/*@jsdoc
|
|
||||||
* Detaches all instances of a particular model from either a specific joint or all joints.
|
|
||||||
* @function Avatar.detachAll
|
|
||||||
* @param {string} modelURL - The URL of the model to detach.
|
|
||||||
* @param {string} [jointName=""] - The name of the joint to detach the model from. If <code>""</code>, then the model is
|
|
||||||
* detached from all joints.
|
|
||||||
* @deprecated This function is deprecated and will be removed. Use avatar entities instead.
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE virtual void detachAll(const QString& modelURL, const QString& jointName = QString());
|
|
||||||
|
|
||||||
QString getSkeletonModelURLFromScript() const;
|
QString getSkeletonModelURLFromScript() const;
|
||||||
void setSkeletonModelURLFromScript(const QString& skeletonModelString) { setSkeletonModelURL(QUrl(skeletonModelString)); }
|
void setSkeletonModelURLFromScript(const QString& skeletonModelString) { setSkeletonModelURL(QUrl(skeletonModelString)); }
|
||||||
|
|
||||||
|
@ -1732,8 +1603,6 @@ protected:
|
||||||
mutable HeadData* _headData { nullptr };
|
mutable HeadData* _headData { nullptr };
|
||||||
|
|
||||||
QUrl _skeletonModelURL;
|
QUrl _skeletonModelURL;
|
||||||
QVector<AttachmentData> _attachmentData;
|
|
||||||
QVector<AttachmentData> _oldAttachmentData;
|
|
||||||
QString _displayName;
|
QString _displayName;
|
||||||
QString _sessionDisplayName { };
|
QString _sessionDisplayName { };
|
||||||
bool _lookAtSnappingEnabled { true };
|
bool _lookAtSnappingEnabled { true };
|
||||||
|
@ -1899,66 +1768,6 @@ Q_DECLARE_METATYPE(AvatarData*)
|
||||||
QJsonValue toJsonValue(const JointData& joint);
|
QJsonValue toJsonValue(const JointData& joint);
|
||||||
JointData jointDataFromJsonValue(const QJsonValue& q);
|
JointData jointDataFromJsonValue(const QJsonValue& q);
|
||||||
|
|
||||||
class AttachmentData {
|
|
||||||
public:
|
|
||||||
QUrl modelURL;
|
|
||||||
QString jointName;
|
|
||||||
glm::vec3 translation;
|
|
||||||
glm::quat rotation;
|
|
||||||
float scale { 1.0f };
|
|
||||||
bool isSoft { false };
|
|
||||||
|
|
||||||
bool isValid() const { return modelURL.isValid(); }
|
|
||||||
|
|
||||||
bool operator==(const AttachmentData& other) const;
|
|
||||||
|
|
||||||
QJsonObject toJson() const;
|
|
||||||
void fromJson(const QJsonObject& json);
|
|
||||||
|
|
||||||
QVariant toVariant() const;
|
|
||||||
bool fromVariant(const QVariant& variant);
|
|
||||||
};
|
|
||||||
|
|
||||||
QDataStream& operator<<(QDataStream& out, const AttachmentData& attachment);
|
|
||||||
QDataStream& operator>>(QDataStream& in, AttachmentData& attachment);
|
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(AttachmentData)
|
|
||||||
Q_DECLARE_METATYPE(QVector<AttachmentData>)
|
|
||||||
|
|
||||||
/// Scriptable wrapper for attachments.
|
|
||||||
class AttachmentDataObject : public QObject, protected Scriptable {
|
|
||||||
Q_OBJECT
|
|
||||||
Q_PROPERTY(QString modelURL READ getModelURL WRITE setModelURL)
|
|
||||||
Q_PROPERTY(QString jointName READ getJointName WRITE setJointName)
|
|
||||||
Q_PROPERTY(glm::vec3 translation READ getTranslation WRITE setTranslation)
|
|
||||||
Q_PROPERTY(glm::quat rotation READ getRotation WRITE setRotation)
|
|
||||||
Q_PROPERTY(float scale READ getScale WRITE setScale)
|
|
||||||
Q_PROPERTY(bool isSoft READ getIsSoft WRITE setIsSoft)
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
Q_INVOKABLE void setModelURL(const QString& modelURL);
|
|
||||||
Q_INVOKABLE QString getModelURL() const;
|
|
||||||
|
|
||||||
Q_INVOKABLE void setJointName(const QString& jointName);
|
|
||||||
Q_INVOKABLE QString getJointName() const;
|
|
||||||
|
|
||||||
Q_INVOKABLE void setTranslation(const glm::vec3& translation);
|
|
||||||
Q_INVOKABLE glm::vec3 getTranslation() const;
|
|
||||||
|
|
||||||
Q_INVOKABLE void setRotation(const glm::quat& rotation);
|
|
||||||
Q_INVOKABLE glm::quat getRotation() const;
|
|
||||||
|
|
||||||
Q_INVOKABLE void setScale(float scale);
|
|
||||||
Q_INVOKABLE float getScale() const;
|
|
||||||
|
|
||||||
Q_INVOKABLE void setIsSoft(bool scale);
|
|
||||||
Q_INVOKABLE bool getIsSoft() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
void registerAvatarTypes(ScriptEngine* engine);
|
|
||||||
void registerAvatarPrototypes(ScriptEngine* engine);
|
|
||||||
|
|
||||||
class RayToAvatarIntersectionResult {
|
class RayToAvatarIntersectionResult {
|
||||||
public:
|
public:
|
||||||
bool intersects { false };
|
bool intersects { false };
|
||||||
|
|
|
@ -200,7 +200,7 @@ bool ScriptAvatarData::getLookAtSnappingEnabled() const {
|
||||||
//
|
//
|
||||||
|
|
||||||
//
|
//
|
||||||
// ATTACHMENT AND JOINT PROPERTIES
|
// JOINT PROPERTIES
|
||||||
// START
|
// START
|
||||||
//
|
//
|
||||||
QString ScriptAvatarData::getSkeletonModelURLFromScript() const {
|
QString ScriptAvatarData::getSkeletonModelURLFromScript() const {
|
||||||
|
@ -285,15 +285,8 @@ QStringList ScriptAvatarData::getJointNames() const {
|
||||||
return QStringList();
|
return QStringList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QVector<AttachmentData> ScriptAvatarData::getAttachmentData() const {
|
|
||||||
if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) {
|
|
||||||
return sharedAvatarData->getAttachmentData();
|
|
||||||
} else {
|
|
||||||
return QVector<AttachmentData>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//
|
//
|
||||||
// ATTACHMENT AND JOINT PROPERTIES
|
// JOINT PROPERTIES
|
||||||
// END
|
// END
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
|
@ -50,10 +50,9 @@ class ScriptAvatarData : public QObject {
|
||||||
Q_PROPERTY(bool lookAtSnappingEnabled READ getLookAtSnappingEnabled NOTIFY lookAtSnappingChanged)
|
Q_PROPERTY(bool lookAtSnappingEnabled READ getLookAtSnappingEnabled NOTIFY lookAtSnappingChanged)
|
||||||
|
|
||||||
//
|
//
|
||||||
// ATTACHMENT AND JOINT PROPERTIES
|
// JOINT PROPERTIES
|
||||||
//
|
//
|
||||||
Q_PROPERTY(QString skeletonModelURL READ getSkeletonModelURLFromScript NOTIFY skeletonModelURLChanged)
|
Q_PROPERTY(QString skeletonModelURL READ getSkeletonModelURLFromScript NOTIFY skeletonModelURLChanged)
|
||||||
Q_PROPERTY(QVector<AttachmentData> attachmentData READ getAttachmentData)
|
|
||||||
Q_PROPERTY(QStringList jointNames READ getJointNames)
|
Q_PROPERTY(QStringList jointNames READ getJointNames)
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -104,7 +103,7 @@ public:
|
||||||
bool getLookAtSnappingEnabled() const;
|
bool getLookAtSnappingEnabled() const;
|
||||||
|
|
||||||
//
|
//
|
||||||
// ATTACHMENT AND JOINT PROPERTIES
|
// JOINT PROPERTIES
|
||||||
//
|
//
|
||||||
QString getSkeletonModelURLFromScript() const;
|
QString getSkeletonModelURLFromScript() const;
|
||||||
|
|
||||||
|
@ -204,15 +203,6 @@ public:
|
||||||
*/
|
*/
|
||||||
Q_INVOKABLE QStringList getJointNames() const;
|
Q_INVOKABLE QStringList getJointNames() const;
|
||||||
|
|
||||||
/*@jsdoc
|
|
||||||
* Gets information about the models currently attached to the avatar.
|
|
||||||
* @function ScriptAvatar.getAttachmentData
|
|
||||||
* @returns {AttachmentData[]} Information about all models attached to the avatar, or <code>[]</code> if the avatar data
|
|
||||||
* aren't available.
|
|
||||||
* @deprecated This function is deprecated and will be removed. Use avatar entities instead.
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE QVector<AttachmentData> getAttachmentData() const;
|
|
||||||
|
|
||||||
#if DEV_BUILD || PR_BUILD
|
#if DEV_BUILD || PR_BUILD
|
||||||
Q_INVOKABLE AvatarEntityMap getAvatarEntities() const;
|
Q_INVOKABLE AvatarEntityMap getAvatarEntities() const;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -454,7 +454,6 @@ bool EntityRenderer::addToScene(const ScenePointer& scene, Transaction& transact
|
||||||
transaction.resetItem(_renderItemID, renderPayload);
|
transaction.resetItem(_renderItemID, renderPayload);
|
||||||
onAddToScene(_entity);
|
onAddToScene(_entity);
|
||||||
updateInScene(scene, transaction);
|
updateInScene(scene, transaction);
|
||||||
_entity->bumpAncestorChainRenderableVersion();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -462,7 +461,6 @@ void EntityRenderer::removeFromScene(const ScenePointer& scene, Transaction& tra
|
||||||
onRemoveFromScene(_entity);
|
onRemoveFromScene(_entity);
|
||||||
transaction.removeItem(_renderItemID);
|
transaction.removeItem(_renderItemID);
|
||||||
Item::clearID(_renderItemID);
|
Item::clearID(_renderItemID);
|
||||||
_entity->bumpAncestorChainRenderableVersion();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityRenderer::updateInScene(const ScenePointer& scene, Transaction& transaction) {
|
void EntityRenderer::updateInScene(const ScenePointer& scene, Transaction& transaction) {
|
||||||
|
|
|
@ -1261,7 +1261,6 @@ void ModelEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoint
|
||||||
if (!_hasModel) {
|
if (!_hasModel) {
|
||||||
if (model) {
|
if (model) {
|
||||||
model->removeFromScene(scene, transaction);
|
model->removeFromScene(scene, transaction);
|
||||||
entity->bumpAncestorChainRenderableVersion();
|
|
||||||
emit DependencyManager::get<scriptable::ModelProviderFactory>()->
|
emit DependencyManager::get<scriptable::ModelProviderFactory>()->
|
||||||
modelRemovedFromScene(entity->getEntityItemID(), NestableType::Entity, model);
|
modelRemovedFromScene(entity->getEntityItemID(), NestableType::Entity, model);
|
||||||
withWriteLock([&] { _model.reset(); });
|
withWriteLock([&] { _model.reset(); });
|
||||||
|
@ -1391,7 +1390,6 @@ void ModelEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoint
|
||||||
makeStatusGetters(entity, statusGetters);
|
makeStatusGetters(entity, statusGetters);
|
||||||
using namespace std::placeholders;
|
using namespace std::placeholders;
|
||||||
model->addToScene(scene, transaction, statusGetters, std::bind(&ModelEntityRenderer::metaBlendshapeOperator, _renderItemID, _1, _2, _3, _4));
|
model->addToScene(scene, transaction, statusGetters, std::bind(&ModelEntityRenderer::metaBlendshapeOperator, _renderItemID, _1, _2, _3, _4));
|
||||||
entity->bumpAncestorChainRenderableVersion();
|
|
||||||
processMaterials();
|
processMaterials();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2969,10 +2969,6 @@ void EntityItem::setVisible(bool value) {
|
||||||
_needsRenderUpdate |= changed;
|
_needsRenderUpdate |= changed;
|
||||||
_visible = value;
|
_visible = value;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (changed) {
|
|
||||||
bumpAncestorChainRenderableVersion();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EntityItem::isVisibleInSecondaryCamera() const {
|
bool EntityItem::isVisibleInSecondaryCamera() const {
|
||||||
|
|
|
@ -183,7 +183,6 @@ QString FSTReader::getNameFromType(ModelType modelType) {
|
||||||
_typesToNames[HEAD_MODEL] = "head";
|
_typesToNames[HEAD_MODEL] = "head";
|
||||||
_typesToNames[BODY_ONLY_MODEL] = "body";
|
_typesToNames[BODY_ONLY_MODEL] = "body";
|
||||||
_typesToNames[HEAD_AND_BODY_MODEL] = "body+head";
|
_typesToNames[HEAD_AND_BODY_MODEL] = "body+head";
|
||||||
_typesToNames[ATTACHMENT_MODEL] = "attachment";
|
|
||||||
}
|
}
|
||||||
return _typesToNames[modelType];
|
return _typesToNames[modelType];
|
||||||
}
|
}
|
||||||
|
@ -195,9 +194,6 @@ FSTReader::ModelType FSTReader::getTypeFromName(const QString& name) {
|
||||||
_namesToTypes["head"] = HEAD_MODEL ;
|
_namesToTypes["head"] = HEAD_MODEL ;
|
||||||
_namesToTypes["body"] = BODY_ONLY_MODEL;
|
_namesToTypes["body"] = BODY_ONLY_MODEL;
|
||||||
_namesToTypes["body+head"] = HEAD_AND_BODY_MODEL;
|
_namesToTypes["body+head"] = HEAD_AND_BODY_MODEL;
|
||||||
|
|
||||||
// NOTE: this is not yet implemented, but will be used to allow you to attach fully independent models to your avatar
|
|
||||||
_namesToTypes["attachment"] = ATTACHMENT_MODEL;
|
|
||||||
}
|
}
|
||||||
return _namesToTypes[name];
|
return _namesToTypes[name];
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,8 +42,7 @@ public:
|
||||||
ENTITY_MODEL,
|
ENTITY_MODEL,
|
||||||
HEAD_MODEL,
|
HEAD_MODEL,
|
||||||
BODY_ONLY_MODEL,
|
BODY_ONLY_MODEL,
|
||||||
HEAD_AND_BODY_MODEL,
|
HEAD_AND_BODY_MODEL
|
||||||
ATTACHMENT_MODEL
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Reads an FST mapping from the supplied data.
|
/// Reads an FST mapping from the supplied data.
|
||||||
|
|
|
@ -38,10 +38,10 @@ PacketVersion versionForPacketType(PacketType packetType) {
|
||||||
return static_cast<PacketVersion>(EntityQueryPacketVersion::ConicalFrustums);
|
return static_cast<PacketVersion>(EntityQueryPacketVersion::ConicalFrustums);
|
||||||
case PacketType::AvatarIdentity:
|
case PacketType::AvatarIdentity:
|
||||||
case PacketType::AvatarData:
|
case PacketType::AvatarData:
|
||||||
return static_cast<PacketVersion>(AvatarMixerPacketVersion::ARKitBlendshapes);
|
return static_cast<PacketVersion>(AvatarMixerPacketVersion::RemoveAttachments);
|
||||||
case PacketType::BulkAvatarData:
|
case PacketType::BulkAvatarData:
|
||||||
case PacketType::KillAvatar:
|
case PacketType::KillAvatar:
|
||||||
return static_cast<PacketVersion>(AvatarMixerPacketVersion::ARKitBlendshapes);
|
return static_cast<PacketVersion>(AvatarMixerPacketVersion::RemoveAttachments);
|
||||||
case PacketType::MessagesData:
|
case PacketType::MessagesData:
|
||||||
return static_cast<PacketVersion>(MessageDataVersion::TextOrBinaryData);
|
return static_cast<PacketVersion>(MessageDataVersion::TextOrBinaryData);
|
||||||
// ICE packets
|
// ICE packets
|
||||||
|
|
|
@ -363,7 +363,8 @@ enum class AvatarMixerPacketVersion : PacketVersion {
|
||||||
FBXJointOrderChange,
|
FBXJointOrderChange,
|
||||||
HandControllerSection,
|
HandControllerSection,
|
||||||
SendVerificationFailed,
|
SendVerificationFailed,
|
||||||
ARKitBlendshapes
|
ARKitBlendshapes,
|
||||||
|
RemoveAttachments,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class DomainConnectRequestVersion : PacketVersion {
|
enum class DomainConnectRequestVersion : PacketVersion {
|
||||||
|
|
|
@ -172,10 +172,6 @@ void RecordingScriptingInterface::setPlayerUseDisplayName(bool useDisplayName) {
|
||||||
_useDisplayName = useDisplayName;
|
_useDisplayName = useDisplayName;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RecordingScriptingInterface::setPlayerUseAttachments(bool useAttachments) {
|
|
||||||
_useAttachments = useAttachments;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RecordingScriptingInterface::setPlayerUseHeadModel(bool useHeadModel) {
|
void RecordingScriptingInterface::setPlayerUseHeadModel(bool useHeadModel) {
|
||||||
_useHeadModel = useHeadModel;
|
_useHeadModel = useHeadModel;
|
||||||
}
|
}
|
||||||
|
|
|
@ -162,14 +162,6 @@ public slots:
|
||||||
*/
|
*/
|
||||||
void setPlayerUseDisplayName(bool useDisplayName);
|
void setPlayerUseDisplayName(bool useDisplayName);
|
||||||
|
|
||||||
/*@jsdoc
|
|
||||||
* <p><em>Not used.</em></p>
|
|
||||||
* @function Recording.setPlayerUseAttachments
|
|
||||||
* @param {boolean} useAttachments - Use attachments.
|
|
||||||
* @deprecated This method is deprecated and will be removed.
|
|
||||||
*/
|
|
||||||
void setPlayerUseAttachments(bool useAttachments);
|
|
||||||
|
|
||||||
/*@jsdoc
|
/*@jsdoc
|
||||||
* <p><em>Not used.</em></p>
|
* <p><em>Not used.</em></p>
|
||||||
* @function Recording.setPlayerUseHeadModel
|
* @function Recording.setPlayerUseHeadModel
|
||||||
|
@ -203,14 +195,6 @@ public slots:
|
||||||
*/
|
*/
|
||||||
bool getPlayerUseDisplayName() { return _useDisplayName; }
|
bool getPlayerUseDisplayName() { return _useDisplayName; }
|
||||||
|
|
||||||
/*@jsdoc
|
|
||||||
* <p><em>Not used.</em></p>
|
|
||||||
* @function Recording.getPlayerUseAttachments
|
|
||||||
* @returns {boolean} Use attachments.
|
|
||||||
* @deprecated This method is deprecated and will be removed.
|
|
||||||
*/
|
|
||||||
bool getPlayerUseAttachments() { return _useAttachments; }
|
|
||||||
|
|
||||||
/*@jsdoc
|
/*@jsdoc
|
||||||
* <p><em>Not used.</em></p>
|
* <p><em>Not used.</em></p>
|
||||||
* @function Recording.getPlayerUseHeadModel
|
* @function Recording.getPlayerUseHeadModel
|
||||||
|
@ -365,7 +349,6 @@ protected:
|
||||||
Flag _playFromCurrentLocation { true };
|
Flag _playFromCurrentLocation { true };
|
||||||
Flag _useDisplayName { false };
|
Flag _useDisplayName { false };
|
||||||
Flag _useHeadModel { false };
|
Flag _useHeadModel { false };
|
||||||
Flag _useAttachments { false };
|
|
||||||
Flag _useSkeletonModel { false };
|
Flag _useSkeletonModel { false };
|
||||||
recording::ClipPointer _lastClip;
|
recording::ClipPointer _lastClip;
|
||||||
|
|
||||||
|
|
|
@ -1,73 +0,0 @@
|
||||||
//
|
|
||||||
// Created by Anthony J. Thibault on 12/17/15.
|
|
||||||
// Copyright 2013 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 "SoftAttachmentModel.h"
|
|
||||||
|
|
||||||
SoftAttachmentModel::SoftAttachmentModel(QObject* parent, const Rig& rigOverride) :
|
|
||||||
CauterizedModel(parent),
|
|
||||||
_rigOverride(rigOverride) {
|
|
||||||
}
|
|
||||||
|
|
||||||
SoftAttachmentModel::~SoftAttachmentModel() {
|
|
||||||
}
|
|
||||||
|
|
||||||
// virtual
|
|
||||||
void SoftAttachmentModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
|
||||||
_needsUpdateClusterMatrices = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int SoftAttachmentModel::getJointIndexOverride(int i) const {
|
|
||||||
QString name = _rig.nameOfJoint(i);
|
|
||||||
if (name.isEmpty()) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return _rigOverride.indexOfJoint(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
// virtual
|
|
||||||
// use the _rigOverride matrices instead of the Model::_rig
|
|
||||||
void SoftAttachmentModel::updateClusterMatrices() {
|
|
||||||
if (!_needsUpdateClusterMatrices) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!isLoaded()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_needsUpdateClusterMatrices = false;
|
|
||||||
|
|
||||||
const HFMModel& hfmModel = getHFMModel();
|
|
||||||
|
|
||||||
for (int i = 0; i < (int) _meshStates.size(); i++) {
|
|
||||||
MeshState& state = _meshStates[i];
|
|
||||||
const HFMMesh& mesh = hfmModel.meshes.at(i);
|
|
||||||
int meshIndex = i;
|
|
||||||
for (int j = 0; j < mesh.clusters.size(); j++) {
|
|
||||||
const HFMCluster& cluster = mesh.clusters.at(j);
|
|
||||||
|
|
||||||
int clusterIndex = j;
|
|
||||||
// TODO: cache these look-ups as an optimization
|
|
||||||
int jointIndexOverride = getJointIndexOverride(cluster.jointIndex);
|
|
||||||
glm::mat4 jointMatrix;
|
|
||||||
if (jointIndexOverride >= 0 && jointIndexOverride < _rigOverride.getJointStateCount()) {
|
|
||||||
jointMatrix = _rigOverride.getJointTransform(jointIndexOverride);
|
|
||||||
} else {
|
|
||||||
jointMatrix = _rig.getJointTransform(cluster.jointIndex);
|
|
||||||
}
|
|
||||||
if (_useDualQuaternionSkinning) {
|
|
||||||
glm::mat4 m;
|
|
||||||
glm_mat4u_mul(jointMatrix, _rig.getAnimSkeleton()->getClusterBindMatricesOriginalValues(meshIndex, clusterIndex).inverseBindMatrix, m);
|
|
||||||
state.clusterDualQuaternions[j] = Model::TransformDualQuaternion(m);
|
|
||||||
} else {
|
|
||||||
glm_mat4u_mul(jointMatrix, _rig.getAnimSkeleton()->getClusterBindMatricesOriginalValues(meshIndex, clusterIndex).inverseBindMatrix, state.clusterMatrices[j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
updateBlendshapes();
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
//
|
|
||||||
// Created by Anthony J. Thibault on 12/17/15.
|
|
||||||
// Copyright 2015 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_SoftAttachmentModel_h
|
|
||||||
#define hifi_SoftAttachmentModel_h
|
|
||||||
|
|
||||||
#include "CauterizedModel.h"
|
|
||||||
|
|
||||||
// A model that allows the creator to specify a secondary rig instance.
|
|
||||||
// When the cluster matrices are created for rendering, the
|
|
||||||
// cluster matrices will use the secondary rig for the joint poses
|
|
||||||
// instead of the primary rig.
|
|
||||||
//
|
|
||||||
// This is used by Avatar instances to wear clothing that follows the same
|
|
||||||
// animated pose as the SkeletonModel.
|
|
||||||
|
|
||||||
class SoftAttachmentModel : public CauterizedModel {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
SoftAttachmentModel(QObject* parent, const Rig& rigOverride);
|
|
||||||
~SoftAttachmentModel();
|
|
||||||
|
|
||||||
void updateRig(float deltaTime, glm::mat4 parentTransform) override;
|
|
||||||
void updateClusterMatrices() override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
int getJointIndexOverride(int i) const;
|
|
||||||
|
|
||||||
const Rig& _rigOverride;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // hifi_SoftAttachmentModel_h
|
|
|
@ -69,7 +69,6 @@ const QUuid SpatiallyNestable::getParentID() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpatiallyNestable::setParentID(const QUuid& parentID) {
|
void SpatiallyNestable::setParentID(const QUuid& parentID) {
|
||||||
bumpAncestorChainRenderableVersion();
|
|
||||||
bool success = false;
|
bool success = false;
|
||||||
auto parent = getParentPointer(success);
|
auto parent = getParentPointer(success);
|
||||||
bool parentChanged = false;
|
bool parentChanged = false;
|
||||||
|
@ -89,7 +88,6 @@ void SpatiallyNestable::setParentID(const QUuid& parentID) {
|
||||||
success = false;
|
success = false;
|
||||||
parent = getParentPointer(success);
|
parent = getParentPointer(success);
|
||||||
if (success && parent) {
|
if (success && parent) {
|
||||||
bumpAncestorChainRenderableVersion();
|
|
||||||
parent->updateQueryAACube();
|
parent->updateQueryAACube();
|
||||||
parent->recalculateChildCauterization();
|
parent->recalculateChildCauterization();
|
||||||
}
|
}
|
||||||
|
@ -1509,17 +1507,3 @@ QUuid SpatiallyNestable::getEditSenderID() {
|
||||||
});
|
});
|
||||||
return editSenderID;
|
return editSenderID;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpatiallyNestable::bumpAncestorChainRenderableVersion(int depth) const {
|
|
||||||
if (depth > MAX_PARENTING_CHAIN_SIZE) {
|
|
||||||
// can't break the parent chain here, because it will call setParentID, which calls this
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_ancestorChainRenderableVersion++;
|
|
||||||
bool success = false;
|
|
||||||
auto parent = getParentPointer(success);
|
|
||||||
if (success && parent) {
|
|
||||||
parent->bumpAncestorChainRenderableVersion(depth + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -224,8 +224,6 @@ public:
|
||||||
bool hasGrabs();
|
bool hasGrabs();
|
||||||
virtual QUuid getEditSenderID();
|
virtual QUuid getEditSenderID();
|
||||||
|
|
||||||
void bumpAncestorChainRenderableVersion(int depth = 0) const;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QUuid _id;
|
QUuid _id;
|
||||||
mutable SpatiallyNestableWeakPointer _parent;
|
mutable SpatiallyNestableWeakPointer _parent;
|
||||||
|
@ -248,8 +246,6 @@ protected:
|
||||||
mutable ReadWriteLockable _grabsLock;
|
mutable ReadWriteLockable _grabsLock;
|
||||||
QSet<GrabPointer> _grabs; // upon this thing
|
QSet<GrabPointer> _grabs; // upon this thing
|
||||||
|
|
||||||
mutable std::atomic<uint32_t> _ancestorChainRenderableVersion { 0 };
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SpatiallyNestable() = delete;
|
SpatiallyNestable() = delete;
|
||||||
const NestableType _nestableType; // EntityItem or an AvatarData
|
const NestableType _nestableType; // EntityItem or an AvatarData
|
||||||
|
|
Loading…
Reference in a new issue