Add scripts to Model Packager

This commit is contained in:
luiscuenca 2018-04-25 19:35:26 -07:00
parent 165c3214a7
commit e0770f06b1
11 changed files with 105 additions and 57 deletions

View file

@ -2285,7 +2285,11 @@ void Application::onAboutToQuit() {
// Hide Running Scripts dialog so that it gets destroyed in an orderly manner; prevents warnings at shutdown. // Hide Running Scripts dialog so that it gets destroyed in an orderly manner; prevents warnings at shutdown.
DependencyManager::get<OffscreenUi>()->hide("RunningScripts"); DependencyManager::get<OffscreenUi>()->hide("RunningScripts");
if (auto avatar = getMyAvatar()) {
auto urls = avatar->getScriptsToUnload();
unloadAvatarScripts(urls);
}
_aboutToQuit = true; _aboutToQuit = true;
cleanupBeforeQuit(); cleanupBeforeQuit();
@ -4724,35 +4728,31 @@ void Application::init() {
avatar->setCollisionSound(sound); avatar->setCollisionSound(sound);
} }
}, Qt::QueuedConnection); }, Qt::QueuedConnection);
}
connect(getMyAvatar().get(), &MyAvatar::avatarScriptsNeedToLoad, this, [this]() { void Application::loadAvatarScripts(const QVector<QString>& urls) {
if (auto avatar = getMyAvatar()) { if (auto avatar = getMyAvatar()) {
auto scripts = avatar->getSkeletonModel()->getFBXGeometry().scripts; if (urls.size() > 0) {
if (scripts.size() > 0) { auto scriptEngines = DependencyManager::get<ScriptEngines>();
auto scriptEngines = DependencyManager::get<ScriptEngines>(); auto runningScripts = scriptEngines->getRunningScripts();
auto runningScripts = scriptEngines->getRunningScripts(); for (auto url : urls) {
for (auto script : scripts) { int index = runningScripts.indexOf(url);
int index = runningScripts.indexOf(script.toString()); if (index < 0) {
if (index < 0) { scriptEngines->loadScript(url);
auto loaded = scriptEngines->loadScript(script); avatar->addScriptToUnload(url);
avatar->addScriptToUnload(script);
}
} }
} }
} }
}, Qt::QueuedConnection); }
}
connect(getMyAvatar().get(), &MyAvatar::avatarScriptsNeedToUnload, this, [this]() { void Application::unloadAvatarScripts(const QVector<QString>& urls) {
if (auto avatar = getMyAvatar()) { if (urls.size() > 0) {
auto scripts = avatar->getScriptsToUnload(); auto scriptEngines = DependencyManager::get<ScriptEngines>();
if (scripts.size() > 0) { for (auto url : urls) {
auto scriptEngines = DependencyManager::get<ScriptEngines>(); scriptEngines->stopScript(url, false);
for (auto script : scripts) {
scriptEngines->stopScript(script.toString(), false);
}
}
} }
}, Qt::QueuedConnection); }
} }
void Application::updateLOD(float deltaTime) const { void Application::updateLOD(float deltaTime) const {

View file

@ -290,6 +290,9 @@ public:
void replaceDomainContent(const QString& url); void replaceDomainContent(const QString& url);
void loadAvatarScripts(const QVector<QString>& urls);
void unloadAvatarScripts(const QVector<QString>& urls);
signals: signals:
void svoImportRequested(const QString& url); void svoImportRequested(const QString& url);

View file

@ -156,9 +156,11 @@ bool ModelPackager::zipModel() {
QByteArray nameField = _mapping.value(NAME_FIELD).toByteArray(); QByteArray nameField = _mapping.value(NAME_FIELD).toByteArray();
tempDir.mkpath(nameField + "/textures"); tempDir.mkpath(nameField + "/textures");
tempDir.mkpath(nameField + "/scripts");
QDir fbxDir(tempDir.path() + "/" + nameField); QDir fbxDir(tempDir.path() + "/" + nameField);
QDir texDir(fbxDir.path() + "/textures"); QDir texDir(fbxDir.path() + "/textures");
QDir scriptDir(fbxDir.path() + "/scripts");
// Copy textures // Copy textures
listTextures(); listTextures();
if (!_textures.empty()) { if (!_textures.empty()) {
@ -166,6 +168,22 @@ bool ModelPackager::zipModel() {
_texDir = _modelFile.path() + "/" + texdirField; _texDir = _modelFile.path() + "/" + texdirField;
copyTextures(_texDir, texDir); 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 // Copy LODs
QVariantHash lodField = _mapping.value(LOD_FIELD).toHash(); QVariantHash lodField = _mapping.value(LOD_FIELD).toHash();
@ -189,7 +207,11 @@ bool ModelPackager::zipModel() {
// Correct FST // Correct FST
_mapping[FILENAME_FIELD] = tempDir.relativeFilePath(newPath); _mapping[FILENAME_FIELD] = tempDir.relativeFilePath(newPath);
_mapping[TEXDIR_FIELD] = tempDir.relativeFilePath(texDir.path()); _mapping[TEXDIR_FIELD] = tempDir.relativeFilePath(texDir.path());
for (auto multi : _mapping.values(SCRIPT_FIELD)) {
multi.fromValue(tempDir.relativeFilePath(scriptDir.path()) + multi.toString());
}
// Copy FST // Copy FST
QFile fst(tempDir.path() + "/" + nameField + ".fst"); QFile fst(tempDir.path() + "/" + nameField + ".fst");
if (fst.open(QIODevice::WriteOnly)) { if (fst.open(QIODevice::WriteOnly)) {
@ -237,7 +259,9 @@ void ModelPackager::populateBasicMapping(QVariantHash& mapping, QString filename
if (!mapping.contains(TEXDIR_FIELD)) { if (!mapping.contains(TEXDIR_FIELD)) {
mapping.insert(TEXDIR_FIELD, "."); mapping.insert(TEXDIR_FIELD, ".");
} }
if (!mapping.contains(SCRIPT_FIELD)) {
mapping.insert(SCRIPT_FIELD, ".");
}
// mixamo/autodesk defaults // mixamo/autodesk defaults
if (!mapping.contains(SCALE_FIELD)) { if (!mapping.contains(SCALE_FIELD)) {
mapping.insert(SCALE_FIELD, 1.0); mapping.insert(SCALE_FIELD, 1.0);

View file

@ -37,10 +37,12 @@ private:
QFileInfo _fbxInfo; QFileInfo _fbxInfo;
FSTReader::ModelType _modelType; FSTReader::ModelType _modelType;
QString _texDir; QString _texDir;
QString _scriptDir;
QVariantHash _mapping; QVariantHash _mapping;
std::unique_ptr<FBXGeometry> _geometry; std::unique_ptr<FBXGeometry> _geometry;
QStringList _textures; QStringList _textures;
QStringList _scripts;
}; };

View file

@ -43,6 +43,9 @@ _geometry(geometry)
form->addRow("Texture Directory:", _textureDirectory = new QPushButton()); form->addRow("Texture Directory:", _textureDirectory = new QPushButton());
connect(_textureDirectory, SIGNAL(clicked(bool)), SLOT(chooseTextureDirectory())); 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()); form->addRow("Scale:", _scale = new QDoubleSpinBox());
_scale->setMaximum(FLT_MAX); _scale->setMaximum(FLT_MAX);
_scale->setSingleStep(0.01); _scale->setSingleStep(0.01);
@ -100,6 +103,7 @@ QVariantHash ModelPropertiesDialog::getMapping() const {
mapping.insert(TYPE_FIELD, getType()); mapping.insert(TYPE_FIELD, getType());
mapping.insert(NAME_FIELD, _name->text()); mapping.insert(NAME_FIELD, _name->text());
mapping.insert(TEXDIR_FIELD, _textureDirectory->text()); mapping.insert(TEXDIR_FIELD, _textureDirectory->text());
mapping.insert(SCRIPT_FIELD, _scriptDirectory->text());
mapping.insert(SCALE_FIELD, QString::number(_scale->value())); mapping.insert(SCALE_FIELD, QString::number(_scale->value()));
// update the joint indices // update the joint indices
@ -157,6 +161,7 @@ void ModelPropertiesDialog::reset() {
_name->setText(_originalMapping.value(NAME_FIELD).toString()); _name->setText(_originalMapping.value(NAME_FIELD).toString());
_textureDirectory->setText(_originalMapping.value(TEXDIR_FIELD).toString()); _textureDirectory->setText(_originalMapping.value(TEXDIR_FIELD).toString());
_scale->setValue(_originalMapping.value(SCALE_FIELD).toDouble()); _scale->setValue(_originalMapping.value(SCALE_FIELD).toDouble());
_scriptDirectory->setText(_originalMapping.value(SCRIPT_FIELD).toString());
QVariantHash jointHash = _originalMapping.value(JOINT_FIELD).toHash(); 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)); _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() { void ModelPropertiesDialog::updatePivotJoint() {
_pivotJoint->setEnabled(!_pivotAboutCenter->isChecked()); _pivotJoint->setEnabled(!_pivotAboutCenter->isChecked());
} }

View file

@ -37,6 +37,7 @@ public:
private slots: private slots:
void reset(); void reset();
void chooseTextureDirectory(); void chooseTextureDirectory();
void chooseScriptDirectory();
void updatePivotJoint(); void updatePivotJoint();
void createNewFreeJoint(const QString& joint = QString()); void createNewFreeJoint(const QString& joint = QString());
@ -52,6 +53,7 @@ private:
FBXGeometry _geometry; FBXGeometry _geometry;
QLineEdit* _name = nullptr; QLineEdit* _name = nullptr;
QPushButton* _textureDirectory = nullptr; QPushButton* _textureDirectory = nullptr;
QPushButton* _scriptDirectory = nullptr;
QDoubleSpinBox* _scale = nullptr; QDoubleSpinBox* _scale = nullptr;
QDoubleSpinBox* _translationX = nullptr; QDoubleSpinBox* _translationX = nullptr;
QDoubleSpinBox* _translationY = nullptr; QDoubleSpinBox* _translationY = nullptr;

View file

@ -121,7 +121,12 @@ MyAvatar::MyAvatar(QThread* thread) :
_skeletonModel = std::make_shared<MySkeletonModel>(this, nullptr); _skeletonModel = std::make_shared<MySkeletonModel>(this, nullptr);
connect(_skeletonModel.get(), &Model::setURLFinished, this, &Avatar::setModelURLFinished); 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::rigReady, this, &Avatar::rigReady);
connect(_skeletonModel.get(), &Model::rigReset, this, &Avatar::rigReset); connect(_skeletonModel.get(), &Model::rigReset, this, &Avatar::rigReset);
@ -1464,9 +1469,7 @@ void MyAvatar::clearJointsData() {
} }
void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
if (_scriptsToUnload.size() > 0) { qApp->unloadAvatarScripts(_scriptsToUnload);
emit avatarScriptsNeedToUnload();
}
_skeletonModelChangeCount++; _skeletonModelChangeCount++;
int skeletonModelChangeCount = _skeletonModelChangeCount; int skeletonModelChangeCount = _skeletonModelChangeCount;
Avatar::setSkeletonModelURL(skeletonModelURL); Avatar::setSkeletonModelURL(skeletonModelURL);
@ -2388,11 +2391,6 @@ void MyAvatar::restrictScaleFromDomainSettings(const QJsonObject& domainSettings
settings.endGroup(); settings.endGroup();
} }
void MyAvatar::setModelURLLoaded() {
_scriptsToUnload.clear();
emit avatarScriptsNeedToLoad();
}
void MyAvatar::leaveDomain() { void MyAvatar::leaveDomain() {
clearScaleRestriction(); clearScaleRestriction();
saveAvatarScale(); saveAvatarScale();
@ -2840,8 +2838,8 @@ float MyAvatar::getWalkSpeed() const {
return _walkSpeed.get() * _walkSpeedScalar; return _walkSpeed.get() * _walkSpeedScalar;
} }
void MyAvatar::addScriptToUnload(QUrl& scriptUrl) { void MyAvatar::addScriptToUnload(QString& url) {
_scriptsToUnload.push_back(scriptUrl); _scriptsToUnload.push_back(url);
} }
void MyAvatar::setSprintMode(bool sprint) { void MyAvatar::setSprintMode(bool sprint) {

View file

@ -594,8 +594,8 @@ public:
void setWalkSpeed(float value); void setWalkSpeed(float value);
float getWalkSpeed() const; float getWalkSpeed() const;
void addScriptToUnload(QUrl& scriptUrl); void addScriptToUnload(QString& url);
const QVector<QUrl>& getScriptsToUnload() const { return _scriptsToUnload; }; const QVector<QString>& getScriptsToUnload() const { return _scriptsToUnload; };
public slots: public slots:
void increaseSize(); void increaseSize();
@ -662,12 +662,9 @@ signals:
void sensorToWorldScaleChanged(float sensorToWorldScale); void sensorToWorldScaleChanged(float sensorToWorldScale);
void attachmentsChanged(); void attachmentsChanged();
void scaleChanged(); void scaleChanged();
void avatarScriptsNeedToLoad();
void avatarScriptsNeedToUnload();
private slots: private slots:
void leaveDomain(); void leaveDomain();
void setModelURLLoaded();
protected: protected:
virtual void beParentOfChild(SpatiallyNestablePointer newChild) const override; virtual void beParentOfChild(SpatiallyNestablePointer newChild) const override;
@ -911,7 +908,7 @@ private:
ThreadSafeValueCache<float> _walkSpeed { DEFAULT_AVATAR_MAX_WALKING_SPEED }; ThreadSafeValueCache<float> _walkSpeed { DEFAULT_AVATAR_MAX_WALKING_SPEED };
float _walkSpeedScalar { AVATAR_WALK_SPEED_SCALAR }; float _walkSpeedScalar { AVATAR_WALK_SPEED_SCALAR };
QVector<QUrl> _scriptsToUnload; QVector<QString> _scriptsToUnload;
}; };
QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode); QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode);

View file

@ -298,7 +298,7 @@ public:
bool hasSkeletonJoints; bool hasSkeletonJoints;
QVector<FBXMesh> meshes; QVector<FBXMesh> meshes;
QVector<QUrl> scripts; QVector<QString> scripts;
QHash<QString, FBXMaterial> materials; QHash<QString, FBXMaterial> materials;

View file

@ -84,7 +84,7 @@ void FSTReader::writeVariant(QBuffer& buffer, QVariantHash::const_iterator& it)
QByteArray FSTReader::writeMapping(const QVariantHash& mapping) { QByteArray FSTReader::writeMapping(const QVariantHash& mapping) {
static const QStringList PREFERED_ORDER = QStringList() << NAME_FIELD << TYPE_FIELD << SCALE_FIELD << FILENAME_FIELD 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; << BLENDSHAPE_FIELD << JOINT_INDEX_FIELD;
QBuffer buffer; QBuffer buffer;
buffer.open(QIODevice::WriteOnly); buffer.open(QIODevice::WriteOnly);
@ -92,7 +92,7 @@ QByteArray FSTReader::writeMapping(const QVariantHash& mapping) {
for (auto key : PREFERED_ORDER) { for (auto key : PREFERED_ORDER) {
auto it = mapping.find(key); auto it = mapping.find(key);
if (it != mapping.constEnd()) { 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)) { for (auto multi : mapping.values(key)) {
buffer.write(key.toUtf8()); buffer.write(key.toUtf8());
buffer.write(" = "); buffer.write(" = ");

View file

@ -210,16 +210,19 @@ void GeometryReader::run() {
throw QString("unsupported format"); throw QString("unsupported format");
} }
if (_mapping.value("type").toString() == "body+head") { // Store fst scripts on geometry
auto scripts = _mapping.value("script"); if (!_mapping.value(SCRIPT_FIELD).isNull()) {
if (!scripts.isNull()) { QVariantList scripts = _mapping.values(SCRIPT_FIELD);
auto scriptsMap = scripts.toMap(); if (scripts.size() > 0) {
auto count = scriptsMap.size(); for (auto &script : scripts) {
if (count > 0) { QString scriptUrl = script.toString();
for (auto &key : scriptsMap.keys()) { if (QUrl(scriptUrl).isRelative()) {
auto scriptUrl = scriptsMap[key].toString(); if (scriptUrl.at(0) == '/') {
fbxGeometry->scripts.push_back(QUrl(scriptUrl)); scriptUrl = scriptUrl.right(scriptUrl.length() - 1);
} }
scriptUrl = _url.resolved(QUrl(scriptUrl)).toString();
}
fbxGeometry->scripts.push_back(scriptUrl);
} }
} }
} }