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