Merge remote-tracking branch 'origin/master' into feature/missions

# Conflicts:
#	data/assets/scene/solarsystem/missions/newhorizons/newhorizons.asset
#	data/assets/scene/solarsystem/missions/osirisrex/osirisrex.asset
#	data/assets/scene/solarsystem/missions/osirisrex/osirisrex.mission
#	data/assets/scene/solarsystem/missions/perseverance/perseverance.asset
#	include/openspace/mission/missionmanager.h
#	modules/server/src/connection.cpp
#	src/mission/missionmanager.cpp
#	src/mission/missionmanager_lua.inl
This commit is contained in:
Ylva Selling
2023-03-21 12:03:10 -04:00
3829 changed files with 169534 additions and 143316 deletions

View File

@@ -2,7 +2,7 @@
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* Copyright (c) 2014-2023 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
@@ -26,7 +26,9 @@
#include <modules/server/include/topics/authorizationtopic.h>
#include <modules/server/include/topics/bouncetopic.h>
#include <modules/server/include/topics/cameratopic.h>
#include <modules/server/include/topics/documentationtopic.h>
#include <modules/server/include/topics/enginemodetopic.h>
#include <modules/server/include/topics/flightcontrollertopic.h>
#include <modules/server/include/topics/getpropertytopic.h>
#include <modules/server/include/topics/luascripttopic.h>
@@ -34,6 +36,7 @@
#include <modules/server/include/topics/sessionrecordingtopic.h>
#include <modules/server/include/topics/setpropertytopic.h>
#include <modules/server/include/topics/shortcuttopic.h>
#include <modules/server/include/topics/skybrowsertopic.h>
#include <modules/server/include/topics/subscriptiontopic.h>
#include <modules/server/include/topics/timetopic.h>
#include <modules/server/include/topics/topic.h>
@@ -49,34 +52,18 @@
#include <fmt/format.h>
namespace {
constexpr const char* _loggerCat = "ServerModule: Connection";
constexpr std::string_view _loggerCat = "ServerModule: Connection";
constexpr const char* MessageKeyType = "type";
constexpr const char* MessageKeyPayload = "payload";
constexpr const char* MessageKeyTopic = "topic";
constexpr std::string_view MessageKeyType = "type";
constexpr std::string_view MessageKeyPayload = "payload";
constexpr std::string_view MessageKeyTopic = "topic";
constexpr const char* AuthenticationTopicKey = "authorize";
constexpr const char* BounceTopicKey = "bounce";
constexpr const char* DocumentationTopicKey = "documentation";
constexpr const char* FlightControllerTopicKey = "flightcontroller";
constexpr const char* GetPropertyTopicKey = "get";
constexpr const char* LuaScriptTopicKey = "luascript";
constexpr const char* MissionTopicKey = "missions";
constexpr const char* SessionRecordingTopicKey = "sessionRecording";
constexpr const char* SetPropertyTopicKey = "set";
constexpr const char* ShortcutTopicKey = "shortcuts";
constexpr const char* SubscriptionTopicKey = "subscribe";
constexpr const char* TimeTopicKey = "time";
constexpr const char* TriggerPropertyTopicKey = "trigger";
constexpr const char* VersionTopicKey = "version";
} // namespace
namespace openspace {
Connection::Connection(std::unique_ptr<ghoul::io::Socket> s,
std::string address,
bool authorized,
const std::string& password)
Connection::Connection(std::unique_ptr<ghoul::io::Socket> s, std::string address,
bool authorized, const std::string& password)
: _socket(std::move(s))
, _address(std::move(address))
, _isAuthorized(authorized)
@@ -84,7 +71,7 @@ Connection::Connection(std::unique_ptr<ghoul::io::Socket> s,
ghoul_assert(_socket, "Socket must not be nullptr");
_topicFactory.registerClass(
AuthenticationTopicKey,
"authorize",
[password](bool, const ghoul::Dictionary&, ghoul::MemoryPoolBase* pool) {
if (pool) {
void* ptr = pool->allocate(sizeof(AuthorizationTopic));
@@ -96,41 +83,46 @@ Connection::Connection(std::unique_ptr<ghoul::io::Socket> s,
}
);
_topicFactory.registerClass<DocumentationTopic>(DocumentationTopicKey);
_topicFactory.registerClass<GetPropertyTopic>(GetPropertyTopicKey);
_topicFactory.registerClass<LuaScriptTopic>(LuaScriptTopicKey);
_topicFactory.registerClass<MissionTopic>(MissionTopicKey);
_topicFactory.registerClass<SessionRecordingTopic>(SessionRecordingTopicKey);
_topicFactory.registerClass<SetPropertyTopic>(SetPropertyTopicKey);
_topicFactory.registerClass<ShortcutTopic>(ShortcutTopicKey);
_topicFactory.registerClass<SubscriptionTopic>(SubscriptionTopicKey);
_topicFactory.registerClass<TimeTopic>(TimeTopicKey);
_topicFactory.registerClass<TriggerPropertyTopic>(TriggerPropertyTopicKey);
_topicFactory.registerClass<BounceTopic>(BounceTopicKey);
_topicFactory.registerClass<FlightControllerTopic>(FlightControllerTopicKey);
_topicFactory.registerClass<VersionTopic>(VersionTopicKey);
_topicFactory.registerClass<MissionTopic>("missions");
_topicFactory.registerClass<DocumentationTopic>("documentation");
_topicFactory.registerClass<GetPropertyTopic>("get");
_topicFactory.registerClass<LuaScriptTopic>("luascript");
_topicFactory.registerClass<EngineModeTopic>("engineMode");
_topicFactory.registerClass<SessionRecordingTopic>("sessionRecording");
_topicFactory.registerClass<SetPropertyTopic>("set");
_topicFactory.registerClass<ShortcutTopic>("shortcuts");
_topicFactory.registerClass<SubscriptionTopic>("subscribe");
_topicFactory.registerClass<TimeTopic>("time");
_topicFactory.registerClass<TriggerPropertyTopic>("trigger");
_topicFactory.registerClass<BounceTopic>("bounce");
_topicFactory.registerClass<FlightControllerTopic>("flightcontroller");
_topicFactory.registerClass<VersionTopic>("version");
_topicFactory.registerClass<SkyBrowserTopic>("skybrowser");
_topicFactory.registerClass<CameraTopic>("camera");
}
void Connection::handleMessage(const std::string& message) {
ZoneScoped
ZoneScoped;
try {
nlohmann::json j = nlohmann::json::parse(message.c_str());
try {
handleJson(j);
} catch (const std::domain_error& e) {
}
catch (const std::domain_error& e) {
LERROR(fmt::format("JSON handling error from: {}. {}", message, e.what()));
}
} catch (const std::out_of_range& e) {
LERROR(fmt::format("JSON handling error from: {}. {}", message, e.what()));
}
catch (const std::exception& e) {
LERROR(e.what());
}
catch (const std::out_of_range& e) {
LERROR(fmt::format("JSON handling error from: {}. {}", message, e.what()));
}
catch (const std::exception& e) {
LERROR(e.what());
} catch (...) {
if (!isAuthorized()) {
_socket->disconnect();
LERROR(fmt::format(
"Could not parse JSON: '{}'. Connection is unauthorized. Disconnecting.",
"Could not parse JSON: '{}'. Connection is unauthorized. Disconnecting",
message
));
return;
@@ -151,7 +143,7 @@ void Connection::handleMessage(const std::string& message) {
}
void Connection::handleJson(const nlohmann::json& json) {
ZoneScoped
ZoneScoped;
auto topicJson = json.find(MessageKeyTopic);
auto payloadJson = json.find(MessageKeyPayload);
@@ -174,21 +166,18 @@ void Connection::handleJson(const nlohmann::json& json) {
// The topic id is not registered: Initialize a new topic.
auto typeJson = json.find(MessageKeyType);
if (typeJson == json.end() || !typeJson->is_string()) {
LERROR(fmt::format(
"A type must be specified (`{}`) as a string when "
"a new topic is initialized", MessageKeyType
));
LERROR("Type must be specified as a string when a new topic is initialized");
return;
}
std::string type = *typeJson;
if (!isAuthorized() && type != AuthenticationTopicKey) {
LERROR("Connection isn't authorized.");
if (!isAuthorized() && type != "authorize") {
LERROR("Connection is not authorized");
return;
}
std::unique_ptr<Topic> topic = std::unique_ptr<Topic>(_topicFactory.create(type));
topic->initialize(this, topicId);
topic->initialize(shared_from_this(), topicId);
topic->handleJson(*payloadJson);
if (!topic->isDone()) {
_topics.emplace(topicId, std::move(topic));
@@ -196,11 +185,11 @@ void Connection::handleJson(const nlohmann::json& json) {
}
else {
if (!isAuthorized()) {
LERROR("Connection isn't authorized.");
LERROR("Connection is not authorized");
return;
}
// Dispatch the message to the existing topic.
// Dispatch the message to the existing topic
Topic& topic = *topicIt->second;
topic.handleJson(*payloadJson);
if (topic.isDone()) {
@@ -210,13 +199,13 @@ void Connection::handleJson(const nlohmann::json& json) {
}
void Connection::sendMessage(const std::string& message) {
ZoneScoped
ZoneScoped;
_socket->putMessage(message);
}
void Connection::sendJson(const nlohmann::json& json) {
ZoneScoped
ZoneScoped;
sendMessage(json.dump());
}

View File

@@ -2,7 +2,7 @@
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* Copyright (c) 2014-2023 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *

View File

@@ -2,7 +2,7 @@
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* Copyright (c) 2014-2023 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
@@ -34,7 +34,7 @@ using json = nlohmann::json;
namespace openspace::properties {
void to_json(json& j, const Property& p) {
std::string description = p.generateBaseJsonDescription();
std::string description = p.generateJsonDescription();
json desc = json::parse(description);
std::string value = p.jsonValue();
@@ -130,11 +130,6 @@ void to_json(json& j, const SceneGraphNode& n) {
{ "subowners", n.propertySubOwners() }
};
/*
auto renderable = n.renderable();
if (renderable != nullptr) {
j["renderable"] = renderable;
}*/
SceneGraphNode* parent = n.parent();
if (parent) {

View File

@@ -2,7 +2,7 @@
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* Copyright (c) 2014-2023 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
@@ -30,18 +30,17 @@
#include <functional>
namespace {
constexpr const char* KeyIdentifier = "Identifier";
constexpr const char* TcpSocketType = "TcpSocket";
constexpr const char* WebSocketType = "WebSocket";
constexpr const char* DenyAccess = "Deny";
constexpr const char* RequirePassword = "RequirePassword";
constexpr const char* AllowAccess = "Allow";
constexpr std::string_view KeyIdentifier = "Identifier";
constexpr std::string_view TcpSocketType = "TcpSocket";
constexpr std::string_view WebSocketType = "WebSocket";
constexpr std::string_view DenyAccess = "Deny";
constexpr std::string_view RequirePassword = "RequirePassword";
constexpr std::string_view AllowAccess = "Allow";
constexpr openspace::properties::Property::PropertyInfo EnabledInfo = {
"Enabled",
"Is Enabled",
"This setting determines whether this server interface is enabled or not."
"This setting determines whether this server interface is enabled or not"
};
constexpr openspace::properties::Property::PropertyInfo TypeInfo = {
@@ -65,20 +64,20 @@ namespace {
constexpr openspace::properties::Property::PropertyInfo AllowAddressesInfo = {
"AllowAddresses",
"Allow Addresses",
"Ip addresses or domains that should always be allowed access to this interface"
"IP addresses or domains that should always be allowed access to this interface"
};
constexpr openspace::properties::Property::PropertyInfo
RequirePasswordAddressesInfo = {
"RequirePasswordAddresses",
"Require Password Addresses",
"Ip addresses or domains that should be allowed access if they provide a password"
"IP addresses or domains that should be allowed access if they provide a password"
};
constexpr openspace::properties::Property::PropertyInfo DenyAddressesInfo = {
"DenyAddresses",
"Deny Addresses",
"Ip addresses or domains that should never be allowed access to this interface"
"IP addresses or domains that should never be allowed access to this interface"
};
constexpr openspace::properties::Property::PropertyInfo PasswordInfo = {
@@ -86,7 +85,7 @@ namespace {
"Password",
"Password for connecting to this interface"
};
}
} // namespace
namespace openspace {
@@ -94,7 +93,7 @@ std::unique_ptr<ServerInterface> ServerInterface::createFromDictionary(
const ghoul::Dictionary& config)
{
// TODO: Use documentation to verify dictionary
std::unique_ptr<ServerInterface> si = std::make_unique<ServerInterface>(config);
auto si = std::make_unique<ServerInterface>(config);
return si;
}
@@ -110,12 +109,27 @@ ServerInterface::ServerInterface(const ghoul::Dictionary& config)
, _password(PasswordInfo)
{
_type.addOption(static_cast<int>(InterfaceType::TcpSocket), TcpSocketType);
_type.addOption(static_cast<int>(InterfaceType::WebSocket), WebSocketType);
_type.addOption(
static_cast<int>(InterfaceType::TcpSocket),
std::string(TcpSocketType)
);
_type.addOption(
static_cast<int>(InterfaceType::WebSocket),
std::string(WebSocketType)
);
_defaultAccess.addOption(static_cast<int>(Access::Deny), DenyAccess);
_defaultAccess.addOption(static_cast<int>(Access::RequirePassword), RequirePassword);
_defaultAccess.addOption(static_cast<int>(Access::Allow), AllowAccess);
_defaultAccess.addOption(
static_cast<int>(Access::Deny),
std::string(DenyAccess)
);
_defaultAccess.addOption(
static_cast<int>(Access::RequirePassword),
std::string(RequirePassword)
);
_defaultAccess.addOption(
static_cast<int>(Access::Allow),
std::string(AllowAccess)
);
if (config.hasKey(DefaultAccessInfo.identifier)) {
std::string access = config.value<std::string>(DefaultAccessInfo.identifier);

View File

@@ -2,7 +2,7 @@
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* Copyright (c) 2014-2023 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
@@ -30,12 +30,12 @@
#include <ghoul/logging/logmanager.h>
namespace {
constexpr const char* _loggerCat = "AuthorizationTopic";
constexpr std::string_view _loggerCat = "AuthorizationTopic";
constexpr const char* KeyStatus = "status";
constexpr const char* Authorized = "authorized";
constexpr const char* IncorrectKey = "incorrectKey";
constexpr const char* BadRequest = "badRequest";
constexpr std::string_view KeyStatus = "status";
constexpr std::string_view Authorized = "authorized";
constexpr std::string_view IncorrectKey = "incorrectKey";
constexpr std::string_view BadRequest = "badRequest";
} // namespace
namespace openspace {
@@ -54,18 +54,20 @@ void AuthorizationTopic::handleJson(const nlohmann::json& json) {
}
else {
try {
auto providedKey = json.at("key").get<std::string>();
std::string providedKey = json.at("key").get<std::string>();
if (authorize(providedKey)) {
_connection->setAuthorized(true);
_connection->sendJson(wrappedPayload({ KeyStatus, Authorized }));
LINFO("Client successfully authorized.");
LINFO("Client successfully authorized");
}
else {
_connection->sendJson(wrappedPayload({ KeyStatus, IncorrectKey }));
}
} catch (const std::out_of_range&) {
}
catch (const std::out_of_range&) {
_connection->sendJson(wrappedPayload({ KeyStatus, BadRequest }));
} catch (const std::domain_error&) {
}
catch (const std::domain_error&) {
_connection->sendJson(wrappedPayload({ KeyStatus, BadRequest }));
}
}

View File

@@ -2,7 +2,7 @@
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* Copyright (c) 2014-2023 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *

View File

@@ -0,0 +1,100 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2023 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include "modules/server/include/topics/cameratopic.h"
#include <modules/server/include/connection.h>
#include <modules/server/servermodule.h>
#include <modules/globebrowsing/globebrowsingmodule.h>
#include <modules/globebrowsing/src/dashboarditemglobelocation.h>
#include <openspace/engine/moduleengine.h>
#include <openspace/engine/globals.h>
#include <openspace/properties/property.h>
#include <openspace/query/query.h>
#include <openspace/util/distanceconversion.h>
#include <ghoul/logging/logmanager.h>
namespace {
constexpr std::string_view SubscribeEvent = "start_subscription";
} // namespace
using nlohmann::json;
namespace openspace {
CameraTopic::CameraTopic()
: _lastUpdateTime(std::chrono::system_clock::now())
{}
CameraTopic::~CameraTopic() {
if (_dataCallbackHandle != UnsetOnChangeHandle) {
ServerModule* module = global::moduleEngine->module<ServerModule>();
if (module) {
module->removePreSyncCallback(_dataCallbackHandle);
}
}
}
bool CameraTopic::isDone() const {
return _isDone;
}
void CameraTopic::handleJson(const nlohmann::json& json) {
std::string event = json.at("event").get<std::string>();
if (event != SubscribeEvent) {
_isDone = true;
return;
}
ServerModule* module = global::moduleEngine->module<ServerModule>();
_dataCallbackHandle = module->addPreSyncCallback(
[this]() {
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
if (now - _lastUpdateTime > _cameraPositionUpdateTime) {
sendCameraData();
_lastUpdateTime = std::chrono::system_clock::now();
}
}
);
}
void CameraTopic::sendCameraData() {
using namespace openspace;
GlobeBrowsingModule* module = global::moduleEngine->module<GlobeBrowsingModule>();
glm::dvec3 position = module->geoPosition();
std::pair<double, std::string_view> altSimplified = simplifyDistance(position.z);
nlohmann::json jsonData = {
{ "latitude", position.x },
{ "longitude", position.y },
{ "altitude", altSimplified.first },
{ "altitudeUnit", altSimplified.second }
};
_connection->sendJson(wrappedPayload(jsonData));
}
} // namespace openspace

View File

@@ -2,7 +2,7 @@
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* Copyright (c) 2014-2023 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
@@ -34,41 +34,31 @@
#include <openspace/scene/scenelicensewriter.h>
#include <ghoul/logging/logmanager.h>
using nlohmann::json;
namespace {
constexpr const char* KeyType = "type";
constexpr const char* TypeLua = "lua";
constexpr const char* TypeFactories = "factories";
constexpr const char* TypeKeyboard = "keyboard";
constexpr const char* TypeAsset = "asset";
constexpr const char* TypeMeta= "meta";
} // namespace
namespace openspace {
void DocumentationTopic::handleJson(const nlohmann::json& json) {
std::string requestedType = json.at(KeyType).get<std::string>();
std::string requestedType = json.at("type").get<std::string>();
nlohmann::json response;
// @emiax: Proposed future refector.
// Do not parse generated json. Instead implement ability to get
// ghoul::Dictionary objects from ScriptEngine, FactoryManager, and KeybindingManager.
if (requestedType == TypeLua) {
if (requestedType == "lua") {
response = json::parse(global::scriptEngine->generateJson());
}
else if (requestedType == TypeFactories) {
else if (requestedType == "factories") {
response = json::parse(FactoryManager::ref().generateJson());
}
else if (requestedType == TypeKeyboard) {
else if (requestedType == "keyboard") {
response = json::parse(global::keybindingManager->generateJson());
}
else if (requestedType == TypeAsset) {
else if (requestedType == "asset") {
response = json::parse(global::keybindingManager->generateJson());
}
else if (requestedType == TypeMeta) {
else if (requestedType == "meta") {
std::string docs = SceneLicenseWriter().generateJson();
nlohmann::json parsedDocs = json::parse(docs);
response = parsedDocs;

View File

@@ -0,0 +1,114 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2023 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include "modules/server/include/topics/enginemodetopic.h"
#include <modules/server/include/connection.h>
#include <openspace/engine/globals.h>
#include <openspace/query/query.h>
#include <ghoul/logging/logmanager.h>
namespace {
constexpr std::string_view _loggerCat = "EngineModeTopic";
constexpr std::string_view SubscribeEvent = "start_subscription";
constexpr std::string_view UnsubscribeEvent = "stop_subscription";
constexpr std::string_view RefreshEvent = "refresh";
} // namespace
using nlohmann::json;
namespace openspace {
EngineModeTopic::EngineModeTopic() {
LDEBUG("Starting new EngineMode subscription");
}
EngineModeTopic::~EngineModeTopic() {
if (_modeCallbackHandle != UnsetOnChangeHandle) {
global::openSpaceEngine->removeModeChangeCallback(_modeCallbackHandle);
}
}
bool EngineModeTopic::isDone() const {
return _isDone;
}
void EngineModeTopic::handleJson(const nlohmann::json& json) {
const std::string event = json.at("event").get<std::string>();
if (event != SubscribeEvent && event != UnsubscribeEvent &&
event != RefreshEvent)
{
LERROR("Unsupported event");
_isDone = true;
return;
}
if (event == UnsubscribeEvent) {
_isDone = true;
return;
}
sendJsonData();
if (event == SubscribeEvent) {
_modeCallbackHandle = global::openSpaceEngine->addModeChangeCallback(
[this]() {
OpenSpaceEngine::Mode currentMode =
global::openSpaceEngine->currentMode();
if (currentMode != _lastMode) {
sendJsonData();
_lastMode = currentMode;
}
}
);
}
}
void EngineModeTopic::sendJsonData() {
json stateJson;
OpenSpaceEngine::Mode mode = global::openSpaceEngine->currentMode();
std::string modeString;
switch (mode) {
case OpenSpaceEngine::Mode::UserControl:
modeString = "user_control";
break;
case OpenSpaceEngine::Mode::SessionRecordingPlayback:
modeString = "session_recording_playback";
break;
case OpenSpaceEngine::Mode::CameraPath:
modeString = "camera_path";
break;
default:
throw ghoul::MissingCaseException();
}
stateJson["mode"] = modeString;
if (!stateJson.empty()) {
_connection->sendJson(wrappedPayload(stateJson));
}
}
} // namespace openspace

View File

@@ -2,7 +2,7 @@
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* Copyright (c) 2014-2023 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
@@ -27,11 +27,10 @@
#include <modules/server/include/connection.h>
#include <modules/server/include/jsonconverters.h>
#include <openspace/engine/globals.h>
#include <openspace/interaction/inputstate.h>
#include <openspace/interaction/websocketcamerastates.h>
#include <openspace/interaction/websocketinputstate.h>
#include <openspace/interaction/navigationhandler.h>
#include <openspace/interaction/orbitalnavigator.h>
#include <openspace/navigation/navigationhandler.h>
#include <openspace/navigation/orbitalnavigator.h>
#include <openspace/rendering/renderable.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/scene/scenegraphnode.h>
@@ -59,7 +58,8 @@ namespace {
using AxisType = openspace::interaction::WebsocketCameraStates::AxisType;
constexpr const char* _loggerCat = "FlightControllerTopic";
constexpr std::string_view _loggerCat = "FlightControllerTopic";
constexpr const char* TypeKey = "type";
constexpr const char* ValuesKey = "values";

View File

@@ -2,7 +2,7 @@
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* Copyright (c) 2014-2023 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
@@ -28,9 +28,8 @@
#include <modules/server/include/jsonconverters.h>
#include <modules/volume/transferfunctionhandler.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/virtualpropertymanager.h>
#include <openspace/engine/windowdelegate.h>
#include <openspace/interaction/navigationhandler.h>
#include <openspace/navigation/navigationhandler.h>
#include <openspace/network/parallelpeer.h>
#include <openspace/query/query.h>
#include <openspace/rendering/luaconsole.h>
@@ -42,18 +41,18 @@
using nlohmann::json;
namespace {
constexpr const char* _loggerCat = "GetPropertyTopic";
constexpr const char* AllPropertiesValue = "__allProperties";
constexpr const char* AllNodesValue = "__allNodes";
constexpr const char* AllScreenSpaceRenderablesValue = "__screenSpaceRenderables";
constexpr const char* PropertyKey = "property";
constexpr const char* RootPropertyOwner = "__rootOwner";
constexpr std::string_view _loggerCat = "GetPropertyTopic";
constexpr std::string_view AllPropertiesValue = "__allProperties";
constexpr std::string_view AllNodesValue = "__allNodes";
constexpr std::string_view AllScreenSpaceRenderablesValue =
"__screenSpaceRenderables";
constexpr std::string_view RootPropertyOwner = "__rootOwner";
} // namespace
namespace openspace {
void GetPropertyTopic::handleJson(const nlohmann::json& json) {
std::string requestedKey = json.at(PropertyKey).get<std::string>();
std::string requestedKey = json.at("property").get<std::string>();
LDEBUG("Getting property '" + requestedKey + "'...");
nlohmann::json response;
if (requestedKey == AllPropertiesValue) {
@@ -88,8 +87,7 @@ json GetPropertyTopic::allProperties() {
global::renderEngine,
global::luaConsole,
global::parallelPeer,
global::navigationHandler,
global::virtualPropertyManager,
global::navigationHandler
}
}
};

View File

@@ -2,7 +2,7 @@
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* Copyright (c) 2014-2023 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
@@ -33,11 +33,11 @@
#include <ghoul/misc/dictionary.h>
namespace {
constexpr const char* KeyScript = "script";
constexpr const char* KeyFunction = "function";
constexpr const char* KeyArguments = "arguments";
constexpr const char* KeyReturn = "return";
constexpr const char* _loggerCat = "LuaScriptTopic";
constexpr std::string_view KeyScript = "script";
constexpr std::string_view KeyFunction = "function";
constexpr std::string_view KeyArguments = "arguments";
constexpr std::string_view KeyReturn = "return";
constexpr std::string_view _loggerCat = "LuaScriptTopic";
std::string formatLua(const nlohmann::json::const_iterator& it);
@@ -112,7 +112,7 @@ namespace {
if (it->is_null()) {
return "nil";
}
throw ghoul::lua::LuaFormatException("Format error.");
throw ghoul::lua::LuaFormatException("Format error");
}
std::string generateScript(const std::string& function,
@@ -176,13 +176,14 @@ void LuaScriptTopic::handleJson(const nlohmann::json& json) {
}
}
void LuaScriptTopic::runScript(const std::string& script, bool shouldReturn) {
void LuaScriptTopic::runScript(std::string script, bool shouldReturn) {
scripting::ScriptEngine::ScriptCallback callback;
if (shouldReturn) {
callback = [this](ghoul::Dictionary data) {
if (_connection) {
nlohmann::json j = data;
_connection->sendJson(wrappedPayload(j));
nlohmann::json payload = wrappedPayload(j);
_connection->sendJson(payload);
_waitingForReturnValue = false;
}
};

View File

@@ -2,7 +2,7 @@
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* Copyright (c) 2014-2023 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
@@ -30,11 +30,11 @@
#include <ghoul/logging/logmanager.h>
namespace {
constexpr const char* _loggerCat = "SessionRecordingTopic";
constexpr const char* EventKey = "event";
constexpr const char* SubscribeEvent = "start_subscription";
constexpr const char* UnsubscribeEvent = "stop_subscription";
constexpr const char* RefreshEvent = "refresh";
constexpr std::string_view _loggerCat = "SessionRecordingTopic";
constexpr std::string_view SubscribeEvent = "start_subscription";
constexpr std::string_view UnsubscribeEvent = "stop_subscription";
constexpr std::string_view RefreshEvent = "refresh";
constexpr const char* PropertiesKey = "properties";
constexpr const char* FilesKey = "files";
@@ -60,7 +60,7 @@ bool SessionRecordingTopic::isDone() const {
}
void SessionRecordingTopic::handleJson(const nlohmann::json& json) {
const std::string event = json.at(EventKey).get<std::string>();
const std::string event = json.at("event").get<std::string>();
if (event != SubscribeEvent && event != UnsubscribeEvent &&
event != RefreshEvent)
{
@@ -76,13 +76,13 @@ void SessionRecordingTopic::handleJson(const nlohmann::json& json) {
if (json.find(PropertiesKey) != json.end()) {
if (!json.at(PropertiesKey).is_array()) {
LERROR("Properties must be an array of strings.");
LERROR("Properties must be an array of strings");
}
nlohmann::json requestedProperties = json.at(PropertiesKey).get<nlohmann::json>();
for (const auto& p : requestedProperties) {
if (!p.is_string()) {
_isDone = true;
LERROR("Properties must be an array of strings.");
LERROR("Properties must be an array of strings");
return;
}
const std::string v = p.get<std::string>();
@@ -124,6 +124,9 @@ void SessionRecordingTopic::sendJsonData() {
case SessionRecording::SessionState::Playback:
stateString = "playing";
break;
case SessionRecording::SessionState::PlaybackPaused:
stateString = "playing-paused";
break;
default:
stateString = "idle";
break;

View File

@@ -2,7 +2,7 @@
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* Copyright (c) 2014-2023 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
@@ -34,10 +34,8 @@
#include <ghoul/logging/logmanager.h>
namespace {
constexpr const char* PropertyKey = "property";
constexpr const char* ValueKey = "value";
constexpr const char* _loggerCat = "SetPropertyTopic";
constexpr const char* SpecialKeyTime = "__time";
constexpr std::string_view _loggerCat = "SetPropertyTopic";
constexpr std::string_view SpecialKeyTime = "__time";
std::string escapedLuaString(const std::string& str) {
std::string luaString;
@@ -113,15 +111,15 @@ namespace openspace {
void SetPropertyTopic::handleJson(const nlohmann::json& json) {
try {
const std::string& propertyKey = json.at(PropertyKey).get<std::string>();
const std::string& propertyKey = json.at("property").get<std::string>();
if (propertyKey == SpecialKeyTime) {
Time newTime;
newTime.setTime(json.at(ValueKey).get<std::string>());
newTime.setTime(json.at("value").get<std::string>());
global::timeManager->setTimeNextFrame(newTime);
}
else {
nlohmann::json value = json.at(ValueKey);
nlohmann::json value = json.at("value");
std::string literal = luaLiteralFromJson(value);
global::scriptEngine->queueScript(

View File

@@ -2,7 +2,7 @@
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* Copyright (c) 2014-2023 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
@@ -26,14 +26,9 @@
#include <modules/server/include/connection.h>
#include <openspace/engine/globals.h>
#include <openspace/interaction/shortcutmanager.h>
#include <openspace/interaction/actionmanager.h>
#include <openspace/interaction/keybindingmanager.h>
namespace {
constexpr const char* EventKey = "event";
constexpr const char* StartSubscription = "start_subscription";
constexpr const char* StopSubscription = "stop_subscription";
} // namespace
#include <ghoul/logging/logmanager.h>
using nlohmann::json;
@@ -44,32 +39,50 @@ bool ShortcutTopic::isDone() const {
}
std::vector<nlohmann::json> ShortcutTopic::shortcutsJson() const {
using ShortcutInformation = interaction::ShortcutManager::ShortcutInformation;
const std::vector<ShortcutInformation>& shortcuts =
global::shortcutManager->shortcuts();
std::vector<nlohmann::json> json;
for (const ShortcutInformation& shortcut : shortcuts) {
std::vector<interaction::Action> actions = global::actionManager->actions();
std::sort(
actions.begin(),
actions.end(),
[](const interaction::Action& lhs, const interaction::Action& rhs) {
if (!lhs.name.empty() && !rhs.name.empty()) {
return lhs.name < rhs.name;
}
else {
return lhs.identifier < rhs.identifier;
}
}
);
for (const interaction::Action& action : actions) {
nlohmann::json shortcutJson = {
{ "name", shortcut.name },
{ "script", shortcut.script },
{ "synchronization", static_cast<bool>(shortcut.synchronization) },
{ "documentation", shortcut.documentation },
{ "guiPath", shortcut.guiPath },
{ "identifier", action.identifier },
{ "name", action.name },
{ "script", action.command },
{ "synchronization", static_cast<bool>(action.synchronization) },
{ "documentation", action.documentation },
{ "guiPath", action.guiPath },
};
json.push_back(shortcutJson);
}
using KeyInformation = interaction::KeybindingManager::KeyInformation;
const std::multimap<KeyWithModifier, KeyInformation>& keyBindings =
const std::multimap<KeyWithModifier, std::string>& keyBindings =
global::keybindingManager->keyBindings();
for (const std::pair<const KeyWithModifier, KeyInformation>& keyBinding : keyBindings)
{
for (const std::pair<const KeyWithModifier, std::string>& keyBinding : keyBindings) {
if (!global::actionManager->hasAction(keyBinding.second)) {
// We don't warn here as we don't know if the user didn't expect the action
// to be there or not. They might have defined a keybind to do multiple things
// only one of which is actually defined
continue;
}
const KeyWithModifier& k = keyBinding.first;
const KeyInformation& info = keyBinding.second;
// @TODO (abock, 2021-08-05) Probably this should be rewritten to better account
// for the new action mechanism
const interaction::Action& action = global::actionManager->action(
keyBinding.second
);
nlohmann::json shortcutJson = {
{ "key", ghoul::to_string(k.key) },
@@ -81,11 +94,7 @@ std::vector<nlohmann::json> ShortcutTopic::shortcutsJson() const {
{ "super" , hasKeyModifier(k.modifier, KeyModifier::Super) }
}
},
{ "name", info.name },
{ "script", info.command },
{ "synchronization", static_cast<bool>(info.synchronization) },
{ "documentation", info.documentation },
{ "guiPath", info.guiPath },
{ "action", action.identifier },
};
json.push_back(shortcutJson);
}
@@ -98,12 +107,12 @@ void ShortcutTopic::sendData() const {
}
void ShortcutTopic::handleJson(const nlohmann::json& input) {
const std::string& event = input.at(EventKey).get<std::string>();
if (event == StartSubscription) {
const std::string& event = input.at("event").get<std::string>();
if (event == "start_subscription") {
// TODO: Subscribe to shortcuts and keybindings
// shortcutManager.subscribe(); ...
}
else if (event == StopSubscription) {
else if (event == "stop_subscription") {
// TODO: Unsubscribe to shortcuts and keybindings
// shortcutManager.unsubscribe(); ...
return;

View File

@@ -0,0 +1,130 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2023 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include "modules/server/include/topics/skybrowsertopic.h"
#include <modules/server/include/connection.h>
#include <modules/server/servermodule.h>
#include <modules/skybrowser/skybrowsermodule.h>
#include <modules/skybrowser/include/targetbrowserpair.h>
#include <openspace/engine/moduleengine.h>
#include <openspace/engine/globals.h>
#include <openspace/properties/property.h>
#include <openspace/query/query.h>
#include <ghoul/logging/logmanager.h>
namespace {
constexpr std::string_view SubscribeEvent = "start_subscription";
constexpr std::string_view UnsubscribeEvent = "stop_subscription";
} // namespace
using nlohmann::json;
namespace openspace {
SkyBrowserTopic::SkyBrowserTopic()
: _lastUpdateTime(std::chrono::system_clock::now())
{
ServerModule* module = global::moduleEngine->module<ServerModule>();
if (module) {
_skyBrowserUpdateTime = std::chrono::milliseconds(module->skyBrowserUpdateTime());
}
}
SkyBrowserTopic::~SkyBrowserTopic() {
if (_targetDataCallbackHandle != UnsetOnChangeHandle) {
ServerModule* module = global::moduleEngine->module<ServerModule>();
if (module) {
module->removePreSyncCallback(_targetDataCallbackHandle);
}
}
}
bool SkyBrowserTopic::isDone() const {
return _isDone;
}
void SkyBrowserTopic::handleJson(const nlohmann::json& json) {
std::string event = json.at("event").get<std::string>();
if (event == UnsubscribeEvent) {
_isDone = true;
return;
}
if (event != SubscribeEvent) {
_isDone = true;
return;
}
ServerModule* module = global::moduleEngine->module<ServerModule>();
_targetDataCallbackHandle = module->addPreSyncCallback(
[this]() {
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
if (now - _lastUpdateTime > _skyBrowserUpdateTime) {
sendBrowserData();
_lastUpdateTime = std::chrono::system_clock::now();
}
}
);
}
void SkyBrowserTopic::sendBrowserData() {
using namespace openspace;
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
ghoul::Dictionary data;
// Set general data
data.setValue("selectedBrowserId", module->selectedBrowserId());
data.setValue("cameraInSolarSystem", module->isCameraInSolarSystem());
// Pass data for all the browsers and the corresponding targets
if (module->isCameraInSolarSystem()) {
const std::vector<std::unique_ptr<TargetBrowserPair>>& pairs = module->pairs();
ghoul::Dictionary targets;
for (const std::unique_ptr<TargetBrowserPair>& pair : pairs) {
std::string id = pair->browserId();
ghoul::Dictionary target = pair->dataAsDictionary();
targets.setValue(id, target);
}
data.setValue("browsers", targets);
}
std::string jsonString = ghoul::formatJson(data);
// Only send message if data actually changed
if (jsonString != _lastUpdateJsonString) {
json jsonData = json::parse(jsonString.begin(), jsonString.end());
_connection->sendJson(wrappedPayload(jsonData));
}
// @TODO (2022-04-28, emmbr) The message is still sent very often; every time the
// camera moves or the time is changes, because this changes the "roll" parameter
// of the browser. This is the update that occurs most often. Maybe it could be
// separated into it's own topic?
_lastUpdateJsonString = jsonString;
}
} // namespace openspace

View File

@@ -2,7 +2,7 @@
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* Copyright (c) 2014-2023 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
@@ -33,12 +33,10 @@
#include <ghoul/logging/logmanager.h>
namespace {
constexpr const char* _loggerCat = "SubscriptionTopic";
constexpr const char* PropertyKey = "property";
constexpr const char* EventKey = "event";
constexpr std::string_view _loggerCat = "SubscriptionTopic";
constexpr const char* StartSubscription = "start_subscription";
constexpr const char* StopSubscription = "stop_subscription";
constexpr std::string_view StartSubscription = "start_subscription";
constexpr std::string_view StopSubscription = "stop_subscription";
} // namespace
using nlohmann::json;
@@ -68,10 +66,10 @@ void SubscriptionTopic::resetCallbacks() {
}
void SubscriptionTopic::handleJson(const nlohmann::json& json) {
const std::string& event = json.at(EventKey).get<std::string>();
const std::string& event = json.at("event").get<std::string>();
if (event == StartSubscription) {
std::string key = json.at(PropertyKey).get<std::string>();
std::string key = json.at("property").get<std::string>();
_prop = property(key);
resetCallbacks();

View File

@@ -2,7 +2,7 @@
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* Copyright (c) 2014-2023 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
@@ -32,10 +32,9 @@
#include <ghoul/logging/logmanager.h>
namespace {
constexpr const char* EventKey = "event";
constexpr const char* SubscribeEvent = "start_subscription";
constexpr const char* UnsubscribeEvent = "stop_subscription";
constexpr const std::chrono::milliseconds TimeUpdateInterval(50);
constexpr std::string_view SubscribeEvent = "start_subscription";
constexpr std::string_view UnsubscribeEvent = "stop_subscription";
constexpr std::chrono::milliseconds TimeUpdateInterval(50);
} // namespace
using nlohmann::json;
@@ -65,7 +64,7 @@ bool TimeTopic::isDone() const {
}
void TimeTopic::handleJson(const nlohmann::json& json) {
std::string event = json.at(EventKey).get<std::string>();
std::string event = json.at("event").get<std::string>();
if (event == UnsubscribeEvent) {
_isDone = true;
return;
@@ -134,7 +133,7 @@ const json TimeTopic::getNextPrevDeltaTimeStepJson() {
}
void TimeTopic::sendCurrentTime() {
ZoneScoped
ZoneScoped;
const json timeJson = {
{ "time", global::timeManager->time().ISO8601() }

View File

@@ -2,7 +2,7 @@
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* Copyright (c) 2014-2023 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
@@ -30,17 +30,13 @@
namespace openspace {
Topic::~Topic() {
_connection = nullptr;
}
void Topic::initialize(Connection* connection, size_t topicId) {
_connection = connection;
void Topic::initialize(std::shared_ptr<Connection> connection, size_t topicId) {
_connection = std::move(connection);
_topicId = topicId;
}
nlohmann::json Topic::wrappedPayload(const nlohmann::json& payload) const {
ZoneScoped
ZoneScoped;
// TODO: add message time
nlohmann::json j = {
@@ -51,7 +47,7 @@ nlohmann::json Topic::wrappedPayload(const nlohmann::json& payload) const {
}
nlohmann::json Topic::wrappedError(std::string message, int code) {
ZoneScoped
ZoneScoped;
nlohmann::json j = {
{ "topic", _topicId },

View File

@@ -2,7 +2,7 @@
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* Copyright (c) 2014-2023 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
@@ -32,16 +32,14 @@
#include <openspace/scripting/scriptengine.h>
namespace {
constexpr const char* PropertyKey = "property";
//constexpr const char* ValueKey = "value";
constexpr const char* _loggerCat = "TriggerPropertyTopic";
constexpr std::string_view _loggerCat = "TriggerPropertyTopic";
} // namespace
namespace openspace {
void TriggerPropertyTopic::handleJson(const nlohmann::json& json) {
try {
const std::string& propertyKey = json.at(PropertyKey).get<std::string>();
const std::string& propertyKey = json.at("property").get<std::string>();
global::scriptEngine->queueScript(
fmt::format(
"openspace.setPropertyValueSingle(\"{}\", nil)", propertyKey

View File

@@ -2,7 +2,7 @@
* *
* OpenSpace *
* *
* Copyright (c) 2014-2021 *
* Copyright (c) 2014-2023 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *