mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-15 08:57:19 +02:00
Added script types and better script reload
This commit is contained in:
parent
12f578c93c
commit
2de982a5a2
12 changed files with 81 additions and 33 deletions
|
@ -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<OffscreenUi>()->hide("RunningScripts");
|
||||
if (auto avatar = getMyAvatar()) {
|
||||
auto urls = avatar->getScriptsToUnload();
|
||||
unloadAvatarScripts(urls);
|
||||
}
|
||||
|
||||
_aboutToQuit = true;
|
||||
|
||||
|
@ -4737,18 +4734,24 @@ void Application::loadAvatarScripts(const QVector<QString>& 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<QString>& urls) {
|
||||
if (urls.size() > 0) {
|
||||
auto scriptEngines = DependencyManager::get<ScriptEngines>();
|
||||
void Application::unloadAvatarScripts() {
|
||||
auto scriptEngines = DependencyManager::get<ScriptEngines>();
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -291,7 +291,7 @@ public:
|
|||
void replaceDomainContent(const QString& url);
|
||||
|
||||
void loadAvatarScripts(const QVector<QString>& urls);
|
||||
void unloadAvatarScripts(const QVector<QString>& urls);
|
||||
void unloadAvatarScripts();
|
||||
|
||||
signals:
|
||||
void svoImportRequested(const QString& url);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -594,9 +594,6 @@ public:
|
|||
void setWalkSpeed(float value);
|
||||
float getWalkSpeed() const;
|
||||
|
||||
void addScriptToUnload(const QString& url);
|
||||
const QVector<QString>& getScriptsToUnload() const { return _scriptsToUnload; };
|
||||
|
||||
public slots:
|
||||
void increaseSize();
|
||||
void decreaseSize();
|
||||
|
@ -907,8 +904,6 @@ private:
|
|||
// max unscaled forward movement speed
|
||||
ThreadSafeValueCache<float> _walkSpeed { DEFAULT_AVATAR_MAX_WALKING_SPEED };
|
||||
float _walkSpeedScalar { AVATAR_WALK_SPEED_SCALAR };
|
||||
|
||||
QVector<QString> _scriptsToUnload;
|
||||
};
|
||||
|
||||
QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode);
|
||||
|
|
|
@ -187,6 +187,28 @@ FSTReader::ModelType FSTReader::predictModelType(const QVariantHash& mapping) {
|
|||
return ENTITY_MODEL;
|
||||
}
|
||||
|
||||
QVector<QString> FSTReader::getScripts(const QUrl& url, const QVariantHash& mapping) {
|
||||
|
||||
auto fstMapping = mapping.isEmpty() ? downloadMapping(url.toString()) : mapping;
|
||||
QVector<QString> 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);
|
||||
|
|
|
@ -50,6 +50,8 @@ public:
|
|||
/// Predicts the type of model by examining the mapping
|
||||
static ModelType predictModelType(const QVariantHash& mapping);
|
||||
|
||||
static QVector<QString> 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);
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<ScriptEngines>())
|
||||
{
|
||||
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
|
||||
|
|
|
@ -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<bool> _isFinished { false };
|
||||
|
|
|
@ -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>();
|
||||
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();
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue