From 450b101cd5beacb589d6f4616ee3edac6731bf69 Mon Sep 17 00:00:00 2001 From: GPayne Date: Tue, 28 Sep 2021 20:35:53 -0600 Subject: [PATCH 01/15] Adding support for lua table as a possible profile properties value --- include/openspace/scene/scene.h | 43 +++++++++++ src/scene/scene.cpp | 123 +++++++++++++++++++++++++++++--- src/scene/scene_lua.inl | 19 +++++ 3 files changed, 177 insertions(+), 8 deletions(-) diff --git a/include/openspace/scene/scene.h b/include/openspace/scene/scene.h index e199f1f425..a7f6cba489 100644 --- a/include/openspace/scene/scene.h +++ b/include/openspace/scene/scene.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -46,6 +47,14 @@ namespace openspace { namespace documentation { struct Documentation; } namespace scripting { struct LuaLibrary; } +enum class PropertyValueType { + Boolean = 0, + Float, + String, + Table, + Nil +}; + class SceneInitializer; // Notifications: @@ -289,6 +298,40 @@ private: void propertyPushValueFromProfileToLuaState(ghoul::lua::LuaState& L, const std::string& value); +/** + * Accepts string version of a property value from a profile, and processes it + * according to the data type of the value + * + * \param L the lua state to (eventually) push to + * \param value string representation of the value with which to set property + * \param pushFn the std::function provided for pushing the result, which may be + * a lambda that pushes to the lua state, or a lambda that pushes + * to a vector (the vector will eventually be pushed to a lua table) + */ +void propertyProcessValue(ghoul::lua::LuaState& L, std::string& value, + std::functionpushFn); + +/** + * Accepts string version of a property value from a profile, and returns the + * supported data types that can be pushed to a lua state. Currently, the full + * range of possible lua values is not supported. + * + * \param value string representation of the value with which to set property + */ +PropertyValueType getPropertyValueType(std::string& value); + +/** + * Accepts string version of a property value from a profile, and adds it to a vector + * which will later be used to push as a lua table containing values of type T + * + * \param L the lua state to (eventually) push to + * \param value string representation of the value with which to set property + * \param table the std::vector container which has elements of type T for a lua table + */ +template +void processPropertyValueTableEntries(ghoul::lua::LuaState& L, std::string& value, + std::vector& table); + } // namespace openspace #endif // __OPENSPACE_CORE___SCENE___H__ diff --git a/src/scene/scene.cpp b/src/scene/scene.cpp index b9797c2c73..12833bade7 100644 --- a/src/scene/scene.cpp +++ b/src/scene/scene.cpp @@ -631,21 +631,128 @@ void Scene::setPropertiesFromProfile(const Profile& p) { } } +template void propertyPushValueFromProfileToLuaState(ghoul::lua::LuaState& L, - const std::string& value) + std::string& value) { + propertyProcessValue( + L, + value, + [&](T resultValue) { + ghoul::lua::push(L, resultValue); + } + ); +} + +template +void propertyProcessValue(ghoul::lua::LuaState& L, std::string& value, + std::functionpushFn) +{ + PropertyValueType pType = getPropertyValueType(value); + switch (pType) { + case PropertyValueType::Boolean: + (value == "true") ? pushFn(true) : pushFn(false); + break; + + case PropertyValueType::Float: + pushFn(L, std::stof(value)); + break; + + case PropertyValueType::Nil: + ghoul::lua::nil_t n; + pushFn(n); + break; + + case PropertyValueType::Table: + std::string nextValue = value; + size_t commaPos = value.find(',', commaPos); + if (commaPos != std::string::npos) { + nextValue = value.substr(1, commaPos); + } + PropertyValueType enclosedType = getPropertyValueType(nextValue); + switch (enclosedType) { + case PropertyValueType::Boolean: + std::vector valsB; + processPropertyValueTableEntries(L, value, valsB); + pushFn(valsB); + break; + + case PropertyValueType::Float: + std::vector valsF; + processPropertyValueTableEntries(L, value, valsF); + pushFn(valsF); + break; + + case PropertyValueType::Nil: + std::vector valsN; + processPropertyValueTableEntries(L, value, valsN); + pushFn(valsN); + break; + + case PropertyValueType::String: + std::vector valsS; + processPropertyValueTableEntries(L, value, valsS); + pushFn(valsS); + break; + + case PropertyValueType::Table: + default: + LERROR("Table-within-a-table values are not supported for profile property"); + break; + } + break; + + default: + value.insert(0, "[["); + value.append("]]"); + pushFn(value); + break; + } +} + +template +void processPropertyValueTableEntries(ghoul::lua::LuaState& L, std::string& value, + std::vector& table) +{ + size_t commaPos = 0; + size_t prevPos = 0; + std::string nextValue; + while (commaPos != std::string::npos) { + commaPos = value.find(',', commaPos); + if (commaPos != std::string::npos) { + nextValue = value.substr(prevPos, commaPos); + prevPos = commaPos + 1; + } + else { + nextValue = value.substr(prevPos); + } + propertyProcessValue(L, nextValue, [&](T val){table.push_back(val);}); + } +} + +PropertyValueType getPropertyValueType(std::string& value) { + //First trim spaces from front and back of string + while (value.front() == ' ') { + value.erase(0, 1); + } + while (value.back() == ' ') { + value.pop_back(); + } + if (luascriptfunctions::isBoolValue(value)) { - ghoul::lua::push(L, (value == "true") ? true : false); + return PropertyValueType::Boolean; } else if (luascriptfunctions::isFloatValue(value)) { - ghoul::lua::push(L, std::stof(value)); + return PropertyValueType::Float; + } + else if (luascriptfunctions::isNilValue(value)) { + return PropertyValueType::Nil; + } + else if (luascriptfunctions::isTableValue(value)) { + return PropertyValueType::Table; } else { - std::string stringRepresentation = value; - if (value.compare("nil") != 0) { - stringRepresentation = "[[" + stringRepresentation + "]]"; - } - ghoul::lua::push(L, stringRepresentation); + return PropertyValueType::String; } } diff --git a/src/scene/scene_lua.inl b/src/scene/scene_lua.inl index 8248d2973d..721394187f 100644 --- a/src/scene/scene_lua.inl +++ b/src/scene/scene_lua.inl @@ -923,4 +923,23 @@ bool isFloatValue(const std::string& s) { } } +/** + * \ingroup LuaScripts + * isNilValue(const std::string& s): + * Used to check if a string is a lua 'nil' value. Returns false if not. + */ +bool isNilValue(const std::string& s) { + return (s == "nil"); +} + +/** + * \ingroup LuaScripts + * isTableValue(const std::string& s): + * Used to check if a string contains a lua table rather than an individual value. + * Returns false if not. + */ +bool isTableValue(const std::string& s) { + return ((s.front() == '{') && (s.back() == '}')); +} + } // namespace openspace::luascriptfunctions From 9464530cdd644c3dbb63b97f5f3fa30288978e1d Mon Sep 17 00:00:00 2001 From: GPayne Date: Fri, 1 Oct 2021 16:44:20 -0600 Subject: [PATCH 02/15] Changes to get lua table entries working using variant type --- include/openspace/scene/scene.h | 101 ++++++++++-------- src/scene/scene.cpp | 177 ++++++++++++++++++++------------ src/scene/scene_lua.inl | 10 +- 3 files changed, 177 insertions(+), 111 deletions(-) diff --git a/include/openspace/scene/scene.h b/include/openspace/scene/scene.h index a7f6cba489..fa0d25cb3e 100644 --- a/include/openspace/scene/scene.h +++ b/include/openspace/scene/scene.h @@ -54,6 +54,7 @@ enum class PropertyValueType { Table, Nil }; +typedef std::variant ProfilePropertyLua; class SceneInitializer; @@ -255,6 +256,60 @@ public: void setPropertiesFromProfile(const Profile& p); private: + /** + * Accepts string version of a property value from a profile, converts it to the + * appropriate type, and then pushes the value onto the lua state. + * + * \param L the lua state to push value to + * \param value string representation of the value with which to set property + */ + void propertyPushValueFromProfileToLuaState(ghoul::lua::LuaState& L, + std::string& value); + + /** + * Accepts string version of a property value from a profile, and processes it + * according to the data type of the value + * + * \param L the lua state to (eventually) push to + * \param value string representation of the value with which to set property + * \param didPushToLua Bool reference that represents the lua push state at the end + * of this function call. This will be set to true if the value (e.g. table) + * has already been pushed to the lua stack + * \return The ProfilePropertyLua variant type translated from string representation + */ + ProfilePropertyLua propertyProcessValue(ghoul::lua::LuaState& L, + std::string& value, bool& didPushToLua); + + /** + * Accepts string version of a property value from a profile, and returns the + * supported data types that can be pushed to a lua state. Currently, the full + * range of possible lua values is not supported. + * + * \param value string representation of the value with which to set property + */ + PropertyValueType getPropertyValueType(std::string& value); + + /** + * Accepts string version of a property value from a profile, and adds it to a vector + * which will later be used to push as a lua table containing values of type T + * + * \param L the lua state to (eventually) push to + * \param value string representation of the value with which to set property + * \param table the std::vector container which has elements of type T for a lua table + */ + template + void processPropertyValueTableEntries(ghoul::lua::LuaState& L, std::string& value, + std::vector& table); + + /** + * Handles a lua table entry, creating a vector of the correct variable type based + * on the profile string, and pushes this vector to the lua stack. + * + * \param L the lua state to (eventually) push to + * \param value string representation of the value with which to set property + */ + void handlePropertyLuaTableEntry(ghoul::lua::LuaState& L, std::string& value); + /** * Update dependencies. */ @@ -269,7 +324,7 @@ private: bool _dirtyNodeRegistry = false; SceneGraphNode _rootDummy; std::unique_ptr _initializer; - + std::string _profilePropertyName; std::vector _interestingTimes; std::mutex _programUpdateLock; @@ -288,49 +343,7 @@ private: ghoul::MemoryPool<4096> _memoryPool; }; -/** - * Accepts string version of a property value from a profile, converts it to the - * appropriate type, and then pushes the value onto the lua state. - * - * \param L the lua state to push value to - * \param value string representation of the value with which to set property - */ -void propertyPushValueFromProfileToLuaState(ghoul::lua::LuaState& L, - const std::string& value); - -/** - * Accepts string version of a property value from a profile, and processes it - * according to the data type of the value - * - * \param L the lua state to (eventually) push to - * \param value string representation of the value with which to set property - * \param pushFn the std::function provided for pushing the result, which may be - * a lambda that pushes to the lua state, or a lambda that pushes - * to a vector (the vector will eventually be pushed to a lua table) - */ -void propertyProcessValue(ghoul::lua::LuaState& L, std::string& value, - std::functionpushFn); - -/** - * Accepts string version of a property value from a profile, and returns the - * supported data types that can be pushed to a lua state. Currently, the full - * range of possible lua values is not supported. - * - * \param value string representation of the value with which to set property - */ -PropertyValueType getPropertyValueType(std::string& value); - -/** - * Accepts string version of a property value from a profile, and adds it to a vector - * which will later be used to push as a lua table containing values of type T - * - * \param L the lua state to (eventually) push to - * \param value string representation of the value with which to set property - * \param table the std::vector container which has elements of type T for a lua table - */ -template -void processPropertyValueTableEntries(ghoul::lua::LuaState& L, std::string& value, - std::vector& table); +void trimSurroundingCharacters(std::string& valueString, const char c); } // namespace openspace diff --git a/src/scene/scene.cpp b/src/scene/scene.cpp index 12833bade7..5f4073c5f3 100644 --- a/src/scene/scene.cpp +++ b/src/scene/scene.cpp @@ -73,6 +73,9 @@ namespace { } } #endif // TRACY_ENABLE + + template struct overloaded : Ts... { using Ts::operator()...; }; + template overloaded(Ts...)->overloaded; } // namespace namespace openspace { @@ -613,10 +616,14 @@ void Scene::setPropertiesFromProfile(const Profile& p) { // Remove group name from start of regex and replace with '*' uriOrRegex = removeGroupNameFromUri(uriOrRegex); } + _profilePropertyName = uriOrRegex; ghoul::lua::push(L, uriOrRegex); ghoul::lua::push(L, 0.0); + + std::string workingValue = prop.value; + trimSurroundingCharacters(workingValue, ' '); // Later functions expect the value to be at the last position on the stack - propertyPushValueFromProfileToLuaState(L, prop.value); + propertyPushValueFromProfileToLuaState(L, workingValue); applyRegularExpression( L, @@ -631,114 +638,145 @@ void Scene::setPropertiesFromProfile(const Profile& p) { } } -template -void propertyPushValueFromProfileToLuaState(ghoul::lua::LuaState& L, - std::string& value) +void Scene::propertyPushValueFromProfileToLuaState(ghoul::lua::LuaState& L, + std::string& value) { - propertyProcessValue( - L, - value, - [&](T resultValue) { - ghoul::lua::push(L, resultValue); - } - ); + bool alreadyPushedToLua = false; + ProfilePropertyLua elem = propertyProcessValue(L, value, alreadyPushedToLua); + if (!alreadyPushedToLua) { + std::visit(overloaded{ + [&L](const bool& value) { + ghoul::lua::push(L, value); + }, + [&L](const float& value) { + ghoul::lua::push(L, value); + }, + [&L](const std::string& value) { + ghoul::lua::push(L, value); + }, + [&L](const ghoul::lua::nil_t& nilValue) { + ghoul::lua::push(L, nilValue); + } + }, elem); + } } -template -void propertyProcessValue(ghoul::lua::LuaState& L, std::string& value, - std::functionpushFn) +ProfilePropertyLua Scene::propertyProcessValue(ghoul::lua::LuaState& L,std::string& value, + bool& didPushToLua) { + ProfilePropertyLua result; PropertyValueType pType = getPropertyValueType(value); switch (pType) { case PropertyValueType::Boolean: - (value == "true") ? pushFn(true) : pushFn(false); + result = (value == "true") ? true : false; break; case PropertyValueType::Float: - pushFn(L, std::stof(value)); + result = std::stof(value); break; case PropertyValueType::Nil: ghoul::lua::nil_t n; - pushFn(n); + result = n; break; case PropertyValueType::Table: - std::string nextValue = value; - size_t commaPos = value.find(',', commaPos); - if (commaPos != std::string::npos) { - nextValue = value.substr(1, commaPos); - } - PropertyValueType enclosedType = getPropertyValueType(nextValue); - switch (enclosedType) { - case PropertyValueType::Boolean: - std::vector valsB; - processPropertyValueTableEntries(L, value, valsB); - pushFn(valsB); - break; + trimSurroundingCharacters(value, '{'); + trimSurroundingCharacters(value, '}'); + handlePropertyLuaTableEntry(L, value); + didPushToLua = true; + break; - case PropertyValueType::Float: + case PropertyValueType::String: + default: + std::string newValue = value; + newValue.insert(0, "[["); + newValue.append("]]"); + result = newValue; + break; + } + return result; +} + +void Scene::handlePropertyLuaTableEntry(ghoul::lua::LuaState& L, std::string& value) { + std::string firstValue; + size_t commaPos = 0; + commaPos = value.find(',', commaPos); + if (commaPos != std::string::npos) { + firstValue = value.substr(0, commaPos); + } + else { + firstValue = value; + } + + PropertyValueType enclosedType = getPropertyValueType(firstValue); + switch (enclosedType) { + case PropertyValueType::Boolean: + LERROR(fmt::format( + "A lua table of bool values is not supported. (processing property {})", + _profilePropertyName) + ); + break; + + case PropertyValueType::Float: + { std::vector valsF; processPropertyValueTableEntries(L, value, valsF); - pushFn(valsF); - break; - - case PropertyValueType::Nil: - std::vector valsN; - processPropertyValueTableEntries(L, value, valsN); - pushFn(valsN); - break; - - case PropertyValueType::String: - std::vector valsS; - processPropertyValueTableEntries(L, value, valsS); - pushFn(valsS); - break; - - case PropertyValueType::Table: - default: - LERROR("Table-within-a-table values are not supported for profile property"); - break; + ghoul::lua::push(L, valsF); } break; + case PropertyValueType::String: + { + std::vector valsS; + processPropertyValueTableEntries(L, value, valsS); + ghoul::lua::push(L, valsS); + } + break; + + case PropertyValueType::Table: default: - value.insert(0, "[["); - value.append("]]"); - pushFn(value); + LERROR(fmt::format( + "Table-within-a-table values are not supported for profile a " + "property (processing property {})", _profilePropertyName) + ); break; } } template -void processPropertyValueTableEntries(ghoul::lua::LuaState& L, std::string& value, +void Scene::processPropertyValueTableEntries(ghoul::lua::LuaState& L, std::string& value, std::vector& table) { size_t commaPos = 0; size_t prevPos = 0; std::string nextValue; while (commaPos != std::string::npos) { - commaPos = value.find(',', commaPos); + commaPos = value.find(',', prevPos); if (commaPos != std::string::npos) { - nextValue = value.substr(prevPos, commaPos); + nextValue = value.substr(prevPos, commaPos - prevPos); prevPos = commaPos + 1; } else { nextValue = value.substr(prevPos); } - propertyProcessValue(L, nextValue, [&](T val){table.push_back(val);}); + trimSurroundingCharacters(nextValue, ' '); + bool alreadyPushedToLua = false; + ProfilePropertyLua tableElement = propertyProcessValue(L, nextValue, + alreadyPushedToLua); + try { + table.push_back(std::get(tableElement)); + } + catch (std::bad_variant_access& e) { + LERROR(fmt::format( + "Error attempting to parse profile property setting for " + "{} using value = {}", _profilePropertyName, value) + ); + } } } -PropertyValueType getPropertyValueType(std::string& value) { - //First trim spaces from front and back of string - while (value.front() == ' ') { - value.erase(0, 1); - } - while (value.back() == ' ') { - value.pop_back(); - } - +PropertyValueType Scene::getPropertyValueType(std::string& value) { if (luascriptfunctions::isBoolValue(value)) { return PropertyValueType::Boolean; } @@ -756,6 +794,15 @@ PropertyValueType getPropertyValueType(std::string& value) { } } +void trimSurroundingCharacters(std::string& valueString, const char c) { + while (valueString.front() == c) { + valueString.erase(0, 1); + } + while (valueString.back() == c) { + valueString.pop_back(); + } +} + scripting::LuaLibrary Scene::luaLibrary() { return { "", diff --git a/src/scene/scene_lua.inl b/src/scene/scene_lua.inl index 721394187f..32a8d9327d 100644 --- a/src/scene/scene_lua.inl +++ b/src/scene/scene_lua.inl @@ -915,8 +915,14 @@ bool isBoolValue(const std::string& s) { */ bool isFloatValue(const std::string& s) { try { - float converted = std::stof(s); - return true; + float converted = std::numeric_limits::min(); + converted = std::stof(s); + if (converted != std::numeric_limits::min()) { + return true; + } + else { + return false; + } } catch (...) { return false; From 80546313fd575542f5e785f0bede723c049908d8 Mon Sep 17 00:00:00 2001 From: GPayne Date: Sun, 3 Oct 2021 21:03:32 -0600 Subject: [PATCH 03/15] Fixed handling of strings with quotes or brackets, and better table push --- include/openspace/scene/scene.h | 7 +++---- src/scene/scene.cpp | 31 ++++++++++++++----------------- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/include/openspace/scene/scene.h b/include/openspace/scene/scene.h index fa0d25cb3e..979ba119c4 100644 --- a/include/openspace/scene/scene.h +++ b/include/openspace/scene/scene.h @@ -263,8 +263,7 @@ private: * \param L the lua state to push value to * \param value string representation of the value with which to set property */ - void propertyPushValueFromProfileToLuaState(ghoul::lua::LuaState& L, - std::string& value); + void propertyPushProfileValueToLua(ghoul::lua::LuaState& L, std::string& value); /** * Accepts string version of a property value from a profile, and processes it @@ -277,8 +276,7 @@ private: * has already been pushed to the lua stack * \return The ProfilePropertyLua variant type translated from string representation */ - ProfilePropertyLua propertyProcessValue(ghoul::lua::LuaState& L, - std::string& value, bool& didPushToLua); + ProfilePropertyLua propertyProcessValue(ghoul::lua::LuaState& L, std::string& value); /** * Accepts string version of a property value from a profile, and returns the @@ -326,6 +324,7 @@ private: std::unique_ptr _initializer; std::string _profilePropertyName; std::vector _interestingTimes; + bool _valueIsTable = false; std::mutex _programUpdateLock; std::set _programsToUpdate; diff --git a/src/scene/scene.cpp b/src/scene/scene.cpp index 5f4073c5f3..d13ecab35d 100644 --- a/src/scene/scene.cpp +++ b/src/scene/scene.cpp @@ -623,7 +623,7 @@ void Scene::setPropertiesFromProfile(const Profile& p) { std::string workingValue = prop.value; trimSurroundingCharacters(workingValue, ' '); // Later functions expect the value to be at the last position on the stack - propertyPushValueFromProfileToLuaState(L, workingValue); + propertyPushProfileValueToLua(L, workingValue); applyRegularExpression( L, @@ -638,12 +638,11 @@ void Scene::setPropertiesFromProfile(const Profile& p) { } } -void Scene::propertyPushValueFromProfileToLuaState(ghoul::lua::LuaState& L, - std::string& value) +void Scene::propertyPushProfileValueToLua(ghoul::lua::LuaState& L, std::string& value) { - bool alreadyPushedToLua = false; - ProfilePropertyLua elem = propertyProcessValue(L, value, alreadyPushedToLua); - if (!alreadyPushedToLua) { + _valueIsTable = false; + ProfilePropertyLua elem = propertyProcessValue(L, value); + if (!_valueIsTable) { std::visit(overloaded{ [&L](const bool& value) { ghoul::lua::push(L, value); @@ -657,15 +656,15 @@ void Scene::propertyPushValueFromProfileToLuaState(ghoul::lua::LuaState& L, [&L](const ghoul::lua::nil_t& nilValue) { ghoul::lua::push(L, nilValue); } - }, elem); + }, elem); } } -ProfilePropertyLua Scene::propertyProcessValue(ghoul::lua::LuaState& L,std::string& value, - bool& didPushToLua) +ProfilePropertyLua Scene::propertyProcessValue(ghoul::lua::LuaState& L,std::string& value) { ProfilePropertyLua result; PropertyValueType pType = getPropertyValueType(value); + switch (pType) { case PropertyValueType::Boolean: result = (value == "true") ? true : false; @@ -684,15 +683,15 @@ ProfilePropertyLua Scene::propertyProcessValue(ghoul::lua::LuaState& L,std::stri trimSurroundingCharacters(value, '{'); trimSurroundingCharacters(value, '}'); handlePropertyLuaTableEntry(L, value); - didPushToLua = true; + _valueIsTable = true; break; case PropertyValueType::String: default: - std::string newValue = value; - newValue.insert(0, "[["); - newValue.append("]]"); - result = newValue; + trimSurroundingCharacters(value, '\"'); + trimSurroundingCharacters(value, '['); + trimSurroundingCharacters(value, ']'); + result = value; break; } return result; @@ -761,9 +760,7 @@ void Scene::processPropertyValueTableEntries(ghoul::lua::LuaState& L, std::strin nextValue = value.substr(prevPos); } trimSurroundingCharacters(nextValue, ' '); - bool alreadyPushedToLua = false; - ProfilePropertyLua tableElement = propertyProcessValue(L, nextValue, - alreadyPushedToLua); + ProfilePropertyLua tableElement = propertyProcessValue(L, nextValue); try { table.push_back(std::get(tableElement)); } From 515bdd6b1ff5451c83452f9e5225bc71988433a6 Mon Sep 17 00:00:00 2001 From: GPayne Date: Wed, 6 Oct 2021 15:47:10 -0600 Subject: [PATCH 04/15] Fix for profile relative time errors --- .../ext/launcher/src/profile/timedialog.cpp | 6 ++-- src/util/time_lua.inl | 35 +++++++++++-------- src/util/timemanager.cpp | 23 +++++++----- 3 files changed, 37 insertions(+), 27 deletions(-) diff --git a/apps/OpenSpace/ext/launcher/src/profile/timedialog.cpp b/apps/OpenSpace/ext/launcher/src/profile/timedialog.cpp index e9f518bc81..efbcf4293c 100644 --- a/apps/OpenSpace/ext/launcher/src/profile/timedialog.cpp +++ b/apps/OpenSpace/ext/launcher/src/profile/timedialog.cpp @@ -50,7 +50,7 @@ TimeDialog::TimeDialog(QWidget* parent, std::optional* _timeData = **_time; if (_timeData.type == Profile::Time::Type::Relative) { if (_timeData.value == "") { - _timeData.value = "now"; + _timeData.value = "0d"; } _relativeEdit->setSelection(0, _relativeEdit->text().length()); } @@ -60,7 +60,7 @@ TimeDialog::TimeDialog(QWidget* parent, std::optional* } else { _timeData.type = Profile::Time::Type::Relative; - _timeData.value = "now"; + _timeData.value = "0d"; } _initializedAsAbsolute = (_timeData.type == Profile::Time::Type::Absolute); enableAccordingToType(static_cast(_timeData.type)); @@ -114,7 +114,7 @@ void TimeDialog::enableAccordingToType(int idx) { if (comboIdx == Profile::Time::Type::Relative) { _relativeEdit->setText("Relative Time:"); if (_initializedAsAbsolute) { - _relativeEdit->setText("now"); + _relativeEdit->setText("0d"); } else { _relativeEdit->setText(QString::fromStdString(_timeData.value)); diff --git a/src/util/time_lua.inl b/src/util/time_lua.inl index 45b62120c1..567056db89 100644 --- a/src/util/time_lua.inl +++ b/src/util/time_lua.inl @@ -447,24 +447,29 @@ int time_advancedTime(lua_State* L) { } ); - double value = std::stod(std::string(modifier.begin(), it)); + try { + double value = std::stod(std::string(modifier.begin(), it)); + std::string unitName = std::string(it, modifier.end()); - std::string unitName = std::string(it, modifier.end()); + TimeUnit unit = TimeUnit::Second; + if (unitName == "s") { unit = TimeUnit::Second; } + else if (unitName == "m") { unit = TimeUnit::Minute; } + else if (unitName == "h") { unit = TimeUnit::Hour; } + else if (unitName == "d") { unit = TimeUnit::Day; } + else if (unitName == "M") { unit = TimeUnit::Month; } + else if (unitName == "y") { unit = TimeUnit::Year; } + else { + return ghoul::lua::luaError(L, fmt::format("Unknown unit '{}'", unitName)); + } - TimeUnit unit = TimeUnit::Second; - if (unitName == "s") { unit = TimeUnit::Second; } - else if (unitName == "m") { unit = TimeUnit::Minute; } - else if (unitName == "h") { unit = TimeUnit::Hour; } - else if (unitName == "d") { unit = TimeUnit::Day; } - else if (unitName == "M") { unit = TimeUnit::Month; } - else if (unitName == "y") { unit = TimeUnit::Year; } - else { - return ghoul::lua::luaError(L, fmt::format("Unknown unit '{}'", unitName)); + dt = convertTime(value, unit, TimeUnit::Second); + if (isNegative) { + dt *= -1.0; + } } - - dt = convertTime(value, unit, TimeUnit::Second); - if (isNegative) { - dt *= -1.0; + catch (...) { + return ghoul::lua::luaError(L, fmt::format("Error parsing relative time " + "offset '{}'", modifier)); } } diff --git a/src/util/timemanager.cpp b/src/util/timemanager.cpp index 89f898dbd9..09bef47d47 100644 --- a/src/util/timemanager.cpp +++ b/src/util/timemanager.cpp @@ -871,17 +871,22 @@ double TimeManager::previousApplicationTimeForInterpolation() const { void TimeManager::setTimeFromProfile(const Profile& p) { Time t; - switch (p.time.value().type) { - case Profile::Time::Type::Relative: - t.setTimeRelativeFromProfile(p.time.value().value); - break; + if (p.time.has_value()) { + switch (p.time.value().type) { + case Profile::Time::Type::Relative: + t.setTimeRelativeFromProfile(p.time.value().value); + break; - case Profile::Time::Type::Absolute: - t.setTimeAbsoluteFromProfile(p.time.value().value); - break; + case Profile::Time::Type::Absolute: + t.setTimeAbsoluteFromProfile(p.time.value().value); + break; - default: - throw ghoul::MissingCaseException(); + default: + throw ghoul::MissingCaseException(); + } + } + else { + throw ghoul::RuntimeError("No 'time' entry exists in the startup profile"); } } From 990835d7cdab51d7dee38a038393089f9d883edb Mon Sep 17 00:00:00 2001 From: GPayne Date: Wed, 6 Oct 2021 16:05:07 -0600 Subject: [PATCH 05/15] Fix for crash if profile has no camera entry --- src/engine/openspaceengine.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index 99c2bd7712..f0c98acbe8 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -1553,6 +1553,9 @@ void OpenSpaceEngine::toggleShutdownMode() { } void setCameraFromProfile(const Profile& p) { + if (!p.camera.has_value()) { + throw ghoul::RuntimeError("No 'camera' entry exists in the startup profile"); + } std::visit( overloaded{ [](const Profile::CameraNavState& navStateProfile) { From c36ea36a43d23ec6c5fc63c5da7857fe9d619adc Mon Sep 17 00:00:00 2001 From: GPayne Date: Thu, 7 Oct 2021 00:26:29 -0600 Subject: [PATCH 06/15] Code review changes --- include/openspace/scene/scene.h | 15 ++-- src/scene/scene.cpp | 145 +++++++++++++++----------------- src/scene/scene_lua.inl | 13 +-- 3 files changed, 81 insertions(+), 92 deletions(-) diff --git a/include/openspace/scene/scene.h b/include/openspace/scene/scene.h index 979ba119c4..03e7ec71ce 100644 --- a/include/openspace/scene/scene.h +++ b/include/openspace/scene/scene.h @@ -54,7 +54,7 @@ enum class PropertyValueType { Table, Nil }; -typedef std::variant ProfilePropertyLua; +using ProfilePropertyLua = std::variant; class SceneInitializer; @@ -263,7 +263,7 @@ private: * \param L the lua state to push value to * \param value string representation of the value with which to set property */ - void propertyPushProfileValueToLua(ghoul::lua::LuaState& L, std::string& value); + void propertyPushProfileValueToLua(ghoul::lua::LuaState& L, const std::string& value); /** * Accepts string version of a property value from a profile, and processes it @@ -276,7 +276,8 @@ private: * has already been pushed to the lua stack * \return The ProfilePropertyLua variant type translated from string representation */ - ProfilePropertyLua propertyProcessValue(ghoul::lua::LuaState& L, std::string& value); + ProfilePropertyLua propertyProcessValue(ghoul::lua::LuaState& L, + const std::string& value); /** * Accepts string version of a property value from a profile, and returns the @@ -285,7 +286,7 @@ private: * * \param value string representation of the value with which to set property */ - PropertyValueType getPropertyValueType(std::string& value); + PropertyValueType propertyValueType(const std::string& value); /** * Accepts string version of a property value from a profile, and adds it to a vector @@ -296,8 +297,8 @@ private: * \param table the std::vector container which has elements of type T for a lua table */ template - void processPropertyValueTableEntries(ghoul::lua::LuaState& L, std::string& value, - std::vector& table); + void processPropertyValueTableEntries(ghoul::lua::LuaState& L, + const std::string& value, std::vector& table); /** * Handles a lua table entry, creating a vector of the correct variable type based @@ -306,7 +307,7 @@ private: * \param L the lua state to (eventually) push to * \param value string representation of the value with which to set property */ - void handlePropertyLuaTableEntry(ghoul::lua::LuaState& L, std::string& value); + void handlePropertyLuaTableEntry(ghoul::lua::LuaState& L, const std::string& value); /** * Update dependencies. diff --git a/src/scene/scene.cpp b/src/scene/scene.cpp index d13ecab35d..b8b570193d 100644 --- a/src/scene/scene.cpp +++ b/src/scene/scene.cpp @@ -638,114 +638,107 @@ void Scene::setPropertiesFromProfile(const Profile& p) { } } -void Scene::propertyPushProfileValueToLua(ghoul::lua::LuaState& L, std::string& value) +void Scene::propertyPushProfileValueToLua(ghoul::lua::LuaState& L, + const std::string& value) { _valueIsTable = false; ProfilePropertyLua elem = propertyProcessValue(L, value); if (!_valueIsTable) { std::visit(overloaded{ - [&L](const bool& value) { + [&L](const bool value) { ghoul::lua::push(L, value); }, - [&L](const float& value) { + [&L](const float value) { ghoul::lua::push(L, value); }, - [&L](const std::string& value) { + [&L](const std::string value) { ghoul::lua::push(L, value); }, - [&L](const ghoul::lua::nil_t& nilValue) { + [&L](const ghoul::lua::nil_t nilValue) { ghoul::lua::push(L, nilValue); } }, elem); } } -ProfilePropertyLua Scene::propertyProcessValue(ghoul::lua::LuaState& L,std::string& value) +ProfilePropertyLua Scene::propertyProcessValue(ghoul::lua::LuaState& L, + const std::string& value) { ProfilePropertyLua result; - PropertyValueType pType = getPropertyValueType(value); + PropertyValueType pType = propertyValueType(value); switch (pType) { - case PropertyValueType::Boolean: - result = (value == "true") ? true : false; - break; - - case PropertyValueType::Float: - result = std::stof(value); - break; - - case PropertyValueType::Nil: - ghoul::lua::nil_t n; - result = n; - break; - - case PropertyValueType::Table: - trimSurroundingCharacters(value, '{'); - trimSurroundingCharacters(value, '}'); - handlePropertyLuaTableEntry(L, value); - _valueIsTable = true; - break; - - case PropertyValueType::String: - default: - trimSurroundingCharacters(value, '\"'); - trimSurroundingCharacters(value, '['); - trimSurroundingCharacters(value, ']'); - result = value; - break; + case PropertyValueType::Boolean: + result = (value == "true") ? true : false; + break; + case PropertyValueType::Float: + result = std::stof(value); + break; + case PropertyValueType::Nil: + result = ghoul::lua::nil_t(); + break; + case PropertyValueType::Table: + trimSurroundingCharacters(const_cast(value), '{'); + trimSurroundingCharacters(const_cast(value), '}'); + handlePropertyLuaTableEntry(L, value); + _valueIsTable = true; + break; + case PropertyValueType::String: + default: + trimSurroundingCharacters(const_cast(value), '\"'); + trimSurroundingCharacters(const_cast(value), '['); + trimSurroundingCharacters(const_cast(value), ']'); + result = value; + break; } return result; } -void Scene::handlePropertyLuaTableEntry(ghoul::lua::LuaState& L, std::string& value) { - std::string firstValue; - size_t commaPos = 0; - commaPos = value.find(',', commaPos); +void Scene::handlePropertyLuaTableEntry(ghoul::lua::LuaState& L, const std::string& value) +{ + PropertyValueType enclosedType; + size_t commaPos = value.find(',', 0); if (commaPos != std::string::npos) { - firstValue = value.substr(0, commaPos); + enclosedType = propertyValueType(value.substr(0, commaPos)); } else { - firstValue = value; + enclosedType = propertyValueType(value); } - PropertyValueType enclosedType = getPropertyValueType(firstValue); switch (enclosedType) { - case PropertyValueType::Boolean: - LERROR(fmt::format( - "A lua table of bool values is not supported. (processing property {})", - _profilePropertyName) - ); - break; - - case PropertyValueType::Float: - { - std::vector valsF; - processPropertyValueTableEntries(L, value, valsF); - ghoul::lua::push(L, valsF); - } - break; - - case PropertyValueType::String: - { - std::vector valsS; - processPropertyValueTableEntries(L, value, valsS); - ghoul::lua::push(L, valsS); - } - break; - - case PropertyValueType::Table: - default: - LERROR(fmt::format( - "Table-within-a-table values are not supported for profile a " - "property (processing property {})", _profilePropertyName) - ); - break; + case PropertyValueType::Boolean: + LERROR(fmt::format( + "A lua table of bool values is not supported. (processing property {})", + _profilePropertyName) + ); + break; + case PropertyValueType::Float: + { + std::vector valsF; + processPropertyValueTableEntries(L, value, valsF); + ghoul::lua::push(L, valsF); + } + break; + case PropertyValueType::String: + { + std::vector valsS; + processPropertyValueTableEntries(L, value, valsS); + ghoul::lua::push(L, valsS); + } + break; + case PropertyValueType::Table: + default: + LERROR(fmt::format( + "Table-within-a-table values are not supported for profile a " + "property (processing property {})", _profilePropertyName + )); + break; } } template -void Scene::processPropertyValueTableEntries(ghoul::lua::LuaState& L, std::string& value, - std::vector& table) +void Scene::processPropertyValueTableEntries(ghoul::lua::LuaState& L, + const std::string& value, std::vector& table) { size_t commaPos = 0; size_t prevPos = 0; @@ -767,13 +760,13 @@ void Scene::processPropertyValueTableEntries(ghoul::lua::LuaState& L, std::strin catch (std::bad_variant_access& e) { LERROR(fmt::format( "Error attempting to parse profile property setting for " - "{} using value = {}", _profilePropertyName, value) - ); + "{} using value = {}", _profilePropertyName, value + )); } } } -PropertyValueType Scene::getPropertyValueType(std::string& value) { +PropertyValueType Scene::propertyValueType(const std::string& value) { if (luascriptfunctions::isBoolValue(value)) { return PropertyValueType::Boolean; } diff --git a/src/scene/scene_lua.inl b/src/scene/scene_lua.inl index 32a8d9327d..96df5a47a8 100644 --- a/src/scene/scene_lua.inl +++ b/src/scene/scene_lua.inl @@ -904,7 +904,7 @@ int worldRotation(lua_State* L) { * isBoolValue(const std::string& s): * Used to check if a string is a lua bool type. Returns false if not a valid bool string. */ -bool isBoolValue(const std::string& s) { +bool isBoolValue(std::string_view s) { return (s == "true" || s == "false"); } @@ -917,12 +917,7 @@ bool isFloatValue(const std::string& s) { try { float converted = std::numeric_limits::min(); converted = std::stof(s); - if (converted != std::numeric_limits::min()) { - return true; - } - else { - return false; - } + return (converted != std::numeric_limits::min()); } catch (...) { return false; @@ -934,7 +929,7 @@ bool isFloatValue(const std::string& s) { * isNilValue(const std::string& s): * Used to check if a string is a lua 'nil' value. Returns false if not. */ -bool isNilValue(const std::string& s) { +bool isNilValue(std::string_view s) { return (s == "nil"); } @@ -944,7 +939,7 @@ bool isNilValue(const std::string& s) { * Used to check if a string contains a lua table rather than an individual value. * Returns false if not. */ -bool isTableValue(const std::string& s) { +bool isTableValue(std::string_view s) { return ((s.front() == '{') && (s.back() == '}')); } From a2a8f93ba58b627bbb5621c419aa3c77b80d0910 Mon Sep 17 00:00:00 2001 From: GPayne Date: Thu, 7 Oct 2021 16:10:00 -0600 Subject: [PATCH 07/15] Moved string bracket trim function to ghoul library --- ext/ghoul | 2 +- include/openspace/scene/scene.h | 2 -- src/scene/scene.cpp | 24 ++++++++---------------- 3 files changed, 9 insertions(+), 19 deletions(-) diff --git a/ext/ghoul b/ext/ghoul index 4b64684acd..4a17b2a165 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit 4b64684acd728069e80948f9a4767b30baf268a3 +Subproject commit 4a17b2a1653cc596ab8610d93a53c639930ddb85 diff --git a/include/openspace/scene/scene.h b/include/openspace/scene/scene.h index 03e7ec71ce..4ebabe66f2 100644 --- a/include/openspace/scene/scene.h +++ b/include/openspace/scene/scene.h @@ -343,8 +343,6 @@ private: ghoul::MemoryPool<4096> _memoryPool; }; -void trimSurroundingCharacters(std::string& valueString, const char c); - } // namespace openspace #endif // __OPENSPACE_CORE___SCENE___H__ diff --git a/src/scene/scene.cpp b/src/scene/scene.cpp index b8b570193d..cc5420524b 100644 --- a/src/scene/scene.cpp +++ b/src/scene/scene.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -621,7 +622,7 @@ void Scene::setPropertiesFromProfile(const Profile& p) { ghoul::lua::push(L, 0.0); std::string workingValue = prop.value; - trimSurroundingCharacters(workingValue, ' '); + ghoul::trimSurroundingCharacters(workingValue, ' '); // Later functions expect the value to be at the last position on the stack propertyPushProfileValueToLua(L, workingValue); @@ -678,16 +679,16 @@ ProfilePropertyLua Scene::propertyProcessValue(ghoul::lua::LuaState& L, result = ghoul::lua::nil_t(); break; case PropertyValueType::Table: - trimSurroundingCharacters(const_cast(value), '{'); - trimSurroundingCharacters(const_cast(value), '}'); + ghoul::trimSurroundingCharacters(const_cast(value), '{'); + ghoul::trimSurroundingCharacters(const_cast(value), '}'); handlePropertyLuaTableEntry(L, value); _valueIsTable = true; break; case PropertyValueType::String: default: - trimSurroundingCharacters(const_cast(value), '\"'); - trimSurroundingCharacters(const_cast(value), '['); - trimSurroundingCharacters(const_cast(value), ']'); + ghoul::trimSurroundingCharacters(const_cast(value), '\"'); + ghoul::trimSurroundingCharacters(const_cast(value), '['); + ghoul::trimSurroundingCharacters(const_cast(value), ']'); result = value; break; } @@ -752,7 +753,7 @@ void Scene::processPropertyValueTableEntries(ghoul::lua::LuaState& L, else { nextValue = value.substr(prevPos); } - trimSurroundingCharacters(nextValue, ' '); + ghoul::trimSurroundingCharacters(nextValue, ' '); ProfilePropertyLua tableElement = propertyProcessValue(L, nextValue); try { table.push_back(std::get(tableElement)); @@ -784,15 +785,6 @@ PropertyValueType Scene::propertyValueType(const std::string& value) { } } -void trimSurroundingCharacters(std::string& valueString, const char c) { - while (valueString.front() == c) { - valueString.erase(0, 1); - } - while (valueString.back() == c) { - valueString.pop_back(); - } -} - scripting::LuaLibrary Scene::luaLibrary() { return { "", From aa2c94fa4c41305f1311cc144195faea988ecdd6 Mon Sep 17 00:00:00 2001 From: Emma Broman Date: Mon, 11 Oct 2021 13:31:08 +0200 Subject: [PATCH 08/15] Support negative altitudes in GlobeTranslation Necessary when height map is not used and a large negative offset is needed --- modules/globebrowsing/src/globetranslation.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/globebrowsing/src/globetranslation.cpp b/modules/globebrowsing/src/globetranslation.cpp index 79c23906fd..5ef97f08f7 100644 --- a/modules/globebrowsing/src/globetranslation.cpp +++ b/modules/globebrowsing/src/globetranslation.cpp @@ -105,7 +105,7 @@ GlobeTranslation::GlobeTranslation(const ghoul::Dictionary& dictionary) : _globe(GlobeInfo) , _latitude(LatitudeInfo, 0.0, -90.0, 90.0) , _longitude(LongitudeInfo, 0.0, -180.0, 180.0) - , _altitude(AltitudeInfo, 0.0, 0.0, 1e12) + , _altitude(AltitudeInfo, 0.0, -1e12, 1e12) , _useHeightmap(UseHeightmapInfo, false) { const Parameters p = codegen::bake(dictionary); @@ -121,7 +121,8 @@ GlobeTranslation::GlobeTranslation(const ghoul::Dictionary& dictionary) addProperty(_longitude); _altitude = p.altitude.value_or(_altitude); - _altitude.setExponent(8.f); + // @TODO (emmbr) uncomment when ranges with negative values are supported + //_altitude.setExponent(8.f); _altitude.onChange([this]() { setUpdateVariables(); }); addProperty(_altitude); From 7c7e5b29999b365b9c0d3fb8b2966a02ea48db99 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 11 Oct 2021 13:38:00 +0200 Subject: [PATCH 09/15] Remove some warnings --- modules/globebrowsing/src/tileprovider.cpp | 4 +- modules/touch/ext/levmarq.cpp | 22 ++-- src/scene/scene.cpp | 2 +- src/util/coordinateconversion.cpp | 111 ++++++++++++--------- 4 files changed, 78 insertions(+), 61 deletions(-) diff --git a/modules/globebrowsing/src/tileprovider.cpp b/modules/globebrowsing/src/tileprovider.cpp index 0f743ec592..033a47089f 100644 --- a/modules/globebrowsing/src/tileprovider.cpp +++ b/modules/globebrowsing/src/tileprovider.cpp @@ -891,7 +891,9 @@ bool initialize(TileProvider& tp) { ghoul_assert(!tp.isInitialized, "TileProvider can only be initialized once."); - if (TileProvider::NumTileProviders > std::numeric_limits::max() - 1) { + if (TileProvider::NumTileProviders > + static_cast(std::numeric_limits::max()) - 1) + { LERRORC( "TileProvider", "Number of tile providers exceeds 65535. Something will break soon" diff --git a/modules/touch/ext/levmarq.cpp b/modules/touch/ext/levmarq.cpp index ad3be17530..351485f566 100644 --- a/modules/touch/ext/levmarq.cpp +++ b/modules/touch/ext/levmarq.cpp @@ -67,7 +67,7 @@ bool levmarq(int npar, double *par, int ny, double *dysq, void (*grad)(double *, double *, int, void *, LMstat*), void *fdata, LMstat *lmstat) { - int x, i, j, it, nit, ill; + int x, j, it, nit, ill; bool verbose; std::string data; double lambda, up, down, mult, weight, err, newerr, derr, target_derr; @@ -86,7 +86,7 @@ bool levmarq(int npar, double *par, int ny, double *dysq, defer { // deallocate the arrays - for (i = 0; i < npar; i++) { + for (int i = 0; i < npar; i++) { delete[] h[i]; delete[] ch[i]; } @@ -109,7 +109,7 @@ bool levmarq(int npar, double *par, int ny, double *dysq, if (verbose) { std::ostringstream qs, gs, ds, ps, oss; - for (i = 0; i < npar; ++i) { + for (int i = 0; i < npar; ++i) { qs << "q" << i; gs << "g" << i; ds << "d" << i; @@ -119,7 +119,7 @@ bool levmarq(int npar, double *par, int ny, double *dysq, ds << ","; } } - for (i = 0; i < ny; ++i) { + for (int i = 0; i < ny; ++i) { for (j = 0; j < 2; ++j) { std::string s = (j == 0) ? "x" : "y"; ps << "p" << i << s; @@ -153,7 +153,7 @@ bool levmarq(int npar, double *par, int ny, double *dysq, } // calculate the approximation to the Hessian and the "derivative" d - for (i = 0; i < npar; i++) { + for (int i = 0; i < npar; i++) { d[i] = 0; for (j = 0; j <= i; j++) { h[i][j] = 0; @@ -164,7 +164,7 @@ bool levmarq(int npar, double *par, int ny, double *dysq, weight = 1 / dysq[x]; // for weighted least-squares } grad(g, par, x, fdata, lmstat); - for (i = 0; i < npar; i++) { + for (int i = 0; i < npar; i++) { d[i] += (0.0 - func(par, x, fdata, lmstat)) * g[i] * weight; //(y[x] - func(par, x, fdata)) * g[i] * weight; for (j = 0; j <= i; j++) { h[i][j] += g[i] * g[j] * weight; @@ -175,13 +175,13 @@ bool levmarq(int npar, double *par, int ny, double *dysq, mult = 1 + lambda; ill = 1; // ill-conditioned? while (ill && (it < nit)) { - for (i = 0; i < npar; i++) { + for (int i = 0; i < npar; i++) { h[i][i] = h[i][i] * mult; } ill = cholesky_decomp(npar, ch, h); if (!ill) { solve_axb_cholesky(npar, ch, delta, d); - for (i = 0; i < npar; i++) { + for (int i = 0; i < npar; i++) { newpar[i] = par[i] + delta[i]; } lmstat->pos.clear(); @@ -197,7 +197,7 @@ bool levmarq(int npar, double *par, int ny, double *dysq, printf("\n");*/ std::ostringstream gString, qString, dString, pString, os; - for (i = 0; i < npar; ++i) { + for (int i = 0; i < npar; ++i) { gString << g[i]; qString << par[i]; dString << d[i]; @@ -207,7 +207,7 @@ bool levmarq(int npar, double *par, int ny, double *dysq, dString << ","; } } - for (i = 0; i < ny; ++i) { + for (int i = 0; i < ny; ++i) { pString << lmstat->pos.at(i).x << "," << lmstat->pos.at(i).y; if (i + 1 < ny) { pString << ","; @@ -222,7 +222,7 @@ bool levmarq(int npar, double *par, int ny, double *dysq, it++; } } - for (i = 0; i < npar; i++) { + for (int i = 0; i < npar; i++) { par[i] = newpar[i]; } err = newerr; diff --git a/src/scene/scene.cpp b/src/scene/scene.cpp index cc5420524b..e17b48f11e 100644 --- a/src/scene/scene.cpp +++ b/src/scene/scene.cpp @@ -758,7 +758,7 @@ void Scene::processPropertyValueTableEntries(ghoul::lua::LuaState& L, try { table.push_back(std::get(tableElement)); } - catch (std::bad_variant_access& e) { + catch (std::bad_variant_access&) { LERROR(fmt::format( "Error attempting to parse profile property setting for " "{} using value = {}", _profilePropertyName, value diff --git a/src/util/coordinateconversion.cpp b/src/util/coordinateconversion.cpp index daaa9a34ea..a9ed1b325c 100644 --- a/src/util/coordinateconversion.cpp +++ b/src/util/coordinateconversion.cpp @@ -51,7 +51,8 @@ namespace { { throw ghoul::lua::LuaRuntimeException(fmt::format( "Ra or Dec '{}' format is incorrect. Correct format is: Ra 'XhYmZs', " - "and Dec 'XdYmZs'", str)); + "and Dec 'XdYmZs'", str + )); } // Construct the number strings @@ -66,7 +67,8 @@ namespace { if (std::floor(temp) != temp) { throw ghoul::lua::LuaRuntimeException(fmt::format( "Ra or Dec '{}' format is incorrect. Correct format is: Ra 'XhYmZs', " - "and Dec 'XdYmZs', where X must be an integer", str)); + "and Dec 'XdYmZs', where X must be an integer", str + )); } hoursOrDegrees = std::stoi(sHoursOrDegrees); @@ -75,83 +77,90 @@ namespace { if (std::floor(temp) != temp) { throw ghoul::lua::LuaRuntimeException(fmt::format( "Ra or Dec '{}' format is incorrect. Correct format is: Ra 'XhYmZs', " - "and Dec 'XdYmZs', where Y must be an integer", str)); + "and Dec 'XdYmZs', where Y must be an integer", str + )); } minutes = std::stoi(sMinutes); // Seconds is a double seconds = std::stod(sSeconds); - } catch (const std::invalid_argument& ia) { + } + catch (const std::invalid_argument&) { throw ghoul::lua::LuaRuntimeException(fmt::format( "Ra or Dec '{}' format is incorrect. Correct format is: Ra 'XhYmZs', " - "and Dec 'XdYmZs'", str)); + "and Dec 'XdYmZs'", str + )); } } void parseRa(const std::string& ra, int& hours, int& minutes, double& seconds) { if (ra.find('d') != std::string::npos) { throw ghoul::lua::LuaRuntimeException(fmt::format( - "Ra '{}' format is incorrect. Correct format is: 'XhYmZs'", ra)); + "Ra '{}' format is incorrect. Correct format is: 'XhYmZs'", ra + )); } parseString(ra, hours, minutes, seconds); } - void parseDec(const std::string& dec, int& degrees, int& minutes, - double& seconds) - { + void parseDec(const std::string& dec, int& degrees, int& minutes, double& seconds) { if (dec.find('h') != std::string::npos) { throw ghoul::lua::LuaRuntimeException(fmt::format( - "Dec '{}' format is incorrect. Correct format is: 'XdYmZs'", dec)); + "Dec '{}' format is incorrect. Correct format is: 'XdYmZs'", dec + )); } parseString(dec, degrees, minutes, seconds); } - bool isRaDecValid(int raH, int raM, double raS, int decD, - int decM, double decS) - { + bool isRaDecValid(int raH, int raM, double raS, int decD, int decM, double decS) { // Ra if (raH < 0.0 || raH >= 24.0) { - LWARNING(fmt::format("Right ascension hours '{}' is outside the allowed " - "range of 0 to 24 hours (exclusive)", raH) - ); + LWARNING(fmt::format( + "Right ascension hours '{}' is outside the allowed range of 0 to 24 " + "hours (exclusive)", raH + )); return false; } if (raM < 0.0 || raM >= 60.0) { - LWARNING(fmt::format("Right ascension minutes '{}' is outside the allowed " - "range of 0 to 60 minutes (exclusive)", raM) - ); + LWARNING(fmt::format( + "Right ascension minutes '{}' is outside the allowed range of 0 to 60 " + "minutes (exclusive)", raM + )); return false; } if (raS < 0.0 || raS >= 60.0) { - LWARNING(fmt::format("Right ascension seconds '{}' is outside the allowed " - "range of 0 to 60 seconds (exclusive)", raS) - ); + LWARNING(fmt::format( + "Right ascension seconds '{}' is outside the allowed " + "range of 0 to 60 seconds (exclusive)", raS + )); return false; } // Dec if (decD < -90.0 || decD > 90.0) { LWARNING(fmt::format("Declination degrees '{}' is outside the allowed range " - "of -90 to 90 degrees (inclusive)", decD) - ); + "of -90 to 90 degrees (inclusive)", decD + )); return false; } else if ((decD == -90.0 || decD == 90.0) && (decM != 0 || decS != 0)) { - LWARNING("Total declination is outside the allowed range of -90 to 90 " - "degrees (inclusive)" + LWARNING( + "Total declination is outside the allowed range of -90 to 90 degrees " + "(inclusive)" ); return false; } if (decM < 0.0 || decM >= 60.0) { - LWARNING(fmt::format("Declination minutes '{}' is outside the allowed range " - "of 0 to 60 minutes (exclusive)", decM) - ); + LWARNING(fmt::format( + "Declination minutes '{}' is outside the allowed range of 0 to 60 " + "minutes (exclusive)", decM + )); return false; } if (decS < 0.0 || decS >= 60.0) { - LWARNING(fmt::format("Declination seconds '{}' is outside the allowed range " - "of 0 to 60 seconds (exclusive)", decS) - ); + LWARNING(fmt::format( + "Declination seconds '{}' is outside the allowed range of 0 to 60 " + "seconds (exclusive)", decS + )); return false; } @@ -191,12 +200,14 @@ glm::dvec3 icrsToGalacticCartesian(double ra, double dec, double distance) { // Dec format 'XdYmZs', where X is a signed integer, Y is a positive integer and Z is a // positive double // Reference: -// https://math.stackexchange.com/questions/15323/how-do-i-calculate-the-cartesian-coordinates-of-stars +// https://math.stackexchange.com/questions/15323/how-do-i-calculate-the-cartesian- +// coordinates-of-stars glm::dvec2 icrsToDecimalDegrees(const std::string& ra, const std::string& dec) { if (ra.size() < 6 || dec.size() < 6) { throw ghoul::lua::LuaRuntimeException(fmt::format( "Ra '{}' or Dec '{}' format is incorrect. Correct format is: Ra 'XhYmZs', " - "and Dec 'XdYmZs'", ra, dec)); + "and Dec 'XdYmZs'", ra, dec + )); } // Parse right ascension @@ -218,9 +229,10 @@ glm::dvec2 icrsToDecimalDegrees(const std::string& ra, const std::string& dec) { ); if (!isValid) { - LWARNING(fmt::format("Ra '{}' or Dec '{}' is outside the allowed range, " - "result may be incorrect", ra, dec) - ); + LWARNING(fmt::format( + "Ra '{}' or Dec '{}' is outside the allowed range, result may be incorrect", + ra, dec + )); } // Convert from hours/degrees, minutes, seconds to decimal degrees @@ -266,7 +278,8 @@ glm::dvec3 galacticCartesianToIcrs(double x, double y, double z) { // Return a pair with two formatted strings from the decimal degrees ra and dec // References: // https://www.rapidtables.com/convert/number/degrees-to-degrees-minutes-seconds.html, -// https://math.stackexchange.com/questions/15323/how-do-i-calculate-the-cartesian-coordinates-of-stars +// https://math.stackexchange.com/questions/15323/how-do-i-calculate-the-cartesian- +// coordinates-of-stars std::pair decimalDegreesToIcrs(double ra, double dec) { // Radians to degrees double raDeg = ra; @@ -274,21 +287,22 @@ std::pair decimalDegreesToIcrs(double ra, double dec) // Check input if (raDeg < 0 || raDeg > 360 || decDeg < -90 || decDeg > 90) { - LWARNING(fmt::format("Given Ra '{}' or Dec '{}' is outside the allowed range, " - "result may be incorrect", ra, dec) - ); + LWARNING(fmt::format( + "Ra '{}' or Dec '{}' is outside the allowed range, result may be incorrect", + ra, dec + )); } // Calculate Ra - int raHours = std::trunc(raDeg) / 15.0; + int raHours = static_cast(std::trunc(raDeg) / 15.0); double raMinutesFull = (raDeg - raHours * 15.0) * 60.0 / 15.0; - int raMinutes = std::trunc(raMinutesFull); + int raMinutes = static_cast(std::trunc(raMinutesFull)); double raSeconds = (raMinutesFull - raMinutes) * 60.0; // Calculate Dec - int decDegrees = std::trunc(decDeg); + int decDegrees = static_cast(std::trunc(decDeg)); double decMinutesFull = (abs(decDeg) - abs(decDegrees)) * 60.0; - int decMinutes = std::trunc(decMinutesFull); + int decMinutes = static_cast(std::trunc(decMinutesFull)); double decSeconds = (decMinutesFull - decMinutes) * 60.0; // Construct strings @@ -311,9 +325,10 @@ std::pair decimalDegreesToIcrs(double ra, double dec) ); if (!isValid) { - LWARNING(fmt::format("Resulting Ra '{}' or Dec '{}' is outside the allowed range, " - "result may be incorrect", result.first, result.second) - ); + LWARNING(fmt::format( + "Resulting Ra '{}' or Dec '{}' is outside the allowed range, result may be " + "incorrect", result.first, result.second + )); } return result; } From d23067518152ef39a33f9c156cf643f71510631c Mon Sep 17 00:00:00 2001 From: Emma Broman Date: Mon, 11 Oct 2021 15:43:06 +0200 Subject: [PATCH 10/15] Add Lua function to get current application time --- src/util/time.cpp | 8 ++++++++ src/util/time_lua.inl | 13 +++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/util/time.cpp b/src/util/time.cpp index 2653ee2b31..0f94934e61 100644 --- a/src/util/time.cpp +++ b/src/util/time.cpp @@ -315,6 +315,14 @@ scripting::LuaLibrary Time::luaLibrary() { "Returns the current wall time as an ISO 8601 date string " "(YYYY-MM-DDTHH-MN-SS) in the UTC timezone" }, + { + "currentApplicationTime", + &luascriptfunctions::time_currentApplicationTime, + {}, + "", + "Returns the current application time as the number of seconds " + "since the OpenSpace application started" + }, { "advancedTime", &luascriptfunctions::time_advancedTime, diff --git a/src/util/time_lua.inl b/src/util/time_lua.inl index 567056db89..9c519ae5c2 100644 --- a/src/util/time_lua.inl +++ b/src/util/time_lua.inl @@ -23,6 +23,7 @@ ****************************************************************************************/ #include +#include #include #include #include @@ -404,6 +405,18 @@ int time_currentWallTime(lua_State* L) { return 1; } +/** + * \ingroup LuaScripts + * currentTime(): + * Returns the current application time as the number of seconds since the OpenSpace + * application started + */ +int time_currentApplicationTime(lua_State* L) { + ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::time_currentApplicationTime"); + ghoul::lua::push(L, global::windowDelegate->applicationTime()); + return 1; +} + int time_advancedTime(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::time_advanceTime"); auto [base, change] = From 76dd45e5ce32cfe51d67883650ea8cd27ace1746 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 11 Oct 2021 21:53:00 +0200 Subject: [PATCH 11/15] Event System (#1741) * Add implementation of the EventEngine to handle global event chains * Add properties to SceneGraphNodes to determine two distance radii for camera-based events --- data/assets/actions/toggle_trail.asset | 105 ++++ data/assets/events/toggle_trail.asset | 27 + data/assets/examples/approachevents.asset | 68 ++ include/openspace/engine/configuration.h | 1 + include/openspace/engine/globals.h | 2 + include/openspace/engine/openspaceengine.h | 3 + include/openspace/events/event.h | 393 ++++++++++++ include/openspace/events/eventengine.h | 125 ++++ include/openspace/events/eventengine.inl | 51 ++ .../openspace/navigation/navigationhandler.h | 5 + include/openspace/scene/scenegraphnode.h | 15 + include/openspace/util/memorymanager.h | 4 +- include/openspace/util/tstring.h | 64 ++ .../base/rendering/renderabletrailorbit.cpp | 7 + modules/globebrowsing/src/layergroup.cpp | 34 +- openspace.cfg | 1 + src/CMakeLists.txt | 8 + src/documentation/core_registration.cpp | 4 +- src/engine/configuration.cpp | 6 + src/engine/globals.cpp | 51 +- src/engine/openspaceengine.cpp | 50 +- src/events/event.cpp | 595 ++++++++++++++++++ src/events/eventengine.cpp | 133 ++++ src/events/eventengine_lua.inl | 49 ++ src/interaction/actionmanager.cpp | 11 +- src/interaction/sessionrecording.cpp | 18 +- src/navigation/navigationhandler.cpp | 117 ++++ src/navigation/orbitalnavigator.cpp | 18 +- src/network/parallelpeer.cpp | 69 +- src/properties/propertyowner.cpp | 3 + src/rendering/renderengine.cpp | 13 +- src/scene/profile.cpp | 8 +- src/scene/scene.cpp | 6 + src/scene/scene_lua.inl | 2 + src/scene/scenegraphnode.cpp | 118 +++- src/util/tstring.cpp | 51 ++ 36 files changed, 2176 insertions(+), 59 deletions(-) create mode 100644 data/assets/actions/toggle_trail.asset create mode 100644 data/assets/events/toggle_trail.asset create mode 100644 data/assets/examples/approachevents.asset create mode 100644 include/openspace/events/event.h create mode 100644 include/openspace/events/eventengine.h create mode 100644 include/openspace/events/eventengine.inl create mode 100644 include/openspace/util/tstring.h create mode 100644 src/events/event.cpp create mode 100644 src/events/eventengine.cpp create mode 100644 src/events/eventengine_lua.inl create mode 100644 src/util/tstring.cpp diff --git a/data/assets/actions/toggle_trail.asset b/data/assets/actions/toggle_trail.asset new file mode 100644 index 0000000000..d3c5848d6c --- /dev/null +++ b/data/assets/actions/toggle_trail.asset @@ -0,0 +1,105 @@ +local toggle_trail = { + Identifier = "os.toggle_trail", + Name = "Toggle Trail", + Command = [[ + local node + if is_declared("args") then + node = args.Node + else + node = openspace.navigation.getNavigationState().Anchor + end + + local trail + if openspace.hasSceneGraphNode(node .. "Trail") then + trail = node .. "Trail" + elseif openspace.hasSceneGraphNode(node .. "_trail") then + trail = node .. "_trail" + else + -- No trail found, so nothing more to do here + return + end + + local visibility + if is_declared("args") then + if args.Transition == "Approaching" then + visibility = false + elseif args.Transition == "Exiting" then + visibility = true + else + return + end + else + visibility = not openspace.getPropertyValue("Scene." .. trail .. ".Renderable.Enabled") + end + + openspace.setPropertyValueSingle("Scene." .. trail .. ".Renderable.Enabled", visibility) + ]], + Documentation = [[Toggles the visibility of the associated trail of a scene graph node. + This action takes optional arguments to 1) determine which trail to hide (as the + 'Node') and 2) the transition direction (as 'After' and 'Before').]], + GuiPath = "/Trails", + IsLocal = true +} +asset.export("toggle_trail", toggle_trail.Identifier) + +local hide_trail = { + Identifier = "os.hide_trail", + Name = "Hide Trail", + Command = [[ + local node + if is_declared("args") then + node = args.Node + else + node = openspace.navigation.getNavigationState().Anchor + end + + if openspace.hasSceneGraphNode(node .. "Trail") then + openspace.setPropertyValue("Scene." .. node .. "Trail.Renderable.Enabled", false) + elseif openspace.hasSceneGraphNode(node .. "_trail") then + openspace.setPropertyValue("Scene." .. node .. "_trail.Renderable.Enabled", false) + end + ]], + Documentation = [[Hides the associated trail of a scene graph node. This action takes an + optional argument to determine whose trail to hide. If no argument is provided, the + current focus node is used instead]], + GuiPath = "/Trails", + IsLocal = true +} +asset.export("hide_trail", hide_trail.Identifier) + +local show_trail = { + Identifier = "os.show_trail", + Name = "Show Trail", + Command = [[ + local node + if is_declared("args") then + node = args.Node + else + node = openspace.navigation.getNavigationState().Anchor + end + + if openspace.hasSceneGraphNode(node .. "Trail") then + openspace.setPropertyValue("Scene." .. node .. "Trail.Renderable.Enabled", true) + elseif openspace.hasSceneGraphNode(node .. "_trail") then + openspace.setPropertyValue("Scene." .. node .. "_trail.Renderable.Enabled", true) + end + ]], + Documentation = [[Shows the associated trail of a scene graph node. This action takes an + optional argument to determine whose trail to hide. If no argument is provided, the + current focus node is used instead]], + GuiPath = "/Trails", + IsLocal = true +} +asset.export("show_trail", show_trail.Identifier) + +asset.onInitialize(function() + openspace.action.registerAction(toggle_trail) + openspace.action.registerAction(show_trail) + openspace.action.registerAction(hide_trail) +end) + +asset.onDeinitialize(function() + openspace.action.removeAction(toggle_trail.Identifier) + openspace.action.removeAction(show_trail.Identifier) + openspace.action.removeAction(hide_trail.Identifier) +end) diff --git a/data/assets/events/toggle_trail.asset b/data/assets/events/toggle_trail.asset new file mode 100644 index 0000000000..2e397ed7d8 --- /dev/null +++ b/data/assets/events/toggle_trail.asset @@ -0,0 +1,27 @@ +local action = asset.require('actions/toggle_trail') + +asset.onInitialize(function() + openspace.event.registerEventAction( + "CameraFocusTransition", + action.show_trail, + { Transition = "Exiting" } + ); + openspace.event.registerEventAction( + "CameraFocusTransition", + action.hide_trail, + { Transition = "Approaching" } + ); +end) + +asset.onDeinitialize(function() + openspace.event.unregisterEventAction( + "CameraFocusTransition", + action.show_trail, + { Transition = "Exiting" } + ); + openspace.event.unregisterEventAction( + "CameraFocusTransition", + action.hide_trail, + { Transition = "Approaching" } + ); +end) diff --git a/data/assets/examples/approachevents.asset b/data/assets/examples/approachevents.asset new file mode 100644 index 0000000000..47ddc3281c --- /dev/null +++ b/data/assets/examples/approachevents.asset @@ -0,0 +1,68 @@ +local assetHelper = asset.require('util/asset_helper') +local sunTransforms = asset.require('scene/solarsystem/sun/transforms') +local transforms = asset.require('scene/solarsystem/planets/earth/transforms') + +local generic_action = { + Identifier = "os.example.generic", + Name = "Generic Example", + Command = [[ + openspace.printInfo("Node: " .. args.Node) + openspace.printInfo("Transition: " .. args.Transition) + ]], + Documentation = "Prints the argument information for camera transitions to the log", + GuiPath = "/Examples/Events", + IsLocal = true +} + +local model = asset.syncedResource({ + Name = "Animated Box", + Type = "HttpSynchronization", + Identifier = "animated_box", + Version = 1 +}) + +local obj = { + Identifier = "ExampleEventModel", + Parent = transforms.EarthCenter.Identifier, + Transform = { + Translation = { + Type = "StaticTranslation", + Position = { 0.0, 11E7, 0.0 } + } + }, + Renderable = { + Type = "RenderableModel", + GeometryFile = model .. "/BoxAnimated.glb", + ModelScale = 1.0, + LightSources = { + { + Type = "SceneGraphLightSource", + Identifier = "Sun", + Node = sunTransforms.SolarSystemBarycenter.Identifier, + Intensity = 1.0 + } + }, + PerformShading = true, + DisableFaceCulling = true + }, + InteractionSphere = 1000.0, + OnApproach = { "os.example.generic" }, + OnReach = { "os.example.generic" }, + OnRecede = { "os.example.generic" }, + OnExit = { "os.example.generic" }, + GUI = { + Name = "Example Event Model", + Path = "/Example", + Description = "", + } +} + +asset.onInitialize(function() + openspace.action.registerAction(generic_action) + openspace.addSceneGraphNode(obj) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(obj.Identifier) + openspace.action.removeAction(generic_action.Identifier) +end) diff --git a/include/openspace/engine/configuration.h b/include/openspace/engine/configuration.h index 9748891b38..cb4303c5bb 100644 --- a/include/openspace/engine/configuration.h +++ b/include/openspace/engine/configuration.h @@ -89,6 +89,7 @@ struct Configuration { bool isCheckingOpenGLState = false; bool isLoggingOpenGLCalls = false; + bool isPrintingEvents = false; float shutdownCountdown = 0.f; diff --git a/include/openspace/engine/globals.h b/include/openspace/engine/globals.h index 0055117b3d..38b7d37915 100644 --- a/include/openspace/engine/globals.h +++ b/include/openspace/engine/globals.h @@ -36,6 +36,7 @@ namespace openspace { class Dashboard; class DeferredcasterManager; class DownloadManager; +class EventEngine; class LuaConsole; class MemoryManager; class MissionManager; @@ -74,6 +75,7 @@ inline ghoul::fontrendering::FontManager* fontManager; inline Dashboard* dashboard; inline DeferredcasterManager* deferredcasterManager; inline DownloadManager* downloadManager; +inline EventEngine* eventEngine; inline LuaConsole* luaConsole; inline MemoryManager* memoryManager; inline MissionManager* missionManager; diff --git a/include/openspace/engine/openspaceengine.h b/include/openspace/engine/openspaceengine.h index aaadc9cd18..5b48f40b2e 100644 --- a/include/openspace/engine/openspaceengine.h +++ b/include/openspace/engine/openspaceengine.h @@ -26,6 +26,7 @@ #define __OPENSPACE_CORE___OPENSPACEENGINE___H__ #include +#include #include #include #include @@ -117,6 +118,8 @@ private: std::string generateFilePath(std::string openspaceRelativePath); void resetPropertyChangeFlagsOfSubowners(openspace::properties::PropertyOwner* po); + properties::BoolProperty _printEvents; + std::unique_ptr _scene; std::unique_ptr _assetManager; bool _shouldAbortLoading = false; diff --git a/include/openspace/events/event.h b/include/openspace/events/event.h new file mode 100644 index 0000000000..9c903917be --- /dev/null +++ b/include/openspace/events/event.h @@ -0,0 +1,393 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2021 * + * * + * 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___EVENT___H__ +#define __OPENSPACE_CORE___EVENT___H__ + +#include +#include +#include + +namespace openspace { + namespace properties { class Property; } + + class Camera; + class Layer; + class Profile; + class SceneGraphNode; + class ScreenSpaceRenderable; + class Time; +} // namespace openspace + +namespace openspace::events { + +struct Event { + // Steps to add a new event type: + // 1. Add a new entry into this enum list + // 2. Create a new subclass of Event in this file with a constructor that sets the + // Event's `type` to this new enum entry + // 3. In the cpp file, add a new `log` message that takes the new type as an argument + // and that prints something useful when the log is encountered and the user wants + // to see all events. + // 4. Add a new case into the logAllEvents function that handles the new enum entry + // 5. If the new event type has any parameters it takes in its constructor, go into + // the `toParameter` function and add a case label for the new enum type and + // return a dictionary with these parameters. This dictionary is passed to actions + // if they are triggered by events + // 6. Add the new enum entry into the `toString` and `fromString` methods + enum class Type { + SceneGraphNodeAdded, + SceneGraphNodeRemoved, + ParallelConnection, + ProfileLoadingFinished, + ApplicationShutdown, + ScreenSpaceRenderableAdded, + ScreenSpaceRenderableRemoved, + CameraFocusTransition, + TimeOfInterestReached, + MissionEventReached, + PlanetEclipsed, + InterpolationFinished, + FocusNodeChanged, + LayerAdded, + LayerRemoved, + SessionRecordingPlayback, + Custom + }; + constexpr explicit Event(Type type_) : type(type_) {} + + const Type type; + const Event* next = nullptr; +}; + +template +T* asType(Event* e) { + ghoul_assert(e->type == T::Type, "Wrong type requested, check 'isType'"); + return static_cast(e); +} + +template +bool isType(Event* e) { + return e->type == T::Type; +} + +std::string_view toString(Event::Type type); +Event::Type fromString(std::string_view str); + +ghoul::Dictionary toParameter(const Event& e); + +void logAllEvents(const Event* e); + +// +// Events +// + +/** + * This event is created whenever a new scene graph node is added to the system. By the + * time this event is signalled, the scene graph node has already been created and added + * to the scene. + * + * \param Node The identifier of the node that was added + */ +struct EventSceneGraphNodeAdded : public Event { + static const Type Type = Event::Type::SceneGraphNodeAdded; + + explicit EventSceneGraphNodeAdded(const SceneGraphNode* node_); + const tstring node; +}; + +/** + * This event is created whenever a scene graph node was removed. By the time this event + * is signalled, the scene graph node has already been removed. + * + * \param Node The identifier of that node that was removed + */ +struct EventSceneGraphNodeRemoved : public Event { + static const Type Type = Event::Type::SceneGraphNodeRemoved; + + explicit EventSceneGraphNodeRemoved(const SceneGraphNode* node_); + const tstring node; +}; + +/** + * This event is created whenever something in the parallel connection subsystem changes. + * The new state is sent as an argument with this event. + * + * \param State The new state of the parallel connection system; is one of `Established`, + * `Lost`, `HostshipGained`, or `HostshipLost` + */ +struct EventParallelConnection : public Event { + static const Type Type = Event::Type::ParallelConnection; + + enum class State : uint8_t { + Established, + Lost, + HostshipGained, + HostshipLost + }; + explicit EventParallelConnection(State state_); + State state; +}; + +/** + * This event is created when the loading of a profile is finished. This is emitted + * regardless of whether it is the initial profile, or any subsequent profile is loaded. + */ +struct EventProfileLoadingFinished : public Event { + static const Type Type = Event::Type::ProfileLoadingFinished; + + EventProfileLoadingFinished(); +}; + +/** + * This event is created whenever some information about the application shutdown sequence + * changes. This can either be that the seqeuence started, was aborted, or is finished, + * which means that OpenSpace is just about the shutdown. + * + * \param State The next state of the application shutdown sequence; is one of `Started`, + * `Aborted`, or `Finished` + */ +struct EventApplicationShutdown : public Event { + static const Type Type = Event::Type::ApplicationShutdown; + + enum class State : uint8_t { + Started, + Aborted, + Finished + }; + + explicit EventApplicationShutdown(State state_); + const State state; +}; + +/** + * This event is created when a new screenspace renderable has been created. By the time + * this event is craeted, the screenspace renderable is already registered and available. + * + * \param Renderable The identifier of the new screenspace renderable that was just added + * to the system + */ +struct EventScreenSpaceRenderableAdded : public Event { + static const Type Type = Event::Type::ScreenSpaceRenderableAdded; + + explicit EventScreenSpaceRenderableAdded(const ScreenSpaceRenderable* renderable_); + const tstring renderable; +}; + +/** + * This event is created when a screenspace renderable has been removed from the system. + * When this event is created, the screenspace renderable has already been removed and is + * no longer available + * + * \param Renderable The identifier of the screenspace renderable that was removed + */ +struct EventScreenSpaceRenderableRemoved : public Event { + static const Type Type = Event::Type::ScreenSpaceRenderableRemoved; + + explicit EventScreenSpaceRenderableRemoved(const ScreenSpaceRenderable* renderable_); + const tstring renderable; +}; + +/** + * This event is created when the camera transitions between different interaction sphere + * distances. Right now, only movement relative to camera's focus node is considered. + * Each scene graph node has an interaction sphere radius that serves as the reference + * distance for all spheres. +``` +Diagram of events for a camera moving from right-to-left. Interaction sphere is 'O' in middle, and ')' are spherical boundaries. The approach factor, reach factor, and interaction sphere radius are all taken from the current focus node. + +|<------------------->| Approach factor * Interaction sphere + |<------>| Reach Factor * Interaction sphere + +( ( O ) ) +^ ^ ^ ^ +Exiting Receding Reaching Approaching +``` + * + * \param Node The name of the node the camera is transitioning relative to. Currently is + * always the same as the camera's focus node + * \param Transition The transition type that the camera just finished; is one of + * `Approaching`, `Reaching`, `Receding`, or `Exiting` + */ +struct EventCameraFocusTransition : public Event { + static const Type Type = Event::Type::CameraFocusTransition; + + enum class Transition { + Approaching, + Reaching, + Receding, + Exiting + }; + + EventCameraFocusTransition(const Camera* camera_, const SceneGraphNode* node_, + Transition transition_); + + const Camera* camera = nullptr; + const tstring node; + const Transition transition; +}; + + +/** + * This event is created with a specific time of interest is reached. This event is + * currently unused. + */ +struct EventTimeOfInterestReached : public Event { + static const Type Type = Event::Type::TimeOfInterestReached; + + EventTimeOfInterestReached(const Time* time_, const Camera* camera_); + const Time* time = nullptr; + const Camera* camera = nullptr; +}; + + +/** + * This event is created when the end of a mission phase is reached. This event is + * currently unused. + */ +struct EventMissionEventReached : public Event { + static const Type Type = Event::Type::MissionEventReached; + + // Not sure which kind of parameters we want to pass here + EventMissionEventReached(); +}; + +/** + * This event is created when a planet is eclipsed by a moon or a different planet. This + * event is currently unused. + * + * \param Eclipsee The identifier of the scene graph node that is eclipsed by another + * object + * \param Eclipser The identifier of the scene graph node that is eclipsing the other + * object + */ +struct EventPlanetEclipsed : public Event { + static const Type Type = Event::Type::PlanetEclipsed; + + EventPlanetEclipsed(const SceneGraphNode* eclipsee_, const SceneGraphNode* eclipser_); + const tstring eclipsee; + const tstring eclipser; +}; + +/** + * This event is created when the interpolation of a property value is finished. If the + * interpolation time of a property change is 0s, this event is not fired + * + * \param Property The URI of the property whose interpolation has finished + */ +struct EventInterpolationFinished : public Event { + static const Type Type = Event::Type::InterpolationFinished; + + EventInterpolationFinished(const properties::Property* property_); + const tstring property; +}; + +/** + * This event is created when the camera changes focus nodes. Even if the camera position + * is interpolated, the node change happens instantaneously and the event is fired at the + * same time. + * + * \param OldNode The identifier of the scene graph node which was the old focus node + * \param NewNode The identifier of the scene graph node that is the new focus node + */ +struct EventFocusNodeChanged : public Event { + static const Type Type = Event::Type::FocusNodeChanged; + + EventFocusNodeChanged(const SceneGraphNode* oldNode_, const SceneGraphNode* newNode_); + const tstring oldNode; + const tstring newNode; +}; + +/** + * This event is created when a layer is added to to a globe. + * + * \param Globe The identifier of the globe to which the layer is added + * \param Group The identifier of the layer group to which the layer is added + * \param Layer The identifier of the layer that was added + */ +struct EventLayerAdded : public Event { + static const Type Type = Event::Type::LayerAdded; + + explicit EventLayerAdded(std::string_view node_, std::string_view layerGroup_, + std::string_view layer_); + const tstring node; + const tstring layerGroup; + const tstring layer; +}; + +/** + * This event is created when a layer is removed from a globe. + * + * \param Globe The identifier of the globe from which the layer is removed + * \param Group The identifier of the layer group from which the layer is removed + * \param Layer The identifier of the layer that was removed + */ +struct EventLayerRemoved : public Event { + static const Type Type = Event::Type::LayerRemoved; + + explicit EventLayerRemoved(std::string_view node_, std::string_view layerGroup_, + std::string_view layer_); + const tstring node; + const tstring layerGroup; + const tstring layer; +}; + +/** + * This event is created when something regarding a session recording playback changes. + * The event contains information about the new state of the session recording subsystem. + * + * \param State The new state of the session recording; one of `Started`, `Paused`, + * `Resumed`, `Finished` + */ +struct EventSessionRecordingPlayback : public Event { + static const Type Type = Event::Type::SessionRecordingPlayback; + + enum class State { + Started, + Paused, + Resumed, + Finished + }; + + EventSessionRecordingPlayback(State state_); + const State state; +}; + +/** + * A custom event type that can be used in a pinch when no explicit event type is + * available. This should only be used in special circumstances and it should be + * transitioned to a specific event type, if it is deemed to be useful. + */ +struct CustomEvent : public Event { + static const Type Type = Event::Type::Custom; + + CustomEvent(std::string_view subtype_, const void* payload_); + + const tstring subtype; + const void* payload = nullptr; +}; + +} // namespace openspace::events + +#endif // __OPENSPACE_CORE___EVENT___H__ diff --git a/include/openspace/events/eventengine.h b/include/openspace/events/eventengine.h new file mode 100644 index 0000000000..70e945012b --- /dev/null +++ b/include/openspace/events/eventengine.h @@ -0,0 +1,125 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2021 * + * * + * 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___EVENTENGINE___H__ +#define __OPENSPACE_CORE___EVENTENGINE___H__ + +#include +#include +#include +#include + +namespace openspace { + +namespace events { struct Event; } + +class EventEngine { +public: + /** + * This function returns the first event stored in the EventEngine, or \c nullptr if + * no event exists. To navigate the full list of events, you can access the returned + * Event's next function. If the end of the list is reached, the next pointer will be + * a nullptr + * + * \return The first event stored in the EventEngine or nullptr if no event exists + */ + events::Event* firstEvent() const; + + /** + * Publish a new event of type T by providing optional arguments Args to the Event's + * constructor. An example of usage is + * engine.publishEvent("a", 2.0); which would call the + * constructor of \c MyEvent with a const char* and \c double parameter. + * + * \param args The arguments that are passed to the constructor of T + * \tparam T The subclass of Event that is to be published + */ + template + void publishEvent(Args&&... args); + + /** + * This function cleans up the memory for all published events.After this function + * has been called, no previously published events are valid any longer. This means + * that pointers retrieved from events before this call must be kept beyond this call. + */ + void postFrameCleanup(); + + /** + * Registers a new action for a specific event type. + * + * \param type The type for which a new action is registered + * \param actionIdentifier The identifier of the action that will be triggered the + * identifier must not exist at this moment, but must exist by the time the + * event is encountered next + * \param filter If the filter is provided, it describes the event parameters that are + * checked and only if an event passes the filter, the corresponding action is + * triggered + */ + void registerEventAction(events::Event::Type type, std::string identifier, + std::optional filter = std::nullopt); + + /** + * Removing registration for a type/action combination. + * + * \param type The type of the action that should be unregistered + * \param actionIdentifier The identifier of the action that should be unregistered + * \param filter The optional filter applied to the event-action combination + */ + void unregisterEventAction(events::Event::Type type, + const std::string& identifier, + std::optional filter = std::nullopt); + + /** + * Triggers all actions that are registered for events that are in the current event + * queue + */ + void triggerActions() const; + + static scripting::LuaLibrary luaLibrary(); + +private: + /// The storage space in which Events are stored + ghoul::MemoryPool<4096> _memory; + /// The first event in the chain of events stored in the memory pool + events::Event* _firstEvent = nullptr; + /// The last event in the chain of events stored in the memory pool + events::Event* _lastEvent = nullptr; + + struct ActionInfo { + std::string action; + std::optional filter; + }; + std::unordered_map> _eventActions; + +#ifdef _DEBUG + /// Stores the total number of events during this frame for debugging purposes + static uint64_t nEvents; +#endif // _DEBUG +}; + +} // namespace openspace + +#include "eventengine.inl" + +#endif // __OPENSPACE_CORE___EVENTENGINE___H__ diff --git a/include/openspace/events/eventengine.inl b/include/openspace/events/eventengine.inl new file mode 100644 index 0000000000..019540b48b --- /dev/null +++ b/include/openspace/events/eventengine.inl @@ -0,0 +1,51 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2021 * + * * + * 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 + +namespace openspace { + +template +void EventEngine::publishEvent(Args&&... args) { + static_assert( + std::is_base_of::value, + "T must be a subclass of Event" + ); + + T* e = _memory.alloc(args...); + if (!_firstEvent) { + _firstEvent = e; + _lastEvent = e; + } + else { + _lastEvent->next = e; + _lastEvent = e; + } + +#ifdef _DEBUG + nEvents++; +#endif // _DEBUG +} + +} // namespace openspace diff --git a/include/openspace/navigation/navigationhandler.h b/include/openspace/navigation/navigationhandler.h index b25a14dfe5..8738c04caa 100644 --- a/include/openspace/navigation/navigationhandler.h +++ b/include/openspace/navigation/navigationhandler.h @@ -140,6 +140,7 @@ public: private: void applyNavigationState(const NavigationState& ns); + void updateCameraTransitions(); bool _playbackModeEnabled = false; @@ -147,6 +148,10 @@ private: Camera* _camera = nullptr; std::function _playbackEndCallback; + inline static const double InteractionHystersis = 0.0125; + bool _inAnchorApproachSphere = false; + bool _inAnchorReachSphere = false; + OrbitalNavigator _orbitalNavigator; KeyframeNavigator _keyframeNavigator; PathNavigator _pathNavigator; diff --git a/include/openspace/scene/scenegraphnode.h b/include/openspace/scene/scenegraphnode.h index d83fda6315..48aae21f1c 100644 --- a/include/openspace/scene/scenegraphnode.h +++ b/include/openspace/scene/scenegraphnode.h @@ -128,9 +128,17 @@ public: SceneGraphNode* parent() const; std::vector children() const; + const std::vector& onApproachAction() const; + const std::vector& onReachAction() const; + const std::vector& onRecedeAction() const; + const std::vector& onExitAction() const; + double boundingSphere() const; double interactionSphere() const; + double reachFactor() const; + double approachFactor() const; + SceneGraphNode* childNode(const std::string& identifier); const Renderable* renderable() const; @@ -155,6 +163,11 @@ private: std::vector _dependentNodes; Scene* _scene = nullptr; + std::vector _onApproachAction; + std::vector _onReachAction; + std::vector _onRecedeAction; + std::vector _onExitAction; + // If this value is 'true' GUIs are asked to hide this node from collections, as it // might be a node that is not very interesting (for example barycenters) properties::BoolProperty _guiHidden; @@ -183,6 +196,8 @@ private: properties::DoubleProperty _boundingSphere; properties::DoubleProperty _interactionSphere; + properties::DoubleProperty _approachFactor; + properties::DoubleProperty _reachFactor; properties::BoolProperty _computeScreenSpaceValues; properties::IVec2Property _screenSpacePosition; properties::BoolProperty _screenVisibility; diff --git a/include/openspace/util/memorymanager.h b/include/openspace/util/memorymanager.h index e6f8771d9e..bf8121a342 100644 --- a/include/openspace/util/memorymanager.h +++ b/include/openspace/util/memorymanager.h @@ -31,11 +31,11 @@ namespace openspace { class MemoryManager { public: - ghoul::MemoryPool<8 * 1024 * 1024, false> PersistentMemory; + ghoul::MemoryPool<8 * 1024 * 1024> PersistentMemory; // This should be replaced with a std::pmr::memory_resource wrapper around our own // Memory pool so that we can get a high-water mark out of it - ghoul::MemoryPool<100 * 4096, false> TemporaryMemory; + ghoul::MemoryPool<100 * 4096, false, true> TemporaryMemory; }; } // namespace openspace diff --git a/include/openspace/util/tstring.h b/include/openspace/util/tstring.h new file mode 100644 index 0000000000..26f41e7ea9 --- /dev/null +++ b/include/openspace/util/tstring.h @@ -0,0 +1,64 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2021 * + * * + * 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 +#include + +namespace openspace { + +/** + * This string is a temporary string that is generated using the temporary memory + * storage. This means that under no circumstances must an instance of a tstring be kept + * across frame boundaries as the temporary storage is reset at between frames. In + * exchange, the allocation of these objects is extreme fast and with barely any overhead + * associated with it. The memory accessed through a tstring object shall never be + * released manually. + */ +using tstring = std::string_view; + +/** + * Allocate and create a temporary string from the passed std::string. + * + * \param str The string to be copied into a newly allocated tstring + * \return The copy of the str as a temporary string + */ +tstring temporaryString(const std::string& str); + +/** + * Allocate and create a temporary string from the passed std::string_view. + * + * \param str The string to be copied into a newly allocated tstring + * \return The copy of the str as a temporary string + */ +tstring temporaryString(std::string_view str); + +/** + * Allocate and create a temporary string from the passed char array. + * + * \param str The string to be copied into a newly allocated tstring + * \return The copy of the str as a temporary string + */ +tstring temporaryString(const char str[]); + +} // namespace openspace diff --git a/modules/base/rendering/renderabletrailorbit.cpp b/modules/base/rendering/renderabletrailorbit.cpp index fffd3effd8..c4a20f212f 100644 --- a/modules/base/rendering/renderabletrailorbit.cpp +++ b/modules/base/rendering/renderabletrailorbit.cpp @@ -28,6 +28,13 @@ #include #include #include +#include +#include +#include +#include +#include +#include + #include #include #include diff --git a/modules/globebrowsing/src/layergroup.cpp b/modules/globebrowsing/src/layergroup.cpp index dc67b2e62b..3254049cb1 100644 --- a/modules/globebrowsing/src/layergroup.cpp +++ b/modules/globebrowsing/src/layergroup.cpp @@ -26,6 +26,9 @@ #include #include +#include +#include +#include #include #include @@ -125,17 +128,18 @@ Layer* LayerGroup::addLayer(const ghoul::Dictionary& layerDict) { } if (!layerDict.hasValue("Identifier")) { - LERROR("'Identifier' must be specified for layer."); + LERROR("'Identifier' must be specified for layer"); return nullptr; } - std::unique_ptr layer = std::make_unique(_groupId, layerDict, *this); - layer->onChange(_onChangeCallback); - if (hasPropertySubOwner(layer->identifier())) { - LINFO("Layer with identifier " + layer->identifier() + " already exists."); + std::string identifier = layerDict.value("Identifier"); + if (hasPropertySubOwner(identifier)) { + LINFO("Layer with identifier '" + identifier + "' already exists"); _levelBlendingEnabled.setVisibility(properties::Property::Visibility::User); return nullptr; } + std::unique_ptr layer = std::make_unique(_groupId, layerDict, *this); + layer->onChange(_onChangeCallback); Layer* ptr = layer.get(); _layers.push_back(std::move(layer)); update(); @@ -144,6 +148,17 @@ Layer* LayerGroup::addLayer(const ghoul::Dictionary& layerDict) { } addPropertySubOwner(ptr); _levelBlendingEnabled.setVisibility(properties::Property::Visibility::User); + + properties::PropertyOwner* layerGroup = ptr->owner(); + properties::PropertyOwner* layerManager = layerGroup->owner(); + properties::PropertyOwner* globe = layerManager->owner(); + properties::PropertyOwner* sceneGraphNode = globe->owner(); + + global::eventEngine->publishEvent( + sceneGraphNode->identifier(), + layerGroup->identifier(), + ptr->identifier() + ); return ptr; } @@ -159,6 +174,15 @@ void LayerGroup::deleteLayer(const std::string& layerName) { removePropertySubOwner(it->get()); (*it)->deinitialize(); _layers.erase(it); + properties::PropertyOwner* layerGroup = it->get()->owner(); + properties::PropertyOwner* layerManager = layerGroup->owner(); + properties::PropertyOwner* globe = layerManager->owner(); + properties::PropertyOwner* sceneGraphNode = globe->owner(); + global::eventEngine->publishEvent( + sceneGraphNode->identifier(), + layerGroup->identifier(), + it->get()->identifier() + ); update(); if (_onChangeCallback) { _onChangeCallback(nullptr); diff --git a/openspace.cfg b/openspace.cfg index 6828473069..9be037a435 100644 --- a/openspace.cfg +++ b/openspace.cfg @@ -222,6 +222,7 @@ LoadingScreen = { } CheckOpenGLState = false LogEachOpenGLCall = false +PrintEvents = false ShutdownCountdown = 3 ScreenshotUseDate = true diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 187628bdce..9fe2d9fbdd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -43,6 +43,9 @@ set(OPENSPACE_SOURCE ${OPENSPACE_BASE_DIR}/src/engine/openspaceengine_lua.inl ${OPENSPACE_BASE_DIR}/src/engine/syncengine.cpp ${OPENSPACE_BASE_DIR}/src/engine/virtualpropertymanager.cpp + ${OPENSPACE_BASE_DIR}/src/events/event.cpp + ${OPENSPACE_BASE_DIR}/src/events/eventengine.cpp + ${OPENSPACE_BASE_DIR}/src/events/eventengine_lua.inl ${OPENSPACE_BASE_DIR}/src/interaction/actionmanager.cpp ${OPENSPACE_BASE_DIR}/src/interaction/actionmanager_lua.inl ${OPENSPACE_BASE_DIR}/src/interaction/camerainteractionstates.cpp @@ -176,6 +179,7 @@ set(OPENSPACE_SOURCE ${OPENSPACE_BASE_DIR}/src/util/spicemanager_lua.inl ${OPENSPACE_BASE_DIR}/src/util/syncbuffer.cpp ${OPENSPACE_BASE_DIR}/src/util/synchronizationwatcher.cpp + ${OPENSPACE_BASE_DIR}/src/util/tstring.cpp ${OPENSPACE_BASE_DIR}/src/util/histogram.cpp ${OPENSPACE_BASE_DIR}/src/util/task.cpp ${OPENSPACE_BASE_DIR}/src/util/taskloader.cpp @@ -223,6 +227,9 @@ set(OPENSPACE_HEADER ${OPENSPACE_BASE_DIR}/include/openspace/engine/syncengine.h ${OPENSPACE_BASE_DIR}/include/openspace/engine/virtualpropertymanager.h ${OPENSPACE_BASE_DIR}/include/openspace/engine/windowdelegate.h + ${OPENSPACE_BASE_DIR}/include/openspace/events/event.h + ${OPENSPACE_BASE_DIR}/include/openspace/events/eventengine.h + ${OPENSPACE_BASE_DIR}/include/openspace/events/eventengine.inl ${OPENSPACE_BASE_DIR}/include/openspace/interaction/action.h ${OPENSPACE_BASE_DIR}/include/openspace/interaction/actionmanager.h ${OPENSPACE_BASE_DIR}/include/openspace/interaction/delayedvariable.h @@ -381,6 +388,7 @@ set(OPENSPACE_HEADER ${OPENSPACE_BASE_DIR}/include/openspace/util/timemanager.h ${OPENSPACE_BASE_DIR}/include/openspace/util/timerange.h ${OPENSPACE_BASE_DIR}/include/openspace/util/touch.h + ${OPENSPACE_BASE_DIR}/include/openspace/util/tstring.h ${OPENSPACE_BASE_DIR}/include/openspace/util/universalhelpers.h ${OPENSPACE_BASE_DIR}/include/openspace/util/updatestructures.h ${OPENSPACE_BASE_DIR}/include/openspace/util/versionchecker.h diff --git a/src/documentation/core_registration.cpp b/src/documentation/core_registration.cpp index 0e604f34e5..f9d5d63c20 100644 --- a/src/documentation/core_registration.cpp +++ b/src/documentation/core_registration.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -77,13 +78,14 @@ void registerCoreClasses(documentation::DocumentationEngine& engine) { // documentation version. void registerCoreClasses(scripting::ScriptEngine& engine) { engine.addLibrary(Dashboard::luaLibrary()); + engine.addLibrary(EventEngine::luaLibrary()); engine.addLibrary(MissionManager::luaLibrary()); engine.addLibrary(ModuleEngine::luaLibrary()); engine.addLibrary(OpenSpaceEngine::luaLibrary()); engine.addLibrary(ParallelPeer::luaLibrary()); + engine.addLibrary(Profile::luaLibrary()); engine.addLibrary(RenderEngine::luaLibrary()); engine.addLibrary(SpiceManager::luaLibrary()); - engine.addLibrary(Profile::luaLibrary()); engine.addLibrary(Scene::luaLibrary()); engine.addLibrary(Time::luaLibrary()); engine.addLibrary(interaction::ActionManager::luaLibrary()); diff --git a/src/engine/configuration.cpp b/src/engine/configuration.cpp index 454ee1f6a3..681315b554 100644 --- a/src/engine/configuration.cpp +++ b/src/engine/configuration.cpp @@ -295,6 +295,11 @@ namespace { // 'false' std::optional logEachOpenGLCall; + // Determines whether events are printed as debug messages to the console each + // frame. If this value is set it determines the default value of the property of + // the OpenSpaceEngine with the same name + std::optional printEvents; + // This value determines whether the initialization of the scene graph should // occur multithreaded, that is, whether multiple scene graph nodes should // initialize in parallel. The only use for this value is to disable it for @@ -391,6 +396,7 @@ void parseLuaState(Configuration& configuration) { p.useMultithreadedInitialization.value_or(c.useMultithreadedInitialization); c.isCheckingOpenGLState = p.checkOpenGLState.value_or(c.isCheckingOpenGLState); c.isLoggingOpenGLCalls = p.logEachOpenGLCall.value_or(c.isLoggingOpenGLCalls); + c.isPrintingEvents = p.printEvents.value_or(c.isPrintingEvents); c.shutdownCountdown = p.shutdownCountdown.value_or(c.shutdownCountdown); c.shouldUseScreenshotDate = p.screenshotUseDate.value_or(c.shouldUseScreenshotDate); if (p.onScreenTextScaling.has_value()) { diff --git a/src/engine/globals.cpp b/src/engine/globals.cpp index 79667a34bd..e2740f9679 100644 --- a/src/engine/globals.cpp +++ b/src/engine/globals.cpp @@ -24,14 +24,15 @@ #include -#include #include +#include #include #include #include #include #include #include +#include #include #include #include @@ -71,12 +72,13 @@ namespace { // in some random global randoms #ifdef WIN32 constexpr const int TotalSize = + sizeof(MemoryManager) + + sizeof(EventEngine) + sizeof(ghoul::fontrendering::FontManager) + sizeof(Dashboard) + sizeof(DeferredcasterManager) + sizeof(DownloadManager) + sizeof(LuaConsole) + - sizeof(MemoryManager) + sizeof(MissionManager) + sizeof(ModuleEngine) + sizeof(OpenSpaceEngine) + @@ -119,6 +121,22 @@ void create() { std::byte* currentPos = DataStorage.data(); #endif // WIN32 +#ifdef WIN32 + memoryManager = new (currentPos) MemoryManager; + ghoul_assert(memoryManager, "No memoryManager"); + currentPos += sizeof(MemoryManager); +#else // ^^^ WIN32 / !WIN32 vvv + memoryManager = new MemoryManager; +#endif // WIN32 + +#ifdef WIN32 + eventEngine = new (currentPos) EventEngine; + ghoul_assert(eventEngine, "No eventEngine"); + currentPos += sizeof(EventEngine); +#else // ^^^ WIN32 / !WIN32 vvv + downloadManager = new EventEngine; +#endif // WIN32 + #ifdef WIN32 fontManager = new (currentPos) ghoul::fontrendering::FontManager({ 1536, 1536, 1 }); ghoul_assert(fontManager, "No fontManager"); @@ -159,14 +177,6 @@ void create() { luaConsole = new LuaConsole; #endif // WIN32 -#ifdef WIN32 - memoryManager = new (currentPos) MemoryManager; - ghoul_assert(memoryManager, "No memoryManager"); - currentPos += sizeof(MemoryManager); -#else // ^^^ WIN32 / !WIN32 vvv - memoryManager = new MemoryManager; -#endif // WIN32 - #ifdef WIN32 missionManager = new (currentPos) MissionManager; ghoul_assert(missionManager, "No missionManager"); @@ -573,13 +583,6 @@ void destroy() { delete missionManager; #endif // WIN32 - LDEBUGC("Globals", "Destroying 'MemoryManager'"); -#ifdef WIN32 - memoryManager->~MemoryManager(); -#else // ^^^ WIN32 / !WIN32 vvv - delete memoryManager; -#endif // WIN32 - LDEBUGC("Globals", "Destroying 'LuaConsole'"); #ifdef WIN32 luaConsole->~LuaConsole(); @@ -615,6 +618,20 @@ void destroy() { delete fontManager; #endif // WIN32 + LDEBUGC("Globals", "Destroying 'EventEngine'"); +#ifdef WIN32 + eventEngine->~EventEngine(); +#else // ^^^ WIN32 / !WIN32 vvv + delete eventEngine; +#endif // WIN32 + + LDEBUGC("Globals", "Destroying 'MemoryManager'"); +#ifdef WIN32 + memoryManager->~MemoryManager(); +#else // ^^^ WIN32 / !WIN32 vvv + delete memoryManager; +#endif // WIN32 + callback::destroy(); } diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index f0c98acbe8..efbaae7daa 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -36,6 +36,8 @@ #include #include #include +#include +#include #include #include #include @@ -53,6 +55,7 @@ #include #include #include +#include #include #include #include @@ -101,13 +104,22 @@ namespace { template overloaded(Ts...)->overloaded; constexpr const char* _loggerCat = "OpenSpaceEngine"; + + openspace::properties::Property::PropertyInfo PrintEventsInfo = { + "PrintEvents", + "Print Events", + "If this is enabled, all events that are propagated through the system are " + "printed to the log." + }; } // namespace namespace openspace { class Scene; -OpenSpaceEngine::OpenSpaceEngine() { +OpenSpaceEngine::OpenSpaceEngine() + : _printEvents(PrintEventsInfo, false) +{ FactoryManager::initialize(); FactoryManager::ref().addFactory( std::make_unique>(), @@ -186,6 +198,8 @@ void OpenSpaceEngine::initialize() { global::initialize(); + _printEvents = global::configuration->isPrintingEvents; + const std::string versionCheckUrl = global::configuration->versionCheckUrl; if (!versionCheckUrl.empty()) { global::versionChecker->requestLatestVersion(versionCheckUrl); @@ -895,13 +909,16 @@ void OpenSpaceEngine::deinitialize() { TransformationManager::deinitialize(); SpiceManager::deinitialize(); + if (_printEvents) { + events::Event* e = global::eventEngine->firstEvent(); + events::logAllEvents(e); + } + ghoul::fontrendering::FontRenderer::deinitialize(); ghoul::logging::LogManager::deinitialize(); LTRACE("deinitialize(end)"); - - LTRACE("OpenSpaceEngine::deinitialize(end)"); } @@ -1101,6 +1118,7 @@ void OpenSpaceEngine::preSynchronization() { resetPropertyChangeFlagsOfSubowners(global::rootPropertyOwner); _hasScheduledAssetLoading = false; _scheduledAssetPathToLoad.clear(); + global::eventEngine->publishEvent(); } else if (_isRenderingFirstFrame) { global::profile->ignoreUpdates = true; @@ -1186,6 +1204,9 @@ void OpenSpaceEngine::postSynchronizationPreDraw() { if (_shutdown.inShutdown) { if (_shutdown.timer <= 0.f) { + global::eventEngine->publishEvent( + events::EventApplicationShutdown::State::Finished + ); global::windowDelegate->terminate(); return; } @@ -1311,6 +1332,23 @@ void OpenSpaceEngine::postDraw() { _isRenderingFirstFrame = false; } + // + // Handle events + // + const events::Event* e = global::eventEngine->firstEvent(); + if (_printEvents) { + events::logAllEvents(e); + } + global::eventEngine->triggerActions(); + while (e) { + // @TODO (abock, 2021-08-25) Need to send all events to a topic to be sent out to + // others + + e = e->next; + } + + + global::eventEngine->postFrameCleanup(); global::memoryManager->PersistentMemory.housekeeping(); LTRACE("OpenSpaceEngine::postDraw(end)"); @@ -1544,11 +1582,17 @@ void OpenSpaceEngine::toggleShutdownMode() { if (_shutdown.inShutdown) { // If we are already in shutdown mode, we want to disable it _shutdown.inShutdown = false; + global::eventEngine->publishEvent( + events::EventApplicationShutdown::State::Aborted + ); } else { // Else, we have to enable it _shutdown.timer = _shutdown.waitTime; _shutdown.inShutdown = true; + global::eventEngine->publishEvent( + events::EventApplicationShutdown::State::Started + ); } } diff --git a/src/events/event.cpp b/src/events/event.cpp new file mode 100644 index 0000000000..f056c2ad33 --- /dev/null +++ b/src/events/event.cpp @@ -0,0 +1,595 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2021 * + * * + * 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { + constexpr const char _loggerCat[] = "EventInfo"; +} // namespace + +using namespace std::string_literals; + +namespace openspace::events { + +void log(int i, const EventSceneGraphNodeAdded& e) { + ghoul_assert(e.type == EventSceneGraphNodeAdded::Type, "Wrong type"); + LINFO(fmt::format("[{}] SceneGraphNodeAdded: {}", i, e.node)); +} + +void log(int i, const EventSceneGraphNodeRemoved& e) { + ghoul_assert(e.type == EventSceneGraphNodeRemoved::Type, "Wrong type"); + LINFO(fmt::format("[{}] SceneGraphNodeRemoved: {}", i, e.node)); +} + +void log(int i, const EventParallelConnection& e) { + ghoul_assert(e.type == EventParallelConnection::Type, "Wrong type"); + std::string_view state = [](EventParallelConnection::State s) { + switch (s) { + case EventParallelConnection::State::Established: return "Established"; + case EventParallelConnection::State::Lost: return "Lost"; + case EventParallelConnection::State::HostshipGained: return "HostshipGained"; + case EventParallelConnection::State::HostshipLost: return "HostshipLost"; + default: throw ghoul::MissingCaseException(); + } + }(e.state); + LINFO(fmt::format("[{}] ParallelConnection ({})", i, state)); +} + +void log(int i, [[ maybe_unused ]] const EventProfileLoadingFinished& e) { + ghoul_assert(e.type == EventProfileLoadingFinished::Type, "Wrong type"); + LINFO(fmt::format("[{}] ProfileLoadingFinished", i)); +} + +void log(int i, const EventApplicationShutdown& e) { + ghoul_assert(e.type == EventApplicationShutdown::Type, "Wrong type"); + std::string t = [](EventApplicationShutdown::State state) { + switch (state) { + case EventApplicationShutdown::State::Started: return "started"; + case EventApplicationShutdown::State::Aborted: return "aborted"; + case EventApplicationShutdown::State::Finished: return "finished"; + default: throw ghoul::MissingCaseException(); + } + }(e.state); + LINFO(fmt::format("[{}] ApplicationShutdown", i)); +} + +void log(int i, const EventScreenSpaceRenderableAdded& e) { + ghoul_assert(e.type == EventScreenSpaceRenderableAdded::Type, "Wrong type"); + LINFO(fmt::format("[{}] ScreenSpaceRenderableAdded: {}", i, e.renderable)); +} + +void log(int i, const EventScreenSpaceRenderableRemoved& e) { + ghoul_assert(e.type == EventScreenSpaceRenderableRemoved::Type, "Wrong type"); + LINFO(fmt::format("[{}] ScreenSpaceRenderableRemoved: {}", i, e.renderable)); +} + +void log(int i, const EventCameraFocusTransition& e) { + ghoul_assert(e.type == EventCameraFocusTransition::Type, "Wrong type"); + std::string_view t = [](EventCameraFocusTransition::Transition transition) { + switch (transition) { + case EventCameraFocusTransition::Transition::Approaching: + return "Approaching"; + case EventCameraFocusTransition::Transition::Reaching: + return "Reaching"; + case EventCameraFocusTransition::Transition::Receding: + return "Receding"; + case EventCameraFocusTransition::Transition::Exiting: + return "Exiting"; + default: throw ghoul::MissingCaseException(); + } + }(e.transition); + + LINFO(fmt::format( + "[{}] CameraTransition: {}, {} ({})", + i, reinterpret_cast(e.camera), e.node, t + )); +} + +void log(int i, const EventTimeOfInterestReached& e) { + ghoul_assert(e.type == EventTimeOfInterestReached::Type, "Wrong type"); + LINFO(fmt::format( + "[{}] TimeOfInterestReached: {}, {}", + i, e.time->UTC(), reinterpret_cast(e.camera) + )); +} + +void log(int i, [[ maybe_unused ]] const EventMissionEventReached& e) { + ghoul_assert(e.type == EventMissionEventReached::Type, "Wrong type"); + LINFO(fmt::format("[{}] MissionEventReached", i)); +} + +void log(int i, const EventPlanetEclipsed& e) { + ghoul_assert(e.type == EventPlanetEclipsed::Type, "Wrong type"); + LINFO(fmt::format("[{}] PlanetEclipsed: {} -> {}", i, e.eclipsee, e.eclipser)); +} + +void log(int i, [[ maybe_unused ]] const EventInterpolationFinished& e) { + ghoul_assert(e.type == EventInterpolationFinished::Type, "Wrong type"); + LINFO(fmt::format("[{}] InterpolationFinished", i)); +} + +void log(int i, const EventFocusNodeChanged& e) { + ghoul_assert(e.type == EventFocusNodeChanged::Type, "Wrong type"); + LINFO(fmt::format("[{}] FocusNodeChanged: {} -> {}", i, e.oldNode, e.newNode)); +} + +void log(int i, const EventLayerAdded& e) { + ghoul_assert(e.type == EventLayerAdded::Type, "Wrong type"); + LINFO(fmt::format("[{}] LayerAdded: {}", i, e.layer)); +} + +void log(int i, const EventLayerRemoved& e) { + ghoul_assert(e.type == EventLayerRemoved::Type, "Wrong type"); + LINFO(fmt::format("[{}] LayerRemoved: {}", i, e.layer)); +} + +void log(int i, const EventSessionRecordingPlayback& e) { + ghoul_assert(e.type == EventSessionRecordingPlayback::Type, "Wrong type"); + + std::string_view state = [](EventSessionRecordingPlayback::State s) { + switch (s) { + case EventSessionRecordingPlayback::State::Started: return "Started"; + case EventSessionRecordingPlayback::State::Paused: return "Paused"; + case EventSessionRecordingPlayback::State::Resumed: return "Resumed"; + case EventSessionRecordingPlayback::State::Finished: return "Finished"; + default: throw ghoul::MissingCaseException(); + } + }(e.state); + + LINFO(fmt::format("[{}] SessionRecordingPlayback: {}", i, state)); +} + +void log(int i, const CustomEvent& e) { + ghoul_assert(e.type == CustomEvent::Type, "Wrong type"); + LINFO(fmt::format("[{}] CustomEvent: {} ({})", i, e.subtype, e.payload)); +} + +std::string_view toString(Event::Type type) { + switch (type) { + case Event::Type::SceneGraphNodeAdded: return "SceneGraphNodeAdded"; + case Event::Type::SceneGraphNodeRemoved: return "SceneGraphNodeRemoved"; + case Event::Type::ParallelConnection: return "ParallelConnection"; + case Event::Type::ProfileLoadingFinished: return "ProfileLoadingFinished"; + case Event::Type::ApplicationShutdown: return "ApplicationShutdown"; + case Event::Type::ScreenSpaceRenderableAdded: return "ScreenSpaceRenderableAdded"; + case Event::Type::ScreenSpaceRenderableRemoved: + return "ScreenSpaceRenderableRemoved"; + case Event::Type::CameraFocusTransition: return "CameraFocusTransition"; + case Event::Type::TimeOfInterestReached: return "TimeOfInterestReached"; + case Event::Type::MissionEventReached: return "MissionEventReached"; + case Event::Type::PlanetEclipsed: return "PlanetEclipsed"; + case Event::Type::InterpolationFinished: return "InterpolationFinished"; + case Event::Type::FocusNodeChanged: return "FocusNodeChanged"; + case Event::Type::LayerAdded: return "LayerAdded"; + case Event::Type::LayerRemoved: return "LayerRemoved"; + case Event::Type::SessionRecordingPlayback: return "SessionRecordingPlayback"; + case Event::Type::Custom: return "Custom"; + default: + throw ghoul::MissingCaseException(); + } +} + +Event::Type fromString(std::string_view str) { + if (str == "SceneGraphNodeAdded") { + return Event::Type::SceneGraphNodeAdded; + } + else if (str == "SceneGraphNodeRemoved") { + return Event::Type::SceneGraphNodeRemoved; + } + else if (str == "ParallelConnection") { + return Event::Type::ParallelConnection; + } + else if (str == "ProfileLoadingFinished") { + return Event::Type::ProfileLoadingFinished; + } + else if (str == "ApplicationShutdown") { + return Event::Type::ApplicationShutdown; + } + else if (str == "ScreenSpaceRenderableAdded") { + return Event::Type::ScreenSpaceRenderableAdded; + } + else if (str == "ScreenSpaceRenderableRemoved") { + return Event::Type::ScreenSpaceRenderableRemoved; + } + else if (str == "CameraFocusTransition") { + return Event::Type::CameraFocusTransition; + } + else if (str == "TimeOfInterestReached") { + return Event::Type::TimeOfInterestReached; + } + else if (str == "MissionEventReached") { + return Event::Type::MissionEventReached; + } + else if (str == "PlanetEclipsed") { + return Event::Type::PlanetEclipsed; + } + else if (str == "InterpolationFinished") { + return Event::Type::InterpolationFinished; + } + else if (str == "FocusNodeChanged") { + return Event::Type::FocusNodeChanged; + } + else if (str == "LayerAdded") { + return Event::Type::LayerAdded; + } + else if (str == "LayerRemoved") { + return Event::Type::LayerRemoved; + } + else if (str == "SessionRecordingPlayback") { + return Event::Type::SessionRecordingPlayback; + } + else if (str == "Custom") { + return Event::Type::Custom; + } + + throw ghoul::RuntimeError(fmt::format("Unknown event type '{}'", str)); +} + +ghoul::Dictionary toParameter(const Event& e) { + ghoul::Dictionary d; + switch (e.type) { + case Event::Type::SceneGraphNodeAdded: + d.setValue( + "Node", + std::string(static_cast(e).node) + ); + break; + case Event::Type::SceneGraphNodeRemoved: + d.setValue( + "Node", + std::string(static_cast(e).node) + ); + break; + case Event::Type::ParallelConnection: + switch (static_cast(e).state) { + case EventParallelConnection::State::Established: + d.setValue("State", "Established"s); + break; + case EventParallelConnection::State::Lost: + d.setValue("State", "Lost"s); + break; + case EventParallelConnection::State::HostshipGained: + d.setValue("State", "HostshipGained"s); + break; + case EventParallelConnection::State::HostshipLost: + d.setValue("State", "HostshipLost"s); + break; + default: + throw ghoul::MissingCaseException(); + } + break; + case Event::Type::ApplicationShutdown: + switch (static_cast(e).state) { + case EventApplicationShutdown::State::Started: + d.setValue("State", "Started"s); + break; + case EventApplicationShutdown::State::Aborted: + d.setValue("State", "Aborted"s); + break; + case EventApplicationShutdown::State::Finished: + d.setValue("State", "Finished"s); + break; + } + break; + case Event::Type::ScreenSpaceRenderableAdded: + d.setValue( + "Renderable", + std::string( + static_cast(e).renderable + ) + ); + break; + case Event::Type::ScreenSpaceRenderableRemoved: + d.setValue( + "Renderable", + std::string( + static_cast(e).renderable + ) + ); + break; + case Event::Type::CameraFocusTransition: + d.setValue( + "Node", + std::string(static_cast(e).node) + ); + switch (static_cast(e).transition) { + case EventCameraFocusTransition::Transition::Approaching: + d.setValue("Transition", "Approaching"s); + break; + case EventCameraFocusTransition::Transition::Reaching: + d.setValue("Transition", "Reaching"s); + break; + case EventCameraFocusTransition::Transition::Receding: + d.setValue("Transition", "Receding"s); + break; + case EventCameraFocusTransition::Transition::Exiting: + d.setValue("Transition", "Exiting"s); + break; + default: + throw ghoul::MissingCaseException(); + } + break; + case Event::Type::PlanetEclipsed: + d.setValue( + "Eclipsee", + std::string(static_cast(e).eclipsee) + ); + d.setValue( + "Eclipser", + std::string(static_cast(e).eclipser) + ); + break; + case Event::Type::InterpolationFinished: + d.setValue( + "Property", + std::string(static_cast(e).property) + ); + break; + case Event::Type::FocusNodeChanged: + d.setValue( + "OldNode", + std::string(static_cast(e).oldNode) + ); + d.setValue( + "NewNode", + std::string(static_cast(e).newNode) + ); + break; + case Event::Type::LayerAdded: + d.setValue( + "Globe", + std::string(static_cast(e).node) + ); + d.setValue( + "Group", + std::string(static_cast(e).layerGroup) + ); + d.setValue( + "Layer", + std::string(static_cast(e).layer) + ); + break; + case Event::Type::LayerRemoved: + d.setValue( + "Globe", + std::string(static_cast(e).node) + ); + d.setValue( + "Group", + std::string(static_cast(e).layerGroup) + ); + d.setValue( + "Layer", + std::string(static_cast(e).layer) + ); + break; + case Event::Type::SessionRecordingPlayback: + switch (static_cast(e).state) { + case EventSessionRecordingPlayback::State::Started: + d.setValue("State", "Started"s); + break; + case EventSessionRecordingPlayback::State::Paused: + d.setValue("State", "Paused"s); + break; + case EventSessionRecordingPlayback::State::Resumed: + d.setValue("State", "Resumed"s); + break; + case EventSessionRecordingPlayback::State::Finished: + d.setValue("State", "Finished"s); + break; + } + break; + case Event::Type::Custom: + d.setValue( + "Subtype", std::string(static_cast(e).subtype) + ); + break; + default: + break; + } + return d; +} + +void logAllEvents(const Event* e) { + int i = 0; + while (e) { + switch (e->type) { + case Event::Type::SceneGraphNodeAdded: + log(i, *static_cast(e)); + break; + case Event::Type::SceneGraphNodeRemoved: + log(i, *static_cast(e)); + break; + case Event::Type::ParallelConnection: + log(i, *static_cast(e)); + break; + case Event::Type::ProfileLoadingFinished: + log(i, *static_cast(e)); + break; + case Event::Type::ApplicationShutdown: + log(i, *static_cast(e)); + break; + case Event::Type::ScreenSpaceRenderableAdded: + log(i, *static_cast(e)); + break; + case Event::Type::ScreenSpaceRenderableRemoved: + log(i, *static_cast(e)); + break; + case Event::Type::CameraFocusTransition: + log(i, *static_cast(e)); + break; + case Event::Type::TimeOfInterestReached: + log(i, *static_cast(e)); + break; + case Event::Type::MissionEventReached: + log(i, *static_cast(e)); + break; + case Event::Type::PlanetEclipsed: + log(i, *static_cast(e)); + break; + case Event::Type::InterpolationFinished: + log(i, *static_cast(e)); + break; + case Event::Type::FocusNodeChanged: + log(i, *static_cast(e)); + break; + case Event::Type::LayerAdded: + log(i, *static_cast(e)); + break; + case Event::Type::LayerRemoved: + log(i, *static_cast(e)); + break; + case Event::Type::SessionRecordingPlayback: + log(i, *static_cast(e)); + break; + case Event::Type::Custom: + log(i, *static_cast(e)); + break; + default: + LINFO(fmt::format("[{}]: Unknown {}", typeid(e).name())); + break; + } + + i++; + e = e->next; + } +} + +EventSceneGraphNodeAdded::EventSceneGraphNodeAdded(const SceneGraphNode* node_) + : Event(Type) + , node(temporaryString(node_->identifier())) +{} + +EventSceneGraphNodeRemoved::EventSceneGraphNodeRemoved(const SceneGraphNode* node_) + : Event(Type) + , node(temporaryString(node_->identifier())) +{} + +EventParallelConnection::EventParallelConnection(State state_) + : Event(Type) + , state(state_) +{} + +EventProfileLoadingFinished::EventProfileLoadingFinished() + : Event(Type) +{} + +EventApplicationShutdown::EventApplicationShutdown(State state_) + : Event(Type) + , state(state_) +{} + +EventScreenSpaceRenderableAdded::EventScreenSpaceRenderableAdded( + const ScreenSpaceRenderable* renderable_) + : Event(Type) + , renderable(temporaryString(renderable_->identifier())) +{} + +EventScreenSpaceRenderableRemoved::EventScreenSpaceRenderableRemoved( + const ScreenSpaceRenderable* renderable_) + : Event(Type) + , renderable(temporaryString(renderable_->identifier())) +{} + +EventCameraFocusTransition::EventCameraFocusTransition(const Camera* camera_, + const SceneGraphNode* node_, + Transition transition_) + : Event(Type) + , camera(camera_) + , node(temporaryString(node_->identifier())) + , transition(transition_) +{} + +EventTimeOfInterestReached::EventTimeOfInterestReached(const Time* time_, + const Camera* camera_) + : Event(Type) + , time(time_) + , camera(camera_) +{} + +EventMissionEventReached::EventMissionEventReached() + : Event(Type) +{} + +EventPlanetEclipsed::EventPlanetEclipsed(const SceneGraphNode* eclipsee_, + const SceneGraphNode* eclipser_) + : Event(Type) + , eclipsee(temporaryString(eclipsee_->identifier())) + , eclipser(temporaryString(eclipser_->identifier())) +{} + +EventInterpolationFinished::EventInterpolationFinished( + const properties::Property* property_) + : Event(Type) + , property(temporaryString(property_->fullyQualifiedIdentifier())) +{} + +EventFocusNodeChanged::EventFocusNodeChanged(const SceneGraphNode* oldNode_, + const SceneGraphNode* newNode_) + : Event(Type) + , oldNode(oldNode_ ? temporaryString(oldNode_->identifier()) : "") + , newNode(temporaryString(newNode_->identifier())) +{ + ghoul_assert(newNode_, "There must be a new node"); +} + +EventLayerAdded::EventLayerAdded(std::string_view node_, std::string_view layerGroup_, + std::string_view layer_) + : Event(Type) + , node(temporaryString(node_)) + , layerGroup(temporaryString(layerGroup_)) + , layer(temporaryString(layer_)) +{} + +EventLayerRemoved::EventLayerRemoved(std::string_view node_, std::string_view layerGroup_, + std::string_view layer_) + : Event(Type) + , node(temporaryString(node_)) + , layerGroup(temporaryString(layerGroup_)) + , layer(temporaryString(layer_)) +{} + +EventSessionRecordingPlayback::EventSessionRecordingPlayback(State state_) + : Event(Type) + , state(state_) +{} + +CustomEvent::CustomEvent(std::string_view subtype_, const void* payload_) + : Event(Type) + , subtype(subtype_) + , payload(payload_) +{} + +} // namespace openspace::events diff --git a/src/events/eventengine.cpp b/src/events/eventengine.cpp new file mode 100644 index 0000000000..b01e1502a0 --- /dev/null +++ b/src/events/eventengine.cpp @@ -0,0 +1,133 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2021 * + * * + * 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 + +#include +#include + +#include "eventengine_lua.inl" + +namespace openspace { + +#ifdef _DEBUG +uint64_t EventEngine::nEvents = 0; +#endif // _DEBUG + +events::Event* EventEngine::firstEvent() const { + return _firstEvent; +} + +void EventEngine::postFrameCleanup() { + _memory.reset(); + _firstEvent = nullptr; + _lastEvent = nullptr; +#ifdef _DEBUG + nEvents = 0; +#endif // _DEBUG +} + +void EventEngine::registerEventAction(events::Event::Type type, + std::string identifier, + std::optional filter) +{ + ActionInfo ai; + ai.action = std::move(identifier); + ai.filter = std::move(filter); + const auto it = _eventActions.find(type); + if (it != _eventActions.end()) { + it->second.push_back(ai); + } + else { + _eventActions[type] = { std::move(ai) }; + } +} + +void EventEngine::unregisterEventAction(events::Event::Type type, + const std::string& identifier, + std::optional filter) +{ + const auto it = _eventActions.find(type); + if (it != _eventActions.end()) { + const auto jt = std::find_if( + it->second.begin(), it->second.end(), + [identifier, filter](const ActionInfo& ai) { + const bool a = ai.action == identifier; + const bool f = !filter.has_value() || *filter == ai.filter; + return a && f; + } + ); + if (jt != it->second.end()) { + it->second.erase(jt); + } + } +} + +void EventEngine::triggerActions() const { + if (_eventActions.empty()) { + // Nothing to do here + return; + } + + const events::Event* e = _firstEvent; + while (e) { + const auto it = _eventActions.find(e->type); + if (it != _eventActions.end()) { + ghoul::Dictionary params = toParameter(*e); + for (const ActionInfo& ai : it->second) { + if (!ai.filter.has_value() || params.isSubset(*ai.filter)) { + global::actionManager->triggerAction(ai.action, params); + } + } + } + + e = e->next; + } +} + +scripting::LuaLibrary EventEngine::luaLibrary() { + scripting::LuaLibrary res; + res.name = "event"; + res.functions.push_back({ + "registerEventAction", + &luascriptfunctions::registerEventAction, + {}, + "string, string [, table]", + "Registers an action (second parameter) to be executed whenever an event (first " + "parameter) is encountered. If the optional third parameter is provided, it " + "describes a filter that the event is being checked against and only if it " + "passes the filter, the action is triggered" + }); + res.functions.push_back({ + "unregisterEventAction", + &luascriptfunctions::unregisterEventAction, + {}, + "string, string [, table]", + "Unregisters a specific combination of event (first parameter), action (second " + "parameter), and potentially a filter (optional third argument)" + }); + return res; +} + +} // namespace openspace diff --git a/src/events/eventengine_lua.inl b/src/events/eventengine_lua.inl new file mode 100644 index 0000000000..0d6bef77ba --- /dev/null +++ b/src/events/eventengine_lua.inl @@ -0,0 +1,49 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2021 * + * * + * 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. * + ****************************************************************************************/ + +namespace openspace::luascriptfunctions { + +int registerEventAction(lua_State* L) { + ghoul::lua::checkArgumentsAndThrow(L, { 2, 3 }, "lua::registerEventAction"); + auto [event, action, filter] = + ghoul::lua::values>(L); + + events::Event::Type type = events::fromString(event); + + global::eventEngine->registerEventAction(type, std::move(action), std::move(filter)); + return 0; +} + +int unregisterEventAction(lua_State* L) { + ghoul::lua::checkArgumentsAndThrow(L, { 2, 3 }, "lua::unregisterEventAction"); + auto [event, action, filter] = + ghoul::lua::values>(L); + + events::Event::Type type = events::fromString(event); + + global::eventEngine->unregisterEventAction(type, action, filter); + return 0; +} + +} // namespace openspace::luascriptfunctions diff --git a/src/interaction/actionmanager.cpp b/src/interaction/actionmanager.cpp index 89a112b0d5..b16f79c5d6 100644 --- a/src/interaction/actionmanager.cpp +++ b/src/interaction/actionmanager.cpp @@ -86,7 +86,14 @@ void ActionManager::triggerAction(const std::string& identifier, const ghoul::Dictionary& arguments) const { ghoul_assert(!identifier.empty(), "Identifier must not be empty"); - ghoul_assert(hasAction(identifier), "Action was not found in the list"); + + if (!hasAction(identifier)) { + LWARNINGC( + "ActionManager", + fmt::format("Action '{}' not found in the list", identifier) + ); + return; + } const Action& a = action(identifier); if (arguments.isEmpty()) { @@ -97,7 +104,7 @@ void ActionManager::triggerAction(const std::string& identifier, } else { global::scriptEngine->queueScript( - fmt::format("local args = {}\n{}", ghoul::formatLua(arguments), a.command), + fmt::format("args = {}\n{}", ghoul::formatLua(arguments), a.command), scripting::ScriptEngine::RemoteScripting(a.synchronization) ); } diff --git a/src/interaction/sessionrecording.cpp b/src/interaction/sessionrecording.cpp index fe390e3648..2c4b8da045 100644 --- a/src/interaction/sessionrecording.cpp +++ b/src/interaction/sessionrecording.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -461,6 +462,9 @@ bool SessionRecording::startPlayback(std::string& filename, (_playbackForceSimTimeAtStart ? 1 : 0) )); + global::eventEngine->publishEvent( + events::EventSessionRecordingPlayback::State::Started + ); initializePlayback_triggerStart(); global::navigationHandler->orbitalNavigator().updateOnCameraInteraction(); @@ -527,12 +531,18 @@ void SessionRecording::setPlaybackPause(bool pause) { global::timeManager->setPause(true); } _state = SessionState::PlaybackPaused; + global::eventEngine->publishEvent( + events::EventSessionRecordingPlayback::State::Paused + ); } else if (!pause && _state == SessionState::PlaybackPaused) { if (!_playbackPausedWithinDeltaTimePause) { global::timeManager->setPause(false); } _state = SessionState::Playback; + global::eventEngine->publishEvent( + events::EventSessionRecordingPlayback::State::Resumed + ); } } @@ -575,7 +585,7 @@ void SessionRecording::signalPlaybackFinishedForComponent(RecordedType type) { if (!_playbackActive_camera && !_playbackActive_time && !_playbackActive_script) { if (_playbackLoopMode) { - //Loop back to the beginning to replay + // Loop back to the beginning to replay _saveRenderingDuringPlayback = false; initializePlayback_time(global::windowDelegate->applicationTime()); initializePlayback_modeFlags(); @@ -586,6 +596,9 @@ void SessionRecording::signalPlaybackFinishedForComponent(RecordedType type) { _state = SessionState::Idle; _cleanupNeeded = true; LINFO("Playback session finished"); + global::eventEngine->publishEvent( + events::EventSessionRecordingPlayback::State::Finished + ); } } } @@ -606,6 +619,9 @@ void SessionRecording::stopPlayback() { _state = SessionState::Idle; _cleanupNeeded = true; LINFO("Session playback stopped"); + global::eventEngine->publishEvent( + events::EventSessionRecordingPlayback::State::Finished + ); } } diff --git a/src/navigation/navigationhandler.cpp b/src/navigation/navigationhandler.cpp index 73d74d4c66..f3d18229d5 100644 --- a/src/navigation/navigationhandler.cpp +++ b/src/navigation/navigationhandler.cpp @@ -27,6 +27,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -175,6 +178,7 @@ void NavigationHandler::updateCamera(double deltaTime) { } else if (_pathNavigator.isPlayingPath()) { _pathNavigator.updateCamera(deltaTime); + updateCameraTransitions(); } else { if (_disableJoystickInputs) { @@ -186,6 +190,7 @@ void NavigationHandler::updateCamera(double deltaTime) { } _orbitalNavigator.updateStatesFromInput(_inputState, deltaTime); _orbitalNavigator.updateCameraStateFromStates(deltaTime); + updateCameraTransitions(); } _orbitalNavigator.updateCameraScalingFromAnchor(deltaTime); @@ -208,6 +213,118 @@ void NavigationHandler::applyNavigationState(const NavigationState& ns) { _orbitalNavigator.clearPreviousState(); } +void NavigationHandler::updateCameraTransitions() { + // This function is concerned with managing transitions of the camera between + // different distances of interest relative to the focus node. For each transition two + // scenarios are handled; SceneGraphNodes can have attached actions for each + // transition, which are automatically triggered. Additionally, an + // EventCameraTransition event is fired that contains information about the focus node + // and the transition state that caused the vent to fire. + + // Diagram of events for a camera moving from right-to-left. + // Interaction sphere is 'O' in middle, and ')' are spherical boundaries. The approach + // factor, reach factor, and interaction sphere radius are all taken from the current + // focus node. + // + // |<------------------->| Approach factor * Interaction sphere + // |<------>| Reach Factor * Interaction sphere + // + // ( ( O ) ) + // ^ ^ ^ ^ + // OnExit OnMoveAway OnReach OnApproach + const glm::dvec3 anchorPos = anchorNode()->worldPosition(); + const glm::dvec3 cameraPos = _camera->positionVec3(); + const double currDistance = glm::distance(anchorPos, cameraPos); + const double d = anchorNode()->interactionSphere(); + const double af = anchorNode()->approachFactor(); + const double rf = anchorNode()->reachFactor(); + + using namespace std::string_literals; + if (_inAnchorApproachSphere) { + if (currDistance > d * (af + InteractionHystersis)) { + // We left the approach sphere outwards + _inAnchorApproachSphere = false; + + if (!anchorNode()->onExitAction().empty()) { + ghoul::Dictionary dict; + dict.setValue("Node", anchorNode()->identifier()); + dict.setValue("Transition", "Exiting"s); + for (const std::string& action : anchorNode()->onExitAction()) { + global::actionManager->triggerAction(action, dict); + } + } + + global::eventEngine->publishEvent( + _camera, + anchorNode(), + events::EventCameraFocusTransition::Transition::Exiting + ); + } + else if (currDistance < d * (rf - InteractionHystersis)) { + // We transitioned from the approach sphere into the reach sphere + _inAnchorApproachSphere = false; + _inAnchorReachSphere = true; + + if (!anchorNode()->onReachAction().empty()) { + ghoul::Dictionary dict; + dict.setValue("Node", anchorNode()->identifier()); + dict.setValue("Transition", "Reaching"s); + for (const std::string& action : anchorNode()->onReachAction()) { + global::actionManager->triggerAction(action, dict); + } + } + + global::eventEngine->publishEvent( + _camera, + anchorNode(), + events::EventCameraFocusTransition::Transition::Reaching + ); + } + } + else if (_inAnchorReachSphere && currDistance > d * (rf + InteractionHystersis)) { + // We transitioned from the reach sphere to the approach sphere + _inAnchorReachSphere = false; + _inAnchorApproachSphere = true; + + if (!anchorNode()->onRecedeAction().empty()) { + ghoul::Dictionary dict; + dict.setValue("Node", anchorNode()->identifier()); + dict.setValue("Transition", "Receding"s); + for (const std::string& action : anchorNode()->onRecedeAction()) { + global::actionManager->triggerAction(action, dict); + } + } + + global::eventEngine->publishEvent( + _camera, + anchorNode(), + events::EventCameraFocusTransition::Transition::Receding + ); + } + else if (!_inAnchorApproachSphere && !_inAnchorReachSphere && + currDistance < d * (af - InteractionHystersis)) + { + // We moved into the approach sphere + _inAnchorApproachSphere = true; + + if (!anchorNode()->onApproachAction().empty()) { + ghoul::Dictionary dict; + dict.setValue("Node", anchorNode()->identifier()); + dict.setValue("Transition", "Approaching"s); + for (const std::string& action : anchorNode()->onApproachAction()) { + global::actionManager->triggerAction(action, dict); + } + } + + global::eventEngine->publishEvent( + _camera, + anchorNode(), + events::EventCameraFocusTransition::Transition::Approaching + ); + } +} + + void NavigationHandler::setEnableKeyFrameInteraction() { _useKeyFrameInteraction = true; } diff --git a/src/navigation/orbitalnavigator.cpp b/src/navigation/orbitalnavigator.cpp index 0be1d03c89..13623fb3e3 100644 --- a/src/navigation/orbitalnavigator.cpp +++ b/src/navigation/orbitalnavigator.cpp @@ -27,6 +27,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -353,7 +356,12 @@ OrbitalNavigator::OrbitalNavigator() } SceneGraphNode* node = sceneGraphNode(_anchor.value()); if (node) { + const SceneGraphNode* previousAnchor = _anchorNode; setAnchorNode(node); + global::eventEngine->publishEvent( + previousAnchor, + node + ); } else { LERROR(fmt::format( @@ -804,8 +812,14 @@ glm::dvec3 OrbitalNavigator::cameraToSurfaceVector(const glm::dvec3& cameraPos, void OrbitalNavigator::setFocusNode(const SceneGraphNode* focusNode, bool resetVelocitiesOnChange) { + const SceneGraphNode* previousAnchor = _anchorNode; setAnchorNode(focusNode, resetVelocitiesOnChange); setAimNode(nullptr); + + global::eventEngine->publishEvent( + previousAnchor, + focusNode + ); } void OrbitalNavigator::setFocusNode(const std::string& focusNode, bool) { @@ -953,8 +967,8 @@ bool OrbitalNavigator::shouldFollowAnchorRotation(const glm::dvec3& cameraPositi const double distanceToCamera = glm::distance(cameraPosition, _anchorNode->worldPosition()); - - return distanceToCamera < maximumDistanceForRotation; + bool shouldFollow = distanceToCamera < maximumDistanceForRotation; + return shouldFollow; } bool OrbitalNavigator::followingAnchorRotation() const { diff --git a/src/network/parallelpeer.cpp b/src/network/parallelpeer.cpp index a4f5f77f8a..b5ee89dd38 100644 --- a/src/network/parallelpeer.cpp +++ b/src/network/parallelpeer.cpp @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #include #include @@ -215,7 +217,7 @@ void ParallelPeer::handleMessage(const ParallelConnection::Message& message) { nConnectionsMessageReceived(message.content); break; default: - //unknown message type + // unknown message type break; } } @@ -259,8 +261,7 @@ double ParallelPeer::latencyStandardDeviation() const { return std::sqrt(latencyVariance); } -void ParallelPeer::dataMessageReceived(const std::vector& message) -{ +void ParallelPeer::dataMessageReceived(const std::vector& message) { size_t offset = 0; // The type of data message received @@ -290,8 +291,10 @@ void ParallelPeer::dataMessageReceived(const std::vector& message) pose.scale = kf._scale; pose.followFocusNodeRotation = kf._followNodeRotation; - global::navigationHandler->keyframeNavigator().addKeyframe(convertedTimestamp, - pose); + global::navigationHandler->keyframeNavigator().addKeyframe( + convertedTimestamp, + pose + ); break; } case datamessagestructures::Type::TimelineData: { @@ -359,10 +362,9 @@ void ParallelPeer::dataMessageReceived(const std::vector& message) } } -void ParallelPeer::connectionStatusMessageReceived(const std::vector& message) - { +void ParallelPeer::connectionStatusMessageReceived(const std::vector& message) { if (message.size() < 2 * sizeof(uint32_t)) { - LERROR("Malformed connection status message."); + LERROR("Malformed connection status message"); return; } size_t pointer = 0; @@ -376,7 +378,7 @@ void ParallelPeer::connectionStatusMessageReceived(const std::vector& mess pointer += sizeof(uint32_t); if (hostNameSize > message.size() - pointer) { - LERROR("Malformed connection status message."); + LERROR("Malformed connection status message"); return; } @@ -387,7 +389,7 @@ void ParallelPeer::connectionStatusMessageReceived(const std::vector& mess pointer += hostNameSize; if (status > ParallelConnection::Status::Host) { - LERROR("Invalid status."); + LERROR("Invalid status"); return; } @@ -410,7 +412,7 @@ void ParallelPeer::connectionStatusMessageReceived(const std::vector& mess void ParallelPeer::nConnectionsMessageReceived(const std::vector& message) { if (message.size() < sizeof(uint32_t)) { - LERROR("Malformed host info message."); + LERROR("Malformed host info message"); return; } const uint32_t nConnections = *(reinterpret_cast(&message[0])); @@ -532,9 +534,54 @@ void ParallelPeer::preSynchronization() { void ParallelPeer::setStatus(ParallelConnection::Status status) { if (_status != status) { + ParallelConnection::Status prevStatus = _status; _status = status; _timeJumped = true; _connectionEvent->publish("statusChanged"); + + + EventEngine* ee = global::eventEngine; + const bool isConnected = + status == ParallelConnection::Status::ClientWithoutHost || + status == ParallelConnection::Status::ClientWithHost || + status == ParallelConnection::Status::Host; + const bool wasConnected = + prevStatus == ParallelConnection::Status::ClientWithoutHost || + prevStatus == ParallelConnection::Status::ClientWithHost || + prevStatus == ParallelConnection::Status::Host; + const bool isDisconnected = status == ParallelConnection::Status::Disconnected; + const bool wasDisconnected = + prevStatus == ParallelConnection::Status::Disconnected; + const bool isHost = status == ParallelConnection::Status::Host; + const bool wasHost = prevStatus == ParallelConnection::Status::Host; + const bool isClient = + status == ParallelConnection::Status::ClientWithoutHost || + status == ParallelConnection::Status::ClientWithHost; + const bool wasClient = + prevStatus == ParallelConnection::Status::ClientWithoutHost || + prevStatus == ParallelConnection::Status::ClientWithHost; + + + if (isDisconnected && wasConnected) { + ee->publishEvent( + events::EventParallelConnection::State::Lost + ); + } + if (isConnected && wasDisconnected) { + ee->publishEvent( + events::EventParallelConnection::State::Established + ); + } + if (isHost && (wasClient || wasDisconnected)) { + ee->publishEvent( + events::EventParallelConnection::State::HostshipGained + ); + } + if ((isClient || isDisconnected) && wasHost) { + ee->publishEvent( + events::EventParallelConnection::State::HostshipLost + ); + } } if (isHost()) { global::timeManager->addTimeJumpCallback([this]() { diff --git a/src/properties/propertyowner.cpp b/src/properties/propertyowner.cpp index 94c716e826..4426580f8d 100644 --- a/src/properties/propertyowner.cpp +++ b/src/properties/propertyowner.cpp @@ -24,6 +24,9 @@ #include +#include +#include +#include #include #include #include diff --git a/src/rendering/renderengine.cpp b/src/rendering/renderengine.cpp index d7c68c6e1b..7bdb20d222 100644 --- a/src/rendering/renderengine.cpp +++ b/src/rendering/renderengine.cpp @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include #include #include @@ -1105,8 +1107,11 @@ void RenderEngine::addScreenSpaceRenderable(std::unique_ptrinitialize(); s->initializeGL(); - global::screenSpaceRootPropertyOwner->addPropertySubOwner(s.get()); + ScreenSpaceRenderable* ssr = s.get(); + global::screenSpaceRootPropertyOwner->addPropertySubOwner(ssr); global::screenSpaceRenderables->push_back(std::move(s)); + + global::eventEngine->publishEvent(ssr); } void RenderEngine::removeScreenSpaceRenderable(ScreenSpaceRenderable* s) { @@ -1119,9 +1124,10 @@ void RenderEngine::removeScreenSpaceRenderable(ScreenSpaceRenderable* s) { if (it != global::screenSpaceRenderables->end()) { s->deinitialize(); global::screenSpaceRootPropertyOwner->removePropertySubOwner(s); - global::screenSpaceRenderables->erase(it); } + + global::eventEngine->publishEvent(s); } void RenderEngine::removeScreenSpaceRenderable(const std::string& identifier) { @@ -1131,8 +1137,7 @@ void RenderEngine::removeScreenSpaceRenderable(const std::string& identifier) { } } -ScreenSpaceRenderable* RenderEngine::screenSpaceRenderable( - const std::string& identifier) +ScreenSpaceRenderable* RenderEngine::screenSpaceRenderable(const std::string& identifier) { const auto it = std::find_if( global::screenSpaceRenderables->begin(), diff --git a/src/scene/profile.cpp b/src/scene/profile.cpp index 938335bcdc..9ded721ecc 100644 --- a/src/scene/profile.cpp +++ b/src/scene/profile.cpp @@ -598,13 +598,9 @@ void Profile::removeAsset(const std::string& path) { } const auto it = std::find(assets.cbegin(), assets.cend(), path); - if (it == assets.end()) { - throw ghoul::RuntimeError(fmt::format( - "Tried to remove non-existing asset '{}'", path - )); + if (it != assets.end()) { + assets.erase(it); } - - assets.erase(it); } std::string Profile::serialize() const { diff --git a/src/scene/scene.cpp b/src/scene/scene.cpp index e17b48f11e..f673ecf336 100644 --- a/src/scene/scene.cpp +++ b/src/scene/scene.cpp @@ -125,6 +125,7 @@ void Scene::registerNode(SceneGraphNode* node) { _nodesByIdentifier[node->identifier()] = node; addPropertySubOwner(node); _dirtyNodeRegistry = true; + global::eventEngine->publishEvent(node); } void Scene::unregisterNode(SceneGraphNode* node) { @@ -144,6 +145,7 @@ void Scene::unregisterNode(SceneGraphNode* node) { } removePropertySubOwner(node); _dirtyNodeRegistry = true; + global::eventEngine->publishEvent(node); } void Scene::markNodeRegistryDirty() { @@ -585,6 +587,10 @@ void Scene::updateInterpolations() { i.prop->interpolateValue(t, i.easingFunction); i.isExpired = (t == 1.f); + + if (i.isExpired) { + global::eventEngine->publishEvent(i.prop); + } } _propertyInterpolationInfos.erase( diff --git a/src/scene/scene_lua.inl b/src/scene/scene_lua.inl index 96df5a47a8..c05919350a 100644 --- a/src/scene/scene_lua.inl +++ b/src/scene/scene_lua.inl @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include #include #include diff --git a/src/scene/scenegraphnode.cpp b/src/scene/scenegraphnode.cpp index 6ce162c4fa..d7c5efdc80 100644 --- a/src/scene/scenegraphnode.cpp +++ b/src/scene/scenegraphnode.cpp @@ -111,6 +111,20 @@ namespace { openspace::properties::Property::Visibility::Developer }; + constexpr openspace::properties::Property::PropertyInfo ApproachFactorInfo = { + "ApproachFactor", + "Approach Factor", + "This value is a multiplication factor for the interaction sphere that " + "determines when the camera is 'approaching' the scene graph node" + }; + + constexpr openspace::properties::Property::PropertyInfo ReachFactorInfo = { + "ReachFactor", + "Reach Factor", + "This value is a multiplication factor for the interaction sphere that " + "determines when the camera has 'reached' the scene graph node" + }; + constexpr openspace::properties::Property::PropertyInfo GuiPathInfo = { "GuiPath", "Gui Path", @@ -174,13 +188,10 @@ namespace { // children std::optional renderable [[codegen::reference("renderable")]]; - // A hard-coded bounding sphere to be used for the cases where the Renderable is - // not able to provide a reasonable bounding sphere or the calculated bounding - // sphere needs to be overwritten for some reason + // [[codegen::verbatim(BoundingSphereInfo.description)]] std::optional boundingSphere; - // A hard-coded radius for limiting the interaction radius, meaning the minimal - // distance that the camera can approach this scene graph node + // [[codegen::verbatim(InteractionSphereInfo.description)]] std::optional interactionSphere; struct Transform { @@ -208,6 +219,36 @@ namespace { // corresponding to a 'Translation', a 'Rotation', and a 'Scale' std::optional transform; + // This value is a multiplication factor for the interaction sphere that + // determines when the camera is 'approaching' the scene graph node. If this value + // is not specified, a default value of 5 is used instead. This value must be + // larger than the reachFactor or unexpected things might happen + std::optional approachFactor [[codegen::greaterequal(0.0)]]; + + // This value is a multiplication factor for the interaction sphere that + // determines when the camera has 'reached' the scene graph node. If this value is + // not specified, a default value of 1.25 is used instead. This value must be + // smaller than the approachFactor or unexpected things might happen + std::optional reachFactor [[codegen::greaterequal(0.0)]]; + + // One or multiple actions that are executed whenever the camera is focused on + // this scene graph node and if it enters the interaction sphere of the node + std::optional>> onApproach; + + // One or multiple actions that are executed whenever the camera is focused on + // this scene graph node and if it transitions from the approach distance to the + // reach distance of the node + std::optional>> onReach; + + // One or multiple actions that are executed whenever the camera is focused on + // this scene graph node and if it transitions from the reach distance to the + // approach distance of the node + std::optional>> onRecede; + + // One or multiple actions that are executed whenever the camera is focused on + // this scene graph node and if it exits the interaction sphere of the node + std::optional>> onExit; + // Specifies the time frame for when this node should be active std::optional timeFrame [[codegen::reference("core_time_frame")]]; @@ -287,6 +328,8 @@ ghoul::mm_unique_ptr SceneGraphNode::createFromDictionary( result->_overrideBoundingSphere = p.boundingSphere; result->_overrideInteractionSphere = p.interactionSphere; + result->_approachFactor = p.approachFactor.value_or(result->_approachFactor); + result->_reachFactor = p.reachFactor.value_or(result->_reachFactor); if (p.transform.has_value()) { if (p.transform->translation.has_value()) { @@ -378,6 +421,43 @@ ghoul::mm_unique_ptr SceneGraphNode::createFromDictionary( )); } + // Extracting the actions from the dictionary + if (p.onApproach.has_value()) { + if (std::holds_alternative(*p.onApproach)) { + result->_onApproachAction = { std::get(*p.onApproach) }; + } + else { + result->_onApproachAction = std::get>(*p.onApproach); + } + } + + if (p.onReach.has_value()) { + if (std::holds_alternative(*p.onReach)) { + result->_onReachAction = { std::get(*p.onReach) }; + } + else { + result->_onReachAction = std::get>(*p.onReach); + } + } + + if (p.onRecede.has_value()) { + if (std::holds_alternative(*p.onRecede)) { + result->_onRecedeAction = { std::get(*p.onRecede) }; + } + else { + result->_onRecedeAction = std::get>(*p.onRecede); + } + } + + if (p.onExit.has_value()) { + if (std::holds_alternative(*p.onExit)) { + result->_onExitAction = { std::get(*p.onExit) }; + } + else { + result->_onExitAction = std::get>(*p.onExit); + } + } + if (p.tag.has_value()) { if (std::holds_alternative(*p.tag)) { result->addTag(std::get(*p.tag)); @@ -425,6 +505,8 @@ SceneGraphNode::SceneGraphNode() } , _boundingSphere(BoundingSphereInfo, -1.0, -1.0, 1e12) , _interactionSphere(InteractionSphereInfo, -1.0, -1.0, 1e12) + , _approachFactor(ApproachFactorInfo, 5.0) + , _reachFactor(ReachFactorInfo, 1.25) , _computeScreenSpaceValues(ComputeScreenSpaceInfo, false) , _screenSpacePosition(ScreenSpacePositionInfo, glm::ivec2(-1, -1)) , _screenVisibility(ScreenVisibilityInfo, false) @@ -463,6 +545,8 @@ SceneGraphNode::SceneGraphNode() // negative values //_interactionSphere.setExponent(10.f); addProperty(_interactionSphere); + addProperty(_reachFactor); + addProperty(_approachFactor); addProperty(_showDebugSphere); } @@ -1066,6 +1150,22 @@ std::vector SceneGraphNode::children() const { return nodes; } +const std::vector& SceneGraphNode::onApproachAction() const { + return _onApproachAction; +} + +const std::vector& SceneGraphNode::onReachAction() const { + return _onReachAction; +} + +const std::vector& SceneGraphNode::onRecedeAction() const { + return _onRecedeAction; +} + +const std::vector& SceneGraphNode::onExitAction() const { + return _onExitAction; +} + double SceneGraphNode::boundingSphere() const { if (_overrideBoundingSphere.has_value()) { return glm::compMax(scale() * *_overrideBoundingSphere); @@ -1092,6 +1192,14 @@ double SceneGraphNode::interactionSphere() const { } } +double SceneGraphNode::reachFactor() const { + return _reachFactor; +} + +double SceneGraphNode::approachFactor() const { + return _approachFactor; +} + const Renderable* SceneGraphNode::renderable() const { return _renderable.get(); } diff --git a/src/util/tstring.cpp b/src/util/tstring.cpp new file mode 100644 index 0000000000..15df8237fd --- /dev/null +++ b/src/util/tstring.cpp @@ -0,0 +1,51 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2021 * + * * + * 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 + +#include +#include + +namespace openspace { + +tstring temporaryString(const std::string& str) { + void* ptr = global::memoryManager->TemporaryMemory.do_allocate(str.size(), 8); + std::strcpy(reinterpret_cast(ptr), str.data()); + return tstring(reinterpret_cast(ptr), str.size()); +} + +tstring temporaryString(std::string_view str) { + void* ptr = global::memoryManager->TemporaryMemory.do_allocate(str.size(), 8); + std::strcpy(reinterpret_cast(ptr), str.data()); + return tstring(reinterpret_cast(ptr), str.size()); +} + +tstring temporaryString(const char str[]) { + size_t size = strlen(str); + void* ptr = global::memoryManager->TemporaryMemory.do_allocate(size, 8); + std::strcpy(reinterpret_cast(ptr), str); + return tstring(reinterpret_cast(ptr), size); +} + +} // namespace openspace From bc306c6f1bc4122bb87fa8bc6f74ba1ba1227d26 Mon Sep 17 00:00:00 2001 From: Emma Broman Date: Tue, 12 Oct 2021 08:37:25 +0200 Subject: [PATCH 12/15] Fix globe transformations not updating from height map if simulation time paused (#1766) --- include/openspace/scene/rotation.h | 2 +- include/openspace/scene/translation.h | 2 +- modules/globebrowsing/src/globerotation.cpp | 18 +++++++++--------- modules/globebrowsing/src/globerotation.h | 1 + modules/globebrowsing/src/globetranslation.cpp | 18 +++++++++--------- modules/globebrowsing/src/globetranslation.h | 1 + 6 files changed, 22 insertions(+), 20 deletions(-) diff --git a/include/openspace/scene/rotation.h b/include/openspace/scene/rotation.h index 28b2ec8f5c..531036a558 100644 --- a/include/openspace/scene/rotation.h +++ b/include/openspace/scene/rotation.h @@ -51,7 +51,7 @@ public: const glm::dmat3& matrix() const; virtual glm::dmat3 matrix(const UpdateData& time) const = 0; - void update(const UpdateData& data); + virtual void update(const UpdateData& data); static documentation::Documentation Documentation(); diff --git a/include/openspace/scene/translation.h b/include/openspace/scene/translation.h index 074b90bbb2..2753456f3e 100644 --- a/include/openspace/scene/translation.h +++ b/include/openspace/scene/translation.h @@ -50,8 +50,8 @@ public: virtual ~Translation() = default; virtual bool initialize(); + virtual void update(const UpdateData& data); glm::dvec3 position() const; - void update(const UpdateData& data); virtual glm::dvec3 position(const UpdateData& data) const = 0; diff --git a/modules/globebrowsing/src/globerotation.cpp b/modules/globebrowsing/src/globerotation.cpp index 08f5eae9b8..f82da69325 100644 --- a/modules/globebrowsing/src/globerotation.cpp +++ b/modules/globebrowsing/src/globerotation.cpp @@ -174,22 +174,22 @@ glm::vec3 GlobeRotation::computeSurfacePosition(double latitude, double longitud ); } -glm::dmat3 GlobeRotation::matrix(const UpdateData&) const { +void GlobeRotation::update(const UpdateData& data) { if (!_globeNode) { - // @TODO(abock): The const cast should be removed on a redesign of the rotation - // to make the matrix function not constant. Const casting this - // away is fine as the factories that create the rotations don't - // create them as constant objects - const_cast(this)->findGlobe(); - _matrixIsDirty = true; + findGlobe(); + setUpdateVariables(); } if (_useHeightmap) { // If we use the heightmap, we have to compute the height every frame - _matrixIsDirty = true; + setUpdateVariables(); } - if (!_matrixIsDirty) { + Rotation::update(data); +} + +glm::dmat3 GlobeRotation::matrix(const UpdateData&) const { + if (!_matrixIsDirty || !_globeNode) { return _matrix; } diff --git a/modules/globebrowsing/src/globerotation.h b/modules/globebrowsing/src/globerotation.h index a1b30a67e6..bd1960dd35 100644 --- a/modules/globebrowsing/src/globerotation.h +++ b/modules/globebrowsing/src/globerotation.h @@ -39,6 +39,7 @@ class GlobeRotation : public Rotation { public: GlobeRotation(const ghoul::Dictionary& dictionary); + void update(const UpdateData& data) override; glm::dmat3 matrix(const UpdateData& data) const override; static documentation::Documentation Documentation(); diff --git a/modules/globebrowsing/src/globetranslation.cpp b/modules/globebrowsing/src/globetranslation.cpp index 5ef97f08f7..1200557171 100644 --- a/modules/globebrowsing/src/globetranslation.cpp +++ b/modules/globebrowsing/src/globetranslation.cpp @@ -153,22 +153,22 @@ void GlobeTranslation::setUpdateVariables() { requireUpdate(); } -glm::dvec3 GlobeTranslation::position(const UpdateData&) const { +void GlobeTranslation::update(const UpdateData& data) { if (!_attachedNode) { - // @TODO(abock): The const cast should be removed on a redesign of the translation - // to make the position function not constant. Const casting this - // away is fine as the factories that create the translations don't - // create them as constant objects - const_cast(this)->fillAttachedNode(); - _positionIsDirty = true; + fillAttachedNode(); + setUpdateVariables(); } if (_useHeightmap) { // If we use the heightmap, we have to compute the height every frame - _positionIsDirty = true; + setUpdateVariables(); } - if (!_positionIsDirty) { + Translation::update(data); +} + +glm::dvec3 GlobeTranslation::position(const UpdateData&) const { + if (!_positionIsDirty || !_attachedNode) { return _position; } diff --git a/modules/globebrowsing/src/globetranslation.h b/modules/globebrowsing/src/globetranslation.h index 85e5945174..530e0bec49 100644 --- a/modules/globebrowsing/src/globetranslation.h +++ b/modules/globebrowsing/src/globetranslation.h @@ -39,6 +39,7 @@ class GlobeTranslation : public Translation { public: GlobeTranslation(const ghoul::Dictionary& dictionary); + void update(const UpdateData& data) override; glm::dvec3 position(const UpdateData& data) const override; static documentation::Documentation Documentation(); From f38a7242e7c439fcfe491cfa405bafbf01bc09e6 Mon Sep 17 00:00:00 2001 From: Emma Broman Date: Tue, 12 Oct 2021 13:25:24 +0200 Subject: [PATCH 13/15] Fix the globetransformatons fix in previous commit (bc306c6f1bc4122bb87fa8bc6f74ba1ba1227d26) It broke the TimelineTranslation for when keyframes were using GlobeTranslations. The intial position was not set up correctly for these when the code for finding the globe was done in the update. Bringing back the check in the matrix/position methods solved the problem. Probably the globe is guaranteed to be created when reaching this function --- modules/globebrowsing/src/globerotation.cpp | 16 ++++++++++------ modules/globebrowsing/src/globetranslation.cpp | 16 ++++++++++------ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/modules/globebrowsing/src/globerotation.cpp b/modules/globebrowsing/src/globerotation.cpp index f82da69325..ddfa96ae77 100644 --- a/modules/globebrowsing/src/globerotation.cpp +++ b/modules/globebrowsing/src/globerotation.cpp @@ -175,11 +175,6 @@ glm::vec3 GlobeRotation::computeSurfacePosition(double latitude, double longitud } void GlobeRotation::update(const UpdateData& data) { - if (!_globeNode) { - findGlobe(); - setUpdateVariables(); - } - if (_useHeightmap) { // If we use the heightmap, we have to compute the height every frame setUpdateVariables(); @@ -189,7 +184,16 @@ void GlobeRotation::update(const UpdateData& data) { } glm::dmat3 GlobeRotation::matrix(const UpdateData&) const { - if (!_matrixIsDirty || !_globeNode) { + if (!_globeNode) { + // @TODO(abock): The const cast should be removed on a redesign of the rotation + // to make the matrix function not constant. Const casting this + // away is fine as the factories that create the rotations don't + // create them as constant objects + const_cast(this)->findGlobe(); + _matrixIsDirty = true; + } + + if (!_matrixIsDirty) { return _matrix; } diff --git a/modules/globebrowsing/src/globetranslation.cpp b/modules/globebrowsing/src/globetranslation.cpp index 1200557171..e935cb723c 100644 --- a/modules/globebrowsing/src/globetranslation.cpp +++ b/modules/globebrowsing/src/globetranslation.cpp @@ -154,11 +154,6 @@ void GlobeTranslation::setUpdateVariables() { } void GlobeTranslation::update(const UpdateData& data) { - if (!_attachedNode) { - fillAttachedNode(); - setUpdateVariables(); - } - if (_useHeightmap) { // If we use the heightmap, we have to compute the height every frame setUpdateVariables(); @@ -168,7 +163,16 @@ void GlobeTranslation::update(const UpdateData& data) { } glm::dvec3 GlobeTranslation::position(const UpdateData&) const { - if (!_positionIsDirty || !_attachedNode) { + if (!_attachedNode) { + // @TODO(abock): The const cast should be removed on a redesign of the translation + // to make the position function not constant. Const casting this + // away is fine as the factories that create the translations don't + // create them as constant objects + const_cast(this)->fillAttachedNode(); + _positionIsDirty = true; + } + + if (!_positionIsDirty) { return _position; } From 8d26f6e1672790f7c07f1bc9e3567acb6e5beb39 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Wed, 13 Oct 2021 21:46:08 +0200 Subject: [PATCH 14/15] Set the user-agent when requesting a download (closes #1765). Also report the error code if a download fails --- apps/OpenSpace/ext/sgct | 2 +- src/engine/downloadmanager.cpp | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/apps/OpenSpace/ext/sgct b/apps/OpenSpace/ext/sgct index d89724510f..3f2bbf3ebb 160000 --- a/apps/OpenSpace/ext/sgct +++ b/apps/OpenSpace/ext/sgct @@ -1 +1 @@ -Subproject commit d89724510f70a5b19dd93f481e4fb6493e67721c +Subproject commit 3f2bbf3ebb1e1ef23af25731c182a711b4102814 diff --git a/src/engine/downloadmanager.cpp b/src/engine/downloadmanager.cpp index cc8429fa84..d523ae24fd 100644 --- a/src/engine/downloadmanager.cpp +++ b/src/engine/downloadmanager.cpp @@ -173,9 +173,10 @@ std::shared_ptr DownloadManager::downloadFile( CURL* curl = curl_easy_init(); if (curl) { curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); // NOLINT + curl_easy_setopt(curl, CURLOPT_USERAGENT, "OpenSpace"); // NOLINT curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); // NOLINT curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); // NOLINT - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeData); // NOLINT + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &writeData); // NOLINT if (timeout_secs) { curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout_secs); // NOLINT } @@ -204,7 +205,11 @@ std::shared_ptr DownloadManager::downloadFile( future->isFinished = true; } else { - future->errorMessage = curl_easy_strerror(res); + long rescode; + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &rescode); + future->errorMessage = fmt::format( + "{}. HTTP code: {}", curl_easy_strerror(res), rescode + ); } if (finishedCb) { From 4a860fb01d77440e1168e996bb924f931cb94a8f Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Thu, 14 Oct 2021 10:31:46 +0200 Subject: [PATCH 15/15] Some code facelifting --- ext/ghoul | 2 +- include/openspace/documentation/verifier.inl | 12 +++---- include/openspace/events/event.h | 34 ++++++++++--------- include/openspace/events/eventengine.h | 8 ++--- .../openspace/navigation/orbitalnavigator.h | 18 +++++----- include/openspace/navigation/path.h | 32 ++++++++--------- include/openspace/navigation/pathcurve.h | 6 ++-- .../pathcurves/avoidcollisioncurve.h | 2 +- include/openspace/navigation/waypoint.h | 3 +- .../openspace/properties/selectionproperty.h | 3 +- include/openspace/util/distanceconversion.h | 4 ++- include/openspace/util/tstring.h | 11 ++++-- .../rendering/atmospheredeferredcaster.cpp | 24 ++++++------- .../rendering/atmospheredeferredcaster.h | 4 +-- modules/base/rendering/renderablemodel.cpp | 9 ++--- modules/base/rendering/renderableprism.cpp | 7 +++- modules/debugging/debuggingmodule_lua.inl | 4 +-- modules/exoplanets/exoplanetsmodule_lua.inl | 2 +- modules/gaia/tasks/constructoctreetask.cpp | 2 +- modules/gaia/tasks/readfitstask.cpp | 2 +- modules/gaia/tasks/readspecktask.cpp | 2 +- modules/globebrowsing/globebrowsingmodule.cpp | 2 +- .../globebrowsing/globebrowsingmodule_lua.inl | 3 +- .../globebrowsing/src/globetranslation.cpp | 4 +-- modules/globebrowsing/src/renderableglobe.cpp | 4 +-- modules/globebrowsing/src/ringscomponent.cpp | 13 +++++-- modules/globebrowsing/src/shadowcomponent.cpp | 2 +- modules/globebrowsing/src/tileprovider.cpp | 2 +- modules/imgui/include/guiactioncomponent.h | 6 ++-- modules/imgui/src/renderproperties.cpp | 5 ++- modules/space/rendering/renderablestars.cpp | 16 ++++----- modules/space/speckloader.cpp | 18 +++++----- .../rendering/renderablefov.cpp | 2 +- .../rendering/renderableplanetprojection.cpp | 2 +- .../util/imagesequencer.h | 10 +++--- .../util/projectioncomponent.cpp | 18 +++++----- modules/statemachine/statemachinemodule.cpp | 3 +- modules/sync/syncs/urlsynchronization.cpp | 10 +++--- .../rendering/renderabletimevaryingvolume.cpp | 2 +- .../volume/tasks/generaterawvolumetask.cpp | 2 +- src/documentation/verifier.cpp | 10 +++--- src/events/event.cpp | 2 +- src/interaction/actionmanager_lua.inl | 2 +- src/interaction/sessionrecording.cpp | 8 +++-- src/navigation/navigationhandler.cpp | 4 +-- src/navigation/navigationhandler_lua.inl | 2 +- src/navigation/navigationstate.cpp | 4 +-- src/navigation/orbitalnavigator.cpp | 12 ++++--- src/navigation/path.cpp | 13 ++++--- .../pathcurves/zoomoutoverviewcurve.cpp | 3 +- src/navigation/pathnavigator.cpp | 9 +++-- src/navigation/pathnavigator_lua.inl | 9 ++--- src/navigation/waypoint.cpp | 4 +-- src/rendering/helper.cpp | 2 +- src/rendering/renderengine.cpp | 4 +-- src/rendering/screenspacerenderable.cpp | 2 +- src/scene/scene.cpp | 6 ++-- src/scene/scene_lua.inl | 2 +- src/scene/scenelicensewriter.cpp | 30 ++++++++++++---- src/scripting/scriptscheduler.cpp | 2 +- src/scripting/scriptscheduler_lua.inl | 2 +- src/util/keys.cpp | 8 ++--- src/util/resourcesynchronization.cpp | 2 +- src/util/spicemanager.cpp | 18 +++++----- src/util/spicemanager_lua.inl | 4 +-- src/util/time_lua.inl | 18 +++++----- 66 files changed, 279 insertions(+), 218 deletions(-) diff --git a/ext/ghoul b/ext/ghoul index 4a17b2a165..874300a089 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit 4a17b2a1653cc596ab8610d93a53c639930ddb85 +Subproject commit 874300a08923cf366a487825c93d6309d016fbcd diff --git a/include/openspace/documentation/verifier.inl b/include/openspace/documentation/verifier.inl index 7363b325ec..6b86ff0918 100644 --- a/include/openspace/documentation/verifier.inl +++ b/include/openspace/documentation/verifier.inl @@ -175,7 +175,7 @@ TestResult OperatorVerifier::operator()(const ghoul::Dictionary& di o.offender = key; o.reason = TestResult::Offense::Reason::Verification; r.offenses.push_back(o); - return r; + return r; } } else { @@ -290,7 +290,7 @@ TestResult NotInListVerifier::operator()(const ghoul::Dictionary& dict, o.offender = key; o.reason = TestResult::Offense::Reason::Verification; r.offenses.push_back(o); - return r; + return r; } } else { @@ -346,7 +346,7 @@ TestResult InRangeVerifier::operator()(const ghoul::Dictionary& dict, o.offender = key; o.reason = TestResult::Offense::Reason::WrongType; r.offenses.push_back(o); - return r; + return r; } } else { @@ -363,7 +363,7 @@ TestResult InRangeVerifier::operator()(const ghoul::Dictionary& dict, o.offender = key; o.reason = TestResult::Offense::Reason::Verification; r.offenses.push_back(o); - return r; + return r; } } else { @@ -405,7 +405,7 @@ TestResult NotInRangeVerifier::operator()(const ghoul::Dictionary& dict, o.offender = key; o.reason = TestResult::Offense::Reason::WrongType; r.offenses.push_back(o); - return r; + return r; } } else { @@ -419,7 +419,7 @@ TestResult NotInRangeVerifier::operator()(const ghoul::Dictionary& dict, o.offender = key; o.reason = TestResult::Offense::Reason::Verification; r.offenses.push_back(o); - return r; + return r; } else { return { true, {}, {} }; diff --git a/include/openspace/events/event.h b/include/openspace/events/event.h index 9c903917be..201814da55 100644 --- a/include/openspace/events/event.h +++ b/include/openspace/events/event.h @@ -52,7 +52,7 @@ struct Event { // to see all events. // 4. Add a new case into the logAllEvents function that handles the new enum entry // 5. If the new event type has any parameters it takes in its constructor, go into - // the `toParameter` function and add a case label for the new enum type and + // the `toParameter` function and add a case label for the new enum type and // return a dictionary with these parameters. This dictionary is passed to actions // if they are triggered by events // 6. Add the new enum entry into the `toString` and `fromString` methods @@ -107,7 +107,7 @@ void logAllEvents(const Event* e); * This event is created whenever a new scene graph node is added to the system. By the * time this event is signalled, the scene graph node has already been created and added * to the scene. - * + * * \param Node The identifier of the node that was added */ struct EventSceneGraphNodeAdded : public Event { @@ -125,7 +125,7 @@ struct EventSceneGraphNodeAdded : public Event { */ struct EventSceneGraphNodeRemoved : public Event { static const Type Type = Event::Type::SceneGraphNodeRemoved; - + explicit EventSceneGraphNodeRemoved(const SceneGraphNode* node_); const tstring node; }; @@ -164,7 +164,7 @@ struct EventProfileLoadingFinished : public Event { * This event is created whenever some information about the application shutdown sequence * changes. This can either be that the seqeuence started, was aborted, or is finished, * which means that OpenSpace is just about the shutdown. - * + * * \param State The next state of the application shutdown sequence; is one of `Started`, * `Aborted`, or `Finished` */ @@ -184,7 +184,7 @@ struct EventApplicationShutdown : public Event { /** * This event is created when a new screenspace renderable has been created. By the time * this event is craeted, the screenspace renderable is already registered and available. - * + * * \param Renderable The identifier of the new screenspace renderable that was just added * to the system */ @@ -199,7 +199,7 @@ struct EventScreenSpaceRenderableAdded : public Event { * This event is created when a screenspace renderable has been removed from the system. * When this event is created, the screenspace renderable has already been removed and is * no longer available - * + * * \param Renderable The identifier of the screenspace renderable that was removed */ struct EventScreenSpaceRenderableRemoved : public Event { @@ -215,11 +215,13 @@ struct EventScreenSpaceRenderableRemoved : public Event { * Each scene graph node has an interaction sphere radius that serves as the reference * distance for all spheres. ``` -Diagram of events for a camera moving from right-to-left. Interaction sphere is 'O' in middle, and ')' are spherical boundaries. The approach factor, reach factor, and interaction sphere radius are all taken from the current focus node. +Diagram of events for a camera moving from right-to-left. Interaction sphere is 'O' in +middle, and ')' are spherical boundaries. The approach factor, reach factor, and +interaction sphere radius are all taken from the current focus node. |<------------------->| Approach factor * Interaction sphere |<------>| Reach Factor * Interaction sphere - + ( ( O ) ) ^ ^ ^ ^ Exiting Receding Reaching Approaching @@ -227,7 +229,7 @@ Exiting Receding Reaching Approachi * * \param Node The name of the node the camera is transitioning relative to. Currently is * always the same as the camera's focus node - * \param Transition The transition type that the camera just finished; is one of + * \param Transition The transition type that the camera just finished; is one of * `Approaching`, `Reaching`, `Receding`, or `Exiting` */ struct EventCameraFocusTransition : public Event { @@ -293,7 +295,7 @@ struct EventPlanetEclipsed : public Event { /** * This event is created when the interpolation of a property value is finished. If the * interpolation time of a property change is 0s, this event is not fired - * + * * \param Property The URI of the property whose interpolation has finished */ struct EventInterpolationFinished : public Event { @@ -307,7 +309,7 @@ struct EventInterpolationFinished : public Event { * This event is created when the camera changes focus nodes. Even if the camera position * is interpolated, the node change happens instantaneously and the event is fired at the * same time. - * + * * \param OldNode The identifier of the scene graph node which was the old focus node * \param NewNode The identifier of the scene graph node that is the new focus node */ @@ -321,7 +323,7 @@ struct EventFocusNodeChanged : public Event { /** * This event is created when a layer is added to to a globe. - * + * * \param Globe The identifier of the globe to which the layer is added * \param Group The identifier of the layer group to which the layer is added * \param Layer The identifier of the layer that was added @@ -329,7 +331,7 @@ struct EventFocusNodeChanged : public Event { struct EventLayerAdded : public Event { static const Type Type = Event::Type::LayerAdded; - explicit EventLayerAdded(std::string_view node_, std::string_view layerGroup_, + explicit EventLayerAdded(std::string_view node_, std::string_view layerGroup_, std::string_view layer_); const tstring node; const tstring layerGroup; @@ -338,7 +340,7 @@ struct EventLayerAdded : public Event { /** * This event is created when a layer is removed from a globe. - * + * * \param Globe The identifier of the globe from which the layer is removed * \param Group The identifier of the layer group from which the layer is removed * \param Layer The identifier of the layer that was removed @@ -346,7 +348,7 @@ struct EventLayerAdded : public Event { struct EventLayerRemoved : public Event { static const Type Type = Event::Type::LayerRemoved; - explicit EventLayerRemoved(std::string_view node_, std::string_view layerGroup_, + explicit EventLayerRemoved(std::string_view node_, std::string_view layerGroup_, std::string_view layer_); const tstring node; const tstring layerGroup; @@ -356,7 +358,7 @@ struct EventLayerRemoved : public Event { /** * This event is created when something regarding a session recording playback changes. * The event contains information about the new state of the session recording subsystem. - * + * * \param State The new state of the session recording; one of `Started`, `Paused`, * `Resumed`, `Finished` */ diff --git a/include/openspace/events/eventengine.h b/include/openspace/events/eventengine.h index 70e945012b..4e98175572 100644 --- a/include/openspace/events/eventengine.h +++ b/include/openspace/events/eventengine.h @@ -41,7 +41,7 @@ public: * no event exists. To navigate the full list of events, you can access the returned * Event's next function. If the end of the list is reached, the next pointer will be * a nullptr - * + * * \return The first event stored in the EventEngine or nullptr if no event exists */ events::Event* firstEvent() const; @@ -51,7 +51,7 @@ public: * constructor. An example of usage is * engine.publishEvent("a", 2.0); which would call the * constructor of \c MyEvent with a const char* and \c double parameter. - * + * * \param args The arguments that are passed to the constructor of T * \tparam T The subclass of Event that is to be published */ @@ -81,7 +81,7 @@ public: /** * Removing registration for a type/action combination. - * + * * \param type The type of the action that should be unregistered * \param actionIdentifier The identifier of the action that should be unregistered * \param filter The optional filter applied to the event-action combination @@ -97,7 +97,7 @@ public: void triggerActions() const; static scripting::LuaLibrary luaLibrary(); - + private: /// The storage space in which Events are stored ghoul::MemoryPool<4096> _memory; diff --git a/include/openspace/navigation/orbitalnavigator.h b/include/openspace/navigation/orbitalnavigator.h index b2b6c8556e..c964e1eef9 100644 --- a/include/openspace/navigation/orbitalnavigator.h +++ b/include/openspace/navigation/orbitalnavigator.h @@ -371,10 +371,10 @@ private: /** * Orbit the current anchor node, in a right-bound orbit, by updating the position - * and global rotation of the camera. - * + * and global rotation of the camera. + * * Used for IdleBehavior::Behavior::Orbit - * + * * \param deltaTime The time step to use for the motion. Controls the rotation angle * \param position The position of the camera. Will be changed by the function * \param globalRotation The camera's global rotation. Will be changed by the function @@ -384,15 +384,15 @@ private: glm::dquat& globalRotation, double speedScale); /** - * Orbit the current anchor node, by adding a rotation around the given axis. For - * example, when the axis is the north vector, the camera will stay on the current - * latitude band. Note that this creates a rolling motion if the camera's forward - * vector coincides with the axis, and should be used with care. - * + * Orbit the current anchor node, by adding a rotation around the given axis. For + * example, when the axis is the north vector, the camera will stay on the current + * latitude band. Note that this creates a rolling motion if the camera's forward + * vector coincides with the axis, and should be used with care. + * * Used for: * IdleBehavior::Behavior::OrbitAtConstantLat ( axis = north = z-axis ) and * IdleBehavior::Behavior::OrbitAroundUp ( axis = up = y-axis ) - * + * * \param axis The axis to arbit around, given in model coordinates of the anchor * \param deltaTime The time step to use for the motion. Controls the rotation angle * \param position The position of the camera. Will be changed by the function diff --git a/include/openspace/navigation/path.h b/include/openspace/navigation/path.h index 7a1a33bc3e..baec1ad261 100644 --- a/include/openspace/navigation/path.h +++ b/include/openspace/navigation/path.h @@ -31,8 +31,8 @@ #include #include -namespace openspace { - struct CameraPose; +namespace openspace { + struct CameraPose; } // namespace openspace namespace openspace::interaction { @@ -44,10 +44,10 @@ public: Linear, ZoomOutOverview, AvoidCollisionWithLookAt // @TODO (2021-08-13, emmbr) This type right now leads - // to rapid rotations, but is useful in specific - // scenarios, e.g. close to surfaces. Later we want to + // to rapid rotations, but is useful in specific + // scenarios, e.g. close to surfaces. Later we want to // remove it, and create a curve type that looks nicely - // at the targets when moving, avoids collisions and + // at the targets when moving, avoids collisions and // doesn't introduce sudden large changes in rotation }; @@ -63,21 +63,21 @@ public: double pathLength() const; /** - * Return a vector of positions corresponding to the control points of the path's + * Return a vector of positions corresponding to the control points of the path's * spline curve */ std::vector controlPoints() const; /** * Take a step along the current path, corresponding to the delta time step \p dt, and - * return the resulting camera pose. The \p speedScale is a factor that will be + * return the resulting camera pose. The \p speedScale is a factor that will be * multiplied with the traversal speed */ CameraPose traversePath(double dt, float speedScale = 1.f); /** - * Return the identifer of the node that is the current appropriate anchor node, of - * the start and end waypoint's reference node. Dtermined based on how far along the + * Return the identifer of the node that is the current appropriate anchor node, of + * the start and end waypoint's reference node. Dtermined based on how far along the * path we have traveled */ std::string currentAnchor() const; @@ -94,7 +94,7 @@ public: private: /** - * Interpolate between the paths start and end rotation using the approach that + * Interpolate between the paths start and end rotation using the approach that * corresponds to the path's curve type. The interpolation parameter \p t is the * same as for the position interpolation, i.e. the relative traveled in distance * along the path, in [0, 1] @@ -107,14 +107,14 @@ private: glm::dquat easedSlerpRotation(double t) const; /** - * Compute the interpolated rotation quaternion using an approach that first - * interpolates to look at the start node, and then the end node, before + * Compute the interpolated rotation quaternion using an approach that first + * interpolates to look at the start node, and then the end node, before * interpolating to the end rotation */ glm::dquat lookAtTargetsRotation(double t) const; /** - * Evaluate the current traversal speed along the path, based on the currently + * Evaluate the current traversal speed along the path, based on the currently * traveled distance. The final speed will be scaled to match the desired duration * for the path (which might have been specified by the user) */ @@ -134,9 +134,9 @@ private: }; -// Create a path of the given type based on an instruction given as a dictionary. -// See top of cpp file for documentation on keys and values for the dictionary. -// Returns the created path. +// Create a path of the given type based on an instruction given as a dictionary. +// See top of cpp file for documentation on keys and values for the dictionary. +// Returns the created path. Path createPathFromDictionary(const ghoul::Dictionary& dictionary, Path::Type type); } // namespace openspace::interaction diff --git a/include/openspace/navigation/pathcurve.h b/include/openspace/navigation/pathcurve.h index e00da37583..ed0a4c5991 100644 --- a/include/openspace/navigation/pathcurve.h +++ b/include/openspace/navigation/pathcurve.h @@ -46,9 +46,9 @@ public: glm::dvec3 positionAt(double relativeDistance) const; /** - * Get the intorlatied position along the spline, based on the given curve parameter - * u in range [0, 1]. A curve parameter of 0 returns the start position and 1 the end - * position. Note that u does not correspond to the relatively traveled distance. + * Get the intorlatied position along the spline, based on the given curve parameter + * u in range [0, 1]. A curve parameter of 0 returns the start position and 1 the end + * position. Note that u does not correspond to the relatively traveled distance. */ virtual glm::dvec3 interpolate(double u) const; diff --git a/include/openspace/navigation/pathcurves/avoidcollisioncurve.h b/include/openspace/navigation/pathcurves/avoidcollisioncurve.h index 5cd95ddd5a..b48a0529a7 100644 --- a/include/openspace/navigation/pathcurves/avoidcollisioncurve.h +++ b/include/openspace/navigation/pathcurves/avoidcollisioncurve.h @@ -45,4 +45,4 @@ private: } // namespace openspace::interaction -#endif // __OPENSPACE_MODULE_AUTONAVIGATION___AVOIDCOLLISIONCURVE___H__ +#endif // __OPENSPACE_CORE___AVOIDCOLLISIONCURVE___H__ diff --git a/include/openspace/navigation/waypoint.h b/include/openspace/navigation/waypoint.h index 79506318e5..09970bb261 100644 --- a/include/openspace/navigation/waypoint.h +++ b/include/openspace/navigation/waypoint.h @@ -53,7 +53,8 @@ public: private: CameraPose _pose; std::string _nodeIdentifier; - double _validBoundingSphere = 0.0; // to be able to handle nodes with faulty bounding spheres + // to be able to handle nodes with faulty bounding spheres + double _validBoundingSphere = 0.0; }; } // namespace openspace::interaction diff --git a/include/openspace/properties/selectionproperty.h b/include/openspace/properties/selectionproperty.h index b17f580a52..f8d4b59ba8 100644 --- a/include/openspace/properties/selectionproperty.h +++ b/include/openspace/properties/selectionproperty.h @@ -114,7 +114,8 @@ public: using TemplateProperty>::operator=; protected: - std::set fromLuaConversion(lua_State* state, bool& success) const override; + std::set fromLuaConversion(lua_State* state, + bool& success) const override; void toLuaConversion(lua_State* state) const override; diff --git a/include/openspace/util/distanceconversion.h b/include/openspace/util/distanceconversion.h index 252948c720..1c1176c5f0 100644 --- a/include/openspace/util/distanceconversion.h +++ b/include/openspace/util/distanceconversion.h @@ -357,7 +357,9 @@ constexpr double convertUnit(DistanceUnit fromUnit, DistanceUnit toUnit) { return convertMeters(toMeter(fromUnit), toUnit); } -constexpr double convertDistance(double distance, DistanceUnit fromUnit, DistanceUnit toUnit) { +constexpr double convertDistance(double distance, DistanceUnit fromUnit, + DistanceUnit toUnit) +{ return distance * convertUnit(fromUnit, toUnit); } diff --git a/include/openspace/util/tstring.h b/include/openspace/util/tstring.h index 26f41e7ea9..01390c49fd 100644 --- a/include/openspace/util/tstring.h +++ b/include/openspace/util/tstring.h @@ -22,6 +22,9 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ +#ifndef __OPENSPACE_CORE___TSTRING___H__ +#define __OPENSPACE_CORE___TSTRING___H__ + #include #include @@ -39,7 +42,7 @@ using tstring = std::string_view; /** * Allocate and create a temporary string from the passed std::string. - * + * * \param str The string to be copied into a newly allocated tstring * \return The copy of the str as a temporary string */ @@ -47,7 +50,7 @@ tstring temporaryString(const std::string& str); /** * Allocate and create a temporary string from the passed std::string_view. - * + * * \param str The string to be copied into a newly allocated tstring * \return The copy of the str as a temporary string */ @@ -55,10 +58,12 @@ tstring temporaryString(std::string_view str); /** * Allocate and create a temporary string from the passed char array. - * + * * \param str The string to be copied into a newly allocated tstring * \return The copy of the str as a temporary string */ tstring temporaryString(const char str[]); } // namespace openspace + +#endif // __OPENSPACE_CORE___TSTRING___H__ diff --git a/modules/atmosphere/rendering/atmospheredeferredcaster.cpp b/modules/atmosphere/rendering/atmospheredeferredcaster.cpp index 8bc8f1061c..dc29181555 100644 --- a/modules/atmosphere/rendering/atmospheredeferredcaster.cpp +++ b/modules/atmosphere/rendering/atmospheredeferredcaster.cpp @@ -498,7 +498,7 @@ void AtmosphereDeferredcaster::setParameters(float atmosphereRadius, float plane float averageGroundReflectance, float groundRadianceEmission, float rayleighHeightScale, bool enableOzone, - float ozoneHeightScale, float mieHeightScale, + float ozoneHeightScale, float mieHeightScale, float miePhaseConstant, float sunRadiance, glm::vec3 rayScatteringCoefficients, glm::vec3 ozoneExtinctionCoefficients, @@ -529,7 +529,7 @@ void AtmosphereDeferredcaster::setHardShadows(bool enabled) { void AtmosphereDeferredcaster::calculateTransmittance() { ZoneScoped - + glFramebufferTexture( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, @@ -566,7 +566,7 @@ void AtmosphereDeferredcaster::calculateTransmittance() { GLuint AtmosphereDeferredcaster::calculateDeltaE() { ZoneScoped - + GLuint deltaE = createTexture(_deltaETableSize, "DeltaE"); glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, deltaE, 0); glViewport(0, 0, _deltaETableSize.x, _deltaETableSize.y); @@ -595,7 +595,7 @@ GLuint AtmosphereDeferredcaster::calculateDeltaE() { std::pair AtmosphereDeferredcaster::calculateDeltaS() { ZoneScoped - + GLuint deltaSRayleigh = createTexture(_textureSize, "DeltaS Rayleigh", 3); glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, deltaSRayleigh, 0); GLuint deltaSMie = createTexture(_textureSize, "DeltaS Mie", 3); @@ -649,7 +649,7 @@ std::pair AtmosphereDeferredcaster::calculateDeltaS() { void AtmosphereDeferredcaster::calculateIrradiance() { ZoneScoped - + glFramebufferTexture( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, @@ -678,7 +678,7 @@ void AtmosphereDeferredcaster::calculateInscattering(GLuint deltaSRayleigh, GLuint deltaSMie) { ZoneScoped - + glFramebufferTexture( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, @@ -726,7 +726,7 @@ void AtmosphereDeferredcaster::calculateDeltaJ(int scatteringOrder, GLuint deltaSRayleigh, GLuint deltaSMie) { ZoneScoped - + glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, deltaJ, 0); glViewport(0, 0, _textureSize.x, _textureSize.y); program.activate(); @@ -745,7 +745,7 @@ void AtmosphereDeferredcaster::calculateDeltaJ(int scatteringOrder, deltaSRayleighUnit.activate(); glBindTexture(GL_TEXTURE_3D, deltaSRayleigh); program.setUniform("deltaSRTexture", deltaSRayleighUnit); - + ghoul::opengl::TextureUnit deltaSMieUnit; deltaSMieUnit.activate(); glBindTexture(GL_TEXTURE_3D, deltaSMie); @@ -784,7 +784,7 @@ void AtmosphereDeferredcaster::calculateDeltaE(int scatteringOrder, GLuint deltaSMie) { ZoneScoped - + glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, deltaE, 0); glViewport(0, 0, _deltaETableSize.x, _deltaETableSize.y); program.activate(); @@ -823,7 +823,7 @@ void AtmosphereDeferredcaster::calculateDeltaS(int scatteringOrder, GLuint deltaSRayleigh, GLuint deltaJ) { ZoneScoped - + glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, deltaSRayleigh, 0); glViewport(0, 0, _textureSize.x, _textureSize.y); program.activate(); @@ -863,7 +863,7 @@ void AtmosphereDeferredcaster::calculateIrradiance(int scatteringOrder, GLuint deltaE) { ZoneScoped - + glFramebufferTexture( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, @@ -895,7 +895,7 @@ void AtmosphereDeferredcaster::calculateInscattering(int scatteringOrder, { ZoneScoped - + glFramebufferTexture( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, diff --git a/modules/atmosphere/rendering/atmospheredeferredcaster.h b/modules/atmosphere/rendering/atmospheredeferredcaster.h index 6836352c0a..1f3608e2d6 100644 --- a/modules/atmosphere/rendering/atmospheredeferredcaster.h +++ b/modules/atmosphere/rendering/atmospheredeferredcaster.h @@ -114,9 +114,9 @@ private: UniformCache(cullAtmosphere, Rg, Rt, groundRadianceEmission, HR, betaRayleigh, HM, betaMieExtinction, mieG, sunRadiance, ozoneLayerEnabled, HO, betaOzoneExtinction, - SAMPLES_R, SAMPLES_MU, SAMPLES_MU_S, SAMPLES_NU, inverseModelTransformMatrix, + SAMPLES_R, SAMPLES_MU, SAMPLES_MU_S, SAMPLES_NU, inverseModelTransformMatrix, modelTransformMatrix, projectionToModelTransform, viewToWorldMatrix, - camPosObj, sunDirectionObj, hardShadows, transmittanceTexture, irradianceTexture, + camPosObj, sunDirectionObj, hardShadows, transmittanceTexture, irradianceTexture, inscatterTexture) _uniformCache; ghoul::opengl::TextureUnit _transmittanceTableTextureUnit; diff --git a/modules/base/rendering/renderablemodel.cpp b/modules/base/rendering/renderablemodel.cpp index 6f00faa4b5..8f236ec978 100644 --- a/modules/base/rendering/renderablemodel.cpp +++ b/modules/base/rendering/renderablemodel.cpp @@ -649,8 +649,8 @@ void RenderableModel::render(const RenderData& data, RendererTasks&) { // Model transform and view transform needs to be in double precision const glm::dmat4 modelTransform = - glm::translate(glm::dmat4(1.0), data.modelTransform.translation) * // Translation - glm::dmat4(data.modelTransform.rotation) * // Spice rotation + glm::translate(glm::dmat4(1.0), data.modelTransform.translation) * + glm::dmat4(data.modelTransform.rotation) * glm::scale(glm::dmat4(1.0), glm::dvec3(data.modelTransform.scale)) * glm::scale( glm::dmat4(_modelTransform.value()), @@ -770,8 +770,9 @@ void RenderableModel::update(const UpdateData& data) { // be converted to the animation time range, so the animation knows which // keyframes it should interpolate between for each frame. The conversion is // done in different ways depending on the animation mode. - // Explanation: s indicates start time, / indicates animation is played once forwards, - // \ indicates animation is played once backwards, time moves to the right. + // Explanation: s indicates start time, / indicates animation is played once + // forwards, \ indicates animation is played once backwards, time moves to the + // right. switch (_animationMode) { case AnimationMode::LoopFromStart: // Start looping from the start time diff --git a/modules/base/rendering/renderableprism.cpp b/modules/base/rendering/renderableprism.cpp index c14798a604..65bb509a68 100644 --- a/modules/base/rendering/renderableprism.cpp +++ b/modules/base/rendering/renderableprism.cpp @@ -329,7 +329,12 @@ void RenderablePrism::render(const RenderData& data, RendererTasks&) { glLineWidth(_lineWidth); glBindVertexArray(_vaoId); - glDrawElements(GL_LINE_LOOP, static_cast(_indexArray.size()), GL_UNSIGNED_BYTE, nullptr); + glDrawElements( + GL_LINE_LOOP, + static_cast(_indexArray.size()), + GL_UNSIGNED_BYTE, + nullptr + ); glBindVertexArray(0); global::renderEngine->openglStateCache().resetLineState(); diff --git a/modules/debugging/debuggingmodule_lua.inl b/modules/debugging/debuggingmodule_lua.inl index 2f90b92376..c5dba570e0 100644 --- a/modules/debugging/debuggingmodule_lua.inl +++ b/modules/debugging/debuggingmodule_lua.inl @@ -151,7 +151,7 @@ int renderCameraPath(lua_State* L) { }; auto addDirectionLine = [addPoint, addLineBetweenPoints] - (const std::string& pointId, const CameraPose& p, + (const std::string& pointId, const CameraPose& p, double lineLength) { const glm::dvec3 dir = glm::normalize(p.rotation * glm::dvec3(0.0, 0.0, -1.0)); @@ -291,7 +291,7 @@ int removePathControlPoints(lua_State* L) { int addCartesianAxes(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::addCartesianAxes"); - auto [nodeIdentifier, scale] = + auto [nodeIdentifier, scale] = ghoul::lua::values>(L); SceneGraphNode* n = global::renderEngine->scene()->sceneGraphNode(nodeIdentifier); diff --git a/modules/exoplanets/exoplanetsmodule_lua.inl b/modules/exoplanets/exoplanetsmodule_lua.inl index 4a2128b9dc..385f43aefa 100644 --- a/modules/exoplanets/exoplanetsmodule_lua.inl +++ b/modules/exoplanets/exoplanetsmodule_lua.inl @@ -557,7 +557,7 @@ void createExoplanetSystem(const std::string& starName) { int addExoplanetSystem(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::addExoplanetSystem"); - std::variant v = + std::variant v = ghoul::lua::value>(L); if (std::holds_alternative(v)) { diff --git a/modules/gaia/tasks/constructoctreetask.cpp b/modules/gaia/tasks/constructoctreetask.cpp index 1239a65960..19bfc8d463 100644 --- a/modules/gaia/tasks/constructoctreetask.cpp +++ b/modules/gaia/tasks/constructoctreetask.cpp @@ -462,7 +462,7 @@ void ConstructOctreeTask::constructOctreeFromFolder( } } } - + std::vector filterValues; auto writeThreads = std::vector(8); diff --git a/modules/gaia/tasks/readfitstask.cpp b/modules/gaia/tasks/readfitstask.cpp index a23d128073..720abd9f66 100644 --- a/modules/gaia/tasks/readfitstask.cpp +++ b/modules/gaia/tasks/readfitstask.cpp @@ -193,7 +193,7 @@ void ReadFitsTask::readAllFitsFilesFromFolder(const Task::ProgressCallback&) { } } } - + size_t nInputFiles = allInputFiles.size(); LINFO("Files to read: " + std::to_string(nInputFiles)); diff --git a/modules/gaia/tasks/readspecktask.cpp b/modules/gaia/tasks/readspecktask.cpp index 7a0b45917e..4ba384ab43 100644 --- a/modules/gaia/tasks/readspecktask.cpp +++ b/modules/gaia/tasks/readspecktask.cpp @@ -39,7 +39,7 @@ namespace { struct [[codegen::Dictionary(ReadSpeckTask)]] Parameters { // The path to the SPECK file that are to be read std::string inFilePath; - + // The path to the file to export raw VBO data to std::string outFilePath; }; diff --git a/modules/globebrowsing/globebrowsingmodule.cpp b/modules/globebrowsing/globebrowsingmodule.cpp index f2d103a4b6..f4fd899794 100644 --- a/modules/globebrowsing/globebrowsingmodule.cpp +++ b/modules/globebrowsing/globebrowsingmodule.cpp @@ -406,7 +406,7 @@ scripting::LuaLibrary GlobeBrowsingModule::luaLibrary() const { { // @TODO (2021-06-23, emmbr) Combine with the above function when the camera // paths work really well close to surfaces - "flyToGeo", + "flyToGeo", &globebrowsing::luascriptfunctions::flyToGeo, {}, "[string], number, number, number [, bool, number]", diff --git a/modules/globebrowsing/globebrowsingmodule_lua.inl b/modules/globebrowsing/globebrowsingmodule_lua.inl index 394f768118..e94f6beb81 100644 --- a/modules/globebrowsing/globebrowsingmodule_lua.inl +++ b/modules/globebrowsing/globebrowsingmodule_lua.inl @@ -301,9 +301,8 @@ int flyToGeo(lua_State* L) { altitude ); - using namespace std::string_literals; ghoul::Dictionary instruction; - instruction.setValue("TargetType", "Node"s); + instruction.setValue("TargetType", std::string("Node")); instruction.setValue("Target", n->identifier()); instruction.setValue("Position", positionModelCoords); diff --git a/modules/globebrowsing/src/globetranslation.cpp b/modules/globebrowsing/src/globetranslation.cpp index e935cb723c..12e6f4f883 100644 --- a/modules/globebrowsing/src/globetranslation.cpp +++ b/modules/globebrowsing/src/globetranslation.cpp @@ -122,7 +122,7 @@ GlobeTranslation::GlobeTranslation(const ghoul::Dictionary& dictionary) _altitude = p.altitude.value_or(_altitude); // @TODO (emmbr) uncomment when ranges with negative values are supported - //_altitude.setExponent(8.f); + //_altitude.setExponent(8.f); _altitude.onChange([this]() { setUpdateVariables(); }); addProperty(_altitude); @@ -171,7 +171,7 @@ glm::dvec3 GlobeTranslation::position(const UpdateData&) const { const_cast(this)->fillAttachedNode(); _positionIsDirty = true; } - + if (!_positionIsDirty) { return _position; } diff --git a/modules/globebrowsing/src/renderableglobe.cpp b/modules/globebrowsing/src/renderableglobe.cpp index b36fab95eb..f194eb4be6 100644 --- a/modules/globebrowsing/src/renderableglobe.cpp +++ b/modules/globebrowsing/src/renderableglobe.cpp @@ -1209,8 +1209,8 @@ void RenderableGlobe::renderChunks(const RenderData& data, RendererTasks&, if (global::sessionRecording->isSavingFramesDuringPlayback()) { // If our tile cache is very full, we assume we need to adjust the level of detail // dynamically to not keep rendering frames with unavailable data - // After certain number of iterations(_debugProperties.dynamicLodIterationCount) of - // unavailable/available data in a row, we assume that a change could be made. + // After certain number of iterations(_debugProperties.dynamicLodIterationCount) + // of unavailable/available data in a row, we assume that a change could be made. const int iterCount = _debugProperties.dynamicLodIterationCount; const bool exceededIterations = static_cast(_iterationsOfUnavailableData) > iterCount; diff --git a/modules/globebrowsing/src/ringscomponent.cpp b/modules/globebrowsing/src/ringscomponent.cpp index b04cf026ca..f8c2ff1f1d 100644 --- a/modules/globebrowsing/src/ringscomponent.cpp +++ b/modules/globebrowsing/src/ringscomponent.cpp @@ -64,7 +64,8 @@ namespace { "modelViewProjectionMatrix", "textureOffset", "colorFilterValue", "nightFactor", "sunPosition", "sunPositionObj", "camPositionObj", "ringTextureFwrd", "ringTextureBckwrd", "ringTextureUnlit", "ringTextureColor", - "ringTextureTransparency", "shadowMatrix", "shadowMapTexture", "zFightingPercentage" + "ringTextureTransparency", "shadowMatrix", "shadowMapTexture", + "zFightingPercentage" }; constexpr const std::array GeomUniformNames = { @@ -413,7 +414,10 @@ void RingsComponent::draw(const RenderData& data, RenderPass renderPass, modelViewProjectionTransform ); _shader->setUniform(_uniformCacheAdvancedRings.textureOffset, _offset); - _shader->setUniform(_uniformCacheAdvancedRings.colorFilterValue, _colorFilter); + _shader->setUniform( + _uniformCacheAdvancedRings.colorFilterValue, + _colorFilter + ); _shader->setUniform(_uniformCacheAdvancedRings.nightFactor, _nightFactor); _shader->setUniform(_uniformCacheAdvancedRings.sunPosition, _sunPosition); @@ -496,7 +500,10 @@ void RingsComponent::draw(const RenderData& data, RenderPass renderPass, ghoul::opengl::TextureUnit shadowMapUnit; shadowMapUnit.activate(); glBindTexture(GL_TEXTURE_2D, shadowData.shadowDepthTexture); - _shader->setUniform(_uniformCacheAdvancedRings.shadowMapTexture, shadowMapUnit); + _shader->setUniform( + _uniformCacheAdvancedRings.shadowMapTexture, + shadowMapUnit + ); glEnable(GL_DEPTH_TEST); glEnablei(GL_BLEND, 0); diff --git a/modules/globebrowsing/src/shadowcomponent.cpp b/modules/globebrowsing/src/shadowcomponent.cpp index 71daef9b4a..4266192eae 100644 --- a/modules/globebrowsing/src/shadowcomponent.cpp +++ b/modules/globebrowsing/src/shadowcomponent.cpp @@ -171,7 +171,7 @@ ShadowComponent::ShadowComponent(const ghoul::Dictionary& dictionary) return; } ghoul::Dictionary d = dictionary.value("Shadows"); - + const Parameters p = codegen::bake(d); addProperty(_enabled); diff --git a/modules/globebrowsing/src/tileprovider.cpp b/modules/globebrowsing/src/tileprovider.cpp index 033a47089f..0e21fc43e2 100644 --- a/modules/globebrowsing/src/tileprovider.cpp +++ b/modules/globebrowsing/src/tileprovider.cpp @@ -868,7 +868,7 @@ TemporalTileProvider::TemporalTileProvider(const ghoul::Dictionary& dictionary) useFixedTime = dictionary.value(temporal::UseFixedTimeInfo.identifier); } addProperty(useFixedTime); - + if (dictionary.hasValue(temporal::FixedTimeInfo.identifier)) { fixedTime = dictionary.value(temporal::FixedTimeInfo.identifier); } diff --git a/modules/imgui/include/guiactioncomponent.h b/modules/imgui/include/guiactioncomponent.h index 40e708c093..1395ff6c89 100644 --- a/modules/imgui/include/guiactioncomponent.h +++ b/modules/imgui/include/guiactioncomponent.h @@ -22,8 +22,8 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#ifndef __OPENSPACE_MODULE_IMGUI___GUISHORTCUTSCOMPONENT___H__ -#define __OPENSPACE_MODULE_IMGUI___GUISHORTCUTSCOMPONENT___H__ +#ifndef __OPENSPACE_MODULE_IMGUI___GUIACTIONCOMPONENT___H__ +#define __OPENSPACE_MODULE_IMGUI___GUIACTIONCOMPONENT___H__ #include @@ -38,4 +38,4 @@ public: } // namespace openspace::gui -#endif // __OPENSPACE_MODULE_IMGUI___GUISHORTCUTSCOMPONENT___H__ +#endif // __OPENSPACE_MODULE_IMGUI___GUIACTIONCOMPONENT___H__ diff --git a/modules/imgui/src/renderproperties.cpp b/modules/imgui/src/renderproperties.cpp index 71f566af29..620745e581 100644 --- a/modules/imgui/src/renderproperties.cpp +++ b/modules/imgui/src/renderproperties.cpp @@ -270,7 +270,10 @@ void renderStringProperty(Property* prop, const std::string& ownerName, void renderListProperty(const std::string& name, const std::string& fullIdentifier, const std::string& stringValue, IsRegularProperty isRegular) { - ghoul_assert(stringValue.size() > 2, "an empty list should have the string value '[]'"); + ghoul_assert( + stringValue.size() > 2, + "an empty list should have the string value '[]'" + ); // Remove brackets from the string value std::string value = stringValue.substr(1, stringValue.size() - 2); diff --git a/modules/space/rendering/renderablestars.cpp b/modules/space/rendering/renderablestars.cpp index 3b42e10193..f8aa080ae6 100644 --- a/modules/space/rendering/renderablestars.cpp +++ b/modules/space/rendering/renderablestars.cpp @@ -529,35 +529,35 @@ RenderableStars::RenderableStars(const ghoul::Dictionary& dictionary) _dataMapping.bvColor = p.dataMapping.bv.value_or(""); _dataMapping.bvColor.onChange([this]() { _dataIsDirty = true; }); _dataMappingContainer.addProperty(_dataMapping.bvColor); - + _dataMapping.luminance = p.dataMapping.luminance.value_or(""); _dataMapping.luminance.onChange([this]() { _dataIsDirty = true; }); _dataMappingContainer.addProperty(_dataMapping.luminance); - + _dataMapping.absoluteMagnitude = p.dataMapping.absoluteMagnitude.value_or(""); _dataMapping.absoluteMagnitude.onChange([this]() { _dataIsDirty = true; }); _dataMappingContainer.addProperty(_dataMapping.absoluteMagnitude); - + _dataMapping.apparentMagnitude = p.dataMapping.apparentMagnitude.value_or(""); _dataMapping.apparentMagnitude.onChange([this]() { _dataIsDirty = true; }); _dataMappingContainer.addProperty(_dataMapping.apparentMagnitude); - + _dataMapping.vx = p.dataMapping.vx.value_or(""); _dataMapping.vx.onChange([this]() { _dataIsDirty = true; }); _dataMappingContainer.addProperty(_dataMapping.vx); - + _dataMapping.vy = p.dataMapping.vy.value_or(""); _dataMapping.vy.onChange([this]() { _dataIsDirty = true; }); _dataMappingContainer.addProperty(_dataMapping.vy); - + _dataMapping.vz = p.dataMapping.vz.value_or(""); _dataMapping.vz.onChange([this]() { _dataIsDirty = true; }); _dataMappingContainer.addProperty(_dataMapping.vz); - + _dataMapping.speed = p.dataMapping.speed.value_or(""); _dataMapping.speed.onChange([this]() { _dataIsDirty = true; }); _dataMappingContainer.addProperty(_dataMapping.speed); - + addPropertySubOwner(_dataMappingContainer); _speckFile = p.speckFile.string(); diff --git a/modules/space/speckloader.cpp b/modules/space/speckloader.cpp index 4bf46d86cf..d4165fa3b6 100644 --- a/modules/space/speckloader.cpp +++ b/modules/space/speckloader.cpp @@ -172,7 +172,7 @@ Dataset loadFile(std::filesystem::path path, SkipAllZeroLines skipAllZeroLines) if (startsWith(line, "datavar")) { // each datavar line is following the form: // datavar - // with being the index of the data variable + // with being the index of the data variable std::stringstream str(line); std::string dummy; @@ -197,7 +197,7 @@ Dataset loadFile(std::filesystem::path path, SkipAllZeroLines skipAllZeroLines) std::stringstream str(line); std::string dummy; str >> dummy >> res.textureDataIndex; - + continue; } @@ -216,8 +216,8 @@ Dataset loadFile(std::filesystem::path path, SkipAllZeroLines skipAllZeroLines) std::stringstream str(line); std::string dummy; str >> dummy >> res.orientationDataIndex; - - // Ok.. this is kind of weird. Speck unfortunately doesn't tell us in the + + // Ok.. this is kind of weird. Speck unfortunately doesn't tell us in the // specification how many values a datavar has. Usually this is 1 value per // datavar, unless it is a polygon orientation thing. Now, the datavar name // for these can be anything (have seen 'orientation' and 'ori' before, so we @@ -268,7 +268,7 @@ Dataset loadFile(std::filesystem::path path, SkipAllZeroLines skipAllZeroLines) return lhs.index < rhs.index; } ); - + std::sort( res.textures.begin(), res.textures.end(), [](const Dataset::Texture& lhs, const Dataset::Texture& rhs) { @@ -292,7 +292,7 @@ Dataset loadFile(std::filesystem::path path, SkipAllZeroLines skipAllZeroLines) if (line.back() == '\r') { line = line.substr(0, line.length() - 1); } - + strip(line); if (line.empty()) { @@ -357,7 +357,7 @@ std::optional loadCachedFile(std::filesystem::path path) { if (!file.good()) { return std::nullopt; } - + Dataset result; int8_t fileVersion; @@ -394,7 +394,7 @@ std::optional loadCachedFile(std::filesystem::path path) { result.textures.resize(nTextures); for (int i = 0; i < nTextures; i += 1) { Dataset::Texture tex; - + int16_t idx; file.read(reinterpret_cast(&idx), sizeof(int16_t)); tex.index = idx; @@ -784,7 +784,7 @@ ColorMap loadFile(std::filesystem::path path, SkipAllZeroLines) { if (nColorLines == -1) { // This is the first time we get this far, it will have to be the first number // meaning that it is the number of color values - + str >> nColorLines; res.entries.reserve(nColorLines); } diff --git a/modules/spacecraftinstruments/rendering/renderablefov.cpp b/modules/spacecraftinstruments/rendering/renderablefov.cpp index 9435d3b3bb..8a4971bc32 100644 --- a/modules/spacecraftinstruments/rendering/renderablefov.cpp +++ b/modules/spacecraftinstruments/rendering/renderablefov.cpp @@ -254,7 +254,7 @@ RenderableFov::RenderableFov(const ghoul::Dictionary& dictionary) _alwaysDrawFov = p.alwaysDrawFov.value_or(_alwaysDrawFov); addProperty(_alwaysDrawFov); - + _simplifyBounds = p.simplifyBounds.value_or(_simplifyBounds); addProperty(_colors.defaultStart); diff --git a/modules/spacecraftinstruments/rendering/renderableplanetprojection.cpp b/modules/spacecraftinstruments/rendering/renderableplanetprojection.cpp index 6be4be39c5..72845c2ecb 100644 --- a/modules/spacecraftinstruments/rendering/renderableplanetprojection.cpp +++ b/modules/spacecraftinstruments/rendering/renderableplanetprojection.cpp @@ -50,7 +50,7 @@ namespace { }; constexpr const std::array FboUniformNames = { - "projectionTexture", "ProjectorMatrix", "ModelTransform", + "projectionTexture", "ProjectorMatrix", "ModelTransform", "boresight", "radius", "segments" }; diff --git a/modules/spacecraftinstruments/util/imagesequencer.h b/modules/spacecraftinstruments/util/imagesequencer.h index 9e258310ca..7c837c741c 100644 --- a/modules/spacecraftinstruments/util/imagesequencer.h +++ b/modules/spacecraftinstruments/util/imagesequencer.h @@ -42,9 +42,9 @@ class SequenceParser; * large image data-sets across all openspace renderable instances, both for past and * future unmanned-spacecraft missions. To load the instance with data the client must * provide a parser inherited from the abstract base class SequenceParser. Hence, there is - * no restriction imposed on data input, whether its data in the form of existing images or - * in the form of a planned observation schedule. Notably, in order for the sequencer to - * function the client must provide or write a parser that fills the ImageSequencers + * no restriction imposed on data input, whether its data in the form of existing images + * or in the form of a planned observation schedule. Notably, in order for the sequencer + * to function the client must provide or write a parser that fills the ImageSequencers * private members. * * \see SequenceParser @@ -136,7 +136,7 @@ private: void sortData(); /** - * This handles any types of ambiguities between the data and SPICE calls. This map is + * This handles any types of ambiguities between the data and SPICE calls. This map is * composed of a key that is a string in the data to be translated and a Decoder that * holds the corresponding translation provided through as asset. * \see Decoder @@ -179,7 +179,7 @@ private: std::string _defaultCaptureImage; std::map _latestImages; - + // if no data, no run bool _hasData = false; }; diff --git a/modules/spacecraftinstruments/util/projectioncomponent.cpp b/modules/spacecraftinstruments/util/projectioncomponent.cpp index b51cf27352..729abeb98b 100644 --- a/modules/spacecraftinstruments/util/projectioncomponent.cpp +++ b/modules/spacecraftinstruments/util/projectioncomponent.cpp @@ -109,8 +109,8 @@ namespace { InstrumentTimes [[codegen::key("instrument-times")]], ImageAndInstrumentTimes [[codegen::key("image-and-instrument-times")]] }; - // This value determines which type of sequencer is used for generating image - // schedules. The 'playbook' is using a custom format designed by the New Horizons + // This value determines which type of sequencer is used for generating image + // schedules. The 'playbook' is using a custom format designed by the New Horizons // team, the 'image-sequence' uses lbl files from a directory, and the 'hybrid' // uses both methods std::optional sequenceType; @@ -128,7 +128,7 @@ namespace { // SPICE integer std::string target [[codegen::annotation("A SPICE name of the observed object")]]; - // The aberration correction that is supposed to be used for the projection. The + // The aberration correction that is supposed to be used for the projection. The // values for the correction correspond to the SPICE definition as described in // ftp://naif.jpl.nasa.gov/pub/naif/toolkit_docs/IDL/cspice/spkezr_c.html std::string aberration [[codegen::inlist("NONE", "LT", "LT+S", "CN", "CN+S", @@ -137,18 +137,18 @@ namespace { // The list of potential targets that are involved with the image projection std::optional> potentialTargets; - // Determines whether the object requires a self-shadowing algorithm. This is - // necessary if the object is concave and might cast a shadow on itself during + // Determines whether the object requires a self-shadowing algorithm. This is + // necessary if the object is concave and might cast a shadow on itself during // presentation. The default value is 'false' std::optional textureMap; - // Determines whether the object requires a self-shadowing algorithm. This is - // necessary if the object is concave and might cast a shadow on itself during + // Determines whether the object requires a self-shadowing algorithm. This is + // necessary if the object is concave and might cast a shadow on itself during // presentation. The default value is 'false' std::optional shadowMap; - // Sets the desired aspect ratio of the projected texture. This might be necessary - // as planets usually have 2x1 aspect ratios, whereas this does not hold for + // Sets the desired aspect ratio of the projected texture. This might be necessary + // as planets usually have 2x1 aspect ratios, whereas this does not hold for // non-planet objects (comets, asteroids, etc). The default value is '1.0' std::optional aspectRatio; diff --git a/modules/statemachine/statemachinemodule.cpp b/modules/statemachine/statemachinemodule.cpp index c8b306ba6f..2a52bfd0d4 100644 --- a/modules/statemachine/statemachinemodule.cpp +++ b/modules/statemachine/statemachinemodule.cpp @@ -194,7 +194,8 @@ scripting::LuaLibrary StateMachineModule::luaLibrary() const { &luascriptfunctions::printCurrentStateInfo, {}, "", - "Prints information about the current state and possible transitions to the log." + "Prints information about the current state and possible transitions to the " + "log." }, { "saveToDotFile", diff --git a/modules/sync/syncs/urlsynchronization.cpp b/modules/sync/syncs/urlsynchronization.cpp index f0c418b02c..2f1fac6b81 100644 --- a/modules/sync/syncs/urlsynchronization.cpp +++ b/modules/sync/syncs/urlsynchronization.cpp @@ -49,22 +49,22 @@ namespace { // provided, all files will be downloaded to the same directory std::variant> url; - // This optional identifier will be part of the used folder structure and, if + // This optional identifier will be part of the used folder structure and, if // provided, can be used to manually find the downloaded folder in the // synchronization folder. If this value is not specified, 'UseHash' has to be set // to 'true' std::optional identifier; // If this value is set to 'true' and it is not overwritten by the global - // settings, the file(s) pointed to by this URLSynchronization will always be - // downloaded, thus overwriting the local files. This is useful for files that are + // settings, the file(s) pointed to by this URLSynchronization will always be + // downloaded, thus overwriting the local files. This is useful for files that are // updated regularly remotely and should be fetch at every startup std::optional forceOverride [[codegen::key("override")]]; // If this value is set to 'true' (the default), the hash of the URL is appended - // to the directory name to produce a unique directory under all circumstances. If + // to the directory name to produce a unique directory under all circumstances. If // this is not desired, the URLSynchronization use the bare directory name alone - // if this value is 'false'. If this value is 'false', the identifier has to be + // if this value is 'false'. If this value is 'false', the identifier has to be // specified std::optional useHash; diff --git a/modules/volume/rendering/renderabletimevaryingvolume.cpp b/modules/volume/rendering/renderabletimevaryingvolume.cpp index cd748315cb..363719f835 100644 --- a/modules/volume/rendering/renderabletimevaryingvolume.cpp +++ b/modules/volume/rendering/renderabletimevaryingvolume.cpp @@ -134,7 +134,7 @@ namespace { // actual time. The default value is 0 std::optional secondsBefore; - // Specifies the number of seconds to show the the last timestep after its + // Specifies the number of seconds to show the the last timestep after its // actual time float secondsAfter; diff --git a/modules/volume/tasks/generaterawvolumetask.cpp b/modules/volume/tasks/generaterawvolumetask.cpp index 109703d6f6..771d875782 100644 --- a/modules/volume/tasks/generaterawvolumetask.cpp +++ b/modules/volume/tasks/generaterawvolumetask.cpp @@ -93,7 +93,7 @@ std::string GenerateRawVolumeTask::description() { "value by evaluating the lua function: `{}`, with three arguments (x, y, z) " "ranging from ({}, {}, {}) to ({}, {}, {}). Write raw volume data into {} and " "dictionary with metadata to {}", - _dimensions.x, _dimensions.y, _dimensions.z, _valueFunctionLua, + _dimensions.x, _dimensions.y, _dimensions.z, _valueFunctionLua, _lowerDomainBound.x, _lowerDomainBound.y, _lowerDomainBound.z, _upperDomainBound.x, _upperDomainBound.y, _upperDomainBound.z, _rawVolumeOutputPath, _dictionaryOutputPath diff --git a/src/documentation/verifier.cpp b/src/documentation/verifier.cpp index 22ffdec0a6..857764daa6 100644 --- a/src/documentation/verifier.cpp +++ b/src/documentation/verifier.cpp @@ -462,7 +462,7 @@ TestResult TemplateVerifier::operator()(const ghoul::Dictionary& dic o.offender = key; o.reason = TestResult::Offense::Reason::MissingKey; res.offenses.push_back(o); - return res; + return res; } } } @@ -498,7 +498,7 @@ TestResult TemplateVerifier::operator()(const ghoul::Dictionary& dic o.offender = key; o.reason = TestResult::Offense::Reason::WrongType; res.offenses.push_back(o); - return res; + return res; } } else { @@ -508,7 +508,7 @@ TestResult TemplateVerifier::operator()(const ghoul::Dictionary& dic o.offender = key; o.reason = TestResult::Offense::Reason::WrongType; res.offenses.push_back(o); - return res; + return res; } } else { @@ -565,7 +565,7 @@ TestResult TemplateVerifier::operator()(const ghoul::Dictionary& dic o.offender = key; o.reason = TestResult::Offense::Reason::WrongType; res.offenses.push_back(o); - return res; + return res; } } else { @@ -575,7 +575,7 @@ TestResult TemplateVerifier::operator()(const ghoul::Dictionary& dic o.offender = key; o.reason = TestResult::Offense::Reason::MissingKey; res.offenses.push_back(o); - return res; + return res; } } } diff --git a/src/events/event.cpp b/src/events/event.cpp index f056c2ad33..ad314e99b8 100644 --- a/src/events/event.cpp +++ b/src/events/event.cpp @@ -280,7 +280,7 @@ ghoul::Dictionary toParameter(const Event& e) { case EventParallelConnection::State::Lost: d.setValue("State", "Lost"s); break; - case EventParallelConnection::State::HostshipGained: + case EventParallelConnection::State::HostshipGained: d.setValue("State", "HostshipGained"s); break; case EventParallelConnection::State::HostshipLost: diff --git a/src/interaction/actionmanager_lua.inl b/src/interaction/actionmanager_lua.inl index 1c677d5226..2c03117c5a 100644 --- a/src/interaction/actionmanager_lua.inl +++ b/src/interaction/actionmanager_lua.inl @@ -200,7 +200,7 @@ int actions(lua_State* L) { action.synchronization == interaction::Action::IsSynchronized::Yes ); lua_settable(L, -3); - + lua_settable(L, -3); } diff --git a/src/interaction/sessionrecording.cpp b/src/interaction/sessionrecording.cpp index 2c4b8da045..44ab5daab0 100644 --- a/src/interaction/sessionrecording.cpp +++ b/src/interaction/sessionrecording.cpp @@ -1979,9 +1979,13 @@ bool SessionRecording::processCameraKeyframe(double now) { } // getPrevTimestamp(); - double prevTime = appropriateTimestamp(_timeline[_idxTimeline_cameraPtrPrev].t3stamps); + double prevTime = appropriateTimestamp( + _timeline[_idxTimeline_cameraPtrPrev].t3stamps + ); // getNextTimestamp(); - double nextTime = appropriateTimestamp(_timeline[_idxTimeline_cameraPtrNext].t3stamps); + double nextTime = appropriateTimestamp( + _timeline[_idxTimeline_cameraPtrNext].t3stamps + ); double t; if ((nextTime - prevTime) < 1e-7) { diff --git a/src/navigation/navigationhandler.cpp b/src/navigation/navigationhandler.cpp index f3d18229d5..10fd242a53 100644 --- a/src/navigation/navigationhandler.cpp +++ b/src/navigation/navigationhandler.cpp @@ -215,7 +215,7 @@ void NavigationHandler::applyNavigationState(const NavigationState& ns) { void NavigationHandler::updateCameraTransitions() { // This function is concerned with managing transitions of the camera between - // different distances of interest relative to the focus node. For each transition two + // different distances of interest relative to the focus node. For each transition two // scenarios are handled; SceneGraphNodes can have attached actions for each // transition, which are automatically triggered. Additionally, an // EventCameraTransition event is fired that contains information about the focus node @@ -228,7 +228,7 @@ void NavigationHandler::updateCameraTransitions() { // // |<------------------->| Approach factor * Interaction sphere // |<------>| Reach Factor * Interaction sphere - // + // // ( ( O ) ) // ^ ^ ^ ^ // OnExit OnMoveAway OnReach OnApproach diff --git a/src/navigation/navigationhandler_lua.inl b/src/navigation/navigationhandler_lua.inl index c3c9b1e4a4..02cb94216c 100644 --- a/src/navigation/navigationhandler_lua.inl +++ b/src/navigation/navigationhandler_lua.inl @@ -217,7 +217,7 @@ int bindJoystickButton(lua_State* L) { actionStr = actionStr.value_or("Press"); isRemote = isRemote.value_or(true); - interaction::JoystickAction action = + interaction::JoystickAction action = ghoul::from_string(*actionStr); global::navigationHandler->bindJoystickButtonCommand( diff --git a/src/navigation/navigationstate.cpp b/src/navigation/navigationstate.cpp index 52a0346170..7d99eb4095 100644 --- a/src/navigation/navigationstate.cpp +++ b/src/navigation/navigationstate.cpp @@ -80,8 +80,8 @@ NavigationState::NavigationState(const ghoul::Dictionary& dictionary) { } NavigationState::NavigationState(std::string anchor_, std::string aim_, - std::string referenceFrame_, glm::dvec3 position_, - std::optional up_, + std::string referenceFrame_, glm::dvec3 position_, + std::optional up_, double yaw_, double pitch_) : anchor(std::move(anchor_)) , aim(std::move(aim_)) diff --git a/src/navigation/orbitalnavigator.cpp b/src/navigation/orbitalnavigator.cpp index 13623fb3e3..fded5fca7f 100644 --- a/src/navigation/orbitalnavigator.cpp +++ b/src/navigation/orbitalnavigator.cpp @@ -463,7 +463,9 @@ OrbitalNavigator::OrbitalNavigator() addPropertySubOwner(_linearFlight); addPropertySubOwner(_idleBehavior); - _idleBehaviorDampenInterpolator.setTransferFunction(ghoul::quadraticEaseInOut); + _idleBehaviorDampenInterpolator.setTransferFunction( + ghoul::quadraticEaseInOut + ); _idleBehavior.dampenInterpolationTime.onChange([&]() { _idleBehaviorDampenInterpolator.setInterpolationTime( _idleBehavior.dampenInterpolationTime @@ -1631,8 +1633,8 @@ void OrbitalNavigator::applyIdleBehavior(double deltaTime, glm::dvec3& position, break; case IdleBehavior::Behavior::OrbitAtConstantLat: { // Assume that "north" coincides with the local z-direction - // @TODO (2021-07-09, emmbr) Make each scene graph node aware of its own - // north/up, so that we can query this information rather than assuming it. + // @TODO (2021-07-09, emmbr) Make each scene graph node aware of its own + // north/up, so that we can query this information rather than assuming it. // The we could also combine this idle behavior with the next const glm::dvec3 north = glm::dvec3(0.0, 0.0, 1.0); orbitAroundAxis(north, deltaTime, position, globalRotation, speedScale); @@ -1672,14 +1674,14 @@ void OrbitalNavigator::orbitAnchor(double deltaTime, glm::dvec3& position, position += rotationDiffVec3; } -void OrbitalNavigator::orbitAroundAxis(const glm::dvec3 axis, double deltaTime, +void OrbitalNavigator::orbitAroundAxis(const glm::dvec3 axis, double deltaTime, glm::dvec3& position, glm::dquat& globalRotation, double speedScale) { ghoul_assert(_anchorNode != nullptr, "Node to orbit must be set!"); const glm::dmat4 modelTransform = _anchorNode->modelTransform(); - const glm::dvec3 axisInWorldCoords = + const glm::dvec3 axisInWorldCoords = glm::dmat3(modelTransform) * glm::normalize(axis); // Compute rotation to be applied around the axis diff --git a/src/navigation/path.cpp b/src/navigation/path.cpp index 8e6b03cdff..97a937cd41 100644 --- a/src/navigation/path.cpp +++ b/src/navigation/path.cpp @@ -59,7 +59,8 @@ namespace { // The desired duration traversing the specified path segment should take std::optional duration; - // (Node): The target node of the camera path. Not optional for 'Node' instructions + // (Node): The target node of the camera path. Not optional for 'Node' + // instructions std::optional target; // (Node): An optional position in relation to the target node, in model @@ -271,9 +272,11 @@ double Path::speedAlongPath(double traveledDistance) const { speed *= remainingDistance / closeUpDistance + 0.01; } - // TODO: also dampen speed based on curvature, or make sure the curve has a rounder shape + // TODO: also dampen speed based on curvature, or make sure the curve has a rounder + // shape - // TODO: check for when path is shorter than the starUpDistance or closeUpDistance variables + // TODO: check for when path is shorter than the starUpDistance or closeUpDistance + // variables return _speedFactorFromDuration * speed; } @@ -384,7 +387,9 @@ Waypoint computeWaypointFromNodeInfo(const NodeInfo& info, const Waypoint& start if (info.position.has_value()) { // The position in instruction is given in the targetNode's local coordinates. // Convert to world coordinates - targetPos = glm::dvec3(targetNode->modelTransform() * glm::dvec4(*info.position, 1.0)); + targetPos = glm::dvec3( + targetNode->modelTransform() * glm::dvec4(*info.position, 1.0) + ); } else { const double radius = Waypoint::findValidBoundingSphere(targetNode); diff --git a/src/navigation/pathcurves/zoomoutoverviewcurve.cpp b/src/navigation/pathcurves/zoomoutoverviewcurve.cpp index 965fbfe3ab..4f96553a44 100644 --- a/src/navigation/pathcurves/zoomoutoverviewcurve.cpp +++ b/src/navigation/pathcurves/zoomoutoverviewcurve.cpp @@ -80,7 +80,8 @@ ZoomOutOverviewCurve::ZoomOutOverviewCurve(const Waypoint& start, const Waypoint goodStepDirection = glm::normalize(n1 + n2); } - // Find a direction that is orthogonal to the line between the start and end position + // Find a direction that is orthogonal to the line between the start and end + // position const glm::dvec3 startPosToEndPos = end.position() - start.position(); const glm::dvec3 outwardStepVector = 0.5 * glm::length(startPosToEndPos) * goodStepDirection; diff --git a/src/navigation/pathnavigator.cpp b/src/navigation/pathnavigator.cpp index 87edf005e7..94dff5aa2c 100644 --- a/src/navigation/pathnavigator.cpp +++ b/src/navigation/pathnavigator.cpp @@ -72,7 +72,8 @@ namespace { "triggered once the path has reached its target." }; - constexpr const openspace::properties::Property::PropertyInfo MinBoundingSphereInfo = { + constexpr const openspace::properties::Property::PropertyInfo MinBoundingSphereInfo = + { "MinimalValidBoundingSphere", "Minimal Valid Bounding Sphere", "The minimal allowed value for a bounding sphere, in meters. Used for " @@ -203,8 +204,10 @@ void PathNavigator::updateCamera(double deltaTime) { if (_applyIdleBehaviorOnFinish) { constexpr const char* ApplyIdleBehaviorScript = - "local f = 'NavigationHandler.OrbitalNavigator.IdleBehavior.ApplyIdleBehavior';" - "openspace.setPropertyValueSingle(f, true);"; + "openspace.setPropertyValueSingle(" + "'NavigationHandler.OrbitalNavigator.IdleBehavior.ApplyIdleBehavior'," + "true" + ");"; global::scriptEngine->queueScript( ApplyIdleBehaviorScript, diff --git a/src/navigation/pathnavigator_lua.inl b/src/navigation/pathnavigator_lua.inl index a5a71f1c59..2e946a8492 100644 --- a/src/navigation/pathnavigator_lua.inl +++ b/src/navigation/pathnavigator_lua.inl @@ -86,9 +86,8 @@ int goTo(lua_State* L) { return ghoul::lua::luaError(L, "Unknown node name: " + nodeIdentifier); } - using namespace std::string_literals; ghoul::Dictionary insDict; - insDict.setValue("TargetType", "Node"s); + insDict.setValue("TargetType", std::string("Node")); insDict.setValue("Target", nodeIdentifier); if (useUpFromTargetOrDuration.has_value()) { if (std::holds_alternative(*useUpFromTargetOrDuration)) { @@ -134,9 +133,8 @@ int goToHeight(lua_State* L) { return ghoul::lua::luaError(L, "Unknown node name: " + nodeIdentifier); } - using namespace std::string_literals; ghoul::Dictionary insDict; - insDict.setValue("TargetType", "Node"s); + insDict.setValue("TargetType", std::string("Node")); insDict.setValue("Target", nodeIdentifier); insDict.setValue("Height", height); if (useUpFromTargetOrDuration.has_value()) { @@ -190,9 +188,8 @@ int goToNavigationState(lua_State* L) { ); } - using namespace std::string_literals; ghoul::Dictionary instruction; - instruction.setValue("TargetType", "NavigationState"s); + instruction.setValue("TargetType", std::string("NavigationState")); instruction.setValue("NavigationState", navigationState); if (duration.has_value()) { diff --git a/src/navigation/waypoint.cpp b/src/navigation/waypoint.cpp index 5799a92635..c1080533bb 100644 --- a/src/navigation/waypoint.cpp +++ b/src/navigation/waypoint.cpp @@ -53,7 +53,7 @@ Waypoint::Waypoint(const glm::dvec3& pos, const glm::dquat& rot, const std::stri } Waypoint::Waypoint(const NavigationState& ns) { - const SceneGraphNode* anchorNode = sceneGraphNode(ns.anchor); + const SceneGraphNode* anchorNode = sceneGraphNode(ns.anchor); if (!anchorNode) { LERROR(fmt::format("Could not find node '{}' to target", ns.anchor)); @@ -92,7 +92,7 @@ double Waypoint::validBoundingSphere() const { double Waypoint::findValidBoundingSphere(const SceneGraphNode* node) { double bs = static_cast(node->boundingSphere()); - const double minValidBoundingSphere = + const double minValidBoundingSphere = global::navigationHandler->pathNavigator().minValidBoundingSphere(); if (bs < minValidBoundingSphere) { diff --git a/src/rendering/helper.cpp b/src/rendering/helper.cpp index cfa790b3d0..9d5d6f8138 100644 --- a/src/rendering/helper.cpp +++ b/src/rendering/helper.cpp @@ -458,7 +458,7 @@ std::pair, std::vector> createSphere(int nSegments // 0 -> PI // azimuth angle (east to west) const float theta = fi * glm::pi() / nSegments; - + // 0 -> 2*PI const float phi = fj * glm::pi() * 2.f / nSegments; diff --git a/src/rendering/renderengine.cpp b/src/rendering/renderengine.cpp index 7bdb20d222..b9c4bafc9f 100644 --- a/src/rendering/renderengine.cpp +++ b/src/rendering/renderengine.cpp @@ -260,7 +260,7 @@ namespace { "Enabled Font Color", "The font color used for enabled options." }; - + constexpr openspace::properties::Property::PropertyInfo DisabledFontColorInfo = { "DisabledFontColor", "Disabled Font Color", @@ -399,7 +399,7 @@ RenderEngine::RenderEngine() _enabledFontColor.setViewOption(openspace::properties::Property::ViewOptions::Color); addProperty(_enabledFontColor); - + _disabledFontColor.setViewOption(openspace::properties::Property::ViewOptions::Color); addProperty(_disabledFontColor); } diff --git a/src/rendering/screenspacerenderable.cpp b/src/rendering/screenspacerenderable.cpp index ef4b358966..d001481b64 100644 --- a/src/rendering/screenspacerenderable.cpp +++ b/src/rendering/screenspacerenderable.cpp @@ -258,7 +258,7 @@ namespace { std::optional opacity [[codegen::inrange(0.f, 1.f)]]; // Defines either a single or multiple tags that apply to this - // ScreenSpaceRenderable, thus making it possible to address multiple, separate + // ScreenSpaceRenderable, thus making it possible to address multiple, separate // Renderables with a single property change std::optional>> tag; }; diff --git a/src/scene/scene.cpp b/src/scene/scene.cpp index f673ecf336..dacc2d65c0 100644 --- a/src/scene/scene.cpp +++ b/src/scene/scene.cpp @@ -911,14 +911,16 @@ scripting::LuaLibrary Scene::luaLibrary() { &luascriptfunctions::worldPosition, {}, "string", - "Returns the world position of the scene graph node with the given string as identifier" + "Returns the world position of the scene graph node with the given " + "string as identifier" }, { "worldRotation", & luascriptfunctions::worldRotation, {}, "string", - "Returns the world rotation matrix of the scene graph node with the given string as identifier" + "Returns the world rotation matrix of the scene graph node with the " + "given string as identifier" } } }; diff --git a/src/scene/scene_lua.inl b/src/scene/scene_lua.inl index c05919350a..539e4ca1fa 100644 --- a/src/scene/scene_lua.inl +++ b/src/scene/scene_lua.inl @@ -618,7 +618,7 @@ int addSceneGraphNode(lua_State* L) { d.value("Identifier") : "Scene"; LERRORC(cat, ghoul::to_string(e.result)); - + return ghoul::lua::luaError( L, fmt::format("Error loading scene graph node: {}", e.what()) diff --git a/src/scene/scenelicensewriter.cpp b/src/scene/scenelicensewriter.cpp index 8e1f9149e3..e9eba3ce1a 100644 --- a/src/scene/scenelicensewriter.cpp +++ b/src/scene/scenelicensewriter.cpp @@ -70,12 +70,30 @@ std::string SceneLicenseWriter::generateJson() const { constexpr const char* replStr = R"("{}": "{}", )"; constexpr const char* replStr2 = R"("{}": "{}")"; json << "{"; - json << fmt::format(replStr, "name", escapedJson(global::profile->meta->name.value())); - json << fmt::format(replStr, "version", escapedJson(global::profile->meta->version.value())); - json << fmt::format(replStr, "description", escapedJson(global::profile->meta->description.value())); - json << fmt::format(replStr, "author", escapedJson(global::profile->meta->author.value())); - json << fmt::format(replStr, "url", escapedJson(global::profile->meta->url.value())); - json << fmt::format(replStr2, "license", escapedJson(global::profile->meta->license.value())); + json << fmt::format( + replStr, + "name", escapedJson(global::profile->meta->name.value_or("")) + ); + json << fmt::format( + replStr, + "version", escapedJson(global::profile->meta->version.value_or("")) + ); + json << fmt::format( + replStr, + "description", escapedJson(global::profile->meta->description.value_or("")) + ); + json << fmt::format( + replStr, + "author", escapedJson(global::profile->meta->author.value_or("")) + ); + json << fmt::format( + replStr, + "url", escapedJson(global::profile->meta->url.value_or("")) + ); + json << fmt::format( + replStr2, + "license", escapedJson(global::profile->meta->license.value_or("")) + ); json << "}"; if (++metaCount != metaTotal) { diff --git a/src/scripting/scriptscheduler.cpp b/src/scripting/scriptscheduler.cpp index c80e1487fb..5d32959f01 100644 --- a/src/scripting/scriptscheduler.cpp +++ b/src/scripting/scriptscheduler.cpp @@ -40,7 +40,7 @@ namespace { // executed instead std::string time; - // The Lua script that will be executed when the specified time is passed + // The Lua script that will be executed when the specified time is passed // independent of its direction. This script will be executed before the // specific scripts if both versions are specified std::optional script; diff --git a/src/scripting/scriptscheduler_lua.inl b/src/scripting/scriptscheduler_lua.inl index 2fe74d9ede..9bf64dad5e 100644 --- a/src/scripting/scriptscheduler_lua.inl +++ b/src/scripting/scriptscheduler_lua.inl @@ -46,7 +46,7 @@ int loadFile(lua_State* L) { for (size_t i = 1; i <= scriptsDict.size(); ++i) { ghoul::Dictionary d = scriptsDict.value(std::to_string(i)); - scripting::ScriptScheduler::ScheduledScript script = + scripting::ScriptScheduler::ScheduledScript script = scripting::ScriptScheduler::ScheduledScript(d); scripts.push_back(script); } diff --git a/src/util/keys.cpp b/src/util/keys.cpp index 0078b379bd..8eb94c13e1 100644 --- a/src/util/keys.cpp +++ b/src/util/keys.cpp @@ -93,9 +93,9 @@ std::string keyToString(KeyWithModifier keyWithModifier) { std::string modifier; if (keyWithModifier.modifier != KeyModifier::None) { for (const openspace::KeyModifierInfo& kmi : openspace::KeyModifierInfos) { - // No need for an extra check for the empty modifier since that is mapped to 0, - // meaning that the `hasKeyModifier` will always fail for it since it checks - // internally against != 0 + // No need for an extra check for the empty modifier since that is mapped + // to 0, meaning that the `hasKeyModifier` will always fail for it since it + // checks internally against != 0 if (hasKeyModifier(keyWithModifier.modifier, kmi.modifier)) { modifier += fmt::format("{}+", kmi.identifier); @@ -126,7 +126,7 @@ std::string to_string(const openspace::Key& key) { return std::string(ki.name); } } - + throw ghoul::MissingCaseException(); } diff --git a/src/util/resourcesynchronization.cpp b/src/util/resourcesynchronization.cpp index 45b655ea30..06948ff505 100644 --- a/src/util/resourcesynchronization.cpp +++ b/src/util/resourcesynchronization.cpp @@ -33,7 +33,7 @@ namespace { struct [[codegen::Dictionary(ResourceSynchronization)]] Parameters { // This key specifies the type of ResourceSyncrhonization that gets created. It // has to be one of the valid ResourceSyncrhonizations that are available for - // creation (see the FactoryDocumentation for a list of possible + // creation (see the FactoryDocumentation for a list of possible // ResourceSyncrhonizations), which depends on the configration of the application std::string type [[codegen::annotation("A ResourceSynchronization created by a factory")]]; diff --git a/src/util/spicemanager.cpp b/src/util/spicemanager.cpp index b5500e1690..6bb9810180 100644 --- a/src/util/spicemanager.cpp +++ b/src/util/spicemanager.cpp @@ -1377,20 +1377,22 @@ scripting::LuaLibrary SpiceManager::luaLibrary() { &luascriptfunctions::rotationMatrix, {}, "{string, string, string}", - "Returns the rotationMatrix for a given body in a frame of reference at a specific" - "time. The first agument is the target body, the second is the frame of reference," - " the third is the time. Example: openspace.spice.rotationMatrix('" - "INSIGHT_LANDER_CRUISE','MARS', '2018 NOV 26 19:45:34')." + "Returns the rotationMatrix for a given body in a frame of reference at " + "a specific time. The first agument is the target body, the second is " + "the frame of reference, the third is the time. Example: " + "openspace.spice.rotationMatrix('INSIGHT_LANDER_CRUISE','MARS'," + "'2018 NOV 26 19:45:34')." }, { "position", &luascriptfunctions::position, {}, "{string, string, string, string}", - "Returns the position for a target by an observer in a frame of reference at a specific" - "time. The first agument is the target body, the second is the observer body, the third" - "is the frame of reference, and the fourth is the time. Example: openspace.spice." - "position('INSIGHT','MARS','GALACTIC', '2018 NOV 26 19:45:34')." + "Returns the position for a target by an observer in a frame of " + "reference at a specific time. The first agument is the target body, the " + "second is the observer body, the third is the frame of reference, and " + "the fourth is the time. Example: openspace.spice.position('INSIGHT'," + "'MARS','GALACTIC', '2018 NOV 26 19:45:34')." }, { "getSpiceBodies", diff --git a/src/util/spicemanager_lua.inl b/src/util/spicemanager_lua.inl index 268de67d63..9a00ecca00 100644 --- a/src/util/spicemanager_lua.inl +++ b/src/util/spicemanager_lua.inl @@ -58,7 +58,7 @@ int loadKernel(lua_State* L) { */ int unloadKernel(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::unloadKernel"); - std::variant argument = + std::variant argument = ghoul::lua::value>(L); if (std::holds_alternative(argument)) { @@ -161,7 +161,7 @@ int rotationMatrix(lua_State* L) { /** * position({string, string, string, string}): - * Returns the position for a given body relative to another body, + * Returns the position for a given body relative to another body, * in a given frame of reference, at a specific time. */ int position(lua_State* L) { diff --git a/src/util/time_lua.inl b/src/util/time_lua.inl index 9c519ae5c2..76fb105660 100644 --- a/src/util/time_lua.inl +++ b/src/util/time_lua.inl @@ -227,7 +227,7 @@ int time_interpolateTogglePause(lua_State* L) { */ int time_pauseToggleViaKeyboard(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::time_pauseToggleViaKeyboard"); - + if (global::sessionRecording->isPlayingBack()) { bool isPlaybackPaused = global::sessionRecording->isPlaybackPaused(); global::sessionRecording->setPlaybackPause(!isPlaybackPaused); @@ -462,17 +462,17 @@ int time_advancedTime(lua_State* L) { try { double value = std::stod(std::string(modifier.begin(), it)); - std::string unitName = std::string(it, modifier.end()); + std::string uName = std::string(it, modifier.end()); TimeUnit unit = TimeUnit::Second; - if (unitName == "s") { unit = TimeUnit::Second; } - else if (unitName == "m") { unit = TimeUnit::Minute; } - else if (unitName == "h") { unit = TimeUnit::Hour; } - else if (unitName == "d") { unit = TimeUnit::Day; } - else if (unitName == "M") { unit = TimeUnit::Month; } - else if (unitName == "y") { unit = TimeUnit::Year; } + if (uName == "s") { unit = TimeUnit::Second; } + else if (uName == "m") { unit = TimeUnit::Minute; } + else if (uName == "h") { unit = TimeUnit::Hour; } + else if (uName == "d") { unit = TimeUnit::Day; } + else if (uName == "M") { unit = TimeUnit::Month; } + else if (uName == "y") { unit = TimeUnit::Year; } else { - return ghoul::lua::luaError(L, fmt::format("Unknown unit '{}'", unitName)); + return ghoul::lua::luaError(L, fmt::format("Unknown unit '{}'", uName)); } dt = convertTime(value, unit, TimeUnit::Second);