mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-01-12 14:40:00 -06:00
Feature/documentation topic (#822)
- Implement documentation topic that can be used to query documentation using the network API. - Implement a way to pass arguments to lua scripts using json (rather than formatting entire lua string clientside) - Implement ability to attach callback to lua script executions - Implement abillity to transport return values from lua scripts back to network API clients. - Do not initialize server interface on slave nodes. - Implement Dictionary -> json converter using nlohmann json library
This commit is contained in:
@@ -161,7 +161,7 @@ bool ScriptEngine::hasLibrary(const std::string& name) {
|
||||
return (it != _registeredLibraries.end());
|
||||
}
|
||||
|
||||
bool ScriptEngine::runScript(const std::string& script) {
|
||||
bool ScriptEngine::runScript(const std::string& script, ScriptCallback callback) {
|
||||
if (script.empty()) {
|
||||
LWARNING("Script was empty");
|
||||
return false;
|
||||
@@ -173,7 +173,13 @@ bool ScriptEngine::runScript(const std::string& script) {
|
||||
}
|
||||
|
||||
try {
|
||||
ghoul::lua::runScript(_state, script);
|
||||
if (callback) {
|
||||
ghoul::Dictionary returnValue =
|
||||
ghoul::lua::loadArrayDictionaryFromString(script, _state);
|
||||
callback.value()(returnValue);
|
||||
} else {
|
||||
ghoul::lua::runScript(_state, script);
|
||||
}
|
||||
}
|
||||
catch (const ghoul::lua::LuaLoadingException& e) {
|
||||
LERRORC(e.component, e.message);
|
||||
@@ -183,6 +189,10 @@ bool ScriptEngine::runScript(const std::string& script) {
|
||||
LERRORC(e.component, e.message);
|
||||
return false;
|
||||
}
|
||||
catch (const ghoul::RuntimeError& e) {
|
||||
LERRORC(e.component, e.message);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -639,72 +649,82 @@ void ScriptEngine::preSync(bool isMaster) {
|
||||
return;
|
||||
}
|
||||
|
||||
_mutex.lock();
|
||||
if (!_queuedScripts.empty()) {
|
||||
_currentSyncedScript = _queuedScripts.back().first;
|
||||
const bool remoteScripting = _queuedScripts.back().second;
|
||||
std::lock_guard<std::mutex> guard(_slaveScriptsMutex);
|
||||
while (!_incomingScripts.empty()) {
|
||||
QueueItem item = std::move(_incomingScripts.front());
|
||||
_incomingScripts.pop();
|
||||
|
||||
_scriptsToSync.push_back(item.script);
|
||||
const bool remoteScripting = item.remoteScripting;
|
||||
|
||||
// Not really a received script but the master also needs to run the script...
|
||||
_receivedScripts.push_back(_currentSyncedScript);
|
||||
_queuedScripts.pop_back();
|
||||
_masterScriptQueue.push(item);
|
||||
|
||||
if (global::parallelPeer.isHost() && remoteScripting) {
|
||||
global::parallelPeer.sendScript(_currentSyncedScript);
|
||||
global::parallelPeer.sendScript(item.script);
|
||||
}
|
||||
if (global::sessionRecording.isRecording()) {
|
||||
global::sessionRecording.saveScriptKeyframe(_currentSyncedScript);
|
||||
global::sessionRecording.saveScriptKeyframe(item.script);
|
||||
}
|
||||
}
|
||||
_mutex.unlock();
|
||||
}
|
||||
|
||||
void ScriptEngine::encode(SyncBuffer* syncBuffer) {
|
||||
syncBuffer->encode(_currentSyncedScript);
|
||||
_currentSyncedScript.clear();
|
||||
size_t nScripts = _scriptsToSync.size();
|
||||
syncBuffer->encode(nScripts);
|
||||
for (const std::string& s : _scriptsToSync) {
|
||||
syncBuffer->encode(s);
|
||||
}
|
||||
_scriptsToSync.clear();
|
||||
}
|
||||
|
||||
void ScriptEngine::decode(SyncBuffer* syncBuffer) {
|
||||
syncBuffer->decode(_currentSyncedScript);
|
||||
std::lock_guard<std::mutex> guard(_slaveScriptsMutex);
|
||||
size_t nScripts;
|
||||
syncBuffer->decode(nScripts);
|
||||
|
||||
if (!_currentSyncedScript.empty()) {
|
||||
_mutex.lock();
|
||||
_receivedScripts.push_back(_currentSyncedScript);
|
||||
_mutex.unlock();
|
||||
for (size_t i = 0; i < nScripts; ++i) {
|
||||
std::string script;
|
||||
syncBuffer->decode(script);
|
||||
_slaveScriptQueue.push(std::move(script));
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptEngine::postSync(bool) {
|
||||
std::vector<std::string> scripts;
|
||||
|
||||
_mutex.lock();
|
||||
scripts.assign(_receivedScripts.begin(), _receivedScripts.end());
|
||||
_receivedScripts.clear();
|
||||
_mutex.unlock();
|
||||
|
||||
while (!scripts.empty()) {
|
||||
try {
|
||||
runScript(scripts.back());
|
||||
void ScriptEngine::postSync(bool isMaster) {
|
||||
if (isMaster) {
|
||||
while (!_masterScriptQueue.empty()) {
|
||||
std::string script = std::move(_masterScriptQueue.front().script);
|
||||
ScriptCallback callback = std::move(_masterScriptQueue.front().callback);
|
||||
_masterScriptQueue.pop();
|
||||
try {
|
||||
runScript(script, callback);
|
||||
}
|
||||
catch (const ghoul::RuntimeError& e) {
|
||||
LERRORC(e.component, e.message);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
catch (const ghoul::RuntimeError& e) {
|
||||
LERRORC(e.component, e.message);
|
||||
} else {
|
||||
std::lock_guard<std::mutex> guard(_slaveScriptsMutex);
|
||||
while (!_slaveScriptQueue.empty()) {
|
||||
try {
|
||||
runScript(_slaveScriptQueue.front());
|
||||
_slaveScriptQueue.pop();
|
||||
}
|
||||
catch (const ghoul::RuntimeError& e) {
|
||||
LERRORC(e.component, e.message);
|
||||
}
|
||||
}
|
||||
scripts.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptEngine::queueScript(const std::string& script,
|
||||
ScriptEngine::RemoteScripting remoteScripting)
|
||||
ScriptEngine::RemoteScripting remoteScripting,
|
||||
ScriptCallback callback)
|
||||
{
|
||||
if (script.empty()) {
|
||||
return;
|
||||
if (!script.empty()) {
|
||||
_incomingScripts.push({ script, remoteScripting, callback });
|
||||
}
|
||||
|
||||
_mutex.lock();
|
||||
_queuedScripts.insert(
|
||||
_queuedScripts.begin(),
|
||||
std::make_pair(script, remoteScripting)
|
||||
);
|
||||
_mutex.unlock();
|
||||
}
|
||||
|
||||
} // namespace openspace::scripting
|
||||
|
||||
Reference in New Issue
Block a user