diff --git a/ext/ghoul b/ext/ghoul index bce78a781c..350c0f6ec9 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit bce78a781c0da924e54af01e031ecc3de62441f5 +Subproject commit 350c0f6ec9df6bbaf3790109188d6c97600fb60d diff --git a/include/openspace/interaction/joystickinputstate.h b/include/openspace/interaction/joystickinputstate.h index c5d320c7b8..e256f39552 100644 --- a/include/openspace/interaction/joystickinputstate.h +++ b/include/openspace/interaction/joystickinputstate.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -126,18 +127,18 @@ inline std::string to_string(const openspace::interaction::JoystickAction& value case openspace::interaction::JoystickAction::Press: return "Press"; case openspace::interaction::JoystickAction::Repeat: return "Repeat"; case openspace::interaction::JoystickAction::Release: return "Release"; - default: throw MissingCaseException(); + default: throw MissingCaseException(); } } template <> constexpr openspace::interaction::JoystickAction from_string(std::string_view string) { - if (string == "Idle") { return openspace::interaction::JoystickAction::Idle; } - if (string == "Press") { return openspace::interaction::JoystickAction::Press; } - if (string == "Repeat") { return openspace::interaction::JoystickAction::Repeat; } + if (string == "Idle") { return openspace::interaction::JoystickAction::Idle; } + if (string == "Press") { return openspace::interaction::JoystickAction::Press; } + if (string == "Repeat") { return openspace::interaction::JoystickAction::Repeat; } if (string == "Release") { return openspace::interaction::JoystickAction::Release; } - throw RuntimeError("Unknown action '" + std::string(string) + "'"); + throw RuntimeError(fmt::format("Unknown action '{}'", string)); } } // namespace ghoul diff --git a/modules/base/CMakeLists.txt b/modules/base/CMakeLists.txt index 4a69424b32..f294216f35 100644 --- a/modules/base/CMakeLists.txt +++ b/modules/base/CMakeLists.txt @@ -108,6 +108,7 @@ set(SOURCE_FILES rendering/renderabletrailorbit.cpp rendering/renderabletrailtrajectory.cpp rendering/screenspacedashboard.cpp + rendering/screenspacedashboard_lua.inl rendering/screenspaceframebuffer.cpp rendering/screenspaceimagelocal.cpp rendering/screenspaceimageonline.cpp diff --git a/modules/base/rendering/screenspacedashboard.cpp b/modules/base/rendering/screenspacedashboard.cpp index 5c3ebae6eb..5cbb793421 100644 --- a/modules/base/rendering/screenspacedashboard.cpp +++ b/modules/base/rendering/screenspacedashboard.cpp @@ -54,79 +54,10 @@ namespace { #include "screenspacedashboard_codegen.cpp" } // namespace +#include "screenspacedashboard_lua.inl" + namespace openspace { -namespace luascriptfunctions { - -/** -* \ingroup LuaScripts -* addDashboardItemToScreenSpace(string, table): -*/ -int addDashboardItemToScreenSpace(lua_State* L) { - ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::addDashboardItemToScreenSpace"); - - const std::string& name = ghoul::lua::value(L, 1); - const int type = lua_type(L, 2); - if (type != LUA_TTABLE) { - return ghoul::lua::luaError(L, "Expected argument of type 'table'"); - } - - ghoul::Dictionary d; - try { - ghoul::lua::luaDictionaryFromState(L, d); - } - catch (const ghoul::lua::LuaFormatException& e) { - LERRORC("addDashboardItem", e.what()); - return 0; - } - - ScreenSpaceRenderable* ssr = global::renderEngine->screenSpaceRenderable(name); - - if (!ssr) { - return ghoul::lua::luaError(L, "Provided name is not a ScreenSpace item"); - } - - ScreenSpaceDashboard* dash = dynamic_cast(ssr); - if (!dash) { - return ghoul::lua::luaError( - L, - "Provided name is a ScreenSpace item but not a dashboard" - ); - } - - dash->dashboard().addDashboardItem(DashboardItem::createFromDictionary(d)); - - lua_settop(L, 0); - return 0; -} - -/** -* \ingroup LuaScripts -* removeDashboardItemsFromScreenSpace(string): -*/ -int removeDashboardItemsFromScreenSpace(lua_State* L) { - ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::removeDashboardItemsFromScreenSpace"); - - const std::string& name = ghoul::lua::value(L, 1); - ScreenSpaceRenderable* ssr = global::renderEngine->screenSpaceRenderable(name); - - if (!ssr) { - return ghoul::lua::luaError(L, "Provided name is not a ScreenSpace item"); - } - - ScreenSpaceDashboard* dash = dynamic_cast(ssr); - if (!dash) { - return ghoul::lua::luaError( - L, - "Provided name is a ScreenSpace item but not a dashboard" - ); - } - - dash->dashboard().clearDashboardItems(); - return 0; -} -} // namespace luascriptfunctions - documentation::Documentation ScreenSpaceDashboard::Documentation() { return codegen::doc("base_screenspace_dashboard"); } diff --git a/modules/base/rendering/screenspacedashboard_lua.inl b/modules/base/rendering/screenspacedashboard_lua.inl new file mode 100644 index 0000000000..ba424e8a5d --- /dev/null +++ b/modules/base/rendering/screenspacedashboard_lua.inl @@ -0,0 +1,77 @@ +/***************************************************************************************** + * * + * 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 { + +/** + * \ingroup LuaScripts + * addDashboardItemToScreenSpace(string, table): + */ +int addDashboardItemToScreenSpace(lua_State* L) { + ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::addDashboardItemToScreenSpace"); + auto [name, d] = ghoul::lua::values(L); + + ScreenSpaceRenderable* ssr = global::renderEngine->screenSpaceRenderable(name); + if (!ssr) { + return ghoul::lua::luaError(L, "Provided name is not a ScreenSpace item"); + } + + ScreenSpaceDashboard* dash = dynamic_cast(ssr); + if (!dash) { + return ghoul::lua::luaError( + L, + "Provided name is a ScreenSpace item but not a dashboard" + ); + } + + dash->dashboard().addDashboardItem(DashboardItem::createFromDictionary(d)); + return 0; +} + +/** + * \ingroup LuaScripts + * removeDashboardItemsFromScreenSpace(string): + */ +int removeDashboardItemsFromScreenSpace(lua_State* L) { + ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::removeDashboardItemsFromScreenSpace"); + const std::string name = ghoul::lua::value(L); + + ScreenSpaceRenderable* ssr = global::renderEngine->screenSpaceRenderable(name); + if (!ssr) { + return ghoul::lua::luaError(L, "Provided name is not a ScreenSpace item"); + } + + ScreenSpaceDashboard* dash = dynamic_cast(ssr); + if (!dash) { + return ghoul::lua::luaError( + L, + "Provided name is a ScreenSpace item but not a dashboard" + ); + } + + dash->dashboard().clearDashboardItems(); + return 0; +} + +} // namespace openspace::luascriptfunctions diff --git a/modules/exoplanets/exoplanetsmodule_lua.inl b/modules/exoplanets/exoplanetsmodule_lua.inl index f5359e9dbe..4a2128b9dc 100644 --- a/modules/exoplanets/exoplanetsmodule_lua.inl +++ b/modules/exoplanets/exoplanetsmodule_lua.inl @@ -88,43 +88,45 @@ ExoplanetSystem findExoplanetSystemInData(std::string_view starName) { std::string name; std::getline(ss, name, ','); - if (name.substr(0, name.length() - 2) == starName) { - std::string location_s; - std::getline(ss, location_s); - long location = std::stol(location_s.c_str()); + if (name.substr(0, name.length() - 2) != starName) { + continue; + } - data.seekg(location); - data.read(reinterpret_cast(&p), sizeof(ExoplanetDataEntry)); + std::string location_s; + std::getline(ss, location_s); + long location = std::stol(location_s.c_str()); - sanitizeNameString(name); + data.seekg(location); + data.read(reinterpret_cast(&p), sizeof(ExoplanetDataEntry)); - if (!hasSufficientData(p)) { - LWARNING(fmt::format("Insufficient data for exoplanet: '{}'", name)); - continue; - } + sanitizeNameString(name); - system.planetNames.push_back(name); - system.planetsData.push_back(p); + if (!hasSufficientData(p)) { + LWARNING(fmt::format("Insufficient data for exoplanet: '{}'", name)); + continue; + } - // Star data - Should not vary between planets, but one data entry might - // lack data for the host star while another does not. So for every planet, - // update star data if needed - const glm::vec3 pos{ p.positionX, p.positionY, p.positionZ }; - if (system.starData.position != pos && isValidPosition(pos)) { - system.starData.position = pos; - } - if (system.starData.radius != p.rStar && !std::isnan(p.rStar)) { - system.starData.radius = p.rStar; - } - if (system.starData.bv != p.bmv && !std::isnan(p.bmv)) { - system.starData.bv = p.bmv; - } - if (system.starData.teff != p.teff && !std::isnan(p.teff)) { - system.starData.teff = p.teff; - } - if (system.starData.luminosity != p.luminosity && !std::isnan(p.luminosity)) { - system.starData.luminosity = p.luminosity; - } + system.planetNames.push_back(name); + system.planetsData.push_back(p); + + // Star data - Should not vary between planets, but one data entry might lack data + // for the host star while another does not. So for every planet, update star data + // if needed + const glm::vec3 pos = glm::vec3(p.positionX, p.positionY, p.positionZ); + if (system.starData.position != pos && isValidPosition(pos)) { + system.starData.position = pos; + } + if (system.starData.radius != p.rStar && !std::isnan(p.rStar)) { + system.starData.radius = p.rStar; + } + if (system.starData.bv != p.bmv && !std::isnan(p.bmv)) { + system.starData.bv = p.bmv; + } + if (system.starData.teff != p.teff && !std::isnan(p.teff)) { + system.starData.teff = p.teff; + } + if (system.starData.luminosity != p.luminosity && !std::isnan(p.luminosity)) { + system.starData.luminosity = p.luminosity; } } @@ -555,50 +557,40 @@ void createExoplanetSystem(const std::string& starName) { int addExoplanetSystem(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::addExoplanetSystem"); + std::variant v = + ghoul::lua::value>(L); - const int t = lua_type(L, 1); - if (t == LUA_TSTRING) { + if (std::holds_alternative(v)) { // The user provided a single name - const std::string& starName = ghoul::lua::value(L, 1); + std::string starName = std::get(v); createExoplanetSystem(starName); } - else if (t == LUA_TTABLE) { + else { // A list of names was provided - ghoul::Dictionary d; - ghoul::lua::luaDictionaryFromState(L, d); - - for (size_t i = 1; i <= d.size(); ++i) { - if (!d.hasValue(std::to_string(i))) { + ghoul::Dictionary starNames = ghoul::lua::value(L); + for (size_t i = 1; i <= starNames.size(); ++i) { + if (!starNames.hasValue(std::to_string(i))) { return ghoul::lua::luaError( - L, fmt::format("List item {} is of invalid type", i) + L, + fmt::format("List item {} is of invalid type", i) ); } - const std::string& starName = d.value(std::to_string(i)); + const std::string& starName = starNames.value(std::to_string(i)); createExoplanetSystem(starName); } - lua_pop(L, 1); } - else { - return ghoul::lua::luaError(L, "Invalid input"); - } - - lua_settop(L, 0); - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int removeExoplanetSystem(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::removeExoplanetSystem"); + std::string starName = ghoul::lua::value(L); - const int StringLocation = -1; - const std::string starName = luaL_checkstring(L, StringLocation); - const std::string starIdentifier = createIdentifier(starName); - + const std::string starIdentifier = createIdentifier(std::move(starName)); openspace::global::scriptEngine->queueScript( "openspace.removeSceneGraphNode('" + starIdentifier + "');", scripting::ScriptEngine::RemoteScripting::Yes ); - return 0; } @@ -656,7 +648,6 @@ std::vector hostStarsWithSufficientData() { // For easier read, sort by names and remove duplicates std::sort(names.begin(), names.end()); names.erase(std::unique(names.begin(), names.end()), names.end()); - return names; } @@ -664,15 +655,13 @@ int getListOfExoplanets(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::getListOfExoplanets"); std::vector names = hostStarsWithSufficientData(); - lua_newtable(L); int number = 1; for (const std::string& s : names) { - lua_pushstring(L, s.c_str()); + ghoul::lua::push(L, s); lua_rawseti(L, -2, number); ++number; } - return 1; } @@ -683,16 +672,15 @@ int listAvailableExoplanetSystems(lua_State* L) { std::string output; for (auto it = names.begin(); it != names.end(); ++it) { - if (it != names.end()) { - output += *it + ", "; - } + output += *it + ", "; } + output.pop_back(); + output.pop_back(); LINFO(fmt::format( "There is data available for the following {} exoplanet systems: {}", names.size(), output )); - return 0; } diff --git a/modules/globebrowsing/globebrowsingmodule_lua.inl b/modules/globebrowsing/globebrowsingmodule_lua.inl index 053ce7d6a3..eb7ab0f871 100644 --- a/modules/globebrowsing/globebrowsingmodule_lua.inl +++ b/modules/globebrowsing/globebrowsingmodule_lua.inl @@ -47,10 +47,8 @@ int addLayer(lua_State* L) { ZoneScoped ghoul::lua::checkArgumentsAndThrow(L, 3, "lua::addLayer"); - - // String arguments - const std::string& globeName = ghoul::lua::value(L, 1); - const std::string& layerGroupName = ghoul::lua::value(L, 2); + auto [globeName, layerGroupName, layerDict] = + ghoul::lua::values(L); // Get the node and make sure it exists SceneGraphNode* n = global::renderEngine->scene()->sceneGraphNode(globeName); @@ -73,23 +71,10 @@ int addLayer(lua_State* L) { } // Get the dictionary defining the layer - ghoul::Dictionary d; - try { - ghoul::lua::luaDictionaryFromState(L, d); - } - catch (const ghoul::lua::LuaFormatException& e) { - LERRORC("addLayerFromDictionary", e.what()); - lua_settop(L, 0); - return 0; - } - lua_settop(L, 0); - - Layer* layer = globe->layerManager().addLayer(groupID, d); + Layer* layer = globe->layerManager().addLayer(groupID, layerDict); if (layer) { layer->initialize(); } - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } @@ -98,11 +83,8 @@ int addLayer(lua_State* L) { */ int deleteLayer(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 3, "lua::deleteLayer"); - - const std::string& globeName = luaL_checkstring(L, 1); - const std::string& layerGroupName = luaL_checkstring(L, 2); - const std::string& layerName = luaL_checkstring(L, 3); - lua_pop(L, 3); + auto [globeName, layerGroupName, layerName] = + ghoul::lua::values(L); // Get the node and make sure it exists SceneGraphNode* n = global::renderEngine->scene()->sceneGraphNode(globeName); @@ -125,17 +107,12 @@ int deleteLayer(lua_State* L) { } globe->layerManager().deleteLayer(groupID, layerName); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int getLayers(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::getLayers"); - - const std::string& globeIdentifier = ghoul::lua::value(L, 1); - const std::string& layer = ghoul::lua::value(L, 2); - lua_pop(L, 2); + auto [globeIdentifier, layer] = ghoul::lua::values(L); SceneGraphNode* n = sceneGraphNode(globeIdentifier); if (!n) { @@ -168,12 +145,8 @@ int getLayers(lua_State* L) { int moveLayer(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 4, "lua::moveLayer"); - - const std::string& globeIdentifier = ghoul::lua::value(L, 1); - const std::string& layer = ghoul::lua::value(L, 2); - int oldPosition = ghoul::lua::value(L, 3); - int newPosition = ghoul::lua::value(L, 4); - lua_pop(L, 4); + auto [globeIdentifier, layer, oldPosition, newPosition] = + ghoul::lua::values(L); if (oldPosition == newPosition) { return 0; @@ -197,22 +170,16 @@ int moveLayer(lua_State* L) { globebrowsing::LayerGroup& lg = globe->layerManager().layerGroup(group); lg.moveLayers(oldPosition, newPosition); - return 0; } int goToChunk(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 4, "lua::goToChunk"); + auto [identifier, x, y, level] = ghoul::lua::values(L); - const std::string& globeIdentifier = ghoul::lua::value(L, 1); - const int x = ghoul::lua::value(L, 2); - const int y = ghoul::lua::value(L, 3); - const int level = ghoul::lua::value(L, 4); - lua_pop(L, 4); - - SceneGraphNode* n = sceneGraphNode(globeIdentifier); + SceneGraphNode* n = sceneGraphNode(identifier); if (!n) { - return ghoul::lua::luaError(L, "Unknown globe name: " + globeIdentifier); + return ghoul::lua::luaError(L, "Unknown globe name: " + identifier); } const RenderableGlobe* globe = dynamic_cast(n->renderable()); @@ -221,22 +188,18 @@ int goToChunk(lua_State* L) { } global::moduleEngine->module()->goToChunk(*globe, x, y, level); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int goToGeo(lua_State* L) { - int nArguments = ghoul::lua::checkArgumentsAndThrow(L, { 2, 4 }, "lua::goToGeo"); + ghoul::lua::checkArgumentsAndThrow(L, { 2, 4 }, "lua::goToGeo"); // Check if the user provided a Scene graph node identifier as the first argument. // lua_isstring returns true for both numbers and strings, so better use !lua_isnumber const bool providedGlobeIdentifier = !lua_isnumber(L, 1); - const int parameterOffset = providedGlobeIdentifier ? 1 : 0; - const SceneGraphNode* n; if (providedGlobeIdentifier) { - const std::string& globeIdentifier = ghoul::lua::value(L, 1); + const std::string& globeIdentifier = ghoul::lua::value(L); n = sceneGraphNode(globeIdentifier); if (!n) { return ghoul::lua::luaError(L, "Unknown globe name: " + globeIdentifier); @@ -249,8 +212,8 @@ int goToGeo(lua_State* L) { } } - const double latitude = ghoul::lua::value(L, parameterOffset + 1); - const double longitude = ghoul::lua::value(L, parameterOffset + 2); + auto [latitude, longitude, altitude] = + ghoul::lua::values>(L); const RenderableGlobe* globe = dynamic_cast(n->renderable()); if (!globe) { @@ -258,32 +221,29 @@ int goToGeo(lua_State* L) { return ghoul::lua::luaError(L, "Identifier must be a RenderableGlobe"); } else { - return ghoul::lua::luaError(L, - "Current anchor node is not a RenderableGlobe. " - "Either change the anchor to a globe, or specify a globe identifier " - "as the first argument" + return ghoul::lua::luaError( + L, + "Current anchor node is not a RenderableGlobe. Either change the anchor " + "to a globe, or specify a globe identifier as the first argument" ); } } - if (nArguments == parameterOffset + 2) { - global::moduleEngine->module()->goToGeo( - *globe, latitude, longitude - ); - } - else if (nArguments == parameterOffset + 3) { - const double altitude = ghoul::lua::value(L, parameterOffset + 3); + if (altitude.has_value()) { global::moduleEngine->module()->goToGeo( *globe, latitude, longitude, - altitude + *altitude + ); + } + else { + global::moduleEngine->module()->goToGeo( + *globe, + latitude, + longitude ); } - - lua_settop(L, 0); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } @@ -394,12 +354,8 @@ int flyToGeo(lua_State* L) { int getLocalPositionFromGeo(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 4, "lua::getLocalPositionFromGeo"); - - const std::string& globeIdentifier = ghoul::lua::value(L, 1); - const double latitude = ghoul::lua::value(L, 2); - const double longitude = ghoul::lua::value(L, 3); - const double altitude = ghoul::lua::value(L, 4); - lua_pop(L, 4); + auto [globeIdentifier, latitude, longitude, altitude] = + ghoul::lua::values(L); SceneGraphNode* n = sceneGraphNode(globeIdentifier); if (!n) { @@ -411,16 +367,8 @@ int getLocalPositionFromGeo(lua_State* L) { } GlobeBrowsingModule& mod = *(global::moduleEngine->module()); - glm::vec3 pos = mod.cartesianCoordinatesFromGeo( - *globe, - latitude, - longitude, - altitude - ); - - ghoul::lua::push(L, pos.x, pos.y, pos.z); - - ghoul_assert(lua_gettop(L) == 3, "Incorrect number of items left on stack"); + glm::vec3 p = mod.cartesianCoordinatesFromGeo(*globe, latitude, longitude, altitude); + ghoul::lua::push(L, p.x, p.y, p.z); return 3; } @@ -450,72 +398,48 @@ int getGeoPositionForCamera(lua_State* L) { posHandle.centerToReferenceSurface); ghoul::lua::push(L, glm::degrees(geo2.lat), glm::degrees(geo2.lon), altitude); - - ghoul_assert(lua_gettop(L) == 3, "Incorrect number of items left on stack"); return 3; } int loadWMSCapabilities(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 3, "lua::loadWMSCapabilities"); - - std::string name = ghoul::lua::value(L, 1); - std::string globe = ghoul::lua::value(L, 2); - std::string url = ghoul::lua::value(L, 3); + auto [name, globe, url] = + ghoul::lua::values(L); global::moduleEngine->module()->loadWMSCapabilities( std::move(name), std::move(globe), std::move(url) ); - - lua_pop(L, 3); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int removeWMSServer(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::removeWMSServer"); - - const std::string& name = ghoul::lua::value( - L, - 1, - ghoul::lua::PopValue::Yes - ); + const std::string name = ghoul::lua::value(L); global::moduleEngine->module()->removeWMSServer(name); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int capabilities(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::capabilities"); + const std::string name = ghoul::lua::value(L); - const std::string& name = ghoul::lua::value( - L, - 1, - ghoul::lua::PopValue::Yes - ); GlobeBrowsingModule::Capabilities cap = global::moduleEngine->module()->capabilities(name); lua_newtable(L); - for (unsigned long i = 0; i < cap.size(); ++i) { + for (size_t i = 0; i < cap.size(); ++i) { const GlobeBrowsingModule::Layer& l = cap[i]; lua_newtable(L); - ghoul::lua::push(L, "Name", l.name); lua_settable(L, -3); - ghoul::lua::push(L, "URL", l.url); lua_settable(L, -3); - lua_rawseti(L, -2, i + 1); } - - ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack"); return 1; } diff --git a/modules/space/spacemodule_lua.inl b/modules/space/spacemodule_lua.inl index 881a191afe..826ca8c53f 100644 --- a/modules/space/spacemodule_lua.inl +++ b/modules/space/spacemodule_lua.inl @@ -30,48 +30,38 @@ int convertFromRaDec(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 3, "lua::convertFromRaDec"); glm::dvec2 degrees = glm::dvec2(0.0); - if (lua_type(L, 1) == LUA_TSTRING && lua_type(L, 2) == LUA_TSTRING) { - std::string ra = ghoul::lua::value(L, 1); - std::string dec = ghoul::lua::value(L, 2); + if (ghoul::lua::hasValue(L, 1) && + ghoul::lua::hasValue(L, 2)) + { + auto [ra, dec] = ghoul::lua::values(L); degrees = icrsToDecimalDegrees(ra, dec); } - else if (lua_type(L, 1) == LUA_TNUMBER && lua_type(L, 2) == LUA_TNUMBER) { - degrees.x = ghoul::lua::value(L, 1); - degrees.y = ghoul::lua::value(L, 2); + else if (ghoul::lua::hasValue(L, 1) && ghoul::lua::hasValue(L, 2)) { + auto [x, y] = ghoul::lua::values(L); + degrees.x = x; + degrees.y = y; } else { - throw ghoul::lua::LuaRuntimeException("lua::convertFromRaDec: Ra and Dec have to " - "be of the same type, either String or Number" + throw ghoul::lua::LuaRuntimeException( + "Ra and Dec have to be of the same type, either String or Number" ); } - double distance = ghoul::lua::value(L, 3); - lua_settop(L, 0); - + double distance = ghoul::lua::value(L); glm::dvec3 pos = icrsToGalacticCartesian(degrees.x, degrees.y, distance); ghoul::lua::push(L, pos); - - ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack"); return 1; } int convertToRaDec(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 3, "lua::convertToRaDec"); + auto [x, y, z] = ghoul::lua::values(L); - double x = ghoul::lua::value(L, 1); - double y = ghoul::lua::value(L, 2); - double z = ghoul::lua::value(L, 3); - lua_settop(L, 0); + glm::dvec3 deg = galacticCartesianToIcrs(x, y, z); + std::pair raDecPair = decimalDegreesToIcrs(deg.x, deg.y); - glm::dvec3 degrees = galacticCartesianToIcrs(x, y, z); - std::pair raDecPair - = decimalDegreesToIcrs(degrees.x, degrees.y); - - ghoul::lua::push(L, raDecPair.first); // Ra - ghoul::lua::push(L, raDecPair.second); // Dec - ghoul::lua::push(L, degrees.z); // Distance - - ghoul_assert(lua_gettop(L) == 3, "Incorrect number of items left on stack"); + // Ra, Dec, Distance + ghoul::lua::push(L, raDecPair.first, raDecPair.second, deg.z); return 3; } diff --git a/modules/statemachine/statemachinemodule_lua.inl b/modules/statemachine/statemachinemodule_lua.inl index 0cacd48dc9..55415af46e 100644 --- a/modules/statemachine/statemachinemodule_lua.inl +++ b/modules/statemachine/statemachinemodule_lua.inl @@ -33,95 +33,37 @@ namespace openspace::luascriptfunctions { int createStateMachine(lua_State* L) { - const int nArguments = ghoul::lua::checkArgumentsAndThrow( - L, - { 2, 3 }, - "lua::createStateMachine" - ); - - // If three arguments, a start state was included - std::optional startState = std::nullopt; - if (nArguments > 2) { - startState = ghoul::lua::value(L, 3, ghoul::lua::PopValue::Yes); - } - - // Last dictionary is on top of the stack - ghoul::Dictionary transitions; - try { - ghoul::lua::luaDictionaryFromState(L, transitions); - } - catch (const ghoul::lua::LuaFormatException& e) { - LERRORC("createStateMachine", e.what()); - return 0; - } - - // Pop, so that first dictionary is on top and can be read - lua_pop(L, 1); - ghoul::Dictionary states; - try { - ghoul::lua::luaDictionaryFromState(L, states); - } - catch (const ghoul::lua::LuaFormatException& e) { - LERRORC("createStateMachine", e.what()); - return 0; - } + ghoul::lua::checkArgumentsAndThrow(L, { 2, 3 }, "lua::createStateMachine"); + auto [states, transitions, startState] = ghoul::lua::values< + ghoul::Dictionary, ghoul::Dictionary, std::optional + >(L); StateMachineModule* module = global::moduleEngine->module(); - - module->initializeStateMachine(states, transitions, startState); - - lua_settop(L, 0); - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); + module->initializeStateMachine( + std::move(states), + std::move(transitions), + std::move(startState) + ); return 0; } int goToState(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::goToState"); - const bool isString = (lua_isstring(L, 1) != 0); + std::string newState = ghoul::lua::value(L); - if (!isString) { - lua_settop(L, 0); - const char* msg = lua_pushfstring( - L, - "%s expected, got %s", - lua_typename(L, LUA_TSTRING), - luaL_typename(L, 0) - ); - return luaL_error(L, "bad argument #%d (%s)", 1, msg); - } - - const std::string newState = lua_tostring(L, 1); StateMachineModule* module = global::moduleEngine->module(); module->transitionTo(newState); LINFOC("StateMachine", "Transitioning to " + newState); - - lua_settop(L, 0); - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int setInitialState(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::setStartState"); - const bool isString = (lua_isstring(L, 1) != 0); + std::string startState = ghoul::lua::value(L); - if (!isString) { - lua_settop(L, 0); - const char* msg = lua_pushfstring( - L, - "%s expected, got %s", - lua_typename(L, LUA_TSTRING), - luaL_typename(L, 0) - ); - return luaL_error(L, "bad argument #%d (%s)", 1, msg); - } - - const std::string startState = lua_tostring(L, 1); StateMachineModule* module = global::moduleEngine->module(); module->setInitialState(startState); LINFOC("StateMachine", "Initial state set to: " + startState); - - lua_settop(L, 0); - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } @@ -130,9 +72,7 @@ int currentState(lua_State* L) { StateMachineModule* module = global::moduleEngine->module(); std::string currentState = module->currentState(); - - lua_pushstring(L, currentState.c_str()); - ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack"); + ghoul::lua::push(L, std::move(currentState)); return 1; } @@ -141,32 +81,16 @@ int possibleTransitions(lua_State* L) { StateMachineModule* module = global::moduleEngine->module(); std::vector transitions = module->possibleTransitions(); - ghoul::lua::push(L, transitions); - ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack"); return 1; } int canGoToState(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::canGoToState"); - const bool isString = (lua_isstring(L, 1) != 0); + std::string state = ghoul::lua::value(L); - if (!isString) { - lua_settop(L, 0); - const char* msg = lua_pushfstring( - L, - "%s expected, got %s", - lua_typename(L, LUA_TSTRING), - luaL_typename(L, 0) - ); - return luaL_error(L, "bad argument #%d (%s)", 1, msg); - } - - const std::string state = lua_tostring(L, 1); StateMachineModule* module = global::moduleEngine->module(); ghoul::lua::push(L, module->canGoToState(state)); - - ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack"); return 1; } @@ -174,7 +98,6 @@ int printCurrentStateInfo(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::printCurrentStateInfo"); StateMachineModule* module = global::moduleEngine->module(); - if (module->hasStateMachine()) { std::string currentState = module->currentState(); std::vector transitions = module->possibleTransitions(); @@ -188,7 +111,6 @@ int printCurrentStateInfo(lua_State* L) { LINFOC("StateMachine", "No state machine has been created"); } - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 1; } diff --git a/src/engine/moduleengine_lua.inl b/src/engine/moduleengine_lua.inl index f999ea1d92..5107f21c06 100644 --- a/src/engine/moduleengine_lua.inl +++ b/src/engine/moduleengine_lua.inl @@ -34,30 +34,15 @@ namespace openspace::luascriptfunctions { */ int isLoaded(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::isLoaded"); - - const int type = lua_type(L, 1); - if (type != LUA_TSTRING) { - return ghoul::lua::luaError(L, "Expected argument of type 'string'"); - } - const std::string& moduleName = ghoul::lua::value( - L, - 1, - ghoul::lua::PopValue::Yes - ); + const std::string name = ghoul::lua::value(L); const std::vector& modules = global::moduleEngine->modules(); - - auto it = std::find_if( - modules.begin(), - modules.end(), - [moduleName](OpenSpaceModule* module) { - return module->identifier() == moduleName; - } + const auto it = std::find_if( + modules.cbegin(), modules.cend(), + [name](OpenSpaceModule* module) { return module->identifier() == name; } ); - ghoul::lua::push(L, it != modules.end()); - - ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack"); + ghoul::lua::push(L, it != modules.cend()); return 1; } diff --git a/src/engine/openspaceengine_lua.inl b/src/engine/openspaceengine_lua.inl index 275300606a..31bdce378d 100644 --- a/src/engine/openspaceengine_lua.inl +++ b/src/engine/openspaceengine_lua.inl @@ -43,25 +43,19 @@ namespace openspace::luascriptfunctions { */ int toggleShutdown(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::toggleShutdown"); - global::openSpaceEngine->toggleShutdownMode(); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } /** -* \ingroup LuaScripts -* writeDocumentation(): -* Writes out documentation files -*/ + * \ingroup LuaScripts + * writeDocumentation(): + * Writes out documentation files + */ int writeDocumentation(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::writeDocumentation"); - global::openSpaceEngine->writeStaticDocumentation(); global::openSpaceEngine->writeSceneDocumentation(); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } @@ -72,15 +66,12 @@ int writeDocumentation(lua_State* L) { */ int addVirtualProperty(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, { 5, 7 }, "lua::addVirtualProperty"); - - const std::string& type = ghoul::lua::value(L, 1); - const std::string& name = ghoul::lua::value(L, 2); - const std::string& identifier = ghoul::lua::value(L, 3); - const std::string& description = ghoul::lua::value(L, 4); + auto [type, name, identifier, description] = + ghoul::lua::values(L); std::unique_ptr prop; if (type == "BoolProperty") { - const bool v = ghoul::lua::value(L, 5); + const bool v = ghoul::lua::value(L); prop = std::make_unique( properties::Property::PropertyInfo { identifier.c_str(), @@ -91,10 +82,7 @@ int addVirtualProperty(lua_State* L) { ); } else if (type == "IntProperty") { - const int v = ghoul::lua::value(L, 5); - const int min = ghoul::lua::value(L, 6); - const int max = ghoul::lua::value(L, 7); - + auto [v, min, max] = ghoul::lua::values(L); prop = std::make_unique( properties::Property::PropertyInfo { identifier.c_str(), @@ -107,10 +95,7 @@ int addVirtualProperty(lua_State* L) { ); } else if (type == "FloatProperty") { - const float v = ghoul::lua::value(L, 5); - const float min = ghoul::lua::value(L, 6); - const float max = ghoul::lua::value(L, 7); - + auto [v, min, max] = ghoul::lua::values(L); prop = std::make_unique( properties::Property::PropertyInfo { identifier.c_str(), @@ -132,26 +117,22 @@ int addVirtualProperty(lua_State* L) { ); } else { - lua_settop(L, 0); return ghoul::lua::luaError(L, fmt::format("Unknown property type '{}'", type)); } - lua_settop(L, 0); global::virtualPropertyManager->addProperty(std::move(prop)); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } /** -* \ingroup LuaScripts -* removeVirtualProperty(): -* Removes a previously added virtual property -*/ + * \ingroup LuaScripts + * removeVirtualProperty(): + * Removes a previously added virtual property + */ int removeVirtualProperty(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::removeVirtualProperty"); + const std::string name = ghoul::lua::value(L); - const std::string& name = ghoul::lua::value(L, 1); properties::Property* p = global::virtualPropertyManager->property(name); if (p) { global::virtualPropertyManager->removeProperty(p); @@ -159,39 +140,30 @@ int removeVirtualProperty(lua_State* L) { else { LWARNINGC( "removeVirtualProperty", - fmt::format("Virtual Property with name '{}'' did not exist", name) + fmt::format("Virtual Property with name '{}' did not exist", name) ); } - - lua_settop(L, 0); - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } /** -* \ingroup LuaScripts -* removeAllVirtualProperties(): -* Remove all registered virtual properties -*/ + * \ingroup LuaScripts + * removeAllVirtualProperties(): + * Remove all registered virtual properties + */ int removeAllVirtualProperties(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::removeAllVirtualProperties"); - const std::vector& ps = - global::virtualPropertyManager->properties(); - for (properties::Property* p : ps) { + for (properties::Property* p : global::virtualPropertyManager->properties()) { global::virtualPropertyManager->removeProperty(p); delete p; } - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int setScreenshotFolder(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::setScreenshotFolder"); - - std::string arg = ghoul::lua::value(L); - lua_pop(L, 0); + const std::string arg = ghoul::lua::value(L); std::filesystem::path folder = absPath(arg); if (!std::filesystem::exists(folder)) { @@ -215,22 +187,14 @@ int setScreenshotFolder(lua_State* L) { */ int addTag(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::addTag"); - - const std::string& uri = ghoul::lua::value(L, 1); - std::string tag = ghoul::lua::value(L, 2); - lua_settop(L, 0); + auto [uri, tag] = ghoul::lua::values(L); SceneGraphNode* node = global::renderEngine->scene()->sceneGraphNode(uri); if (!node) { - return ghoul::lua::luaError( - L, - fmt::format("Unknown scene graph node type '{}'", uri) - ); + return ghoul::lua::luaError(L, fmt::format("Unknown scene graph node '{}'", uri)); } node->addTag(std::move(tag)); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } @@ -240,41 +204,28 @@ int addTag(lua_State* L) { * Removes a tag from a SceneGraphNode */ int removeTag(lua_State* L) { - ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::addTag"); - - const std::string& uri = ghoul::lua::value(L, 1); - const std::string& tag = ghoul::lua::value(L, 2); - lua_settop(L, 0); + ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::removeTag"); + auto [uri, tag] = ghoul::lua::values(L); SceneGraphNode* node = global::renderEngine->scene()->sceneGraphNode(uri); if (!node) { - return ghoul::lua::luaError( - L, - fmt::format("Unknown scene graph node type '{}'", uri) - ); + return ghoul::lua::luaError(L, fmt::format("Unknown scene graph node '{}'", uri)); } node->removeTag(tag); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } /** -* \ingroup LuaScripts -* downloadFile(): -* Downloads a file from Lua interpreter -*/ + * \ingroup LuaScripts + * downloadFile(): + * Downloads a file from Lua interpreter + */ int downloadFile(lua_State* L) { - int n = ghoul::lua::checkArgumentsAndThrow(L, {2, 3}, "lua::addTag"); - - const std::string& uri = ghoul::lua::value(L, 1); - const std::string& savePath = ghoul::lua::value(L, 2); - bool waitForComplete = false; - if (n == 3) { - waitForComplete = ghoul::lua::value(L, 3); - } - lua_settop(L, 0); + ghoul::lua::checkArgumentsAndThrow(L, { 2, 3 }, "lua::downloadFile"); + auto [uri, savePath, waitForComplete] = + ghoul::lua::values>(L); + waitForComplete = waitForComplete.value_or(false); LINFOC("OpenSpaceEngine", fmt::format("Downloading file from {}", uri)); std::shared_ptr future = @@ -300,21 +251,17 @@ int downloadFile(lua_State* L) { ); } - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } /** -* \ingroup LuaScripts -* createSingleColorImage(): -* Creates a one pixel image with a given color and returns the path to the cached file -*/ + * \ingroup LuaScripts + * createSingleColorImage(): + * Creates a one pixel image with a given color and returns the path to the cached file + */ int createSingleColorImage(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::createSingleColorImage"); - - const std::string& name = ghoul::lua::value(L, 1); - const ghoul::Dictionary& d = ghoul::lua::value(L, 2); - lua_settop(L, 0); + auto [name, d] = ghoul::lua::values(L); // @TODO (emmbr 2020-12-18) Verify that the input dictionary is a vec3 // Would like to clean this up with a more direct use of the Verifier in the future diff --git a/src/interaction/actionmanager_lua.inl b/src/interaction/actionmanager_lua.inl index 909d74d2b7..1c677d5226 100644 --- a/src/interaction/actionmanager_lua.inl +++ b/src/interaction/actionmanager_lua.inl @@ -33,8 +33,8 @@ namespace openspace::luascriptfunctions { */ int hasAction(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::hasAction"); + const std::string identifier = ghoul::lua::value(L); - const std::string& identifier = ghoul::lua::value(L, 1); if (identifier.empty()) { return ghoul::lua::luaError(L, "Identifier must not be empty"); } @@ -51,8 +51,8 @@ int hasAction(lua_State* L) { */ int removeAction(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::removeAction"); + const std::string identifier = ghoul::lua::value(L); - const std::string& identifier = ghoul::lua::value(L, 1); if (identifier.empty()) { return ghoul::lua::luaError(L, "Identifier must not be empty"); } @@ -63,7 +63,6 @@ int removeAction(lua_State* L) { ); } - global::actionManager->removeAction(identifier); return 0; } @@ -81,8 +80,7 @@ int removeAction(lua_State* L) { */ int registerAction(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::registerAction"); - - ghoul::Dictionary d = ghoul::lua::value(L, 1); + const ghoul::Dictionary d = ghoul::lua::value(L); if (!d.hasValue("Identifier")) { return ghoul::lua::luaError(L, "Identifier must to provided to register action"); @@ -138,8 +136,8 @@ int registerAction(lua_State* L) { */ int action(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::action"); + const std::string identifier = ghoul::lua::value(L); - const std::string& identifier = ghoul::lua::value(L, 1); if (identifier.empty()) { return ghoul::lua::luaError(L, "Identifier must not be empty"); } @@ -168,7 +166,6 @@ int action(lua_State* L) { action.synchronization == interaction::Action::IsSynchronized::Yes ); lua_settable(L, -3); - return 1; } @@ -216,25 +213,18 @@ int actions(lua_State* L) { * Triggers the action given by the specified identifier. */ int triggerAction(lua_State* L) { - int n = ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::triggerAction"); + ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::triggerAction"); + auto [id, arg] = ghoul::lua::values>(L); + arg = arg.value_or(ghoul::Dictionary()); - const std::string& identifier = ghoul::lua::value(L, 1); - if (identifier.empty()) { + if (id.empty()) { return ghoul::lua::luaError(L, "Identifier must not be empty"); } - if (!global::actionManager->hasAction(identifier)) { - return ghoul::lua::luaError( - L, - fmt::format("Identifier '{}' for action not found", identifier) - ); + if (!global::actionManager->hasAction(id)) { + return ghoul::lua::luaError(L, fmt::format("Action '{}' not found", id)); } - ghoul::Dictionary arguments; - if (n == 2) { - ghoul::lua::luaDictionaryFromState(L, arguments, 2); - } - - global::actionManager->triggerAction(identifier, arguments); + global::actionManager->triggerAction(id, *arg); return 0; } diff --git a/src/interaction/keybindingmanager_lua.inl b/src/interaction/keybindingmanager_lua.inl index db8fb38258..f55650997b 100644 --- a/src/interaction/keybindingmanager_lua.inl +++ b/src/interaction/keybindingmanager_lua.inl @@ -34,35 +34,24 @@ namespace openspace::luascriptfunctions { * node is hosting a parallel connection. */ int bindKey(lua_State* L) { - using ghoul::lua::luaTypeToString; - ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::bindKey"); - - std::string key = ghoul::lua::value(L, 1); - std::string action = ghoul::lua::value(L, 2); + auto [key, action] = ghoul::lua::values(L); if (action.empty()) { - lua_settop(L, 0); return ghoul::lua::luaError(L, "Action must not be empty"); } if (!global::actionManager->hasAction(action)) { - lua_settop(L, 0); return ghoul::lua::luaError(L, fmt::format("Action '{}' does not exist", action)); } openspace::KeyWithModifier iKey = openspace::stringToKey(key); - if (iKey.key == openspace::Key::Unknown) { std::string error = fmt::format("Could not find key '{}'", key); LERRORC("lua.bindKey", error); - lua_settop(L, 0); return ghoul::lua::luaError(L, error); } global::keybindingManager->bindKey(iKey.key, iKey.modifier, std::move(action)); - - lua_settop(L, 0); - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } @@ -74,16 +63,10 @@ int bindKey(lua_State* L) { */ int getKeyBindings(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::getKeyBindings"); - - const std::string& key = ghoul::lua::value( - L, - 1, - ghoul::lua::PopValue::Yes - ); + const std::string& key = ghoul::lua::value(L); using K = KeyWithModifier; using V = std::string; - const std::vector>& info = global::keybindingManager->keyBinding( stringToKey(key) ); @@ -97,7 +80,6 @@ int getKeyBindings(lua_State* L) { ++i; } - ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack"); return 1; } @@ -109,25 +91,18 @@ int getKeyBindings(lua_State* L) { int clearKey(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::clearKey"); - const int t = lua_type(L, 1); - if (t == LUA_TSTRING) { - // The user provided a single key - const std::string& key = ghoul::lua::value(L, 1); - global::keybindingManager->removeKeyBinding(stringToKey(key)); + std::variant key = ghoul::lua::value>(L); + if (std::holds_alternative(key)) { + KeyWithModifier k = stringToKey(std::get(key)); + global::keybindingManager->removeKeyBinding(k); } else { - // The user provided a list of keys - ghoul::Dictionary d; - ghoul::lua::luaDictionaryFromState(L, d); + ghoul::Dictionary d = std::get(key); for (size_t i = 1; i <= d.size(); ++i) { const std::string& k = d.value(std::to_string(i)); global::keybindingManager->removeKeyBinding(stringToKey(k)); } - lua_pop(L, 1); } - - lua_settop(L, 0); - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } @@ -138,10 +113,7 @@ int clearKey(lua_State* L) { */ int clearKeys(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::clearKeys"); - global::keybindingManager->resetKeyBindings(); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } diff --git a/src/interaction/sessionrecording_lua.inl b/src/interaction/sessionrecording_lua.inl index 520f074dd5..f4004d2796 100644 --- a/src/interaction/sessionrecording_lua.inl +++ b/src/interaction/sessionrecording_lua.inl @@ -24,17 +24,9 @@ namespace openspace::luascriptfunctions { - int startRecording(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::startRecording"); - - using ghoul::lua::luaTypeToString; - - const std::string recordFilePath = ghoul::lua::value( - L, - 1, - ghoul::lua::PopValue::Yes - ); + const std::string recordFilePath = ghoul::lua::value(L); if (recordFilePath.empty()) { return luaL_error(L, "filepath string is empty"); @@ -43,21 +35,12 @@ int startRecording(lua_State* L) { interaction::SessionRecording::DataMode::Binary ); global::sessionRecording->startRecording(recordFilePath); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int startRecordingAscii(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::startRecordingAscii"); - - using ghoul::lua::luaTypeToString; - - const std::string recordFilePath = ghoul::lua::value( - L, - 1, - ghoul::lua::PopValue::Yes - ); + const std::string recordFilePath = ghoul::lua::value(L); if (recordFilePath.empty()) { return luaL_error(L, "filepath string is empty"); @@ -66,196 +49,109 @@ int startRecordingAscii(lua_State* L) { interaction::SessionRecording::DataMode::Ascii ); global::sessionRecording->startRecording(recordFilePath); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int stopRecording(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::stopRecording"); - global::sessionRecording->stopRecording(); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int startPlayback(lua_State* L, interaction::KeyframeTimeRef timeMode, bool forceSimTimeAtStart) { - using ghoul::lua::luaTypeToString; - const int nArguments = lua_gettop(L); - bool loop = false; + ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::startPlayback"); + auto [file, loop] = ghoul::lua::values>(L); + loop = loop.value_or(false); - if (nArguments == 2) { - loop = lua_toboolean(L, 2) == 1; + if (file.empty()) { + return ghoul::lua::luaError(L, "Filepath string is empty"); } - else if (nArguments != 1) { - lua_settop(L, 0); - return luaL_error( - L, - "bad number of arguments, expected 1 or 2, got %i", - nArguments - ); - } - - const std::string playbackFilePath = ghoul::lua::value( - L, - 1, - ghoul::lua::PopValue::Yes - ); - - if (playbackFilePath.empty()) { - return luaL_error(L, "filepath string is empty"); - } - - global::sessionRecording->startPlayback( - const_cast(playbackFilePath), - timeMode, - forceSimTimeAtStart, - loop - ); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); + global::sessionRecording->startPlayback(file, timeMode, forceSimTimeAtStart, *loop); return 0; } int startPlaybackDefault(lua_State* L) { - using interaction::KeyframeNavigator; - ghoul::lua::checkArgumentsAndThrow(L, {1, 2}, "lua::startPlaybackDefault"); - return startPlayback(L, - interaction::KeyframeTimeRef::Relative_recordedStart, true); + ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::startPlaybackDefault"); + return startPlayback(L, interaction::KeyframeTimeRef::Relative_recordedStart, true); } int startPlaybackApplicationTime(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::startPlaybackApplicationTime"); - return startPlayback(L, - interaction::KeyframeTimeRef::Relative_applicationStart, false); + return startPlayback( + L, + interaction::KeyframeTimeRef::Relative_applicationStart, + false + ); } int startPlaybackRecordedTime(lua_State* L) { using interaction::KeyframeNavigator; - ghoul::lua::checkArgumentsAndThrow(L, {1, 2}, "lua::startPlaybackRecordedTime"); - return startPlayback(L, - interaction::KeyframeTimeRef::Relative_recordedStart, false); + ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::startPlaybackRecordedTime"); + return startPlayback(L, interaction::KeyframeTimeRef::Relative_recordedStart, false); } int startPlaybackSimulationTime(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::startPlaybackSimulationTime"); - using interaction::KeyframeNavigator; - return startPlayback(L, - interaction::KeyframeTimeRef::Absolute_simTimeJ2000, false); + return startPlayback(L, interaction::KeyframeTimeRef::Absolute_simTimeJ2000, false); } int stopPlayback(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::stopPlayback"); - global::sessionRecording->stopPlayback(); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int enableTakeScreenShotDuringPlayback(lua_State* L) { - const int nArguments = ghoul::lua::checkArgumentsAndThrow( + ghoul::lua::checkArgumentsAndThrow( L, { 0, 1 }, "lua::enableTakeScreenShotDuringPlayback" ); + std::optional fps = ghoul::lua::value>(L); + fps = fps.value_or(60); - const int fps = nArguments == 0 ? 60 : ghoul::lua::value(L, 1); - - global::sessionRecording->enableTakeScreenShotDuringPlayback(fps); - - lua_settop(L, 0); - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); + global::sessionRecording->enableTakeScreenShotDuringPlayback(*fps); return 0; } int disableTakeScreenShotDuringPlayback(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::disableTakeScreenShotDuringPlayback"); - global::sessionRecording->disableTakeScreenShotDuringPlayback(); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int fileFormatConversion(lua_State* L) { - using ghoul::lua::luaTypeToString; - - const std::string convertFilePath = ghoul::lua::value( - L, - 1, - ghoul::lua::PopValue::Yes - ); + ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::fileFormatConversion"); + const std::string convertFilePath = ghoul::lua::value(L); if (convertFilePath.empty()) { - return luaL_error(L, "filepath string is empty"); + return luaL_error(L, "Filepath string must not be empty"); } global::sessionRecording->convertFile(convertFilePath); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int setPlaybackPause(lua_State* L) { - const int nArguments = lua_gettop(L); + ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::setPlaybackPause"); + const bool pause = ghoul::lua::value(L); - if (nArguments == 1) { - const bool pause = lua_toboolean(L, 1) == 1; - global::sessionRecording->setPlaybackPause(pause); - } - else { - lua_settop(L, 0); - return luaL_error( - L, - "bad number of arguments, expected 1, got %i", - nArguments - ); - } - - lua_settop(L, 0); - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); + global::sessionRecording->setPlaybackPause(pause); return 0; } int togglePlaybackPause(lua_State* L) { - const int nArguments = lua_gettop(L); - - if (nArguments == 0) { - bool isPlaybackPaused = global::sessionRecording->isPlaybackPaused(); - global::sessionRecording->setPlaybackPause(!isPlaybackPaused); - } - else { - lua_settop(L, 0); - return luaL_error( - L, - "bad number of arguments, expected 0, got %i", - nArguments - ); - } - - lua_settop(L, 0); - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); + ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::togglePlaybackPause"); + bool isPlaybackPaused = global::sessionRecording->isPlaybackPaused(); + global::sessionRecording->setPlaybackPause(!isPlaybackPaused); return 0; } int isPlayingBack(lua_State* L) { - const int nArguments = lua_gettop(L); - - if (nArguments != 0) { - lua_settop(L, 0); - return luaL_error( - L, - "bad number of arguments, expected 0, got %i", - nArguments - ); - } - + ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::isPlayingBack"); ghoul::lua::push(L, global::sessionRecording->isPlayingBack()); - ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack"); return 1; } diff --git a/src/mission/missionmanager_lua.inl b/src/mission/missionmanager_lua.inl index 029737fd09..910690a0b2 100644 --- a/src/mission/missionmanager_lua.inl +++ b/src/mission/missionmanager_lua.inl @@ -28,33 +28,21 @@ namespace openspace::luascriptfunctions { int loadMission(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::loadMission"); + const std::string& missionFileName = ghoul::lua::value(L); - const std::string& missionFileName = ghoul::lua::value( - L, - 1, - ghoul::lua::PopValue::Yes - ); if (missionFileName.empty()) { return ghoul::lua::luaError(L, "Filepath is empty"); } - std::string name = global::missionManager->loadMission( - absPath(missionFileName).string() - ); + const std::string name = global::missionManager->loadMission(missionFileName); ghoul::lua::push(L, name); - - ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack"); return 1; } int unloadMission(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::unloadMission"); + const std::string missionName = ghoul::lua::value(L); - const std::string& missionName = ghoul::lua::value( - L, - 1, - ghoul::lua::PopValue::Yes - ); if (missionName.empty()) { return ghoul::lua::luaError(L, "Mission name is empty"); } @@ -64,46 +52,30 @@ int unloadMission(lua_State* L) { } global::missionManager->unloadMission(missionName); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int hasMission(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::hasMission"); + const std::string missionName = ghoul::lua::value(L); - const std::string& missionName = ghoul::lua::value( - L, - 1, - ghoul::lua::PopValue::Yes - ); if (missionName.empty()) { return ghoul::lua::luaError(L, "Missing name is empty"); } const bool hasMission = global::missionManager->hasMission(missionName); - ghoul::lua::push(L, hasMission); - - ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack"); return 1; } int setCurrentMission(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::setCurrentMission"); + const std::string missionName = ghoul::lua::value(L); - const std::string& missionName = ghoul::lua::value( - L, - 1, - ghoul::lua::PopValue::Yes - ); if (missionName.empty()) { return ghoul::lua::luaError(L, "Mission name is empty"); } - global::missionManager->setCurrentMission(missionName); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } diff --git a/src/navigation/navigationhandler_lua.inl b/src/navigation/navigationhandler_lua.inl index c0fd722b09..c3c9b1e4a4 100644 --- a/src/navigation/navigationhandler_lua.inl +++ b/src/navigation/navigationhandler_lua.inl @@ -30,41 +30,28 @@ namespace openspace::luascriptfunctions { int loadNavigationState(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::loadNavigationState"); - - const std::string& cameraStateFilePath = ghoul::lua::value( - L, - 1, - ghoul::lua::PopValue::Yes - ); + const std::string cameraStateFilePath = ghoul::lua::value(L); if (cameraStateFilePath.empty()) { return ghoul::lua::luaError(L, "filepath string is empty"); } global::navigationHandler->loadNavigationState(cameraStateFilePath); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int getNavigationState(lua_State* L) { - const int n = ghoul::lua::checkArgumentsAndThrow( - L, - { 0, 1 }, - "lua::getNavigationState" - ); + ghoul::lua::checkArgumentsAndThrow(L, { 0, 1 }, "lua::getNavigationState"); + std::optional frame = ghoul::lua::value>(L); interaction::NavigationState state; - if (n == 1) { - const std::string referenceFrameIdentifier = ghoul::lua::value(L, 1); - const SceneGraphNode* referenceFrame = sceneGraphNode(referenceFrameIdentifier); + if (frame.has_value()) { + const SceneGraphNode* referenceFrame = sceneGraphNode(*frame); if (!referenceFrame) { - LERROR(fmt::format( - "Could not find node '{}' to use as reference frame", - referenceFrameIdentifier - )); - lua_settop(L, 0); - return 0; + return ghoul::lua::luaError( + L, + fmt::format("Could not find node '{}' as reference frame", *frame) + ); } state = global::navigationHandler->navigationState(*referenceFrame); } @@ -72,7 +59,6 @@ int getNavigationState(lua_State* L) { state = global::navigationHandler->navigationState(); } - lua_settop(L, 0); const auto pushVector = [](lua_State* s, const glm::dvec3& v) { lua_newtable(s); @@ -114,15 +100,12 @@ int getNavigationState(lua_State* L) { lua_rawset(L, -3); } - ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack"); return 1; } int setNavigationState(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::setNavigationState"); - - ghoul::Dictionary navigationStateDictionary; - ghoul::lua::luaDictionaryFromState(L, navigationStateDictionary); + ghoul::Dictionary navigationStateDictionary = ghoul::lua::value(L); openspace::documentation::TestResult r = openspace::documentation::testSpecification( interaction::NavigationState::Documentation(), @@ -130,278 +113,196 @@ int setNavigationState(lua_State* L) { ); if (!r.success) { - lua_settop(L, 0); return ghoul::lua::luaError( - L, fmt::format("Could not set camera state: {}", ghoul::to_string(r)) + L, + fmt::format("Could not set camera state: {}", ghoul::to_string(r)) ); } global::navigationHandler->setNavigationStateNextFrame( interaction::NavigationState(navigationStateDictionary) ); - - // @CLEANUP: When luaDictionaryFromState doesn't leak space anymore, remove the next - // line ---abock(2018-02-15) - lua_settop(L, 0); - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int saveNavigationState(lua_State* L) { - const int n = ghoul::lua::checkArgumentsAndThrow( - L, - { 1, 2 }, - "lua::saveNavigationState" - ); + ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::saveNavigationState"); + auto [path, frame] = ghoul::lua::values>(L); + frame = frame.value_or(""); - const std::string& cameraStateFilePath = ghoul::lua::value(L, 1); - - std::string referenceFrame = ""; - if (n > 1) { - referenceFrame = ghoul::lua::value(L, 2); + if (path.empty()) { + return ghoul::lua::luaError(L, "Filepath string is empty"); } - if (cameraStateFilePath.empty()) { - return ghoul::lua::luaError(L, "filepath string is empty"); - } - - global::navigationHandler->saveNavigationState(cameraStateFilePath, referenceFrame); - - lua_settop(L, 0); - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); + global::navigationHandler->saveNavigationState(path, *frame); return 0; } int retargetAnchor(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::retargetAnchor"); - global::navigationHandler->orbitalNavigator().startRetargetAnchor(); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int retargetAim(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::retargetAim"); - global::navigationHandler->orbitalNavigator().startRetargetAim(); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int bindJoystickAxis(lua_State* L) { - const int n = ghoul::lua::checkArgumentsAndThrow( - L, - { 2, 6 }, - "lua::bindJoystickAxis" - ); - - const int axis = ghoul::lua::value(L, 1); - const std::string& axisType = ghoul::lua::value(L, 2); - - const bool shouldInvert = n > 2 ? ghoul::lua::value(L, 3) : false; - const bool shouldNormalize = n > 3 ? ghoul::lua::value(L, 4) : false; - const bool isSticky = n > 4 ? ghoul::lua::value(L, 5) : false; - const double sensitivity = n > 5 ? ghoul::lua::value(L, 6) : 0.0; + ghoul::lua::checkArgumentsAndThrow(L, { 2, 6 }, "lua::bindJoystickAxis"); + auto [axis, axisType, shouldInvert, shouldNormalize, isSticky, sensitivity] = + ghoul::lua::values< + int, std::string, std::optional, std::optional, + std::optional, std::optional + >(L); + shouldInvert = shouldInvert.value_or(false); + shouldNormalize = shouldNormalize.value_or(false); + isSticky = isSticky.value_or(false); + sensitivity = sensitivity.value_or(0.0); global::navigationHandler->setJoystickAxisMapping( axis, ghoul::from_string(axisType), - interaction::JoystickCameraStates::AxisInvert(shouldInvert), - interaction::JoystickCameraStates::AxisNormalize(shouldNormalize), - isSticky, - sensitivity + interaction::JoystickCameraStates::AxisInvert(*shouldInvert), + interaction::JoystickCameraStates::AxisNormalize(*shouldNormalize), + *isSticky, + *sensitivity ); - - lua_settop(L, 0); - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int joystickAxis(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::joystickAxis"); - - const int axis = ghoul::lua::value(L, 1); + const int axis = ghoul::lua::value(L); using AI = interaction::JoystickCameraStates::AxisInformation; AI info = global::navigationHandler->joystickAxisMapping(axis); - lua_settop(L, 0); - const bool invert = info.invert; - const bool normalize = info.normalize; - const bool isSticky = info.isSticky; - const double sensitivity = info.sensitivity; ghoul::lua::push( L, ghoul::to_string(info.type), - invert, - normalize, - isSticky, - sensitivity + static_cast(info.invert), + static_cast(info.normalize), + info.isSticky, + info.sensitivity ); - - ghoul_assert(lua_gettop(L) == 5, "Incorrect number of items left on stack"); return 5; } int setJoystickAxisDeadzone(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::setJoystickAxisDeadzone"); - - const int axis = ghoul::lua::value(L, 1); - const float deadzone = ghoul::lua::value(L, 2); - lua_settop(L, 0); + auto [axis, deadzone] = ghoul::lua::values(L); global::navigationHandler->setJoystickAxisDeadzone(axis, deadzone); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int joystickAxisDeadzone(lua_State* L) { - ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::setJoystickAxisDeadzone"); - - const int axis = ghoul::lua::value(L, 1, ghoul::lua::PopValue::Yes); + ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::joystickAxisDeadzone"); + const int axis = ghoul::lua::value(L); const float deadzone = global::navigationHandler->joystickAxisDeadzone(axis); - ghoul::lua::push(L, deadzone); - ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack"); return 1; } int bindJoystickButton(lua_State* L) { - const int n = ghoul::lua::checkArgumentsAndThrow( - L, - { 3, 5 }, - "lua::bindJoystickButton" - ); + ghoul::lua::checkArgumentsAndThrow(L, { 3, 5 }, "lua::bindJoystickButton"); + auto [button, command, documentation, actionStr, isRemote] = + ghoul::lua::values< + int, std::string, std::string, std::optional, std::optional + >(L); + actionStr = actionStr.value_or("Press"); + isRemote = isRemote.value_or(true); - const int button = ghoul::lua::value(L, 1); - std::string command = ghoul::lua::value(L, 2); - std::string documentation = ghoul::lua::value(L, 3); - - interaction::JoystickAction action = interaction::JoystickAction::Press; - if (n >= 4) { - const std::string& actionStr = ghoul::lua::value(L, 4); - action = ghoul::from_string(actionStr); - } - - const bool isRemote = n == 5 ? ghoul::lua::value(L, 5) : true; - lua_settop(L, 0); + interaction::JoystickAction action = + ghoul::from_string(*actionStr); global::navigationHandler->bindJoystickButtonCommand( button, command, action, - interaction::JoystickCameraStates::ButtonCommandRemote(isRemote), + interaction::JoystickCameraStates::ButtonCommandRemote(*isRemote), documentation ); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int clearJoystickButton(lua_State* L) { - ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::bindJoystickButton"); - - const int button = ghoul::lua::value(L, 1, ghoul::lua::PopValue::Yes); - + ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::clearJoystickButton"); + const int button = ghoul::lua::value(L); global::navigationHandler->clearJoystickButtonCommand(button); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int joystickButton(lua_State* L) { - ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::bindJoystickButton"); - - const int button = ghoul::lua::value(L, 1, ghoul::lua::PopValue::Yes); + ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::joystickButton"); + const int button = ghoul::lua::value(L); const std::vector& cmds = global::navigationHandler->joystickButtonCommand(button); std::string cmd = std::accumulate( - cmds.begin(), - cmds.end(), + cmds.cbegin(), + cmds.cend(), std::string(), [](const std::string& lhs, const std::string& rhs) { return lhs + ";" + rhs; } ); - ghoul::lua::push(L, cmd); - ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack"); return 1; } int addGlobalRotation(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::addGlobalRotation"); - - const double v1 = ghoul::lua::value(L, 1, ghoul::lua::PopValue::No); - const double v2 = ghoul::lua::value(L, 2, ghoul::lua::PopValue::No); + auto [v1, v2] = ghoul::lua::values(L); global::navigationHandler->orbitalNavigator().scriptStates().addGlobalRotation( glm::dvec2(v1, v2) ); - - lua_settop(L, 0); return 0; } int addLocalRotation(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::addLocalRotation"); - - const double v1 = ghoul::lua::value(L, 1, ghoul::lua::PopValue::No); - const double v2 = ghoul::lua::value(L, 2, ghoul::lua::PopValue::No); + auto [v1, v2] = ghoul::lua::values(L); global::navigationHandler->orbitalNavigator().scriptStates().addLocalRotation( glm::dvec2(v1, v2) ); - - lua_settop(L, 0); return 0; } int addTruckMovement(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::addTruckMovement"); - - const double v1 = ghoul::lua::value(L, 1, ghoul::lua::PopValue::No); - const double v2 = ghoul::lua::value(L, 2, ghoul::lua::PopValue::No); + auto [v1, v2] = ghoul::lua::values(L); global::navigationHandler->orbitalNavigator().scriptStates().addTruckMovement( glm::dvec2(v1, v2) ); - - lua_settop(L, 0); return 0; } int addLocalRoll(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::addLocalRoll"); - - const double v1 = ghoul::lua::value(L, 1, ghoul::lua::PopValue::No); - const double v2 = ghoul::lua::value(L, 2, ghoul::lua::PopValue::No); + auto [v1, v2] = ghoul::lua::values(L); global::navigationHandler->orbitalNavigator().scriptStates().addLocalRoll( glm::dvec2(v1, v2) ); - - lua_settop(L, 0); return 0; } int addGlobalRoll(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::addGlobalRoll"); - - const double v1 = ghoul::lua::value(L, 1, ghoul::lua::PopValue::No); - const double v2 = ghoul::lua::value(L, 2, ghoul::lua::PopValue::No); + auto [v1, v2] = ghoul::lua::values(L); global::navigationHandler->orbitalNavigator().scriptStates().addGlobalRoll( glm::dvec2(v1, v2) ); - - lua_settop(L, 0); return 0; } diff --git a/src/navigation/pathnavigator_lua.inl b/src/navigation/pathnavigator_lua.inl index 8766fbacd6..4fc9978e03 100644 --- a/src/navigation/pathnavigator_lua.inl +++ b/src/navigation/pathnavigator_lua.inl @@ -44,44 +44,29 @@ namespace openspace::luascriptfunctions { int isFlying(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::isFlying"); - bool hasFinished = global::navigationHandler->pathNavigator().hasFinished(); - ghoul::lua::push(L, !hasFinished); - ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack"); return 1; } int continuePath(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::continuePath"); - global::navigationHandler->pathNavigator().continuePath(); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int pausePath(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::pausePath"); - global::navigationHandler->pathNavigator().pausePath(); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int stopPath(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::stopPath"); - global::navigationHandler->pathNavigator().abortPath(); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } -// All the goTo function has the same two optional input parameters at the end. The -// purpose of this function is to handle these input parameters and add the result -// to the dictionary specifying the instruction for a camera path. int handleOptionalGoToParameters(lua_State* L, const int startLocation, const int nArguments, ghoul::Dictionary& resultInstruction) @@ -127,11 +112,19 @@ int handleOptionalGoToParameters(lua_State* L, const int startLocation, int goTo(lua_State* L) { int nArguments = ghoul::lua::checkArgumentsAndThrow(L, { 1, 3 }, "lua::goTo"); + auto [nodeIdentifier, useUpFromTargetOrDuration, duration] = ghoul::lua::values< + std::string, std::optional>, std::optional + >(L); + + if (useUpFromTargetOrDuration.has_value() && + std::holds_alternative(*useUpFromTargetOrDuration) + && duration.has_value()) + { + return ghoul::lua::luaError(L, "Duration cannot be specified twice"); + } - const std::string& nodeIdentifier = ghoul::lua::value(L, 1); if (!sceneGraphNode(nodeIdentifier)) { - lua_settop(L, 0); return ghoul::lua::luaError(L, "Unknown node name: " + nodeIdentifier); } @@ -139,12 +132,27 @@ int goTo(lua_State* L) { ghoul::Dictionary insDict; insDict.setValue("TargetType", "Node"s); insDict.setValue("Target", nodeIdentifier); - - if (nArguments > 1) { - int result = handleOptionalGoToParameters(L, 2, nArguments, insDict); - if (result != 0) { - return result; // An error occurred + if (useUpFromTargetOrDuration.has_value()) { + if (std::holds_alternative(*useUpFromTargetOrDuration)) { + insDict.setValue( + "UseTargetUpDirection", + std::get(*useUpFromTargetOrDuration) + ); } + else { + double d = std::get(*useUpFromTargetOrDuration); + if (d <= Epsilon) { + return ghoul::lua::luaError(L, "Duration must be larger than zero"); + } + insDict.setValue("Duration", d); + } + } + if (duration.has_value()) { + double d = *duration; + if (d <= Epsilon) { + return ghoul::lua::luaError(L, "Duration must be larger than zero"); + } + insDict.setValue("Duration", d); } global::navigationHandler->pathNavigator().createPath(insDict); @@ -152,35 +160,48 @@ int goTo(lua_State* L) { if (global::navigationHandler->pathNavigator().hasCurrentPath()) { global::navigationHandler->pathNavigator().startPath(); } - - lua_settop(L, 0); - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int goToHeight(lua_State* L) { int nArguments = ghoul::lua::checkArgumentsAndThrow(L, { 2, 4 }, "lua::goToHeight"); + auto [nodeIdentifier, height, useUpFromTargetOrDuration, duration] = + ghoul::lua::values< + std::string, double, std::optional>, + std::optional + >(L); - const std::string& nodeIdentifier = ghoul::lua::value(L, 1); if (!sceneGraphNode(nodeIdentifier)) { - lua_settop(L, 0); return ghoul::lua::luaError(L, "Unknown node name: " + nodeIdentifier); } - double height = ghoul::lua::value(L, 2); - using namespace std::string_literals; ghoul::Dictionary insDict; insDict.setValue("TargetType", "Node"s); insDict.setValue("Target", nodeIdentifier); insDict.setValue("Height", height); - - if (nArguments > 2) { - int result = handleOptionalGoToParameters(L, 3, nArguments, insDict); - if (result != 0) { - return result; // An error occurred + if (useUpFromTargetOrDuration.has_value()) { + if (std::holds_alternative(*useUpFromTargetOrDuration)) { + insDict.setValue( + "UseTargetUpDirection", + std::get(*useUpFromTargetOrDuration) + ); } + else { + double d = std::get(*useUpFromTargetOrDuration); + if (d <= Epsilon) { + return ghoul::lua::luaError(L, "Duration must be larger than zero"); + } + insDict.setValue("Duration", d); + } + } + if (duration.has_value()) { + double d = *duration; + if (d <= Epsilon) { + return ghoul::lua::luaError(L, "Duration must be larger than zero"); + } + insDict.setValue("Duration", d); } global::navigationHandler->pathNavigator().createPath(insDict); @@ -189,25 +210,17 @@ int goToHeight(lua_State* L) { global::navigationHandler->pathNavigator().startPath(); } - lua_settop(L, 0); - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int generatePath(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::generatePath"); - - ghoul::Dictionary dictionary; - ghoul::lua::luaDictionaryFromState(L, dictionary); + ghoul::Dictionary dictionary = ghoul::lua::value(L); global::navigationHandler->pathNavigator().createPath(dictionary); - if (global::navigationHandler->pathNavigator().hasCurrentPath()) { global::navigationHandler->pathNavigator().startPath(); } - - lua_settop(L, 0); - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } diff --git a/src/network/parallelpeer_lua.inl b/src/network/parallelpeer_lua.inl index 8aad523b26..c3711d1e2f 100644 --- a/src/network/parallelpeer_lua.inl +++ b/src/network/parallelpeer_lua.inl @@ -26,45 +26,33 @@ namespace openspace::luascriptfunctions { int connect(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::connect"); - if (global::windowDelegate->isMaster()) { global::parallelPeer->connect(); } - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int disconnect(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::disconnect"); - if (global::windowDelegate->isMaster()) { global::parallelPeer->connect(); } - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int requestHostship(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::requestHostship"); - if (global::windowDelegate->isMaster()) { global::parallelPeer->requestHostship(); } - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int resignHostship(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::resignHostship"); - if (global::windowDelegate->isMaster()) { global::parallelPeer->resignHostship(); } - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } diff --git a/src/rendering/dashboard_lua.inl b/src/rendering/dashboard_lua.inl index 081e2ecbe1..3af0b132f4 100644 --- a/src/rendering/dashboard_lua.inl +++ b/src/rendering/dashboard_lua.inl @@ -28,70 +28,45 @@ namespace openspace::luascriptfunctions { /** -* \ingroup LuaScripts -* addDashboardItem(table): -*/ + * \ingroup LuaScripts + * addDashboardItem(table): + */ int addDashboardItem(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::addDashboardItem"); + ghoul::Dictionary d = ghoul::lua::value(L); - const int type = lua_type(L, -1); - if (type == LUA_TTABLE) { - ghoul::Dictionary d; - try { - ghoul::lua::luaDictionaryFromState(L, d); - } - catch (const ghoul::lua::LuaFormatException& e) { - LERRORC("addDashboardItem", e.what()); - lua_settop(L, 0); - return 0; - } - lua_settop(L, 0); - - try { - global::dashboard->addDashboardItem(DashboardItem::createFromDictionary(d)); - } - catch (const ghoul::RuntimeError& e) { - LERRORC("addDashboardItem", e.what()); - return ghoul::lua::luaError(L, "Error adding dashboard item"); - } - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); - return 0; + try { + global::dashboard->addDashboardItem( + DashboardItem::createFromDictionary(std::move(d)) + ); } - else { - return ghoul::lua::luaError(L, "Expected argument of type 'table'"); + catch (const ghoul::RuntimeError& e) { + LERRORC("addDashboardItem", e.what()); + return ghoul::lua::luaError(L, "Error adding dashboard item"); } -} -/** -* \ingroup LuaScripts -* removeDashboardItem(string): -*/ -int removeDashboardItem(lua_State* L) { - using ghoul::lua::errorLocation; - - ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::removeDashbordItem"); - - std::string identifier = luaL_checkstring(L, -1); - - global::dashboard->removeDashboardItem(identifier); - - lua_settop(L, 0); - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } +/** + * \ingroup LuaScripts + * removeDashboardItem(string): + */ +int removeDashboardItem(lua_State* L) { + ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::removeDashbordItem"); + const std::string identifier = ghoul::lua::value(L); + + global::dashboard->removeDashboardItem(identifier); + return 0; +} /** -* \ingroup LuaScripts -* removeDashboardItems(): -*/ + * \ingroup LuaScripts + * removeDashboardItems(): + */ int clearDashboardItems(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::clearDashboardItems"); - global::dashboard->clearDashboardItems(); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } diff --git a/src/rendering/renderengine_lua.inl b/src/rendering/renderengine_lua.inl index b011722f42..e3debf38c5 100644 --- a/src/rendering/renderengine_lua.inl +++ b/src/rendering/renderengine_lua.inl @@ -28,50 +28,28 @@ namespace openspace::luascriptfunctions { int addScreenSpaceRenderable(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::addScreenSpaceRenderable"); - - using ghoul::lua::errorLocation; - - ghoul::Dictionary d; - try { - ghoul::lua::luaDictionaryFromState(L, d); - lua_settop(L, 0); - } - catch (const ghoul::lua::LuaFormatException& e) { - LERRORC("addScreenSpaceRenderable", e.what()); - lua_settop(L, 0); - return 0; - } + const ghoul::Dictionary d = ghoul::lua::value(L); std::unique_ptr s = - ScreenSpaceRenderable::createFromDictionary(d); + ScreenSpaceRenderable::createFromDictionary(d); global::renderEngine->addScreenSpaceRenderable(std::move(s)); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int removeScreenSpaceRenderable(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::removeScreenSpaceRenderable"); + const std::string name = ghoul::lua::value(L); - const std::string& name = ghoul::lua::value( - L, - 1, - ghoul::lua::PopValue::Yes - ); global::renderEngine->removeScreenSpaceRenderable(name); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int takeScreenshot(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::takeScreenshot"); - global::renderEngine->takeScreenshot(); const unsigned int screenshotNumber = global::renderEngine->latestScreenshotNumber(); - - lua_pushinteger(L, screenshotNumber); + ghoul::lua::push(L, screenshotNumber); return 1; } diff --git a/src/scene/assetloader_lua.inl b/src/scene/assetloader_lua.inl index 0b8884f3e2..b47b7ee4b8 100644 --- a/src/scene/assetloader_lua.inl +++ b/src/scene/assetloader_lua.inl @@ -28,8 +28,8 @@ namespace openspace::assetloader { * Adds a Lua function to be called upon asset initialization * Usage: void asset.onInitialize(function initFun) */ -int onInitialize(lua_State* state) { - Asset* asset = reinterpret_cast(lua_touserdata(state, lua_upvalueindex(1))); +int onInitialize(lua_State* L) { + Asset* asset = reinterpret_cast(lua_touserdata(L, lua_upvalueindex(1))); return asset->loader()->onInitializeLua(asset); } @@ -37,36 +37,28 @@ int onInitialize(lua_State* state) { * Adds a Lua function to be called upon asset deinitialization * Usage: void asset.onDeinitialize(function initFun) */ -int onDeinitialize(lua_State* state) { - Asset* asset = reinterpret_cast(lua_touserdata(state, lua_upvalueindex(1))); +int onDeinitialize(lua_State* L) { + Asset* asset = reinterpret_cast(lua_touserdata(L, lua_upvalueindex(1))); return asset->loader()->onDeinitializeLua(asset); } /** -* Adds a Lua function to be called when a dependency link is initialized -* Usage: void asset.onInitialize(function initFun) -*/ -int onInitializeDependency(lua_State* state) { - Asset* dependant = reinterpret_cast( - lua_touserdata(state, lua_upvalueindex(1)) - ); - Asset* dependency = reinterpret_cast( - lua_touserdata(state, lua_upvalueindex(2)) - ); + * Adds a Lua function to be called when a dependency link is initialized + * Usage: void asset.onInitialize(function initFun) + */ +int onInitializeDependency(lua_State* L) { + Asset* dependant = reinterpret_cast(lua_touserdata(L, lua_upvalueindex(1))); + Asset* dependency = reinterpret_cast(lua_touserdata(L, lua_upvalueindex(2))); return dependant->loader()->onInitializeDependencyLua(dependant, dependency); } /** -* Adds a Lua function to be called upon asset deinitialization -* Usage: void asset.onDeinitialize(function initFun) -*/ -int onDeinitializeDependency(lua_State* state) { - Asset* dependant = reinterpret_cast( - lua_touserdata(state, lua_upvalueindex(1)) - ); - Asset* dependency = reinterpret_cast( - lua_touserdata(state, lua_upvalueindex(2)) - ); + * Adds a Lua function to be called upon asset deinitialization + * Usage: void asset.onDeinitialize(function initFun) + */ +int onDeinitializeDependency(lua_State* L) { + Asset* dependant = reinterpret_cast(lua_touserdata(L, lua_upvalueindex(1))); + Asset* dependency = reinterpret_cast(lua_touserdata(L, lua_upvalueindex(2))); return dependant->loader()->onDeinitializeDependencyLua(dependant, dependency); } @@ -77,28 +69,28 @@ int onDeinitializeDependency(lua_State* state) { * Dependency: ... * Usage: {AssetTable, Dependency} = asset.import(string assetIdentifier) */ -int require(lua_State* state) { - Asset* asset = reinterpret_cast(lua_touserdata(state, lua_upvalueindex(1))); +int require(lua_State* L) { + Asset* asset = reinterpret_cast(lua_touserdata(L, lua_upvalueindex(1))); return asset->loader()->requireLua(asset); } -int exists(lua_State* state) { - Asset* asset = reinterpret_cast(lua_touserdata(state, lua_upvalueindex(1))); +int exists(lua_State* L) { + Asset* asset = reinterpret_cast(lua_touserdata(L, lua_upvalueindex(1))); return asset->loader()->existsLua(asset); } -int localResource(lua_State* state) { - Asset* asset = reinterpret_cast(lua_touserdata(state, lua_upvalueindex(1))); +int localResource(lua_State* L) { + Asset* asset = reinterpret_cast(lua_touserdata(L, lua_upvalueindex(1))); return asset->loader()->localResourceLua(asset); } -int syncedResource(lua_State* state) { - Asset* asset = reinterpret_cast(lua_touserdata(state, lua_upvalueindex(1))); +int syncedResource(lua_State* L) { + Asset* asset = reinterpret_cast(lua_touserdata(L, lua_upvalueindex(1))); return asset->loader()->syncedResourceLua(asset); } -int exportAsset(lua_State* state) { - Asset* asset = reinterpret_cast(lua_touserdata(state, lua_upvalueindex(1))); +int exportAsset(lua_State* L) { + Asset* asset = reinterpret_cast(lua_touserdata(L, lua_upvalueindex(1))); return asset->loader()->exportAssetLua(asset); } diff --git a/src/scene/assetmanager_lua.inl b/src/scene/assetmanager_lua.inl index 82bbbd62f9..a27e6a6bf4 100644 --- a/src/scene/assetmanager_lua.inl +++ b/src/scene/assetmanager_lua.inl @@ -28,17 +28,13 @@ namespace openspace::luascriptfunctions::asset { -int add(lua_State* state) { - ghoul::lua::checkArgumentsAndThrow(state, 1, "lua::add"); +int add(lua_State* L) { + ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::add"); - AssetManager* assetManager = - reinterpret_cast(lua_touserdata(state, lua_upvalueindex(1))); - - const std::string& assetName = ghoul::lua::value( - state, - 1, - ghoul::lua::PopValue::Yes + AssetManager* assetManager = reinterpret_cast( + lua_touserdata(L, lua_upvalueindex(1)) ); + const std::string assetName = ghoul::lua::value(L); if (global::renderEngine->scene()) { assetManager->add(assetName); @@ -49,36 +45,27 @@ int add(lua_State* state) { global::openSpaceEngine->scheduleLoadSingleAsset(assetName); } - - ghoul_assert(lua_gettop(state) == 0, "Incorrect number of items left on stack"); return 0; } -int remove(lua_State* state) { - ghoul::lua::checkArgumentsAndThrow(state, 1, "lua::remove"); +int remove(lua_State* L) { + ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::remove"); AssetManager* assetManager = - reinterpret_cast(lua_touserdata(state, lua_upvalueindex(1))); + reinterpret_cast(lua_touserdata(L, lua_upvalueindex(1))); + const std::string assetName = ghoul::lua::value(L); - const std::string& assetName = ghoul::lua::value( - state, - 1, - ghoul::lua::PopValue::Yes - ); assetManager->remove(assetName); - - ghoul_assert(lua_gettop(state) == 0, "Incorrect number of items left on stack"); return 0; } -int removeAll(lua_State* state) { - ghoul::lua::checkArgumentsAndThrow(state, 0, "lua::removeAll"); +int removeAll(lua_State* L) { + ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::removeAll"); AssetManager* assetManager = - reinterpret_cast(lua_touserdata(state, lua_upvalueindex(1))); + reinterpret_cast(lua_touserdata(L, lua_upvalueindex(1))); assetManager->removeAll(); - return 0; } diff --git a/src/scene/profile_lua.inl b/src/scene/profile_lua.inl index 9f573830b0..a66f8dc1c2 100644 --- a/src/scene/profile_lua.inl +++ b/src/scene/profile_lua.inl @@ -37,21 +37,19 @@ namespace openspace::luascriptfunctions { int saveSettingsToProfile(lua_State* L) { if (!global::configuration->usingProfile) { - return luaL_error( + return ghoul::lua::luaError( L, "Program was not started with a profile, so cannot use this " "save-current-settings feature" ); } - const int n = ghoul::lua::checkArgumentsAndThrow( - L, - { 0, 2 }, - "lua::saveSettingsToProfile" - ); + ghoul::lua::checkArgumentsAndThrow(L, { 0, 2 }, "lua::saveSettingsToProfile"); + auto [saveFilePath, overwrite] = + ghoul::lua::values, std::optional>(L); + overwrite = overwrite.value_or(true); - std::string saveFilePath; - if (n == 0) { + if (!saveFilePath.has_value()) { std::time_t t = std::time(nullptr); std::tm* utcTime = std::gmtime(&t); ghoul_assert(utcTime, "Conversion to UTC failed"); @@ -68,22 +66,27 @@ int saveSettingsToProfile(lua_State* L) { std::filesystem::path path = global::configuration->profile; path.replace_extension(); std::string newFile = fmt::format("{}_{}", path.string(), time); - std::string sourcePath = fmt::format("{}/{}.profile", - absPath("${USER_PROFILES}").string(), global::configuration->profile); - std::string destPath = fmt::format("{}/{}.profile", - absPath("${PROFILES}").string(), global::configuration->profile); + std::string sourcePath = fmt::format( + "{}/{}.profile", + absPath("${USER_PROFILES}").string(), global::configuration->profile + ); + std::string destPath = fmt::format( + "{}/{}.profile", + absPath("${PROFILES}").string(), global::configuration->profile + ); if (!std::filesystem::is_regular_file(sourcePath)) { - sourcePath = absPath("${USER_PROFILES}").string() - + '/' + global::configuration->profile + ".profile"; + sourcePath = fmt::format( + "{}/{}.profile", + absPath("${USER_PROFILES}").string(), global::configuration->profile + ); } LINFOC("Profile", fmt::format("Saving a copy of the old profile as {}", newFile)); std::filesystem::copy(sourcePath, destPath); saveFilePath = global::configuration->profile; } else { - saveFilePath = ghoul::lua::value(L, 1); - if (saveFilePath.empty()) { - return luaL_error(L, "save filepath string is empty"); + if (saveFilePath->empty()) { + return ghoul::lua::luaError(L, "Save filepath string is empty"); } } @@ -91,32 +94,35 @@ int saveSettingsToProfile(lua_State* L) { std::string currentTime = std::string(global::timeManager->time().ISO8601()); interaction::NavigationState navState = global::navigationHandler->navigationState(); global::profile->saveCurrentSettingsToProfile(root, currentTime, navState); - global::configuration->profile = saveFilePath; + global::configuration->profile = *saveFilePath; - if (saveFilePath.find('/') != std::string::npos) { - return luaL_error(L, "Profile filename must not contain path (/) elements"); + if (saveFilePath->find('/') != std::string::npos) { + return ghoul::lua::luaError(L, "Profile filename must not contain (/) elements"); } - else if (saveFilePath.find(':') != std::string::npos) { - return luaL_error(L, "Profile filename must not contain path (:) elements"); + else if (saveFilePath->find(':') != std::string::npos) { + return ghoul::lua::luaError(L, "Profile filename must not contain (:) elements"); } - else if (saveFilePath.find('.') != std::string::npos) { - return luaL_error(L, "Only provide the filename to save without file extension"); + else if (saveFilePath->find('.') != std::string::npos) { + return ghoul::lua::luaError( + L, + "Only provide the filename to save without file extension" + ); } - std::string absFilename = fmt::format("{}/{}.profile", - absPath("${PROFILES}").string(), saveFilePath); + std::string absFilename = fmt::format( + "{}/{}.profile", absPath("${PROFILES}").string(), *saveFilePath + ); if (!std::filesystem::is_regular_file(absFilename)) { - absFilename = absPath("${USER_PROFILES}/" + saveFilePath + ".profile").string(); + absFilename = absPath("${USER_PROFILES}/" + *saveFilePath + ".profile").string(); } - const bool overwrite = (n == 2) ? ghoul::lua::value(L, 2) : true; if (std::filesystem::is_regular_file(absFilename) && !overwrite) { - return luaL_error( + return ghoul::lua::luaError( L, fmt::format( "Unable to save profile '{}'. File of same name already exists", absFilename - ).c_str() + ) ); } @@ -126,11 +132,11 @@ int saveSettingsToProfile(lua_State* L) { outFile.open(absFilename, std::ofstream::out); } catch (const std::ofstream::failure& e) { - return luaL_error( + return ghoul::lua::luaError( L, fmt::format( "Exception opening profile file for write: {} ({})", absFilename, e.what() - ).c_str() + ) ); } @@ -138,17 +144,11 @@ int saveSettingsToProfile(lua_State* L) { outFile << global::profile->serialize(); } catch (const std::ofstream::failure& e) { - return luaL_error( + return ghoul::lua::luaError( L, - fmt::format( - "Data write error to file: {} ({})", absFilename, e.what() - ).c_str() + fmt::format("Data write error to file: {} ({})", absFilename, e.what()) ); } - - outFile.close(); - - lua_settop(L, 0); return 0; } diff --git a/src/scene/scene_lua.inl b/src/scene/scene_lua.inl index e685a23370..77a5fd803a 100644 --- a/src/scene/scene_lua.inl +++ b/src/scene/scene_lua.inl @@ -35,7 +35,7 @@ namespace { template properties::PropertyOwner* findPropertyOwnerWithMatchingGroupTag(T* prop, - const std::string& tagToMatch) + const std::string& tagToMatch) { properties::PropertyOwner* tagMatchOwner = nullptr; properties::PropertyOwner* owner = prop->owner(); @@ -59,10 +59,9 @@ properties::PropertyOwner* findPropertyOwnerWithMatchingGroupTag(T* prop, } void applyRegularExpression(lua_State* L, const std::string& regex, - const std::vector& properties, - double interpolationDuration, - const std::string& groupName, - ghoul::EasingFunction easingFunction) + const std::vector& properties, + double interpolationDuration, const std::string& groupName, + ghoul::EasingFunction easingFunction) { using ghoul::lua::errorLocation; using ghoul::lua::luaTypeToString; @@ -73,8 +72,8 @@ void applyRegularExpression(lua_State* L, const std::string& regex, const int type = lua_type(L, -1); // Extract the property and node name to be searched for from regex - std::string propertyName = ""; - std::string nodeName = ""; + std::string propertyName; + std::string nodeName; size_t wildPos = regex.find_first_of("*"); if (wildPos != std::string::npos) { nodeName = regex.substr(0, wildPos); @@ -85,8 +84,8 @@ void applyRegularExpression(lua_State* L, const std::string& regex, LERRORC( "applyRegularExpression", fmt::format( - "Malformed regular expression: '{}': " - "Empty both before and after '*'", regex + "Malformed regular expression: '{}': Empty both before and after '*'", + regex ) ); return; @@ -97,8 +96,8 @@ void applyRegularExpression(lua_State* L, const std::string& regex, LERRORC( "applyRegularExpression", fmt::format( - "Malformed regular expression: '{}': " - "Currently only one '*' is supported", regex + "Malformed regular expression: '{}': Currently only one '*' is " + "supported", regex ) ); return; @@ -117,7 +116,7 @@ void applyRegularExpression(lua_State* L, const std::string& regex, bool foundMatching = false; for (properties::Property* prop : properties) { // Check the regular expression for all properties - const std::string& id = prop->fullyQualifiedIdentifier(); + const std::string id = prop->fullyQualifiedIdentifier(); if (isLiteral && id != propertyName) { continue; @@ -138,10 +137,7 @@ void applyRegularExpression(lua_State* L, const std::string& regex, // Check tag if (isGroupMode) { properties::PropertyOwner* matchingTaggedOwner = - findPropertyOwnerWithMatchingGroupTag( - prop, - groupName - ); + findPropertyOwnerWithMatchingGroupTag(prop, groupName); if (!matchingTaggedOwner) { continue; } @@ -154,14 +150,10 @@ void applyRegularExpression(lua_State* L, const std::string& regex, else if (!nodeName.empty()) { size_t nodePos = id.find(nodeName); if (nodePos != std::string::npos) { - // Check tag if (isGroupMode) { properties::PropertyOwner* matchingTaggedOwner = - findPropertyOwnerWithMatchingGroupTag( - prop, - groupName - ); + findPropertyOwnerWithMatchingGroupTag(prop, groupName); if (!matchingTaggedOwner) { continue; } @@ -181,12 +173,10 @@ void applyRegularExpression(lua_State* L, const std::string& regex, LERRORC( "property_setValue", fmt::format( - "{}: Property '{}' does not accept input of type '{}'. " - "Requested type: '{}'", - errorLocation(L), - prop->fullyQualifiedIdentifier(), - luaTypeToString(type), - luaTypeToString(prop->typeLua()) + "{}: Property '{}' does not accept input of type '{}'. Requested " + "type: '{}'", + errorLocation(L), prop->fullyQualifiedIdentifier(), + luaTypeToString(type), luaTypeToString(prop->typeLua()) ) ); } @@ -217,9 +207,7 @@ void applyRegularExpression(lua_State* L, const std::string& regex, LERRORC( "property_setValue", fmt::format( - "{}: No property matched the requested URI '{}'", - errorLocation(L), - regex + "{}: No property matched the requested URI '{}'", errorLocation(L), regex ) ); } @@ -228,7 +216,7 @@ void applyRegularExpression(lua_State* L, const std::string& regex, // Checks to see if URI contains a group tag (with { } around the first term). If so, // returns true and sets groupName with the tag bool doesUriContainGroupTag(const std::string& command, std::string& groupName) { - std::string name = command.substr(0, command.find_first_of(".")); + const std::string name = command.substr(0, command.find_first_of(".")); if (name.front() == '{' && name.back() == '}') { groupName = name.substr(1, name.length() - 2); return true; @@ -248,8 +236,8 @@ std::string removeGroupNameFromUri(const std::string& uri) { namespace openspace::luascriptfunctions { int setPropertyCall_single(properties::Property& prop, const std::string& uri, - lua_State* L, double duration, - ghoul::EasingFunction easingFunction) + lua_State* L, double duration, + ghoul::EasingFunction easingFunction) { using ghoul::lua::errorLocation; using ghoul::lua::luaTypeToString; @@ -261,9 +249,7 @@ int setPropertyCall_single(properties::Property& prop, const std::string& uri, fmt::format( "{}: Property '{}' does not accept input of type '{}'. " "Requested type: '{}'", - errorLocation(L), - uri, - luaTypeToString(type), + errorLocation(L), uri, luaTypeToString(type), luaTypeToString(prop.typeLua()) ) ); @@ -301,37 +287,39 @@ int setPropertyCall_single(properties::Property& prop, const std::string& uri, */ int property_setValue(lua_State* L) { - using ghoul::lua::errorLocation; - using ghoul::lua::luaTypeToString; - ghoul::lua::checkArgumentsAndThrow(L, { 2, 5 }, "lua::property_setValue"); defer { lua_settop(L, 0); }; - std::string uriOrRegex = ghoul::lua::value(L, 1); + std::string uriOrRegex = + ghoul::lua::value(L, 1, ghoul::lua::PopValue::No); std::string optimization; double interpolationDuration = 0.0; std::string easingMethodName; ghoul::EasingFunction easingMethod = ghoul::EasingFunction::Linear; if (lua_gettop(L) >= 3) { - if (lua_type(L, 3) == LUA_TNUMBER) { - interpolationDuration = ghoul::lua::value(L, 3); + if (ghoul::lua::hasValue(L, 3)) { + interpolationDuration = + ghoul::lua::value(L, 3, ghoul::lua::PopValue::No); } else { - optimization = ghoul::lua::value(L, 3); + optimization = + ghoul::lua::value(L, 3, ghoul::lua::PopValue::No); } if (lua_gettop(L) >= 4) { - if (lua_type(L, 4) == LUA_TNUMBER) { - interpolationDuration = ghoul::lua::value(L, 4); + if (ghoul::lua::hasValue(L, 4)) { + interpolationDuration = + ghoul::lua::value(L, 4, ghoul::lua::PopValue::No); } else { - easingMethodName = ghoul::lua::value(L, 4); + easingMethodName = + ghoul::lua::value(L, 4, ghoul::lua::PopValue::No); } } if (lua_gettop(L) == 5) { - optimization = ghoul::lua::value(L, 5); + optimization = ghoul::lua::value(L, 5, ghoul::lua::PopValue::No); } // Later functions expect the value to be at the last position on the stack @@ -346,7 +334,7 @@ int property_setValue(lua_State* L) { } if (!easingMethodName.empty()) { - bool correctName = ghoul::isValidEasingFunctionName(easingMethodName.c_str()); + bool correctName = ghoul::isValidEasingFunctionName(easingMethodName); if (!correctName) { LWARNINGC( "property_setValue", @@ -354,7 +342,7 @@ int property_setValue(lua_State* L) { ); } else { - easingMethod = ghoul::easingFunctionFromName(easingMethodName.c_str()); + easingMethod = ghoul::easingFunctionFromName(easingMethodName); } } @@ -392,8 +380,7 @@ int property_setValue(lua_State* L) { "property_setValue", fmt::format( "{}: Property with URI '{}' was not found", - errorLocation(L), - uriOrRegex + ghoul::lua::errorLocation(L), uriOrRegex ) ); return 0; @@ -411,8 +398,7 @@ int property_setValue(lua_State* L) { "lua::property_setGroup", fmt::format( "{}: Unexpected optimization '{}'", - errorLocation(L), - optimization + ghoul::lua::errorLocation(L), optimization ) ); } @@ -439,14 +425,9 @@ int property_setValueSingle(lua_State* L) { */ int property_hasProperty(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::property_hasProperty"); + const std::string uri = ghoul::lua::value(L); - std::string uri = ghoul::lua::value( - L, - 1, - ghoul::lua::PopValue::Yes - ); - - openspace::properties::Property* prop = property(uri); + properties::Property* prop = property(uri); ghoul::lua::push(L, prop != nullptr); return 1; } @@ -459,44 +440,33 @@ int property_hasProperty(lua_State* L) { */ int property_getValue(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::property_getValue"); + const std::string uri = ghoul::lua::value(L); - std::string uri = ghoul::lua::value( - L, - 1, - ghoul::lua::PopValue::Yes - ); - - openspace::properties::Property* prop = property(uri); + properties::Property* prop = property(uri); if (!prop) { LERRORC( "property_getValue", fmt::format( "{}: Property with URI '{}' was not found", - ghoul::lua::errorLocation(L), - uri + ghoul::lua::errorLocation(L), uri ) ); - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } else { prop->getLuaValue(L); } - - ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack"); return 1; } /** -* \ingroup LuaScripts -* getProperty -* Returns a list of property identifiers that match the passed regular expression -*/ + * \ingroup LuaScripts + * getProperty + * Returns a list of property identifiers that match the passed regular expression + */ int property_getProperty(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::property_getProperty"); - - std::string regex = ghoul::lua::value(L, 1); - lua_pop(L, 1); + std::string regex = ghoul::lua::value(L); std::string groupName; if (doesUriContainGroupTag(regex, groupName)) { @@ -506,8 +476,8 @@ int property_getProperty(lua_State* L) { // Extract the property and node name to be searched for from regex bool isLiteral = false; - std::string propertyName = ""; - std::string nodeName = ""; + std::string propertyName; + std::string nodeName; size_t wildPos = regex.find_first_of("*"); if (wildPos != std::string::npos) { nodeName = regex.substr(0, wildPos); @@ -518,8 +488,8 @@ int property_getProperty(lua_State* L) { LERRORC( "property_getProperty", fmt::format( - "Malformed regular expression: '{}': " - "Empty both before and after '*'", regex + "Malformed regular expression: '{}': Empty both before and after '*'", + regex ) ); return 0; @@ -571,10 +541,7 @@ int property_getProperty(lua_State* L) { // Check tag if (!groupName.empty()) { properties::PropertyOwner* matchingTaggedOwner = - findPropertyOwnerWithMatchingGroupTag( - prop, - groupName - ); + findPropertyOwnerWithMatchingGroupTag(prop, groupName); if (!matchingTaggedOwner) { continue; } @@ -591,10 +558,7 @@ int property_getProperty(lua_State* L) { // Check tag if (!groupName.empty()) { properties::PropertyOwner* matchingTaggedOwner = - findPropertyOwnerWithMatchingGroupTag( - prop, - groupName - ); + findPropertyOwnerWithMatchingGroupTag(prop, groupName); if (!matchingTaggedOwner) { continue; } @@ -615,35 +579,24 @@ int property_getProperty(lua_State* L) { lua_newtable(L); int number = 1; for (const std::string& s : res) { - lua_pushstring(L, s.c_str()); + ghoul::lua::push(L, s); lua_rawseti(L, -2, number); ++number; } - return 1; } int loadScene(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::loadScene"); + std::string sceneFile = ghoul::lua::value(L); - const std::string& sceneFile = ghoul::lua::value(L, 1); - global::openSpaceEngine->scheduleLoadSingleAsset(sceneFile); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); + global::openSpaceEngine->scheduleLoadSingleAsset(std::move(sceneFile)); return 0; } int addSceneGraphNode(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::addSceneGraphNode"); - - ghoul::Dictionary d; - try { - ghoul::lua::luaDictionaryFromState(L, d); - } - catch (const ghoul::lua::LuaFormatException& e) { - LERRORC("addSceneGraphNode", e.what()); - return ghoul::lua::luaError(L, "Error loading dictionary from lua state"); - } + const ghoul::Dictionary d = ghoul::lua::value(L); try { SceneGraphNode* node = global::renderEngine->scene()->loadNode(d); @@ -655,7 +608,7 @@ int addSceneGraphNode(lua_State* L) { global::renderEngine->scene()->initializeNode(node); } catch (const documentation::SpecificationError& e) { - std::string cat = + std::string cat = d.hasValue("Identifier") ? d.value("Identifier") : "Scene"; @@ -672,16 +625,12 @@ int addSceneGraphNode(lua_State* L) { fmt::format("Error loading scene graph node: {}", e.what()) ); } - - lua_settop(L, 0); - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int removeSceneGraphNode(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::removeSceneGraphNode"); - - std::string name = ghoul::lua::value(L, 1, ghoul::lua::PopValue::Yes); + const std::string name = ghoul::lua::value(L); SceneGraphNode* foundNode = sceneGraphNode(name); if (!foundNode) { @@ -730,23 +679,20 @@ int removeSceneGraphNode(lua_State* L) { }; removeNode(foundNode); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int removeSceneGraphNodesFromRegex(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::removeSceneGraphNodesFromRegex"); - - std::string name = ghoul::lua::value(L, 1, ghoul::lua::PopValue::Yes); + const std::string name = ghoul::lua::value(L); const std::vector& nodes = global::renderEngine->scene()->allSceneGraphNodes(); // Extract the property and node name to be searched for from name bool isLiteral = false; - std::string propertyName = ""; - std::string nodeName = ""; + std::string propertyName; + std::string nodeName; size_t wildPos = name.find_first_of("*"); if (wildPos != std::string::npos) { nodeName = name.substr(0, wildPos); @@ -757,8 +703,8 @@ int removeSceneGraphNodesFromRegex(lua_State* L) { LERRORC( "removeSceneGraphNodesFromRegex", fmt::format( - "Malformed regular expression: '{}': " - "Empty both before and after '*'", name + "Malformed regular expression: '{}': Empty both before and after '*'", + name ) ); return 0; @@ -824,8 +770,7 @@ int removeSceneGraphNodesFromRegex(lua_State* L) { SceneGraphNode* parent = node->parent(); if (!parent) { LERRORC( - "removeSceneGraphNodesFromRegex", - fmt::format("Cannot remove root node") + "removeSceneGraphNodesFromRegex", fmt::format("Cannot remove root node") ); } else { @@ -845,8 +790,7 @@ int removeSceneGraphNodesFromRegex(lua_State* L) { std::function&)> markNode = [&markNode](SceneGraphNode* node, std::vector& marked) { - std::vector children = node->children(); - for (SceneGraphNode* child : children) { + for (SceneGraphNode* child : node->children()) { markNode(child, marked); } @@ -896,48 +840,33 @@ int removeSceneGraphNodesFromRegex(lua_State* L) { removeNode(markedList[0]); } - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int hasSceneGraphNode(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::hasSceneGraphNode"); + const std::string nodeName = ghoul::lua::value(L); - std::string nodeName = ghoul::lua::value( - L, - 1, - ghoul::lua::PopValue::Yes - ); SceneGraphNode* node = global::renderEngine->scene()->sceneGraphNode(nodeName); - ghoul::lua::push(L, node != nullptr); - - ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack"); return 1; } int addInterestingTime(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::addInterestingTime"); - - std::string name = ghoul::lua::value(L, 1, ghoul::lua::PopValue::No); - std::string time = ghoul::lua::value(L, 2, ghoul::lua::PopValue::No); - lua_pop(L, 2); + auto [name, time] = ghoul::lua::values(L); global::renderEngine->scene()->addInterestingTime( { std::move(name), std::move(time) } ); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int worldPosition(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::worldPosition"); + const std::string identifier = ghoul::lua::value(L); - std::string identifier = ghoul::lua::value(L, 1, ghoul::lua::PopValue::Yes); SceneGraphNode* node = sceneGraphNode(identifier); - if (!node) { return ghoul::lua::luaError( L, @@ -946,18 +875,15 @@ int worldPosition(lua_State* L) { } glm::dvec3 pos = node->worldPosition(); - ghoul::lua::push(L, pos); - - ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack"); + ghoul::lua::push(L, std::move(pos)); return 1; } int worldRotation(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::worldRotation"); + std::string identifier = ghoul::lua::value(L); - std::string identifier = ghoul::lua::value(L, 1, ghoul::lua::PopValue::Yes); SceneGraphNode* node = sceneGraphNode(identifier); - if (!node) { return ghoul::lua::luaError( L, @@ -966,9 +892,7 @@ int worldRotation(lua_State* L) { } glm::dmat3 rot = node->worldRotationMatrix(); - ghoul::lua::push(L, rot); - - ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack"); + ghoul::lua::push(L, std::move(rot)); return 1; } diff --git a/src/scripting/scriptengine_lua.inl b/src/scripting/scriptengine_lua.inl index 1cdc5882f9..894f6387ab 100644 --- a/src/scripting/scriptengine_lua.inl +++ b/src/scripting/scriptengine_lua.inl @@ -35,8 +35,6 @@ int printInternal(ghoul::logging::LogLevel level, lua_State* L) { log(level, "print", ghoul::lua::luaValueToString(L, i)); } lua_pop(L, nArguments); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } @@ -114,16 +112,9 @@ int printFatal(lua_State* L) { */ int absolutePath(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::absolutePath"); - - const std::string& path = ghoul::lua::value( - L, - 1, - ghoul::lua::PopValue::Yes - ); + const std::string path = ghoul::lua::value(L); ghoul::lua::push(L, absPath(path).string()); - - ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack"); return 1; } @@ -135,18 +126,13 @@ int absolutePath(lua_State* L) { */ int setPathToken(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::setPathToken"); - - std::string pathToken = ghoul::lua::value(L, 1); - std::string path = ghoul::lua::value(L, 2); + auto [pathToken, path] = ghoul::lua::values(L); FileSys.registerPathToken( std::move(pathToken), std::move(path), ghoul::filesystem::FileSystem::Override::Yes ); - - lua_pop(L, 2); - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } @@ -157,17 +143,10 @@ int setPathToken(lua_State* L) { */ int fileExists(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::fileExists"); + std::string file = ghoul::lua::value(L); - const std::string& file = ghoul::lua::value( - L, - 1, - ghoul::lua::PopValue::Yes - ); - const bool e = std::filesystem::is_regular_file(absPath(file)); - + const bool e = std::filesystem::is_regular_file(absPath(std::move(file))); ghoul::lua::push(L, e); - - ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack"); return 1; } @@ -178,15 +157,11 @@ int fileExists(lua_State* L) { */ int readFile(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::readFile"); + const std::string file = ghoul::lua::value(L); - const std::string& file = ghoul::lua::value( - L, - 1, - ghoul::lua::PopValue::Yes - ); std::filesystem::path p = absPath(file); if (!std::filesystem::is_regular_file(p)) { - return ghoul::lua::luaError(L, fmt::format("Could not open file {}", file)); + return ghoul::lua::luaError(L, fmt::format("Could not open file '{}'", file)); } std::ifstream f(p); @@ -204,26 +179,19 @@ int readFile(lua_State* L) { */ int directoryExists(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::directoryExists"); + std::string file = ghoul::lua::value(L); - const std::string& file = ghoul::lua::value( - L, - 1, - ghoul::lua::PopValue::Yes - ); - const bool e = std::filesystem::is_directory(absPath(file)); - + const bool e = std::filesystem::is_directory(absPath(std::move(file))); ghoul::lua::push(L, e); - - ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack"); return 1; } int walkCommon(lua_State* L, std::function filter) { - int nArguments = ghoul::lua::checkArgumentsAndThrow(L, { 1, 3 }, "lua::walkCommon"); - - const std::string path = ghoul::lua::value(L, 1); - const bool recursive = nArguments >= 2 ? ghoul::lua::value(L, 2) : false; - const bool sorted = nArguments == 3 ? ghoul::lua::value(L, 3) : false; + ghoul::lua::checkArgumentsAndThrow(L, { 1, 3 }, "lua::walkCommon"); + auto [path, recursive, sorted] = + ghoul::lua::values, std::optional>(L); + recursive = recursive.value_or(false); + sorted = sorted.value_or(false); namespace fs = std::filesystem; std::vector result; @@ -242,16 +210,14 @@ int walkCommon(lua_State* L, std::function f } } } - - if (sorted) { - std::sort(result.begin(), result.end()); - } + } + if (sorted) { + std::sort(result.begin(), result.end()); } lua_newtable(L); - for (int i = 0; i < static_cast(result.size()); ++i) { - lua_pushstring(L, result[i].path().string().c_str()); + ghoul::lua::push(L, result[i].path().string()); lua_rawseti(L, -2, i + 1); } return 1; @@ -289,14 +255,14 @@ int walkDirectoryFiles(lua_State* L) { } /** -* \ingroup LuaScripts -* walkDirectory(string, bool, bool): -* Walks a directory and returns the subfolders of the directory as absolute paths. The -* first argument is the path of the directory that should be walked, the second argument -* determines if the walk is recursive and will continue in contained directories. The -* default value for this parameter is "false". The third argument determines whether the -* table that is returned is sorted. The default value for this parameter is "false". -*/ + * \ingroup LuaScripts + * walkDirectory(string, bool, bool): + * Walks a directory and returns the subfolders of the directory as absolute paths. The + * first argument is the path of the directory that should be walked, the second argument + * determines if the walk is recursive and will continue in contained directories. The + * default value for this parameter is "false". The third argument determines whether the + * table that is returned is sorted. The default value for this parameter is "false". + */ int walkDirectoryFolder(lua_State* L) { namespace fs = std::filesystem; return walkCommon(L, [](const fs::path& p) { return fs::is_directory(p); }); @@ -311,13 +277,10 @@ int walkDirectoryFolder(lua_State* L) { */ int directoryForPath(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::directoryForPath"); + std::string file = ghoul::lua::value(L); - std::string file = ghoul::lua::value(L, 1, ghoul::lua::PopValue::Yes); std::string path = std::filesystem::path(std::move(file)).parent_path().string(); - - ghoul::lua::push(L, path); - - ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack"); + ghoul::lua::push(L, std::move(path)); return 1; } @@ -330,33 +293,19 @@ int directoryForPath(lua_State* L) { * is finished. */ int unzipFile(lua_State* L) { - const int nArguments = ghoul::lua::checkArgumentsAndThrow( - L, - { 2, 3 }, - "lua::unzipFile" - ); + ghoul::lua::checkArgumentsAndThrow(L, { 2, 3 }, "lua::unzipFile"); + auto [source, dest, deleteSource] = + ghoul::lua::values>(L); + source = absPath(source).string(); + dest = absPath(dest).string(); + deleteSource = deleteSource.value_or(false); - std::filesystem::path source = absPath( - ghoul::lua::value(L, 1, ghoul::lua::PopValue::No) - ); - std::filesystem::path dest = absPath( - ghoul::lua::value(L, 2, ghoul::lua::PopValue::No) - ); - - bool deleteSource = false; - if (nArguments == 3) { - deleteSource = ghoul::lua::value(L, 3, ghoul::lua::PopValue::No); - } - - auto onExtractEntry = [](const char*, void*) { return 0; }; int arg = 2; - zip_extract(source.string().c_str(), dest.string().c_str(), onExtractEntry, &arg); + zip_extract(source.c_str(), dest.c_str(), [](const char*, void*) { return 0; }, &arg); if (deleteSource && std::filesystem::is_regular_file(source)) { std::filesystem::remove(source); } - - lua_settop(L, 0); return 0; } @@ -372,7 +321,7 @@ int saveLastChangeToProfile(lua_State* L) { std::string actualLastLine; std::string lastLine; std::string line; - //add check for log file + // add check for log file if (!logfile.good()) { ghoul::lua::push(L, fmt::format("Could not open scriptlog {}", logFilePath)); printInternal(ghoul::logging::LogLevel::Error, L); diff --git a/src/scripting/scriptscheduler_lua.inl b/src/scripting/scriptscheduler_lua.inl index f0d2402539..2fe74d9ede 100644 --- a/src/scripting/scriptscheduler_lua.inl +++ b/src/scripting/scriptscheduler_lua.inl @@ -28,12 +28,8 @@ namespace openspace::luascriptfunctions { int loadFile(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::loadFile"); + const std::string& fileName = ghoul::lua::value(L); - const std::string& fileName = ghoul::lua::value( - L, - 1, - ghoul::lua::PopValue::Yes - ); if (fileName.empty()) { return ghoul::lua::luaError(L, "filepath string is empty"); } @@ -56,78 +52,48 @@ int loadFile(lua_State* L) { } global::scriptScheduler->loadScripts(scripts); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int loadScheduledScript(lua_State* L) { - int nArguments = ghoul::lua::checkArgumentsAndThrow( - L, - { 2, 4 }, - "lua::loadScheduledScript" - ); + ghoul::lua::checkArgumentsAndThrow(L, { 2, 4 }, "lua::loadScheduledScript"); + auto [time, forwardScript, backwardScript, universalScript] = ghoul::lua::values< + std::string, std::string, std::optional, std::optional + >(L); scripting::ScriptScheduler::ScheduledScript script; - - std::string time = ghoul::lua::value(L, 1); script.time = Time::convertTime(time); - std::string forwardScript = ghoul::lua::value(L, 2); script.forwardScript = std::move(forwardScript); + script.backwardScript = backwardScript.value_or(script.backwardScript); + script.universalScript = universalScript.value_or(script.universalScript); - if (nArguments == 3) { - std::string backwardScript = ghoul::lua::value(L, 3); - script.backwardScript = std::move(backwardScript); - } - else if (nArguments == 4) { - std::string backwardScript = ghoul::lua::value(L, 3); - script.backwardScript = std::move(backwardScript); - std::string universalScript = ghoul::lua::value(L, 4); - script.universalScript = std::move(universalScript); - } std::vector scripts; scripts.push_back(std::move(script)); global::scriptScheduler->loadScripts(scripts); - - lua_settop(L, 0); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int setModeApplicationTime(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::setModeApplicationTime"); - global::scriptScheduler->setModeApplicationTime(); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int setModeRecordedTime(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::setModeRecordedTime"); - global::scriptScheduler->setModeRecordedTime(); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int setModeSimulationTime(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::setModeSimulationTime"); - global::scriptScheduler->setModeSimulationTime(); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } int clear(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::clear"); - global::scriptScheduler->clearSchedule(); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } diff --git a/src/util/spicemanager.cpp b/src/util/spicemanager.cpp index 0f4897ac31..f5defa1f1c 100644 --- a/src/util/spicemanager.cpp +++ b/src/util/spicemanager.cpp @@ -1362,14 +1362,14 @@ scripting::LuaLibrary SpiceManager::luaLibrary() { "getSpkCoverage", &luascriptfunctions::spkCoverage, {}, - "{string [, printValues]}", + "string", "Returns a list of SPK coverage intervals for the target." }, { "getCkCoverage", &luascriptfunctions::ckCoverage, {}, - "{string [, printValues]}", + "string", "Returns a list of CK coverage intervals for the target." }, { diff --git a/src/util/spicemanager_lua.inl b/src/util/spicemanager_lua.inl index b0c2df9b63..268de67d63 100644 --- a/src/util/spicemanager_lua.inl +++ b/src/util/spicemanager_lua.inl @@ -38,20 +38,8 @@ namespace openspace::luascriptfunctions { int loadKernel(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::loadKernel"); + std::string argument = ghoul::lua::value(L); - bool isString = (lua_isstring(L, 1) == 1); - if (!isString) { - LERROR(fmt::format( - "{}: Expected argument of type 'string'", ghoul::lua::errorLocation(L) - )); - return 0; - } - - std::string argument = ghoul::lua::value( - L, - 1, - ghoul::lua::PopValue::Yes - ); if (!std::filesystem::is_regular_file(argument)) { return ghoul::lua::luaError( L, @@ -59,10 +47,7 @@ int loadKernel(lua_State* L) { ); } unsigned int result = SpiceManager::ref().loadKernel(argument); - - lua_pushnumber(L, result); - - ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack"); + ghoul::lua::push(L, result); return 1; } @@ -72,37 +57,16 @@ int loadKernel(lua_State* L) { * automatically resolved. */ int unloadKernel(lua_State* L) { - ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::loadKernel"); + ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::unloadKernel"); + std::variant argument = + ghoul::lua::value>(L); - bool isString = (lua_isstring(L, 1) == 1); - bool isNumber = (lua_isnumber(L, 1) == 1); - - if (!isString && !isNumber) { - LERRORC( - "loadKernel", - fmt::format( - "{}: Expected argument of type 'string' or 'number'", - ghoul::lua::errorLocation(L) - ) - ); - lua_settop(L, 0); - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); - return 0; + if (std::holds_alternative(argument)) { + SpiceManager::ref().unloadKernel(std::get(argument)); } - - if (isString) { - std::string argument = ghoul::lua::value(L, 1); - SpiceManager::ref().unloadKernel(argument); + else { + SpiceManager::ref().unloadKernel(std::get(argument)); } - - if (isNumber) { - unsigned int argument = ghoul::lua::value(L, 1); - SpiceManager::ref().unloadKernel(argument); - } - - lua_settop(L, 0); - - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } @@ -111,13 +75,9 @@ int unloadKernel(lua_State* L) { * Returns the list of bodies loaded into the spicemanager */ int spiceBodies(lua_State* L) { - ghoul::lua::checkArgumentsAndThrow(L, { 1,2 }, "lua::getSpiceBodies"); - bool isBool = (lua_isboolean(L, 1) == 1); - const bool buildInBodies = isBool ? ghoul::lua::value(L, 1) : false; + ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::spiceBodies"); + const bool buildInBodies = ghoul::lua::value(L); - isBool = (lua_isboolean(L, 2) == 1); - bool printValues = isBool ? ghoul::lua::value(L, 2) : false; - lua_settop(L, 0); std::vector> bodies = SpiceManager::ref().spiceBodies( buildInBodies ); @@ -132,35 +92,20 @@ int spiceBodies(lua_State* L) { lua_rawset(L, -3); lua_rawseti(L, -2, number); ++number; - - if (printValues) { - LINFO(fmt::format("Body id '{}' and name: {}", body.first, body.second)); - } } - return 1; } -//internal function for getSpk and getCk coverages +// internal function for getSpk and getCk coverages void buildLuaCoverageStack(lua_State* L, - const std::vector>& coverage, - bool printValues) + const std::vector>& coverage) { - lua_settop(L, 0); lua_newtable(L); int number = 1; for (const std::pair& window : coverage) { std::string start = SpiceManager::ref().dateFromEphemerisTime(window.first); std::string end = SpiceManager::ref().dateFromEphemerisTime(window.second); - if (printValues) { - LINFO(fmt::format( - "Coverage start {} and end: {}", - SpiceManager::ref().dateFromEphemerisTime(window.first), - SpiceManager::ref().dateFromEphemerisTime(window.second) - )); - } - lua_newtable(L); ghoul::lua::push(L, 1, start); lua_rawset(L, -3); @@ -172,97 +117,45 @@ void buildLuaCoverageStack(lua_State* L, } /** - * getSpkCoverage({string, bool(optional)}): + * spkCoverage(string): * Returns the spk coverage for given body */ int spkCoverage(lua_State* L) { - ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::getSpkCoverage"); - const bool isString = (lua_isstring(L, 1) == 1); - const bool isBool = (lua_isboolean(L, 2) == 1); - - if (!isString) { - LERRORC( - "getSpkCoverage", - fmt::format( - "{}: Expected argument of type 'string'", - ghoul::lua::errorLocation(L) - ) - ); - lua_settop(L, 0); - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); - return 0; - } - - std::string argument = ghoul::lua::value(L, 1); - - bool printValues = isBool ? ghoul::lua::value(L, 2) : false; - buildLuaCoverageStack(L, SpiceManager::ref().spkCoverage(argument), printValues); + ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::spkCoverage"); + std::string argument = ghoul::lua::value(L); + buildLuaCoverageStack(L, SpiceManager::ref().spkCoverage(argument)); return 1; } /** - * getCkCoverage({string, bool(optional)}): + * ckCoverage(string): * Returns the spk coverage for given body */ int ckCoverage(lua_State* L) { - ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::getCkCoverage"); - - const bool isString = (lua_isstring(L, 1) == 1); - const bool isBool = (lua_isboolean(L, 2) == 1); - - if (!isString) { - LERRORC( - "getCkCoverage", - fmt::format( - "{}: Expected argument of type 'string'", - ghoul::lua::errorLocation(L) - ) - ); - lua_settop(L, 0); - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); - return 0; - } - - std::string argument = ghoul::lua::value(L, 1); - bool printValues = isBool ? ghoul::lua::value(L, 2) : false; - buildLuaCoverageStack(L, SpiceManager::ref().ckCoverage(argument), printValues); + ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::ckCoverage"); + std::string argument = ghoul::lua::value(L); + buildLuaCoverageStack(L, SpiceManager::ref().ckCoverage(argument)); return 1; } /** * rotationMatrix({string, string, string}): - * Returns the rotationMatrix for a given body in a frame of reference - * at a specific time. + * Returns the rotationMatrix for a given body in a frame of reference at a specific time */ int rotationMatrix(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 3, "lua::rotationMatrix"); + auto [body, frame, date] = + ghoul::lua::values(L); - const bool isString = (lua_isstring(L, 1) == 1) && - (lua_isstring(L, 2) == 1) && (lua_isstring(L, 3) == 1); - - if (!isString) { - LERRORC( - "rotationMatrix", - fmt::format( - "{}: Expected argument of type 'string' for all three agruments", - ghoul::lua::errorLocation(L) - ) - ); - lua_settop(L, 0); - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); - return 0; - } - - std::string body = ghoul::lua::value(L, 1); - std::string frame = ghoul::lua::value(L, 2); - std::string date = ghoul::lua::value(L, 3); const double ephemerisTime = SpiceManager::ref().ephemerisTimeFromDate(date); - glm::dmat3 rotationMatrix = SpiceManager::ref().frameTransformationMatrix - (body, frame, ephemerisTime); + glm::dmat3 rotationMatrix = SpiceManager::ref().frameTransformationMatrix( + body, + frame, + ephemerisTime + ); ghoul::lua::push(L, 1, rotationMatrix); - return 1; } @@ -273,31 +166,17 @@ int rotationMatrix(lua_State* L) { */ int position(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 4, "lua::position"); + auto [target, observer, frame, date] = + ghoul::lua::values(L); - const bool isString = (lua_isstring(L, 1) == 1) && - (lua_isstring(L, 2) == 1) && - (lua_isstring(L, 3) == 1) && - (lua_isstring(L, 4) == 1); - - if (!isString) { - LERRORC( - "position", - fmt::format( - "{}: Expected argument of type 'string' for all four agruments", - ghoul::lua::errorLocation(L) - ) - ); - lua_settop(L, 0); - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); - return 0; - } - - std::string target = ghoul::lua::value(L, 1); - std::string observer = ghoul::lua::value(L, 2); - std::string frame = ghoul::lua::value(L, 3); - std::string date = ghoul::lua::value(L, 4); const double ephemerisTime = SpiceManager::ref().ephemerisTimeFromDate(date); - glm::dvec3 postion = SpiceManager::ref().targetPosition(target, observer, frame, {}, ephemerisTime); + glm::dvec3 postion = SpiceManager::ref().targetPosition( + target, + observer, + frame, + {}, + ephemerisTime + ); ghoul::lua::push(L, 1, postion); return 1; diff --git a/src/util/time_lua.inl b/src/util/time_lua.inl index 185567f97b..45b62120c1 100644 --- a/src/util/time_lua.inl +++ b/src/util/time_lua.inl @@ -42,46 +42,23 @@ namespace openspace::luascriptfunctions { * Sets the delta time by calling the Time::setDeltaTime method */ int time_setDeltaTime(lua_State* L) { - const int nArguments = lua_gettop(L); - if (nArguments == 1) { - const bool isNumber = (lua_isnumber(L, 1) != 0); - if (!isNumber) { - lua_settop(L, 0); - const char* msg = lua_pushfstring( - L, - "%s expected, got %s", - lua_typename(L, LUA_TNUMBER), - luaL_typename(L, -1) - ); - return luaL_error(L, "bad argument #%d (%s)", 2, msg); - } - const double newDeltaTime = lua_tonumber(L, 1); - global::timeManager->setDeltaTime(newDeltaTime); - } - else { - lua_settop(L, 0); - const char* msg = lua_pushfstring(L, - "Bad number of arguments. Expected 1 or 2."); - return ghoul::lua::luaError(L, fmt::format("bad argument ({})", msg)); - } + ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::time_setDeltaTime"); + double newDeltaTime = ghoul::lua::value(L); - lua_settop(L, 0); - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); + global::timeManager->setDeltaTime(newDeltaTime); return 0; } /** * \ingroup LuaScripts -* interpolateNextDeltaTimeStep(list of numbers): -* Sets the list of discrete delta time steps for the simulation speed. + * interpolateNextDeltaTimeStep(list of numbers): + * Sets the list of discrete delta time steps for the simulation speed. */ int time_setDeltaTimeSteps(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::time_setDeltaTimeSteps"); + ghoul::Dictionary dict = ghoul::lua::value(L); - ghoul::Dictionary dict; - ghoul::lua::luaDictionaryFromState(L, dict); const size_t nItems = dict.size(); - std::vector inputDeltaTimes; inputDeltaTimes.reserve(nItems); @@ -92,61 +69,48 @@ int time_setDeltaTimeSteps(lua_State* L) { inputDeltaTimes.push_back(time); } else { - const char* msg = lua_pushfstring( + return ghoul::lua::luaError( L, "Error setting delta times. Expected list of numbers" ); - return ghoul::lua::luaError(L, fmt::format("bad argument ({})", msg)); } } - lua_pop(L, 1); global::timeManager->setDeltaTimeSteps(inputDeltaTimes); - - lua_settop(L, 0); - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } /** * \ingroup LuaScripts -* setNextDeltaTimeStep(): -* Immediately set the simulation speed to the first delta time step in the list that is -* larger than the current choice of simulation speed, if any. + * setNextDeltaTimeStep(): + * Immediately set the simulation speed to the first delta time step in the list that is + * larger than the current choice of simulation speed, if any. */ int time_setNextDeltaTimeStep(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::time_setNextDeltaTimeStep"); - global::timeManager->setNextDeltaTimeStep(); - - lua_settop(L, 0); - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } /** * \ingroup LuaScripts -* setPreviousDeltaTimeStep(): -* Immediately set the simulation speed to the first delta time step in the list that is -* smaller than the current choice of simulation speed, if any. + * setPreviousDeltaTimeStep(): + * Immediately set the simulation speed to the first delta time step in the list that is + * smaller than the current choice of simulation speed, if any. */ int time_setPreviousDeltaTimeStep(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::time_setPreviousDeltaTimeStep"); - global::timeManager->setPreviousDeltaTimeStep(); - - lua_settop(L, 0); - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } /** * \ingroup LuaScripts -* interpolateNextDeltaTimeStep([interpolationDuration]): -* Interpolate the simulation speed to the next delta time step in the list. If an input -* value is given, the interpolation is done over the specified number of seconds. -* If interpolationDuration is not provided, the interpolation time will be based on the -* `defaultDeltaTimeInterpolationDuration` property of the TimeManager. + * interpolateNextDeltaTimeStep([interpolationDuration]): + * Interpolate the simulation speed to the next delta time step in the list. If an input + * value is given, the interpolation is done over the specified number of seconds. + * If interpolationDuration is not provided, the interpolation time will be based on the + * `defaultDeltaTimeInterpolationDuration` property of the TimeManager. */ int time_interpolateNextDeltaTimeStep(lua_State* L) { ghoul::lua::checkArgumentsAndThrow( @@ -154,40 +118,22 @@ int time_interpolateNextDeltaTimeStep(lua_State* L) { { 0, 1 }, "lua::time_interpolateNextDeltaTimeStep" ); + std::optional interpDuration = ghoul::lua::value>(L); + interpDuration = interpDuration.value_or( + global::timeManager->defaultDeltaTimeInterpolationDuration() + ); - double interpolationDuration = - global::timeManager->defaultDeltaTimeInterpolationDuration(); - - const int nArguments = lua_gettop(L); - if (nArguments == 1) { - const bool durationIsNumber = (lua_isnumber(L, 1) != 0); - if (!durationIsNumber) { - lua_settop(L, 0); - const char* msg = lua_pushfstring( - L, - "%s expected, got %s", - lua_typename(L, LUA_TNUMBER), - luaL_typename(L, -1) - ); - return luaL_error(L, "bad argument #%d (%s)", 1, msg); - } - interpolationDuration = lua_tonumber(L, 1); - } - - global::timeManager->interpolateNextDeltaTimeStep(interpolationDuration); - - lua_settop(L, 0); - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); + global::timeManager->interpolateNextDeltaTimeStep(*interpDuration); return 0; } /** * \ingroup LuaScripts -* interpolatePreviousDeltaTimeStep([interpolationDuration]): -* Interpolate the simulation speed to the previous delta time step in the list. If an -* input value is given, the interpolation is done over the specified number of seconds. -* If interpolationDuration is not provided, the interpolation time will be based on the -* `defaultDeltaTimeInterpolationDuration` property of the TimeManager. + * interpolatePreviousDeltaTimeStep([interpolationDuration]): + * Interpolate the simulation speed to the previous delta time step in the list. If an + * input value is given, the interpolation is done over the specified number of seconds. + * If interpolationDuration is not provided, the interpolation time will be based on the + * `defaultDeltaTimeInterpolationDuration` property of the TimeManager. */ int time_interpolatePreviousDeltaTimeStep(lua_State* L) { ghoul::lua::checkArgumentsAndThrow( @@ -195,111 +141,43 @@ int time_interpolatePreviousDeltaTimeStep(lua_State* L) { { 0, 1 }, "lua::time_interpolatePreviousDeltaTimeStep" ); + std::optional interpDuration = ghoul::lua::value>(L); + interpDuration = interpDuration.value_or( + global::timeManager->defaultDeltaTimeInterpolationDuration() + ); - double interpolationDuration = - global::timeManager->defaultDeltaTimeInterpolationDuration(); - - const int nArguments = lua_gettop(L); - if (nArguments == 1) { - const bool durationIsNumber = (lua_isnumber(L, 1) != 0); - if (!durationIsNumber) { - lua_settop(L, 0); - const char* msg = lua_pushfstring( - L, - "%s expected, got %s", - lua_typename(L, LUA_TNUMBER), - luaL_typename(L, -1) - ); - return luaL_error(L, "bad argument #%d (%s)", 1, msg); - } - interpolationDuration = lua_tonumber(L, 1); - } - - global::timeManager->interpolatePreviousDeltaTimeStep(interpolationDuration); - - lua_settop(L, 0); - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); + global::timeManager->interpolatePreviousDeltaTimeStep(*interpDuration); return 0; } /** -* \ingroup LuaScripts -* time_interpolateDeltaTime(number [, number]): -* Interpolates the delta time by calling the Time::interpolateDeltaTime method -* Same behaviour as setDeltaTime, but interpolates the delta time. -* If interpolationDuration is not provided, the interpolation time will be based on the -* `defaultDeltaTimeInterpolationDuration` property of the TimeManager. -*/ + * \ingroup LuaScripts + * time_interpolateDeltaTime(number [, number]): + * Interpolates the delta time by calling the Time::interpolateDeltaTime method + * Same behaviour as setDeltaTime, but interpolates the delta time. + * If interpolationDuration is not provided, the interpolation time will be based on the + * `defaultDeltaTimeInterpolationDuration` property of the TimeManager. + */ int time_interpolateDeltaTime(lua_State* L) { - const int nArguments = lua_gettop(L); - if (nArguments == 2) { - const bool deltaIsNumber = (lua_isnumber(L, 1) != 0); - if (!deltaIsNumber) { - lua_settop(L, 0); - const char* msg = lua_pushfstring( - L, - "%s expected, got %s", - lua_typename(L, LUA_TNUMBER), - luaL_typename(L, -1) - ); - return luaL_error(L, "bad argument #%d (%s)", 2, msg); - } + ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::time_interpolateDeltaTime"); + auto [deltaTime, interpDuration] = + ghoul::lua::values>(L); + interpDuration = interpDuration.value_or( + global::timeManager->defaultDeltaTimeInterpolationDuration() + ); - const bool durationIsNumber = (lua_isnumber(L, 2) != 0); - if (!durationIsNumber) { - lua_settop(L, 0); - const char* msg = lua_pushfstring( - L, - "%s expected, got %s", - lua_typename(L, LUA_TNUMBER), - luaL_typename(L, -1) - ); - return luaL_error(L, "bad argument #%d (%s)", 2, msg); - } - - const double interpolationDuration = lua_tonumber(L, 2); - const double newDeltaTime = lua_tonumber(L, 1); - global::timeManager->interpolateDeltaTime(newDeltaTime, interpolationDuration); - } - else if (nArguments == 1) { - const bool isNumber = (lua_isnumber(L, 1) != 0); - if (!isNumber) { - lua_settop(L, 0); - const char* msg = lua_pushfstring( - L, - "%s expected, got %s", - lua_typename(L, LUA_TNUMBER), - luaL_typename(L, -1) - ); - return luaL_error(L, "bad argument #%d (%s)", 2, msg); - } - const double newDeltaTime = lua_tonumber(L, 1); - global::timeManager->interpolateDeltaTime( - newDeltaTime, - global::timeManager->defaultDeltaTimeInterpolationDuration() - ); - } - else { - lua_settop(L, 0); - const char* msg = lua_pushfstring(L, - "Bad number of arguments. Expected 1 or 2."); - return ghoul::lua::luaError(L, fmt::format("bad argument ({})", msg)); - } - - lua_settop(L, 0); - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); + global::timeManager->interpolateDeltaTime(deltaTime, *interpDuration); return 0; } - /** * \ingroup LuaScripts * deltaTime(): * Returns the delta time by calling the Time::deltaTime method */ int time_deltaTime(lua_State* L) { - lua_pushnumber(L, global::timeManager->deltaTime()); - ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack"); + ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::time_deltaTime"); + ghoul::lua::push(L, global::timeManager->deltaTime()); return 1; } @@ -309,56 +187,51 @@ int time_deltaTime(lua_State* L) { * Toggles pause, i.e. setting the delta time to 0 and restoring it afterwards */ int time_togglePause(lua_State* L) { - const int nArguments = lua_gettop(L); - - if (nArguments == 0) { - global::timeManager->setPause(!global::timeManager->isPaused()); - } - else { - lua_settop(L, 0); - return luaL_error( - L, - "bad number of arguments, expected 0, got %i", - nArguments - ); - } - - lua_settop(L, 0); - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); + ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::time_togglePause"); + global::timeManager->setPause(!global::timeManager->isPaused()); return 0; } /** -* \ingroup LuaScripts -* interpolateTogglePause([interpolationDuration]): -* Same behaviour as togglePause, but with interpolation. -* If no interpolation duration is provided, the interpolation time will be based on the -* `defaultPauseInterpolationDuration` and `defaultUnpauseInterpolationDuration` properties -* of the TimeManager. -*/ + * \ingroup LuaScripts + * interpolateTogglePause([interpolationDuration]): + * Same behaviour as togglePause, but with interpolation. + * If no interpolation duration is provided, the interpolation time will be based on the + * `defaultPauseInterpolationDuration` and `defaultUnpauseInterpolationDuration` + * properties of the TimeManager. + */ int time_interpolateTogglePause(lua_State* L) { - const int nArguments = lua_gettop(L); + ghoul::lua::checkArgumentsAndThrow(L, { 0, 1 }, "lua::time_interpolateTogglePause"); + std::optional interpDuration = ghoul::lua::value>(L); + interpDuration = interpDuration.value_or( + global::timeManager->isPaused() ? + global::timeManager->defaultUnpauseInterpolationDuration() : + global::timeManager->defaultPauseInterpolationDuration() + ); - if (nArguments == 1) { - const bool isNumber = (lua_isnumber(L, 1) != 0); - if (!isNumber) { - const char* msg = lua_pushfstring( - L, - "%s expected, got %s", - lua_typename(L, LUA_TNUMBER), - luaL_typename(L, -1) - ); - return luaL_error(L, "bad argument #%d (%s)", 1, msg); - } + global::timeManager->interpolatePause( + !global::timeManager->isPaused(), + *interpDuration + ); + return 0; +} - const double interpolationDuration = lua_tonumber(L, 1); - - global::timeManager->interpolatePause( - !global::timeManager->isPaused(), - interpolationDuration - ); +/** + * \ingroup LuaScripts + * time_pauseToggleViaKeyboard(): + * This allows for a keypress (via keybinding) to have dual functionality. In normal +* operational mode it will behave just like time_interpolateTogglePause, but + * during playback of a session recording it will pause the playback without manipulating + * the delta time. + */ +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); } - else if (nArguments == 0) { + else { const bool pause = !global::timeManager->isPaused(); global::timeManager->interpolatePause(pause, pause ? @@ -366,56 +239,6 @@ int time_interpolateTogglePause(lua_State* L) { global::timeManager->defaultUnpauseInterpolationDuration() ); } - else { - lua_settop(L, 0); - return luaL_error( - L, - "bad number of arguments, expected 0 or 1, got %i", - nArguments - ); - } - - lua_settop(L, 0); - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); - return 0; -} - -/** -* \ingroup LuaScripts -* time_pauseToggleViaKeyboard(): -* This allows for a keypress (via keybinding) to have dual functionality. In normal -* operational mode it will behave just like time_interpolateTogglePause, but -* during playback of a session recording it will pause the playback without manipulating -* the delta time. -*/ -int time_pauseToggleViaKeyboard(lua_State* L) { - const int nArguments = lua_gettop(L); - - if (nArguments == 0) { - if (global::sessionRecording->isPlayingBack()) { - bool isPlaybackPaused = global::sessionRecording->isPlaybackPaused(); - global::sessionRecording->setPlaybackPause(!isPlaybackPaused); - } - else { - const bool pause = !global::timeManager->isPaused(); - global::timeManager->interpolatePause(pause, - pause ? - global::timeManager->defaultPauseInterpolationDuration() : - global::timeManager->defaultUnpauseInterpolationDuration() - ); - } - } - else { - lua_settop(L, 0); - return luaL_error( - L, - "bad number of arguments, expected 0 or 1, got %i", - nArguments - ); - } - - lua_settop(L, 0); - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); return 0; } @@ -425,76 +248,34 @@ int time_pauseToggleViaKeyboard(lua_State* L) { * Toggles a pause function i.e. setting the delta time to 0 and restoring it afterwards */ int time_setPause(lua_State* L) { - const int nArguments = lua_gettop(L); + ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::time_setPause"); + bool pause = ghoul::lua::value(L); - if (nArguments == 1) { - const bool pause = lua_toboolean(L, 1) == 1; - global::timeManager->setPause(pause); - } - else { - lua_settop(L, 0); - return luaL_error( - L, - "bad number of arguments, expected 1, got %i", - nArguments - ); - } - - lua_settop(L, 0); - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); + global::timeManager->setPause(pause); return 0; } /** -* \ingroup LuaScripts -* interpolateTogglePause(bool [, interpolationDuration]): -* Same behaviour as setPause, but with interpolation. -* If no interpolation duration is provided, the interpolation time will be based on the -* `defaultPauseInterpolationDuration` and `defaultUnpauseInterpolationDuration` properties -* of the TimeManager. -*/ + * \ingroup LuaScripts + * interpolateTogglePause(bool [, interpolationDuration]): + * Same behaviour as setPause, but with interpolation. + * If no interpolation duration is provided, the interpolation time will be based on the + * `defaultPauseInterpolationDuration` and `defaultUnpauseInterpolationDuration` + * properties of the TimeManager. + */ int time_interpolatePause(lua_State* L) { - const int nArguments = lua_gettop(L); + ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::time_interpolatePause"); + auto [pause, interpDuration] = ghoul::lua::values>(L); + interpDuration = interpDuration.value_or( + pause ? + global::timeManager->defaultPauseInterpolationDuration() : + global::timeManager->defaultUnpauseInterpolationDuration() + ); - if (nArguments == 2) { - const bool isNumber = (lua_isnumber(L, 2) != 0); - if (!isNumber) { - lua_settop(L, 0); - const char* msg = lua_pushfstring( - L, - "%s expected, got %s", - lua_typename(L, LUA_TNUMBER), - luaL_typename(L, -1) - ); - return luaL_error(L, "bad argument #%d (%s)", 2, msg); - } - const double interpolationDuration = lua_tonumber(L, 2); - const bool pause = lua_toboolean(L, 1) == 1; - global::timeManager->interpolatePause(pause, interpolationDuration); - } - else if (nArguments == 1) { - const bool pause = lua_toboolean(L, 1) == 1; - global::timeManager->interpolatePause(pause, - pause ? - global::timeManager->defaultPauseInterpolationDuration() : - global::timeManager->defaultUnpauseInterpolationDuration() - ); - } - else { - lua_settop(L, 0); - return luaL_error( - L, - "bad number of arguments, expected 1 or 2, got %i", - nArguments - ); - } - - lua_settop(L, 0); - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); + global::timeManager->interpolatePause(pause, *interpDuration); return 0; } - /** * \ingroup LuaScripts * setTime({number, string}): @@ -505,187 +286,76 @@ int time_interpolatePause(lua_State* L) { * is called */ int time_setTime(lua_State* L) { - const bool isFunction = (lua_isfunction(L, -1) != 0); - if (isFunction) { - // If the top of the stack is a function, it is ourself - const char* msg = lua_pushfstring(L, "method called without argument"); - return ghoul::lua::luaError(L, fmt::format("bad argument #1 ({})", msg)); - } + ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::time_setTime"); + std::variant time = + ghoul::lua::value>(L); - const bool isNumber = (lua_isnumber(L, 1) != 0); - const bool isString = (lua_isstring(L, 1) != 0); - if (!isNumber && !isString) { - const char* msg = lua_pushfstring( - L, - "%s or %s expected, got %s", - lua_typename(L, LUA_TNUMBER), - lua_typename(L, LUA_TSTRING), - luaL_typename(L, -1) - ); - return ghoul::lua::luaError(L, fmt::format("bad argument #1 ({})", msg)); - } - - const int nArguments = lua_gettop(L); - if (nArguments == 1) { - if (isNumber) { - double value = lua_tonumber(L, 1); - global::timeManager->setTimeNextFrame(Time(value)); - return 0; - } - if (isString) { - const char* time = lua_tostring(L, 1); - global::timeManager->setTimeNextFrame(Time(Time::convertTime(time))); - return 0; - } - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); + double t; + if (std::holds_alternative(time)) { + t = Time::convertTime(std::get(time)); } else { - return luaL_error( - L, - "bad number of arguments, expected 1 or 2, got %i", - nArguments - ); + t = std::get(time); } + + global::timeManager->setTimeNextFrame(Time(t)); return 0; } - /** -* \ingroup LuaScripts -* interpolateTime({number, string} [, interpolationDuration]): -* Interpolates the simulation time to the passed value. -* Same behaviour as setTime, but interpolates time. -* If interpolationDuration is not provided, the interpolation time will be based on the -* `defaultTimeInterpolationDuration` property of the TimeManager. -*/ + * \ingroup LuaScripts + * interpolateTime({number, string} [, interpolationDuration]): + * Interpolates the simulation time to the passed value. + * Same behaviour as setTime, but interpolates time. + * If interpolationDuration is not provided, the interpolation time will be based on the + * `defaultTimeInterpolationDuration` property of the TimeManager. + */ int time_interpolateTime(lua_State* L) { - const bool isFunction = (lua_isfunction(L, -1) != 0); - if (isFunction) { - // If the top of the stack is a function, it is ourself - const char* msg = lua_pushfstring(L, "method called without argument"); - return ghoul::lua::luaError(L, fmt::format("bad argument #1 ({})", msg)); - } + ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::time_interpolateTime"); + auto [time, interpDuration] = + ghoul::lua::values, std::optional>(L); + interpDuration = interpDuration.value_or( + global::timeManager->defaultTimeInterpolationDuration() + ); - const bool isNumber = (lua_isnumber(L, 1) != 0); - const bool isString = (lua_isstring(L, 1) != 0); - if (!isNumber && !isString) { - const char* msg = lua_pushfstring( - L, - "%s or %s expected, got %s", - lua_typename(L, LUA_TNUMBER), - lua_typename(L, LUA_TSTRING), - luaL_typename(L, -1) - ); - return ghoul::lua::luaError(L, fmt::format("bad argument #1 ({})", msg)); - } - - if (lua_gettop(L) == 1) { - if (isNumber) { - double value = lua_tonumber(L, 1); - global::timeManager->interpolateTime( - value, - global::timeManager->defaultTimeInterpolationDuration() - ); - return 0; - } - if (isString) { - const char* time = lua_tostring(L, 1); - global::timeManager->interpolateTime( - Time::convertTime(time), - global::timeManager->defaultTimeInterpolationDuration() - ); - return 0; - } - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); + double targetTime; + if (std::holds_alternative(time)) { + targetTime = Time::convertTime(std::get(time)); } else { - int nArguments = lua_gettop(L); - if (nArguments != 2) { - return luaL_error( - L, - "bad number of arguments, expected 1 or 2, got %i", - nArguments - ); - } + targetTime = std::get(time); + } - double targetTime; - if (lua_isnumber(L, 1)) { - targetTime = lua_tonumber(L, 1); - } - else { - targetTime = Time::convertTime(lua_tostring(L, 1)); - } - - const double duration = lua_tonumber(L, 2); - if (duration > 0) { - global::timeManager->interpolateTime(targetTime, duration); - } - else { - global::timeManager->setTimeNextFrame(Time(targetTime)); - } + if (*interpDuration > 0) { + global::timeManager->interpolateTime(targetTime, *interpDuration); + } + else { + global::timeManager->setTimeNextFrame(Time(targetTime)); } return 0; } - /** -* \ingroup LuaScripts -* interpolateTimeRelative(number [, interpolationDuration]): -* Interpolates the simulation time relatively, based on the specified number of seconds. -* If interpolationDuration is not provided, the interpolation time will be based on the -* `defaultTimeInterpolationDuration` property of the TimeManager. + * \ingroup LuaScripts + * interpolateTimeRelative(number [, interpolationDuration]): + * Interpolates the simulation time relatively, based on the specified number of seconds. + * If interpolationDuration is not provided, the interpolation time will be based on the + * `defaultTimeInterpolationDuration` property of the TimeManager. */ int time_interpolateTimeRelative(lua_State* L) { - const bool isFunction = (lua_isfunction(L, -1) != 0); - if (isFunction) { - // If the top of the stack is a function, it is ourself - const char* msg = lua_pushfstring(L, "method called without argument"); - return ghoul::lua::luaError(L, fmt::format("bad argument #1 ({})", msg)); - } + ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::time_interpolateTimeRelative"); + auto [delta, interpDuration] = ghoul::lua::values>(L); + interpDuration = interpDuration.value_or( + global::timeManager->defaultTimeInterpolationDuration() + ); - const bool isNumber = (lua_isnumber(L, 1) != 0); - if (!isNumber) { - const char* msg = lua_pushfstring( - L, - "%s or expected, got %s", - lua_typename(L, LUA_TNUMBER), - luaL_typename(L, -1) - ); - return ghoul::lua::luaError(L, fmt::format("bad argument #1 ({})", msg)); - } - - if (lua_gettop(L) == 1) { - double delta = lua_tonumber(L, 1); - global::timeManager->interpolateTimeRelative( - delta, - global::timeManager->defaultTimeInterpolationDuration() - ); - ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack"); - - return 0; + if (*interpDuration > 0) { + global::timeManager->interpolateTimeRelative(delta, *interpDuration); } else { - int nArguments = lua_gettop(L); - if (nArguments != 2) { - return luaL_error( - L, - "bad number of arguments, expected 1 or 2, got %i", - nArguments - ); - } - - double delta; - delta = lua_tonumber(L, 1); - - const double duration = lua_tonumber(L, 2); - if (duration > 0) { - global::timeManager->interpolateTimeRelative(delta, duration); - } - else { - global::timeManager->setTimeNextFrame( - Time(global::timeManager->time().j2000Seconds() + delta) - ); - } + global::timeManager->setTimeNextFrame( + Time(global::timeManager->time().j2000Seconds() + delta) + ); } return 0; } @@ -697,8 +367,8 @@ int time_interpolateTimeRelative(lua_State* L) { * It is returned by calling the Time::currentTime method. */ int time_currentTime(lua_State* L) { + ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::time_currentTime"); ghoul::lua::push(L, global::timeManager->time().j2000Seconds()); - ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack"); return 1; } @@ -709,8 +379,8 @@ int time_currentTime(lua_State* L) { * timezone by calling the Time::UTC method */ int time_currentTimeUTC(lua_State* L) { + ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::time_currentTimeUTC"); ghoul::lua::push(L, global::timeManager->time().UTC()); - ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack"); return 1; } @@ -720,45 +390,44 @@ int time_currentTimeUTC(lua_State* L) { * Returns the current wallclock time as a structured ISO 8601 string in the UTC timezone. */ int time_currentWallTime(lua_State* L) { + ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::time_currentWallTime"); + std::time_t t = std::time(nullptr); std::tm* utcTime = std::gmtime(&t); - ghoul_assert(utcTime, "Conversion to UTC failed"); std::string time = fmt::format( "{:04d}-{:02d}-{:02d}T{:02d}:{:02d}:{:02d}", - utcTime->tm_year + 1900, - utcTime->tm_mon + 1, - utcTime->tm_mday, - utcTime->tm_hour, - utcTime->tm_min, - utcTime->tm_sec + utcTime->tm_year + 1900, utcTime->tm_mon + 1, utcTime->tm_mday, + utcTime->tm_hour, utcTime->tm_min, utcTime->tm_sec ); - lua_pushstring(L, time.c_str()); - ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack"); + ghoul::lua::push(L, time); return 1; } int time_advancedTime(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::time_advanceTime"); + auto [base, change] = + ghoul::lua::values< + std::variant, std::variant + >(L); double j2000Seconds = -1.0; - Time t; bool usesISO = false; - if (lua_type(L, 1) == LUA_TSTRING) { - j2000Seconds = Time::convertTime(ghoul::lua::value(L, 1)); + if (std::holds_alternative(base)) { + j2000Seconds = Time::convertTime(std::get(base)); usesISO = true; } - else if (lua_type(L, 1) == LUA_TNUMBER) { - j2000Seconds = ghoul::lua::value(L, 1); + else { + j2000Seconds = std::get(base); usesISO = false; } double dt = 0.0; - if (lua_type(L, 2) == LUA_TNUMBER) { - dt = ghoul::lua::value(L, 2); + if (std::holds_alternative(change)) { + dt = std::get(change); } else { - std::string modifier = ghoul::lua::value(L, 2); + std::string modifier = std::get(change); if (modifier.empty()) { return ghoul::lua::luaError(L, "Modifier string must not be empty"); } @@ -770,8 +439,7 @@ int time_advancedTime(lua_State* L) { } auto it = std::find_if( - modifier.begin(), - modifier.end(), + modifier.begin(), modifier.end(), [](unsigned char c) { const bool digit = std::isdigit(c) != 0; const bool isDot = c == '.'; @@ -784,29 +452,14 @@ int time_advancedTime(lua_State* L) { 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; - } + 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) - ); + return ghoul::lua::luaError(L, fmt::format("Unknown unit '{}'", unitName)); } dt = convertTime(value, unit, TimeUnit::Second); @@ -815,8 +468,6 @@ int time_advancedTime(lua_State* L) { } } - lua_pop(L, 2); - if (usesISO) { ghoul::lua::push(L, Time(j2000Seconds + dt).ISO8601()); }