Add first draft of property tree topic

This commit is contained in:
Ylva Selling
2026-01-20 11:33:14 +01:00
parent 31badffa39
commit 516504f7d2
11 changed files with 221 additions and 0 deletions

View File

@@ -60,6 +60,7 @@ public:
void handleJson(const nlohmann::json& json);
void sendJson(const nlohmann::json& json);
void setAuthorized(bool status);
Topic* findTopicByType(const std::string& type);
bool isAuthorized() const;

View File

@@ -66,6 +66,8 @@ public:
CallbackHandle addPreSyncCallback(CallbackFunction cb);
void removePreSyncCallback(CallbackHandle handle);
void passDataToTopic(const std::string& topic, const nlohmann::json& jsonData);
static documentation::Documentation Documentation();
private:

View File

@@ -0,0 +1,58 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2025 *
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_CORE___PROPERTYTREE_TOPIC___H__
#define __OPENSPACE_CORE___PROPERTYTREE_TOPIC___H__
#include <openspace/topic/topics/topic.h>
namespace openspace::properties { class Property; }
namespace openspace {
class PropertyTreeTopic : public Topic {
public:
PropertyTreeTopic() = default;
~PropertyTreeTopic() override;
void handleJson(const nlohmann::json& json) override;
bool isDone() const override;
std::string type() const override;
private:
void resetCallbacks();
const int UnsetCallbackHandle = -1;
bool _requestedResourceIsSubscribable = false;
bool _isSubscribedTo = false;
int _onChangeHandle = UnsetCallbackHandle;
int _onDeleteHandle = UnsetCallbackHandle;
int _onMetaDataChangeHandle = UnsetCallbackHandle;
properties::Property* _prop = nullptr;
};
} // namespace openspace
#endif // __OPENSPACE_CORE___PROPERTYTREE_TOPIC___H__

View File

@@ -41,6 +41,7 @@ public:
int code = 500);
virtual void handleJson(const nlohmann::json& json) = 0;
virtual bool isDone() const = 0;
virtual std::string type() const;
protected:
size_t _topicId = 0;

View File

