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.
DependencyManager::get<OffscreenUi>()->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<ScriptEngines>();
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<QString>& urls) {
if (auto avatar = getMyAvatar()) {
if (urls.size() > 0) {
auto scriptEngines = DependencyManager::get<ScriptEngines>();
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<ScriptEngines>();
for (auto script : scripts) {
scriptEngines->stopScript(script.toString(), false);
}
}
void Application::unloadAvatarScripts(const QVector<QString>& urls) {
if (urls.size() > 0) {
auto scriptEngines = DependencyManager::get<ScriptEngines>();
for (auto url : urls) {
scriptEngines->stopScript(url, false);
}
}, Qt::QueuedConnection);
}
}
void Application::updateLOD(float deltaTime) const {

View file

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

View file

@ -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);

View file

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

View file

@ -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());
}

View file

@ -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;

View file

@ -121,7 +121,12 @@ MyAvatar::MyAvatar(QThread* thread) :
_skeletonModel = std::make_shared<MySkeletonModel>(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) {

View file

@ -594,8 +594,8 @@ public:
void setWalkSpeed(float value);
float getWalkSpeed() const;
void addScriptToUnload(QUrl& scriptUrl);
const QVector<QUrl>& getScriptsToUnload() const { return _scriptsToUnload; };
void addScriptToUnload(QString& url);
const QVector<QString>& 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<float> _walkSpeed { DEFAULT_AVATAR_MAX_WALKING_SPEED };
float _walkSpeedScalar { AVATAR_WALK_SPEED_SCALAR };
QVector<QUrl> _scriptsToUnload;
QVector<QString> _scriptsToUnload;
};
QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode);

View file

@ -298,7 +298,7 @@ public:
bool hasSkeletonJoints;
QVector<FBXMesh> meshes;
QVector<QUrl> scripts;
QVector<QString> scripts;
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) {
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(" = ");

View file

@ -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);
}
}
}