Merge remote-tracking branch 'origin/master' into feature/use-renamed-cmake-copy-macro

This commit is contained in:
Alexander Bock
2017-06-06 11:52:03 -04:00
15 changed files with 519 additions and 116 deletions

View File

@@ -55,8 +55,24 @@ struct LuaLibrary {
};
/// The name of the library
std::string name;
/// The list of all functions for this library
/// The list of all C-based callback functions for this library
std::vector<Function> functions;
/// A list of script files that are executed for each Lua state
std::vector<std::string> scripts;
/// This struct contains information about a function or constant that is defined in
/// a Lua script
struct Documentation {
/// The name of the function/variable
std::string name;
/// The description of the parameters for a function
std::string parameter;
/// The description of the function/variable
std::string description;
};
/// The list of documentations will be populated automatically by parsing the Lua
/// scripts
std::vector<Documentation> documentations;
/// Comparison function that compares two LuaLibrary%s name
bool operator<(const LuaLibrary& rhs) const;

View File

@@ -101,8 +101,8 @@ public:
static std::string OpenSpaceLibraryName;
private:
bool registerLuaLibrary(lua_State* state, const LuaLibrary& library);
void addLibraryFunctions(lua_State* state, const LuaLibrary& library, bool replace);
bool registerLuaLibrary(lua_State* state, LuaLibrary& library);
void addLibraryFunctions(lua_State* state, LuaLibrary& library, bool replace);
bool isLibraryNameAllowed(lua_State* state, const std::string& name);
@@ -112,7 +112,8 @@ private:
std::string generateJson() const override;
ghoul::lua::LuaState _state;
std::set<LuaLibrary> _registeredLibraries;
std::vector<LuaLibrary> _registeredLibraries;
//sync variables
std::mutex _mutex;

View File

@@ -111,4 +111,14 @@ globebrowsing::cache::MemoryAwareTileCache* GlobeBrowsingModule::tileCache() {
return _tileCache.get();
}
scripting::LuaLibrary GlobeBrowsingModule::luaLibrary() const {
return {
"globebrowsing",
{},
{
"${MODULE_GLOBEBROWSING}/scripts/layer_support.lua"
}
};
}
} // namespace openspace

View File