@@ -190,6 +190,7 @@ set(OPENSPACE_SOURCE
topic/topics/luascripttopic.cpp
topic/topics/missiontopic.cpp
topic/topics/profiletopic.cpp
topic/topics/propertytreetopic.cpp
topic/topics/sessionrecordingtopic.cpp
topic/topics/setpropertytopic.cpp
topic/topics/subscriptiontopic.cpp
@@ -416,6 +417,7 @@ set(OPENSPACE_HEADER
${PROJECT_SOURCE_DIR}/include/openspace/topic/topics/sessionrecordingtopic.h
${PROJECT_SOURCE_DIR}/include/openspace/topic/topics/setpropertytopic.h
${PROJECT_SOURCE_DIR}/include/openspace/topic/topics/subscriptiontopic.h
${PROJECT_SOURCE_DIR}/include/openspace/topic/topics/propertytreetopic.h
${PROJECT_SOURCE_DIR}/include/openspace/topic/topics/timetopic.h
${PROJECT_SOURCE_DIR}/include/openspace/topic/topics/skybrowsertopic.h
${PROJECT_SOURCE_DIR}/include/openspace/topic/topics/topic.h

View File

@@ -134,6 +134,14 @@ void create() {
memoryManager = new MemoryManager;
#endif // WIN32
#ifdef WIN32
topicManager = new (currentPos) TopicManager;
ghoul_assert(topicManager, "No topicManager");
currentPos += sizeof(TopicManager);
#else // ^^^ WIN32 / !WIN32 vvv
topicManager = new TopicManager;
#endif // WIN32
#ifdef WIN32
openSpaceEngine = new (currentPos) OpenSpaceEngine;
ghoul_assert(openSpaceEngine, "No openSpaceEngine");
@@ -673,6 +681,13 @@ void destroy() {
delete openSpaceEngine;
#endif // WIN32
LDEBUGC("Globals", "Destroying 'TopicManager'");
#ifdef WIN32
topicManager->~TopicManager();
#else // ^^^ WIN32 / !WIN32 vvv
delete topicManager;
#endif // WIN32
LDEBUGC("Globals", "Destroying 'MemoryManager'");
#ifdef WIN32
memoryManager->~MemoryManager();

View File

@@ -25,6 +25,7 @@
#include <openspace/properties/property.h>
#include <openspace/engine/globals.h>
#include <openspace/topic/topicmanager.h>
#include <openspace/events/eventengine.h>
#include <openspace/properties/propertyowner.h>
#include <ghoul/logging/logmanager.h>
@@ -252,6 +253,14 @@ void Property::notifyChangeListeners() {
for (const std::pair<OnChangeHandle, std::function<void()>>& p : _onChangeCallbacks) {
p.second();
}
nlohmann::json payload;
payload["event"] = "property_changed";
payload["payload"] = {
{ "property", uri() },
{ "value", nlohmann::json::parse(jsonValue()) }
};
global::topicManager->passDataToTopic("propertyTree", payload);
}
void Property::notifyMetaDataChangeListeners() {

View File

@@ -42,6 +42,7 @@
#include <openspace/topic/topics/setpropertytopic.h>
#include <openspace/topic/topics/actionkeybindtopic.h>
#include <openspace/topic/topics/skybrowsertopic.h>
#include <openspace/topic/topics/propertytreetopic.h>
#include <openspace/topic/topics/subscriptiontopic.h>
#include <openspace/topic/topics/timetopic.h>
#include <openspace/topic/topics/topic.h>
@@ -109,6 +110,7 @@ Connection::Connection(std::unique_ptr<ghoul::io::Socket> s, std::string address
_topicFactory.registerClass<TimeTopic>("time");
_topicFactory.registerClass<TriggerPropertyTopic>("trigger");
_topicFactory.registerClass<VersionTopic>("version");
_topicFactory.registerClass<PropertyTreeTopic>("propertyTree");
}
void Connection::handleMessage(const std::string& message) {
@@ -246,4 +248,20 @@ void Connection::setAuthorized(bool status) {
_isAuthorized = status;
}
Topic* Connection::findTopicByType(const std::string& type) {
const auto it = std::find_if(
_topics.begin(),
_topics.end(),
[&type](const auto& pair) {
//LINFO(pair.second->type());
return pair.second->type() == type;
});
if (it == _topics.end()) {
return nullptr;
}
return it->second.get();
}
} // namespace openspace

View File

@@ -256,4 +256,13 @@ void TopicManager::removePreSyncCallback(CallbackHandle handle) {
_preSyncCallbacks.erase(it);
}
void TopicManager::passDataToTopic(const std::string& topicType,
const nlohmann::json& jsonData) {
for (const ConnectionData& connectionData : _connections) {
if (auto topic = connectionData.connection->findTopicByType(topicType)) {
topic->handleJson(jsonData);
}
}
}
} // namespace openspace

View File

@@ -0,0 +1,102 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2025 *
* *
* 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 <openspace/topic/topics/propertytreetopic.h>
#include <openspace/engine/globals.h>
#include <openspace/topic/connection.h>
#include <openspace/topic/jsonconverters.h>
#include <openspace/properties/property.h>
#include <openspace/query/query.h>
#include <openspace/util/timemanager.h>
#include <ghoul/format.h>
#include <ghoul/logging/logmanager.h>
namespace {
constexpr std::string_view _loggerCat = "PropertyTreeTopic";
constexpr std::string_view StartSubscription = "start_subscription";
constexpr std::string_view StopSubscription = "stop_subscription";
constexpr std::string_view PropertyChanged = "property_changed";
} // namespace
using nlohmann::json;
namespace openspace {
PropertyTreeTopic::~PropertyTreeTopic() {
resetCallbacks();
}
bool PropertyTreeTopic::isDone() const {
return !_requestedResourceIsSubscribable || !_isSubscribedTo;
}
std::string PropertyTreeTopic::type() const {
return "propertyTree";
}
void PropertyTreeTopic::resetCallbacks() {
if (!_prop) {
return;
}
if (_onChangeHandle != UnsetCallbackHandle) {
_prop->removeOnChange(_onChangeHandle);
_onChangeHandle = UnsetCallbackHandle;
}
if (_onMetaDataChangeHandle != UnsetCallbackHandle) {
_prop->removeOnMetaDataChange(_onMetaDataChangeHandle);
_onMetaDataChangeHandle = UnsetCallbackHandle;
}
if (_onDeleteHandle != UnsetCallbackHandle) {
_prop->removeOnDelete(_onDeleteHandle);
_onDeleteHandle = UnsetCallbackHandle;
}
}
void PropertyTreeTopic::handleJson(const nlohmann::json& json) {
const std::string& event = json.at("event").get<std::string>();
if (event == StartSubscription) {
nlohmann::json data = {
{ "event", "root" },
{ "payload", global::rootPropertyOwner }
};
_connection->sendJson(wrappedPayload(data));
_isSubscribedTo = true;
_requestedResourceIsSubscribable = true;
}
if (event == StopSubscription) {
_isSubscribedTo = false;
resetCallbacks();
}
if (event == PropertyChanged) {
const nlohmann::json& payload = json.at("payload").get<nlohmann::json>();
_connection->sendJson(wrappedPayload(payload));
}
}
} // namespace openspace

View File

@@ -35,6 +35,10 @@ void Topic::initialize(std::shared_ptr<Connection> connection, size_t topicId) {
_topicId = topicId;
}
std::string Topic::type() const {
return "";
}
nlohmann::json Topic::wrappedPayload(const nlohmann::json& payload) const {
ZoneScoped;