Feature/luaextensions (#232)

* Add systemcapabilities bindings that make the functions of
GeneralSystemCapabilitiesComponent and OpenGLSystemCapabilitiesComponent
available in Lua scripts

* Windows compile fix

* Return OpenGL extensions as array in Lua
This commit is contained in:
Alexander Bock
2017-02-19 22:17:00 +01:00
committed by GitHub
parent 6d1f0c7029
commit b876c3553b
6 changed files with 419 additions and 28 deletions

View File

@@ -29,6 +29,7 @@
#include <openspace/util/syncdata.h>
#include <ghoul/lua/ghoul_lua.h>
#include <ghoul/lua/luastate.h>
#include <map>
#include <memory>
@@ -93,8 +94,9 @@ public:
//bool shouldScriptBeSent(const std::string &library, const std::string &function);
//void cacheScript(const std::string &library, const std::string &function, const std::string &script);
static std::string OpenSpaceLibraryName;
private:
bool registerLuaLibrary(lua_State* state, const LuaLibrary& library);
void addLibraryFunctions(lua_State* state, const LuaLibrary& library, bool replace);
@@ -103,7 +105,7 @@ private:
void addBaseLibrary();
void remapPrintFunction();
lua_State* _state = nullptr;
ghoul::lua::LuaState _state;
std::set<LuaLibrary> _registeredLibraries;
//sync variables

View File

@@ -0,0 +1,39 @@
/*****************************************************************************************
* *
* 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_CORE___SYSTEMCAPABLITIESBINDING___H__
#define __OPENSPACE_CORE___SYSTEMCAPABLITIESBINDING___H__
#include <openspace/scripting/lualibrary.h>
namespace openspace {
namespace scripting {
LuaLibrary generalSystemCapabilities();
LuaLibrary openglSystemCapabilities();
} // namespace scripting
} // namespace openspace
#endif // __OPENSPACE_CORE___SYSTEMCAPABLITIESBINDING___H__

View File

@@ -135,6 +135,7 @@ set(OPENSPACE_SOURCE
${OPENSPACE_BASE_DIR}/src/scripting/scriptengine_lua.inl
${OPENSPACE_BASE_DIR}/src/scripting/scriptscheduler.cpp
${OPENSPACE_BASE_DIR}/src/scripting/scriptscheduler_lua.inl
${OPENSPACE_BASE_DIR}/src/scripting/systemcapabilitiesbinding.cpp
${OPENSPACE_BASE_DIR}/src/util/blockplaneintersectiongeometry.cpp
${OPENSPACE_BASE_DIR}/src/util/boxgeometry.cpp
${OPENSPACE_BASE_DIR}/src/util/camera.cpp
@@ -275,6 +276,7 @@ set(OPENSPACE_HEADER
${OPENSPACE_BASE_DIR}/include/openspace/scripting/script_helper.h
${OPENSPACE_BASE_DIR}/include/openspace/scripting/scriptengine.h
${OPENSPACE_BASE_DIR}/include/openspace/scripting/scriptscheduler.h
${OPENSPACE_BASE_DIR}/include/openspace/scripting/systemcapabilitiesbinding.h
${OPENSPACE_BASE_DIR}/include/openspace/util/blockplaneintersectiongeometry.h
${OPENSPACE_BASE_DIR}/include/openspace/util/boxgeometry.h
${OPENSPACE_BASE_DIR}/include/openspace/util/camera.h

View File

@@ -42,6 +42,7 @@
#include <openspace/scene/translation.h>
#include <openspace/scripting/scriptengine.h>
#include <openspace/scripting/scriptscheduler.h>
#include <openspace/scripting/systemcapabilitiesbinding.h>
#include <openspace/util/spicemanager.h>
#include <openspace/util/time.h>
#include <openspace/util/timerange.h>
@@ -74,6 +75,9 @@ void registerCoreClasses(scripting::ScriptEngine& engine) {
engine.addLibrary(scripting::ScriptScheduler::luaLibrary());
engine.addLibrary(WindowWrapper::luaLibrary());
engine.addLibrary(MissionManager::luaLibrary());
engine.addLibrary(scripting::generalSystemCapabilities());
engine.addLibrary(scripting::openglSystemCapabilities());
}
} // namespace openspace

View File

@@ -41,12 +41,12 @@
#include "scriptengine_lua.inl"
namespace {
const std::string MainTemplateFilename = "${OPENSPACE_DATA}/web/luascripting/main.hbs";
const std::string ScriptingTemplateFilename = "${OPENSPACE_DATA}/web/luascripting/scripting.hbs";
const std::string HandlebarsFilename = "${OPENSPACE_DATA}/web/common/handlebars-v4.0.5.js";
const std::string JsFilename = "${OPENSPACE_DATA}/web/luascripting/script.js";
const std::string BootstrapFilename = "${OPENSPACE_DATA}/web/common/bootstrap.min.css";
const std::string CssFilename = "${OPENSPACE_DATA}/web/common/style.css";
const char* MainTemplateFilename = "${OPENSPACE_DATA}/web/luascripting/main.hbs";
const char* ScriptingTemplateFilename = "${OPENSPACE_DATA}/web/luascripting/scripting.hbs";
const char* HandlebarsFilename = "${OPENSPACE_DATA}/web/common/handlebars-v4.0.5.js";
const char* JsFilename = "${OPENSPACE_DATA}/web/luascripting/script.js";
const char* BootstrapFilename = "${OPENSPACE_DATA}/web/common/bootstrap.min.css";
const char* CssFilename = "${OPENSPACE_DATA}/web/common/style.css";
}
namespace openspace {
@@ -56,40 +56,35 @@ namespace scripting {
namespace {
const std::string _loggerCat = "ScriptEngine";
const std::string _openspaceLibraryName = "openspace";
const std::string _luaGlobalNamespace = "_G";
const std::string _printFunctionName = "print";
const char* LuaGlobalNamespace = "_G";
const char* PrintFunctionName = "print";
//const lua_CFunction _printFunctionReplacement = luascriptfunctions::printInfo;
const int _setTableOffset = -3; // -1 (top) -1 (first argument) -1 (second argument)
const int TableOffset = -3; // -1 (top) -1 (first argument) -1 (second argument)
}
std::string ScriptEngine::OpenSpaceLibraryName = "openspace";
void ScriptEngine::initialize() {
LDEBUG("Adding base library");
addBaseLibrary();
LDEBUG("Creating new Lua state");
_state = ghoul::lua::createNewLuaState();
LDEBUG("Initializing Lua state");
initializeLuaState(_state);
LDEBUG("Remapping Print functions");
remapPrintFunction();
}
void ScriptEngine::deinitialize() {
if (_state) {
lua_close(_state);
_state = nullptr;
}
}
void ScriptEngine::deinitialize() {}
void ScriptEngine::initializeLuaState(lua_State* state) {
LDEBUG("Create openspace base library");
lua_newtable(state);
lua_setglobal(state, _openspaceLibraryName.c_str());
lua_setglobal(state, OpenSpaceLibraryName.c_str());
LDEBUG("Add OpenSpace modules");
for (const LuaLibrary& lib : _registeredLibraries)
for (const LuaLibrary& lib : _registeredLibraries) {
registerLuaLibrary(state, lib);
}
}
void ScriptEngine::addLibrary(LuaLibrary library) {
@@ -294,7 +289,7 @@ bool ScriptEngine::parseLibraryAndFunctionNames(std::string &library, std::strin
*/
bool ScriptEngine::isLibraryNameAllowed(lua_State* state, const std::string& name) {
bool result = false;
lua_getglobal(state, _openspaceLibraryName.c_str());
lua_getglobal(state, OpenSpaceLibraryName.c_str());
const bool hasOpenSpaceLibrary = lua_istable(state, -1);
if (!hasOpenSpaceLibrary) {
LFATAL("OpenSpace library was not created in initialize method");
@@ -360,7 +355,7 @@ void ScriptEngine::addLibraryFunctions(lua_State* state, const LuaLibrary& libra
//ghoul::lua::logStack(_state);
lua_pushcfunction(state, p.function);
//ghoul::lua::logStack(_state);
lua_settable(state, _setTableOffset);
lua_settable(state, TableOffset);
//ghoul::lua::logStack(_state);
}
}
@@ -443,14 +438,15 @@ void ScriptEngine::remapPrintFunction() {
}
bool ScriptEngine::registerLuaLibrary(lua_State* state, const LuaLibrary& library) {
assert(state);
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());
lua_getglobal(state, OpenSpaceLibraryName.c_str());
//ghoul::lua::logStack(_state);
if (library.name.empty()) {
//ghoul::lua::logStack(_state);
@@ -461,8 +457,9 @@ bool ScriptEngine::registerLuaLibrary(lua_State* state, const LuaLibrary& librar
}
else {
const bool allowed = isLibraryNameAllowed(state, library.name);
if (!allowed)
if (!allowed) {
return false;
}
//ghoul::lua::logStack(_state);
@@ -471,7 +468,7 @@ bool ScriptEngine::registerLuaLibrary(lua_State* state, const LuaLibrary& librar
lua_newtable(state);
//ghoul::lua::logStack(_state);
addLibraryFunctions(state, library, false);
lua_settable(state, _setTableOffset);
lua_settable(state, TableOffset);
//ghoul::lua::logStack(_state);
//_registeredLibraries.insert(library);

View File

@@ -0,0 +1,347 @@
/*****************************************************************************************
* *
* 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 <openspace/scripting/systemcapabilitiesbinding.h>
#include <openspace/scripting/script_helper.h>
#include <openspace/scripting/scriptengine.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/misc/misc.h>
#include <ghoul/systemcapabilities/generalcapabilitiescomponent.h>
#include <ghoul/systemcapabilities/openglcapabilitiescomponent.h>
#include <cctype>
using namespace ghoul::lua;
using namespace ghoul::systemcapabilities;
namespace luascripting {
namespace general {
int operatingSystem(lua_State* L) {
lua_pushstring(L, CpuCap.operatingSystemString().c_str());
return 1;
}
int fullOperatingSystem(lua_State* L) {
lua_pushstring(L, CpuCap.fullOperatingSystem().c_str());
return 1;
}
int installedMainMemory(lua_State* L) {
lua_pushnumber(L, CpuCap.installedMainMemory());
return 1;
}
int cores(lua_State* L) {
lua_pushnumber(L, CpuCap.cores());
return 1;
}
int cacheLineSize(lua_State* L) {
lua_pushnumber(L, CpuCap.cacheLineSize());
return 1;
}
int L2Associativity(lua_State* L) {
lua_pushnumber(L, CpuCap.L2Associativity());
return 1;
}
int cacheSize(lua_State* L) {
lua_pushnumber(L, CpuCap.cacheSize());
return 1;
}
int extensions(lua_State* L) {
lua_pushstring(L, CpuCap.extensions().c_str());
return 1;
}
} // namespace general
namespace opengl {
int hasOpenGLVersion(lua_State* L) {
int nArguments = lua_gettop(L);
SCRIPT_CHECK_ARGUMENTS("hasVersion", L, 1, nArguments);
std::vector<std::string> v = ghoul::tokenizeString(luaL_checkstring(L, -1));
if (v.size() != 2 && v.size() != 3) {
LERRORC("hasVersion", ghoul::lua::errorLocation(L) << "Malformed version string");
return 0;
}
for (const std::string& i : v) {
for (char c : i) {
if (!std::isdigit(c)) {
LERRORC(
"hasVersion",
ghoul::lua::errorLocation(L) << "Malformed version string"
);
return 0;
}
}
}
int major = std::stoi(v[0]);
int minor = std::stoi(v[1]);
int release = v.size() == 3 ? std::stoi(v[2]) : 0;
OpenGLCapabilitiesComponent::Version version = { major, minor, release };
bool supported = OpenGLCap.openGLVersion() >= version;
lua_pushboolean(L, supported);
return 1;
}
int openGLVersion(lua_State* L) {
lua_pushstring(L, OpenGLCap.openGLVersion().toString().c_str());
return 1;
}
int glslCompiler(lua_State* L) {
lua_pushstring(L, OpenGLCap.glslCompiler().c_str());
return 1;
}
int gpuVendor(lua_State* L) {
lua_pushstring(L, OpenGLCap.gpuVendorString().c_str());
return 1;
}
int extensions(lua_State* L) {
const std::vector<std::string>& extensions = OpenGLCap.extensions();
lua_newtable(L);
for (int i = 1; i <= extensions.size(); ++i) {
lua_pushstring(L, extensions[i].c_str());
lua_rawseti(L, -2, i);
}
return 1;
}
int isExtensionSupported(lua_State* L) {
int nArguments = lua_gettop(L);
SCRIPT_CHECK_ARGUMENTS("hasVersion", L, 1, nArguments);
std::string extension = luaL_checkstring(L, -1);
lua_pushboolean(L, OpenGLCap.isExtensionSupported(extension));
return 1;
}
int maxTextureUnits(lua_State* L) {
lua_pushnumber(L, OpenGLCap.maxTextureUnits());
return 1;
}
int max2DTextureSize(lua_State* L) {
lua_pushnumber(L, OpenGLCap.max2DTextureSize());
return 1;
}
int max3DTextureSize(lua_State* L) {
lua_pushnumber(L, OpenGLCap.max3DTextureSize());
return 1;
}
int maxAtomicCounterBufferBindings(lua_State* L) {
lua_pushnumber(L, OpenGLCap.maxAtomicCounterBufferBindings());
return 1;
}
int maxShaderStorageBufferBindings(lua_State* L) {
lua_pushnumber(L, OpenGLCap.maxShaderStorageBufferBindings());
return 1;
}
int maxUniformBufferBindings(lua_State* L) {
lua_pushnumber(L, OpenGLCap.maxUniformBufferBindings());
return 1;
}
} // namespace opengl
} // namespace luascripting
namespace openspace {
namespace scripting {
LuaLibrary generalSystemCapabilities() {
return {
"systemCapabilities",
{
{
"operatingSystem",
&luascripting::general::operatingSystem,
"",
"Returns a parsed string of the operating system type, for example "
"Windows, Linux, MacOS, or others, together with the specific version, "
"where available."
},
{
"fullOperatingSystem",
&luascripting::general::fullOperatingSystem,
"",
"Returns the operating system as a string. The exact format of the "
"returned string is implementation and operating system-dependent but it "
"should contain the manufacturer and the version."
},
{
"installedMainMemory",
&luascripting::general::installedMainMemory,
"",
"Returns the amount of available, installed main memory (RAM) on the "
"system in MB."
},
{
"cores",
&luascripting::general::cores,
"",
"Returns the number of cores."
},
{
"cacheLineSize",
&luascripting::general::cacheLineSize,
"",
"Returns the cache line size."
},
{
"L2Associativity",
&luascripting::general::L2Associativity,
"",
"Returns the L2 associativity."
},
{
"cacheSize",
&luascripting::general::cacheSize,
"",
"Returns the cache size."
},
{
"extensions",
&luascripting::general::extensions,
"",
"Returns all supported exteions as comma-separated string."
}
}
};
}
LuaLibrary openglSystemCapabilities() {
return {
"openglCapabilities",
{
{
"hasOpenGLVersion",
&luascripting::opengl::hasOpenGLVersion,
"string",
"Tests whether the current instance supports the passed OpenGL version. "
"The parameter has to have the form 'X.Y' or 'X.Y.Z'."
},
{
"openGLVersion",
&luascripting::opengl::openGLVersion,
"",
"Returns the maximum OpenGL version that is supported on this platform."
},
{
"glslCompiler",
&luascripting::opengl::glslCompiler,
"",
"Returns the value of a call to <code>glGetString(GL_VENDOR)</code>. "
"This will give detailed information about the vendor of the main "
"graphics card. This string can be used if the automatic Vendor "
"detection failed."
},
{
"gpuVendor",
&luascripting::opengl::gpuVendor,
"",
"Returns the vendor of the main graphics card."
},
{
"extensions",
&luascripting::opengl::extensions,
"",
"Returns all available extensions as a list of names."
},
{
"isExtensionSupported",
&luascripting::opengl::isExtensionSupported,
"string",
"Checks is a specific <code>extension</code> is supported or not."
},
{
"maxTextureUnits",
&luascripting::opengl::maxTextureUnits,
"",
"Returns the maximum number of texture units that are available on the "
"main graphics card."
},
{
"max2DTextureSize",
&luascripting::opengl::max2DTextureSize,
"",
"Returns the largest dimension for a 2D texture on this graphics card."
},
{
"max3DTextureSize",
&luascripting::opengl::max3DTextureSize,
"",
"Returns the largest dimension for a 3D texture on this graphics card."
},
{
"maxAtomicCounterBufferBindings",
&luascripting::opengl::maxAtomicCounterBufferBindings,
"",
"Returns the maximum number of atomic counter buffer bindings that are "
"available on the main graphics card."
},
{
"maxShaderStorageBufferBindings",
&luascripting::opengl::maxShaderStorageBufferBindings,
"",
"Returns the maximum number of shader storage bindings that are "
"available on the main graphics card."
},
{
"maxUniformBufferBindings",
&luascripting::opengl::maxUniformBufferBindings,
"",
"Returns the maximum number of uniform buffer bindings that are "
"available on the main graphics card."
}
}
};
}
} // namespace scripting
} // namespace openspace