From 22735c5aaf439b73190b022df23295e110a04a29 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 12 May 2025 21:19:24 +0200 Subject: [PATCH] Add support for non-numerical values to the DashboardItemTimevaryingText (closes #3653) --- .../data/dummydata_mixed.json | 10 +++ .../timevaryingtext_mixed.asset | 17 ++++ .../timevaryingtext_styled.asset | 2 +- .../dashboarditemtimevaryingtext.cpp | 89 +++++++++++++++---- .../dashboard/dashboarditemtimevaryingtext.h | 48 +++++----- 5 files changed, 123 insertions(+), 43 deletions(-) create mode 100644 data/assets/examples/dashboarditem/dashboarditemtimevaryingtext/data/dummydata_mixed.json create mode 100644 data/assets/examples/dashboarditem/dashboarditemtimevaryingtext/timevaryingtext_mixed.asset diff --git a/data/assets/examples/dashboarditem/dashboarditemtimevaryingtext/data/dummydata_mixed.json b/data/assets/examples/dashboarditem/dashboarditemtimevaryingtext/data/dummydata_mixed.json new file mode 100644 index 0000000000..9e4734c38e --- /dev/null +++ b/data/assets/examples/dashboarditem/dashboarditemtimevaryingtext/data/dummydata_mixed.json @@ -0,0 +1,10 @@ +{ + "data": [ + [ "2024-05-10T00:00:00Z", 2.33 ], + [ "2024-05-10T03:00:00Z", true ], + [ "2024-05-10T06:00:00Z", "Test string" ], + [ "2024-05-10T09:00:00Z", { "a": 1.0, "b": 2.0 } ], + [ "2024-05-10T12:00:00Z", [ 1.0, 2.0, 3.0 ] ], + [ "2024-05-10T15:00:00Z", 3 ] + ] +} diff --git a/data/assets/examples/dashboarditem/dashboarditemtimevaryingtext/timevaryingtext_mixed.asset b/data/assets/examples/dashboarditem/dashboarditemtimevaryingtext/timevaryingtext_mixed.asset new file mode 100644 index 0000000000..f7409eae41 --- /dev/null +++ b/data/assets/examples/dashboarditem/dashboarditemtimevaryingtext/timevaryingtext_mixed.asset @@ -0,0 +1,17 @@ +-- Mixed +-- This example shows how to create a time-varying text dashboard item that is using a +-- mixed type of data entries in the `DataFile`. + +local Item = { + Type = "DashboardItemTimeVaryingText", + Identifier = "DashboardItemTimeVaryingText_Example_Mixed", + DataFile = asset.resource("data/dummydata_mixed.json"), +} + +asset.onInitialize(function() + openspace.dashboard.addDashboardItem(Item) +end) + +asset.onDeinitialize(function() + openspace.dashboard.removeDashboardItem(Item) +end) diff --git a/data/assets/examples/dashboarditem/dashboarditemtimevaryingtext/timevaryingtext_styled.asset b/data/assets/examples/dashboarditem/dashboarditemtimevaryingtext/timevaryingtext_styled.asset index 71f258da82..54b10c23f5 100644 --- a/data/assets/examples/dashboarditem/dashboarditemtimevaryingtext/timevaryingtext_styled.asset +++ b/data/assets/examples/dashboarditem/dashboarditemtimevaryingtext/timevaryingtext_styled.asset @@ -4,7 +4,7 @@ local Item = { Type = "DashboardItemTimeVaryingText", - Identifier = "DashboardItemTimeVaryingText_Example-Styled", + Identifier = "DashboardItemTimeVaryingText_Example_Styled", DataFile = asset.resource("data/dummydata.json"), FormatString = "Observed KP index: {}", FontSize = 40 diff --git a/modules/base/dashboard/dashboarditemtimevaryingtext.cpp b/modules/base/dashboard/dashboarditemtimevaryingtext.cpp index 84b07dc527..f539715570 100644 --- a/modules/base/dashboard/dashboarditemtimevaryingtext.cpp +++ b/modules/base/dashboard/dashboarditemtimevaryingtext.cpp @@ -50,8 +50,9 @@ namespace { openspace::properties::Property::Visibility::User }; - // This `DashboardItem` displays text based on the content of a provided data file. The - // value that is displayed depends on the current in-game simulation time. + // This `DashboardItem` displays text based on the content of a provided data file. + // The value that is displayed depends on the current in-game simulation time. + // // The JSON must contain a 'data' array with timestamp-value pairs. Example format: // {\"data\": [[\"2024-05-10T00:00:00Z\", 2.33], [\"2024-05-10T03:00:00Z\", 3.0]]} struct [[codegen::Dictionary(DashboardItemTimeVaryingText)]] Parameters { @@ -59,7 +60,7 @@ namespace { std::optional formatString; // [[codegen::verbatim(DataFileInfo.description)]] - std::string dataFile; + std::filesystem::path dataFile; }; #include "dashboarditemtimevaryingtext_codegen.cpp" } // namespace @@ -84,14 +85,9 @@ DashboardItemTimeVaryingText::DashboardItemTimeVaryingText( _formatString = p.formatString.value_or(_formatString); addProperty(_formatString); - _dataFile = absPath(p.dataFile).string(); + _dataFile.onChange([this]() { loadDataFromJson(_dataFile); }); + _dataFile = p.dataFile.string(); addProperty(_dataFile); - - _dataFile.onChange([this]() { - loadDataFromJson(_dataFile); - }); - - loadDataFromJson(_dataFile); } void DashboardItemTimeVaryingText::update() { @@ -109,14 +105,70 @@ void DashboardItemTimeVaryingText::update() { if (newIdx != _activeTriggerTimeIndex) { _activeTriggerTimeIndex = newIdx; double timeKey = _startTimes[_activeTriggerTimeIndex]; - double value = _data[timeKey]; - - std::ostringstream oss; - oss << value; - std::string valueString = oss.str(); + const nlohmann::json value = _data[timeKey]; try { - _buffer = std::vformat(_formatString.value(), - std::make_format_args(valueString)); + switch (value.type()) { + case nlohmann::json::value_t::null: + case nlohmann::json::value_t::discarded: + break; + case nlohmann::json::value_t::boolean: { + const bool v = value.get(); + _buffer = std::vformat( + _formatString.value(), + std::make_format_args(v) + ); + break; + } + case nlohmann::json::value_t::string: { + const std::string v = value.get(); + _buffer = std::vformat( + _formatString.value(), + std::make_format_args(v) + ); + break; + } + case nlohmann::json::value_t::number_integer: { + const int v = value.get(); + _buffer = std::vformat( + _formatString.value(), + std::make_format_args(v) + ); + break; + } + case nlohmann::json::value_t::number_unsigned: { + const unsigned v = value.get(); + _buffer = std::vformat( + _formatString.value(), + std::make_format_args(v) + ); + break; + } + case nlohmann::json::value_t::number_float: { + const double v = value.get(); + _buffer = std::vformat( + _formatString.value(), + std::make_format_args(v) + ); + break; + } + case nlohmann::json::value_t::object: + case nlohmann::json::value_t::array: { + const std::string v = nlohmann::to_string(value); + _buffer = std::vformat( + _formatString.value(), + std::make_format_args(v) + ); + break; + } + case nlohmann::json::value_t::binary: { + LWARNINGC( + "DashboardItemTimeVaryingText", + "Binary data is not supported" + ); + break; + } + } + } catch (const std::format_error&) { LERRORC("DashboardItemTimeVaryingText", "Illegal format string"); @@ -154,8 +206,7 @@ void DashboardItemTimeVaryingText::loadDataFromJson(const std::string& filePath) for (const nlohmann::json& item : jsonData["data"]) { const std::string& timeString = item[0].get(); double j2000Time = Time::convertTime(timeString); - double value = item[1].get(); - _data[j2000Time] = value; + _data[j2000Time] = item[1]; _startTimes.push_back(j2000Time); } diff --git a/modules/base/dashboard/dashboarditemtimevaryingtext.h b/modules/base/dashboard/dashboarditemtimevaryingtext.h index dda5efba25..80a4f330de 100644 --- a/modules/base/dashboard/dashboarditemtimevaryingtext.h +++ b/modules/base/dashboard/dashboarditemtimevaryingtext.h @@ -22,40 +22,42 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ - #ifndef __OPENSPACE_MODULE_BASE___DASHBOARDITEMTIMEVARYINGTEXT___H__ - #define __OPENSPACE_MODULE_BASE___DASHBOARDITEMTIMEVARYINGTEXT___H__ +#ifndef __OPENSPACE_MODULE_BASE___DASHBOARDITEMTIMEVARYINGTEXT___H__ +#define __OPENSPACE_MODULE_BASE___DASHBOARDITEMTIMEVARYINGTEXT___H__ - #include +#include - #include +#include +#include - namespace openspace { +namespace openspace { - namespace documentation { struct Documentation; } +namespace documentation { struct Documentation; } - class DashboardItemTimeVaryingText : public DashboardTextItem { - public: - explicit DashboardItemTimeVaryingText(const ghoul::Dictionary& dictionary); - ~DashboardItemTimeVaryingText() override = default; +class DashboardItemTimeVaryingText : public DashboardTextItem { +public: + explicit DashboardItemTimeVaryingText(const ghoul::Dictionary& dictionary); + ~DashboardItemTimeVaryingText() override = default; - void update() override; + void update() override; - static documentation::Documentation Documentation(); + static documentation::Documentation Documentation(); - private: - void loadDataFromJson(const std::string& filePath); - void computeSequenceEndTime(); - int updateActiveTriggerTimeIndex(double currentTime) const; +private: + void loadDataFromJson(const std::string& filePath); + void computeSequenceEndTime(); + int updateActiveTriggerTimeIndex(double currentTime) const; - properties::StringProperty _formatString; - properties::StringProperty _dataFile; + properties::StringProperty _formatString; + properties::StringProperty _dataFile; - std::unordered_map _data; - std::vector _startTimes; + std::unordered_map _data; + std::vector _startTimes; - int _activeTriggerTimeIndex = -1; - double _sequenceEndTime = 0.0; + int _activeTriggerTimeIndex = -1; + double _sequenceEndTime = 0.0; }; - } // namespace openspace + +} // namespace openspace #endif // __OPENSPACE_MODULE_BASE___DASHBOARDITEMTIMEVARYINGTEXT___H__