@@ -38,14 +38,18 @@ namespace cache {
class GlobeBrowsingModule : public OpenSpaceModule {
public:
static const std::string name;
GlobeBrowsingModule();
globebrowsing::cache::MemoryAwareTileCache* tileCache();
static const std::string name;
scripting::LuaLibrary luaLibrary() const override;
protected:
void internalInitialize() override;
private:
std::unique_ptr<globebrowsing::cache::MemoryAwareTileCache> _tileCache;
};

View File

@@ -0,0 +1,37 @@
openspace.globebrowsing.documentation = {
{
Name = "createTextureLayers",
Arguments = "table",
Documentation = "Creates a table used in the 'ColorLayers', 'GrayScaleLayers', or 'GrayScaleColorOverlays' of a RenderableGlobe."
},
{
Name = "createHeightLayers",
Arguments = "table",
Documentation = "Creates a table used in the 'HeightLayers' of a RenderableGlobe."
}
}
-- Creates a table used in the 'ColorLayers', 'GrayScaleLayers', or 'GrayScaleColorOverlays'
-- of a RenderableGlobe
-- Usage:
-- table.unpack(openspace.globebrowsing.createTextureLayers(p))
-- where p is an array that contains tables with 'Name' and 'Texture' values
openspace.globebrowsing.createTextureLayers = function (patches)
result = {}
for k,v in pairs(patches) do
table.insert(result, { Name = v["Name"], FilePath = v["Texture"] })
end
return result
end
-- Creates a table used in the 'HeightLayers' of a RenderableGlobe
-- Usage:
-- table.unpack(openspace.globebrowsing.openspace.globebrowsing.createHeightLayers(p))
-- where p is an array that contains tables with 'Name' and 'Height' values
openspace.globebrowsing.createHeightLayers = function (patches)
result = {}
for k,v in pairs(patches) do
table.insert(result, { Name = v["Name"], FilePath = v["Height"], TilePixelSize = 90, DoPreProcessing = true })
end
return result
end

View File

@@ -27,6 +27,7 @@ include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake)
set(HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/include/gui.h
${CMAKE_CURRENT_SOURCE_DIR}/include/guicomponent.h
${CMAKE_CURRENT_SOURCE_DIR}/include/guifilepathcomponent.h
${CMAKE_CURRENT_SOURCE_DIR}/include/guihelpcomponent.h
${CMAKE_CURRENT_SOURCE_DIR}/include/guiorigincomponent.h
${CMAKE_CURRENT_SOURCE_DIR}/include/guiperformancecomponent.h
@@ -42,6 +43,7 @@ set(SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/src/gui.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/gui_lua.inl
${CMAKE_CURRENT_SOURCE_DIR}/src/guicomponent.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/guifilepathcomponent.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/guihelpcomponent.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/guiorigincomponent.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/guiperformancecomponent.cpp

View File

@@ -26,6 +26,7 @@
#define __OPENSPACE_MODULE_ONSCREENGUI___GUI___H__
#include <modules/onscreengui/include/guicomponent.h>
#include <modules/onscreengui/include/guifilepathcomponent.h>
#include <modules/onscreengui/include/guihelpcomponent.h>
#include <modules/onscreengui/include/guiperformancecomponent.h>
#include <modules/onscreengui/include/guipropertycomponent.h>
@@ -65,6 +66,7 @@ public:
//protected:
GuiHelpComponent _help;
GuiFilePathComponent _filePath;
GuiOriginComponent _origin;
GuiPerformanceComponent _performance;
GuiPropertyComponent _globalProperty;

View File

@@ -0,0 +1,43 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2017 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_ONSCREENGUI___GUIFILEPATHCOMPONENT___H__
#define __OPENSPACE_MODULE_ONSCREENGUI___GUIFILEPATHCOMPONENT___H__
#include <modules/onscreengui/include/guicomponent.h>
namespace openspace {
namespace gui {
class GuiFilePathComponent : public GuiComponent {
public:
GuiFilePathComponent();
void render() override;
};
} // namespace gui
} // namespace openspace
#endif // __OPENSPACE_MODULE_ONSCREENGUI___GUIFILEPATHCOMPONENT___H__

View File

@@ -210,12 +210,9 @@ void addScreenSpaceRenderable(std::string texturePath) {
return;
}
texturePath = absPath(texturePath);
texturePath = FileSys.convertPathSeparator(texturePath, '/');
std::string luaTable =
"{Type = 'ScreenSpaceImage', TexturePath = '" + texturePath + "' }";
std::string script = "openspace.registerScreenSpaceRenderable(" + luaTable + ");";
const std::string luaTable =
"{Type = 'ScreenSpaceImage', TexturePath = openspace.absPath('" + texturePath + "') }";
const std::string script = "openspace.registerScreenSpaceRenderable(" + luaTable + ");";
OsEng.scriptEngine().queueScript(script, openspace::scripting::ScriptEngine::RemoteScripting::Yes);
}
} // namespace
@@ -238,6 +235,7 @@ GUI::GUI()
addPropertySubOwner(_property);
addPropertySubOwner(_screenSpaceProperty);
addPropertySubOwner(_virtualProperty);
addPropertySubOwner(_filePath);
addPropertySubOwner(_time);
addPropertySubOwner(_iswa);
}
@@ -321,6 +319,7 @@ void GUI::initialize() {
_globalProperty.initialize();
_globalProperty.setHasRegularProperties(true);
_virtualProperty.initialize();
_filePath.initialize();
_performance.initialize();
_help.initialize();
_parallel.initialize();
@@ -337,6 +336,7 @@ void GUI::deinitialize() {
_globalProperty.deinitialize();
_screenSpaceProperty.deinitialize();
_virtualProperty.deinitialize();
_filePath.deinitialize();
_property.deinitialize();
delete iniFileBuffer;
@@ -488,6 +488,9 @@ void GUI::endFrame() {
if (_iswa.isEnabled()) {
_iswa.render();
}
if (_filePath.isEnabled()) {
_filePath.render();
}
}
ImGui::Render();
@@ -583,6 +586,10 @@ void GUI::render() {
ImGui::Checkbox("Virtual Properties", &virtualProperty);
_virtualProperty.setEnabled(virtualProperty);
bool filePath = _filePath.isEnabled();
ImGui::Checkbox("File Paths", &filePath);
_filePath.setEnabled(filePath);
#ifdef OPENSPACE_MODULE_ISWA_ENABLED
bool iswa = _iswa.isEnabled();
ImGui::Checkbox("iSWA", &iswa);

View File

@@ -0,0 +1,62 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2017 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/onscreengui/include/guifilepathcomponent.h>
#include <ghoul/filesystem/filesystem.h>
#include "imgui.h"
namespace openspace {
namespace gui {
GuiFilePathComponent::GuiFilePathComponent()
: GuiComponent("File Path")
{}
void GuiFilePathComponent::render() {
bool v = _isEnabled;
ImGui::Begin("File Path", &v);
ImGui::Text(
"%s",
"These are file paths registered in the current OpenSpace instance."
);
ImGui::Separator();
ImGui::Columns(2);
ImGui::Separator();
std::vector<std::string> tokens = FileSys.tokens();
for (const std::string& t : tokens) {
ImGui::Text("%s", t.c_str());
ImGui::NextColumn();
ImGui::Text("%s", absPath(t).c_str());
ImGui::NextColumn();
ImGui::Separator();
}
ImGui::End();
}
} // gui
} // openspace

View File

@@ -9,8 +9,6 @@ return {
-- A regular 1280x720 window
SGCTConfig = sgct.config.single{},
-- SGCTConfig = sgct.config.single{res={1920, 1080}, shared=true},
-- A regular 1920x1080 window
-- SGCTConfig = sgct.config.single{1920, 1080},
@@ -20,6 +18,10 @@ return {
-- A 4k fisheye rendering in a 1024x1024 window
-- SGCTConfig = sgct.config.fisheye{1024, 1024, res={4096, 4096}, quality="2k", tilt=27},
-- Streaming OpenSpace via Spout to OBS
-- SGCTConfig = sgct.config.single{2560, 1440, shared=true, name="WV_OBS_SPOUT1"},
--SGCTConfig = "${SGCT}/openvr_oculusRiftCv1.xml",
--SGCTConfig = "${SGCT}/openvr_htcVive.xml",

View File

@@ -311,7 +311,7 @@ void RenderEngine::deinitialize() {
}
void RenderEngine::updateScene() {
const Time& currentTime = OsEng.timeManager().time();
const Time& currentTime = OsEng.timeManager().time();
_scene->update({
{ glm::dvec3(0), glm::dmat3(1), 1.0 },
currentTime,
@@ -485,9 +485,9 @@ void RenderEngine::renderShutdownInformation(float timer, float fullTime) {
}
void RenderEngine::postDraw() {
Time& currentTime = OsEng.timeManager().time();
Time& currentTime = OsEng.timeManager().time();
if (currentTime.timeJumped()) {
currentTime.setTimeJumped(false);
currentTime.setTimeJumped(false);
}
if (_shouldTakeScreenshot) {

View File

@@ -76,8 +76,8 @@ void ScriptEngine::initialize() {
addBaseLibrary();
LDEBUG("Initializing Lua state");
initializeLuaState(_state);
LDEBUG("Remapping Print functions");
remapPrintFunction();
//LDEBUG("Remapping Print functions");
//remapPrintFunction();
}
void ScriptEngine::deinitialize() {}
@@ -88,7 +88,7 @@ void ScriptEngine::initializeLuaState(lua_State* state) {
lua_setglobal(state, OpenSpaceLibraryName.c_str());
LDEBUG("Add OpenSpace modules");
for (const LuaLibrary& lib : _registeredLibraries) {
for (LuaLibrary& lib : _registeredLibraries) {
registerLuaLibrary(state, lib);
}
}
@@ -106,7 +106,8 @@ void ScriptEngine::addLibrary(LuaLibrary library) {
if (it == _registeredLibraries.end()) {
// If not, we can add it after we sorted it
std::sort(library.functions.begin(), library.functions.end(), sortFunc);
_registeredLibraries.insert(std::move(library));
_registeredLibraries.push_back(std::move(library));
std::sort(_registeredLibraries.begin(), _registeredLibraries.end());
}
else {
// otherwise, we merge the libraries
@@ -127,15 +128,21 @@ void ScriptEngine::addLibrary(LuaLibrary library) {
"' has been defined twice");
return;
}
else
else {
merged.functions.push_back(fun);
}
}
for (const std::string& script : library.scripts) {
merged.scripts.push_back(script);
}
_registeredLibraries.erase(it);
// Sort the merged library before inserting it
std::sort(merged.functions.begin(), merged.functions.end(), sortFunc);
_registeredLibraries.insert(std::move(merged));
_registeredLibraries.push_back(std::move(merged));
std::sort(_registeredLibraries.begin(), _registeredLibraries.end());
}
}
@@ -345,13 +352,11 @@ bool ScriptEngine::isLibraryNameAllowed(lua_State* state, const std::string& nam
return result;
}
void ScriptEngine::addLibraryFunctions(lua_State* state, const LuaLibrary& library, bool replace) {
assert(state);
void ScriptEngine::addLibraryFunctions(lua_State* state, LuaLibrary& library, bool replace) {
ghoul_assert(state, "State must not be nullptr");
for (LuaLibrary::Function p : library.functions) {
if (!replace) {
//ghoul::lua::logStack(_state);
lua_getfield(state, -1, p.name.c_str());
//ghoul::lua::logStack(_state);
const bool isNil = lua_isnil(state, -1);
if (!isNil) {
LERROR("Function name '" << p.name << "' was already assigned");
@@ -359,13 +364,49 @@ void ScriptEngine::addLibraryFunctions(lua_State* state, const LuaLibrary& libra
}
lua_pop(state, 1);
}
//ghoul::lua::logStack(_state);
lua_pushstring(state, p.name.c_str());
//ghoul::lua::logStack(_state);
lua_pushcfunction(state, p.function);
//ghoul::lua::logStack(_state);
lua_settable(state, TableOffset);
//ghoul::lua::logStack(_state);
}
for (const std::string& script : library.scripts) {
// First we run the script to set its values in the current state
ghoul::lua::runScriptFile(state, absPath(script));
library.documentations.clear();
// Then, we extract the documentation information from the file
lua_pushstring(state, "documentation");
lua_gettable(state, -2);
if (lua_isnil(state, -1)) {
LERROR(
"Module '" << library.name << "' did not provide a documentation in " <<
"script file '" << script << "'");
}
else {
lua_pushnil(state);
while (lua_next(state, -2)) {
lua_pushstring(state, "Name");
lua_gettable(state, -2);
const std::string name = lua_tostring(state, -1);
lua_pop(state, 1);
lua_pushstring(state, "Arguments");
lua_gettable(state, -2);
const std::string arguments = lua_tostring(state, -1);
lua_pop(state, 1);
lua_pushstring(state, "Documentation");
lua_gettable(state, -2);
const std::string documentation = lua_tostring(state, -1);
lua_pop(state, 1);
lua_pop(state, 1);
library.documentations.push_back({ name, arguments, documentation });
}
lua_pop(state, 1);
}
}
}
@@ -422,12 +463,48 @@ void ScriptEngine::addBaseLibrary() {
"Returns the absolute path to the passed path, resolving path tokens as "
"well as resolving relative paths"
},
{
"fileExists",
&luascriptfunctions::fileExists,
"string",
"Checks whether the provided file exists."
},
{
"setPathToken",
&luascriptfunctions::setPathToken,
"string, string",
"Registers a new path token provided by the first argument to the path "
"provided in the second argument"
},
{
"walkDirectory",
&luascriptfunctions::walkDirectory,
"string [bool, bool]",
"Walks a directory and returns all contents (files and directories) 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 third "
"argument determines whether the table that is returned is sorted."
},
{
"walkDirectoryFiles",
&luascriptfunctions::walkDirectoryFiles,
"string [bool, bool]",
"Walks a directory and returns the files 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 third argument determines "
"whether the table that is returned is sorted."
},
{
"walkDirectoryFolder",
&luascriptfunctions::walkDirectoryFolder,
"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 third "
"argument determines whether the table that is returned is sorted."
}
}
};
@@ -446,42 +523,37 @@ void ScriptEngine::remapPrintFunction() {
//ghoul::lua::logStack(_state);
}
bool ScriptEngine::registerLuaLibrary(lua_State* state, const LuaLibrary& library) {
bool ScriptEngine::registerLuaLibrary(lua_State* state, LuaLibrary& library) {
ghoul_assert(state, "State must not be nullptr");
if (library.functions.empty()) {
LERROR("Lua library '" << library.name << "' does not have any functions");
return false;
}
//ghoul::lua::logStack(_state);
lua_getglobal(state, OpenSpaceLibraryName.c_str());
//ghoul::lua::logStack(_state);
if (library.name.empty()) {
//ghoul::lua::logStack(_state);
addLibraryFunctions(state, library, true);
//ghoul::lua::logStack(_state);
lua_pop(state, 1);
//ghoul::lua::logStack(_state);
}
else {
const bool allowed = isLibraryNameAllowed(state, library.name);
if (!allowed) {
return false;
}
//ghoul::lua::logStack(_state);
lua_pushstring(state, library.name.c_str());
//ghoul::lua::logStack(_state);
lua_newtable(state);
//ghoul::lua::logStack(_state);
addLibraryFunctions(state, library, false);
lua_settable(state, TableOffset);
//ghoul::lua::logStack(_state);
//_registeredLibraries.insert(library);
//_registeredLibraries.push_back(library);
// We need to first create the table and then retrieve it as the table will
// probably be used by scripts already
// Add the table
lua_pushstring(state, library.name.c_str());
lua_newtable(state);
lua_settable(state, TableOffset);
// Retrieve the table
lua_pushstring(state, library.name.c_str());
lua_gettable(state, -2);
// Add the library functions into the table
addLibraryFunctions(state, library, false);
// Pop the table
lua_pop(state, 1);
}
return true;
}
@@ -492,11 +564,21 @@ std::vector<std::string> ScriptEngine::allLuaFunctions() const {
for (const LuaLibrary& library : _registeredLibraries) {
for (const LuaLibrary::Function& function : library.functions) {
std::string total = "openspace.";
if (!library.name.empty())
if (!library.name.empty()) {
total += library.name + ".";
}
total += function.name;
result.push_back(std::move(total));
}
for (const LuaLibrary::Documentation& doc : library.documentations) {
std::string total = "openspace.";
if (!library.name.empty()) {
total += library.name + ".";
}
total += doc.name;
result.push_back(std::move(total));
}
}
return result;
@@ -524,10 +606,23 @@ std::string ScriptEngine::generateJson() const {
json << "\"arguments\": \"" << f.argumentText << "\", ";
json << "\"help\": \"" << f.helpText << "\"";
json << "}";
if (&f != &l.functions.back()) {
if (&f != &l.functions.back() || !l.documentations.empty()) {
json << ",";
}
}
for (const LuaLibrary::Documentation& doc : l.documentations) {
json << "{";
json << "\"name\": \"" << doc.name << "\", ";
json << "\"arguments\": \"" << doc.parameter<< "\", ";
json << "\"help\": \"" << doc.description<< "\"";
json << "}";
if (&doc != &l.documentations.back()) {
json << ",";
}
}
json << "]}";
}
@@ -594,15 +689,15 @@ bool ScriptEngine::writeLog(const std::string& script) {
}
void ScriptEngine::presync(bool isMaster) {
if (!isMaster) return;
if (!isMaster) {
return;
}
_mutex.lock();
if (!_queuedScripts.empty()) {
_currentSyncedScript = _queuedScripts.back().first;
bool remoteScripting = _queuedScripts.back().second;
//Not really a received script but the master also needs to run the script...
_receivedScripts.push_back(_currentSyncedScript);
_queuedScripts.pop_back();
@@ -610,11 +705,8 @@ void ScriptEngine::presync(bool isMaster) {
if (OsEng.parallelConnection().isHost() && remoteScripting) {
OsEng.parallelConnection().sendScript(_currentSyncedScript);
}
}
_mutex.unlock();
}
void ScriptEngine::encode(SyncBuffer* syncBuffer) {
@@ -652,13 +744,12 @@ void ScriptEngine::postsync(bool) {
}
void ScriptEngine::queueScript(const std::string &script, ScriptEngine::RemoteScripting remoteScripting){
if (script.empty())
if (script.empty()) {
return;
}
_mutex.lock();
_queuedScripts.insert(_queuedScripts.begin(), std::make_pair(script, remoteScripting));
_mutex.unlock();
}

View File

@@ -22,15 +22,75 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <ghoul/filesystem/directory.h>
namespace openspace {
namespace luascriptfunctions {
namespace {
using walkFunc = std::vector<std::string>(ghoul::filesystem::Directory::*)(
ghoul::filesystem::Directory::Recursive, ghoul::filesystem::Directory::Sort) const;
// Defining a common walk function that works off a pointer-to-member function (defined
// above) allows us to easily reuse this code
int walkCommon(lua_State* L, walkFunc func) {
// @CPP17 Replace with std::invoke
#define CALL_MEMBER_FN(object,ptrToMember) ((object).*(ptrToMember))
using namespace ghoul::filesystem;
const int nArguments = lua_gettop(L);
if (nArguments < 1 || nArguments > 3) {
return luaL_error(L, "Expected %i-%i arguments, got %i", 1, 3, nArguments);
}
std::vector<std::string> result;
if (nArguments == 1) {
// Only the path was passed
const std::string path = luaL_checkstring(L, -1);
result = CALL_MEMBER_FN(Directory(path), func)(
ghoul::filesystem::Directory::Recursive::No,
ghoul::filesystem::Directory::Sort::No
);
}
else if (nArguments == 2) {
// The path and the recursive value were passed
const std::string path = luaL_checkstring(L, -2);
const bool recursive = lua_toboolean(L, -1) != 0;
result = CALL_MEMBER_FN(Directory(path), func)(
ghoul::filesystem::Directory::Recursive(recursive),
ghoul::filesystem::Directory::Sort::No
);
}
else if (nArguments == 3) {
// All three arguments were passed
const std::string path = luaL_checkstring(L, -3);
const bool recursive = lua_toboolean(L, -2) != 0;
const bool sorted = lua_toboolean(L, -1) != 0;
result = CALL_MEMBER_FN(Directory(path), func)(
ghoul::filesystem::Directory::Recursive(recursive),
ghoul::filesystem::Directory::Sort(sorted)
);
}
// Copy values into the lua_State
lua_newtable(L);
for (int i = 0; i < result.size(); ++i) {
lua_pushstring(L, result[i].c_str());
lua_rawseti(L, -2, i + 1);
}
return 1;
}
} // namespace
int printInternal(ghoul::logging::LogLevel level, lua_State* L) {
using ghoul::lua::luaTypeToString;
const std::string _loggerCat = "print";
int nArguments = lua_gettop(L);
const int nArguments = lua_gettop(L);
if (nArguments != 1) {
return luaL_error(L, "Expected %i arguments, got %i", 1, nArguments);
}
@@ -61,103 +121,104 @@ int printInternal(ghoul::logging::LogLevel level, lua_State* L) {
}
/**
* \ingroup LuaScripts
* printTrace(*):
* Logs the passed value to the installed LogManager with a LogLevel of 'Trace'.
* For Boolean, numbers, and strings, the internal values are printed, for all other
* types, the type is printed instead
*/
* \ingroup LuaScripts
* printTrace(*):
* Logs the passed value to the installed LogManager with a LogLevel of 'Trace'.
* For Boolean, numbers, and strings, the internal values are printed, for all other
* types, the type is printed instead
*/
int printTrace(lua_State* L) {
return printInternal(ghoul::logging::LogLevel::Trace, L);
}
/**
* \ingroup LuaScripts
* printDebug(*):
* Logs the passed value to the installed LogManager with a LogLevel of 'Debug'.
* For Boolean, numbers, and strings, the internal values are printed, for all other
* types, the type is printed instead
*/
* \ingroup LuaScripts
* printDebug(*):
* Logs the passed value to the installed LogManager with a LogLevel of 'Debug'.
* For Boolean, numbers, and strings, the internal values are printed, for all other
* types, the type is printed instead
*/
int printDebug(lua_State* L) {
return printInternal(ghoul::logging::LogLevel::Debug, L);
}
/**
* \ingroup LuaScripts
* printInfo(*):
* Logs the passed value to the installed LogManager with a LogLevel of 'Info'.
* For Boolean, numbers, and strings, the internal values are printed, for all other
* types, the type is printed instead
*/
* \ingroup LuaScripts
* printInfo(*):
* Logs the passed value to the installed LogManager with a LogLevel of 'Info'.
* For Boolean, numbers, and strings, the internal values are printed, for all other
* types, the type is printed instead
*/
int printInfo(lua_State* L) {
return printInternal(ghoul::logging::LogLevel::Info, L);
}
/**
* \ingroup LuaScripts
* printWarning(*):
* Logs the passed value to the installed LogManager with a LogLevel of 'Warning'.
* For Boolean, numbers, and strings, the internal values are printed, for all other
* types, the type is printed instead
*/
* \ingroup LuaScripts
* printWarning(*):
* Logs the passed value to the installed LogManager with a LogLevel of 'Warning'.
* For Boolean, numbers, and strings, the internal values are printed, for all other
* types, the type is printed instead
*/
int printWarning(lua_State* L) {
return printInternal(ghoul::logging::LogLevel::Warning, L);
}
/**
* \ingroup LuaScripts
* printError(*):
* Logs the passed value to the installed LogManager with a LogLevel of 'Error'.
* For Boolean, numbers, and strings, the internal values are printed, for all other
* types, the type is printed instead
*/
* \ingroup LuaScripts
* printError(*):
* Logs the passed value to the installed LogManager with a LogLevel of 'Error'.
* For Boolean, numbers, and strings, the internal values are printed, for all other
* types, the type is printed instead
*/
int printError(lua_State* L) {
return printInternal(ghoul::logging::LogLevel::Error, L);
}
/**
* \ingroup LuaScripts
* printFatal(*):
* Logs the passed value to the installed LogManager with a LogLevel of 'Fatal'.
* For Boolean, numbers, and strings, the internal values are printed, for all other
* types, the type is printed instead
*/
* \ingroup LuaScripts
* printFatal(*):
* Logs the passed value to the installed LogManager with a LogLevel of 'Fatal'.
* For Boolean, numbers, and strings, the internal values are printed, for all other
* types, the type is printed instead
*/
int printFatal(lua_State* L) {
return printInternal(ghoul::logging::LogLevel::Fatal, L);
}
/**
* \ingroup LuaScripts
* absPath(string):
* Passes the argument to FileSystem::absolutePath, which resolves occuring path
* tokens and returns the absolute path.
*/
* \ingroup LuaScripts
* absPath(string):
* Passes the argument to FileSystem::absolutePath, which resolves occuring path
* tokens and returns the absolute path.
*/
int absolutePath(lua_State* L) {
int nArguments = lua_gettop(L);
const int nArguments = lua_gettop(L);
if (nArguments != 1) {
return luaL_error(L, "Expected %d arguments, got %d", 1, nArguments);
}
std::string path = luaL_checkstring(L, -1);
path = absPath(path);
path = FileSys.convertPathSeparator(path, '/');
lua_pushstring(L, path.c_str());
return 1;
}
/**
* \ingroup LuaScripts
* setPathToken(string, string):
* Registers the path token provided by the first argument to the path in the second
* argument. If the path token already exists, it will be silently overridden.
*/
* \ingroup LuaScripts
* setPathToken(string, string):
* Registers the path token provided by the first argument to the path in the second
* argument. If the path token already exists, it will be silently overridden.
*/
int setPathToken(lua_State* L) {
int nArguments = lua_gettop(L);
const int nArguments = lua_gettop(L);
if (nArguments != 2) {
return luaL_error(L, "Expected %i arguments, got %i", 2, nArguments);
}
std::string path = luaL_checkstring(L, -1);
std::string pathToken = luaL_checkstring(L, -2);
const std::string path = luaL_checkstring(L, -1);
const std::string pathToken = luaL_checkstring(L, -2);
FileSys.registerPathToken(
pathToken,
path,
@@ -166,6 +227,71 @@ int setPathToken(lua_State* L) {
return 0;
}
/**
* \ingroup LuaScripts
* walkDirectory(string, bool, bool):
* Walks a directory and returns the contents 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 fileExists(lua_State* L) {
const int nArguments = lua_gettop(L);
if (nArguments != 1) {
return luaL_error(L, "Expected %i arguments, got %i", 1, nArguments);
}
const std::string file = luaL_checkstring(L, -1);
const bool e = FileSys.fileExists(absPath(file));
lua_pushboolean(
L,
e ? 1 : 0
);
return 1;
}
/**
* \ingroup LuaScripts
* walkDirectory(string, bool, bool):
* Walks a directory and returns the contents 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 walkDirectory(lua_State* L) {
return walkCommon(L, &ghoul::filesystem::Directory::read);
}
/**
* \ingroup LuaScripts
* walkDirectoryFiles(string, bool, bool):
* Walks a directory and returns the files 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 walkDirectoryFiles(lua_State* L) {
return walkCommon(L, &ghoul::filesystem::Directory::readFiles);
}
/**
* \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) {
return walkCommon(L, &ghoul::filesystem::Directory::readDirectories);
}
} // namespace luascriptfunctions
} // namespace openspace