diff --git a/data/assets/scene/digitaluniverse/dwarfs.asset b/data/assets/scene/digitaluniverse/dwarfs.asset index a2817d4dc2..07a68b3c03 100644 --- a/data/assets/scene/digitaluniverse/dwarfs.asset +++ b/data/assets/scene/digitaluniverse/dwarfs.asset @@ -35,7 +35,8 @@ local object = { Unit = "pc" }, GUI = { - Path = "/Milky Way/Brown Dwarfs" + Name = "Brown Dwarfs", + Path = "/Milky Way" } } diff --git a/data/assets/scene/digitaluniverse/globularclusters.asset b/data/assets/scene/digitaluniverse/globularclusters.asset index 70ad83f995..b029c5237d 100644 --- a/data/assets/scene/digitaluniverse/globularclusters.asset +++ b/data/assets/scene/digitaluniverse/globularclusters.asset @@ -36,7 +36,7 @@ local object = { }, GUI = { Name = "Globular Clusters", - Path = "/Milky Way/Globular Clusters" + Path = "/Milky Way" } } diff --git a/data/assets/scene/digitaluniverse/h2regions.asset b/data/assets/scene/digitaluniverse/h2regions.asset index 27772f3728..dd77eab63e 100644 --- a/data/assets/scene/digitaluniverse/h2regions.asset +++ b/data/assets/scene/digitaluniverse/h2regions.asset @@ -36,7 +36,7 @@ local object = { }, GUI = { Name = "HII Regions", - Path = "/Milky Way/HII" + Path = "/Milky Way" } } diff --git a/data/assets/scene/digitaluniverse/milkyway.asset b/data/assets/scene/digitaluniverse/milkyway.asset index 5b6fc20343..dff01194a4 100644 --- a/data/assets/scene/digitaluniverse/milkyway.asset +++ b/data/assets/scene/digitaluniverse/milkyway.asset @@ -43,8 +43,8 @@ local sphere = { FadeOutThreshold = 0.025 }, GUI = { - Name = "Milky Way", - Path = "/Milky Way/Milky Way" + Name = "Milky Way Sphere", + Path = "/Milky Way" } } diff --git a/data/assets/scene/digitaluniverse/obassociations.asset b/data/assets/scene/digitaluniverse/obassociations.asset index 44fda4b670..c8411d45c0 100644 --- a/data/assets/scene/digitaluniverse/obassociations.asset +++ b/data/assets/scene/digitaluniverse/obassociations.asset @@ -36,7 +36,7 @@ local object = { }, GUI = { Name = "OB Associations", - Path = "/Milky Way/OB Associations" + Path = "/Milky Way" } } diff --git a/data/assets/scene/digitaluniverse/planetarynebulae.asset b/data/assets/scene/digitaluniverse/planetarynebulae.asset index ccd45f3ce3..ec5e04ab05 100644 --- a/data/assets/scene/digitaluniverse/planetarynebulae.asset +++ b/data/assets/scene/digitaluniverse/planetarynebulae.asset @@ -36,7 +36,7 @@ local object = { }, GUI = { Name = "Planetary Nebulae", - Path = "/Milky Way/Planetary Nebulae" + Path = "/Milky Way" } } diff --git a/data/assets/scene/digitaluniverse/pulsars.asset b/data/assets/scene/digitaluniverse/pulsars.asset index 401dca9381..35c3f376c8 100644 --- a/data/assets/scene/digitaluniverse/pulsars.asset +++ b/data/assets/scene/digitaluniverse/pulsars.asset @@ -35,7 +35,7 @@ local object = { Unit = "pc" }, GUI = { - Path = "/Milky Way/Pulsars" + Path = "/Milky Way" } } diff --git a/data/assets/scene/digitaluniverse/quasars.asset b/data/assets/scene/digitaluniverse/quasars.asset index 546fac9bd7..beeff0ac60 100644 --- a/data/assets/scene/digitaluniverse/quasars.asset +++ b/data/assets/scene/digitaluniverse/quasars.asset @@ -33,7 +33,7 @@ local object = { BillboardMinSize = 0.0, }, GUI = { - Path = "/Universe/Quasars" + Path = "/Universe" } } diff --git a/data/assets/scene/digitaluniverse/supernovaremnants.asset b/data/assets/scene/digitaluniverse/supernovaremnants.asset index 31cbe5d1c5..4254f908f9 100644 --- a/data/assets/scene/digitaluniverse/supernovaremnants.asset +++ b/data/assets/scene/digitaluniverse/supernovaremnants.asset @@ -38,7 +38,7 @@ local object = { }, GUI = { Name = "Supernova Remnants", - Path = "/Milky Way/Supernova Remnants" + Path = "/Milky Way" } } diff --git a/data/assets/util/webgui.asset b/data/assets/util/webgui.asset index 002c01aa80..036fcbdfc0 100644 --- a/data/assets/util/webgui.asset +++ b/data/assets/util/webgui.asset @@ -1,7 +1,7 @@ local guiCustomization = asset.require('customization/gui') -- Select which commit hashes to use for the frontend and backend -local frontendHash = "4fe87ea6b119de54a45e03543b8b95d5ea3808d5" +local frontendHash = "49e171f457fba4b890c4667e471c80fab05f07d2" local backendHash = "408142f26d3fa3d041399fcf58645874589d5b64" local dataProvider = "data.openspaceproject.com/files/webgui" diff --git a/include/openspace/interaction/sessionrecording.h b/include/openspace/interaction/sessionrecording.h index 01973613dd..301f507912 100644 --- a/include/openspace/interaction/sessionrecording.h +++ b/include/openspace/interaction/sessionrecording.h @@ -171,9 +171,9 @@ public: /** * Provides list of available playback files. - * \returns string of newline-delimited filenames in recordings dir. + * \returns vector of filenames in recordings dir. */ - std::string playbackList(); + std::vector playbackList() const; private: enum class RecordedType { diff --git a/include/openspace/rendering/renderable.h b/include/openspace/rendering/renderable.h index 390c3babb2..38563baa57 100644 --- a/include/openspace/rendering/renderable.h +++ b/include/openspace/rendering/renderable.h @@ -29,6 +29,7 @@ #include #include +#include namespace ghoul { class Dictionary; } namespace ghoul::opengl { @@ -91,6 +92,7 @@ public: protected: properties::BoolProperty _enabled; properties::FloatProperty _opacity; + properties::StringProperty _renderableType; void registerUpdateRenderBinFromOpacity(); diff --git a/modules/server/include/topics/sessionrecordingtopic.h b/modules/server/include/topics/sessionrecordingtopic.h index 96f496d598..96a0529ed1 100644 --- a/modules/server/include/topics/sessionrecordingtopic.h +++ b/modules/server/include/topics/sessionrecordingtopic.h @@ -41,12 +41,15 @@ public: private: const int UnsetOnChangeHandle = -1; - //Provides the idle/recording/playback state int value in json message - nlohmann::json state(); + bool _sendState; + bool _sendFiles; + // Provides the idle/recording/playback state int value in json message + void sendJsonData(); + + interaction::SessionRecording::SessionState _lastState; int _stateCallbackHandle = UnsetOnChangeHandle; bool _isDone = false; - interaction::SessionRecording::SessionState _lastState; }; } // namespace openspace diff --git a/modules/server/src/topics/getpropertytopic.cpp b/modules/server/src/topics/getpropertytopic.cpp index c1384f895a..21c1cb8a59 100644 --- a/modules/server/src/topics/getpropertytopic.cpp +++ b/modules/server/src/topics/getpropertytopic.cpp @@ -72,11 +72,6 @@ void GetPropertyTopic::handleJson(const nlohmann::json& json) { else if (requestedKey == RootPropertyOwner) { response = wrappedPayload(global::rootPropertyOwner); } - else if (requestedKey == SessionRecordingPlaybackList) { - std::string fileList = global::sessionRecording.playbackList(); - nlohmann::json getJson = { { SessionRecordingPlaybackList, fileList } }; - response = wrappedPayload(getJson); - } else { response = propertyFromKey(requestedKey); } diff --git a/modules/server/src/topics/sessionrecordingtopic.cpp b/modules/server/src/topics/sessionrecordingtopic.cpp index ce93fcafe0..ae5cfbd8bf 100644 --- a/modules/server/src/topics/sessionrecordingtopic.cpp +++ b/modules/server/src/topics/sessionrecordingtopic.cpp @@ -32,10 +32,14 @@ namespace { constexpr const char* _loggerCat = "SessionRecordingTopic"; - constexpr const char* PropertyKey = "property"; constexpr const char* EventKey = "event"; + constexpr const char* SubscribeEvent = "start_subscription"; constexpr const char* UnsubscribeEvent = "stop_subscription"; - constexpr const char* StateKey = "recState"; + constexpr const char* RefreshEvent = "refresh"; + + constexpr const char* PropertiesKey = "properties"; + constexpr const char* FilesKey = "files"; + constexpr const char* StateKey = "state"; } // namespace using nlohmann::json; @@ -59,37 +63,87 @@ bool SessionRecordingTopic::isDone() const { } void SessionRecordingTopic::handleJson(const nlohmann::json& json) { - std::string event = json.at(EventKey).get(); + using SessionRecording = openspace::interaction::SessionRecording; + + const std::string event = json.at(EventKey).get(); + if (event != SubscribeEvent && + event != UnsubscribeEvent && + event != RefreshEvent) + { + LERROR("Unsupported event."); + _isDone = true; + return; + } + if (event == UnsubscribeEvent) { _isDone = true; return; } - std::string requestedKey = json.at(PropertyKey).get(); - LDEBUG("Subscribing to " + requestedKey); - - if (requestedKey == StateKey) { - _stateCallbackHandle = global::sessionRecording.addStateChangeCallback( - [this]() { - openspace::interaction::SessionRecording::SessionState nowState = - global::sessionRecording.state(); - if (nowState != _lastState) { - _connection->sendJson(state()); - _lastState = nowState; - } + if (json.find(PropertiesKey) != json.end()) { + if (!json.at(PropertiesKey).is_array()) { + LERROR("Properties must be an array of strings."); + } + nlohmann::json requestedProperties = json.at(PropertiesKey).get(); + for (const auto& p : requestedProperties) { + if (!p.is_string()) { + _isDone = true; + LERROR("Properties must be an array of strings."); + return; } - ); - _connection->sendJson(state()); + const std::string v = p.get(); + if (v == FilesKey) { + _sendFiles = true; + } + if (v == StateKey) { + _sendState = true; + } + } } - else { - LWARNING("Cannot get " + requestedKey); - _isDone = true; + + sendJsonData(); + + if (event == SubscribeEvent) { + if (_sendState) { + _stateCallbackHandle = global::sessionRecording.addStateChangeCallback( + [this]() { + SessionRecording::SessionState currentState = + global::sessionRecording.state(); + if (currentState != _lastState) { + sendJsonData(); + _lastState = currentState; + } + } + ); + } } } -json SessionRecordingTopic::state() { - json statJson = { { "state", static_cast(global::sessionRecording.state()) } }; - return wrappedPayload(statJson); +void SessionRecordingTopic::sendJsonData() { + json stateJson; + using SessionRecording = openspace::interaction::SessionRecording; + if (_sendState) { + SessionRecording::SessionState state = global::sessionRecording.state(); + std::string stateString; + switch (state) { + case SessionRecording::SessionState::Recording: + stateString = "recording"; + break; + case SessionRecording::SessionState::Playback: + stateString = "playing"; + break; + default: + stateString = "idle"; + break; + } + stateJson[StateKey] = stateString; + }; + if (_sendFiles) { + stateJson[FilesKey] = global::sessionRecording.playbackList(); + } + if (stateJson.size() > 0) { + _connection->sendJson(wrappedPayload(stateJson)); + } } } // namespace openspace diff --git a/src/interaction/sessionrecording.cpp b/src/interaction/sessionrecording.cpp index 240a5945c3..ca43040f02 100644 --- a/src/interaction/sessionrecording.cpp +++ b/src/interaction/sessionrecording.cpp @@ -1297,19 +1297,20 @@ void SessionRecording::removeStateChangeCallback(CallbackHandle handle) { _stateChangeCallbacks.erase(it); } -std::string SessionRecording::playbackList() { - std::string fileList; +std::vector SessionRecording::playbackList() const { const std::string recordingsPath = absPath("${RECORDINGS}"); + std::vector fileList; ghoul::filesystem::Directory currentDir(recordingsPath); std::vector allInputFiles = currentDir.readFiles(); for (std::string f : allInputFiles) { - //Remove path and keep only the filename, and add newline after - fileList.append(f.substr(recordingsPath.length() + 1, (f.length() - recordingsPath.length()) - 1)); - fileList.append("\n"); + // Remove path and keep only the filename + fileList.push_back(f.substr( + recordingsPath.length() + 1, + f.length() - recordingsPath.length() - 1 + )); } - //Remove the final trailing newline from the list and return it. - return fileList.substr(0, fileList.size() - 1); + return fileList; } scripting::LuaLibrary SessionRecording::luaLibrary() { diff --git a/src/rendering/renderable.cpp b/src/rendering/renderable.cpp index cc1e12fac0..15baa05e51 100644 --- a/src/rendering/renderable.cpp +++ b/src/rendering/renderable.cpp @@ -46,6 +46,14 @@ namespace { "Transparency", "This value determines the transparency of this object." }; + + constexpr openspace::properties::Property::PropertyInfo RenderableTypeInfo = { + "Type", + "Renderable Type", + "This tells the type of the renderable.", + openspace::properties::Property::Visibility::Hidden + }; + } // namespace namespace openspace { @@ -95,10 +103,12 @@ std::unique_ptr Renderable::createFromDictionary( return result; } + Renderable::Renderable(const ghoul::Dictionary& dictionary) : properties::PropertyOwner({ "Renderable" }) , _enabled(EnabledInfo, true) , _opacity(OpacityInfo, 1.f, 0.f, 1.f) + , _renderableType(RenderableTypeInfo, "Renderable") { // I can't come up with a good reason not to do this for all renderables registerUpdateRenderBinFromOpacity(); @@ -128,6 +138,12 @@ Renderable::Renderable(const ghoul::Dictionary& dictionary) } addProperty(_enabled); + + //set type for UI + if (dictionary.hasKey(RenderableTypeInfo.identifier)) { + _renderableType = dictionary.value(RenderableTypeInfo.identifier); + } + addProperty(_renderableType); } void Renderable::initialize() {}