From 165c3214a75df8e9496023d92086672bd9deedf9 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Tue, 24 Apr 2018 18:43:53 -0700 Subject: [PATCH 1/7] Avatar Scripts --- interface/src/Application.cpp | 29 +++++++++++++++++++ interface/src/avatar/MyAvatar.cpp | 13 +++++++++ interface/src/avatar/MyAvatar.h | 9 +++++- libraries/fbx/src/FBX.h | 1 + libraries/fbx/src/FSTReader.h | 1 + .../src/model-networking/ModelCache.cpp | 15 ++++++++++ 6 files changed, 67 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6d4c82d4bf..c1f77c792a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4724,6 +4724,35 @@ void Application::init() { avatar->setCollisionSound(sound); } }, Qt::QueuedConnection); + + connect(getMyAvatar().get(), &MyAvatar::avatarScriptsNeedToLoad, this, [this]() { + if (auto avatar = getMyAvatar()) { + auto scripts = avatar->getSkeletonModel()->getFBXGeometry().scripts; + if (scripts.size() > 0) { + auto scriptEngines = DependencyManager::get(); + auto runningScripts = scriptEngines->getRunningScripts(); + for (auto script : scripts) { + int index = runningScripts.indexOf(script.toString()); + if (index < 0) { + auto loaded = scriptEngines->loadScript(script); + avatar->addScriptToUnload(script); + } + } + } + } + }, Qt::QueuedConnection); + + connect(getMyAvatar().get(), &MyAvatar::avatarScriptsNeedToUnload, this, [this]() { + if (auto avatar = getMyAvatar()) { + auto scripts = avatar->getScriptsToUnload(); + if (scripts.size() > 0) { + auto scriptEngines = DependencyManager::get(); + for (auto script : scripts) { + scriptEngines->stopScript(script.toString(), false); + } + } + } + }, Qt::QueuedConnection); } void Application::updateLOD(float deltaTime) const { diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 249a765d92..2ba4a6afca 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -121,6 +121,7 @@ MyAvatar::MyAvatar(QThread* thread) : _skeletonModel = std::make_shared(this, nullptr); connect(_skeletonModel.get(), &Model::setURLFinished, this, &Avatar::setModelURLFinished); + connect(_skeletonModel.get(), &Model::setURLFinished, this, &MyAvatar::setModelURLLoaded); connect(_skeletonModel.get(), &Model::rigReady, this, &Avatar::rigReady); connect(_skeletonModel.get(), &Model::rigReset, this, &Avatar::rigReset); @@ -1463,6 +1464,9 @@ void MyAvatar::clearJointsData() { } void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { + if (_scriptsToUnload.size() > 0) { + emit avatarScriptsNeedToUnload(); + } _skeletonModelChangeCount++; int skeletonModelChangeCount = _skeletonModelChangeCount; Avatar::setSkeletonModelURL(skeletonModelURL); @@ -2384,6 +2388,11 @@ void MyAvatar::restrictScaleFromDomainSettings(const QJsonObject& domainSettings settings.endGroup(); } +void MyAvatar::setModelURLLoaded() { + _scriptsToUnload.clear(); + emit avatarScriptsNeedToLoad(); +} + void MyAvatar::leaveDomain() { clearScaleRestriction(); saveAvatarScale(); @@ -2831,6 +2840,10 @@ float MyAvatar::getWalkSpeed() const { return _walkSpeed.get() * _walkSpeedScalar; } +void MyAvatar::addScriptToUnload(QUrl& scriptUrl) { + _scriptsToUnload.push_back(scriptUrl); +} + void MyAvatar::setSprintMode(bool sprint) { _walkSpeedScalar = sprint ? AVATAR_SPRINT_SPEED_SCALAR : AVATAR_WALK_SPEED_SCALAR; } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 6f82c7dfb9..38e189f92b 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -594,6 +594,9 @@ public: void setWalkSpeed(float value); float getWalkSpeed() const; + void addScriptToUnload(QUrl& scriptUrl); + const QVector& getScriptsToUnload() const { return _scriptsToUnload; }; + public slots: void increaseSize(); void decreaseSize(); @@ -659,10 +662,12 @@ signals: void sensorToWorldScaleChanged(float sensorToWorldScale); void attachmentsChanged(); void scaleChanged(); + void avatarScriptsNeedToLoad(); + void avatarScriptsNeedToUnload(); private slots: void leaveDomain(); - + void setModelURLLoaded(); protected: virtual void beParentOfChild(SpatiallyNestablePointer newChild) const override; @@ -905,6 +910,8 @@ private: // max unscaled forward movement speed ThreadSafeValueCache _walkSpeed { DEFAULT_AVATAR_MAX_WALKING_SPEED }; float _walkSpeedScalar { AVATAR_WALK_SPEED_SCALAR }; + + QVector _scriptsToUnload; }; QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode); diff --git a/libraries/fbx/src/FBX.h b/libraries/fbx/src/FBX.h index a609d85fc8..d40511ce27 100644 --- a/libraries/fbx/src/FBX.h +++ b/libraries/fbx/src/FBX.h @@ -298,6 +298,7 @@ public: bool hasSkeletonJoints; QVector meshes; + QVector scripts; QHash materials; diff --git a/libraries/fbx/src/FSTReader.h b/libraries/fbx/src/FSTReader.h index 981bae4feb..d1204c0876 100644 --- a/libraries/fbx/src/FSTReader.h +++ b/libraries/fbx/src/FSTReader.h @@ -28,6 +28,7 @@ static const QString TRANSLATION_Z_FIELD = "tz"; static const QString JOINT_FIELD = "joint"; static const QString FREE_JOINT_FIELD = "freeJoint"; static const QString BLENDSHAPE_FIELD = "bs"; +static const QString SCRIPT_FIELD = "script"; class FSTReader { public: diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index f17cdbb7e8..5a25bbc6fd 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -66,6 +66,7 @@ void GeometryMappingResource::downloadFinished(const QByteArray& data) { auto mapping = FSTReader::readMapping(data); QString filename = mapping.value("filename").toString(); + if (filename.isNull()) { qCDebug(modelnetworking) << "Mapping file" << _url << "has no \"filename\" field"; finishedLoading(false); @@ -209,6 +210,20 @@ void GeometryReader::run() { throw QString("unsupported format"); } + if (_mapping.value("type").toString() == "body+head") { + auto scripts = _mapping.value("script"); + if (!scripts.isNull()) { + auto scriptsMap = scripts.toMap(); + auto count = scriptsMap.size(); + if (count > 0) { + for (auto &key : scriptsMap.keys()) { + auto scriptUrl = scriptsMap[key].toString(); + fbxGeometry->scripts.push_back(QUrl(scriptUrl)); + } + } + } + } + // Ensure the resource has not been deleted auto resource = _resource.toStrongRef(); if (!resource) { From e0770f06b1eb27fcc5a8bd8db34ffb145bf0b3c5 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Wed, 25 Apr 2018 19:35:26 -0700 Subject: [PATCH 2/7] Add scripts to Model Packager --- interface/src/Application.cpp | 48 +++++++++---------- interface/src/Application.h | 3 ++ interface/src/ModelPackager.cpp | 30 ++++++++++-- interface/src/ModelPackager.h | 2 + interface/src/ModelPropertiesDialog.cpp | 19 ++++++++ interface/src/ModelPropertiesDialog.h | 2 + interface/src/avatar/MyAvatar.cpp | 20 ++++---- interface/src/avatar/MyAvatar.h | 9 ++-- libraries/fbx/src/FBX.h | 2 +- libraries/fbx/src/FSTReader.cpp | 4 +- .../src/model-networking/ModelCache.cpp | 23 +++++---- 11 files changed, 105 insertions(+), 57 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c1f77c792a..ad4cb56703 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2285,7 +2285,11 @@ void Application::onAboutToQuit() { // Hide Running Scripts dialog so that it gets destroyed in an orderly manner; prevents warnings at shutdown. DependencyManager::get()->hide("RunningScripts"); - + if (auto avatar = getMyAvatar()) { + auto urls = avatar->getScriptsToUnload(); + unloadAvatarScripts(urls); + } + _aboutToQuit = true; cleanupBeforeQuit(); @@ -4724,35 +4728,31 @@ void Application::init() { avatar->setCollisionSound(sound); } }, Qt::QueuedConnection); +} - connect(getMyAvatar().get(), &MyAvatar::avatarScriptsNeedToLoad, this, [this]() { - if (auto avatar = getMyAvatar()) { - auto scripts = avatar->getSkeletonModel()->getFBXGeometry().scripts; - if (scripts.size() > 0) { - auto scriptEngines = DependencyManager::get(); - auto runningScripts = scriptEngines->getRunningScripts(); - for (auto script : scripts) { - int index = runningScripts.indexOf(script.toString()); - if (index < 0) { - auto loaded = scriptEngines->loadScript(script); - avatar->addScriptToUnload(script); - } +void Application::loadAvatarScripts(const QVector& urls) { + if (auto avatar = getMyAvatar()) { + if (urls.size() > 0) { + auto scriptEngines = DependencyManager::get(); + auto runningScripts = scriptEngines->getRunningScripts(); + for (auto url : urls) { + int index = runningScripts.indexOf(url); + if (index < 0) { + scriptEngines->loadScript(url); + avatar->addScriptToUnload(url); } } } - }, Qt::QueuedConnection); + } +} - connect(getMyAvatar().get(), &MyAvatar::avatarScriptsNeedToUnload, this, [this]() { - if (auto avatar = getMyAvatar()) { - auto scripts = avatar->getScriptsToUnload(); - if (scripts.size() > 0) { - auto scriptEngines = DependencyManager::get(); - for (auto script : scripts) { - scriptEngines->stopScript(script.toString(), false); - } - } +void Application::unloadAvatarScripts(const QVector& urls) { + if (urls.size() > 0) { + auto scriptEngines = DependencyManager::get(); + for (auto url : urls) { + scriptEngines->stopScript(url, false); } - }, Qt::QueuedConnection); + } } void Application::updateLOD(float deltaTime) const { diff --git a/interface/src/Application.h b/interface/src/Application.h index 74b0e5a110..2e91f842a4 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -290,6 +290,9 @@ public: void replaceDomainContent(const QString& url); + void loadAvatarScripts(const QVector& urls); + void unloadAvatarScripts(const QVector& urls); + signals: void svoImportRequested(const QString& url); diff --git a/interface/src/ModelPackager.cpp b/interface/src/ModelPackager.cpp index 5f4c7526e0..a87669bf47 100644 --- a/interface/src/ModelPackager.cpp +++ b/interface/src/ModelPackager.cpp @@ -156,9 +156,11 @@ bool ModelPackager::zipModel() { QByteArray nameField = _mapping.value(NAME_FIELD).toByteArray(); tempDir.mkpath(nameField + "/textures"); + tempDir.mkpath(nameField + "/scripts"); QDir fbxDir(tempDir.path() + "/" + nameField); QDir texDir(fbxDir.path() + "/textures"); - + QDir scriptDir(fbxDir.path() + "/scripts"); + // Copy textures listTextures(); if (!_textures.empty()) { @@ -166,6 +168,22 @@ bool ModelPackager::zipModel() { _texDir = _modelFile.path() + "/" + texdirField; copyTextures(_texDir, texDir); } + + // Copy scripts + QByteArray scriptField = _mapping.value(SCRIPT_FIELD).toByteArray(); + _mapping.remove(SCRIPT_FIELD); + if (scriptField.size() > 1) { + tempDir.mkpath(nameField + "/scripts"); + _scriptDir = _modelFile.path() + "/" + scriptField; + QDir wdir = QDir(_scriptDir); + _mapping.remove(SCRIPT_FIELD); + auto list = wdir.entryList(QDir::NoDotAndDotDot | QDir::AllEntries); + for (auto script : list) { + auto sc = tempDir.relativeFilePath(scriptDir.path()) + "/" + QUrl(script).fileName(); + _mapping.insertMulti(SCRIPT_FIELD, sc); + } + copyDirectoryContent(wdir, scriptDir); + } // Copy LODs QVariantHash lodField = _mapping.value(LOD_FIELD).toHash(); @@ -189,7 +207,11 @@ bool ModelPackager::zipModel() { // Correct FST _mapping[FILENAME_FIELD] = tempDir.relativeFilePath(newPath); _mapping[TEXDIR_FIELD] = tempDir.relativeFilePath(texDir.path()); - + + for (auto multi : _mapping.values(SCRIPT_FIELD)) { + + multi.fromValue(tempDir.relativeFilePath(scriptDir.path()) + multi.toString()); + } // Copy FST QFile fst(tempDir.path() + "/" + nameField + ".fst"); if (fst.open(QIODevice::WriteOnly)) { @@ -237,7 +259,9 @@ void ModelPackager::populateBasicMapping(QVariantHash& mapping, QString filename if (!mapping.contains(TEXDIR_FIELD)) { mapping.insert(TEXDIR_FIELD, "."); } - + if (!mapping.contains(SCRIPT_FIELD)) { + mapping.insert(SCRIPT_FIELD, "."); + } // mixamo/autodesk defaults if (!mapping.contains(SCALE_FIELD)) { mapping.insert(SCALE_FIELD, 1.0); diff --git a/interface/src/ModelPackager.h b/interface/src/ModelPackager.h index 10942833f9..60b3825c4d 100644 --- a/interface/src/ModelPackager.h +++ b/interface/src/ModelPackager.h @@ -37,10 +37,12 @@ private: QFileInfo _fbxInfo; FSTReader::ModelType _modelType; QString _texDir; + QString _scriptDir; QVariantHash _mapping; std::unique_ptr _geometry; QStringList _textures; + QStringList _scripts; }; diff --git a/interface/src/ModelPropertiesDialog.cpp b/interface/src/ModelPropertiesDialog.cpp index ae352974ae..35b07aa2b2 100644 --- a/interface/src/ModelPropertiesDialog.cpp +++ b/interface/src/ModelPropertiesDialog.cpp @@ -43,6 +43,9 @@ _geometry(geometry) form->addRow("Texture Directory:", _textureDirectory = new QPushButton()); connect(_textureDirectory, SIGNAL(clicked(bool)), SLOT(chooseTextureDirectory())); + form->addRow("Script Directory:", _scriptDirectory = new QPushButton()); + connect(_scriptDirectory, SIGNAL(clicked(bool)), SLOT(chooseScriptDirectory())); + form->addRow("Scale:", _scale = new QDoubleSpinBox()); _scale->setMaximum(FLT_MAX); _scale->setSingleStep(0.01); @@ -100,6 +103,7 @@ QVariantHash ModelPropertiesDialog::getMapping() const { mapping.insert(TYPE_FIELD, getType()); mapping.insert(NAME_FIELD, _name->text()); mapping.insert(TEXDIR_FIELD, _textureDirectory->text()); + mapping.insert(SCRIPT_FIELD, _scriptDirectory->text()); mapping.insert(SCALE_FIELD, QString::number(_scale->value())); // update the joint indices @@ -157,6 +161,7 @@ void ModelPropertiesDialog::reset() { _name->setText(_originalMapping.value(NAME_FIELD).toString()); _textureDirectory->setText(_originalMapping.value(TEXDIR_FIELD).toString()); _scale->setValue(_originalMapping.value(SCALE_FIELD).toDouble()); + _scriptDirectory->setText(_originalMapping.value(SCRIPT_FIELD).toString()); QVariantHash jointHash = _originalMapping.value(JOINT_FIELD).toHash(); @@ -207,6 +212,20 @@ void ModelPropertiesDialog::chooseTextureDirectory() { _textureDirectory->setText(directory.length() == _basePath.length() ? "." : directory.mid(_basePath.length() + 1)); } +void ModelPropertiesDialog::chooseScriptDirectory() { + QString directory = QFileDialog::getExistingDirectory(this, "Choose Script Directory", + _basePath + "/" + _scriptDirectory->text()); + if (directory.isEmpty()) { + return; + } + if (!directory.startsWith(_basePath)) { + OffscreenUi::asyncWarning(NULL, "Invalid script directory", "Script directory must be child of base path."); + return; + } + _scriptDirectory->setText(directory.length() == _basePath.length() ? "." : directory.mid(_basePath.length() + 1)); +} + + void ModelPropertiesDialog::updatePivotJoint() { _pivotJoint->setEnabled(!_pivotAboutCenter->isChecked()); } diff --git a/interface/src/ModelPropertiesDialog.h b/interface/src/ModelPropertiesDialog.h index 11abc5ab54..e3c2d8ed6a 100644 --- a/interface/src/ModelPropertiesDialog.h +++ b/interface/src/ModelPropertiesDialog.h @@ -37,6 +37,7 @@ public: private slots: void reset(); void chooseTextureDirectory(); + void chooseScriptDirectory(); void updatePivotJoint(); void createNewFreeJoint(const QString& joint = QString()); @@ -52,6 +53,7 @@ private: FBXGeometry _geometry; QLineEdit* _name = nullptr; QPushButton* _textureDirectory = nullptr; + QPushButton* _scriptDirectory = nullptr; QDoubleSpinBox* _scale = nullptr; QDoubleSpinBox* _translationX = nullptr; QDoubleSpinBox* _translationY = nullptr; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 2ba4a6afca..69acf26477 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -121,7 +121,12 @@ MyAvatar::MyAvatar(QThread* thread) : _skeletonModel = std::make_shared(this, nullptr); connect(_skeletonModel.get(), &Model::setURLFinished, this, &Avatar::setModelURLFinished); - connect(_skeletonModel.get(), &Model::setURLFinished, this, &MyAvatar::setModelURLLoaded); + connect(_skeletonModel.get(), &Model::setURLFinished, this, [this](bool success) { + if (success) { + auto geometry = getSkeletonModel()->getFBXGeometry(); + qApp->loadAvatarScripts(geometry.scripts); + } + }); connect(_skeletonModel.get(), &Model::rigReady, this, &Avatar::rigReady); connect(_skeletonModel.get(), &Model::rigReset, this, &Avatar::rigReset); @@ -1464,9 +1469,7 @@ void MyAvatar::clearJointsData() { } void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { - if (_scriptsToUnload.size() > 0) { - emit avatarScriptsNeedToUnload(); - } + qApp->unloadAvatarScripts(_scriptsToUnload); _skeletonModelChangeCount++; int skeletonModelChangeCount = _skeletonModelChangeCount; Avatar::setSkeletonModelURL(skeletonModelURL); @@ -2388,11 +2391,6 @@ void MyAvatar::restrictScaleFromDomainSettings(const QJsonObject& domainSettings settings.endGroup(); } -void MyAvatar::setModelURLLoaded() { - _scriptsToUnload.clear(); - emit avatarScriptsNeedToLoad(); -} - void MyAvatar::leaveDomain() { clearScaleRestriction(); saveAvatarScale(); @@ -2840,8 +2838,8 @@ float MyAvatar::getWalkSpeed() const { return _walkSpeed.get() * _walkSpeedScalar; } -void MyAvatar::addScriptToUnload(QUrl& scriptUrl) { - _scriptsToUnload.push_back(scriptUrl); +void MyAvatar::addScriptToUnload(QString& url) { + _scriptsToUnload.push_back(url); } void MyAvatar::setSprintMode(bool sprint) { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 38e189f92b..6e67defe6f 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -594,8 +594,8 @@ public: void setWalkSpeed(float value); float getWalkSpeed() const; - void addScriptToUnload(QUrl& scriptUrl); - const QVector& getScriptsToUnload() const { return _scriptsToUnload; }; + void addScriptToUnload(QString& url); + const QVector& getScriptsToUnload() const { return _scriptsToUnload; }; public slots: void increaseSize(); @@ -662,12 +662,9 @@ signals: void sensorToWorldScaleChanged(float sensorToWorldScale); void attachmentsChanged(); void scaleChanged(); - void avatarScriptsNeedToLoad(); - void avatarScriptsNeedToUnload(); private slots: void leaveDomain(); - void setModelURLLoaded(); protected: virtual void beParentOfChild(SpatiallyNestablePointer newChild) const override; @@ -911,7 +908,7 @@ private: ThreadSafeValueCache _walkSpeed { DEFAULT_AVATAR_MAX_WALKING_SPEED }; float _walkSpeedScalar { AVATAR_WALK_SPEED_SCALAR }; - QVector _scriptsToUnload; + QVector _scriptsToUnload; }; QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode); diff --git a/libraries/fbx/src/FBX.h b/libraries/fbx/src/FBX.h index d40511ce27..ce3fc52c3a 100644 --- a/libraries/fbx/src/FBX.h +++ b/libraries/fbx/src/FBX.h @@ -298,7 +298,7 @@ public: bool hasSkeletonJoints; QVector meshes; - QVector scripts; + QVector scripts; QHash materials; diff --git a/libraries/fbx/src/FSTReader.cpp b/libraries/fbx/src/FSTReader.cpp index cc4a919445..603f214c3e 100644 --- a/libraries/fbx/src/FSTReader.cpp +++ b/libraries/fbx/src/FSTReader.cpp @@ -84,7 +84,7 @@ void FSTReader::writeVariant(QBuffer& buffer, QVariantHash::const_iterator& it) QByteArray FSTReader::writeMapping(const QVariantHash& mapping) { static const QStringList PREFERED_ORDER = QStringList() << NAME_FIELD << TYPE_FIELD << SCALE_FIELD << FILENAME_FIELD - << TEXDIR_FIELD << JOINT_FIELD << FREE_JOINT_FIELD + << TEXDIR_FIELD << SCRIPT_FIELD << JOINT_FIELD << FREE_JOINT_FIELD << BLENDSHAPE_FIELD << JOINT_INDEX_FIELD; QBuffer buffer; buffer.open(QIODevice::WriteOnly); @@ -92,7 +92,7 @@ QByteArray FSTReader::writeMapping(const QVariantHash& mapping) { for (auto key : PREFERED_ORDER) { auto it = mapping.find(key); if (it != mapping.constEnd()) { - if (key == FREE_JOINT_FIELD) { // writeVariant does not handle strings added using insertMulti. + if (key == FREE_JOINT_FIELD || key == SCRIPT_FIELD) { // writeVariant does not handle strings added using insertMulti. for (auto multi : mapping.values(key)) { buffer.write(key.toUtf8()); buffer.write(" = "); diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index 5a25bbc6fd..e3f543c403 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -210,16 +210,19 @@ void GeometryReader::run() { throw QString("unsupported format"); } - if (_mapping.value("type").toString() == "body+head") { - auto scripts = _mapping.value("script"); - if (!scripts.isNull()) { - auto scriptsMap = scripts.toMap(); - auto count = scriptsMap.size(); - if (count > 0) { - for (auto &key : scriptsMap.keys()) { - auto scriptUrl = scriptsMap[key].toString(); - fbxGeometry->scripts.push_back(QUrl(scriptUrl)); - } + // Store fst scripts on geometry + if (!_mapping.value(SCRIPT_FIELD).isNull()) { + QVariantList scripts = _mapping.values(SCRIPT_FIELD); + if (scripts.size() > 0) { + for (auto &script : scripts) { + QString scriptUrl = script.toString(); + if (QUrl(scriptUrl).isRelative()) { + if (scriptUrl.at(0) == '/') { + scriptUrl = scriptUrl.right(scriptUrl.length() - 1); + } + scriptUrl = _url.resolved(QUrl(scriptUrl)).toString(); + } + fbxGeometry->scripts.push_back(scriptUrl); } } } From 12f578c93c825feabf420b9f8548b597ad7b69d0 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Wed, 25 Apr 2018 19:46:31 -0700 Subject: [PATCH 3/7] More fixes --- interface/src/Application.cpp | 18 ++++++++---------- interface/src/avatar/MyAvatar.cpp | 2 +- interface/src/avatar/MyAvatar.h | 2 +- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ad4cb56703..c38bb9295a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4731,16 +4731,14 @@ void Application::init() { } void Application::loadAvatarScripts(const QVector& urls) { - if (auto avatar = getMyAvatar()) { - if (urls.size() > 0) { - auto scriptEngines = DependencyManager::get(); - auto runningScripts = scriptEngines->getRunningScripts(); - for (auto url : urls) { - int index = runningScripts.indexOf(url); - if (index < 0) { - scriptEngines->loadScript(url); - avatar->addScriptToUnload(url); - } + if (urls.size() > 0) { + auto scriptEngines = DependencyManager::get(); + auto runningScripts = scriptEngines->getRunningScripts(); + for (auto url : urls) { + int index = runningScripts.indexOf(url); + if (index < 0) { + scriptEngines->loadScript(url); + getMyAvatar()->addScriptToUnload(url); } } } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 69acf26477..462dbebbbb 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2838,7 +2838,7 @@ float MyAvatar::getWalkSpeed() const { return _walkSpeed.get() * _walkSpeedScalar; } -void MyAvatar::addScriptToUnload(QString& url) { +void MyAvatar::addScriptToUnload(const QString& url) { _scriptsToUnload.push_back(url); } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 6e67defe6f..00cb50e079 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -594,7 +594,7 @@ public: void setWalkSpeed(float value); float getWalkSpeed() const; - void addScriptToUnload(QString& url); + void addScriptToUnload(const QString& url); const QVector& getScriptsToUnload() const { return _scriptsToUnload; }; public slots: From 2de982a5a2751d27989cef07630d94cb62daa2c1 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Mon, 30 Apr 2018 12:04:35 -0700 Subject: [PATCH 4/7] Added script types and better script reload --- interface/src/Application.cpp | 23 +++++++++++-------- interface/src/Application.h | 2 +- interface/src/ModelPackager.cpp | 1 + interface/src/avatar/MyAvatar.cpp | 6 +---- interface/src/avatar/MyAvatar.h | 5 ---- libraries/fbx/src/FSTReader.cpp | 22 ++++++++++++++++++ libraries/fbx/src/FSTReader.h | 2 ++ .../src/model-networking/ModelCache.cpp | 19 +++++++-------- libraries/script-engine/src/ScriptEngine.cpp | 14 +++++++++++ libraries/script-engine/src/ScriptEngine.h | 12 ++++++++++ libraries/script-engine/src/ScriptEngines.cpp | 6 +++-- libraries/script-engine/src/ScriptEngines.h | 2 +- 12 files changed, 81 insertions(+), 33 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c38bb9295a..833224510b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1231,6 +1231,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo connect(scriptEngines, &ScriptEngines::scriptsReloading, scriptEngines, [this] { getEntities()->reloadEntityScripts(); + loadAvatarScripts(getMyAvatar()->getSkeletonModel()->getFBXGeometry().scripts); }, Qt::QueuedConnection); connect(scriptEngines, &ScriptEngines::scriptLoadError, @@ -2285,10 +2286,6 @@ void Application::onAboutToQuit() { // Hide Running Scripts dialog so that it gets destroyed in an orderly manner; prevents warnings at shutdown. DependencyManager::get()->hide("RunningScripts"); - if (auto avatar = getMyAvatar()) { - auto urls = avatar->getScriptsToUnload(); - unloadAvatarScripts(urls); - } _aboutToQuit = true; @@ -4737,18 +4734,24 @@ void Application::loadAvatarScripts(const QVector& urls) { for (auto url : urls) { int index = runningScripts.indexOf(url); if (index < 0) { - scriptEngines->loadScript(url); - getMyAvatar()->addScriptToUnload(url); + auto scriptEnginePointer = scriptEngines->loadScript(url, false); + if (scriptEnginePointer) { + scriptEnginePointer->setType(ScriptEngine::Type::AVATAR); + } } } } } -void Application::unloadAvatarScripts(const QVector& urls) { - if (urls.size() > 0) { - auto scriptEngines = DependencyManager::get(); +void Application::unloadAvatarScripts() { + auto scriptEngines = DependencyManager::get(); + auto urls = scriptEngines->getRunningScripts(); + if (urls.size() > 0) { for (auto url : urls) { - scriptEngines->stopScript(url, false); + auto scriptEngine = scriptEngines->getScriptEngine(url); + if (scriptEngine->getType() == ScriptEngine::Type::AVATAR) { + scriptEngines->stopScript(url, false); + } } } } diff --git a/interface/src/Application.h b/interface/src/Application.h index 2e91f842a4..28c85ec855 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -291,7 +291,7 @@ public: void replaceDomainContent(const QString& url); void loadAvatarScripts(const QVector& urls); - void unloadAvatarScripts(const QVector& urls); + void unloadAvatarScripts(); signals: void svoImportRequested(const QString& url); diff --git a/interface/src/ModelPackager.cpp b/interface/src/ModelPackager.cpp index a87669bf47..72b99ce5a3 100644 --- a/interface/src/ModelPackager.cpp +++ b/interface/src/ModelPackager.cpp @@ -177,6 +177,7 @@ bool ModelPackager::zipModel() { _scriptDir = _modelFile.path() + "/" + scriptField; QDir wdir = QDir(_scriptDir); _mapping.remove(SCRIPT_FIELD); + wdir.setSorting(QDir::Name | QDir::Reversed); auto list = wdir.entryList(QDir::NoDotAndDotDot | QDir::AllEntries); for (auto script : list) { auto sc = tempDir.relativeFilePath(scriptDir.path()) + "/" + QUrl(script).fileName(); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 462dbebbbb..99fdea0449 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -123,6 +123,7 @@ MyAvatar::MyAvatar(QThread* thread) : connect(_skeletonModel.get(), &Model::setURLFinished, this, &Avatar::setModelURLFinished); connect(_skeletonModel.get(), &Model::setURLFinished, this, [this](bool success) { if (success) { + qApp->unloadAvatarScripts(); auto geometry = getSkeletonModel()->getFBXGeometry(); qApp->loadAvatarScripts(geometry.scripts); } @@ -1469,7 +1470,6 @@ void MyAvatar::clearJointsData() { } void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { - qApp->unloadAvatarScripts(_scriptsToUnload); _skeletonModelChangeCount++; int skeletonModelChangeCount = _skeletonModelChangeCount; Avatar::setSkeletonModelURL(skeletonModelURL); @@ -2838,10 +2838,6 @@ float MyAvatar::getWalkSpeed() const { return _walkSpeed.get() * _walkSpeedScalar; } -void MyAvatar::addScriptToUnload(const QString& url) { - _scriptsToUnload.push_back(url); -} - void MyAvatar::setSprintMode(bool sprint) { _walkSpeedScalar = sprint ? AVATAR_SPRINT_SPEED_SCALAR : AVATAR_WALK_SPEED_SCALAR; } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 00cb50e079..a927a1d0ba 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -594,9 +594,6 @@ public: void setWalkSpeed(float value); float getWalkSpeed() const; - void addScriptToUnload(const QString& url); - const QVector& getScriptsToUnload() const { return _scriptsToUnload; }; - public slots: void increaseSize(); void decreaseSize(); @@ -907,8 +904,6 @@ private: // max unscaled forward movement speed ThreadSafeValueCache _walkSpeed { DEFAULT_AVATAR_MAX_WALKING_SPEED }; float _walkSpeedScalar { AVATAR_WALK_SPEED_SCALAR }; - - QVector _scriptsToUnload; }; QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode); diff --git a/libraries/fbx/src/FSTReader.cpp b/libraries/fbx/src/FSTReader.cpp index 603f214c3e..fcbfca1e7d 100644 --- a/libraries/fbx/src/FSTReader.cpp +++ b/libraries/fbx/src/FSTReader.cpp @@ -187,6 +187,28 @@ FSTReader::ModelType FSTReader::predictModelType(const QVariantHash& mapping) { return ENTITY_MODEL; } +QVector FSTReader::getScripts(const QUrl& url, const QVariantHash& mapping) { + + auto fstMapping = mapping.isEmpty() ? downloadMapping(url.toString()) : mapping; + QVector scriptPaths; + if (!fstMapping.value(SCRIPT_FIELD).isNull()) { + auto scripts = fstMapping.values(SCRIPT_FIELD).toVector(); + if (scripts.size() > 0) { + for (auto &script : scripts) { + QString scriptPath = script.toString(); + if (QUrl(scriptPath).isRelative()) { + if (scriptPath.at(0) == '/') { + scriptPath = scriptPath.right(scriptPath.length() - 1); + } + scriptPath = url.resolved(QUrl(scriptPath)).toString(); + } + scriptPaths.push_back(scriptPath); + } + } + } + return scriptPaths; +} + QVariantHash FSTReader::downloadMapping(const QString& url) { QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); QNetworkRequest networkRequest = QNetworkRequest(url); diff --git a/libraries/fbx/src/FSTReader.h b/libraries/fbx/src/FSTReader.h index d1204c0876..4a8574f0cf 100644 --- a/libraries/fbx/src/FSTReader.h +++ b/libraries/fbx/src/FSTReader.h @@ -50,6 +50,8 @@ public: /// Predicts the type of model by examining the mapping static ModelType predictModelType(const QVariantHash& mapping); + static QVector getScripts(const QUrl& fstUrl, const QVariantHash& mapping = QVariantHash()); + static QString getNameFromType(ModelType modelType); static FSTReader::ModelType getTypeFromName(const QString& name); static QVariantHash downloadMapping(const QString& url); diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index e3f543c403..e1086bc0c9 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -83,6 +83,14 @@ void GeometryMappingResource::downloadFinished(const QByteArray& data) { _textureBaseUrl = url.resolved(QUrl(".")); } + auto scripts = FSTReader::getScripts(_url, mapping); + if (scripts.size() > 0) { + mapping.remove(SCRIPT_FIELD); + for (auto &scriptPath : scripts) { + mapping.insertMulti(SCRIPT_FIELD, scriptPath); + } + } + auto animGraphVariant = mapping.value("animGraphUrl"); if (animGraphVariant.isValid()) { QUrl fstUrl(animGraphVariant.toString()); @@ -210,19 +218,12 @@ void GeometryReader::run() { throw QString("unsupported format"); } - // Store fst scripts on geometry + // Add scripts to fbxgeometry if (!_mapping.value(SCRIPT_FIELD).isNull()) { QVariantList scripts = _mapping.values(SCRIPT_FIELD); if (scripts.size() > 0) { for (auto &script : scripts) { - QString scriptUrl = script.toString(); - if (QUrl(scriptUrl).isRelative()) { - if (scriptUrl.at(0) == '/') { - scriptUrl = scriptUrl.right(scriptUrl.length() - 1); - } - scriptUrl = _url.resolved(QUrl(scriptUrl)).toString(); - } - fbxGeometry->scripts.push_back(scriptUrl); + fbxGeometry->scripts.push_back(script.toString()); } } } diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index c79ffffec7..d4912fbd3d 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -180,6 +180,20 @@ ScriptEngine::ScriptEngine(Context context, const QString& scriptContents, const // don't delete `ScriptEngines` until all `ScriptEngine`s are gone _scriptEngines(DependencyManager::get()) { + switch (_context) { + case Context::CLIENT_SCRIPT: + _type = Type::CLIENT; + break; + case Context::ENTITY_CLIENT_SCRIPT: + _type = Type::ENTITY_CLIENT; + break; + case Context::ENTITY_SERVER_SCRIPT: + _type = Type::ENTITY_SERVER; + break; + case Context::AGENT_SCRIPT: + _type = Type::AGENT; + } + connect(this, &QScriptEngine::signalHandlerException, this, [this](const QScriptValue& exception) { if (hasUncaughtException()) { // the engine's uncaughtException() seems to produce much better stack traces here diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 7f69eee990..cf2606330f 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -99,6 +99,14 @@ public: AGENT_SCRIPT }; + enum Type { + CLIENT, + ENTITY_CLIENT, + ENTITY_SERVER, + AGENT, + AVATAR + }; + static int processLevelMaxRetries; ScriptEngine(Context context, const QString& scriptContents = NO_SCRIPT, const QString& fileNameString = QString("about:ScriptEngine")); ~ScriptEngine(); @@ -209,6 +217,9 @@ public: Q_INVOKABLE QUuid generateUUID() { return QUuid::createUuid(); } + void setType(Type type) { _type = type; }; + Type getType() { return _type; }; + bool isFinished() const { return _isFinished; } // used by Application and ScriptWidget bool isRunning() const { return _isRunning; } // used by ScriptWidget @@ -293,6 +304,7 @@ protected: void callWithEnvironment(const EntityItemID& entityID, const QUrl& sandboxURL, QScriptValue function, QScriptValue thisObject, QScriptValueList args); Context _context; + Type _type; QString _scriptContents; QString _parentURL; std::atomic _isFinished { false }; diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp index 871705d74b..59d431fabb 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -427,11 +427,13 @@ bool ScriptEngines::stopScript(const QString& rawScriptURL, bool restart) { if (_scriptEnginesHash.contains(scriptURL)) { ScriptEnginePointer scriptEngine = _scriptEnginesHash[scriptURL]; if (restart) { + bool isUserLoaded = scriptEngine->isUserLoaded(); + ScriptEngine::Type type = scriptEngine->getType(); auto scriptCache = DependencyManager::get(); scriptCache->deleteScript(scriptURL); connect(scriptEngine.data(), &ScriptEngine::finished, - this, [this](QString scriptName, ScriptEnginePointer engine) { - reloadScript(scriptName); + this, [this, isUserLoaded, type](QString scriptName, ScriptEnginePointer engine) { + reloadScript(scriptName, isUserLoaded)->setType(type); }); } scriptEngine->stop(); diff --git a/libraries/script-engine/src/ScriptEngines.h b/libraries/script-engine/src/ScriptEngines.h index ea07ebe840..63b18c73ea 100644 --- a/libraries/script-engine/src/ScriptEngines.h +++ b/libraries/script-engine/src/ScriptEngines.h @@ -110,7 +110,7 @@ protected slots: protected: friend class ScriptEngine; - void reloadScript(const QString& scriptName) { loadScript(scriptName, true, false, false, true); } + ScriptEnginePointer reloadScript(const QString& scriptName, bool isUserLoaded = true) { return loadScript(scriptName, isUserLoaded, false, false, true); } void removeScriptEngine(ScriptEnginePointer); void onScriptEngineLoaded(const QString& scriptFilename); void onScriptEngineError(const QString& scriptFilename); From 50ca09b3b421d44fa9a27177f8b7291b94a1572a Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Mon, 30 Apr 2018 16:26:04 -0700 Subject: [PATCH 5/7] minor fixes --- interface/src/Application.cpp | 2 +- libraries/script-engine/src/ScriptEngine.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 833224510b..ec40ffc653 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2286,7 +2286,7 @@ void Application::onAboutToQuit() { // Hide Running Scripts dialog so that it gets destroyed in an orderly manner; prevents warnings at shutdown. DependencyManager::get()->hide("RunningScripts"); - + _aboutToQuit = true; cleanupBeforeQuit(); diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index d4912fbd3d..255a4832a9 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -192,6 +192,7 @@ ScriptEngine::ScriptEngine(Context context, const QString& scriptContents, const break; case Context::AGENT_SCRIPT: _type = Type::AGENT; + break; } connect(this, &QScriptEngine::signalHandlerException, this, [this](const QScriptValue& exception) { From 2ac7fcadd2c02f89b0655631d1ee3b9c4660bad5 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Tue, 1 May 2018 09:37:01 -0700 Subject: [PATCH 6/7] load scripts once on rigReady --- interface/src/avatar/MyAvatar.cpp | 6 ++++++ interface/src/avatar/MyAvatar.h | 3 +++ 2 files changed, 9 insertions(+) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 99fdea0449..85b2ece077 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -124,8 +124,14 @@ MyAvatar::MyAvatar(QThread* thread) : connect(_skeletonModel.get(), &Model::setURLFinished, this, [this](bool success) { if (success) { qApp->unloadAvatarScripts(); + _shouldLoadScripts = true; + } + }); + connect(_skeletonModel.get(), &Model::rigReady, this, [this]() { + if (_shouldLoadScripts) { auto geometry = getSkeletonModel()->getFBXGeometry(); qApp->loadAvatarScripts(geometry.scripts); + _shouldLoadScripts = false; } }); connect(_skeletonModel.get(), &Model::rigReady, this, &Avatar::rigReady); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index a927a1d0ba..2bcbd878a9 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -904,6 +904,9 @@ private: // max unscaled forward movement speed ThreadSafeValueCache _walkSpeed { DEFAULT_AVATAR_MAX_WALKING_SPEED }; float _walkSpeedScalar { AVATAR_WALK_SPEED_SCALAR }; + + // load avatar scripts once when rig is ready + bool _shouldLoadScripts { false }; }; QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode); From 689fbd2da07aeb30f698e06b4b7d166367aac8fe Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Wed, 2 May 2018 11:09:17 -0700 Subject: [PATCH 7/7] added requested changes --- interface/src/Application.cpp | 30 ++++++++----------- interface/src/ModelPackager.cpp | 1 - interface/src/avatar/MyAvatar.cpp | 5 ++++ interface/src/avatar/MyAvatar.h | 2 ++ libraries/fbx/src/FSTReader.cpp | 16 +++++----- .../src/model-networking/ModelCache.cpp | 6 ++-- 6 files changed, 29 insertions(+), 31 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ec40ffc653..b384e1086e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1231,7 +1231,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo connect(scriptEngines, &ScriptEngines::scriptsReloading, scriptEngines, [this] { getEntities()->reloadEntityScripts(); - loadAvatarScripts(getMyAvatar()->getSkeletonModel()->getFBXGeometry().scripts); + loadAvatarScripts(getMyAvatar()->getScriptUrls()); }, Qt::QueuedConnection); connect(scriptEngines, &ScriptEngines::scriptLoadError, @@ -4728,16 +4728,14 @@ void Application::init() { } void Application::loadAvatarScripts(const QVector& urls) { - if (urls.size() > 0) { - auto scriptEngines = DependencyManager::get(); - auto runningScripts = scriptEngines->getRunningScripts(); - for (auto url : urls) { - int index = runningScripts.indexOf(url); - if (index < 0) { - auto scriptEnginePointer = scriptEngines->loadScript(url, false); - if (scriptEnginePointer) { - scriptEnginePointer->setType(ScriptEngine::Type::AVATAR); - } + auto scriptEngines = DependencyManager::get(); + auto runningScripts = scriptEngines->getRunningScripts(); + for (auto url : urls) { + int index = runningScripts.indexOf(url); + if (index < 0) { + auto scriptEnginePointer = scriptEngines->loadScript(url, false); + if (scriptEnginePointer) { + scriptEnginePointer->setType(ScriptEngine::Type::AVATAR); } } } @@ -4746,12 +4744,10 @@ void Application::loadAvatarScripts(const QVector& urls) { void Application::unloadAvatarScripts() { auto scriptEngines = DependencyManager::get(); auto urls = scriptEngines->getRunningScripts(); - if (urls.size() > 0) { - for (auto url : urls) { - auto scriptEngine = scriptEngines->getScriptEngine(url); - if (scriptEngine->getType() == ScriptEngine::Type::AVATAR) { - scriptEngines->stopScript(url, false); - } + for (auto url : urls) { + auto scriptEngine = scriptEngines->getScriptEngine(url); + if (scriptEngine->getType() == ScriptEngine::Type::AVATAR) { + scriptEngines->stopScript(url, false); } } } diff --git a/interface/src/ModelPackager.cpp b/interface/src/ModelPackager.cpp index 72b99ce5a3..0e34eebc80 100644 --- a/interface/src/ModelPackager.cpp +++ b/interface/src/ModelPackager.cpp @@ -210,7 +210,6 @@ bool ModelPackager::zipModel() { _mapping[TEXDIR_FIELD] = tempDir.relativeFilePath(texDir.path()); for (auto multi : _mapping.values(SCRIPT_FIELD)) { - multi.fromValue(tempDir.relativeFilePath(scriptDir.path()) + multi.toString()); } // Copy FST diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 85b2ece077..5ce056e9b7 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2852,6 +2852,11 @@ void MyAvatar::setWalkSpeed(float value) { _walkSpeed.set(value); } +QVector MyAvatar::getScriptUrls() { + QVector scripts = _skeletonModel->isLoaded() ? _skeletonModel->getFBXGeometry().scripts : QVector(); + return scripts; +} + glm::vec3 MyAvatar::getPositionForAudio() { glm::vec3 result; switch (_audioListenerMode) { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 2bcbd878a9..d605e1cc44 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -594,6 +594,8 @@ public: void setWalkSpeed(float value); float getWalkSpeed() const; + QVector getScriptUrls(); + public slots: void increaseSize(); void decreaseSize(); diff --git a/libraries/fbx/src/FSTReader.cpp b/libraries/fbx/src/FSTReader.cpp index fcbfca1e7d..d63a5b3cc4 100644 --- a/libraries/fbx/src/FSTReader.cpp +++ b/libraries/fbx/src/FSTReader.cpp @@ -193,17 +193,15 @@ QVector FSTReader::getScripts(const QUrl& url, const QVariantHash& mapp QVector scriptPaths; if (!fstMapping.value(SCRIPT_FIELD).isNull()) { auto scripts = fstMapping.values(SCRIPT_FIELD).toVector(); - if (scripts.size() > 0) { - for (auto &script : scripts) { - QString scriptPath = script.toString(); - if (QUrl(scriptPath).isRelative()) { - if (scriptPath.at(0) == '/') { - scriptPath = scriptPath.right(scriptPath.length() - 1); - } - scriptPath = url.resolved(QUrl(scriptPath)).toString(); + for (auto &script : scripts) { + QString scriptPath = script.toString(); + if (QUrl(scriptPath).isRelative()) { + if (scriptPath.at(0) == '/') { + scriptPath = scriptPath.right(scriptPath.length() - 1); } - scriptPaths.push_back(scriptPath); + scriptPath = url.resolved(QUrl(scriptPath)).toString(); } + scriptPaths.push_back(scriptPath); } } return scriptPaths; diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index e1086bc0c9..416920d43f 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -221,10 +221,8 @@ void GeometryReader::run() { // Add scripts to fbxgeometry if (!_mapping.value(SCRIPT_FIELD).isNull()) { QVariantList scripts = _mapping.values(SCRIPT_FIELD); - if (scripts.size() > 0) { - for (auto &script : scripts) { - fbxGeometry->scripts.push_back(script.toString()); - } + for (auto &script : scripts) { + fbxGeometry->scripts.push_back(script.toString()); } }